summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2020-11-20 16:15:15 +0100
committerMichael Brown2020-11-20 17:57:50 +0100
commite10a40d41fa082ddbd5ccca1d1cc415815759f02 (patch)
treebb7607d0bb3daab858854a688c2ded975b45137d
parent[intel] Use physical addresses in debug messages (diff)
downloadipxe-e10a40d41fa082ddbd5ccca1d1cc415815759f02.tar.gz
ipxe-e10a40d41fa082ddbd5ccca1d1cc415815759f02.tar.xz
ipxe-e10a40d41fa082ddbd5ccca1d1cc415815759f02.zip
[efi] Avoid dropping below TPL as at entry to iPXE
iPXE will currently drop to TPL_APPLICATION whenever the current system time is obtained via currticks(), since the system time mechanism relies on a timer that can fire only when the TPL is below TPL_CALLBACK. This can cause unexpected behaviour if the system time is obtained in the middle of an API call into iPXE by external code. For example, MnpDxe sets up a 10ms periodic timer running at TPL_CALLBACK to poll the underling EFI_SIMPLE_NETWORK_PROTOCOL device for received packets. If the resulting poll within iPXE happens to hit a code path that requires obtaining the current system time (e.g. due to reception of an STP packet, which affects iPXE's blocked link timer), then iPXE will end up temporarily dropping to TPL_APPLICATION. This can potentially result in retriggering the MnpDxe periodic timer, causing code to be unexpectedly re-entered. Fix by recording the external TPL at any entry point into iPXE and dropping only as far as this external TPL, rather than dropping unconditionally to TPL_APPLICATION. The side effect of this change is that iPXE's view of the current system time will be frozen for the duration of any API calls made into iPXE by external code at TPL_CALLBACK or above. Since any such external code is already responsible for allowing execution at TPL_APPLICATION to occur, then this should not cause a problem in practice. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/efi/efi.h11
-rw-r--r--src/interface/efi/efi_driver.c15
-rw-r--r--src/interface/efi/efi_entropy.c4
-rw-r--r--src/interface/efi/efi_init.c34
-rw-r--r--src/interface/efi/efi_snp.c58
-rw-r--r--src/interface/efi/efi_timer.c15
-rw-r--r--src/interface/efi/efi_usb.c36
-rw-r--r--src/interface/efi/efidrvprefix.c8
8 files changed, 110 insertions, 71 deletions
diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h
index 62609b4b..6d0c2567 100644
--- a/src/include/ipxe/efi/efi.h
+++ b/src/include/ipxe/efi/efi.h
@@ -68,6 +68,14 @@ typedef struct {} *EFI_HANDLE;
#include <ipxe/version.h>
#include <ipxe/profile.h>
+/** An EFI saved task priority level */
+struct efi_saved_tpl {
+ /** Current external TPL */
+ EFI_TPL current;
+ /** Previous external TPL */
+ EFI_TPL previous;
+};
+
/** An EFI protocol used by iPXE */
struct efi_protocol {
/** GUID */
@@ -220,6 +228,7 @@ extern EFI_HANDLE efi_image_handle;
extern EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image;
extern EFI_DEVICE_PATH_PROTOCOL *efi_loaded_image_path;
extern EFI_SYSTEM_TABLE *efi_systab;
+extern EFI_TPL efi_external_tpl;
extern int efi_shutdown_in_progress;
extern const __attribute__ (( pure )) char *
@@ -314,5 +323,7 @@ efi_init_stack_guard ( EFI_HANDLE handle ) {
extern EFI_STATUS efi_init ( EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE *systab );
+extern void efi_raise_tpl ( struct efi_saved_tpl *tpl );
+extern void efi_restore_tpl ( struct efi_saved_tpl *tpl );
#endif /* _IPXE_EFI_H */
diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c
index 8388dd53..8e537d53 100644
--- a/src/interface/efi/efi_driver.c
+++ b/src/interface/efi/efi_driver.c
@@ -156,13 +156,13 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_driver *efidrv;
struct efi_device *efidev;
+ struct efi_saved_tpl tpl;
union {
EFI_DEVICE_PATH_PROTOCOL *path;
void *interface;
} path;
EFI_DEVICE_PATH_PROTOCOL *path_end;
size_t path_len;
- EFI_TPL saved_tpl;
EFI_STATUS efirc;
int rc;
@@ -181,7 +181,7 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
}
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Do nothing if we are currently disconnecting drivers */
if ( efi_driver_disconnecting ) {
@@ -236,7 +236,7 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
DBGC ( device, "EFIDRV %s using driver \"%s\"\n",
efi_handle_name ( device ),
efidev->driver->name );
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return 0;
}
DBGC ( device, "EFIDRV %s could not start driver \"%s\": %s\n",
@@ -254,7 +254,7 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
}
err_open_path:
err_disconnecting:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
err_already_started:
return efirc;
}
@@ -273,10 +273,9 @@ static EFI_STATUS EFIAPI
efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
EFI_HANDLE device, UINTN num_children,
EFI_HANDLE *children ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_driver *efidrv;
struct efi_device *efidev;
- EFI_TPL saved_tpl;
+ struct efi_saved_tpl tpl;
UINTN i;
DBGC ( device, "EFIDRV %s DRIVER_STOP", efi_handle_name ( device ) );
@@ -295,7 +294,7 @@ efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
}
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Stop this device */
efidrv = efidev->driver;
@@ -304,7 +303,7 @@ efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
list_del ( &efidev->dev.siblings );
free ( efidev );
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return 0;
}
diff --git a/src/interface/efi/efi_entropy.c b/src/interface/efi/efi_entropy.c
index dca0b6f1..70cd0629 100644
--- a/src/interface/efi/efi_entropy.c
+++ b/src/interface/efi/efi_entropy.c
@@ -79,8 +79,8 @@ static int efi_entropy_enable ( void ) {
DBGC ( &tick, "ENTROPY %s RNG protocol\n",
( efirng ? "has" : "has no" ) );
- /* Drop to TPL_APPLICATION to allow timer tick event to take place */
- bs->RestoreTPL ( TPL_APPLICATION );
+ /* Drop to external TPL to allow timer tick event to take place */
+ bs->RestoreTPL ( efi_external_tpl );
/* Create timer tick event */
if ( ( efirc = bs->CreateEvent ( EVT_TIMER, TPL_NOTIFY, NULL, NULL,
diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c
index 6d46c566..b7cac16e 100644
--- a/src/interface/efi/efi_init.c
+++ b/src/interface/efi/efi_init.c
@@ -47,6 +47,9 @@ EFI_DEVICE_PATH_PROTOCOL *efi_loaded_image_path;
*/
EFI_SYSTEM_TABLE * _C2 ( PLATFORM, _systab );
+/** External task priority level */
+EFI_TPL efi_external_tpl = TPL_APPLICATION;
+
/** EFI shutdown is in progress */
int efi_shutdown_in_progress;
@@ -361,3 +364,34 @@ __attribute__ (( noreturn )) void __stack_chk_fail ( void ) {
while ( 1 ) {}
}
+
+/**
+ * Raise task priority level to TPL_CALLBACK
+ *
+ * @v tpl Saved TPL
+ */
+void efi_raise_tpl ( struct efi_saved_tpl *tpl ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ /* Record current external TPL */
+ tpl->previous = efi_external_tpl;
+
+ /* Raise TPL and record previous TPL as new external TPL */
+ tpl->current = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_external_tpl = tpl->current;
+}
+
+/**
+ * Restore task priority level
+ *
+ * @v tpl Saved TPL
+ */
+void efi_restore_tpl ( struct efi_saved_tpl *tpl ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ /* Restore external TPL */
+ efi_external_tpl = tpl->previous;
+
+ /* Restore TPL */
+ bs->RestoreTPL ( tpl->current );
+}
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
index 5285d322..c1ce9042 100644
--- a/src/interface/efi/efi_snp.c
+++ b/src/interface/efi/efi_snp.c
@@ -48,7 +48,7 @@ static LIST_HEAD ( efi_snp_devices );
static int efi_snp_claimed;
/** TPL prior to network devices being claimed */
-static EFI_TPL efi_snp_old_tpl;
+static struct efi_saved_tpl efi_snp_saved_tpl;
/* Downgrade user experience if configured to do so
*
@@ -235,10 +235,9 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
static EFI_STATUS EFIAPI
efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev =
container_of ( snp, struct efi_snp_device, snp );
- EFI_TPL saved_tpl;
+ struct efi_saved_tpl tpl;
int rc;
DBGC ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
@@ -252,7 +251,7 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
}
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Open network device */
if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
@@ -263,7 +262,7 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
efi_snp_set_state ( snpdev );
err_open:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
err_claimed:
return EFIRC ( rc );
}
@@ -277,10 +276,9 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
*/
static EFI_STATUS EFIAPI
efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev =
container_of ( snp, struct efi_snp_device, snp );
- EFI_TPL saved_tpl;
+ struct efi_saved_tpl tpl;
int rc;
DBGC ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
@@ -293,7 +291,7 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
}
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Close network device */
netdev_close ( snpdev->netdev );
@@ -309,7 +307,7 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
efi_snp_set_state ( snpdev );
err_open:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
err_claimed:
return EFIRC ( rc );
}
@@ -322,10 +320,9 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
*/
static EFI_STATUS EFIAPI
efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev =
container_of ( snp, struct efi_snp_device, snp );
- EFI_TPL saved_tpl;
+ struct efi_saved_tpl tpl;
DBGC ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
@@ -334,7 +331,7 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
return EFI_NOT_READY;
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Close network device */
netdev_close ( snpdev->netdev );
@@ -342,7 +339,7 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
efi_snp_flush ( snpdev );
/* Restore TPL */
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return 0;
}
@@ -546,10 +543,9 @@ efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
static EFI_STATUS EFIAPI
efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
UINT32 *interrupts, VOID **txbuf ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev =
container_of ( snp, struct efi_snp_device, snp );
- EFI_TPL saved_tpl;
+ struct efi_saved_tpl tpl;
DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
@@ -560,7 +556,7 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
}
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Poll the network device */
efi_snp_poll ( snpdev );
@@ -585,7 +581,7 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
}
/* Restore TPL */
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
DBGC2 ( snpdev, "\n" );
return 0;
@@ -608,14 +604,13 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
UINTN ll_header_len, UINTN len, VOID *data,
EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
UINT16 *net_proto ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev =
container_of ( snp, struct efi_snp_device, snp );
struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
+ struct efi_saved_tpl tpl;
struct io_buffer *iobuf;
size_t payload_len;
unsigned int tx_fill;
- EFI_TPL saved_tpl;
int rc;
DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
@@ -642,7 +637,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
}
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Sanity checks */
if ( ll_header_len ) {
@@ -727,7 +722,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
snpdev->interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
/* Restore TPL */
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return 0;
@@ -737,7 +732,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
free_iob ( iobuf );
err_alloc_iob:
err_sanity:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
err_claimed:
return EFIRC ( rc );
}
@@ -759,17 +754,16 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
UINTN *ll_header_len, UINTN *len, VOID *data,
EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
UINT16 *net_proto ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev =
container_of ( snp, struct efi_snp_device, snp );
struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
+ struct efi_saved_tpl tpl;
struct io_buffer *iobuf;
const void *iob_ll_dest;
const void *iob_ll_src;
uint16_t iob_net_proto;
unsigned int iob_flags;
size_t copy_len;
- EFI_TPL saved_tpl;
int rc;
DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
@@ -782,7 +776,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
}
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Poll the network device */
efi_snp_poll ( snpdev );
@@ -831,7 +825,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
out_bad_ll_header:
free_iob ( iobuf );
out_no_packet:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
err_claimed:
return EFIRC ( rc );
}
@@ -844,9 +838,8 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
*/
static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event __unused,
VOID *context ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev = context;
- EFI_TPL saved_tpl;
+ struct efi_saved_tpl tpl;
DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
@@ -859,13 +852,13 @@ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event __unused,
return;
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Poll the network device */
efi_snp_poll ( snpdev );
/* Restore TPL */
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
}
/** SNP interface */
@@ -1967,12 +1960,11 @@ struct efi_snp_device * last_opened_snpdev ( void ) {
* @v delta Claim count change
*/
void efi_snp_add_claim ( int delta ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev;
/* Raise TPL if we are about to claim devices */
if ( ! efi_snp_claimed )
- efi_snp_old_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &efi_snp_saved_tpl );
/* Claim SNP devices */
efi_snp_claimed += delta;
@@ -1984,5 +1976,5 @@ void efi_snp_add_claim ( int delta ) {
/* Restore TPL if we have released devices */
if ( ! efi_snp_claimed )
- bs->RestoreTPL ( efi_snp_old_tpl );
+ efi_restore_tpl ( &efi_snp_saved_tpl );
}
diff --git a/src/interface/efi/efi_timer.c b/src/interface/efi/efi_timer.c
index 8f40cb81..405cd345 100644
--- a/src/interface/efi/efi_timer.c
+++ b/src/interface/efi/efi_timer.c
@@ -97,8 +97,17 @@ static unsigned long efi_currticks ( void ) {
* gain us any substantive benefits (since even with such
* calls we would still be suffering from the limitations of a
* polling design), we instead choose to run at TPL_CALLBACK
- * almost all of the time, dropping to TPL_APPLICATION to
- * allow timer ticks to occur.
+ * almost all of the time, dropping to a lower TPL to allow
+ * timer ticks to occur.
+ *
+ * We record the external TPL at the point of entry into iPXE,
+ * and drop back only as far as this external TPL. This
+ * avoids the unexpected behaviour that may arise from having
+ * iPXE temporarily drop to TPL_APPLICATION in the middle of
+ * an entry point invoked at TPL_CALLBACK. The side effect is
+ * that iPXE's view of the system time is effectively frozen
+ * for the duration of any call made in to iPXE at
+ * TPL_CALLBACK or higher.
*
*
* For added excitement, UEFI provides no clean way for device
@@ -127,7 +136,7 @@ static unsigned long efi_currticks ( void ) {
if ( efi_shutdown_in_progress ) {
efi_jiffies++;
} else {
- bs->RestoreTPL ( TPL_APPLICATION );
+ bs->RestoreTPL ( efi_external_tpl );
bs->RaiseTPL ( TPL_CALLBACK );
}
diff --git a/src/interface/efi/efi_usb.c b/src/interface/efi/efi_usb.c
index 55b5bc88..bcf15699 100644
--- a/src/interface/efi/efi_usb.c
+++ b/src/interface/efi/efi_usb.c
@@ -551,7 +551,6 @@ 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;
@@ -559,7 +558,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;
+ struct efi_saved_tpl tpl;
int rc;
DBGC2 ( usbdev, "USBDEV %s control %04x:%04x:%04x:%04x %s %dms "
@@ -569,7 +568,7 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio,
( ( size_t ) len ) );
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Clear status */
*status = 0;
@@ -613,7 +612,7 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio,
err_control:
err_change_config:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return EFIRC ( rc );
}
@@ -631,12 +630,11 @@ 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;
+ struct efi_saved_tpl tpl;
int rc;
DBGC2 ( usbdev, "USBDEV %s bulk %s %p+%zx %dms\n", usbintf->name,
@@ -644,7 +642,7 @@ efi_usb_bulk_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, VOID *data,
( ( size_t ) *len ), ( ( unsigned int ) timeout ) );
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Clear status */
*status = 0;
@@ -659,7 +657,7 @@ efi_usb_bulk_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint, VOID *data,
}
err_transfer:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return EFIRC ( rc );
}
@@ -678,12 +676,11 @@ 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;
+ struct efi_saved_tpl tpl;
int rc;
DBGC2 ( usbdev, "USBDEV %s sync intr %s %p+%zx %dms\n", usbintf->name,
@@ -691,7 +688,7 @@ efi_usb_sync_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint,
( ( size_t ) *len ), ( ( unsigned int ) timeout ) );
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Clear status */
*status = 0;
@@ -706,7 +703,7 @@ efi_usb_sync_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint,
}
err_transfer:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return EFIRC ( rc );
}
@@ -727,11 +724,10 @@ 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;
+ struct efi_saved_tpl tpl;
int rc;
DBGC2 ( usbdev, "USBDEV %s async intr %s len %#zx int %d %p/%p\n",
@@ -741,7 +737,7 @@ efi_usb_async_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint,
callback, context );
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Start/stop transfer as applicable */
if ( start ) {
@@ -763,7 +759,7 @@ efi_usb_async_interrupt_transfer ( EFI_USB_IO_PROTOCOL *usbio, UINT8 endpoint,
}
err_start:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return EFIRC ( rc );
}
@@ -959,9 +955,9 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language,
container_of ( usbio, struct efi_usb_interface, usbio );
struct efi_usb_device *usbdev = usbintf->usbdev;
struct usb_descriptor_header header;
+ struct efi_saved_tpl tpl;
VOID *buffer;
size_t len;
- EFI_TPL saved_tpl;
EFI_STATUS efirc;
int rc;
@@ -969,7 +965,7 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language,
usbintf->name, language, index );
/* Raise TPL */
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Read descriptor header */
if ( ( rc = usb_get_descriptor ( usbdev->func->usb, 0,
@@ -1012,7 +1008,7 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language,
memset ( ( buffer + len - sizeof ( header ) ), 0, sizeof ( **string ) );
/* Restore TPL */
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
/* Return allocated string */
*string = buffer;
@@ -1023,7 +1019,7 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language,
err_alloc:
err_len:
err_get_header:
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return EFIRC ( rc );
}
diff --git a/src/interface/efi/efidrvprefix.c b/src/interface/efi/efidrvprefix.c
index ac7d9437..9ca54ff4 100644
--- a/src/interface/efi/efidrvprefix.c
+++ b/src/interface/efi/efidrvprefix.c
@@ -34,8 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
*/
EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE *systab ) {
- EFI_BOOT_SERVICES *bs;
- EFI_TPL saved_tpl;
+ static struct efi_saved_tpl tpl; /* avoid triggering stack protector */
EFI_STATUS efirc;
/* Initialise stack cookie */
@@ -46,15 +45,14 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
return efirc;
/* Raise TPL */
- bs = efi_systab->BootServices;
- saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ efi_raise_tpl ( &tpl );
/* Initialise iPXE environment */
initialise();
startup();
/* Restore TPL */
- bs->RestoreTPL ( saved_tpl );
+ efi_restore_tpl ( &tpl );
return 0;
}