From 24a855f1fc8d97ad3ca6be3eaabdc1c8285e86e8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 7 Mar 2024 14:09:54 +0000 Subject: [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 --- src/hci/commands/sanboot_cmd.c | 7 +++- src/include/ipxe/sanboot.h | 2 ++ src/interface/efi/efi_block.c | 73 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) 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 #include +#include #include +#include #include #include #include @@ -51,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include #include #include @@ -595,6 +598,68 @@ static int efi_block_filename ( unsigned int drive, EFI_HANDLE handle, return rc; } +/** + * 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 * @@ -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 ); -- cgit v1.2.3-55-g7522