diff options
author | Michael Brown <mcb30@ipxe.org> | 2020-12-17 21:46:52 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2020-12-17 21:46:52 +0000 |
commit | 47098d7cb1fb00f92dbee5e5de7ab335f0f30076 (patch) | |
tree | 887e136e50547811c1e474d28f522ecd9d483771 | |
parent | 6769a7c3c669cbb0455c7d83a3257c4582cf683d (diff) | |
download | ipxe-47098d7cb1fb00f92dbee5e5de7ab335f0f30076.tar.gz |
[efi] Allow EFI_USB_IO_PROTOCOL interfaces to be nullified and leaked
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/include/ipxe/efi/efi_null.h | 2 | ||||
-rw-r--r-- | src/interface/efi/efi_null.c | 140 | ||||
-rw-r--r-- | src/interface/efi/efi_usb.c | 48 |
3 files changed, 181 insertions, 9 deletions
diff --git a/src/include/ipxe/efi/efi_null.h b/src/include/ipxe/efi/efi_null.h index cc91e09bb..297457081 100644 --- a/src/include/ipxe/efi/efi_null.h +++ b/src/include/ipxe/efi/efi_null.h @@ -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 */ diff --git a/src/interface/efi/efi_null.c b/src/interface/efi/efi_null.c index aa27ab674..29ca5b9b6 100644 --- a/src/interface/efi/efi_null.c +++ b/src/interface/efi/efi_null.c @@ -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 ) ); +} diff --git a/src/interface/efi/efi_usb.c b/src/interface/efi/efi_usb.c index bcf156999..df66df45f 100644 --- a/src/interface/efi/efi_usb.c +++ b/src/interface/efi/efi_usb.c @@ -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 ); + } } /** |