aboutsummaryrefslogtreecommitdiff
path: root/src/include/ipxe/efi
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2020-11-20 15:15:15 +0000
committerMichael Brown <mcb30@ipxe.org>2020-11-20 16:57:50 +0000
commite10a40d41fa082ddbd5ccca1d1cc415815759f02 (patch)
treebb7607d0bb3daab858854a688c2ded975b45137d /src/include/ipxe/efi
parent062711f1cfacd0708107933b6a977476a7f7479e (diff)
downloadipxe-e10a40d41fa082ddbd5ccca1d1cc415815759f02.zip
ipxe-e10a40d41fa082ddbd5ccca1d1cc415815759f02.tar.gz
ipxe-e10a40d41fa082ddbd5ccca1d1cc415815759f02.tar.bz2
[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>
Diffstat (limited to 'src/include/ipxe/efi')
-rw-r--r--src/include/ipxe/efi/efi.h11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h
index 62609b4..6d0c256 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 */