Starting with d9a0c9413e81d3c0affc6383693bdd28dc863a5c, GRUB unconditionally disables watchdog on EFI platforms. This opens up a window (starting at GRUB's grub_efi_init(), until OS re-enables it) when EFI system operates w/o watchdog. If an EFI system gets stuck in that window, the chipset will never reset the system.
Add `--enable-efi-watchdog' configure argument, which defaults to Off. When enabled, efi watchdog will not be disabled. Otherwise, efi watchdog will be disabled. Create a command line interface to enable/disable watchdog: efi-watchdog (enable|disable) <timeout> --- configure.ac | 18 +++++++++++++- docs/grub.texi | 8 ++++++ grub-core/kern/efi/init.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c864311..91de439 100644 --- a/configure.ac +++ b/configure.ac @@ -211,7 +211,10 @@ esac case "$platform" in coreboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_COREBOOT=1" ;; multiboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MULTIBOOT=1" ;; - efi) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EFI=1" ;; + efi) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EFI=1" + if test x"$enable_efi_watchdog" = xyes ; then + machine_CPPFLAGS="$machine_CPPFLAGS -DEFI_WATCHDOG_LEAVE_ALONE=1" + fi ;; xen) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_XEN=1" ;; ieee1275) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_IEEE1275=1" ;; uboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_UBOOT=1" ;; @@ -1705,6 +1708,10 @@ if test x"$enable_werror" != xno ; then HOST_CFLAGS="$HOST_CFLAGS -Werror" fi +AC_ARG_ENABLE([efi-watchdog], + [AS_HELP_STRING([--enable-efi-watchdog], + [Do not explicitly disable EFI watchdog])]) + TARGET_CPP="$TARGET_CC -E" TARGET_CCAS=$TARGET_CC @@ -1899,6 +1906,15 @@ echo efiemu runtime: Yes else echo efiemu runtime: No "($efiemu_excuse)" fi + +if [ x"$platform" = xefi ]; then +if [ x"$enable_efi_watchdog" != xyes ]; then +echo disable EFI watchdog: Yes +else +echo disable EFI watchdog: No +fi +fi + if [ x"$grub_mkfont_excuse" = x ]; then echo grub-mkfont: Yes else diff --git a/docs/grub.texi b/docs/grub.texi index b9f41a7..4cfd50c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3784,6 +3784,7 @@ you forget a command, you can run the command @command{help} * distrust:: Remove a pubkey from trusted keys * drivemap:: Map a drive to another * echo:: Display a line of text +* efi-watchdog:: Manipulate EFI watchdog * eval:: Evaluate agruments as GRUB commands * export:: Export an environment variable * false:: Do nothing, unsuccessfully @@ -4192,6 +4193,13 @@ When interpreting backslash escapes, backslash followed by any other character will print that character. @end deffn +@node efi-watchdog +@subsection efi-watchdog + +@deffn Command efi-watchdog enable|disable <timeout> +Enable or disable the system's watchdog timer. Only available in EFI targeted +GRUB. +@end deffn @node eval @subsection eval diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index e9c85de..47053d2 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -25,9 +25,62 @@ #include <grub/env.h> #include <grub/mm.h> #include <grub/kernel.h> +#include <grub/extcmd.h> +#include <grub/command.h> grub_addr_t grub_modbase; +static grub_command_t cmd_list; + +static grub_err_t +grub_cmd_efi_watchdog (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + long input; + grub_efi_status_t status; + grub_efi_uintn_t timeout; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("efi-watchdog (enable|disable) <timeout>")); + + if (grub_strcasecmp (args[0], "enable") == 0) { + + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("efi-watchdog enable <timeout>")); + + input = grub_strtol (args[1], 0, 0); + + if (input >= 0) { + timeout = input; + } else { + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("<timeout> must be non-negative")); + } + + } else if (grub_strcasecmp (args[0], "disable") == 0) { + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("efi-watchdog disable")); + timeout = 0; + + } else { + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("efi-watchdog (enable|disable) <timeout>")); + } + + status = efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer, + timeout, 0, sizeof(L"GRUB"), L"GRUB"); + + if (status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BUG, + N_("EFI SetWatchdogTimer() bug")); + else + return GRUB_ERR_NONE; +} + void grub_efi_init (void) { @@ -39,10 +92,15 @@ grub_efi_init (void) /* Initialize the memory management system. */ grub_efi_mm_init (); +#ifndef EFI_WATCHDOG_LEAVE_ALONE efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer, 0, 0, 0, NULL); +#endif grub_efidisk_init (); + + cmd_list = grub_register_command ("efi-watchdog", grub_cmd_efi_watchdog, 0, + N_("Enable/Disable system's watchdog timer.")); } void (*grub_efi_net_config) (grub_efi_handle_t hnd, @@ -77,4 +135,5 @@ grub_efi_fini (void) { grub_efidisk_fini (); grub_console_fini (); + grub_unregister_command (cmd_list); } -- 1.7.9.5
pgpcSPnP55qA9.pgp
Description: PGP signature
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel