[efi] Allow EFI_USB_IO_PROTOCOL interfaces to be nullified and leaked

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/186/head
Michael Brown 2020-12-17 21:46:52 +00:00
parent 6769a7c3c6
commit 47098d7cb1
3 changed files with 181 additions and 9 deletions

View File

@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
#include <ipxe/efi/Protocol/PxeBaseCode.h>
#include <ipxe/efi/Protocol/SimpleNetwork.h>
#include <ipxe/efi/Protocol/UsbIo.h>
extern void efi_nullify_snp ( EFI_SIMPLE_NETWORK_PROTOCOL *snp );
extern void efi_nullify_nii ( EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii );
@ -27,5 +28,6 @@ extern void efi_nullify_hii ( EFI_HII_CONFIG_ACCESS_PROTOCOL *hii );
extern void efi_nullify_block ( EFI_BLOCK_IO_PROTOCOL *block );
extern void efi_nullify_pxe ( EFI_PXE_BASE_CODE_PROTOCOL *pxe );
extern void efi_nullify_apple ( EFI_APPLE_NET_BOOT_PROTOCOL *apple );
extern void efi_nullify_usbio ( EFI_USB_IO_PROTOCOL *usbio );
#endif /* _IPXE_EFI_NULL_H */

View File

@ -530,3 +530,143 @@ void efi_nullify_apple ( EFI_APPLE_NET_BOOT_PROTOCOL *apple ) {
memcpy ( apple, &efi_null_apple, sizeof ( *apple ) );
}
/******************************************************************************
*
* USB I/O Protocol
*
******************************************************************************
*/
static EFI_STATUS EFIAPI
efi_null_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio __unused,
EFI_USB_DEVICE_REQUEST *packet __unused,
EFI_USB_DATA_DIRECTION direction __unused,
UINT32 timeout __unused, VOID *data __unused,
UINTN len __unused, UINT32 *status __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_bulk_transfer ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT8 endpoint __unused, VOID *data __unused,
UINTN *len __unused, UINTN timeout __unused,
UINT32 *status __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_sync_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT8 endpoint __unused,
VOID *data __unused,
UINTN *len __unused,
UINTN timeout __unused,
UINT32 *status __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_async_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT8 endpoint __unused,
BOOLEAN start __unused,
UINTN interval __unused,
UINTN len __unused,
EFI_ASYNC_USB_TRANSFER_CALLBACK
callback __unused,
VOID *context __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_isochronous_transfer ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT8 endpoint __unused,
VOID *data __unused, UINTN len __unused,
UINT32 *status __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_async_isochronous_transfer ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT8 endpoint __unused,
VOID *data __unused,
UINTN len __unused,
EFI_ASYNC_USB_TRANSFER_CALLBACK
callback __unused,
VOID *context __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_get_device_descriptor ( EFI_USB_IO_PROTOCOL *usbio __unused,
EFI_USB_DEVICE_DESCRIPTOR
*efidesc __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_get_config_descriptor ( EFI_USB_IO_PROTOCOL *usbio __unused,
EFI_USB_CONFIG_DESCRIPTOR
*efidesc __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_get_interface_descriptor ( EFI_USB_IO_PROTOCOL *usbio __unused,
EFI_USB_INTERFACE_DESCRIPTOR
*efidesc __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_get_endpoint_descriptor ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT8 index __unused,
EFI_USB_ENDPOINT_DESCRIPTOR
*efidesc __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT16 language __unused,
UINT8 index __unused,
CHAR16 **string __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_get_supported_languages ( EFI_USB_IO_PROTOCOL *usbio __unused,
UINT16 **languages __unused,
UINT16 *len __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI
efi_null_usb_port_reset ( EFI_USB_IO_PROTOCOL *usbio __unused ) {
return EFI_UNSUPPORTED;
}
static EFI_USB_IO_PROTOCOL efi_null_usbio = {
.UsbControlTransfer = efi_null_usb_control_transfer,
.UsbBulkTransfer = efi_null_usb_bulk_transfer,
.UsbAsyncInterruptTransfer = efi_null_usb_async_interrupt_transfer,
.UsbSyncInterruptTransfer = efi_null_usb_sync_interrupt_transfer,
.UsbIsochronousTransfer = efi_null_usb_isochronous_transfer,
.UsbAsyncIsochronousTransfer = efi_null_usb_async_isochronous_transfer,
.UsbGetDeviceDescriptor = efi_null_usb_get_device_descriptor,
.UsbGetConfigDescriptor = efi_null_usb_get_config_descriptor,
.UsbGetInterfaceDescriptor = efi_null_usb_get_interface_descriptor,
.UsbGetEndpointDescriptor = efi_null_usb_get_endpoint_descriptor,
.UsbGetStringDescriptor = efi_null_usb_get_string_descriptor,
.UsbGetSupportedLanguages = efi_null_usb_get_supported_languages,
.UsbPortReset = efi_null_usb_port_reset,
};
/**
* Nullify USB I/O protocol
*
* @v usbio USB I/O protocol
*/
void efi_nullify_usbio ( EFI_USB_IO_PROTOCOL *usbio ) {
memcpy ( usbio, &efi_null_usbio, sizeof ( *usbio ) );
}

View File

@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_path.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_null.h>
#include <ipxe/efi/efi_usb.h>
#include <ipxe/usb.h>
@ -1106,6 +1107,7 @@ static int efi_usb_install ( struct efi_usb_device *usbdev,
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct usb_function *func = usbdev->func;
struct efi_usb_interface *usbintf;
int leak = 0;
EFI_STATUS efirc;
int rc;
@ -1148,19 +1150,30 @@ static int efi_usb_install ( struct efi_usb_device *usbdev,
usbintf->name, efi_handle_name ( usbintf->handle ) );
return 0;
bs->UninstallMultipleProtocolInterfaces (
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
usbintf->handle,
&efi_usb_io_protocol_guid, &usbintf->usbio,
&efi_device_path_protocol_guid, usbintf->path,
NULL );
NULL ) ) != 0 ) {
DBGC ( usbdev, "USBDEV %s could not uninstall: %s\n",
usbintf->name, strerror ( -EEFI ( efirc ) ) );
leak = 1;
}
efi_nullify_usbio ( &usbintf->usbio );
err_install_protocol:
efi_usb_close_all ( usbintf );
efi_usb_free_all ( usbintf );
list_del ( &usbintf->list );
free ( usbintf->path );
if ( ! leak )
free ( usbintf->path );
err_path:
free ( usbintf );
if ( ! leak )
free ( usbintf );
err_alloc:
if ( leak ) {
DBGC ( usbdev, "USBDEV %s nullified and leaked\n",
usbintf->name );
}
return rc;
}
@ -1172,6 +1185,8 @@ static int efi_usb_install ( struct efi_usb_device *usbdev,
static void efi_usb_uninstall ( struct efi_usb_interface *usbintf ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_usb_device *usbdev = usbintf->usbdev;
int leak = efi_shutdown_in_progress;
EFI_STATUS efirc;
DBGC ( usbdev, "USBDEV %s uninstalling %s\n",
usbintf->name, efi_handle_name ( usbintf->handle ) );
@ -1180,14 +1195,21 @@ static void efi_usb_uninstall ( struct efi_usb_interface *usbintf ) {
* seems to be required on some platforms to avoid failures
* when uninstalling protocols.
*/
bs->DisconnectController ( usbintf->handle, NULL, NULL );
if ( ! efi_shutdown_in_progress )
bs->DisconnectController ( usbintf->handle, NULL, NULL );
/* Uninstall protocols */
bs->UninstallMultipleProtocolInterfaces (
if ( ( ! efi_shutdown_in_progress ) &&
( ( efirc = bs->UninstallMultipleProtocolInterfaces (
usbintf->handle,
&efi_usb_io_protocol_guid, &usbintf->usbio,
&efi_device_path_protocol_guid, usbintf->path,
NULL );
NULL ) ) != 0 ) ) {
DBGC ( usbdev, "USBDEV %s could not uninstall: %s\n",
usbintf->name, strerror ( -EEFI ( efirc ) ) );
leak = 1;
}
efi_nullify_usbio ( &usbintf->usbio );
/* Close and free all endpoints */
efi_usb_close_all ( usbintf );
@ -1197,10 +1219,18 @@ static void efi_usb_uninstall ( struct efi_usb_interface *usbintf ) {
list_del ( &usbintf->list );
/* Free device path */
free ( usbintf->path );
if ( ! leak )
free ( usbintf->path );
/* Free interface */
free ( usbintf );
if ( ! leak )
free ( usbintf );
/* Report leakage, if applicable */
if ( leak && ( ! efi_shutdown_in_progress ) ) {
DBGC ( usbdev, "USBDEV %s nullified and leaked\n",
usbintf->name );
}
}
/**