db4a99
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
db4a99
From: Peter Jones <pjones@redhat.com>
db4a99
Date: Thu, 4 Oct 2018 14:22:09 -0400
db4a99
Subject: [PATCH] Reimplement boot_counter
db4a99
db4a99
This adds "increment" and "decrement" commands, and uses them to maintain our
db4a99
variables in 01_fallback_counter.  It also simplifies the counter logic, so
db4a99
that there are no nested tests that conflict with each other.
db4a99
db4a99
Apparently, this *really* wasn't tested well enough.
db4a99
db4a99
Resolves: rhbz#1614637
db4a99
Signed-off-by: Peter Jones <pjones@redhat.com>
db4a99
---
db4a99
 Makefile.util.def                   |   6 +++
db4a99
 grub-core/Makefile.core.def         |   5 ++
db4a99
 grub-core/commands/increment.c      | 105 ++++++++++++++++++++++++++++++++++++
db4a99
 util/grub.d/01_fallback_counting.in |  15 ++++++
db4a99
 4 files changed, 131 insertions(+)
db4a99
 create mode 100644 grub-core/commands/increment.c
db4a99
 create mode 100644 util/grub.d/01_fallback_counting.in
db4a99
db4a99
diff --git a/Makefile.util.def b/Makefile.util.def
db4a99
index cba4d500198..c8cb91308d9 100644
db4a99
--- a/Makefile.util.def
db4a99
+++ b/Makefile.util.def
db4a99
@@ -448,6 +448,12 @@ script = {
db4a99
   installdir = grubconf;
db4a99
 };
db4a99
 
