Allow to pass extra initrd archives to the bootloader (#534265)
This commit is contained in:
@@ -1914,6 +1914,7 @@
|
||||
./system/boot/clevis-luks-askpass.nix
|
||||
./system/boot/clevis.nix
|
||||
./system/boot/emergency-mode.nix
|
||||
./system/boot/extra-initrd.nix
|
||||
./system/boot/grow-partition.nix
|
||||
./system/boot/initrd-network.nix
|
||||
./system/boot/initrd-openvpn.nix
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
options.system.boot.extraInitrd = {
|
||||
paths = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of paths relative to the ESP that are combined with the NixOS
|
||||
main initrd before being passed to the kernel.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
boot.bootspec.extensions = lib.mkIf (config.system.boot.extraInitrd.paths != [ ]) {
|
||||
"org.nixos.extra-initrd.v1" = {
|
||||
inherit (config.system.boot.extraInitrd) paths;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -205,6 +205,17 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
extraInstallCommands = lib.mkOption {
|
||||
default = "";
|
||||
type = lib.types.lines;
|
||||
description = ''
|
||||
Additional shell commands inserted in the bootloader installer
|
||||
script after generating menu entries. It can be used to expand
|
||||
on extra boot entries that cannot incorporate certain pieces of
|
||||
information (such as the resulting `init=` kernel parameter).
|
||||
'';
|
||||
};
|
||||
|
||||
secureBoot = {
|
||||
enable = lib.mkEnableOption null // {
|
||||
description = ''
|
||||
@@ -443,14 +454,25 @@ in
|
||||
|
||||
system = {
|
||||
boot.loader.id = "limine";
|
||||
build.installBootLoader = pkgs.replaceVarsWith {
|
||||
src = ./limine-install.py;
|
||||
isExecutable = true;
|
||||
replacements = {
|
||||
python3 = pkgs.python3.withPackages (python-packages: [ python-packages.psutil ]);
|
||||
configPath = limineInstallConfig;
|
||||
};
|
||||
};
|
||||
build.installBootLoader =
|
||||
let
|
||||
install = pkgs.replaceVarsWith {
|
||||
src = ./limine-install.py;
|
||||
isExecutable = true;
|
||||
replacements = {
|
||||
python3 = pkgs.python3.withPackages (python-packages: [ python-packages.psutil ]);
|
||||
configPath = limineInstallConfig;
|
||||
};
|
||||
};
|
||||
|
||||
final = pkgs.writeScript "limine-install.sh" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
set -euo pipefail
|
||||
${install} "$@"
|
||||
${cfg.extraInstallCommands}
|
||||
'';
|
||||
in
|
||||
final;
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.enable && cfg.secureBoot.enable) {
|
||||
|
||||
@@ -45,6 +45,7 @@ BOOT_COUNTING = "@bootCounting@" == "True"
|
||||
class BootSpec:
|
||||
init: Path
|
||||
initrd: Path
|
||||
extraInitrdPaths: list[Path]
|
||||
kernel: Path
|
||||
kernelParams: list[str] # noqa: N815
|
||||
label: str
|
||||
@@ -306,9 +307,7 @@ def get_bootspec(profile: str | None, generation: int) -> BootSpec | None:
|
||||
try:
|
||||
bootspec_json = json.load(f)
|
||||
except ValueError as e:
|
||||
print(
|
||||
f"error: Malformed Json: {e}, in {boot_json_path}", file=sys.stderr
|
||||
)
|
||||
print(f"error: Malformed Json: {e}, in {boot_json_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return bootspec_from_json(bootspec_json)
|
||||
|
||||
@@ -320,6 +319,11 @@ def bootspec_from_json(bootspec_json: dict[str, Any]) -> BootSpec:
|
||||
sortKey = systemdBootExtension.get("sortKey", "nixos")
|
||||
devicetree = systemdBootExtension.get("devicetree")
|
||||
|
||||
extraInitrdExtension = bootspec_json.get("org.nixos.extra-initrd.v1", {})
|
||||
extraInitrdPaths = list(
|
||||
map(lambda path: Path(path), extraInitrdExtension.get("paths", []))
|
||||
)
|
||||
|
||||
if devicetree:
|
||||
devicetree = Path(devicetree)
|
||||
|
||||
@@ -332,6 +336,7 @@ def bootspec_from_json(bootspec_json: dict[str, Any]) -> BootSpec:
|
||||
specialisations=specialisations,
|
||||
sortKey=sortKey,
|
||||
devicetree=devicetree,
|
||||
extraInitrdPaths=extraInitrdPaths,
|
||||
)
|
||||
|
||||
|
||||
@@ -374,16 +379,21 @@ def boot_file(
|
||||
specialisation=" (%s)" % specialisation if specialisation else "",
|
||||
)
|
||||
description = f"Generation {generation} {bootspec.label}, built on {build_date}"
|
||||
boot_entry = [
|
||||
f"title {title}",
|
||||
f"version {description}",
|
||||
f"linux /{str(kernel.path)}",
|
||||
f"initrd /{str(initrd.path)}",
|
||||
f"options {kernel_params}",
|
||||
f"machine-id {machine_id}" if machine_id is not None else None,
|
||||
f"devicetree /{str(devicetree.path)}" if devicetree is not None else None,
|
||||
f"sort-key {bootspec.sortKey}",
|
||||
]
|
||||
boot_entry = (
|
||||
[
|
||||
f"title {title}",
|
||||
f"version {description}",
|
||||
f"linux /{str(kernel.path)}",
|
||||
f"initrd /{str(initrd.path)}",
|
||||
]
|
||||
+ list(map(lambda initrd: f"initrd /{initrd}", bootspec.extraInitrdPaths))
|
||||
+ [
|
||||
f"options {kernel_params}",
|
||||
f"machine-id {machine_id}" if machine_id is not None else None,
|
||||
f"devicetree /{str(devicetree.path)}" if devicetree is not None else None,
|
||||
f"sort-key {bootspec.sortKey}",
|
||||
]
|
||||
)
|
||||
contents = "\n".join(filter(None, boot_entry))
|
||||
entry, bootctl_id = BootFile.from_entry(contents.encode("utf-8"))
|
||||
return (list(filter(None, [kernel, initrd, devicetree, entry])), bootctl_id)
|
||||
|
||||
@@ -554,6 +554,9 @@ in
|
||||
etebase-server = runTest ./etebase-server.nix;
|
||||
etesync-dav = runTest ./etesync-dav.nix;
|
||||
evcc = runTest ./evcc.nix;
|
||||
extra-initrd = import ./extra-initrd.nix {
|
||||
inherit runTest pkgs;
|
||||
};
|
||||
facter = runTest ./facter;
|
||||
fail2ban = runTest ./fail2ban.nix;
|
||||
fakeroute = runTest ./fakeroute.nix;
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
{
|
||||
runTest,
|
||||
...
|
||||
}:
|
||||
let
|
||||
common =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
virtualisation.useBootLoader = true;
|
||||
virtualisation.useEFIBoot = true;
|
||||
system.boot.extraInitrd.paths = [
|
||||
extraInitrdPath
|
||||
];
|
||||
|
||||
boot.loader.timeout = 2;
|
||||
|
||||
boot.initrd.systemd.mounts = [
|
||||
{
|
||||
what = "/canary.txt";
|
||||
where = "/sysroot/run/canary.txt";
|
||||
type = "none";
|
||||
options = "bind";
|
||||
unitConfig = {
|
||||
DefaultDependencies = false;
|
||||
};
|
||||
requiredBy = [ "initrd-fs.target" ];
|
||||
before = [ "initrd-fs.target" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
extraInitrdPath = "custom.cpio";
|
||||
canaryCpio =
|
||||
pkgs:
|
||||
pkgs.runCommand "canary.cpio"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.cpio ];
|
||||
}
|
||||
''
|
||||
echo canary > canary.txt
|
||||
find . -print0 | cpio --null -o --format=newc > $out
|
||||
'';
|
||||
|
||||
testScript =
|
||||
# python
|
||||
''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
# Check that the extra cpio archive is on the ESP
|
||||
machine.succeed("test -e /boot/custom.cpio")
|
||||
|
||||
# Check that the initrd that we booted with contained the file from
|
||||
# the extra initrd and our initrd mount unit bound it into sysroot
|
||||
assert machine.succeed("cat /run/canary.txt").strip() == "canary"
|
||||
'';
|
||||
in
|
||||
{
|
||||
systemd-boot = runTest (
|
||||
{ pkgs, ... }: {
|
||||
name = "systemd-boot-extra-initrd";
|
||||
|
||||
nodes.machine = { config, ... }: {
|
||||
imports = [ common ];
|
||||
|
||||
boot.loader.systemd-boot = {
|
||||
enable = true;
|
||||
extraInstallCommands = ''
|
||||
cp ${canaryCpio pkgs} ${config.boot.loader.efi.efiSysMountPoint}/${extraInitrdPath}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
inherit testScript;
|
||||
}
|
||||
);
|
||||
|
||||
limine = runTest {
|
||||
name = "limine-extra-initrd";
|
||||
|
||||
nodes.machine = { pkgs, config, ... }: {
|
||||
imports = [ common ];
|
||||
|
||||
boot.loader.limine = {
|
||||
enable = true;
|
||||
efiSupport = true;
|
||||
enableEditor = true;
|
||||
extraInstallCommands = ''
|
||||
cp ${canaryCpio pkgs} ${config.boot.loader.efi.efiSysMountPoint}/${extraInitrdPath}
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inherit testScript;
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
# Derivation containing the Limine host tool and the compiled bootloader
|
||||
{
|
||||
fetchpatch,
|
||||
fetchurl,
|
||||
lib,
|
||||
llvmPackages,
|
||||
@@ -57,6 +58,16 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
hash = "sha256-8aUp2lzVClyje6WHMTOnuOclhLEn1zMf6U5VTl5gEvc=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Merged upstream in https://github.com/Limine-Bootloader/Limine/pull/599,
|
||||
# remove on the next release.
|
||||
(fetchpatch {
|
||||
name = "align-linux-modules.patch";
|
||||
url = "https://github.com/Limine-Bootloader/Limine/commit/6635ae4ff2321f9a3c85116a57a00e3b6edc100b.patch";
|
||||
hash = "sha256-poAcZND5xwS8npHCytS9lwcQi9oCEcc4bR+6HKVXJ78=";
|
||||
})
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
hardeningDisable = lib.optionals missingZerocallusedregs [
|
||||
|
||||
Reference in New Issue
Block a user