summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_timer.c
Commit message (Collapse)AuthorAgeFilesLines
* [build] Mark core files as permitted for UEFI Secure BootMichael Brown2026-01-141-0/+1
| | | | | | | | | | | | Mark all files used in a standard build of bin-x86_64-efi/snponly.efi as permitted for UEFI Secure Boot. These files represent the core functionality of iPXE that is guaranteed to have been included in every binary that was previously subject to a security review and signed by Microsoft. It is therefore legitimate to assume that at least these files have already been reviewed to the required standard multiple times. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Run ExitBootServices shutdown hook at TPL_NOTIFYMichael Brown2021-11-231-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On some systems (observed with the Thunderbolt ports on a ThinkPad X1 Extreme Gen3 and a ThinkPad P53), if the IOMMU is enabled then the system firmware will install an ExitBootServices notification event that disables bus mastering on the Thunderbolt xHCI controller and all PCI bridges, and destroys any extant IOMMU mappings. This leaves the xHCI controller unable to perform any DMA operations. As described in commit 236299b ("[xhci] Avoid DMA during shutdown if firmware has disabled bus mastering"), any subsequent DMA operation attempted by the xHCI controller will end up completing after the operating system kernel has reenabled bus mastering, resulting in a DMA operation to an area of memory that the hardware is no longer permitted to access and, on Windows with the Driver Verifier enabled, a STOP 0xE6 (DRIVER_VERIFIER_DMA_VIOLATION). That commit avoids triggering any DMA attempts during the shutdown of the xHCI controller itself. However, this is not a complete solution since any attached and opened USB device (e.g. a USB NIC) may asynchronously trigger DMA attempts that happen to occur after bus mastering has been disabled but before we reset the xHCI controller. Avoid this problem by installing our own ExitBootServices notification event at TPL_NOTIFY, thereby causing it to be invoked before the firmware's own ExitBootServices notification event that disables bus mastering. This unsurprisingly causes the shutdown hook itself to be invoked at TPL_NOTIFY, which causes a fatal error when later code attempts to raise the TPL to TPL_CALLBACK (which is a lower TPL). Work around this problem by redefining the "internal" iPXE TPL to be variable, and set this internal TPL to TPL_NOTIFY when the shutdown hook is invoked. Avoid calling into an underlying SNP protocol instance from within our shutdown hook at TPL_NOTIFY, since the underlying SNP driver may attempt to raise the TPL to TPL_CALLBACK (which would cause a fatal error). Failing to shut down the underlying SNP device is safe to do since the underlying device must, in any case, have installed its own ExitBootServices hook if any shutdown actions are required. Reported-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Tested-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Avoid dropping below TPL as at entry to iPXEMichael Brown2020-11-201-3/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* [init] Show startup and shutdown function names in debug messagesMichael Brown2019-01-251-0/+1
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Run at TPL_CALLBACK to protect against UEFI timersMichael Brown2018-02-201-6/+35
| | | | | | | | | | | | | | | | | | | As noted in the comments, UEFI manages to combines the all of the worst aspects of both a polling design (inefficiency and inability to sleep until something interesting happens) and of an interrupt-driven design (the complexity of code that could be preempted at any time, thanks to UEFI timers). This causes problems in particular for UEFI USB keyboards: the keyboard driver calls UsbAsyncInterruptTransfer() to set up a periodic timer which is used to poll the USB bus. This poll may interrupt a critical section within iPXE, typically resulting in list corruption and either a hang or reboot. Work around this problem by mirroring the BIOS design, in which we run with interrupts disabled almost all of the time. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [time] Allow timer to be selected at runtimeMichael Brown2017-01-261-6/+16
| | | | | | | | | | | | | | | | | | | | | | Allow the active timer (providing udelay() and currticks()) to be selected at runtime based on probing during the INIT_EARLY stage of initialisation. TICKS_PER_SEC is now a fixed compile-time constant for all builds, and is independent of the underlying clock tick rate. We choose the value 1024 to allow multiplications and divisions on seconds to be converted to bit shifts. TICKS_PER_MS is defined as 1, allowing multiplications and divisions on milliseconds to be omitted entirely. The 2% inaccuracy in this definition is negligible when using the standard BIOS timer (running at around 18.2Hz). TIMER_RDTSC now checks for a constant TSC before claiming to be a usable timer. (This timer can be tested in KVM via the command-line option "-cpu host,+invtsc".) Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Work around temporal anomaly encountered during ExitBootServices()Michael Brown2016-12-071-0/+25
| | | | | | | | | | | | | | | | | | | | | | | | EFI provides no clean way for device drivers to shut down in preparation for handover to a booted operating system. The platform firmware simply doesn't bother to call the drivers' Stop() methods. Instead, drivers must register an EVT_SIGNAL_EXIT_BOOT_SERVICES event to be signalled when ExitBootServices() is called, and clean up without any reference to the EFI driver model. Unfortunately, all timers silently stop working when ExitBootServices() is called. Even more unfortunately, and for no discernible reason, this happens before any EVT_SIGNAL_EXIT_BOOT_SERVICES events are signalled. The net effect of this entertaining design choice is that any timeout loops on the shutdown path (e.g. for gracefully closing outstanding TCP connections) may wait indefinitely. There is no way to report failure from currticks(), since the API lazily assumes that the host system continues to travel through time in the usual direction. Work around EFI's violation of this assumption by falling back to a simple free-running monotonic counter. Debugged-by: Maor Dickman <maord@mellanox.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Report failures to stop the EFI timer tick eventMichael Brown2016-06-201-2/+16
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Use a timer event to generate the currticks() timerMichael Brown2016-05-041-50/+68
| | | | | | | | | | | | | | We currently use the EFI_CPU_ARCH_PROTOCOL's GetTimerValue() method to generate the currticks() timer, calibrated against a 1ms delay from the boot services Stall() method. This does not work on ARM platforms, where GetTimerValue() is an empty stub which just returns EFI_UNSUPPORTED. Fix by instead creating a periodic timer event, and using this event to increment a current tick counter. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [legal] Relicense files under GPL2_OR_LATER_OR_UBDLMichael Brown2015-03-021-1/+5
| | | | | | | Relicense files for which I am the sole author (as identified by util/relicense.pl). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Perform meaningful error code conversionsMichael Brown2013-04-191-3/+8
| | | | | | | | Exploit the redefinition of iPXE error codes to include a "platform error code" to allow for meaningful conversion of EFI_STATUS values to iPXE errors and vice versa. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [legal] Update FSF mailing address in GPL licence textsMichael Brown2012-07-201-1/+2
| | | | | Suggested-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [build] Rename gPXE to iPXEMichael Brown2010-04-201-4/+4
| | | | | | | | | | | Access to the gpxe.org and etherboot.org domains and associated resources has been revoked by the registrant of the domain. Work around this problem by renaming project from gPXE to iPXE, and updating URLs to match. Also update README, LOG and COPYRIGHTS to remove obsolete information. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [legal] Add a selection of FILE_LICENCE declarationsMichael Brown2009-05-181-0/+2
| | | | | Add FILE_LICENCE declarations to almost all files that make up the various standard builds of gPXE.
* [efi] Add efi_strerror()Michael Brown2008-11-191-3/+4
| | | | | | | | | EFI_STATUS is defined as an INTN, which maps to UINT32 (i.e. unsigned int) on i386 and UINT64 (i.e. unsigned long) on x86_64. This would require a cast each time the error status is printed. Add efi_strerror() to avoid this ickiness and simultaneously enable prettier reporting of EFI status codes.
* [i386] Change [u]int32_t to [unsigned] int, rather than [unsigned] longMichael Brown2008-11-191-2/+2
| | | | | | This brings us in to line with Linux definitions, and also simplifies adding x86_64 support since both platforms have 2-byte shorts, 4-byte ints and 8-byte long longs.
* [efi] Add EFI image format and basic runtime environmentMichael Brown2008-10-131-0/+115
We have EFI APIs for CPU I/O, PCI I/O, timers, console I/O, user access and user memory allocation. EFI executables are created using the vanilla GNU toolchain, with the EXE header handcrafted in assembly and relocations generated by a custom efilink utility.