|
@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
30
|
30
|
#include <ipxe/efi/Protocol/ComponentName2.h>
|
31
|
31
|
#include <ipxe/efi/Protocol/DevicePath.h>
|
32
|
32
|
#include <ipxe/efi/efi_strings.h>
|
|
33
|
+#include <ipxe/efi/efi_utils.h>
|
33
|
34
|
#include <ipxe/efi/efi_driver.h>
|
34
|
35
|
|
35
|
36
|
/** @file
|
|
@@ -132,8 +133,15 @@ efi_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
|
132
|
133
|
static EFI_STATUS EFIAPI
|
133
|
134
|
efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
|
134
|
135
|
EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
|
|
136
|
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
135
|
137
|
struct efi_driver *efidrv;
|
136
|
138
|
struct efi_device *efidev;
|
|
139
|
+ union {
|
|
140
|
+ EFI_DEVICE_PATH_PROTOCOL *path;
|
|
141
|
+ void *interface;
|
|
142
|
+ } path;
|
|
143
|
+ EFI_DEVICE_PATH_PROTOCOL *path_end;
|
|
144
|
+ size_t path_len;
|
137
|
145
|
EFI_STATUS efirc;
|
138
|
146
|
int rc;
|
139
|
147
|
|
|
@@ -151,17 +159,37 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
|
151
|
159
|
goto err_already_started;
|
152
|
160
|
}
|
153
|
161
|
|
|
162
|
+ /* Open device path */
|
|
163
|
+ if ( ( efirc = bs->OpenProtocol ( device,
|
|
164
|
+ &efi_device_path_protocol_guid,
|
|
165
|
+ &path.interface, efi_image_handle,
|
|
166
|
+ device,
|
|
167
|
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
|
|
168
|
+ rc = -EEFI ( efirc );
|
|
169
|
+ DBGC ( device, "EFIDRV %s could not open device path: %s\n",
|
|
170
|
+ efi_handle_name ( device ), strerror ( rc ) );
|
|
171
|
+ goto err_open_path;
|
|
172
|
+ }
|
|
173
|
+ path_len = ( efi_devpath_len ( path.path ) + sizeof ( *path_end ) );
|
|
174
|
+
|
154
|
175
|
/* Allocate and initialise structure */
|
155
|
|
- efidev = zalloc ( sizeof ( *efidev ) );
|
|
176
|
+ efidev = zalloc ( sizeof ( *efidev ) + path_len );
|
156
|
177
|
if ( ! efidev ) {
|
157
|
178
|
efirc = EFI_OUT_OF_RESOURCES;
|
158
|
179
|
goto err_alloc;
|
159
|
180
|
}
|
160
|
181
|
efidev->device = device;
|
161
|
182
|
efidev->dev.desc.bus_type = BUS_TYPE_EFI;
|
|
183
|
+ efidev->path = ( ( ( void * ) efidev ) + sizeof ( *efidev ) );
|
|
184
|
+ memcpy ( efidev->path, path.path, path_len );
|
162
|
185
|
INIT_LIST_HEAD ( &efidev->dev.children );
|
163
|
186
|
list_add ( &efidev->dev.siblings, &efi_devices );
|
164
|
187
|
|
|
188
|
+ /* Close device path */
|
|
189
|
+ bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
|
|
190
|
+ efi_image_handle, device );
|
|
191
|
+ path.path = NULL;
|
|
192
|
+
|
165
|
193
|
/* Try to start this device */
|
166
|
194
|
for_each_table_entry ( efidrv, EFI_DRIVERS ) {
|
167
|
195
|
if ( ( rc = efidrv->supported ( device ) ) != 0 ) {
|
|
@@ -187,6 +215,11 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
|
187
|
215
|
list_del ( &efidev->dev.siblings );
|
188
|
216
|
free ( efidev );
|
189
|
217
|
err_alloc:
|
|
218
|
+ if ( path.path ) {
|
|
219
|
+ bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
|
|
220
|
+ efi_image_handle, device );
|
|
221
|
+ }
|
|
222
|
+ err_open_path:
|
190
|
223
|
err_already_started:
|
191
|
224
|
return efirc;
|
192
|
225
|
}
|