]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Raise TPL within EFI_USB_IO_PROTOCOL entry points
authorMichael Brown <mcb30@ipxe.org>
Tue, 20 Feb 2018 11:19:39 +0000 (11:19 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 20 Feb 2018 11:19:39 +0000 (11:19 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/interface/efi/efi_usb.c

index f9c91d09ba431820897d0c4cc331abe9e652d55a..48274f1d6200e2f820a8e44e02c2dfafde7f8af1 100644 (file)
@@ -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 );
 }