[grub2] Add a patch to implement check_completed_boot

Peter Jones pjones at fedoraproject.org
Fri May 25 19:01:58 UTC 2012


commit a4d61ac7d23de8551ba92496dcfcaaf350862f10
Author: Peter Jones <pjones at redhat.com>
Date:   Fri May 25 13:37:22 2012 -0400

    Add a patch to implement check_completed_boot

 grub-2.00-Add-check_completed_boot.patch |  161 ++++++++++++++++++++++++++++++
 1 files changed, 161 insertions(+), 0 deletions(-)
---
diff --git a/grub-2.00-Add-check_completed_boot.patch b/grub-2.00-Add-check_completed_boot.patch
new file mode 100644
index 0000000..f7f0f8f
--- /dev/null
+++ b/grub-2.00-Add-check_completed_boot.patch
@@ -0,0 +1,161 @@
+From 7b886580f92bf6b766b042b6ef46cb77a5ba7451 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones at redhat.com>
+Date: Fri, 25 May 2012 10:49:06 -0400
+Subject: [PATCH] Add check_completed_boot command on EFI systems.
+
+check_completed_boot <guid> [<timeout>]
+
+checks for a 1-byte integer in an EFI variable guid:CompletedBoot and sets
+a command-line specified timeout, with a default of 30s, if the variable is
+not equal to 1.  This can be used to enter the grub menus in the event that
+your OS did not correctly boot on the previous boot.  It also unconditionally
+sets the value to 0.
+---
+ grub-core/Makefile.core.def           |    6 ++
+ grub-core/commands/efi/eficompleted.c |  117 +++++++++++++++++++++++++++++++++
+ 2 files changed, 123 insertions(+)
+ create mode 100644 grub-core/commands/efi/eficompleted.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index d0c06d5..0a21838 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -582,6 +582,12 @@ module = {
+ };
+ 
+ module = {
++  name = eficompleted;
++  efi = commands/efi/eficompleted.c;
++  enable = efi;
++};
++
++module = {
+   name = blocklist;
+   common = commands/blocklist.c;
+ };
+diff --git a/grub-core/commands/efi/eficompleted.c b/grub-core/commands/efi/eficompleted.c
+new file mode 100644
+index 0000000..77a856a
+--- /dev/null
++++ b/grub-core/commands/efi/eficompleted.c
+@@ -0,0 +1,117 @@
++/* completed.c - Check if previous boot was successful. */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2012  Free Software Foundation, Inc.
++ *
++ *  GRUB is free software: you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation, either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++#include <grub/types.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/command.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++static grub_err_t
++grub_efi_parse_guid(char *arg, grub_efi_guid_t *outguid)
++{
++  grub_err_t status = GRUB_ERR_NONE;
++  grub_efi_guid_t guid;
++  char *s = arg;
++  grub_uint64_t guidcomp;
++  int i;
++
++  guid.data1 = grub_cpu_to_le32 (grub_strtoul(s, &s, 16));
++  if (*s != '-')
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid guid `%s'", arg);
++  s++;
++
++  guid.data2 = grub_cpu_to_le16 (grub_strtoul(s, &s, 16));
++  if (*s != '-')
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid guid `%s'", arg);
++  s++;
++
++  guid.data2 = grub_cpu_to_le16 (grub_strtoul(s, &s, 16));
++  if (*s != '-')
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid guid `%s'", arg);
++  s++;
++
++  guidcomp = grub_strtoull (s, 0, 16);
++  for (i = 0; i < 8; i++)
++    guid.data4[i] = (guidcomp >> (56 - 8 * i)) & 0xff;
++
++  grub_memcpy(outguid, &guid, sizeof (*outguid));
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_cmd_completed (grub_command_t cmd __attribute__ ((unused)),
++		  int argc __attribute__ ((unused)),
++		  char **args __attribute__ ((unused)))
++{
++  grub_efi_uint8_t *old_completed_boot;
++  grub_efi_uint8_t completed_boot = 0;
++  unsigned long timeout = 30;
++  grub_efi_guid_t guid;
++  grub_err_t status;
++  grub_size_t cb_size;
++
++  if (argc < 2)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
++
++  if (argc > 3)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments");
++
++  status = grub_efi_parse_guid(args[1], &guid);
++  if (status != GRUB_ERR_NONE)
++    return status;
++
++  if (argc > 2)
++    {
++      char *s = args[2];
++      timeout = grub_strtoul(s, &s, 0);
++      if (grub_errno != GRUB_ERR_NONE)
++	return grub_errno;
++    }
++
++  old_completed_boot = grub_efi_get_variable("CompletedBoot", &guid, &cb_size);
++  status = grub_efi_set_variable("CompletedBoot", &guid, &completed_boot,
++				 sizeof (completed_boot));
++
++  if (old_completed_boot == NULL)
++    {
++      /* We assume this means it's our first boot after installation. */
++      return GRUB_ERR_NONE;
++    }
++
++  if (cb_size != sizeof(*old_completed_boot) || *old_completed_boot != 1)
++    grub_env_set("timeout", timeout);
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_command_t cmd = NULL;
++
++GRUB_MOD_INIT(eficompleted)
++{
++  cmd = grub_register_command("check_completed_boot", grub_cmd_completed, "",
++			      "Check if the last boot completed successfully.");
++}
++
++GRUB_MOD_FINI(eficompleted)
++{
++  grub_unregister_command (cmd);
++}
+-- 
+1.7.10.1
+


More information about the scm-commits mailing list