daandemeyer / rpms / grub2

Forked from rpms/grub2 5 months ago
Clone
7e98da0
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
7e98da0
From: Peter Jones <pjones@redhat.com>
7e98da0
Date: Thu, 4 Oct 2018 14:22:09 -0400
7e98da0
Subject: [PATCH] Reimplement boot_counter
7e98da0
7e98da0
This adds "increment" and "decrement" commands, and uses them to maintain our
7e98da0
variables in 01_fallback_counter.  It also simplifies the counter logic, so
7e98da0
that there are no nested tests that conflict with each other.
7e98da0
7e98da0
Apparently, this *really* wasn't tested well enough.
7e98da0
7e98da0
Resolves: rhbz#1614637
7e98da0
Signed-off-by: Peter Jones <pjones@redhat.com>
7e98da0
[lorbus: add comments and revert logic changes in 01_fallback_counting]
7e98da0
Signed-off-by: Christian Glombek <lorbus@fedoraproject.org>
7e98da0
---
7e98da0
 Makefile.util.def                   |   6 +++
7e98da0
 grub-core/Makefile.core.def         |   5 ++
7e98da0
 grub-core/commands/increment.c      | 105 ++++++++++++++++++++++++++++++++++++
7e98da0
 util/grub.d/01_fallback_counting.in |  22 ++++++++
7e98da0
 4 files changed, 138 insertions(+)
7e98da0
 create mode 100644 grub-core/commands/increment.c
7e98da0
 create mode 100644 util/grub.d/01_fallback_counting.in
7e98da0
7e98da0
diff --git a/Makefile.util.def b/Makefile.util.def
3d407d2
index d066652e9b..e10fe766d1 100644
7e98da0
--- a/Makefile.util.def
7e98da0
+++ b/Makefile.util.def
46968b6
@@ -458,6 +458,12 @@ script = {
7e98da0
   installdir = grubconf;
7e98da0
 };
7e98da0
 
