nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone
d9d99f
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
d9d99f
From: Hans de Goede <hdegoede@redhat.com>
d9d99f
Date: Wed, 6 Jun 2018 08:44:11 +0200
d9d99f
Subject: [PATCH] Add auto-hide menu support
d9d99f
d9d99f
On single-os systems we do not want to show the menu, unless something
d9d99f
went wrong with the previous boot, in which case the user may need the
d9d99f
menu to debug/fix the problem.
d9d99f
d9d99f
This commit adds a new grub.d/00_menu_auto_hide file which emits a
d9d99f
config snippet implementing this. I've chosen to do this in a separate
d9d99f
grub.d file because chances of this going upstream are small and this way
d9d99f
it will be easier to rebase.
d9d99f
d9d99f
Since auto-hiding the menu requires detecting the previous boot was ok,
d9d99f
we get fastboot support (where we don't check for a key at all) for free
d9d99f
so this commit also adds support for this.
d9d99f
d9d99f
The new config-file code uses the following variables:
d9d99f
d9d99f
menu_auto_hide     Set this to "1" to activate the new auto-hide feature
d9d99f
                   Set this to "2" to auto-hide the menu even when multiple
d9d99f
                   operating systems are installed. Note the menu will still
d9d99f
                   auto show after booting an other os as that won't set
d9d99f
                   boot_success.
d9d99f
menu_show_once     Set this to "1" to force showing the menu once.
d9d99f
boot_success       The OS sets this to "1" to indicate a successful boot.
d9d99f
boot_indeterminate The OS increments this integer when rebooting after e.g.
d9d99f
                   installing updates or a selinux relabel.
d9d99f
fastboot           If set to "1" and the conditions for auto-hiding the menu
d9d99f
                   are met, the menu is not shown and all checks for keypresses
d9d99f
                   are skipped, booting the default immediately.
d9d99f
d9d99f
30_os-prober.in changes somewhat inspired by:
d9d99f
https://git.launchpad.net/~ubuntu-core-dev/grub/+git/ubuntu/tree/debian/patches/quick_boot.patch
d9d99f
d9d99f
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
d9d99f
---
d9d99f
Changes in v2:
d9d99f
-Drop shutdown_success tests, there is no meaningful way for systemd to set
d9d99f
 this flag (by the time it knows all filesystems are unmounted or read-only
d9d99f
-Drop fwsetup_once support, systemd already supports booting directly into
d9d99f
 the fwsetup by doing "systemctl reboot --firmware"
d9d99f
---
d9d99f
 Makefile.util.def                |  6 +++++
d9d99f
 util/grub.d/00_menu_auto_hide.in | 50 ++++++++++++++++++++++++++++++++++++++++
d9d99f
 util/grub.d/30_os-prober.in      | 18 +++++++++++++++
d9d99f
 3 files changed, 74 insertions(+)
d9d99f
 create mode 100644 util/grub.d/00_menu_auto_hide.in
d9d99f
d9d99f
diff --git a/Makefile.util.def b/Makefile.util.def
b71686
index cbd661d63..0fdfdd91f 100644
d9d99f
--- a/Makefile.util.def
d9d99f
+++ b/Makefile.util.def
d9d99f
@@ -448,6 +448,12 @@ script = {
d9d99f
   installdir = grubconf;
d9d99f
 };
d9d99f
 
d9d99f
+script = {
d9d99f
+  name = '00_menu_auto_hide';
d9d99f
+  common = util/grub.d/00_menu_auto_hide.in;
d9d99f
+  installdir = grubconf;
d9d99f
+};
d9d99f
+
d9d99f
 script = {
d9d99f
   name = '01_users';
d9d99f
   common = util/grub.d/01_users.in;
d9d99f
diff --git a/util/grub.d/00_menu_auto_hide.in b/util/grub.d/00_menu_auto_hide.in
d9d99f
new file mode 100644
b71686
index 000000000..a10fe45bb
d9d99f
--- /dev/null
d9d99f
+++ b/util/grub.d/00_menu_auto_hide.in
d9d99f
@@ -0,0 +1,50 @@
d9d99f
+#! /bin/sh
d9d99f
+
d9d99f
+# Disable / skip generating menu-auto-hide config parts on serial terminals
d9d99f
+for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do
d9d99f
+  case "$x" in
d9d99f
+    serial*)
d9d99f
+      exit 0
d9d99f
+      ;;
d9d99f
+  esac
d9d99f
+done
d9d99f
+
d9d99f
+cat << EOF
d9d99f
+if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then
d9d99f
+  set last_boot_ok=1
d9d99f
+else
d9d99f
+  set last_boot_ok=0
d9d99f
+fi
d9d99f
+
d9d99f
+# Reset boot_indeterminate after a successful boot
d9d99f
+if [ "\${boot_success}" = "1" ] ; then
d9d99f
+  set boot_indeterminate=0
d9d99f
+  save_env boot_indeterminate
d9d99f
+# Avoid boot_indeterminate causing the menu to be hidden more then once
d9d99f
+elif [ "\${boot_indeterminate}" = "1" ]; then
d9d99f
+  set boot_indeterminate=2
d9d99f
+  save_env boot_indeterminate
d9d99f
+fi
d9d99f
+set boot_success=0
d9d99f
+save_env boot_success
d9d99f
+
d9d99f
+if [ x\$feature_timeout_style = xy ] ; then
d9d99f
+  if [ "\${menu_show_once}" ]; then
d9d99f
+    unset menu_show_once
d9d99f
+    save_env menu_show_once
d9d99f
+    set timeout_style=menu
d9d99f
+    unset timeout
d9d99f
+  elif [ "\${menu_auto_hide}" -a "\${last_boot_ok}" = "1" ]; then
d9d99f
+    set orig_timeout_style=\${timeout_style}
d9d99f
+    set orig_timeout=\${timeout}
d9d99f
+    if [ "\${fastboot}" = "1" ]; then
d9d99f
+      # timeout_style=menu + timeout=0 avoids the countdown code keypress check
d9d99f
+      set timeout_style=menu
d9d99f
+      set timeout=0
d9d99f
+    else
d9d99f
+      set timeout_style=hidden
d9d99f
+      set timeout=1
d9d99f
+    fi
d9d99f
+  fi
d9d99f
+fi
d9d99f
+EOF
d9d99f
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
b71686
index 13a3a6bc7..ab634393a 100644
d9d99f
--- a/util/grub.d/30_os-prober.in
d9d99f
+++ b/util/grub.d/30_os-prober.in
d9d99f
@@ -42,6 +42,7 @@ if [ -z "${OSPROBED}" ] ; then
d9d99f
 fi
d9d99f
 
d9d99f
 osx_entry() {
d9d99f
+    found_other_os=1
d9d99f
     # TRANSLATORS: it refers on the OS residing on device %s
d9d99f
     onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
d9d99f
     hints=""
d9d99f
@@ -102,6 +103,7 @@ for OS in ${OSPROBED} ; do
d9d99f
 
d9d99f
   case ${BOOT} in
d9d99f
     chain)
d9d99f
+      found_other_os=1
d9d99f
 
d9d99f
 	  onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
d9d99f
       cat << EOF
d9d99f
@@ -132,6 +134,7 @@ EOF
d9d99f
 EOF
d9d99f
     ;;
d9d99f
     efi)
d9d99f
+      found_other_os=1
d9d99f
 
d9d99f
 	EFIPATH=${DEVICE#*@}
d9d99f
 	DEVICE=${DEVICE%@*}
d9d99f
@@ -176,6 +179,7 @@ EOF
d9d99f
 	  LINITRD="${LINITRD#/boot}"
d9d99f
 	fi
d9d99f
 
d9d99f
+        found_other_os=1
d9d99f
 	onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
d9d99f
 	recovery_params="$(echo "${LPARAMS}" | grep single)" || true
d9d99f
 	counter=1
d9d99f
@@ -249,6 +253,7 @@ EOF
d9d99f
       done
d9d99f
     ;;
d9d99f
     hurd)
d9d99f
+      found_other_os=1
d9d99f
       onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
d9d99f
       cat << EOF
d9d99f
 menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' {
d9d99f
@@ -275,6 +280,7 @@ EOF
d9d99f
 EOF
d9d99f
     ;;
d9d99f
     minix)
d9d99f
+      found_other_os=1
d9d99f
 	  cat << EOF
d9d99f
 menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" {
d9d99f
 EOF
d9d99f
@@ -306,3 +312,15 @@ EOF
d9d99f
       esac
d9d99f
   esac
d9d99f
 done
d9d99f
+
d9d99f
+# We override the results of the menu_auto_hide code here, this is a bit ugly,
d9d99f
+# but grub-mkconfig writes out the file linearly, so this is the only way
d9d99f
+if [ "${found_other_os}" = "1" ]; then
d9d99f
+  cat << EOF
d9d99f
+# Other OS found, undo autohiding of menu unless menu_auto_hide=2
d9d99f
+if [ "\${orig_timeout_style}" -a "\${menu_auto_hide}" != "2" ]; then
d9d99f
+  set timeout_style=\${orig_timeout_style}
d9d99f
+  set timeout=\${orig_timeout}
d9d99f
+fi
d9d99f
+EOF
d9d99f
+fi