[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>
pull/1174/head
Michael Brown 2024-03-05 20:00:15 +00:00
parent 636ccb4ca5
commit c4471e3408
3 changed files with 46 additions and 0 deletions

View File

@ -20,6 +20,7 @@ struct aoe_device;
struct fcp_description; struct fcp_description;
struct ib_srp_device; struct ib_srp_device;
struct usb_function; struct usb_function;
union uuid;
/** /**
* Terminate device path * Terminate device path
@ -43,6 +44,7 @@ extern EFI_DEVICE_PATH_PROTOCOL *
efi_path_end ( EFI_DEVICE_PATH_PROTOCOL *path ); efi_path_end ( EFI_DEVICE_PATH_PROTOCOL *path );
extern size_t efi_path_len ( 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 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_paths ( EFI_DEVICE_PATH_PROTOCOL *first,
... ); ... );
extern EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path ( struct net_device *netdev ); extern EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path ( struct net_device *netdev );

View File

@ -80,6 +80,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_acpimac ( ERRFILE_CORE | 0x00280000 ) #define ERRFILE_acpimac ( ERRFILE_CORE | 0x00280000 )
#define ERRFILE_efi_strings ( ERRFILE_CORE | 0x00290000 ) #define ERRFILE_efi_strings ( ERRFILE_CORE | 0x00290000 )
#define ERRFILE_uuid ( ERRFILE_CORE | 0x002a0000 ) #define ERRFILE_uuid ( ERRFILE_CORE | 0x002a0000 )
#define ERRFILE_efi_path ( ERRFILE_CORE | 0x002b0000 )
#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 ) #define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 ) #define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )

View File

@ -22,9 +22,11 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <byteswap.h> #include <byteswap.h>
#include <ipxe/netdevice.h> #include <ipxe/netdevice.h>
#include <ipxe/vlan.h> #include <ipxe/vlan.h>
#include <ipxe/uuid.h>
#include <ipxe/tcpip.h> #include <ipxe/tcpip.h>
#include <ipxe/uri.h> #include <ipxe/uri.h>
#include <ipxe/iscsi.h> #include <ipxe/iscsi.h>
@ -132,6 +134,47 @@ unsigned int efi_path_vlan ( EFI_DEVICE_PATH_PROTOCOL *path ) {
return 0; 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 * Concatenate EFI device paths
* *