[ipxe-devel] [PATCH 1/1] efi: reimplement efi_locate_device

Heinrich Schuchardt xypron.glpk at gmx.de
Wed Jul 12 17:46:51 UTC 2017


Currently efi_locate_device looks for a device supporting a
protocol only in the list of parents. This leads to errors like
EFIDEV mmc at 72000.blk has no parent supporting SimpleNetwork

Obviously looking for a network protocol in a block device or
its parents does not make sense.

With the patch efi_locate_device returns the device if it supports
the protocol. Otherwise it returns the fist device it can find
supporting the protocol.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 src/interface/efi/efi_utils.c | 57 ++++++++++++++++++++++---------------------
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/src/interface/efi/efi_utils.c b/src/interface/efi/efi_utils.c
index 4dc75414..5069ce9d 100644
--- a/src/interface/efi/efi_utils.c
+++ b/src/interface/efi/efi_utils.c
@@ -63,7 +63,7 @@ size_t efi_devpath_len ( EFI_DEVICE_PATH_PROTOCOL *path ) {
 }
 
 /**
- * Locate parent device supporting a given protocol
+ * Locate device supporting a given protocol
  *
  * @v device		EFI device handle
  * @v protocol		Protocol GUID
@@ -73,44 +73,45 @@ size_t efi_devpath_len ( EFI_DEVICE_PATH_PROTOCOL *path ) {
 int efi_locate_device ( EFI_HANDLE device, EFI_GUID *protocol,
 			EFI_HANDLE *parent ) {
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
-	union {
-		EFI_DEVICE_PATH_PROTOCOL *path;
-		void *interface;
-	} path;
-	EFI_DEVICE_PATH_PROTOCOL *devpath;
 	EFI_STATUS efirc;
+	EFI_HANDLE *handles;
+	UINTN num_handles;
+	UINTN i;
 	int rc;
 
-	/* Get device path */
-	if ( ( efirc = bs->OpenProtocol ( device,
-					  &efi_device_path_protocol_guid,
-					  &path.interface,
-					  efi_image_handle, device,
-					  EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
+	/* Identify candidate handles */
+	if ( ( efirc = bs->LocateHandleBuffer ( ByProtocol, protocol,
+						NULL, &num_handles,
+						&handles ) ) != 0 ) {
 		rc = -EEFI ( efirc );
-		DBGC ( device, "EFIDEV %s cannot open device path: %s\n",
-		       efi_handle_name ( device ), strerror ( rc ) );
-		goto err_open_device_path;
+		DBGC ( device, "EFIDEV found no handle supporting %s: %s\n",
+		       efi_guid_ntoa ( protocol ), strerror ( rc ) );
+		return rc;
 	}
-	devpath = path.path;
 
-	/* Check for presence of specified protocol */
-	if ( ( efirc = bs->LocateDevicePath ( protocol, &devpath,
-					      parent ) ) != 0 ) {
-		rc = -EEFI ( efirc );
-		DBGC ( device, "EFIDEV %s has no parent supporting %s: %s\n",
-		       efi_handle_name ( device ),
-		       efi_guid_ntoa ( protocol ), strerror ( rc ) );
-		goto err_locate_protocol;
+	if (!num_handles || !*handles)
+		return -EEFI( EFI_NOT_FOUND);
+
+	*parent = NULL;
+
+	/* If device provice supports the protocol then return it. */
+	for ( i = 0; i < num_handles; ++i ) {
+		if (device == handles[i]) {
+			*parent = device;
+			break;
+		}
 	}
 
+	/* Otherwise use first handle supporting the protocol. */
+	if ( !*parent && num_handles )
+		*parent = handles[0];
+
+	/* Clean up */
+	bs->FreePool( handles );	
+
 	/* Success */
 	rc = 0;
 
- err_locate_protocol:
-	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
-			    efi_image_handle, device );
- err_open_device_path:
 	return rc;
 }
 
-- 
2.11.0




More information about the ipxe-devel mailing list