7e98da0
+script = {
7e98da0
+  name = '01_fallback_counting';
7e98da0
+  common = util/grub.d/01_fallback_counting.in;
7e98da0
+  installdir = grubconf;
7e98da0
+};
7e98da0
+
7e98da0
 script = {
7e98da0
   name = '01_menu_auto_hide';
7e98da0
   common = util/grub.d/01_menu_auto_hide.in;
7e98da0
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
ed1787d
index 4f203533f5..ea4d59f51b 100644
7e98da0
--- a/grub-core/Makefile.core.def
7e98da0
+++ b/grub-core/Makefile.core.def
46968b6
@@ -398,6 +398,11 @@ kernel = {
7e98da0
   extra_dist = kern/mips/cache_flush.S;
7e98da0
 };
7e98da0
 
7e98da0
+module = {
7e98da0
+  name = increment;
7e98da0
+  common = commands/increment.c;
7e98da0
+};
7e98da0
+
7e98da0
 program = {
7e98da0
   name = grub-emu;
7e98da0
   mansection = 1;
7e98da0
diff --git a/grub-core/commands/increment.c b/grub-core/commands/increment.c
7e98da0
new file mode 100644
e622855
index 0000000000..79cf137656
7e98da0
--- /dev/null
7e98da0
+++ b/grub-core/commands/increment.c
7e98da0
@@ -0,0 +1,105 @@
7e98da0
+/* increment.c - Commands to increment and decrement variables. */
7e98da0
+/*
7e98da0
+ *  GRUB  --  GRand Unified Bootloader
7e98da0
+ *  Copyright (C) 2006,2007,2008  Free Software Foundation, Inc.
7e98da0
+ *
7e98da0
+ *  GRUB is free software: you can redistribute it and/or modify
7e98da0
+ *  it under the terms of the GNU General Public License as published by
7e98da0
+ *  the Free Software Foundation, either version 3 of the License, or
7e98da0
+ *  (at your option) any later version.
7e98da0
+ *
7e98da0
+ *  GRUB is distributed in the hope that it will be useful,
7e98da0
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
7e98da0
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7e98da0
+ *  GNU General Public License for more details.
7e98da0
+ *
7e98da0
+ *  You should have received a copy of the GNU General Public License
7e98da0
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
7e98da0
+ */
7e98da0
+
7e98da0
+#include <grub/dl.h>
7e98da0
+#include <grub/term.h>
7e98da0
+#include <grub/time.h>
7e98da0
+#include <grub/types.h>
7e98da0
+#include <grub/misc.h>
7e98da0
+#include <grub/extcmd.h>
7e98da0
+#include <grub/i18n.h>
7e98da0
+#include <grub/env.h>
7e98da0
+
7e98da0
+GRUB_MOD_LICENSE ("GPLv3+");
7e98da0
+
7e98da0
+typedef enum {
7e98da0
+    INCREMENT,
7e98da0
+    DECREMENT,
7e98da0
+} operation;
7e98da0
+
7e98da0
+static grub_err_t
7e98da0
+incr_decr(operation op, int argc, char **args)
7e98da0
+{
7e98da0
+  const char *old;
7e98da0
+  char *new;
7e98da0
+  long value;
7e98da0
+
7e98da0
+  if (argc < 1)
7e98da0
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no variable specified"));
7e98da0
+  if (argc > 1)
7e98da0
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("too many arguments"));
7e98da0
+
7e98da0
+  old = grub_env_get (*args);
7e98da0
+  if (!old)
7e98da0
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("No such variable \"%s\""),
7e98da0
+		       *args);
7e98da0
+
7e98da0
+  value = grub_strtol (old, NULL, 0);
7e98da0
+  if (grub_errno != GRUB_ERR_NONE)
7e98da0
+    return grub_errno;
7e98da0
+
7e98da0
+  switch (op)
7e98da0
+    {
7e98da0
+    case INCREMENT:
7e98da0
+      value += 1;
7e98da0
+      break;
7e98da0
+    case DECREMENT:
7e98da0
+      value -= 1;
7e98da0
+      break;
7e98da0
+    }
7e98da0
+
7e98da0
+  new = grub_xasprintf ("%ld", value);
7e98da0
+  if (!new)
7e98da0
+    return grub_errno;
7e98da0
+
7e98da0
+  grub_env_set (*args, new);
7e98da0
+  grub_free (new);
7e98da0
+
7e98da0
+  return GRUB_ERR_NONE;
7e98da0
+}
7e98da0
+
7e98da0
+static grub_err_t
7e98da0
+grub_cmd_incr(struct grub_command *cmd UNUSED,
7e98da0
+              int argc, char **args)
7e98da0
+{
7e98da0
+  return incr_decr(INCREMENT, argc, args);
7e98da0
+}
7e98da0
+
7e98da0
+static grub_err_t
7e98da0
+grub_cmd_decr(struct grub_command *cmd UNUSED,
7e98da0
+              int argc, char **args)
7e98da0
+{
7e98da0
+  return incr_decr(DECREMENT, argc, args);
7e98da0
+}
7e98da0
+
7e98da0
+static grub_command_t cmd_incr, cmd_decr;
7e98da0
+
7e98da0
+GRUB_MOD_INIT(increment)
7e98da0
+{
7e98da0
+  cmd_incr = grub_register_command ("increment", grub_cmd_incr, N_("VARIABLE"),
7e98da0
+                                    N_("increment VARIABLE"));
7e98da0
+  cmd_decr = grub_register_command ("decrement", grub_cmd_decr, N_("VARIABLE"),
7e98da0
+                                    N_("decrement VARIABLE"));
7e98da0
+}
7e98da0
+
7e98da0
+GRUB_MOD_FINI(increment)
7e98da0
+{
7e98da0
+  grub_unregister_command (cmd_incr);
7e98da0
+  grub_unregister_command (cmd_decr);
7e98da0
+}
7e98da0
diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/01_fallback_counting.in
7e98da0
new file mode 100644
e622855
index 0000000000..be0e770ea8
7e98da0
--- /dev/null
7e98da0
+++ b/util/grub.d/01_fallback_counting.in
7e98da0
@@ -0,0 +1,22 @@
7e98da0
+#! /bin/sh -e
7e98da0
+
7e98da0
+# Boot Counting
7e98da0
+# The boot_counter env var can be used to count down boot attempts after an
7e98da0
+# OSTree upgrade and choose the rollback deployment when 0 is reached.  Both
7e98da0
+# boot_counter and boot_success need to be (re-)set from userspace.
7e98da0
+cat << EOF
7e98da0
+insmod increment
7e98da0
+# Check if boot_counter exists and boot_success=0 to activate this behaviour.
7e98da0
+if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then
7e98da0
+  # if countdown has ended, choose to boot rollback deployment (default=1 on
7e98da0
+  # OSTree-based systems)
7e98da0
+  if  [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then
7e98da0
+    set default=1
7e98da0
+    set boot_counter=-1
7e98da0
+  # otherwise decrement boot_counter
7e98da0
+  else
7e98da0
+    decrement boot_counter
7e98da0
+  fi
7e98da0
+  save_env boot_counter
7e98da0
+fi
7e98da0
+EOF