grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
From: Arthur Mesh <amesh@juniper.net>
To: <grub-devel@gnu.org>
Subject: [PATCH] Make UEFI watchdog behaviour configurable
Date: Tue, 22 Sep 2015 14:01:03 -0700	[thread overview]
Message-ID: <20150922210103.GS9962@juniper.net> (raw)

[-- Attachment #1: Type: text/plain, Size: 4433 bytes --]

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>
---
 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 b9f41a7..507e1c6 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,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 e9c85de..e3d8288 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -25,9 +25,73 @@
 #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;
+    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)
 {
@@ -43,6 +107,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, 
@@ -77,4 +144,5 @@ grub_efi_fini (void)
 {
   grub_efidisk_fini ();
   grub_console_fini ();
+  grub_unregister_command (cmd_list);
 }
-- 
1.7.9.5


-- 
Arthur Mesh <amesh@juniper.net>
Juniper Networks
+1 408 936-4968

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 648 bytes --]

             reply	other threads:[~2015-09-22 21:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-22 21:01 Arthur Mesh [this message]
2015-10-01 14:55 ` [PATCH] Make UEFI watchdog behaviour configurable Arthur Mesh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150922210103.GS9962@juniper.net \
    --to=amesh@juniper.net \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).