Merge pull request #220263 from samueldr/feature/misc-grub-fixes

nixos/grub: Fixes to allow flicker-free boot, themes and bug fixes
This commit is contained in:
Samuel Dionne-Riel 2023-08-12 20:32:51 -04:00 committed by GitHub
commit f064a5bcc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 8 deletions

View file

@ -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;
@ -63,7 +87,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
@ -148,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";
@ -425,6 +451,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;
@ -699,7 +747,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 = [

View file

@ -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
@ -383,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
@ -725,9 +752,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";
}