mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-16 14:54:29 +01:00
nixos/systemd-boot: Add support for an XBOOTLDR partition
This commit is contained in:
parent
04beb0aea2
commit
b470b4432d
4 changed files with 218 additions and 29 deletions
|
@ -279,6 +279,10 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
|||
|
||||
- Cinnamon has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release.
|
||||
|
||||
- New `boot.loader.systemd-boot.xbootldrMountPoint` allows setting up a separate [XBOOTLDR partition](https://uapi-group.org/specifications/specs/boot_loader_specification/) to store boot files. Useful on systems with a small EFI System partition that cannot be easily repartitioned.
|
||||
|
||||
- `boot.loader.systemd-boot` will now verify that `efiSysMountPoint` (and `xbootldrMountPoint` if configured) are mounted partitions.
|
||||
|
||||
- `services.postgresql.extraPlugins` changed its type from just a list of packages to also a function that returns such a list.
|
||||
For example a config line like ``services.postgresql.extraPlugins = with pkgs.postgresql_11.pkgs; [ postgis ];`` is recommended to be changed to ``services.postgresql.extraPlugins = ps: with ps; [ postgis ];``;
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ from dataclasses import dataclass
|
|||
|
||||
# These values will be replaced with actual values during the package build
|
||||
EFI_SYS_MOUNT_POINT = "@efiSysMountPoint@"
|
||||
BOOT_MOUNT_POINT = "@bootMountPoint@"
|
||||
LOADER_CONF = f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf" # Always stored on the ESP
|
||||
NIXOS_DIR = "@nixosDir@"
|
||||
TIMEOUT = "@timeout@"
|
||||
EDITOR = "@editor@" == "1"
|
||||
CONSOLE_MODE = "@consoleMode@"
|
||||
|
@ -28,6 +31,7 @@ CONFIGURATION_LIMIT = int("@configurationLimit@")
|
|||
CAN_TOUCH_EFI_VARIABLES = "@canTouchEfiVariables@"
|
||||
GRACEFUL = "@graceful@"
|
||||
COPY_EXTRA_FILES = "@copyExtraFiles@"
|
||||
CHECK_MOUNTPOINTS = "@checkMountpoints@"
|
||||
|
||||
@dataclass
|
||||
class BootSpec:
|
||||
|
@ -87,7 +91,7 @@ def generation_conf_filename(profile: str | None, generation: int, specialisatio
|
|||
|
||||
|
||||
def write_loader_conf(profile: str | None, generation: int, specialisation: str | None) -> None:
|
||||
with open(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf.tmp", 'w') as f:
|
||||
with open(f"{LOADER_CONF}.tmp", 'w') as f:
|
||||
if TIMEOUT != "":
|
||||
f.write(f"timeout {TIMEOUT}\n")
|
||||
f.write("default %s\n" % generation_conf_filename(profile, generation, specialisation))
|
||||
|
@ -96,7 +100,7 @@ def write_loader_conf(profile: str | None, generation: int, specialisation: str
|
|||
f.write(f"console-mode {CONSOLE_MODE}\n")
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
os.rename(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf.tmp", f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf")
|
||||
os.rename(f"{LOADER_CONF}.tmp", LOADER_CONF)
|
||||
|
||||
|
||||
def get_bootspec(profile: str | None, generation: int) -> BootSpec:
|
||||
|
@ -126,9 +130,9 @@ def copy_from_file(file: str, dry_run: bool = False) -> str:
|
|||
store_file_path = os.path.realpath(file)
|
||||
suffix = os.path.basename(store_file_path)
|
||||
store_dir = os.path.basename(os.path.dirname(store_file_path))
|
||||
efi_file_path = "/efi/nixos/%s-%s.efi" % (store_dir, suffix)
|
||||
efi_file_path = f"{NIXOS_DIR}/{store_dir}-{suffix}.efi"
|
||||
if not dry_run:
|
||||
copy_if_not_exists(store_file_path, f"{EFI_SYS_MOUNT_POINT}%s" % (efi_file_path))
|
||||
copy_if_not_exists(store_file_path, f"{BOOT_MOUNT_POINT}{efi_file_path}")
|
||||
return efi_file_path
|
||||
|
||||
def write_entry(profile: str | None, generation: int, specialisation: str | None,
|
||||
|
@ -145,7 +149,7 @@ def write_entry(profile: str | None, generation: int, specialisation: str | None
|
|||
|
||||
try:
|
||||
if bootspec.initrdSecrets is not None:
|
||||
subprocess.check_call([bootspec.initrdSecrets, f"{EFI_SYS_MOUNT_POINT}%s" % (initrd)])
|
||||
subprocess.check_call([bootspec.initrdSecrets, f"{BOOT_MOUNT_POINT}%s" % (initrd)])
|
||||
except subprocess.CalledProcessError:
|
||||
if current:
|
||||
print("failed to create initrd secrets!", file=sys.stderr)
|
||||
|
@ -155,7 +159,7 @@ def write_entry(profile: str | None, generation: int, specialisation: str | None
|
|||
f'for "{title} - Configuration {generation}", an older generation', file=sys.stderr)
|
||||
print("note: this is normal after having removed "
|
||||
"or renamed a file in `boot.initrd.secrets`", file=sys.stderr)
|
||||
entry_file = f"{EFI_SYS_MOUNT_POINT}/loader/entries/%s" % (
|
||||
entry_file = f"{BOOT_MOUNT_POINT}/loader/entries/%s" % (
|
||||
generation_conf_filename(profile, generation, specialisation))
|
||||
tmp_path = "%s.tmp" % (entry_file)
|
||||
kernel_params = "init=%s " % bootspec.init
|
||||
|
@ -202,14 +206,14 @@ def get_generations(profile: str | None = None) -> list[SystemIdentifier]:
|
|||
|
||||
|
||||
def remove_old_entries(gens: list[SystemIdentifier]) -> None:
|
||||
rex_profile = re.compile(r"^" + re.escape(EFI_SYS_MOUNT_POINT) + "/loader/entries/nixos-(.*)-generation-.*\.conf$")
|
||||
rex_generation = re.compile(r"^" + re.escape(EFI_SYS_MOUNT_POINT) + "/loader/entries/nixos.*-generation-([0-9]+)(-specialisation-.*)?\.conf$")
|
||||
rex_profile = re.compile(r"^" + re.escape(BOOT_MOUNT_POINT) + "/loader/entries/nixos-(.*)-generation-.*\.conf$")
|
||||
rex_generation = re.compile(r"^" + re.escape(BOOT_MOUNT_POINT) + "/loader/entries/nixos.*-generation-([0-9]+)(-specialisation-.*)?\.conf$")
|
||||
known_paths = []
|
||||
for gen in gens:
|
||||
bootspec = get_bootspec(gen.profile, gen.generation)
|
||||
known_paths.append(copy_from_file(bootspec.kernel, True))
|
||||
known_paths.append(copy_from_file(bootspec.initrd, True))
|
||||
for path in glob.iglob(f"{EFI_SYS_MOUNT_POINT}/loader/entries/nixos*-generation-[1-9]*.conf"):
|
||||
for path in glob.iglob(f"{BOOT_MOUNT_POINT}/loader/entries/nixos*-generation-[1-9]*.conf"):
|
||||
if rex_profile.match(path):
|
||||
prof = rex_profile.sub(r"\1", path)
|
||||
else:
|
||||
|
@ -220,11 +224,18 @@ def remove_old_entries(gens: list[SystemIdentifier]) -> None:
|
|||
continue
|
||||
if not (prof, gen_number, None) in gens:
|
||||
os.unlink(path)
|
||||
for path in glob.iglob(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/*"):
|
||||
for path in glob.iglob(f"{BOOT_MOUNT_POINT}/{NIXOS_DIR}/*"):
|
||||
if not path in known_paths and not os.path.isdir(path):
|
||||
os.unlink(path)
|
||||
|
||||
|
||||
def cleanup_esp() -> None:
|
||||
for path in glob.iglob(f"{EFI_SYS_MOUNT_POINT}/loader/entries/nixos*"):
|
||||
os.unlink(path)
|
||||
if os.path.isdir(f"{EFI_SYS_MOUNT_POINT}/{NIXOS_DIR}"):
|
||||
shutil.rmtree(f"{EFI_SYS_MOUNT_POINT}/{NIXOS_DIR}")
|
||||
|
||||
|
||||
def get_profiles() -> list[str]:
|
||||
if os.path.isdir("/nix/var/nix/profiles/system-profiles/"):
|
||||
return [x
|
||||
|
@ -255,6 +266,9 @@ def install_bootloader(args: argparse.Namespace) -> None:
|
|||
# flags to pass to bootctl install/update
|
||||
bootctl_flags = []
|
||||
|
||||
if BOOT_MOUNT_POINT != EFI_SYS_MOUNT_POINT:
|
||||
bootctl_flags.append(f"--boot-path={BOOT_MOUNT_POINT}")
|
||||
|
||||
if CAN_TOUCH_EFI_VARIABLES != "1":
|
||||
bootctl_flags.append("--no-variables")
|
||||
|
||||
|
@ -263,8 +277,8 @@ def install_bootloader(args: argparse.Namespace) -> None:
|
|||
|
||||
if os.getenv("NIXOS_INSTALL_BOOTLOADER") == "1":
|
||||
# bootctl uses fopen() with modes "wxe" and fails if the file exists.
|
||||
if os.path.exists(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf"):
|
||||
os.unlink(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf")
|
||||
if os.path.exists(LOADER_CONF):
|
||||
os.unlink(LOADER_CONF)
|
||||
|
||||
subprocess.check_call([f"{SYSTEMD}/bin/bootctl", f"--esp-path={EFI_SYS_MOUNT_POINT}"] + bootctl_flags + ["install"])
|
||||
else:
|
||||
|
@ -291,13 +305,15 @@ def install_bootloader(args: argparse.Namespace) -> None:
|
|||
print("updating systemd-boot from %s to %s" % (installed_version, available_version))
|
||||
subprocess.check_call([f"{SYSTEMD}/bin/bootctl", f"--esp-path={EFI_SYS_MOUNT_POINT}"] + bootctl_flags + ["update"])
|
||||
|
||||
os.makedirs(f"{EFI_SYS_MOUNT_POINT}/efi/nixos", exist_ok=True)
|
||||
os.makedirs(f"{EFI_SYS_MOUNT_POINT}/loader/entries", exist_ok=True)
|
||||
os.makedirs(f"{BOOT_MOUNT_POINT}/{NIXOS_DIR}", exist_ok=True)
|
||||
os.makedirs(f"{BOOT_MOUNT_POINT}/loader/entries", exist_ok=True)
|
||||
|
||||
gens = get_generations()
|
||||
for profile in get_profiles():
|
||||
gens += get_generations(profile)
|
||||
|
||||
remove_old_entries(gens)
|
||||
|
||||
for gen in gens:
|
||||
try:
|
||||
bootspec = get_bootspec(gen.profile, gen.generation)
|
||||
|
@ -315,9 +331,15 @@ def install_bootloader(args: argparse.Namespace) -> None:
|
|||
else:
|
||||
raise e
|
||||
|
||||
for root, _, files in os.walk(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/.extra-files", topdown=False):
|
||||
relative_root = root.removeprefix(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/.extra-files").removeprefix("/")
|
||||
actual_root = os.path.join(f"{EFI_SYS_MOUNT_POINT}", relative_root)
|
||||
if BOOT_MOUNT_POINT != EFI_SYS_MOUNT_POINT:
|
||||
# Cleanup any entries in ESP if xbootldrMountPoint is set.
|
||||
# If the user later unsets xbootldrMountPoint, entries in XBOOTLDR will not be cleaned up
|
||||
# automatically, as we don't have information about the mount point anymore.
|
||||
cleanup_esp()
|
||||
|
||||
for root, _, files in os.walk(f"{BOOT_MOUNT_POINT}/{NIXOS_DIR}/.extra-files", topdown=False):
|
||||
relative_root = root.removeprefix(f"{BOOT_MOUNT_POINT}/{NIXOS_DIR}/.extra-files").removeprefix("/")
|
||||
actual_root = os.path.join(f"{BOOT_MOUNT_POINT}", relative_root)
|
||||
|
||||
for file in files:
|
||||
actual_file = os.path.join(actual_root, file)
|
||||
|
@ -330,7 +352,7 @@ def install_bootloader(args: argparse.Namespace) -> None:
|
|||
os.rmdir(actual_root)
|
||||
os.rmdir(root)
|
||||
|
||||
os.makedirs(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/.extra-files", exist_ok=True)
|
||||
os.makedirs(f"{BOOT_MOUNT_POINT}/{NIXOS_DIR}/.extra-files", exist_ok=True)
|
||||
|
||||
subprocess.check_call(COPY_EXTRA_FILES)
|
||||
|
||||
|
@ -340,6 +362,8 @@ def main() -> None:
|
|||
parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help=f"The default {DISTRO_NAME} config to boot")
|
||||
args = parser.parse_args()
|
||||
|
||||
subprocess.check_call(CHECK_MOUNTPOINTS)
|
||||
|
||||
try:
|
||||
install_bootloader(args)
|
||||
finally:
|
||||
|
@ -347,9 +371,14 @@ def main() -> None:
|
|||
# it can leave the system in an unbootable state, when a crash/outage
|
||||
# happens shortly after an update. To decrease the likelihood of this
|
||||
# event sync the efi filesystem after each update.
|
||||
rc = libc.syncfs(os.open(f"{EFI_SYS_MOUNT_POINT}", os.O_RDONLY))
|
||||
rc = libc.syncfs(os.open(f"{BOOT_MOUNT_POINT}", os.O_RDONLY))
|
||||
if rc != 0:
|
||||
print(f"could not sync {EFI_SYS_MOUNT_POINT}: {os.strerror(rc)}", file=sys.stderr)
|
||||
print(f"could not sync {BOOT_MOUNT_POINT}: {os.strerror(rc)}", file=sys.stderr)
|
||||
|
||||
if BOOT_MOUNT_POINT != EFI_SYS_MOUNT_POINT:
|
||||
rc = libc.syncfs(os.open(EFI_SYS_MOUNT_POINT, os.O_RDONLY))
|
||||
if rc != 0:
|
||||
print(f"could not sync {EFI_SYS_MOUNT_POINT}: {os.strerror(rc)}", file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -7,7 +7,7 @@ let
|
|||
|
||||
efi = config.boot.loader.efi;
|
||||
|
||||
systemdBootBuilder = pkgs.substituteAll {
|
||||
systemdBootBuilder = pkgs.substituteAll rec {
|
||||
src = ./systemd-boot-builder.py;
|
||||
|
||||
isExecutable = true;
|
||||
|
@ -28,23 +28,40 @@ let
|
|||
|
||||
inherit (efi) efiSysMountPoint canTouchEfiVariables;
|
||||
|
||||
bootMountPoint = if cfg.xbootldrMountPoint != null
|
||||
then cfg.xbootldrMountPoint
|
||||
else efi.efiSysMountPoint;
|
||||
|
||||
nixosDir = "/EFI/nixos";
|
||||
|
||||
inherit (config.system.nixos) distroName;
|
||||
|
||||
memtest86 = optionalString cfg.memtest86.enable pkgs.memtest86plus;
|
||||
|
||||
netbootxyz = optionalString cfg.netbootxyz.enable pkgs.netbootxyz-efi;
|
||||
|
||||
checkMountpoints = pkgs.writeShellScript "check-mountpoints" ''
|
||||
fail() {
|
||||
echo "$1 = '$2' is not a mounted partition. Is the path configured correctly?" >&2
|
||||
exit 1
|
||||
}
|
||||
${pkgs.util-linuxMinimal}/bin/findmnt ${efiSysMountPoint} > /dev/null || fail efiSysMountPoint ${efiSysMountPoint}
|
||||
${lib.optionalString
|
||||
(cfg.xbootldrMountPoint != null)
|
||||
"${pkgs.util-linuxMinimal}/bin/findmnt ${cfg.xbootldrMountPoint} > /dev/null || fail xbootldrMountPoint ${cfg.xbootldrMountPoint}"}
|
||||
'';
|
||||
|
||||
copyExtraFiles = pkgs.writeShellScript "copy-extra-files" ''
|
||||
empty_file=$(${pkgs.coreutils}/bin/mktemp)
|
||||
|
||||
${concatStrings (mapAttrsToList (n: v: ''
|
||||
${pkgs.coreutils}/bin/install -Dp "${v}" "${efi.efiSysMountPoint}/"${escapeShellArg n}
|
||||
${pkgs.coreutils}/bin/install -D $empty_file "${efi.efiSysMountPoint}/efi/nixos/.extra-files/"${escapeShellArg n}
|
||||
${pkgs.coreutils}/bin/install -Dp "${v}" "${bootMountPoint}/"${escapeShellArg n}
|
||||
${pkgs.coreutils}/bin/install -D $empty_file "${bootMountPoint}/${nixosDir}/.extra-files/"${escapeShellArg n}
|
||||
'') cfg.extraFiles)}
|
||||
|
||||
${concatStrings (mapAttrsToList (n: v: ''
|
||||
${pkgs.coreutils}/bin/install -Dp "${pkgs.writeText n v}" "${efi.efiSysMountPoint}/loader/entries/"${escapeShellArg n}
|
||||
${pkgs.coreutils}/bin/install -D $empty_file "${efi.efiSysMountPoint}/efi/nixos/.extra-files/loader/entries/"${escapeShellArg n}
|
||||
${pkgs.coreutils}/bin/install -Dp "${pkgs.writeText n v}" "${bootMountPoint}/loader/entries/"${escapeShellArg n}
|
||||
${pkgs.coreutils}/bin/install -D $empty_file "${bootMountPoint}/${nixosDir}/.extra-files/loader/entries/"${escapeShellArg n}
|
||||
'') cfg.extraEntries)}
|
||||
'';
|
||||
};
|
||||
|
@ -99,6 +116,18 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
xbootldrMountPoint = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = lib.mdDoc ''
|
||||
Where the XBOOTLDR partition is mounted.
|
||||
|
||||
If set, this partition will be used as $BOOT to store boot loader entries and extra files
|
||||
instead of the EFI partition. As per the bootloader specification, it is recommended that
|
||||
the EFI and XBOOTLDR partitions be mounted at `/efi` and `/boot`, respectively.
|
||||
'';
|
||||
};
|
||||
|
||||
configurationLimit = mkOption {
|
||||
default = null;
|
||||
example = 120;
|
||||
|
@ -108,7 +137,7 @@ in {
|
|||
Useful to prevent boot partition running out of disk space.
|
||||
|
||||
`null` means no limit i.e. all generations
|
||||
that were not garbage collected yet.
|
||||
that have not been garbage collected yet.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -200,7 +229,7 @@ in {
|
|||
'';
|
||||
description = lib.mdDoc ''
|
||||
Any additional entries you want added to the `systemd-boot` menu.
|
||||
These entries will be copied to {file}`/boot/loader/entries`.
|
||||
These entries will be copied to {file}`$BOOT/loader/entries`.
|
||||
Each attribute name denotes the destination file name,
|
||||
and the corresponding attribute value is the contents of the entry.
|
||||
|
||||
|
@ -217,9 +246,9 @@ in {
|
|||
{ "efi/memtest86/memtest.efi" = "''${pkgs.memtest86plus}/memtest.efi"; }
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
A set of files to be copied to {file}`/boot`.
|
||||
A set of files to be copied to {file}`$BOOT`.
|
||||
Each attribute name denotes the destination file name in
|
||||
{file}`/boot`, while the corresponding
|
||||
{file}`$BOOT`, while the corresponding
|
||||
attribute value specifies the source file.
|
||||
'';
|
||||
};
|
||||
|
@ -243,6 +272,18 @@ in {
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = (hasPrefix "/" efi.efiSysMountPoint);
|
||||
message = "The ESP mount point '${efi.efiSysMountPoint}' must be an absolute path";
|
||||
}
|
||||
{
|
||||
assertion = cfg.xbootldrMountPoint == null || (hasPrefix "/" cfg.xbootldrMountPoint);
|
||||
message = "The XBOOTLDR mount point '${cfg.xbootldrMountPoint}' must be an absolute path";
|
||||
}
|
||||
{
|
||||
assertion = cfg.xbootldrMountPoint != efi.efiSysMountPoint;
|
||||
message = "The XBOOTLDR mount point '${cfg.xbootldrMountPoint}' cannot be the same as the ESP mount point '${efi.efiSysMountPoint}'";
|
||||
}
|
||||
{
|
||||
assertion = (config.boot.kernelPackages.kernel.features or { efiBootStub = true; }) ? efiBootStub;
|
||||
message = "This kernel does not support the EFI boot stub";
|
||||
|
|
|
@ -14,6 +14,72 @@ let
|
|||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
environment.systemPackages = [ pkgs.efibootmgr ];
|
||||
};
|
||||
|
||||
commonXbootldr = { config, lib, pkgs, ... }:
|
||||
let
|
||||
diskImage = import ../lib/make-disk-image.nix {
|
||||
inherit config lib pkgs;
|
||||
label = "nixos";
|
||||
format = "qcow2";
|
||||
partitionTableType = "efixbootldr";
|
||||
touchEFIVars = true;
|
||||
installBootLoader = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [ common ];
|
||||
virtualisation.useBootLoader = lib.mkForce false; # Only way to tell qemu-vm not to create the default system image
|
||||
virtualisation.directBoot.enable = false; # But don't direct boot either because we're testing systemd-boot
|
||||
|
||||
system.build.diskImage = diskImage; # Use custom disk image with an XBOOTLDR partition
|
||||
virtualisation.efi.variables = "${diskImage}/efi-vars.fd";
|
||||
|
||||
virtualisation.useDefaultFilesystems = false; # Needs custom setup for `diskImage`
|
||||
virtualisation.bootPartition = null;
|
||||
virtualisation.fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/vda3";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/boot" = {
|
||||
device = "/dev/vda2";
|
||||
fsType = "vfat";
|
||||
noCheck = true;
|
||||
};
|
||||
"/efi" = {
|
||||
device = "/dev/vda1";
|
||||
fsType = "vfat";
|
||||
noCheck = true;
|
||||
};
|
||||
};
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.efiSysMountPoint = "/efi";
|
||||
boot.loader.systemd-boot.xbootldrMountPoint = "/boot";
|
||||
};
|
||||
|
||||
customDiskImage = nodes: ''
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
tmp_disk_image = tempfile.NamedTemporaryFile()
|
||||
|
||||
subprocess.run([
|
||||
"${nodes.machine.virtualisation.qemu.package}/bin/qemu-img",
|
||||
"create",
|
||||
"-f",
|
||||
"qcow2",
|
||||
"-b",
|
||||
"${nodes.machine.system.build.diskImage}/nixos.qcow2",
|
||||
"-F",
|
||||
"qcow2",
|
||||
tmp_disk_image.name,
|
||||
])
|
||||
|
||||
# Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
|
||||
os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
|
||||
'';
|
||||
in
|
||||
{
|
||||
basic = makeTest {
|
||||
|
@ -65,6 +131,32 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
basicXbootldr = makeTest {
|
||||
name = "systemd-boot-xbootldr";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ sdht0 ];
|
||||
|
||||
nodes.machine = commonXbootldr;
|
||||
|
||||
testScript = { nodes, ... }: ''
|
||||
${customDiskImage nodes}
|
||||
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("test -e /efi/EFI/systemd/systemd-bootx64.efi")
|
||||
machine.succeed("test -e /boot/loader/entries/nixos-generation-1.conf")
|
||||
|
||||
# Ensure we actually booted using systemd-boot
|
||||
# Magic number is the vendor UUID used by systemd-boot.
|
||||
machine.succeed(
|
||||
"test -e /sys/firmware/efi/efivars/LoaderEntrySelected-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"
|
||||
)
|
||||
|
||||
# "bootctl install" should have created an EFI entry
|
||||
machine.succeed('efibootmgr | grep "Linux Boot Manager"')
|
||||
'';
|
||||
};
|
||||
|
||||
# Check that specialisations create corresponding boot entries.
|
||||
specialisation = makeTest {
|
||||
name = "systemd-boot-specialisation";
|
||||
|
@ -184,6 +276,29 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
entryFilenameXbootldr = makeTest {
|
||||
name = "systemd-boot-entry-filename-xbootldr";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ sdht0 ];
|
||||
|
||||
nodes.machine = { pkgs, lib, ... }: {
|
||||
imports = [ commonXbootldr ];
|
||||
boot.loader.systemd-boot.memtest86.enable = true;
|
||||
boot.loader.systemd-boot.memtest86.entryFilename = "apple.conf";
|
||||
};
|
||||
|
||||
testScript = { nodes, ... }: ''
|
||||
${customDiskImage nodes}
|
||||
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("test -e /efi/EFI/systemd/systemd-bootx64.efi")
|
||||
machine.fail("test -e /boot/loader/entries/memtest86.conf")
|
||||
machine.succeed("test -e /boot/loader/entries/apple.conf")
|
||||
machine.succeed("test -e /boot/EFI/memtest86/memtest.efi")
|
||||
'';
|
||||
};
|
||||
|
||||
extraEntries = makeTest {
|
||||
name = "systemd-boot-extra-entries";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ Enzime julienmalka ];
|
||||
|
|
Loading…
Reference in a new issue