From eff8d3bdb114bdd48bc84589d876f31fe3acc83b Mon Sep 17 00:00:00 2001 From: SrTobi Date: Wed, 13 Jan 2021 18:55:30 +0100 Subject: [PATCH] nixos/grub: implements GRUB_SAVEDEFAULT feature Grub will remember the configuration that was booted and select it as default menu entry the next time (#108206). --- .../modules/system/boot/loader/grub/grub.nix | 2 ++ .../system/boot/loader/grub/install-grub.pl | 31 +++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index e183bc3648ce..1be663670384 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -553,6 +553,8 @@ in apply = toString; description = '' Index of the default menu item to be booted. + Can also be set to "saved", which will make GRUB select + the menu item that was used at the last boot. ''; }; diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index e0167654748e..4d8537d4c327 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -85,6 +85,7 @@ my $bootloaderId = get("bootloaderId"); my $forceInstall = get("forceInstall"); my $font = get("font"); my $theme = get("theme"); +my $saveDefault = $defaultEntry eq "saved"; $ENV{'PATH'} = get("path"); die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2; @@ -250,6 +251,8 @@ if ($copyKernels == 0) { my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n"; if ($grubVersion == 1) { + # $defaultEntry might be "saved", indicating that we want to use the last selected configuration as default. + # Incidentally this is already the correct value for the grub 1 config to achieve this behaviour. $conf .= " default $defaultEntry timeout $timeout @@ -305,6 +308,10 @@ else { " . $grubStore->search; } # FIXME: should use grub-mkconfig. + my $defaultEntryText = $defaultEntry; + if ($saveDefault) { + $defaultEntryText = "\"\${saved_entry}\""; + } $conf .= " " . $grubBoot->search . " if [ -s \$prefix/grubenv ]; then @@ -318,11 +325,19 @@ else { set next_entry= save_env next_entry set timeout=1 + set boot_once=true else - set default=$defaultEntry + set default=$defaultEntryText set timeout=$timeout fi + function savedefault { + if [ -z \"\${boot_once}\"]; then + saved_entry=\"\${chosen}\" + save_env saved_entry + fi + } + # Setup the graphics stack for bios and efi systems if [ \"\${grub_platform}\" = \"efi\" ]; then insmod efi_gop @@ -468,9 +483,16 @@ sub addEntry { $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; $conf .= " kernel $xen $xenParams\n" if $xen; $conf .= " " . ($xen ? "module" : "kernel") . " $kernel $kernelParams\n"; - $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n"; + $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n"; + if ($saveDefault) { + $conf .= " savedefault\n"; + } + $conf .= "\n"; } else { $conf .= "menuentry \"$name\" " . ($options||"") . " {\n"; + if ($saveDefault) { + $conf .= " savedefault\n"; + } $conf .= $grubBoot->search . "\n"; if ($copyKernels == 0) { $conf .= $grubStore->search . "\n"; @@ -605,6 +627,11 @@ my $efiTarget = getEfiTarget(); # Append entries detected by os-prober if (get("useOSProber") eq "true") { + if ($saveDefault) { + # os-prober will read this to determine if "savedefault" should be added to generated entries + $ENV{'GRUB_SAVEDEFAULT'} = "true"; + } + my $targetpackage = ($efiTarget eq "no") ? $grub : $grubEfi; system(get("shell"), "-c", "pkgdatadir=$targetpackage/share/grub $targetpackage/etc/grub.d/30_os-prober >> $tmpFile"); }