]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Add efi_path_guid() utility function
authorMichael Brown <mcb30@ipxe.org>
Tue, 5 Mar 2024 20:00:15 +0000 (20:00 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 6 Mar 2024 16:11:29 +0000 (16:11 +0000)
EFI provides no API for determining the partition GUID (if any) for a
specified device handle.  The partition GUID appears to be exposed
only as part of the device path.

Add efi_path_guid() to extract the partition GUID (if any) from a
device path.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/efi/efi_path.h
src/include/ipxe/errfile.h
src/interface/efi/efi_path.c

index e75ae42c4840119cdfe990bb510f1441a91b7960..20ff43f645b65ff450c311e69c4ecbf32e57191f 100644 (file)
@@ -20,6 +20,7 @@ struct aoe_device;
 struct fcp_description;
 struct ib_srp_device;
 struct usb_function;
+union uuid;
 
 /**
  * Terminate device path
@@ -43,6 +44,7 @@ extern EFI_DEVICE_PATH_PROTOCOL *
 efi_path_end ( EFI_DEVICE_PATH_PROTOCOL *path );
 extern size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *path );
 extern unsigned int efi_path_vlan ( EFI_DEVICE_PATH_PROTOCOL *path );
+extern int efi_path_guid ( EFI_DEVICE_PATH_PROTOCOL *path, union uuid *uuid );
 extern EFI_DEVICE_PATH_PROTOCOL * efi_paths ( EFI_DEVICE_PATH_PROTOCOL *first,
                                              ... );
 extern EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path ( struct net_device *netdev );
index 7cff594d534a409f3d99981dc43db3ec74bdf76f..1fe34113d2fd417885a518c85b59ae49a635e32c 100644 (file)
@@ -80,6 +80,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define ERRFILE_acpimac                       ( ERRFILE_CORE | 0x00280000 )
 #define ERRFILE_efi_strings           ( ERRFILE_CORE | 0x00290000 )
 #define ERRFILE_uuid                  ( ERRFILE_CORE | 0x002a0000 )
+#define ERRFILE_efi_path              ( ERRFILE_CORE | 0x002b0000 )
 
 #define ERRFILE_eisa                ( ERRFILE_DRIVER | 0x00000000 )
 #define ERRFILE_isa                 ( ERRFILE_DRIVER | 0x00010000 )
index a78f97fce6d7d8c4639ae8ff03a828c55b5d05bc..d1e22eeaa53f0cda6a22ce926459f86db7d37099 100644 (file)
@@ -22,9 +22,11 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <errno.h>
 #include <byteswap.h>
 #include <ipxe/netdevice.h>
 #include <ipxe/vlan.h>
+#include <ipxe/uuid.h>
 #include <ipxe/tcpip.h>
 #include <ipxe/uri.h>
 #include <ipxe/iscsi.h>
@@ -132,6 +134,47 @@ unsigned int efi_path_vlan ( EFI_DEVICE_PATH_PROTOCOL *path ) {
        return 0;
 }
 
+/**
+ * Get partition GUID from device path
+ *
+ * @v path             Device path
+ * @v guid             Partition GUID to fill in
+ * @ret rc             Return status code
+ */
+int efi_path_guid ( EFI_DEVICE_PATH_PROTOCOL *path, union uuid *guid ) {
+       EFI_DEVICE_PATH_PROTOCOL *next;
+       HARDDRIVE_DEVICE_PATH *hd;
+       int rc;
+
+       /* Search for most specific partition device path */
+       rc = -ENOENT;
+       for ( ; ( next = efi_path_next ( path ) ) ; path = next ) {
+
+               /* Skip non-harddrive device paths */
+               if ( path->Type != MEDIA_DEVICE_PATH )
+                       continue;
+               if ( path->SubType != MEDIA_HARDDRIVE_DP )
+                       continue;
+
+               /* Skip non-GUID signatures */
+               hd = container_of ( path, HARDDRIVE_DEVICE_PATH, Header );
+               if ( hd->SignatureType != SIGNATURE_TYPE_GUID )
+                       continue;
+
+               /* Extract GUID */
+               memcpy ( guid, hd->Signature, sizeof ( *guid ) );
+               uuid_mangle ( guid );
+
+               /* Record success, but continue searching in case
+                * there exists a more specific GUID (e.g. a partition
+                * GUID rather than a disk GUID).
+                */
+               rc = 0;
+       }
+
+       return rc;
+}
+
 /**
  * Concatenate EFI device paths
  *