|  | @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 22 | 22 |  #include <string.h>
 | 
		
	
		
			
			| 23 | 23 |  #include <errno.h>
 | 
		
	
		
			
			| 24 | 24 |  #include <ipxe/efi/efi.h>
 | 
		
	
		
			
			|  | 25 | +#include <ipxe/efi/efi_driver.h>
 | 
		
	
		
			
			| 25 | 26 |  #include <ipxe/efi/Protocol/LoadedImage.h>
 | 
		
	
		
			
			| 26 | 27 |  #include <ipxe/efi/Protocol/DevicePath.h>
 | 
		
	
		
			
			| 27 | 28 |  #include <ipxe/uuid.h>
 | 
		
	
	
		
			
			|  | @@ -50,6 +51,64 @@ static EFI_GUID efi_loaded_image_device_path_protocol_guid
 | 
		
	
		
			
			| 50 | 51 |  /** Event used to signal shutdown */
 | 
		
	
		
			
			| 51 | 52 |  static EFI_EVENT efi_shutdown_event;
 | 
		
	
		
			
			| 52 | 53 |  
 | 
		
	
		
			
			|  | 54 | +/* Forward declarations */
 | 
		
	
		
			
			|  | 55 | +static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
 | 
		
	
		
			
			|  | 56 | +
 | 
		
	
		
			
			|  | 57 | +/**
 | 
		
	
		
			
			|  | 58 | + * Check to see if driver supports a device
 | 
		
	
		
			
			|  | 59 | + *
 | 
		
	
		
			
			|  | 60 | + * @v driver		EFI driver
 | 
		
	
		
			
			|  | 61 | + * @v device		EFI device
 | 
		
	
		
			
			|  | 62 | + * @v child		Path to child device, if any
 | 
		
	
		
			
			|  | 63 | + * @ret efirc		EFI status code
 | 
		
	
		
			
			|  | 64 | + */
 | 
		
	
		
			
			|  | 65 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 66 | +efi_image_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
 | 
		
	
		
			
			|  | 67 | +		    EFI_HANDLE device __unused,
 | 
		
	
		
			
			|  | 68 | +		    EFI_DEVICE_PATH_PROTOCOL *child __unused ) {
 | 
		
	
		
			
			|  | 69 | +
 | 
		
	
		
			
			|  | 70 | +	return EFI_UNSUPPORTED;
 | 
		
	
		
			
			|  | 71 | +}
 | 
		
	
		
			
			|  | 72 | +
 | 
		
	
		
			
			|  | 73 | +/**
 | 
		
	
		
			
			|  | 74 | + * Attach driver to device
 | 
		
	
		
			
			|  | 75 | + *
 | 
		
	
		
			
			|  | 76 | + * @v driver		EFI driver
 | 
		
	
		
			
			|  | 77 | + * @v device		EFI device
 | 
		
	
		
			
			|  | 78 | + * @v child		Path to child device, if any
 | 
		
	
		
			
			|  | 79 | + * @ret efirc		EFI status code
 | 
		
	
		
			
			|  | 80 | + */
 | 
		
	
		
			
			|  | 81 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 82 | +efi_image_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
 | 
		
	
		
			
			|  | 83 | +		EFI_HANDLE device __unused,
 | 
		
	
		
			
			|  | 84 | +		EFI_DEVICE_PATH_PROTOCOL *child __unused ) {
 | 
		
	
		
			
			|  | 85 | +
 | 
		
	
		
			
			|  | 86 | +	return EFI_UNSUPPORTED;
 | 
		
	
		
			
			|  | 87 | +}
 | 
		
	
		
			
			|  | 88 | +
 | 
		
	
		
			
			|  | 89 | +/**
 | 
		
	
		
			
			|  | 90 | + * Detach driver from device
 | 
		
	
		
			
			|  | 91 | + *
 | 
		
	
		
			
			|  | 92 | + * @v driver		EFI driver
 | 
		
	
		
			
			|  | 93 | + * @v device		EFI device
 | 
		
	
		
			
			|  | 94 | + * @v pci		PCI device
 | 
		
	
		
			
			|  | 95 | + * @v num_children	Number of child devices
 | 
		
	
		
			
			|  | 96 | + * @v children		List of child devices
 | 
		
	
		
			
			|  | 97 | + * @ret efirc		EFI status code
 | 
		
	
		
			
			|  | 98 | + */
 | 
		
	
		
			
			|  | 99 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 100 | +efi_image_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
 | 
		
	
		
			
			|  | 101 | +	       EFI_HANDLE device __unused, UINTN num_children __unused,
 | 
		
	
		
			
			|  | 102 | +	       EFI_HANDLE *children __unused ) {
 | 
		
	
		
			
			|  | 103 | +
 | 
		
	
		
			
			|  | 104 | +	return EFI_UNSUPPORTED;
 | 
		
	
		
			
			|  | 105 | +}
 | 
		
	
		
			
			|  | 106 | +
 | 
		
	
		
			
			|  | 107 | +/** EFI loaded image driver */
 | 
		
	
		
			
			|  | 108 | +static struct efi_driver efi_image_driver =
 | 
		
	
		
			
			|  | 109 | +	EFI_DRIVER_INIT ( NULL, efi_image_supported, efi_image_start,
 | 
		
	
		
			
			|  | 110 | +			  efi_image_stop );
 | 
		
	
		
			
			|  | 111 | +
 | 
		
	
		
			
			| 53 | 112 |  /**
 | 
		
	
		
			
			| 54 | 113 |   * Shut down in preparation for booting an OS.
 | 
		
	
		
			
			| 55 | 114 |   *
 | 
		
	
	
		
			
			|  | @@ -189,5 +248,43 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
 | 
		
	
		
			
			| 189 | 248 |  		return efirc;
 | 
		
	
		
			
			| 190 | 249 |  	}
 | 
		
	
		
			
			| 191 | 250 |  
 | 
		
	
		
			
			|  | 251 | +	/* Install an EFI driver on the image handle, to allow the
 | 
		
	
		
			
			|  | 252 | +	 * driver to be subsequently unloaded.
 | 
		
	
		
			
			|  | 253 | +	 */
 | 
		
	
		
			
			|  | 254 | +	efi_image_driver.driver.DriverBindingHandle = image_handle;
 | 
		
	
		
			
			|  | 255 | +	if ( ( rc = efi_driver_install ( &efi_image_driver ) ) != 0 ) {
 | 
		
	
		
			
			|  | 256 | +		DBGC ( systab, "EFI could not install loaded image driver: "
 | 
		
	
		
			
			|  | 257 | +		       "%s\n", strerror ( rc ) );
 | 
		
	
		
			
			|  | 258 | +		return EFIRC ( rc );
 | 
		
	
		
			
			|  | 259 | +	}
 | 
		
	
		
			
			|  | 260 | +
 | 
		
	
		
			
			|  | 261 | +	/* Install image unload method */
 | 
		
	
		
			
			|  | 262 | +	efi_loaded_image->Unload = efi_unload;
 | 
		
	
		
			
			|  | 263 | +
 | 
		
	
		
			
			|  | 264 | +	return 0;
 | 
		
	
		
			
			|  | 265 | +}
 | 
		
	
		
			
			|  | 266 | +
 | 
		
	
		
			
			|  | 267 | +/**
 | 
		
	
		
			
			|  | 268 | + * Shut down EFI environment
 | 
		
	
		
			
			|  | 269 | + *
 | 
		
	
		
			
			|  | 270 | + * @v image_handle	Image handle
 | 
		
	
		
			
			|  | 271 | + */
 | 
		
	
		
			
			|  | 272 | +static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) {
 | 
		
	
		
			
			|  | 273 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 274 | +	EFI_SYSTEM_TABLE *systab = efi_systab;
 | 
		
	
		
			
			|  | 275 | +
 | 
		
	
		
			
			|  | 276 | +	DBGC ( systab, "EFI image unloading\n" );
 | 
		
	
		
			
			|  | 277 | +
 | 
		
	
		
			
			|  | 278 | +	/* Shut down */
 | 
		
	
		
			
			|  | 279 | +	shutdown_exit();
 | 
		
	
		
			
			|  | 280 | +
 | 
		
	
		
			
			|  | 281 | +	/* Uninstall exit boot services event */
 | 
		
	
		
			
			|  | 282 | +	bs->CloseEvent ( efi_shutdown_event );
 | 
		
	
		
			
			|  | 283 | +
 | 
		
	
		
			
			|  | 284 | +	/* Uninstall loaded image driver */
 | 
		
	
		
			
			|  | 285 | +	efi_driver_uninstall ( &efi_image_driver );
 | 
		
	
		
			
			|  | 286 | +
 | 
		
	
		
			
			|  | 287 | +	DBGC ( systab, "EFI image unloaded\n" );
 | 
		
	
		
			
			|  | 288 | +
 | 
		
	
		
			
			| 192 | 289 |  	return 0;
 | 
		
	
		
			
			| 193 | 290 |  }
 |