[efi] Include a copy of the device path within struct efi_device

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/41/head
Michael Brown 2015-09-10 23:23:14 +01:00
parent 7107334391
commit e727f576c2
3 changed files with 38 additions and 23 deletions

View File

@ -19,6 +19,8 @@ struct efi_device {
struct device dev; struct device dev;
/** EFI device handle */ /** EFI device handle */
EFI_HANDLE device; EFI_HANDLE device;
/** EFI device path copy */
EFI_DEVICE_PATH_PROTOCOL *path;
/** Driver for this device */ /** Driver for this device */
struct efi_driver *driver; struct efi_driver *driver;
/** Driver-private data */ /** Driver-private data */

View File

@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/Protocol/ComponentName2.h> #include <ipxe/efi/Protocol/ComponentName2.h>
#include <ipxe/efi/Protocol/DevicePath.h> #include <ipxe/efi/Protocol/DevicePath.h>
#include <ipxe/efi/efi_strings.h> #include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_utils.h>
#include <ipxe/efi/efi_driver.h> #include <ipxe/efi/efi_driver.h>
/** @file /** @file
@ -132,8 +133,15 @@ efi_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
static EFI_STATUS EFIAPI static EFI_STATUS EFIAPI
efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused, efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) { EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_driver *efidrv; struct efi_driver *efidrv;
struct efi_device *efidev; 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; EFI_STATUS efirc;
int rc; int rc;
@ -151,17 +159,37 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
goto err_already_started; 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 */ /* Allocate and initialise structure */
efidev = zalloc ( sizeof ( *efidev ) ); efidev = zalloc ( sizeof ( *efidev ) + path_len );
if ( ! efidev ) { if ( ! efidev ) {
efirc = EFI_OUT_OF_RESOURCES; efirc = EFI_OUT_OF_RESOURCES;
goto err_alloc; goto err_alloc;
} }
efidev->device = device; efidev->device = device;
efidev->dev.desc.bus_type = BUS_TYPE_EFI; 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 ); INIT_LIST_HEAD ( &efidev->dev.children );
list_add ( &efidev->dev.siblings, &efi_devices ); 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 */ /* Try to start this device */
for_each_table_entry ( efidrv, EFI_DRIVERS ) { for_each_table_entry ( efidrv, EFI_DRIVERS ) {
if ( ( rc = efidrv->supported ( device ) ) != 0 ) { if ( ( rc = efidrv->supported ( device ) ) != 0 ) {
@ -187,6 +215,11 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
list_del ( &efidev->dev.siblings ); list_del ( &efidev->dev.siblings );
free ( efidev ); free ( efidev );
err_alloc: err_alloc:
if ( path.path ) {
bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
efi_image_handle, device );
}
err_open_path:
err_already_started: err_already_started:
return efirc; return efirc;
} }

View File

@ -936,10 +936,6 @@ static int efi_snp_probe ( struct net_device *netdev ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_device *efidev; struct efi_device *efidev;
struct efi_snp_device *snpdev; struct efi_snp_device *snpdev;
union {
EFI_DEVICE_PATH_PROTOCOL *path;
void *interface;
} path;
EFI_DEVICE_PATH_PROTOCOL *path_end; EFI_DEVICE_PATH_PROTOCOL *path_end;
MAC_ADDR_DEVICE_PATH *macpath; MAC_ADDR_DEVICE_PATH *macpath;
size_t path_prefix_len = 0; size_t path_prefix_len = 0;
@ -1019,21 +1015,8 @@ static int efi_snp_probe ( struct net_device *netdev ) {
sizeof ( snpdev->name[0] ) ), sizeof ( snpdev->name[0] ) ),
"%s", netdev->name ); "%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 */ /* 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 ) + snpdev->path = zalloc ( path_prefix_len + sizeof ( *macpath ) +
sizeof ( *path_end ) ); sizeof ( *path_end ) );
if ( ! snpdev->path ) { if ( ! snpdev->path ) {
@ -1042,7 +1025,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
} }
/* Populate the device path */ /* 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 ); macpath = ( ( ( void * ) snpdev->path ) + path_prefix_len );
path_end = ( ( void * ) ( macpath + 1 ) ); path_end = ( ( void * ) ( macpath + 1 ) );
memset ( macpath, 0, sizeof ( *macpath ) ); memset ( macpath, 0, sizeof ( *macpath ) );
@ -1119,9 +1102,6 @@ static int efi_snp_probe ( struct net_device *netdev ) {
err_install_protocol_interface: err_install_protocol_interface:
free ( snpdev->path ); free ( snpdev->path );
err_alloc_device_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 ); bs->CloseEvent ( snpdev->snp.WaitForPacket );
err_create_event: err_create_event:
err_ll_addr_len: err_ll_addr_len: