diff options
-rw-r--r-- | src/include/ipxe/efi/efi_driver.h | 2 | ||||
-rw-r--r-- | src/interface/efi/efi_driver.c | 35 | ||||
-rw-r--r-- | src/interface/efi/efi_snp.c | 24 |
3 files changed, 38 insertions, 23 deletions
diff --git a/src/include/ipxe/efi/efi_driver.h b/src/include/ipxe/efi/efi_driver.h index f497df3..74ece90 100644 --- a/src/include/ipxe/efi/efi_driver.h +++ b/src/include/ipxe/efi/efi_driver.h @@ -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 */ diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c index b59362c..ec67bbc 100644 --- a/src/interface/efi/efi_driver.c +++ b/src/interface/efi/efi_driver.c @@ -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; } diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 5729a39..c6a56ab 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -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: |