db4a99
+script = {
db4a99
+  name = '01_fallback_counting';
db4a99
+  common = util/grub.d/01_fallback_counting.in;
db4a99
+  installdir = grubconf;
db4a99
+};
db4a99
+
db4a99
 script = {
db4a99
   name = '01_menu_auto_hide';
db4a99
   common = util/grub.d/01_menu_auto_hide.in;
db4a99
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
db4a99
index 30c2ac8f3c8..826e27af900 100644
db4a99
--- a/grub-core/Makefile.core.def
db4a99
+++ b/grub-core/Makefile.core.def
db4a99
@@ -362,6 +362,11 @@ kernel = {
db4a99
   extra_dist = kern/mips/cache_flush.S;
db4a99
 };
db4a99
 
db4a99
+module = {
db4a99
+  name = increment;
db4a99
+  common = commands/increment.c;
db4a99
+};
db4a99
+
db4a99
 program = {
db4a99
   name = grub-emu;
db4a99
   mansection = 1;
db4a99
diff --git a/grub-core/commands/increment.c b/grub-core/commands/increment.c
db4a99
new file mode 100644
db4a99
index 00000000000..79cf137656c
db4a99
--- /dev/null
db4a99
+++ b/grub-core/commands/increment.c
db4a99
@@ -0,0 +1,105 @@
db4a99
+/* increment.c - Commands to increment and decrement variables. */
db4a99
+/*
db4a99
+ *  GRUB  --  GRand Unified Bootloader
db4a99
+ *  Copyright (C) 2006,2007,2008  Free Software Foundation, Inc.
db4a99
+ *
db4a99
+ *  GRUB is free software: you can redistribute it and/or modify
db4a99
+ *  it under the terms of the GNU General Public License as published by
db4a99
+ *  the Free Software Foundation, either version 3 of the License, or
db4a99
+ *  (at your option) any later version.
db4a99
+ *
db4a99
+ *  GRUB is distributed in the hope that it will be useful,
db4a99
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
db4a99
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
db4a99
+ *  GNU General Public License for more details.
db4a99
+ *
db4a99
+ *  You should have received a copy of the GNU General Public License
db4a99
+ *  along with GRUB.  If not, see <http: www.gnu.org="" licenses=""/>.
db4a99
+ */
db4a99
+
db4a99
+#include <grub dl.h="">
db4a99
+#include <grub term.h="">
db4a99
+#include <grub time.h="">
db4a99
+#include <grub types.h="">
db4a99
+#include <grub misc.h="">
db4a99
+#include <grub extcmd.h="">
db4a99
+#include <grub i18n.h="">
db4a99
+#include <grub env.h="">
db4a99
+
db4a99
+GRUB_MOD_LICENSE ("GPLv3+");
db4a99
+
db4a99
+typedef enum {
db4a99
+    INCREMENT,
db4a99
+    DECREMENT,
db4a99
+} operation;
db4a99
+
db4a99
+static grub_err_t
db4a99
+incr_decr(operation op, int argc, char **args)
db4a99
+{
db4a99
+  const char *old;
db4a99
+  char *new;
db4a99
+  long value;
db4a99
+
db4a99
+  if (argc < 1)
db4a99
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no variable specified"));
db4a99
+  if (argc > 1)
db4a99
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("too many arguments"));
db4a99
+
db4a99
+  old = grub_env_get (*args);
db4a99
+  if (!old)
db4a99
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("No such variable \"%s\""),
db4a99
+		       *args);
db4a99
+
db4a99
+  value = grub_strtol (old, NULL, 0);
db4a99
+  if (grub_errno != GRUB_ERR_NONE)
db4a99
+    return grub_errno;
db4a99
+
db4a99
+  switch (op)
db4a99
+    {
db4a99
+    case INCREMENT:
db4a99
+      value += 1;
db4a99
+      break;
db4a99
+    case DECREMENT:
db4a99
+      value -= 1;
db4a99
+      break;
db4a99
+    }
db4a99
+
db4a99
+  new = grub_xasprintf ("%ld", value);
db4a99
+  if (!new)
db4a99
+    return grub_errno;
db4a99
+
db4a99
+  grub_env_set (*args, new);
db4a99
+  grub_free (new);
db4a99
+
db4a99
+  return GRUB_ERR_NONE;
db4a99
+}
db4a99
+
db4a99
+static grub_err_t
db4a99
+grub_cmd_incr(struct grub_command *cmd UNUSED,
db4a99
+              int argc, char **args)
db4a99
+{
db4a99
+  return incr_decr(INCREMENT, argc, args);
db4a99
+}
db4a99
+
db4a99
+static grub_err_t
db4a99
+grub_cmd_decr(struct grub_command *cmd UNUSED,
db4a99
+              int argc, char **args)
db4a99
+{
db4a99
+  return incr_decr(DECREMENT, argc, args);
db4a99
+}
db4a99
+
db4a99
+static grub_command_t cmd_incr, cmd_decr;
db4a99
+
db4a99
+GRUB_MOD_INIT(increment)
db4a99
+{
db4a99
+  cmd_incr = grub_register_command ("increment", grub_cmd_incr, N_("VARIABLE"),
db4a99
+                                    N_("increment VARIABLE"));
db4a99
+  cmd_decr = grub_register_command ("decrement", grub_cmd_decr, N_("VARIABLE"),
db4a99
+                                    N_("decrement VARIABLE"));
db4a99
+}
db4a99
+
db4a99
+GRUB_MOD_FINI(increment)
db4a99
+{
db4a99
+  grub_unregister_command (cmd_incr);
db4a99
+  grub_unregister_command (cmd_decr);
db4a99
+}
db4a99
diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/01_fallback_counting.in
db4a99
new file mode 100644
db4a99
index 00000000000..6ca13da03df
db4a99
--- /dev/null
db4a99
+++ b/util/grub.d/01_fallback_counting.in
db4a99
@@ -0,0 +1,15 @@
db4a99
+#! /bin/sh -e
db4a99
+
db4a99
+# Boot Counting
db4a99
+cat << EOF
db4a99
+insmod increment
db4a99
+if [ -z "\${boot_counter}" ]; then
db4a99
+  set boot_counter=0
db4a99
+elif [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then
db4a99
+  increment default
db4a99
+  set boot_counter=-1
db4a99
+else
db4a99
+  decrement boot_counter
db4a99
+fi
db4a99
+save_env boot_counter
db4a99
+EOF