summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2024-03-05 21:00:15 +0100
committerMichael Brown2024-03-06 17:11:29 +0100
commitc4471e3408d85c51a69991974985fe283d869eac (patch)
treec3e24fa6bb2386dbbcf19993e26dc8ba1b29b685
parent[block] Allow for additional SAN boot parameters alongside filename (diff)
downloadipxe-c4471e3408d85c51a69991974985fe283d869eac.tar.gz
ipxe-c4471e3408d85c51a69991974985fe283d869eac.tar.xz
ipxe-c4471e3408d85c51a69991974985fe283d869eac.zip
[efi] Add efi_path_guid() utility function
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>
-rw-r--r--src/include/ipxe/efi/efi_path.h2
-rw-r--r--src/include/ipxe/errfile.h1
-rw-r--r--src/interface/efi/efi_path.c43
3 files changed, 46 insertions, 0 deletions
diff --git a/src/include/ipxe/efi/efi_path.h b/src/include/ipxe/efi/efi_path.h
index e75ae42c..20ff43f6 100644
--- a/src/include/ipxe/efi/efi_path.h
+++ b/src/include/ipxe/efi/efi_path.h
@@ -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 );
diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h
index 7cff594d..1fe34113 100644
--- a/src/include/ipxe/errfile.h
+++ b/src/include/ipxe/errfile.h
@@ -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 )
diff --git a/src/interface/efi/efi_path.c b/src/interface/efi/efi_path.c
index a78f97fc..d1e22eea 100644
--- a/src/interface/efi/efi_path.c
+++ b/src/interface/efi/efi_path.c
@@ -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>
@@ -133,6 +135,47 @@ unsigned int efi_path_vlan ( EFI_DEVICE_PATH_PROTOCOL *path ) {
}
/**
+ * 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
*
* @v ... List of device paths (NULL terminated)