integ/grub/grub-efi/debian/patches/0003-Make-UEFI-watchdog-beh...

154 lines
4.8 KiB
Diff

From d8d9c3ce2441be42fc65d2bde5d0fb299de39ad0 Mon Sep 17 00:00:00 2001
From: Jiang Lu <lu.jiang@windriver.com>
Date: Thu, 31 Jan 2019 15:27:03 +0800
Subject: [PATCH] Make UEFI watchdog behaviour configurable
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.
Create a command line interface to enable/disable watchdog:
efi-watchdog (enable|disable) <code> <timeout>
Signed-off-by: Jiang Lu <lu.jiang@windriver.com>
Rebase for grub 2.06
Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
---
docs/grub.texi | 11 +++++++
grub-core/kern/efi/init.c | 68 +++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/docs/grub.texi b/docs/grub.texi
index f8b4b3b..95e8367 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3991,6 +3991,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
@@ -4442,6 +4443,16 @@ 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 <code> <timeout>
+Enable or disable the system's watchdog timer. Only available in EFI targeted
+GRUB.
+The <code> is logged upon watchdog timeout event. The UEFI BIOS reserves codes
+0x0000 to 0xFFFF.
+The <timeout> represents number of seconds to set the watchdog timeout to.
+@end deffn
@node eval
@subsection eval
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index 7facacf..4a88397 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -28,6 +28,8 @@
#include <grub/mm.h>
#include <grub/kernel.h>
#include <grub/stack_protector.h>
+#include <grub/extcmd.h>
+#include <grub/command.h>
#ifdef GRUB_STACK_PROTECTOR
@@ -82,6 +84,68 @@ stack_protector_init (void)
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;
+ grub_efi_uint64_t code;
+
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("usage: efi-watchdog (enable|disable) <code> <timeout>"));
+
+ if (grub_strcasecmp (args[0], "enable") == 0) {
+
+ if (argc != 3)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("usage: efi-watchdog enable <code> <timeout>"));
+
+ input = grub_strtol (args[1], 0, 0);
+
+ if (input >= 0) {
+ code = input;
+ } else {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("<code> must be non-negative"));
+ }
+
+ input = grub_strtol (args[2], 0, 0);
+
+ if (input >= 0) {
+ timeout = (grub_efi_uintn_t) 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_("usage: efi-watchdog disable"));
+ timeout = 0;
+ code = 0;
+
+ } else {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("usage: efi-watchdog (enable|disable) <code> <timeout>"));
+ }
+
+ status = efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
+ timeout, code, sizeof(L"GRUB"), L"GRUB");
+
+ if (status != GRUB_EFI_SUCCESS)
+ return grub_error (GRUB_ERR_BUG,
+ N_("Unexpected UEFI SetWatchdogTimer() error"));
+ else
+ return GRUB_ERR_NONE;
+}
+
void
grub_efi_init (void)
{
@@ -109,6 +173,9 @@ grub_efi_init (void)
0, 0, 0, NULL);
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,
@@ -146,4 +213,5 @@ grub_efi_fini (void)
{
grub_efidisk_fini ();
grub_console_fini ();
+ grub_unregister_command (cmd_list);
}
--
2.17.1