diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index f48a085ce57a..d8baed65c6df 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -47,9 +47,9 @@ def write_loader_conf(profile, generation): if "@timeout@" != "": f.write("timeout @timeout@\n") if profile: - f.write("default nixos-%s-generation-%d\n" % (profile, generation)) + f.write("default nixos-%s-generation-%d.conf\n".format(profile, generation)) else: - f.write("default nixos-generation-%d\n" % (generation)) + f.write("default nixos-generation-%d.conf\n".format(generation)) if not @editor@: f.write("editor 0\n"); f.write("console-mode @consoleMode@\n"); @@ -197,6 +197,22 @@ def main(): subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "install"]) else: subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "--no-variables", "install"]) + else: + # Update bootloader to latest if needed + systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[1] + sdboot_status = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True) + + # See status_binaries() in systemd bootctl.c for code which generates this + m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot (\d+)\)$", + sdboot_status, re.IGNORECASE | re.MULTILINE) + if m is None: + print("could not find any previously installed systemd-boot") + else: + sdboot_version = m.group(2) + if systemd_version > sdboot_version: + print("updating systemd-boot from %s to %s" % (sdboot_version, systemd_version)) + subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"]) + mkdir_p("@efiSysMountPoint@/efi/nixos") mkdir_p("@efiSysMountPoint@/loader/entries") diff --git a/nixos/tests/systemd-boot.nix b/nixos/tests/systemd-boot.nix index e911c3933616..eba4729d6de8 100644 --- a/nixos/tests/systemd-boot.nix +++ b/nixos/tests/systemd-boot.nix @@ -6,26 +6,53 @@ with import ../lib/testing-python.nix { inherit system pkgs; }; with pkgs.lib; -makeTest { - name = "systemd-boot"; - meta.maintainers = with pkgs.stdenv.lib.maintainers; [ danielfullmer ]; - - machine = { pkgs, lib, ... }: { +let + common = { virtualisation.useBootLoader = true; virtualisation.useEFIBoot = true; boot.loader.systemd-boot.enable = true; }; +in +{ + basic = makeTest { + name = "systemd-boot"; + meta.maintainers = with pkgs.stdenv.lib.maintainers; [ danielfullmer ]; - testScript = '' - machine.start() - machine.wait_for_unit("multi-user.target") + machine = common; - machine.succeed("test -e /boot/loader/entries/nixos-generation-1.conf") + testScript = '' + machine.start() + machine.wait_for_unit("multi-user.target") - # 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" - ) - ''; + 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" + ) + ''; + }; + + update = makeTest { + name = "systemd-boot-update"; + meta.maintainers = with pkgs.stdenv.lib.maintainers; [ danielfullmer ]; + + machine = common; + + testScript = '' + machine.succeed("mount -o remount,rw /boot") + + # Replace version inside sd-boot with something older. See magic[] string in systemd src/boot/efi/boot.c + machine.succeed( + """ + find /boot -iname '*.efi' -print0 | \ + xargs -0 -I '{}' sed -i 's/#### LoaderInfo: systemd-boot .* ####/#### LoaderInfo: systemd-boot 001 ####/' '{}' + """ + ) + + output = machine.succeed("/run/current-system/bin/switch-to-configuration boot") + assert "updating systemd-boot from 001 to " in output + ''; + }; }