[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3] templates: introduce GRUB_TOP_LEVEL_* vars
From: |
Denton Liu |
Subject: |
[PATCH v3] templates: introduce GRUB_TOP_LEVEL_* vars |
Date: |
Wed, 5 Oct 2022 02:22:38 -0700 |
A user may wish to use an image that is not sorted as the "latest"
version as the top-level entry. For example, in Arch Linux, if a user
has the LTS and regular kernels installed, `/boot/vmlinuz-linux-lts`
gets sorted as the "latest" compared to `/boot/vmlinuz-linux`. However,
a user may wish to use the regular kernel as the default with the LTS
only existing as a backup.
Introduce the GRUB_TOP_LEVEL, GRUB_TOP_LEVEL_XEN and
GRUB_TOP_LEVEL_OS_PROBER variables to allow users to specify the
top-level entry.
Create grub_move_to_front() as a helper function which moves entries to
the front of a list. This function does the heavy lifting of moving
the menu entry to the front in each script.
In 10_netbsd, since there isn't an explicit list variable, extract the
items that are being iterated through into a list so that we can
optionally apply grub_move_to_front() to the list before the loop.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
Notes:
The only file that was tested is 10_linux. I do not have access to any
of the other images or systems so they remain untested.
Changes since v2:
* Added more detail to GRUB_TOP_LEVEL docs
* Moved GRUB_TOP_LEVEL_OS_PROBER to separate section in docs
* Renamed grub_move_entry_to_front() to grub_move_to_front() and added
code comment
* Give 10_netbsd an intermediate list of images to interact with
Interdiff against v2:
diff --git a/docs/grub.texi b/docs/grub.texi
index 16a445178..db6b20531 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1446,9 +1446,13 @@ and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux and
Xen menu entries.
@item GRUB_TOP_LEVEL
@item GRUB_TOP_LEVEL_XEN
+This option should be a path to a kernel image. If provided, the image
+specified will be made the top-level entry if it is found in the scan.
+
@item GRUB_TOP_LEVEL_OS_PROBER
-If this option is provided, the given image file will be made the top-level
-entry if the image file is found in the scan.
+This option should be a line of output from @command{os-prober}. As
+@samp{GRUB_TOP_LEVEL}, if provided, the image specified will be made the
+top-level entry if it is found in the scan.
@item GRUB_EARLY_INITRD_LINUX_CUSTOM
@itemx GRUB_EARLY_INITRD_LINUX_STOCK
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 5be49a07c..f4ae41f86 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -218,23 +218,26 @@ version_sort ()
esac
}
-grub_move_entry_to_front ()
+# Given an item as the first argument and a list as the subsequent arguments,
+# returns the list with the first argument moved to the front if it exists in
+# the list.
+grub_move_to_front ()
{
- entry="$1"
+ item="$1"
shift
- entry_found=false
+ item_found=false
for i in "$@"; do
- if [ "x$i" = "x$entry" ]; then
- entry_found=true
+ if [ "x$i" = "x$item" ]; then
+ item_found=true
fi
done
- if [ "x$entry_found" = xtrue ]; then
- echo "$entry"
+ if [ "x$item_found" = xtrue ]; then
+ echo "$item"
fi
for i in "$@"; do
- if [ "x$i" = "x$entry" ]; then continue; fi
+ if [ "x$i" = "x$item" ]; then continue; fi
echo "$i"
done
}
diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in
index 0ae5a3927..b7be7041c 100644
--- a/util/grub.d/10_hurd.in
+++ b/util/grub.d/10_hurd.in
@@ -206,7 +206,7 @@ submenu_indentation=""
reverse_sorted_kernels=$(echo ${kernels} | tr ' ' '\n' | sed -e 's/\.old$/
1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
if [ "x$GRUB_TOP_LEVEL" != x ]; then
- reverse_sorted_kernels=$(grub_move_entry_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_kernels})
+ reverse_sorted_kernels=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_kernels})
fi
is_top_level=true
diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in
index 506b2df66..83e9636e8 100644
--- a/util/grub.d/10_kfreebsd.in
+++ b/util/grub.d/10_kfreebsd.in
@@ -165,7 +165,7 @@ submenu_indentation=""
reverse_sorted_list=$(echo ${list} | tr ' ' '\n' | sed -e 's/\.old$/ 1/; /
1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
if [ "x$GRUB_TOP_LEVEL" != x ]; then
- reverse_sorted_list=$(grub_move_entry_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_list})
+ reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_list})
fi
is_top_level=true
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index a479c16af..7263f2983 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -203,7 +203,7 @@ submenu_indentation=""
reverse_sorted_list=$(echo $list | tr ' ' '\n' | sed -e 's/\.old$/ 1/; /
1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
if [ "x$GRUB_TOP_LEVEL" != x ]; then
- reverse_sorted_list=$(grub_move_entry_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_list})
+ reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_list})
fi
is_top_level=true
diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
index 4eae58e82..3154e9e15 100644
--- a/util/grub.d/10_netbsd.in
+++ b/util/grub.d/10_netbsd.in
@@ -146,19 +146,17 @@ pattern="^ELF[^,]*executable.*statically linked"
# yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
submenu_indentation=""
+list="/netbsd $(ls -t /netbsd?* 2>/dev/null)"
+
+if [ "x$GRUB_TOP_LEVEL" != x ]; then
+ list=$(grub_move_to_front "$GRUB_TOP_LEVEL" ${list})
+fi
+
is_top_level=true
-grub_top_level_found=false
-for k in "$GRUB_TOP_LEVEL" /netbsd $(ls -t /netbsd?* 2>/dev/null) ; do
+for k in ${list}; do
if ! grub_file_is_not_garbage "$k" ; then
continue
fi
- if [ "x$GRUB_TOP_LEVEL" = "x$k" ] ; then
- if [ "x$grub_top_level_found" = xfalse ] ; then
- grub_top_level_found=true
- else
- continue
- fi
- fi
if ! (zcat -f "$k" | file -bL - | grep -q "${pattern}") 2>/dev/null ; then
continue
fi
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index c32bb979f..386bfb9be 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -246,10 +246,10 @@ reverse_sorted_xen_list=$(echo ${xen_list} | tr ' '
'\n' | sed -e 's/\.old$/ 1/;
reverse_sorted_linux_list=$(echo ${linux_list} | tr ' ' '\n' | sed -e
's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/
2$//')
if [ "x$GRUB_TOP_LEVEL_XEN" != x ]; then
- reverse_sorted_xen_list=$(grub_move_entry_to_front "$GRUB_TOP_LEVEL_XEN"
${reverse_sorted_xen_list})
+ reverse_sorted_xen_list=$(grub_move_to_front "$GRUB_TOP_LEVEL_XEN"
${reverse_sorted_xen_list})
fi
-if [ "x$GRUB_TOP_LEVEL_LINUX" != x ]; then
- reverse_sorted_linux_list=$(grub_move_entry_to_front
"$GRUB_TOP_LEVEL_LINUX" ${reverse_sorted_linux_list})
+if [ "x$GRUB_TOP_LEVEL" != x ]; then
+ reverse_sorted_linux_list=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_linux_list})
fi
is_top_level=true
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 9b2a96bd0..656301eaf 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -114,7 +114,7 @@ EOF
used_osprober_linux_ids=
if [ "x$GRUB_TOP_LEVEL_OS_PROBER" != x ]; then
- OSPROBED=$(grub_move_entry_to_front "$GRUB_TOP_LEVEL_OS_PROBER"
${OSPROBED})
+ OSPROBED=$(grub_move_to_front "$GRUB_TOP_LEVEL_OS_PROBER" ${OSPROBED})
fi
for OS in ${OSPROBED} ; do
docs/grub.texi | 10 ++++++++++
util/grub-mkconfig.in | 3 +++
util/grub-mkconfig_lib.in | 24 ++++++++++++++++++++++++
util/grub.d/10_hurd.in | 4 ++++
util/grub.d/10_kfreebsd.in | 4 ++++
util/grub.d/10_linux.in | 4 ++++
util/grub.d/10_netbsd.in | 8 +++++++-
util/grub.d/20_linux_xen.in | 7 +++++++
util/grub.d/30_os-prober.in | 4 ++++
9 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 107f66ebc..db6b20531 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1444,6 +1444,16 @@ for all respectively normal entries.
The values of these options replace the values of @samp{GRUB_CMDLINE_LINUX}
and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux and Xen menu entries.
+@item GRUB_TOP_LEVEL
+@item GRUB_TOP_LEVEL_XEN
+This option should be a path to a kernel image. If provided, the image
+specified will be made the top-level entry if it is found in the scan.
+
+@item GRUB_TOP_LEVEL_OS_PROBER
+This option should be a line of output from @command{os-prober}. As
+@samp{GRUB_TOP_LEVEL}, if provided, the image specified will be made the
+top-level entry if it is found in the scan.
+
@item GRUB_EARLY_INITRD_LINUX_CUSTOM
@itemx GRUB_EARLY_INITRD_LINUX_STOCK
List of space-separated early initrd images to be loaded from @samp{/boot}.
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 62335d027..32c480dae 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -233,6 +233,9 @@ export GRUB_DEFAULT \
GRUB_CMDLINE_NETBSD \
GRUB_CMDLINE_NETBSD_DEFAULT \
GRUB_CMDLINE_GNUMACH \
+ GRUB_TOP_LEVEL \
+ GRUB_TOP_LEVEL_XEN \
+ GRUB_TOP_LEVEL_OS_PROBER \
GRUB_EARLY_INITRD_LINUX_CUSTOM \
GRUB_EARLY_INITRD_LINUX_STOCK \
GRUB_TERMINAL_INPUT \
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 634bc8a50..f4ae41f86 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -218,6 +218,30 @@ version_sort ()
esac
}
+# Given an item as the first argument and a list as the subsequent arguments,
+# returns the list with the first argument moved to the front if it exists in
+# the list.
+grub_move_to_front ()
+{
+ item="$1"
+ shift
+
+ item_found=false
+ for i in "$@"; do
+ if [ "x$i" = "x$item" ]; then
+ item_found=true
+ fi
+ done
+
+ if [ "x$item_found" = xtrue ]; then
+ echo "$item"
+ fi
+ for i in "$@"; do
+ if [ "x$i" = "x$item" ]; then continue; fi
+ echo "$i"
+ done
+}
+
# One layer of quotation is eaten by "" and the second by sed; so this turns
# ' into \'.
grub_quote () {
diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in
index 4294bbe4c..b7be7041c 100644
--- a/util/grub.d/10_hurd.in
+++ b/util/grub.d/10_hurd.in
@@ -205,6 +205,10 @@ submenu_indentation=""
reverse_sorted_kernels=$(echo ${kernels} | tr ' ' '\n' | sed -e 's/\.old$/ 1/;
/ 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
+if [ "x$GRUB_TOP_LEVEL" != x ]; then
+ reverse_sorted_kernels=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_kernels})
+fi
+
is_top_level=true
for kernel in ${reverse_sorted_kernels}; do
diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in
index 0a67decaa..83e9636e8 100644
--- a/util/grub.d/10_kfreebsd.in
+++ b/util/grub.d/10_kfreebsd.in
@@ -164,6 +164,10 @@ submenu_indentation=""
reverse_sorted_list=$(echo ${list} | tr ' ' '\n' | sed -e 's/\.old$/ 1/; /
1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
+if [ "x$GRUB_TOP_LEVEL" != x ]; then
+ reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_list})
+fi
+
is_top_level=true
for kfreebsd in ${reverse_sorted_list}; do
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index c6a1ec935..7263f2983 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -202,6 +202,10 @@ submenu_indentation=""
reverse_sorted_list=$(echo $list | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/!
s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
+if [ "x$GRUB_TOP_LEVEL" != x ]; then
+ reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_list})
+fi
+
is_top_level=true
for linux in ${reverse_sorted_list}; do
gettext_printf "Found linux image: %s\n" "$linux" >&2
diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
index dc0cd1b17..3154e9e15 100644
--- a/util/grub.d/10_netbsd.in
+++ b/util/grub.d/10_netbsd.in
@@ -146,8 +146,14 @@ pattern="^ELF[^,]*executable.*statically linked"
# yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
submenu_indentation=""
+list="/netbsd $(ls -t /netbsd?* 2>/dev/null)"
+
+if [ "x$GRUB_TOP_LEVEL" != x ]; then
+ list=$(grub_move_to_front "$GRUB_TOP_LEVEL" ${list})
+fi
+
is_top_level=true
-for k in /netbsd $(ls -t /netbsd?* 2>/dev/null) ; do
+for k in ${list}; do
if ! grub_file_is_not_garbage "$k" ; then
continue
fi
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index 626aed40c..386bfb9be 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -245,6 +245,13 @@ submenu_indentation=""
reverse_sorted_xen_list=$(echo ${xen_list} | tr ' ' '\n' | sed -e 's/\.old$/
1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
reverse_sorted_linux_list=$(echo ${linux_list} | tr ' ' '\n' | sed -e
's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/
2$//')
+if [ "x$GRUB_TOP_LEVEL_XEN" != x ]; then
+ reverse_sorted_xen_list=$(grub_move_to_front "$GRUB_TOP_LEVEL_XEN"
${reverse_sorted_xen_list})
+fi
+if [ "x$GRUB_TOP_LEVEL" != x ]; then
+ reverse_sorted_linux_list=$(grub_move_to_front "$GRUB_TOP_LEVEL"
${reverse_sorted_linux_list})
+fi
+
is_top_level=true
for current_xen in ${reverse_sorted_xen_list}; do
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index daa603778..656301eaf 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -113,6 +113,10 @@ EOF
used_osprober_linux_ids=
+if [ "x$GRUB_TOP_LEVEL_OS_PROBER" != x ]; then
+ OSPROBED=$(grub_move_to_front "$GRUB_TOP_LEVEL_OS_PROBER" ${OSPROBED})
+fi
+
for OS in ${OSPROBED} ; do
DEVICE="`echo ${OS} | cut -d ':' -f 1`"
LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
--
2.37.3
- [PATCH v3] templates: introduce GRUB_TOP_LEVEL_* vars,
Denton Liu <=