summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_driver.c
diff options
context:
space:
mode:
authorMichael Brown2015-09-11 00:23:14 +0200
committerMichael Brown2015-09-13 14:08:08 +0200
commite727f576c266221c6ee62ae293506078ca6871b2 (patch)
tree03740c28a9eacb0192dc06e3412f2a0466bdcbcc /src/interface/efi/efi_driver.c
parent[efi] Provide efi_devpath_len() (diff)
downloadipxe-e727f576c266221c6ee62ae293506078ca6871b2.tar.gz
ipxe-e727f576c266221c6ee62ae293506078ca6871b2.tar.xz
ipxe-e727f576c266221c6ee62ae293506078ca6871b2.zip
[efi] Include a copy of the device path within struct efi_device
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi/efi_driver.c')
-rw-r--r--src/interface/efi/efi_driver.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c
index b59362c6..ec67bbcd 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;
}