mirror of
https://git.proxmox.com/git/grub2
synced 2025-10-20 20:18:18 +00:00
The overflow was in fact impossible in practice because the int parameter is only ever 0, 1, or 2, but GCC couldn't prove that.
359 lines
10 KiB
Diff
359 lines
10 KiB
Diff
From 82480176b8b1404acb7aec08d108cb7517d4fb23 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 dd2fbd01c..e508f9c43 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -1841,6 +1841,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 e935af33e..5b2a7bbb2 100644
|
|
--- a/docs/grub.texi
|
|
+++ b/docs/grub.texi
|
|
@@ -1490,6 +1490,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 1f3447ad3..906a480a2 100644
|
|
--- a/grub-core/normal/menu.c
|
|
+++ b/grub-core/normal/menu.c
|
|
@@ -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 ();
|
|
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
|
|
index b4f0011b5..fac560464 100644
|
|
--- a/util/grub-mkconfig.in
|
|
+++ b/util/grub-mkconfig.in
|
|
@@ -239,7 +239,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 67d57ecfd..0f8a16837 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"
|
|
|
|
@@ -119,6 +120,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 271044f59..da5f28876 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
|
|
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)")"
|
|
@@ -165,6 +180,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}")' {
|
|
@@ -195,6 +211,7 @@ EOF
|
|
;;
|
|
efi)
|
|
|
|
+ found_other_os=1
|
|
EFIPATH=${DEVICE#*@}
|
|
DEVICE=${DEVICE%@*}
|
|
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
|
|
@@ -243,6 +260,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
|
|
@@ -311,6 +329,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}")' {
|
|
@@ -353,3 +372,5 @@ EOF
|
|
;;
|
|
esac
|
|
done
|
|
+
|
|
+adjust_timeout
|