aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2021-11-24 15:43:46 +0000
committerMichael Brown <mcb30@ipxe.org>2021-11-25 09:30:59 +0000
commit9062544f6a0c69c249b90d21a08d05518aafc2ec (patch)
tree137fda7208fd3c7b2311f92d6dcc91a82da2bb34
parent562c74e1ea52a399f7a6c416e35d98f4b37888cf (diff)
downloadipxe-9062544f6a0c69c249b90d21a08d05518aafc2ec.zip
ipxe-9062544f6a0c69c249b90d21a08d05518aafc2ec.tar.gz
ipxe-9062544f6a0c69c249b90d21a08d05518aafc2ec.tar.bz2
[efi] Disable EFI watchdog timer when shutting down to boot an OS
The UEFI specification mandates that the EFI watchdog timer should be disabled by the platform firmware as part of the ExitBootServices() call, but some platforms (e.g. Hyper-V) are observed to occasionally forget to do so, resulting in a reboot approximately five minutes after starting the operating system. Work around these firmware bugs by disabling the watchdog timer ourselves. Requested-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Tested-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/interface/efi/efi_watchdog.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/interface/efi/efi_watchdog.c b/src/interface/efi/efi_watchdog.c
index 7061f81..dcc9a56 100644
--- a/src/interface/efi/efi_watchdog.c
+++ b/src/interface/efi/efi_watchdog.c
@@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <ipxe/retry.h>
#include <ipxe/timer.h>
+#include <ipxe/init.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_watchdog.h>
@@ -80,3 +81,36 @@ static void efi_watchdog_expired ( struct retry_timer *timer,
/** Watchdog holdoff timer */
struct retry_timer efi_watchdog = TIMER_INIT ( efi_watchdog_expired );
+
+/**
+ * Disable watching when shutting down to boot an operating system
+ *
+ * @v booting System is shutting down for OS boot
+ */
+static void efi_watchdog_shutdown ( int booting ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* If we are shutting down to boot an operating system, then
+ * disable the boot services watchdog timer. The UEFI
+ * specification mandates that the platform firmware does this
+ * as part of the ExitBootServices() call, but some platforms
+ * (e.g. Hyper-V) are observed to occasionally forget to do
+ * so, resulting in a reboot approximately five minutes after
+ * starting the operating system.
+ */
+ if ( booting &&
+ ( ( efirc = bs->SetWatchdogTimer ( 0, 0, 0, NULL ) ) != 0 ) ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &efi_watchdog, "EFI could not disable watchdog timer: "
+ "%s\n", strerror ( rc ) );
+ /* Nothing we can do */
+ }
+}
+
+/** Watchdog startup/shutdown function */
+struct startup_fn efi_watchdog_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .name = "efi_watchdog",
+ .shutdown = efi_watchdog_shutdown,
+};