All of lore.kernel.org
 help / color / mirror / Atom feed
From: Denton Liu <liu.denton@gmail.com>
To: grub-devel@gnu.org
Cc: Daniel Kiper <daniel.kiper@oracle.com>,
	Oskari Pirhonen <xxc3ncoredxx@gmail.com>,
	mathieu.desnoyers@efficios.com, rharwood@redhat.com,
	samuel.thibault@ens-lyon.org, debian-bsd@lists.debian.org,
	xen-devel@lists.xenproject.org, Olaf Hering <olaf@aepfle.de>
Subject: [PATCH v5] templates: introduce GRUB_TOP_LEVEL_* vars
Date: Mon, 24 Oct 2022 03:46:42 -0700	[thread overview]
Message-ID: <20221024104642.251016-1-liu.denton@gmail.com> (raw)

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`, meaning
the LTS kernel becomes the top-level entry. However, a user may wish to
use the regular kernel as the top-level default with the LTS only
existing as a backup.

This need can be seen in Arch Linux's AUR with two user-submitted
packages[0][1] providing an update hook which patches
/etc/grub.d/10_linux to move the desired kernel to the top-level. This
patch serves to solve this in a more generic way.

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.

[0]: https://aur.archlinux.org/packages/grub-linux-default-hook
[1]: https://aur.archlinux.org/packages/grub-linux-rt-default-hook

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 v4:
    
    * Update docs to specify that GRUB_TOP_LEVEL and GRUB_TOP_LEVEL_XEN take
      an absolute path
    
    * Add more justification in the commit message
    
    Changes since v3:
    
    * Fix if formatting nit
    
    * Rebase on top of latest 'master'
    
    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

Range-diff against v4:
1:  d3a693804 ! 1:  ee633189b templates: introduce GRUB_TOP_LEVEL_* vars
    @@ Commit message
         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.
    +    gets sorted as the "latest" compared to `/boot/vmlinuz-linux`, meaning
    +    the LTS kernel becomes the top-level entry. However, a user may wish to
    +    use the regular kernel as the top-level default with the LTS only
    +    existing as a backup.
    +
    +    This need can be seen in Arch Linux's AUR with two user-submitted
    +    packages[0][1] providing an update hook which patches
    +    /etc/grub.d/10_linux to move the desired kernel to the top-level. This
    +    patch serves to solve this in a more generic way.
     
         Introduce the GRUB_TOP_LEVEL, GRUB_TOP_LEVEL_XEN and
         GRUB_TOP_LEVEL_OS_PROBER variables to allow users to specify the
    @@ Commit message
         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.
     
    +    [0]: https://aur.archlinux.org/packages/grub-linux-default-hook
    +    [1]: https://aur.archlinux.org/packages/grub-linux-rt-default-hook
    +
         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 v4:
    +
    +    * Update docs to specify that GRUB_TOP_LEVEL and GRUB_TOP_LEVEL_XEN take
    +      an absolute path
    +
    +    * Add more justification in the commit message
    +
         Changes since v3:
     
         * Fix if formatting nit
    @@ docs/grub.texi: for all respectively normal 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.
    ++This option should be an absolute 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

 docs/grub.texi              | 10 ++++++++++
 util/grub-mkconfig.in       |  3 +++
 util/grub-mkconfig_lib.in   | 26 ++++++++++++++++++++++++++
 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, 69 insertions(+), 1 deletion(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 0dbbdc374..641fb4ad3 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 an absolute 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..08953287c 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -218,6 +218,32 @@ 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 a021d02c2..b317a4b14 100644
--- a/util/grub.d/10_hurd.in
+++ b/util/grub.d/10_hurd.in
@@ -229,6 +229,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.38.1



             reply	other threads:[~2022-10-24 10:47 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-24 10:46 Denton Liu [this message]
2022-10-25  3:21 ` [PATCH v5] templates: introduce GRUB_TOP_LEVEL_* vars Oskari Pirhonen
2022-11-03 16:39   ` Daniel Kiper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221024104642.251016-1-liu.denton@gmail.com \
    --to=liu.denton@gmail.com \
    --cc=daniel.kiper@oracle.com \
    --cc=debian-bsd@lists.debian.org \
    --cc=grub-devel@gnu.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=olaf@aepfle.de \
    --cc=rharwood@redhat.com \
    --cc=samuel.thibault@ens-lyon.org \
    --cc=xen-devel@lists.xenproject.org \
    --cc=xxc3ncoredxx@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.