diff options
author | Michael Brown | 2018-02-20 12:19:39 +0100 |
---|---|---|
committer | Michael Brown | 2018-02-20 12:19:39 +0100 |
commit | f672a27b34220865b403df519593f382859559e0 (patch) | |
tree | 67723bacf80a2c9f67a20d8946f03731868b8b34 /src | |
parent | [efi] Raise TPL within EFI_SIMPLE_NETWORK_PROTOCOL entry points (diff) | |
download | ipxe-f672a27b34220865b403df519593f382859559e0.tar.gz ipxe-f672a27b34220865b403df519593f382859559e0.tar.xz ipxe-f672a27b34220865b403df519593f382859559e0.zip |
[efi] Raise TPL within EFI_USB_IO_PROTOCOL entry points
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/interface/efi/efi_usb.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/src/interface/efi/efi_usb.c b/src/interface/efi/efi_usb.c index f9c91d09..48274f1d 100644 --- a/src/interface/efi/efi_usb.c +++ b/src/interface/efi/efi_usb.c @@ -505,6 +505,7 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio, EFI_USB_DATA_DIRECTION direction, UINT32 timeout, VOID *data, UINTN len, UINT32 *status ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_usb_interface *usbintf = container_of ( usbio, struct efi_usb_interface, usbio ); struct efi_usb_device *usbdev = usbintf->usbdev; @@ -512,6 +513,7 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio, USB_REQUEST_TYPE ( packet->Request ) ); unsigned int value = le16_to_cpu ( packet->Value ); unsigned int index = le16_to_cpu ( packet->Index ); + EFI_TPL saved_tpl; int rc; DBGC2 ( usbdev, "USBDEV %s control %04x:%04x:%04x:%04x %s %dms " @@ -520,6 +522,9 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio, efi_usb_direction_name ( direction ), timeout, data, ( ( size_t ) len ) ); + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Clear status */ *status = 0; @@ -563,6 +568,7 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio, err_control: err_change_config: + bs->RestoreTPL ( saved_tpl ); return EFIRC ( rc ); } @@ -580,16 +586,21 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio, static EFI_STATUS EFIAPI efi_usb_bulk_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, VOID *data, UINTN *len, UINTN timeout, UINT32 *status ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_usb_interface *usbintf = container_of ( usbio, struct efi_usb_interface, usbio ); struct efi_usb_device *usbdev = usbintf->usbdev; size_t actual = *len; + EFI_TPL saved_tpl; int rc; DBGC2 ( usbdev, "USBDEV %s bulk %s %p+%zx %dms\n", usbintf->name, ( ( endpoint & USB_ENDPOINT_IN ) ? "IN" : "OUT" ), data, ( ( size_t ) *len ), ( ( unsigned int ) timeout ) ); + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Clear status */ *status = 0; @@ -599,10 +610,12 @@ efi_usb_bulk_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, VOID *data, data, &actual ) ) != 0 ) { /* Assume that any error represents a timeout */ *status = EFI_USB_ERR_TIMEOUT; - return rc; + goto err_transfer; } - return 0; + err_transfer: + bs->RestoreTPL ( saved_tpl ); + return EFIRC ( rc ); } /** @@ -620,16 +633,21 @@ static EFI_STATUS EFIAPI efi_usb_sync_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, VOID *data, UINTN *len, UINTN timeout, UINT32 *status ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_usb_interface *usbintf = container_of ( usbio, struct efi_usb_interface, usbio ); struct efi_usb_device *usbdev = usbintf->usbdev; size_t actual = *len; + EFI_TPL saved_tpl; int rc; DBGC2 ( usbdev, "USBDEV %s sync intr %s %p+%zx %dms\n", usbintf->name, ( ( endpoint & USB_ENDPOINT_IN ) ? "IN" : "OUT" ), data, ( ( size_t ) *len ), ( ( unsigned int ) timeout ) ); + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Clear status */ *status = 0; @@ -639,10 +657,12 @@ efi_usb_sync_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, timeout, data, &actual ) ) != 0 ) { /* Assume that any error represents a timeout */ *status = EFI_USB_ERR_TIMEOUT; - return rc; + goto err_transfer; } - return 0; + err_transfer: + bs->RestoreTPL ( saved_tpl ); + return EFIRC ( rc ); } /** @@ -662,9 +682,11 @@ efi_usb_async_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, BOOLEAN start, UINTN interval, UINTN len, EFI_ASYNC_USB_TRANSFER_CALLBACK callback, VOID *context ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_usb_interface *usbintf = container_of ( usbio, struct efi_usb_interface, usbio ); struct efi_usb_device *usbdev = usbintf->usbdev; + EFI_TPL saved_tpl; int rc; DBGC2 ( usbdev, "USBDEV %s async intr %s len %#zx int %d %p/%p\n", @@ -673,6 +695,9 @@ efi_usb_async_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, ( ( size_t ) len ), ( ( unsigned int ) interval ), callback, context ); + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Start/stop transfer as applicable */ if ( start ) { @@ -687,11 +712,13 @@ efi_usb_async_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, /* Stop transfer */ efi_usb_async_stop ( usbintf, endpoint ); - } + /* Success */ + rc = 0; - return 0; + } err_start: + bs->RestoreTPL ( saved_tpl ); return EFIRC ( rc ); } @@ -889,12 +916,16 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language, struct usb_descriptor_header header; VOID *buffer; size_t len; + EFI_TPL saved_tpl; EFI_STATUS efirc; int rc; DBGC2 ( usbdev, "USBDEV %s get string %d:%d descriptor\n", usbintf->name, language, index ); + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Read descriptor header */ if ( ( rc = usb_get_descriptor ( usbdev->usb, 0, USB_STRING_DESCRIPTOR, index, language, &header, @@ -928,6 +959,9 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language, ( len - sizeof ( header ) ) ); memset ( ( buffer + len - sizeof ( header ) ), 0, sizeof ( **string ) ); + /* Restore TPL */ + bs->RestoreTPL ( saved_tpl ); + /* Return allocated string */ *string = buffer; return 0; @@ -936,6 +970,7 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language, bs->FreePool ( buffer ); err_alloc: err_get_header: + bs->RestoreTPL ( saved_tpl ); return EFIRC ( rc ); } |