|  | @@ -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 |  }
 |