359 lines
10 KiB
Diff
359 lines
10 KiB
Diff
From e760841d961fc46c5f7a82830d2e0eb6d4b53e8d Mon Sep 17 00:00:00 2001
|
|
From: Colin Watson <cjwatson@ubuntu.com>
|
|
Date: Mon, 13 Jan 2014 12:13:28 +0000
|
|
Subject: Add configure option to bypass boot menu if possible
|
|
|
|
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>
|
|
Author: Robie Basak <robie.basak@ubuntu.com>
|
|
Forwarded: no
|
|
Last-Update: 2015-09-04
|
|
|
|
Patch-Name: quick-boot.patch
|
|
---
|
|
configure.ac | 11 ++++++
|
|
docs/grub.texi | 14 +++++++
|
|
grub-core/normal/menu.c | 24 ++++++++++++
|
|
util/grub-mkconfig.in | 3 +-
|
|
util/grub.d/00_header.in | 77 +++++++++++++++++++++++++++++++------
|
|
util/grub.d/10_linux.in | 4 ++
|
|
util/grub.d/30_os-prober.in | 21 ++++++++++
|
|
7 files changed, 141 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 256fc44ef..c42e4c784 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -1926,6 +1926,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])
|
|
diff --git a/docs/grub.texi b/docs/grub.texi
|
|
index f8b4b3b21..0b58dafb2 100644
|
|
--- a/docs/grub.texi
|
|
+++ b/docs/grub.texi
|
|
@@ -1563,6 +1563,20 @@ 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. A
|
|
+setting of -1 causes GRUB to wait for user input indefinitely. However, a
|
|
+false positive in the recordfail mechanism may occur if power is lost during
|
|
+boot before boot success is recorded in userspace. The default setting is
|
|
+30, which causes GRUB to wait for user input for thirty seconds before
|
|
+continuing. This default allows interactive users the opportunity to switch
|
|
+to a different, working kernel, while avoiding a false positive causing the
|
|
+boot to block indefinitely 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
|
|
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
|
|
index e9d8444b5..0440340b8 100644
|
|
--- a/grub-core/normal/menu.c
|
|
+++ b/grub-core/normal/menu.c
|
|
@@ -603,6 +603,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 ();
|
|
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
|
|
index 0265a5a66..fa9c53a92 100644
|
|
--- a/util/grub-mkconfig.in
|
|
+++ b/util/grub-mkconfig.in
|
|
@@ -256,7 +256,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"
|
|
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
|
|
index 93a90233e..674a76140 100644
|
|
--- a/util/grub.d/00_header.in
|
|
+++ b/util/grub.d/00_header.in
|
|
@@ -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,50 @@ function savedefault {
|
|
save_env saved_entry
|
|
fi
|
|
}
|
|
+EOF
|
|
+
|
|
+if [ "$quick_boot" = 1 ]; then
|
|
+ cat <<EOF
|
|
+function recordfail {
|
|
+ set recordfail=1
|
|
+EOF
|
|
+
|
|
+ check_writable () {
|
|
+ abstractions="$(grub-probe --target=abstraction "${grubdir}")"
|
|
+ for abstraction in $abstractions; do
|
|
+ case "$abstraction" in
|
|
+ diskfilter | lvm)
|
|
+ cat <<EOF
|
|
+ # GRUB lacks write support for $abstraction, so recordfail support is disabled.
|
|
+EOF
|
|
+ return
|
|
+ ;;
|
|
+ esac
|
|
+ done
|
|
+
|
|
+ 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
|
|
+ return
|
|
+ ;;
|
|
+ esac
|
|
+
|
|
+ cat <<EOF
|
|
+ if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi
|
|
+EOF
|
|
+ }
|
|
+
|
|
+ check_writable
|
|
|
|
+ cat <<EOF
|
|
+}
|
|
+EOF
|
|
+fi
|
|
+
|
|
+cat <<EOF
|
|
function load_video {
|
|
EOF
|
|
if [ -n "${GRUB_VIDEO_BACKEND}" ]; then
|
|
@@ -282,10 +328,16 @@ fi
|
|
|
|
make_timeout ()
|
|
{
|
|
+ cat << EOF
|
|
+if [ "\${recordfail}" = 1 ] ; then
|
|
+ set timeout=${GRUB_RECORDFAIL_TIMEOUT:-30}
|
|
+else
|
|
+EOF
|
|
if [ "x${3}" != "x" ] ; then
|
|
timeout="${2}"
|
|
style="${3}"
|
|
- elif [ "x${1}" != "x" ] && [ "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 +356,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
|
|
}
|
|
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
|
|
index 869a7eec5..80315a31b 100644
|
|
--- a/util/grub.d/10_linux.in
|
|
+++ b/util/grub.d/10_linux.in
|
|
@@ -22,6 +22,7 @@ exec_prefix="@exec_prefix@"
|
|
datarootdir="@datarootdir@"
|
|
ubuntu_recovery="@UBUNTU_RECOVERY@"
|
|
quiet_boot="@QUIET_BOOT@"
|
|
+quick_boot="@QUICK_BOOT@"
|
|
|
|
. "$pkgdatadir/grub-mkconfig_lib"
|
|
|
|
@@ -129,6 +130,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
|
|
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
|
|
index 98aee403e..225a3baf7 100644
|
|
--- a/util/grub.d/30_os-prober.in
|
|
+++ b/util/grub.d/30_os-prober.in
|
|
@@ -20,12 +20,26 @@ set -e
|
|
prefix="@prefix@"
|
|
exec_prefix="@exec_prefix@"
|
|
datarootdir="@datarootdir@"
|
|
+quick_boot="@QUICK_BOOT@"
|
|
|
|
export TEXTDOMAIN=@PACKAGE@
|
|
export TEXTDOMAINDIR="@localedir@"
|
|
|
|
. "$pkgdatadir/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
|
|
grub_warn "$(gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.")"
|
|
exit 0
|
|
@@ -45,6 +59,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)")"
|
|
@@ -168,6 +183,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 --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' {
|
|
@@ -198,6 +214,7 @@ EOF
|
|
;;
|
|
efi)
|
|
|
|
+ found_other_os=1
|
|
EFIPATH=${DEVICE#*@}
|
|
DEVICE=${DEVICE%@*}
|
|
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
|
|
@@ -246,6 +263,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
|
|
@@ -322,6 +340,7 @@ EOF
|
|
fi
|
|
;;
|
|
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}")' {
|
|
@@ -364,3 +383,5 @@ EOF
|
|
;;
|
|
esac
|
|
done
|
|
+
|
|
+adjust_timeout
|