summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brown2018-02-20 12:19:39 +0100
committerMichael Brown2018-02-20 12:19:39 +0100
commitf672a27b34220865b403df519593f382859559e0 (patch)
tree67723bacf80a2c9f67a20d8946f03731868b8b34 /src
parent[efi] Raise TPL within EFI_SIMPLE_NETWORK_PROTOCOL entry points (diff)
downloadipxe-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.c47
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 );
}