summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2024-03-06 09:55:55 +0100
committerMichael Brown2024-03-06 17:11:29 +0100
commitcea22d76e4cfdbd2d5a3a29bd541346710760457 (patch)
tree989f3ba4e8c9a604ecf060ce5aa5ce53dd526cca
parent[efi] Add efi_path_guid() utility function (diff)
downloadipxe-cea22d76e4cfdbd2d5a3a29bd541346710760457.tar.gz
ipxe-cea22d76e4cfdbd2d5a3a29bd541346710760457.tar.xz
ipxe-cea22d76e4cfdbd2d5a3a29bd541346710760457.zip
[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.c7
-rw-r--r--src/hci/commands/sanboot_cmd.c10
-rw-r--r--src/include/ipxe/parseopt.h10
-rw-r--r--src/include/ipxe/sanboot.h3
-rw-r--r--src/interface/efi/efi_block.c18
5 files changed, 41 insertions, 7 deletions
diff --git a/src/core/parseopt.c b/src/core/parseopt.c
index 7aff1485..8410e6e9 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 9c7e9ab7..b3d9ccad 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 ebd18804..61010f22 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 d981226e..9841edda 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 e81d6bb7..f5b913f1 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: