[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>
pull/1174/head
Michael Brown 2024-03-06 08:55:55 +00:00
parent c4471e3408
commit cea22d76e4
5 changed files with 41 additions and 7 deletions

View File

@ -129,20 +129,21 @@ int parse_timeout ( char *text, unsigned long *value ) {
* Parse UUID * Parse UUID
* *
* @v text Text * @v text Text
* @ret value UUID value * @ret uuid UUID value
* @ret rc Return status code * @ret rc Return status code
*/ */
int parse_uuid ( char *text, union uuid *value ) { int parse_uuid ( char *text, struct uuid_option *uuid ) {
int rc; int rc;
/* Sanity check */ /* Sanity check */
assert ( text != NULL ); assert ( text != NULL );
/* Parse UUID */ /* Parse UUID */
if ( ( rc = uuid_aton ( text, value ) ) != 0 ) { if ( ( rc = uuid_aton ( text, &uuid->buf ) ) != 0 ) {
printf ( "\"%s\": invalid UUID\n", text ); printf ( "\"%s\": invalid UUID\n", text );
return rc; return rc;
} }
uuid->value = &uuid->buf;
return 0; return 0;
} }

View File

@ -49,12 +49,14 @@ struct sanboot_options {
int keep; int keep;
/** Filename */ /** Filename */
char *filename; char *filename;
/** UUID */
struct uuid_option uuid;
}; };
/** "sanboot" option list */ /** "sanboot" option list */
static union { static union {
/* "sanboot" takes all four options */ /* "sanboot" takes all options */
struct option_descriptor sanboot[4]; struct option_descriptor sanboot[5];
/* "sanhook" takes only --drive and --no-describe */ /* "sanhook" takes only --drive and --no-describe */
struct option_descriptor sanhook[2]; struct option_descriptor sanhook[2];
/* "sanunhook" takes only --drive */ /* "sanunhook" takes only --drive */
@ -69,10 +71,11 @@ static union {
struct sanboot_options, keep, parse_flag ), struct sanboot_options, keep, parse_flag ),
OPTION_DESC ( "filename", 'f', required_argument, OPTION_DESC ( "filename", 'f', required_argument,
struct sanboot_options, filename, parse_string ), struct sanboot_options, filename, parse_string ),
OPTION_DESC ( "uuid", 'u', required_argument,
struct sanboot_options, uuid, parse_uuid ),
}, },
}; };
/** "sanhook" command descriptor */ /** "sanhook" command descriptor */
static struct command_descriptor sanhook_cmd = static struct command_descriptor sanhook_cmd =
COMMAND_DESC ( struct sanboot_options, opts.sanhook, 1, MAX_ARGUMENTS, 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 */ /* Construct configuration parameters */
config.filename = opts.filename; config.filename = opts.filename;
config.uuid = opts.uuid.value;
/* Construct flags */ /* Construct flags */
flags = default_flags; flags = default_flags;

View File

@ -126,10 +126,18 @@ struct named_setting {
struct setting 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_string ( char *text, char **value );
extern int parse_integer ( char *text, unsigned int *value ); extern int parse_integer ( char *text, unsigned int *value );
extern int parse_timeout ( char *text, unsigned long *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 ( char *text, struct net_device **netdev );
extern int extern int
parse_netdev_configurator ( char *text, parse_netdev_configurator ( char *text,

View File

@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/process.h> #include <ipxe/process.h>
#include <ipxe/blockdev.h> #include <ipxe/blockdev.h>
#include <ipxe/acpi.h> #include <ipxe/acpi.h>
#include <ipxe/uuid.h>
#include <config/sanboot.h> #include <config/sanboot.h>
/** /**
@ -109,6 +110,8 @@ enum san_device_flags {
struct san_boot_config { struct san_boot_config {
/** Boot filename (or NULL to use default) */ /** Boot filename (or NULL to use default) */
const char *filename; const char *filename;
/** UUID (or NULL to ignore UUID) */
union uuid *uuid;
}; };
/** /**

View File

@ -597,6 +597,7 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle,
EFI_DEVICE_PATH_PROTOCOL *path; EFI_DEVICE_PATH_PROTOCOL *path;
void *interface; void *interface;
} u; } u;
union uuid guid;
EFI_STATUS efirc; EFI_STATUS efirc;
int rc; 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", DBGC ( drive, "EFIBLK %#02x contains filesystem %s\n",
drive, efi_devpath_text ( u.path ) ); 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 */ /* Check if filesystem contains boot filename */
if ( ( rc = efi_block_filename ( drive, handle, if ( ( rc = efi_block_filename ( drive, handle,
config->filename ) ) != 0 ) { config->filename ) ) != 0 ) {
@ -633,6 +649,8 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle,
rc = 0; rc = 0;
err_filename: err_filename:
err_wrong_guid:
err_no_guid:
err_not_child: err_not_child:
bs->CloseProtocol ( handle, protocol, efi_image_handle, handle ); bs->CloseProtocol ( handle, protocol, efi_image_handle, handle );
err_open: err_open: