diff options
author | Michael Brown <mcb30@ipxe.org> | 2024-03-06 08:55:55 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2024-03-06 16:11:29 +0000 |
commit | cea22d76e4cfdbd2d5a3a29bd541346710760457 (patch) | |
tree | 989f3ba4e8c9a604ecf060ce5aa5ce53dd526cca | |
parent | c4471e3408d85c51a69991974985fe283d869eac (diff) | |
download | ipxe-cea22d76e4cfdbd2d5a3a29bd541346710760457.tar.gz |
[block] Allow SAN boot device to be identified by UUID
Add a "--uuid" option which may be used to specify a boot device UUID,
to be matched against the GPT partition GUID.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/core/parseopt.c | 7 | ||||
-rw-r--r-- | src/hci/commands/sanboot_cmd.c | 10 | ||||
-rw-r--r-- | src/include/ipxe/parseopt.h | 10 | ||||
-rw-r--r-- | src/include/ipxe/sanboot.h | 3 | ||||
-rw-r--r-- | src/interface/efi/efi_block.c | 18 |
5 files changed, 41 insertions, 7 deletions
diff --git a/src/core/parseopt.c b/src/core/parseopt.c index 7aff14851..8410e6e90 100644 --- a/src/core/parseopt.c +++ b/src/core/parseopt.c @@ -129,20 +129,21 @@ int parse_timeout ( char *text, unsigned long *value ) { * Parse UUID * * @v text Text - * @ret value UUID value + * @ret uuid UUID value * @ret rc Return status code */ -int parse_uuid ( char *text, union uuid *value ) { +int parse_uuid ( char *text, struct uuid_option *uuid ) { int rc; /* Sanity check */ assert ( text != NULL ); /* Parse UUID */ - if ( ( rc = uuid_aton ( text, value ) ) != 0 ) { + if ( ( rc = uuid_aton ( text, &uuid->buf ) ) != 0 ) { printf ( "\"%s\": invalid UUID\n", text ); return rc; } + uuid->value = &uuid->buf; return 0; } diff --git a/src/hci/commands/sanboot_cmd.c b/src/hci/commands/sanboot_cmd.c index 9c7e9ab72..b3d9ccad3 100644 --- a/src/hci/commands/sanboot_cmd.c +++ b/src/hci/commands/sanboot_cmd.c @@ -49,12 +49,14 @@ struct sanboot_options { int keep; /** Filename */ char *filename; + /** UUID */ + struct uuid_option uuid; }; /** "sanboot" option list */ static union { - /* "sanboot" takes all four options */ - struct option_descriptor sanboot[4]; + /* "sanboot" takes all options */ + struct option_descriptor sanboot[5]; /* "sanhook" takes only --drive and --no-describe */ struct option_descriptor sanhook[2]; /* "sanunhook" takes only --drive */ @@ -69,10 +71,11 @@ static union { struct sanboot_options, keep, parse_flag ), OPTION_DESC ( "filename", 'f', required_argument, struct sanboot_options, filename, parse_string ), + OPTION_DESC ( "uuid", 'u', required_argument, + struct sanboot_options, uuid, parse_uuid ), }, }; - /** "sanhook" command descriptor */ static struct command_descriptor sanhook_cmd = COMMAND_DESC ( struct sanboot_options, opts.sanhook, 1, MAX_ARGUMENTS, @@ -127,6 +130,7 @@ static int sanboot_core_exec ( int argc, char **argv, /* Construct configuration parameters */ config.filename = opts.filename; + config.uuid = opts.uuid.value; /* Construct flags */ flags = default_flags; diff --git a/src/include/ipxe/parseopt.h b/src/include/ipxe/parseopt.h index ebd18804f..61010f22a 100644 --- a/src/include/ipxe/parseopt.h +++ b/src/include/ipxe/parseopt.h @@ -126,10 +126,18 @@ struct named_setting { struct setting setting; }; +/** A UUID command-line option */ +struct uuid_option { + /** UUID */ + union uuid *value; + /** Storage buffer */ + union uuid buf; +}; + extern int parse_string ( char *text, char **value ); extern int parse_integer ( char *text, unsigned int *value ); extern int parse_timeout ( char *text, unsigned long *value ); -extern int parse_uuid ( char *text, union uuid *value ); +extern int parse_uuid ( char *text, struct uuid_option *uuid ); extern int parse_netdev ( char *text, struct net_device **netdev ); extern int parse_netdev_configurator ( char *text, diff --git a/src/include/ipxe/sanboot.h b/src/include/ipxe/sanboot.h index d981226e9..9841edda5 100644 --- a/src/include/ipxe/sanboot.h +++ b/src/include/ipxe/sanboot.h @@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/process.h> #include <ipxe/blockdev.h> #include <ipxe/acpi.h> +#include <ipxe/uuid.h> #include <config/sanboot.h> /** @@ -109,6 +110,8 @@ enum san_device_flags { struct san_boot_config { /** Boot filename (or NULL to use default) */ const char *filename; + /** 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 e81d6bb7e..f5b913f15 100644 --- a/src/interface/efi/efi_block.c +++ b/src/interface/efi/efi_block.c @@ -597,6 +597,7 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle, EFI_DEVICE_PATH_PROTOCOL *path; void *interface; } u; + union uuid guid; EFI_STATUS efirc; int rc; @@ -623,6 +624,21 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle, DBGC ( drive, "EFIBLK %#02x contains filesystem %s\n", drive, efi_devpath_text ( u.path ) ); + /* Check if filesystem matches GUID, if applicable */ + if ( config->uuid ) { + if ( ( rc = efi_path_guid ( u.path, &guid ) ) != 0 ) { + DBGC ( drive, "EFIBLK %#02x could not determine GUID: " + "%s\n", drive, strerror ( rc ) ); + goto err_no_guid; + } + if ( memcmp ( config->uuid, &guid, sizeof ( guid ) ) != 0 ) { + DBGC ( drive, "EFIBLK %#02x has wrong GUID %s\n", + drive, uuid_ntoa ( &guid ) ); + rc = -ENOENT; + goto err_wrong_guid; + } + } + /* Check if filesystem contains boot filename */ if ( ( rc = efi_block_filename ( drive, handle, config->filename ) ) != 0 ) { @@ -633,6 +649,8 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle, rc = 0; err_filename: + err_wrong_guid: + err_no_guid: err_not_child: bs->CloseProtocol ( handle, protocol, efi_image_handle, handle ); err_open: |