From ca3db79c35360b4724afc4359cf32e6356f8e298 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Fri, 19 Feb 2021 13:09:31 +0100 Subject: [PATCH] stages/grub2: support `saved_entry` grubenv var The current grub configuration has no logic to select the default boot entry, which means the next boot entry is chosen by grub2 by the sort order of available entries. This will break tooling like grub2-set-default and grub2-reboot that set on a specific variable `saved_entry` in the grub environment file `grubenv` to to point to the select boot entry. Change our grub configuration file to use that `saved_entry` var to select the next boot entry to unbreak the tooling. In addition to the aforementioned tools, the saved_entry is also updated by the kernel install scripts when new kernel is installed, but only if the newly installed kernel is the selected default. Thus not respecting the `saved_entry` variable might cause a bug where a newly installed non-default kernel gets selected by grub2. --- stages/org.osbuild.grub2 | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/stages/org.osbuild.grub2 b/stages/org.osbuild.grub2 index e7f8a24b..6c6b9079 100755 --- a/stages/org.osbuild.grub2 +++ b/stages/org.osbuild.grub2 @@ -36,6 +36,16 @@ and accompanying data can be installed from the built root via `uefi.install`. Both UEFI and Legacy can be specified at the same time. +If the `saved_entry` option is present it will result in an entry in the +`grubenv` file of the same name. The grub config file contains logic so +that this variable will be used to select the next boot entry. This will +also make grub2-reboot and grub2-set-default tools work. It will also +prevent newly installed non-default kernels (like e.g. the debug kernel) +to be selected as default. The contents of variable needs to match the +corresponding loader entry, which currently is a combination of the +machine id and kernel NVRA, like e.g.: + `ffffffffffffffffffffffffffffffff-5.6.6-300.fc32.x86_64` + Support for ignition (https://github.com/coreos/ignition) can be turned on via the `ignition` option. If enabled, a 'ignition_firstboot' variable will be created, which is meant to be included in the kernel command line. @@ -141,6 +151,10 @@ SCHEMA = """ } } }, + "saved_entry": { + "description": "Set the variable of the same name in `grubenv`.", + "type": "string" + }, "write_defaults": { "description": "Whether to write /etc/defaults/grub", "type": "boolean", @@ -163,7 +177,23 @@ SCHEMA = """ # is enabled GRUB_CFG_TEMPLATE = """ set timeout=0 + +# load the grubenv file load_env + +# selection of the next boot entry via variables 'next_entry' and +# `saved_entry` present in the 'grubenv' file. Both variables are +# set by grub tools, like grub2-reboot, grub2-set-default + +if [ "${next_entry}" ] ; then + set default="${next_entry}" + set next_entry= + save_env next_entry + set boot_once=true +else + set default="${saved_entry}" +fi + search --no-floppy --set=root $search set boot=$${root} function load_video { @@ -321,6 +351,7 @@ class GrubConfig: cfg.write(data) +#pylint: disable=too-many-statements def main(tree, options): root_fs = options.get("rootfs") boot_fs = options.get("bootfs") @@ -329,6 +360,7 @@ def main(tree, options): uefi = options.get("uefi", None) write_defaults = options.get("write_defaults", True) ignition = options.get("ignition", False) + saved_entry = options.get("saved_entry") # backwards compatibility if not root_fs: @@ -378,6 +410,9 @@ def main(tree, options): f"kernelopts=root={fs_type}={fs_id} {kernel_opts}\n" ) + if saved_entry: + data += f"saved_entry={saved_entry}\n" + # The 'grubenv' file is, according to the documentation, # a 'preallocated 1024-byte file'. The empty space is # needs to be filled with '#' as padding