From 894d47f9896096587aed6028099a90430355199d Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Wed, 8 Mar 2023 02:18:37 -0500 Subject: [PATCH 1/5] nixos/grub: Always install with bootloader id The intent was to not pass the flag when installing as removable. In reality there is a third case, where you may not want to touch EFI variables, and not want to install as removable. In that case, it would install to the generic \EFI\grub\grubx64.efi, which is not a good choice in any cases. The operating system should "own" their path under \EFI\ to be a good citizen [citation needed]. With this change, there can be only two paths GRUB can be installed to: - \EFI\NixOS-boot\grubx64.efi - \EFI\BOOT\bootx64.efi This removes the surprising behaviour where GRUB may be installed to a different location only because we configured NixOS not to touch EFI variables. It may be necessary under some configurations to install GRUB without touching EFI variables, but to the NixOS-owned location. --- nixos/modules/system/boot/loader/grub/install-grub.pl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 27f03f2fb58c..f301d838f663 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -725,9 +725,8 @@ if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both")) if ($forceInstall eq "true") { push @command, "--force"; } - if ($canTouchEfiVariables eq "true") { - push @command, "--bootloader-id=$bootloaderId"; - } else { + push @command, "--bootloader-id=$bootloaderId"; + if ($canTouchEfiVariables ne "true") { push @command, "--no-nvram"; push @command, "--removable" if $efiInstallAsRemovable eq "true"; } From f12b216574f5dfd6f26a8be5b19661e89d92c983 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Mon, 6 Mar 2023 23:40:12 -0500 Subject: [PATCH 2/5] nixos/grub: Fix extraFiles in subdirectories This directly copies the systemd-boot logic, which works. `install` with `-D` will create all leading directory components. --- nixos/modules/system/boot/loader/grub/grub.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 8f2f578e3070..e0171a71da93 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -699,7 +699,7 @@ in boot.loader.grub.extraPrepareConfig = concatStrings (mapAttrsToList (n: v: '' - ${pkgs.coreutils}/bin/cp -pf "${v}" "@bootPath@/${n}" + ${pkgs.coreutils}/bin/install -Dp "${v}" "${efi.efiSysMountPoint}/"${escapeShellArg n} '') config.boot.loader.grub.extraFiles); assertions = [ From 50063bf9d62f782757bf33a83fec40db593841d6 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Mon, 6 Mar 2023 23:59:39 -0500 Subject: [PATCH 3/5] nixos/grub: Add support for timeoutStyle --- .../modules/system/boot/loader/grub/grub.nix | 26 ++++++++++++++++++- .../system/boot/loader/grub/install-grub.pl | 2 ++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index e0171a71da93..120e7f331534 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -63,7 +63,9 @@ let extraGrubInstallArgs extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios - users; + users + timeoutStyle + ; path = with pkgs; makeBinPath ( [ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ] ++ optional cfg.efiSupport efibootmgr @@ -425,6 +427,28 @@ in ''; }; + timeoutStyle = mkOption { + default = "menu"; + type = types.enum [ "menu" "countdown" "hidden" ]; + description = lib.mdDoc '' + - `menu` shows the menu. + - `countdown` uses a text-mode countdown. + - `hidden` hides GRUB entirely. + + When using a theme, the default value (`menu`) is appropriate for the graphical countdown. + + When attempting to do flicker-free boot, `hidden` should be used. + + See the [GRUB documentation section about `timeout_style`](https://www.gnu.org/software/grub/manual/grub/html_node/timeout.html). + + ::: {.note} + If this option is set to ‘countdown’ or ‘hidden’ [...] and ESC or F4 are pressed, or SHIFT is held down during that time, it will display the menu and wait for input. + ::: + + From: [Simple configuration handling page, under GRUB_TIMEOUT_STYLE](https://www.gnu.org/software/grub/manual/grub/html_node/Simple-configuration.html). + ''; + }; + entryOptions = mkOption { default = "--class nixos --unrestricted"; type = types.nullOr types.str; diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index f301d838f663..93ad3f1ed706 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -75,6 +75,7 @@ my $backgroundColor = get("backgroundColor"); my $configurationLimit = int(get("configurationLimit")); my $copyKernels = get("copyKernels") eq "true"; my $timeout = int(get("timeout")); +my $timeoutStyle = get("timeoutStyle"); my $defaultEntry = get("default"); my $fsIdentifier = get("fsIdentifier"); my $grubEfi = get("grubEfi"); @@ -319,6 +320,7 @@ $conf .= " set default=$defaultEntryText set timeout=$timeout fi + set timeout_style=$timeoutStyle function savedefault { if [ -z \"\${boot_once}\"]; then From c867c6d17288a604d08e313092d0db7c19f11d60 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Wed, 8 Mar 2023 14:24:37 -0500 Subject: [PATCH 4/5] nixos/grub: Insert required image modules for themes With a limited testing of all packaged GRUB 2 themes (pkgs.nixos-grub2-theme) this is tested to work. Without this change, the theme loading will error out (waiting for a key press). With this change, the theme loads and works as expected. --- .../system/boot/loader/grub/install-grub.pl | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 93ad3f1ed706..a84e374624d1 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -385,6 +385,31 @@ rmtree("$bootPath/theme") or die "cannot clean up theme folder in $bootPath\n" i if ($theme) { # Copy theme rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n"; + + # Detect which modules will need to be loaded + my $with_png = 0; + my $with_jpeg = 0; + + find({ wanted => sub { + if ($_ =~ /\.png$/i) { + $with_png = 1; + } + elsif ($_ =~ /\.jpe?g$/i) { + $with_jpeg = 1; + } + }, no_chdir => 1 }, $theme); + + if ($with_png) { + $conf .= " + insmod png + " + } + if ($with_jpeg) { + $conf .= " + insmod jpeg + " + } + $conf .= " # Sets theme. set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt From 1d416595adfc7d48ef06ee49ffd2d9efee2c8859 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Tue, 1 Aug 2023 19:18:48 -0400 Subject: [PATCH 5/5] nixos/grub: Remove `with` with broad scopes. There is only other `with` with a somewhat broad scope, `with pkgs`, but it's used in a place where it would become awkward to change out. And anyway its scope is rather limited still. --- .../modules/system/boot/loader/grub/grub.nix | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 120e7f331534..468f701ae5bc 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -1,8 +1,32 @@ { config, options, lib, pkgs, ... }: -with lib; - let + inherit (lib) + all + concatMap + concatMapStrings + concatStrings + concatStringsSep + escapeShellArg + flip + foldr + forEach + hasPrefix + mapAttrsToList + literalExpression + makeBinPath + mkDefault + mkIf + mkMerge + mkOption + mkRemovedOptionModule + mkRenamedOptionModule + optional + optionals + optionalString + replaceStrings + types + ; cfg = config.boot.loader.grub; @@ -150,7 +174,7 @@ in (as opposed to external files) will be copied into the Nix store, and will be visible to all local users. ''; - type = with types; attrsOf (submodule { + type = types.attrsOf (types.submodule { options = { hashedPasswordFile = mkOption { example = "/path/to/file";