]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[block] Allow SAN boot device to be identified by UUID
authorMichael Brown <mcb30@ipxe.org>
Wed, 6 Mar 2024 08:55:55 +0000 (08:55 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 6 Mar 2024 16:11:29 +0000 (16:11 +0000)
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>
src/core/parseopt.c
src/hci/commands/sanboot_cmd.c
src/include/ipxe/parseopt.h
src/include/ipxe/sanboot.h
src/interface/efi/efi_block.c

index 7aff14851c5cda14ad31260777dac0491181b3c8..8410e6e90f41a604315f2bb5fcf739988a968d3e 100644 (file)
@@ -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;
 }
index 9c7e9ab724b51b613eecff924ada46a631e01805..b3d9ccad38223bbac131d1f5d9fe3408eaac27b7 100644 (file)
@@ -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;
index ebd18804f6dc8320ec5c971e8556e279ce702b4c..61010f22aea9c13f4a2762f67414bf6aba52d2c8 100644 (file)
@@ -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,
index d981226e907b15400dd0b046b637d126f7e8c3ed..9841edda5d9b30d97cc85a783a19a91fe864fa39 100644 (file)
@@ -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;
 };
 
 /**
index e81d6bb7e623d40942449e9c03b05b01c6fc9167..f5b913f15aa9f322d4a43708cdba844b0a90b111 100644 (file)
@@ -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: