grub2/0095-Add-BLS-support-to-grub-mkconfig.patch
Javier Martinez Canillas e1531466e1
Update to grub 2.04
This change updates grub to the 2.04 release. The new release changed how
grub is built, so the bootstrap and bootstrap.conf files have to be added
to the dist-git. Also, the gitignore file changed so it has to be updated.

Since the patches have been forward ported to 2.04, there's no need for a
logic to maintain a patch with the delta between the release and the grub
master branch. So the release-to-master.patch is dropped and no longer is
updated by the do-rebase script.

Also since gnulib isn't part of the grub repository anymore and cloned by
the boostrap tool, a gnulib tarball is included as other source file and
copied before calling the bootstrap tool. That way grub can be built even
in builders that only have access to the sources lookaside cache.

Resolves: rhbz#1727279

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2019-08-15 08:04:53 +02:00

741 lines
24 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 9 Dec 2016 15:40:29 -0500
Subject: [PATCH] Add BLS support to grub-mkconfig
GRUB now has BootLoaderSpec support, the user can choose to use this by
setting GRUB_ENABLE_BLSCFG to true in /etc/default/grub. On this setup,
the boot menu entries are not added to the grub.cfg, instead BLS config
files are parsed by blscfg command and the entries created dynamically.
A 10_linux_bls grub.d snippet to generate menu entries from BLS files
is also added that can be used on platforms where the bootloader doesn't
have BLS support and only can parse a normal grub configuration file.
Portions of the 10_linux_bls were taken from the ostree-grub-generator
script that's included in the OSTree project.
Fixes to support multi-devices and generate a BLS section even if no
kernels are found in the boot directory were proposed by Yclept Nemo
and Tom Gundersen respectively.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
Makefile.util.def | 7 +
util/grub-mkconfig.8 | 4 +
util/grub-mkconfig.in | 9 +-
util/grub-mkconfig_lib.in | 20 +-
util/grub.d/10_linux.in | 67 ++++++-
util/grub.d/10_linux_bls.in | 478 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 580 insertions(+), 5 deletions(-)
create mode 100644 util/grub.d/10_linux_bls.in
diff --git a/Makefile.util.def b/Makefile.util.def
index 2215cc759c0..a61613656d1 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -499,6 +499,13 @@ script = {
condition = COND_HOST_LINUX;
};
+script = {
+ name = '10_linux_bls';
+ common = util/grub.d/10_linux_bls.in;
+ installdir = grubconf;
+ condition = COND_HOST_LINUX;
+};
+
script = {
name = '10_xnu';
common = util/grub.d/10_xnu.in;
diff --git a/util/grub-mkconfig.8 b/util/grub-mkconfig.8
index a2d1f577b9b..434fa4deda4 100644
--- a/util/grub-mkconfig.8
+++ b/util/grub-mkconfig.8
@@ -13,5 +13,9 @@
\fB--output\fR=\fIFILE\fR
Write generated output to \fIFILE\fR.
+.TP
+\fB--no-grubenv-update\fR
+Do not update variables in the grubenv file.
+
.SH SEE ALSO
.BR "info grub"
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 4649e92eb0f..2601bdc0711 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -50,6 +50,8 @@ grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
+export GRUB_GRUBENV_UPDATE="yes"
+
. "${pkgdatadir}/grub-mkconfig_lib"
# Usage: usage
@@ -59,6 +61,7 @@ usage () {
gettext "Generate a grub config file"; echo
echo
print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")"
+ print_option_help "--no-grubenv-update" "$(gettext "do not update variables in the grubenv file")"
print_option_help "-h, --help" "$(gettext "print this message and exit")"
print_option_help "-v, --version" "$(gettext "print the version information and exit")"
echo
@@ -94,6 +97,9 @@ do
--output=*)
grub_cfg=`echo "$option" | sed 's/--output=//'`
;;
+ --no-grubenv-update)
+ GRUB_GRUBENV_UPDATE="no"
+ ;;
-*)
gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
usage
@@ -259,7 +265,8 @@ export GRUB_DEFAULT \
GRUB_OS_PROBER_SKIP_LIST \
GRUB_DISABLE_SUBMENU \
GRUB_DEFAULT_DTB \
- SUSE_BTRFS_SNAPSHOT_BOOTING
+ SUSE_BTRFS_SNAPSHOT_BOOTING \
+ GRUB_ENABLE_BLSCFG
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index b3aae534ddc..bc11df2bd84 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -30,6 +30,9 @@ fi
if test "x$grub_file" = x; then
grub_file="${bindir}/@grub_file@"
fi
+if test "x$grub_editenv" = x; then
+ grub_editenv="${bindir}/@grub_editenv@"
+fi
if test "x$grub_mkrelpath" = x; then
grub_mkrelpath="${bindir}/@grub_mkrelpath@"
fi
@@ -125,8 +128,19 @@ EOF
fi
}
+prepare_grub_to_access_device_with_variable ()
+{
+ device_variable="$1"
+ shift
+ prepare_grub_to_access_device "$@"
+ unset "device_variable"
+}
+
prepare_grub_to_access_device ()
{
+ if [ -z "$device_variable" ]; then
+ device_variable="root"
+ fi
old_ifs="$IFS"
IFS='
'
@@ -161,14 +175,14 @@ prepare_grub_to_access_device ()
# otherwise set root as per value in device.map.
fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`"
if [ "x$fs_hint" != x ]; then
- echo "set root='$fs_hint'"
+ echo "set ${device_variable}='$fs_hint'"
fi
if [ "x$GRUB_DISABLE_UUID" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
echo "if [ x\$feature_platform_search_hint = xy ]; then"
- echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${hints} ${fs_uuid}"
echo "else"
- echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}"
+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}"
echo "fi"
fi
IFS="$old_ifs"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 5cab299dc08..301594a0c9e 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -82,6 +82,67 @@ case x"$GRUB_FS" in
;;
esac
+populate_header_warn()
+{
+cat <<EOF
+
+# This section was generated by a script. Do not modify the generated file - all changes
+# will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files.
+#
+# The blscfg command parses the BootLoaderSpec files stored in /boot/loader/entries and
+# populates the boot menu. Please refer to the Boot Loader Specification documentation
+# for the files format: https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/.
+
+EOF
+}
+
+if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE}
+ fi
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT}
+ fi
+ fi
+
+ if [ -d /sys/firmware/efi ]; then
+ bootefi_device="`${grub_probe} --target=device /boot/efi/`"
+ prepare_grub_to_access_device_with_variable boot ${bootefi_device}
+ else
+ boot_device="`${grub_probe} --target=device /boot/`"
+ prepare_grub_to_access_device_with_variable boot ${boot_device}
+ fi
+
+ populate_header_warn
+
+ cat << EOF
+set default_kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX}"
+
+insmod blscfg
+blscfg
+EOF
+
+ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then
+ blsdir="/boot/loader/entries"
+ [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})"
+ if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then
+ blsdir=$(make_system_path_relative_to_its_root "${blsdir}")
+ if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then
+ ${grub_editenv} - set blsdir="${blsdir}"
+ fi
+ fi
+
+ ${grub_editenv} - set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX}"
+ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
+ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
+ fi
+ fi
+
+ exit 0
+fi
+
mktitle ()
{
local title_type
@@ -121,6 +182,7 @@ linux_entry ()
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
+
if [ x$type != xsimple ] ; then
title=$(mktitle "$type" "$version")
if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
@@ -224,6 +286,7 @@ is_top_level=true
while [ "x$list" != "x" ] ; do
linux=`version_find_latest $list`
gettext_printf "Found linux image: %s\n" "$linux" >&2
+
basename=`basename $linux`
dirname=`dirname $linux`
rel_dirname=`make_system_path_relative_to_its_root $dirname`
@@ -262,7 +325,9 @@ while [ "x$list" != "x" ] ; do
for i in ${initrd}; do
initrd_display="${initrd_display} ${dirname}/${i}"
done
- gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ fi
fi
fdt=
diff --git a/util/grub.d/10_linux_bls.in b/util/grub.d/10_linux_bls.in
new file mode 100644
index 00000000000..1b7536435f1
--- /dev/null
+++ b/util/grub.d/10_linux_bls.in
@@ -0,0 +1,478 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+datarootdir="@datarootdir@"
+
+. "$pkgdatadir/grub-mkconfig_lib"
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR="@localedir@"
+
+CLASS="--class gnu-linux --class gnu --class os --unrestricted"
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS="$(eval $(grep PRETTY_NAME /etc/os-release) ; echo ${PRETTY_NAME})"
+ CLASS="--class $(eval $(grep '^ID_LIKE=\|^ID=' /etc/os-release) ; [ -n "${ID_LIKE}" ] && echo ${ID_LIKE} || echo ${ID}) ${CLASS}"
+else
+ OS="${GRUB_DISTRIBUTOR}"
+ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
+fi
+
+# loop-AES arranges things so that /dev/loop/X can be our root device, but
+# the initrds that Linux uses don't like that.
+case ${GRUB_DEVICE} in
+ /dev/loop/*|/dev/loop[0-9])
+ GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
+ ;;
+esac
+
+# Default to disabling partition uuid support to maintian compatibility with
+# older kernels.
+GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+
+# btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
+# and mounting btrfs requires user space scanning, so force UUID in this case.
+if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
+ || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+ && [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
+ || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+ && ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
+ || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
+ LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
+ || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+ LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
+else
+ LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
+fi
+
+case x"$GRUB_FS" in
+ xbtrfs)
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then
+ GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}"
+ else
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ]; then
+ GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+ fi
+ fi;;
+ xzfs)
+ rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
+ bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`"
+ LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs}"
+ ;;
+esac
+
+mktitle ()
+{
+ local title_type
+ local version
+ local OS_NAME
+ local OS_VERS
+
+ title_type=$1 && shift
+ version=$1 && shift
+
+ OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})"
+ OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})"
+
+ case $title_type in
+ recovery)
+ title=$(printf '%s (%s) %s (recovery mode)' \
+ "${OS_NAME}" "${version}" "${OS_VERS}")
+ ;;
+ *)
+ title=$(printf '%s (%s) %s' \
+ "${OS_NAME}" "${version}" "${OS_VERS}")
+ ;;
+ esac
+ echo -n ${title}
+}
+
+title_correction_code=
+
+populate_header_warn()
+{
+cat <<EOF
+
+# This section was generated by a script. Do not modify the generated file - all changes
+# will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files.
+
+EOF
+}
+
+read_config()
+{
+ config_file=${1}
+ title=""
+ initrd=""
+ options=""
+ linux=""
+ grub_users=""
+ grub_arg=""
+ grub_class=""
+
+ while read -r line
+ do
+ record=$(echo ${line} | cut -f 1 -d ' ')
+ value=$(echo ${line} | cut -s -f2- -d ' ')
+ case "${record}" in
+ "title")
+ title=${value}
+ ;;
+ "initrd")
+ initrd=${value}
+ ;;
+ "linux")
+ linux=${value}
+ ;;
+ "options")
+ options=${value}
+ ;;
+ "grub_users")
+ grub_users=${value}
+ ;;
+ "grub_arg")
+ grub_arg=${value}
+ ;;
+ "grub_class")
+ grub_class=${value}
+ ;;
+ esac
+ done < ${config_file}
+}
+
+populate_menu()
+{
+ blsdir="/boot/loader/entries"
+ local -a files
+ local IFS=$'\n'
+ gettext_printf "Generating boot entries from BLS files...\n" >&2
+
+ files=($(for bls in ${blsdir}/*.conf ; do
+ if ! [[ -e "${bls}" ]] ; then
+ continue
+ fi
+ bls="${bls%.conf}"
+ bls="${bls##*/}"
+ echo "${bls}"
+ done | ${kernel_sort} | tac)) || :
+
+ for bls in "${files[@]}" ; do
+ read_config "${blsdir}/${bls}.conf"
+
+ menu="${menu}menuentry '${title}' --class ${grub_class} ${grub_arg} --id=${bls} {\n"
+ menu="${menu}\t linux ${linux} ${options}\n"
+ if [ -n "${initrd}" ] ; then
+ menu="${menu}\t initrd ${boot_prefix}${initrd}\n"
+ fi
+ menu="${menu}}\n\n"
+ done
+ # The printf command seems to be more reliable across shells for special character (\n, \t) evaluation
+ printf "$menu"
+}
+
+linux_entry ()
+{
+ os="$1"
+ version="$2"
+ type="$3"
+ isdebug="$4"
+ args="$5"
+
+ if [ -z "$boot_device_id" ]; then
+ boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+ fi
+
+ if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE}
+ fi
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT}
+ fi
+ fi
+
+ if [ -d /sys/firmware/efi ]; then
+ bootefi_device="`${grub_probe} --target=device /boot/efi/`"
+ prepare_grub_to_access_device_with_variable boot ${bootefi_device}
+ else
+ boot_device="`${grub_probe} --target=device /boot/`"
+ prepare_grub_to_access_device_with_variable boot ${boot_device}
+ fi
+
+ populate_header_warn
+ populate_menu
+
+ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then
+ blsdir="/boot/loader/entries"
+ [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})"
+ if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then
+ blsdir=$(make_system_path_relative_to_its_root "${blsdir}")
+ if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then
+ ${grub_editenv} - set blsdir="${blsdir}"
+ fi
+ fi
+
+ ${grub_editenv} - set kernelopts="root=${linux_root_device_thisversion} ro ${args}"
+ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
+ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
+ fi
+ fi
+
+ exit 0
+ fi
+
+ if [ x$type != xsimple ] ; then
+ title=$(mktitle "$type" "$version")
+ if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
+ replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
+ quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
+ title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
+ fi
+ if [ x$isdebug = xdebug ]; then
+ title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}"
+ fi
+ echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ else
+ echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ fi
+ if [ x$type != xrecovery ] ; then
+ save_default_entry | grub_add_tab
+ fi
+
+ # Use ELILO's generic "efifb" when it's known to be available.
+ # FIXME: We need an interface to select vesafb in case efifb can't be used.
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
+ if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
+ && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
+ echo " set gfxpayload=keep" | sed "s/^/$submenu_indentation/"
+ fi
+ else
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
+ fi
+ echo " set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/"
+ fi
+
+ echo " insmod gzio" | sed "s/^/$submenu_indentation/"
+
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)"
+ fi
+ printf '%s\n' "${prepare_root_cache}" | sed "s/^/$submenu_indentation/"
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)"
+ fi
+ printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
+ fi
+ sed "s/^/$submenu_indentation/" << EOF
+ linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+EOF
+ if test -n "${initrd}" ; then
+ initrd_path=
+ for i in ${initrd}; do
+ initrd_path="${initrd_path} ${rel_dirname}/${i}"
+ done
+ sed "s/^/$submenu_indentation/" << EOF
+ initrd $(echo $initrd_path)
+EOF
+ fi
+ if test -n "${fdt}" ; then
+ sed "s/^/$submenu_indentation/" << EOF
+ devicetree ${rel_dirname}/${fdt}
+EOF
+ fi
+ sed "s/^/$submenu_indentation/" << EOF
+}
+EOF
+}
+
+machine=`uname -m`
+case "x$machine" in
+ xi?86 | xx86_64)
+ list=
+ for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
+ if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+ done ;;
+ *)
+ list=
+ for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
+ if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+ done ;;
+esac
+
+if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
+ for i in /boot/ostree/*/vmlinuz-* ; do
+ if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+ done
+fi
+
+case "$machine" in
+ i?86) GENKERNEL_ARCH="x86" ;;
+ mips|mips64) GENKERNEL_ARCH="mips" ;;
+ mipsel|mips64el) GENKERNEL_ARCH="mipsel" ;;
+ arm*) GENKERNEL_ARCH="arm" ;;
+ *) GENKERNEL_ARCH="$machine" ;;
+esac
+
+prepare_boot_cache=
+prepare_root_cache=
+boot_device_id=
+title_correction_code=
+
+# Extra indentation to add to menu entries in a submenu. We're not in a submenu
+# yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
+submenu_indentation=""
+
+is_top_level=true
+while [ "x$list" != "x" ] ; do
+ linux=`version_find_latest $list`
+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+ gettext_printf "Found linux image: %s\n" "$linux" >&2
+ fi
+
+ basename=`basename $linux`
+ dirname=`dirname $linux`
+ rel_dirname=`make_system_path_relative_to_its_root $dirname`
+ version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
+ alt_version=`echo $version | sed -e "s,\.old$,,g"`
+ linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"
+
+ initrd_early=
+ for i in ${GRUB_EARLY_INITRD_LINUX_STOCK} \
+ ${GRUB_EARLY_INITRD_LINUX_CUSTOM}; do
+ if test -e "${dirname}/${i}" ; then
+ initrd_early="${initrd_early} ${i}"
+ fi
+ done
+
+ initrd_real=
+ for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
+ "initrd-${version}" "initramfs-${version}.img" \
+ "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
+ "initrd-${alt_version}" "initramfs-${alt_version}.img" \
+ "initramfs-genkernel-${version}" \
+ "initramfs-genkernel-${alt_version}" \
+ "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
+ "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
+ if test -e "${dirname}/${i}" ; then
+ initrd_real="${i}"
+ break
+ fi
+ done
+
+ initrd=
+ if test -n "${initrd_early}" || test -n "${initrd_real}"; then
+ initrd="${initrd_early} ${initrd_real}"
+
+ initrd_display=
+ for i in ${initrd}; do
+ initrd_display="${initrd_display} ${dirname}/${i}"
+ done
+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ fi
+ fi
+
+ fdt=
+ for i in "dtb-${version}" "dtb-${alt_version}"; do
+ if test -f "${dirname}/${i}/${GRUB_DEFAULT_DTB}" ; then
+ fdt="${i}/${GRUB_DEFAULT_DTB}"
+ break
+ fi
+ done
+
+ config=
+ for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ if test -e "${i}" ; then
+ config="${i}"
+ break
+ fi
+ done
+
+ initramfs=
+ if test -n "${config}" ; then
+ initramfs=`grep CONFIG_INITRAMFS_SOURCE= "${config}" | cut -f2 -d= | tr -d \"`
+ fi
+
+ if test -z "${initramfs}" && test -z "${initrd_real}" ; then
+ # "UUID=" and "ZFS=" magic is parsed by initrd or initramfs. Since there's
+ # no initrd or builtin initramfs, it can't work here.
+ if [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] \
+ || [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ]; then
+
+ linux_root_device_thisversion=${GRUB_DEVICE}
+ else
+ linux_root_device_thisversion=PARTUUID=${GRUB_DEVICE_PARTUUID}
+ fi
+ fi
+
+ if [ "x${GRUB_DISABLE_SUBMENU}" = "xyes" ] || [ "x${GRUB_DISABLE_SUBMENU}" = "xy" ]; then
+ GRUB_DISABLE_SUBMENU="true"
+ fi
+
+ if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
+ linux_entry "${OS}" "${version}" simple standard \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ linux_entry "${OS}" "${version}" simple debug \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+
+ submenu_indentation="$grub_tab"
+
+ if [ -z "$boot_device_id" ]; then
+ boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+ fi
+ # TRANSLATORS: %s is replaced with an OS name
+ echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
+ is_top_level=false
+ fi
+
+ linux_entry "${OS}" "${version}" advanced standard \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ linux_entry "${OS}" "${version}" advanced debug \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ linux_entry "${OS}" "${version}" recovery standard \
+ "single ${GRUB_CMDLINE_LINUX}"
+ fi
+
+ list=`echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '`
+done
+
+# If at least one kernel was found, then we need to
+# add a closing '}' for the submenu command.
+if [ x"$is_top_level" != xtrue ]; then
+ echo '}'
+fi
+
+echo "$title_correction_code"