mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 21:50:33 +03:00
nixos/grub: generate BLS entries
This commit is contained in:
parent
e90d001cbb
commit
435a72e469
2 changed files with 89 additions and 2 deletions
|
@ -50,6 +50,10 @@ let
|
||||||
then realGrub.override { efiSupport = cfg.efiSupport; }
|
then realGrub.override { efiSupport = cfg.efiSupport; }
|
||||||
else null;
|
else null;
|
||||||
|
|
||||||
|
bootPath = if cfg.mirroredBoots != [ ]
|
||||||
|
then (builtins.head cfg.mirroredBoots).path
|
||||||
|
else "/boot";
|
||||||
|
|
||||||
f = x: optionalString (x != null) ("" + x);
|
f = x: optionalString (x != null) ("" + x);
|
||||||
|
|
||||||
grubConfig = args:
|
grubConfig = args:
|
||||||
|
@ -756,6 +760,16 @@ in
|
||||||
|
|
||||||
environment.systemPackages = mkIf (grub != null) [ grub ];
|
environment.systemPackages = mkIf (grub != null) [ grub ];
|
||||||
|
|
||||||
|
# Link /boot under /run/boot-loder-entries to make
|
||||||
|
# systemd happy even on non-EFI system
|
||||||
|
systemd.mounts = lib.optional (!cfg.efiSupport) {
|
||||||
|
what = bootPath;
|
||||||
|
where = "/run/boot-loader-entries";
|
||||||
|
type = "none";
|
||||||
|
options = "bind";
|
||||||
|
requiredBy = [ "local-fs.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
boot.loader.grub.extraPrepareConfig =
|
boot.loader.grub.extraPrepareConfig =
|
||||||
concatStrings (mapAttrsToList (n: v: ''
|
concatStrings (mapAttrsToList (n: v: ''
|
||||||
${pkgs.coreutils}/bin/install -Dp "${v}" "${efi.efiSysMountPoint}/"${escapeShellArg n}
|
${pkgs.coreutils}/bin/install -Dp "${v}" "${efi.efiSysMountPoint}/"${escapeShellArg n}
|
||||||
|
|
|
@ -99,7 +99,15 @@ $ENV{'PATH'} = get("path");
|
||||||
|
|
||||||
print STDERR "updating GRUB 2 menu...\n";
|
print STDERR "updating GRUB 2 menu...\n";
|
||||||
|
|
||||||
make_path("$bootPath/grub", { mode => 0700 });
|
# Make GRUB directory
|
||||||
|
make_path("$bootPath/grub", { mode => 0700 });
|
||||||
|
|
||||||
|
# Make BLS entries directory, see addBLSEntry
|
||||||
|
make_path("$bootPath/loader/entries", { mode => 0700 });
|
||||||
|
writeFile("$bootPath/loader/entries.srel", "type1");
|
||||||
|
|
||||||
|
# and a temporary one for new entries
|
||||||
|
make_path("$bootPath/loader/entries.tmp", { mode => 0700 });
|
||||||
|
|
||||||
# Discover whether the bootPath is on the same filesystem as / and
|
# Discover whether the bootPath is on the same filesystem as / and
|
||||||
# /nix/store. If not, then all kernels and initrds must be copied to
|
# /nix/store. If not, then all kernels and initrds must be copied to
|
||||||
|
@ -460,6 +468,7 @@ sub copyToKernelsDir {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub addEntry {
|
sub addEntry {
|
||||||
|
# Creates a Grub menu entry for a given system
|
||||||
my ($name, $path, $options, $current) = @_;
|
my ($name, $path, $options, $current) = @_;
|
||||||
return unless -e "$path/kernel" && -e "$path/initrd";
|
return unless -e "$path/kernel" && -e "$path/initrd";
|
||||||
|
|
||||||
|
@ -521,6 +530,58 @@ sub addEntry {
|
||||||
$conf .= "}\n\n";
|
$conf .= "}\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub addBLSEntry {
|
||||||
|
# Creates a Boot Loader Specification[1] entry for a given system.
|
||||||
|
# The information contained in the entry mirrors a boot entry in GRUB menu.
|
||||||
|
#
|
||||||
|
# [1]: https://uapi-group.org/specifications/specs/boot_loader_specification
|
||||||
|
my ($prof, $spec, $gen, $link) = @_;
|
||||||
|
|
||||||
|
# collect data from system
|
||||||
|
my %bootspec = %{decode_json(readFile("$link/boot.json"))->{"org.nixos.bootspec.v1"}};
|
||||||
|
my $date = strftime("%F", localtime(lstat($link)->mtime));
|
||||||
|
my $kernel = $bootspec{kernel} =~ s@$storePath/@@r =~ s@/@-@r;
|
||||||
|
my $initrd = $bootspec{initrd} =~ s@$storePath/@@r =~ s@/@-@r;
|
||||||
|
my $kernelParams = readFile("$link/kernel-params");
|
||||||
|
my $machineId = readFile("/etc/machine-id");
|
||||||
|
|
||||||
|
if ($grubEfi eq "" && !$copyKernels) {
|
||||||
|
# workaround for https://github.com/systemd/systemd/issues/35729
|
||||||
|
make_path("$bootPath/kernels", { mode => 0755 });
|
||||||
|
symlink($bootspec{kernel}, "$bootPath/kernels/$kernel");
|
||||||
|
symlink($bootspec{initrd}, "$bootPath/kernels/$initrd");
|
||||||
|
$copied{"$bootPath/kernels/$kernel"} = 1;
|
||||||
|
$copied{"$bootPath/kernels/$initrd"} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# fill in the entry
|
||||||
|
my $extras = join(' ', $prof = $prof ne "system" ? " [$prof] " : "",
|
||||||
|
$spec = $spec ne "" ? " ($spec) " : "");
|
||||||
|
my $entry = <<~END;
|
||||||
|
title @distroName@$extras
|
||||||
|
sort-key nixos
|
||||||
|
version Generation $gen $bootspec{label}, built on $date
|
||||||
|
linux kernels/$kernel
|
||||||
|
initrd kernels/$initrd
|
||||||
|
options init=$bootspec{init} $kernelParams
|
||||||
|
END
|
||||||
|
$entry .= "machine-id $machineId" if defined $machineId;
|
||||||
|
|
||||||
|
# entry file basename
|
||||||
|
my $name = join("-", grep { length $_ > 0 }
|
||||||
|
"nixos", $prof ne "system" ? $prof : "",
|
||||||
|
"generation", $gen,
|
||||||
|
$spec ? "specialisation-$spec" : "");
|
||||||
|
|
||||||
|
# write entry to the temp directory
|
||||||
|
writeFile("$bootPath/loader/entries.tmp/$name.conf", $entry);
|
||||||
|
|
||||||
|
# mark the default entry
|
||||||
|
if (readlink($link) eq $defaultConfig) {
|
||||||
|
writeFile("$bootPath/loader/loader.conf", "default $name.conf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub addGeneration {
|
sub addGeneration {
|
||||||
my ($name, $nameSuffix, $path, $options, $current) = @_;
|
my ($name, $nameSuffix, $path, $options, $current) = @_;
|
||||||
|
|
||||||
|
@ -592,12 +653,18 @@ sub addProfile {
|
||||||
warn "skipping corrupt system profile entry ‘$link’\n";
|
warn "skipping corrupt system profile entry ‘$link’\n";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
my $gen = nrFromGen($link);
|
||||||
my $date = strftime("%F", localtime(lstat($link)->mtime));
|
my $date = strftime("%F", localtime(lstat($link)->mtime));
|
||||||
my $version =
|
my $version =
|
||||||
-e "$link/nixos-version"
|
-e "$link/nixos-version"
|
||||||
? readFile("$link/nixos-version")
|
? readFile("$link/nixos-version")
|
||||||
: basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]);
|
: basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]);
|
||||||
addGeneration("@distroName@ - Configuration " . nrFromGen($link), " ($date - $version)", $link, $subEntryOptions, 0);
|
addGeneration("@distroName@ - Configuration " . $gen, " ($date - $version)", $link, $subEntryOptions, 0);
|
||||||
|
|
||||||
|
addBLSEntry(basename($profile), "", $gen, $link);
|
||||||
|
foreach my $spec (glob "$link/specialisation/*") {
|
||||||
|
addBLSEntry(basename($profile), $spec, $gen, $spec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$conf .= "}\n";
|
$conf .= "}\n";
|
||||||
|
@ -611,6 +678,12 @@ for my $profile (glob "/nix/var/nix/profiles/system-profiles/*") {
|
||||||
addProfile $profile, "@distroName@ - Profile '$name'";
|
addProfile $profile, "@distroName@ - Profile '$name'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Atomically replace the BLS entries directory
|
||||||
|
my $entriesDir = "$bootPath/loader/entries";
|
||||||
|
rename $entriesDir, "$entriesDir.bak" or die "cannot rename $entriesDir to $entriesDir.bak: $!\n";
|
||||||
|
rename "$entriesDir.tmp", $entriesDir or die "cannot rename $entriesDir.tmp to $entriesDir: $!\n";
|
||||||
|
rmtree "$entriesDir.bak" or die "cannot remove $entriesDir.bak: $!\n";
|
||||||
|
|
||||||
# extraPrepareConfig could refer to @bootPath@, which we have to substitute
|
# extraPrepareConfig could refer to @bootPath@, which we have to substitute
|
||||||
$extraPrepareConfig =~ s/\@bootPath\@/$bootPath/g;
|
$extraPrepareConfig =~ s/\@bootPath\@/$bootPath/g;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue