]> git.proxmox.com Git - grub2.git/commitdiff
Add configure option to bypass boot menu if possible
authorColin Watson <cjwatson@ubuntu.com>
Mon, 13 Jan 2014 12:13:28 +0000 (12:13 +0000)
committerColin Watson <cjwatson@debian.org>
Mon, 31 Mar 2014 14:18:13 +0000 (15:18 +0100)
If other operating systems are installed, then automatically unhide the
menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus if
available to check whether Shift is pressed.  If it is, show the menu,
otherwise boot immediately.  If keystatus is not available, then fall
back to a short delay interruptible with Escape.

This may or may not remain Ubuntu-specific, although it's not obviously
wanted upstream.  It implements a requirement of
https://wiki.ubuntu.com/DesktopExperienceTeam/KarmicBootExperienceDesignSpec#Bootloader.

If the previous boot failed (defined as failing to get to the end of one
of the normal runlevels), then show the boot menu regardless.

Author: Richard Laager <rlaager@wiktel.com>
Forwarded: no
Last-Update: 2014-01-17

Patch-Name: quick_boot.patch

configure.ac
docs/grub.texi
grub-core/normal/menu.c
util/grub-mkconfig.in
util/grub.d/00_header.in
util/grub.d/10_linux.in
util/grub.d/30_os-prober.in

index 7c8d0afd7bd40dd83d684e125d079e145cf12caf..2a7e410f99c125daabdbb6b7318e568abc71e6b3 100644 (file)
@@ -1594,6 +1594,17 @@ else
 fi
 AC_SUBST([QUIET_BOOT])
 
+AC_ARG_ENABLE([quick-boot],
+              [AS_HELP_STRING([--enable-quick-boot],
+                              [bypass boot menu if possible (default=no)])],
+              [], [enable_quick_boot=no])
+if test x"$enable_quick_boot" = xyes ; then
+  QUICK_BOOT=1
+else
+  QUICK_BOOT=0
+fi
+AC_SUBST([QUICK_BOOT])
+
 LIBS=""
 
 AC_SUBST([FONT_SOURCE])
index 46b9e7f8e3198c9f40375f22d2874336498dd14a..28743d5a03a315355556d7b7be80c2a278bbb95c 100644 (file)
@@ -1490,6 +1490,15 @@ This option may be set to a list of GRUB module names separated by spaces.
 Each module will be loaded as early as possible, at the start of
 @file{grub.cfg}.
 
+@item GRUB_RECORDFAIL_TIMEOUT
+If this option is set, it overrides the default recordfail setting. The
+default setting is -1, which causes GRUB to wait for user input. This option
+should be set on headless and appliance systems where access to a console is
+restricted or limited.
+
+This option is only effective when GRUB was configured with the
+@option{--enable-quick-boot} option.
+
 @end table
 
 The following options are still accepted for compatibility with existing
index 7b55c277b75fb3540cb0ee3c1f9879e303621ac6..a968e0f0049b643dcea986d5e32de407fdf46194 100644 (file)
@@ -604,6 +604,30 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
       static struct grub_term_coordinate *pos;
       int entry = -1;
 
+      if (timeout == 0)
+       {
+         /* If modifier key statuses can't be detected without a delay,
+            then a hidden timeout of zero cannot be interrupted in any way,
+            which is not very helpful.  Bump it to three seconds in this
+            case to give the user a fighting chance.  */
+         grub_term_input_t term;
+         int nterms = 0;
+         int mods_detectable = 1;
+
+         FOR_ACTIVE_TERM_INPUTS(term)
+         {
+           if (!term->getkeystatus)
+             {
+               mods_detectable = 0;
+               break;
+             }
+           else
+             nterms++;
+         }
+         if (!mods_detectable || !nterms)
+           timeout = 3;
+       }
+
       if (timeout_style == TIMEOUT_STYLE_COUNTDOWN && timeout)
        {
          pos = grub_term_save_pos ();
index 62780bf8430ddf1f5adfb4b1a8926c1a8e439fdd..17350d47c0d77f981132f7f403886b0b85fc174c 100644 (file)
@@ -236,7 +236,8 @@ export GRUB_DEFAULT \
   GRUB_ENABLE_CRYPTODISK \
   GRUB_BADRAM \
   GRUB_OS_PROBER_SKIP_LIST \
-  GRUB_DISABLE_SUBMENU
+  GRUB_DISABLE_SUBMENU \
+  GRUB_RECORDFAIL_TIMEOUT
 
 if test "x${grub_cfg}" != "x"; then
   rm -f "${grub_cfg}.new"
index 0c82f231574fafa4ebb3e7205095424a66050fdc..8dc55921f1652ddc1567462d54542a37bea612f4 100644 (file)
@@ -21,6 +21,8 @@ prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
 grub_lang=`echo $LANG | cut -d . -f 1`
+grubdir="`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`"
+quick_boot="@QUICK_BOOT@"
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
@@ -44,6 +46,7 @@ if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT
 
 cat << EOF
 if [ -s \$prefix/grubenv ]; then
+  set have_grubenv=true
   load_env
 fi
 EOF
@@ -96,7 +99,31 @@ function savedefault {
     save_env saved_entry
   fi
 }
+EOF
 
+if [ "$quick_boot" = 1 ]; then
+    cat <<EOF
+function recordfail {
+  set recordfail=1
+EOF
+    FS="$(grub-probe --target=fs "${grubdir}")"
+    case "$FS" in
+      btrfs | cpiofs | newc | odc | romfs | squash4 | tarfs | zfs)
+       cat <<EOF
+  # GRUB lacks write support for $FS, so recordfail support is disabled.
+EOF
+       ;;
+      *)
+       cat <<EOF
+  if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi
+EOF
+    esac
+    cat <<EOF
+}
+EOF
+fi
+
+cat <<EOF
 function load_video {
 EOF
 if [ -n "${GRUB_VIDEO_BACKEND}" ]; then
@@ -282,10 +309,16 @@ fi
 
 make_timeout ()
 {
+    cat << EOF
+if [ "\${recordfail}" = 1 ] ; then
+  set timeout=${GRUB_RECORDFAIL_TIMEOUT:--1}
+else
+EOF
     if [ "x${3}" != "x" ] ; then
        timeout="${2}"
        style="${3}"
-    elif [ "x${1}" != "x" -a "x${1}" != "x0" ] ; then
+    elif [ "x${1}" != "x" ] && \
+        ([ "$quick_boot" = 1 ] || [ "x${1}" != "x0" ]) ; then
        # Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme.
        timeout="${1}"
        if [ "x${2}" != "x0" ] ; then
@@ -304,26 +337,27 @@ make_timeout ()
        style="menu"
     fi
     cat << EOF
-if [ x\$feature_timeout_style = xy ] ; then
-  set timeout_style=${style}
-  set timeout=${timeout}
+  if [ x\$feature_timeout_style = xy ] ; then
+    set timeout_style=${style}
+    set timeout=${timeout}
 EOF
     if [ "x${style}" = "xmenu" ] ; then
        cat << EOF
-# Fallback normal timeout code in case the timeout_style feature is
-# unavailable.
-else
-  set timeout=${timeout}
+  # Fallback normal timeout code in case the timeout_style feature is
+  # unavailable.
+  else
+    set timeout=${timeout}
 EOF
     else
        cat << EOF
-# Fallback hidden-timeout code in case the timeout_style feature is
-# unavailable.
-elif sleep${verbose} --interruptible ${timeout} ; then
-  set timeout=0
+  # Fallback hidden-timeout code in case the timeout_style feature is
+  # unavailable.
+  elif sleep${verbose} --interruptible ${timeout} ; then
+    set timeout=0
 EOF
     fi
     cat << EOF
+  fi
 fi
 EOF
 }
index 0616c6d5dc565898a163d14d027912f41905d29a..aa2c369907a3da014bd4f0848bb7c7732d8019ca 100644 (file)
@@ -22,6 +22,7 @@ exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
 ubuntu_recovery="@UBUNTU_RECOVERY@"
 quiet_boot="@QUIET_BOOT@"
+quick_boot="@QUICK_BOOT@"
 
 . "@datadir@/@PACKAGE@/grub-mkconfig_lib"
 
@@ -117,6 +118,9 @@ linux_entry ()
   else
       echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
   fi      
+  if [ "$quick_boot" = 1 ]; then
+      echo "   recordfail" | sed "s/^/$submenu_indentation/"
+  fi
   if [ x$type != xrecovery ] ; then
       save_default_entry | grub_add_tab
   fi
index 1c44cf27878a07175ccc2011b155de98d1f70206..1106ad1849a160b2be489ba935bf6ce93691cbea 100644 (file)
@@ -20,12 +20,26 @@ set -e
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
+quick_boot="@QUICK_BOOT@"
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
 
 . "@datadir@/@PACKAGE@/grub-mkconfig_lib"
 
+found_other_os=
+
+adjust_timeout () {
+  if [ "$quick_boot" = 1 ] && [ "x${found_other_os}" != "x" ]; then
+    cat << EOF
+set timeout_style=menu
+if [ "\${timeout}" = 0 ]; then
+  set timeout=10
+fi
+EOF
+  fi
+}
+
 if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
   exit 0
 fi
@@ -42,6 +56,7 @@ if [ -z "${OSPROBED}" ] ; then
 fi
 
 osx_entry() {
+    found_other_os=1
     if [ x$2 = x32 ]; then
         # TRANSLATORS: it refers to kernel architecture (32-bit)
        bitstr="$(gettext "(32-bit)")"
@@ -158,6 +173,7 @@ for OS in ${OSPROBED} ; do
          ;;
       esac
 
+      found_other_os=1
          onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
       cat << EOF
 menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' {
@@ -188,6 +204,7 @@ EOF
     ;;
     efi)
 
+       found_other_os=1
        EFIPATH=${DEVICE#*@}
        DEVICE=${DEVICE%@*}
        onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
@@ -236,6 +253,7 @@ EOF
          [ "${prepare_boot_cache}" ] || continue
        fi
 
+       found_other_os=1
        onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
        recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true
        counter=1
@@ -302,6 +320,7 @@ EOF
       osx_entry xnu_kernel64 64
     ;;
     hurd)
+      found_other_os=1
       onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
       cat << EOF
 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}")' {
@@ -345,3 +364,5 @@ EOF
     ;;
   esac
 done
+
+adjust_timeout