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