]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Include a copy of the device path within struct efi_device
authorMichael Brown <mcb30@ipxe.org>
Thu, 10 Sep 2015 22:23:14 +0000 (23:23 +0100)
committerMichael Brown <mcb30@ipxe.org>
Sun, 13 Sep 2015 12:08:08 +0000 (13:08 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/efi/efi_driver.h
src/interface/efi/efi_driver.c
src/interface/efi/efi_snp.c

index f497df3e3b6d61be98ac5847081441f8515a9e5d..74ece90dbd033636dd7fd59c91befe6305ed7d3b 100644 (file)
@@ -19,6 +19,8 @@ struct efi_device {
        struct device dev;
        /** EFI device handle */
        EFI_HANDLE device;
+       /** EFI device path copy */
+       EFI_DEVICE_PATH_PROTOCOL *path;
        /** Driver for this device */
        struct efi_driver *driver;
        /** Driver-private data */
index b59362c64068a1f9afc68d4ab066f96d7d810ba1..ec67bbcdf1b65c2921ab965addfbb2acd3a9ac08 100644 (file)
@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/efi/Protocol/ComponentName2.h>
 #include <ipxe/efi/Protocol/DevicePath.h>
 #include <ipxe/efi/efi_strings.h>
+#include <ipxe/efi/efi_utils.h>
 #include <ipxe/efi/efi_driver.h>
 
 /** @file
@@ -132,8 +133,15 @@ efi_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
 static EFI_STATUS EFIAPI
 efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
                   EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
+       EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_driver *efidrv;
        struct efi_device *efidev;
+       union {
+               EFI_DEVICE_PATH_PROTOCOL *path;
+               void *interface;
+       } path;
+       EFI_DEVICE_PATH_PROTOCOL *path_end;
+       size_t path_len;
        EFI_STATUS efirc;
        int rc;
 
@@ -151,17 +159,37 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
                goto err_already_started;
        }
 
+       /* Open device path */
+       if ( ( efirc = bs->OpenProtocol ( device,
+                                         &efi_device_path_protocol_guid,
+                                         &path.interface, efi_image_handle,
+                                         device,
+                                         EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
+               rc = -EEFI ( efirc );
+               DBGC ( device, "EFIDRV %s could not open device path: %s\n",
+                      efi_handle_name ( device ), strerror ( rc ) );
+               goto err_open_path;
+       }
+       path_len = ( efi_devpath_len ( path.path ) + sizeof ( *path_end ) );
+
        /* Allocate and initialise structure */
-       efidev = zalloc ( sizeof ( *efidev ) );
+       efidev = zalloc ( sizeof ( *efidev ) + path_len );
        if ( ! efidev ) {
                efirc = EFI_OUT_OF_RESOURCES;
                goto err_alloc;
        }
        efidev->device = device;
        efidev->dev.desc.bus_type = BUS_TYPE_EFI;
+       efidev->path = ( ( ( void * ) efidev ) + sizeof ( *efidev ) );
+       memcpy ( efidev->path, path.path, path_len );
        INIT_LIST_HEAD ( &efidev->dev.children );
        list_add ( &efidev->dev.siblings, &efi_devices );
 
+       /* Close device path */
+       bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
+                           efi_image_handle, device );
+       path.path = NULL;
+
        /* Try to start this device */
        for_each_table_entry ( efidrv, EFI_DRIVERS ) {
                if ( ( rc = efidrv->supported ( device ) ) != 0 ) {
@@ -187,6 +215,11 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
        list_del ( &efidev->dev.siblings );
        free ( efidev );
  err_alloc:
+       if ( path.path ) {
+               bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
+                                   efi_image_handle, device );
+       }
+ err_open_path:
  err_already_started:
        return efirc;
 }
index 5729a39c1e7582c804dc2724f9e7e02bde09696d..c6a56ab79acf303208ef16ff63f47ee26c44a549 100644 (file)
@@ -936,10 +936,6 @@ static int efi_snp_probe ( struct net_device *netdev ) {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_device *efidev;
        struct efi_snp_device *snpdev;
-       union {
-               EFI_DEVICE_PATH_PROTOCOL *path;
-               void *interface;
-       } path;
        EFI_DEVICE_PATH_PROTOCOL *path_end;
        MAC_ADDR_DEVICE_PATH *macpath;
        size_t path_prefix_len = 0;
@@ -1019,21 +1015,8 @@ static int efi_snp_probe ( struct net_device *netdev ) {
                                       sizeof ( snpdev->name[0] ) ),
                       "%s", netdev->name );
 
-       /* Get the parent device path */
-       if ( ( efirc = bs->OpenProtocol ( efidev->device,
-                                         &efi_device_path_protocol_guid,
-                                         &path.interface, efi_image_handle,
-                                         efidev->device,
-                                         EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
-               rc = -EEFI ( efirc );
-               DBGC ( snpdev, "SNPDEV %p cannot get %s device path: %s\n",
-                      snpdev, efi_handle_name ( efidev->device ),
-                      strerror ( rc ) );
-               goto err_open_device_path;
-       }
-
        /* Allocate the new device path */
-       path_prefix_len = efi_devpath_len ( path.path );
+       path_prefix_len = efi_devpath_len ( efidev->path );
        snpdev->path = zalloc ( path_prefix_len + sizeof ( *macpath ) +
                                sizeof ( *path_end ) );
        if ( ! snpdev->path ) {
@@ -1042,7 +1025,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
        }
 
        /* Populate the device path */
-       memcpy ( snpdev->path, path.path, path_prefix_len );
+       memcpy ( snpdev->path, efidev->path, path_prefix_len );
        macpath = ( ( ( void * ) snpdev->path ) + path_prefix_len );
        path_end = ( ( void * ) ( macpath + 1 ) );
        memset ( macpath, 0, sizeof ( *macpath ) );
@@ -1119,9 +1102,6 @@ static int efi_snp_probe ( struct net_device *netdev ) {
  err_install_protocol_interface:
        free ( snpdev->path );
  err_alloc_device_path:
-       bs->CloseProtocol ( efidev->device, &efi_device_path_protocol_guid,
-                           efi_image_handle, efidev->device );
- err_open_device_path:
        bs->CloseEvent ( snpdev->snp.WaitForPacket );
  err_create_event:
  err_ll_addr_len: