summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2024-03-07 15:09:54 +0100
committerMichael Brown2024-03-07 15:11:46 +0100
commit24a855f1fc8d97ad3ca6be3eaabdc1c8285e86e8 (patch)
treeec790a5fc8dd748fc35138819e5d6b7cf5288e9d
parent[block] Allow SAN boot device to be identified by an extra filename (diff)
downloadipxe-24a855f1fc8d97ad3ca6be3eaabdc1c8285e86e8.tar.gz
ipxe-24a855f1fc8d97ad3ca6be3eaabdc1c8285e86e8.tar.xz
ipxe-24a855f1fc8d97ad3ca6be3eaabdc1c8285e86e8.zip
[block] Allow SAN boot device to be identified by filesystem label
Add a "--label" option that can be used to specify a filesystem label, to be matched against the FAT volume label. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/hci/commands/sanboot_cmd.c7
-rw-r--r--src/include/ipxe/sanboot.h2
-rw-r--r--src/interface/efi/efi_block.c73
3 files changed, 81 insertions, 1 deletions
diff --git a/src/hci/commands/sanboot_cmd.c b/src/hci/commands/sanboot_cmd.c
index add0756d..6ab9e884 100644
--- a/src/hci/commands/sanboot_cmd.c
+++ b/src/hci/commands/sanboot_cmd.c
@@ -51,6 +51,8 @@ struct sanboot_options {
char *filename;
/** Required extra filename */
char *extra;
+ /** Volume label */
+ char *label;
/** UUID */
struct uuid_option uuid;
};
@@ -58,7 +60,7 @@ struct sanboot_options {
/** "sanboot" option list */
static union {
/* "sanboot" takes all options */
- struct option_descriptor sanboot[6];
+ struct option_descriptor sanboot[7];
/* "sanhook" takes only --drive and --no-describe */
struct option_descriptor sanhook[2];
/* "sanunhook" takes only --drive */
@@ -75,6 +77,8 @@ static union {
struct sanboot_options, filename, parse_string ),
OPTION_DESC ( "extra", 'e', required_argument,
struct sanboot_options, extra, parse_string ),
+ OPTION_DESC ( "label", 'l', required_argument,
+ struct sanboot_options, label, parse_string ),
OPTION_DESC ( "uuid", 'u', required_argument,
struct sanboot_options, uuid, parse_uuid ),
},
@@ -135,6 +139,7 @@ static int sanboot_core_exec ( int argc, char **argv,
/* Construct configuration parameters */
config.filename = opts.filename;
config.extra = opts.extra;
+ config.label = opts.label;
config.uuid = opts.uuid.value;
/* Construct flags */
diff --git a/src/include/ipxe/sanboot.h b/src/include/ipxe/sanboot.h
index 91c848b0..e44367cd 100644
--- a/src/include/ipxe/sanboot.h
+++ b/src/include/ipxe/sanboot.h
@@ -112,6 +112,8 @@ struct san_boot_config {
const char *filename;
/** Required extra filename (or NULL to ignore) */
const char *extra;
+ /** Filesystem label (or NULL to ignore volume label) */
+ const char *label;
/** UUID (or NULL to ignore UUID) */
union uuid *uuid;
};
diff --git a/src/interface/efi/efi_block.c b/src/interface/efi/efi_block.c
index 269b9abd..28a7f723 100644
--- a/src/interface/efi/efi_block.c
+++ b/src/interface/efi/efi_block.c
@@ -32,7 +32,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
+#include <strings.h>
#include <errno.h>
#include <ipxe/refcnt.h>
#include <ipxe/list.h>
@@ -51,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/Protocol/BlockIo.h>
#include <ipxe/efi/Protocol/SimpleFileSystem.h>
#include <ipxe/efi/Protocol/AcpiTable.h>
+#include <ipxe/efi/Guid/FileSystemInfo.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_snp.h>
@@ -596,6 +599,68 @@ static int efi_block_filename ( unsigned int drive, EFI_HANDLE handle,
}
/**
+ * Check for EFI block device filesystem label
+ *
+ * @v drive Drive number
+ * @v root Root directory
+ * @v label Volume label
+ * @ret rc Return status code
+ */
+static int efi_block_label ( unsigned int drive, EFI_FILE_PROTOCOL *root,
+ const char *label ) {
+ EFI_FILE_SYSTEM_INFO *info;
+ UINTN size;
+ char *actual;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Get length of file system information */
+ size = 0;
+ root->GetInfo ( root, &efi_file_system_info_id, &size, NULL );
+
+ /* Allocate file system information */
+ info = malloc ( size );
+ if ( ! info ) {
+ rc = -ENOMEM;
+ goto err_alloc_info;
+ }
+
+ /* Get file system information */
+ if ( ( efirc = root->GetInfo ( root, &efi_file_system_info_id, &size,
+ info ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( drive, "EFIBLK %#02x could not get filesystem info: "
+ "%s\n", drive, strerror ( rc ) );
+ goto err_get_info;
+ }
+
+ /* Construct volume label for comparison */
+ if ( asprintf ( &actual, "%ls", info->VolumeLabel ) < 0 ) {
+ rc = -ENOMEM;
+ goto err_alloc_label;
+ }
+
+ /* Compare volume label */
+ if ( strcasecmp ( label, actual ) != 0 ) {
+ DBGC ( drive, "EFIBLK %#02x has wrong label \"%s\"\n",
+ drive, actual );
+ rc = -ENOENT;
+ goto err_compare;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_compare:
+ free ( actual );
+ err_alloc_label:
+ err_get_info:
+ free ( info );
+ err_alloc_info:
+ return rc;
+}
+
+/**
* Check EFI block device filesystem match
*
* @v drive Drive number
@@ -675,9 +740,17 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle,
goto err_extra;
}
+ /* Check volume label, if applicable */
+ if ( config->label &&
+ ( ( rc = efi_block_label ( drive, root,
+ config->label ) ) != 0 ) ) {
+ goto err_label;
+ }
+
/* Success */
rc = 0;
+ err_label:
err_extra:
err_filename:
root->Close ( root );