Loading nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +12 −3 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ class BootSpec: toplevel: str specialisations: dict[str, "BootSpec"] sortKey: str # noqa: N815 devicetree: str | None = None # noqa: N815 initrdSecrets: str | None = None # noqa: N815 @dataclass Loading Loading @@ -85,6 +86,7 @@ class DiskEntry: kernel_params: str | None machine_id: str | None sort_key: str devicetree: str | None @classmethod def from_path(cls: Type["DiskEntry"], path: Path) -> "DiskEntry": Loading @@ -109,7 +111,9 @@ class DiskEntry: initrd=entry_map["initrd"], kernel_params=entry_map.get("options"), machine_id=entry_map.get("machine-id"), sort_key=entry_map.get("sort_key", "nixos")) sort_key=entry_map.get("sort_key", "nixos"), devicetree=entry_map.get("devicetree"), ) return disk_entry def write(self, sorted_first: str) -> None: Loading @@ -128,7 +132,8 @@ class DiskEntry: f"initrd {self.initrd}", f"options {self.kernel_params}" if self.kernel_params is not None else None, f"machine-id {self.machine_id}" if self.machine_id is not None else None, f"sort-key {default_sort_key if self.default else self.sort_key}" f"sort-key {default_sort_key if self.default else self.sort_key}", f"devicetree {self.devicetree}" if self.devicetree is not None else None, ] f.write("\n".join(filter(None, boot_entry))) Loading Loading @@ -236,10 +241,12 @@ def bootspec_from_json(bootspec_json: dict[str, Any]) -> BootSpec: specialisations = {k: bootspec_from_json(v) for k, v in specialisations.items()} systemdBootExtension = bootspec_json.get('org.nixos.systemd-boot', {}) sortKey = systemdBootExtension.get('sortKey', 'nixos') devicetree = systemdBootExtension.get('devicetree') return BootSpec( **bootspec_json['org.nixos.bootspec.v1'], specialisations=specialisations, sortKey=sortKey sortKey=sortKey, devicetree=devicetree, ) Loading @@ -264,6 +271,7 @@ def write_entry(profile: str | None, bootspec = bootspec.specialisations[specialisation] kernel = copy_from_file(bootspec.kernel) initrd = copy_from_file(bootspec.initrd) devicetree = copy_from_file(bootspec.devicetree) if bootspec.devicetree is not None else None title = "{name}{profile}{specialisation}".format( name=DISTRO_NAME, Loading Loading @@ -306,6 +314,7 @@ def write_entry(profile: str | None, machine_id=machine_id, description=f"Generation {generation} {bootspec.label}, built on {build_date}", sort_key=bootspec.sortKey, devicetree=devicetree, default=current ).write(sorted_first) Loading nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix +14 −0 Original line number Diff line number Diff line Loading @@ -191,6 +191,15 @@ in { ''; }; installDeviceTree = mkOption { default = with config.hardware.deviceTree; enable && name != null; defaultText = ''with config.hardware.deviceTree; enable && name != null''; description = '' Install the devicetree blob specified by `config.hardware.deviceTree.name` to the ESP and instruct systemd-boot to pass this DTB to linux. ''; }; extraInstallCommands = mkOption { default = ""; example = '' Loading Loading @@ -369,6 +378,10 @@ in { assertion = (config.boot.kernelPackages.kernel.features or { efiBootStub = true; }) ? efiBootStub; message = "This kernel does not support the EFI boot stub"; } { assertion = cfg.installDeviceTree -> config.hardware.deviceTree.enable -> config.hardware.deviceTree.name != null; message = "Cannot install devicetree without 'config.hardware.deviceTree.enable' enabled and 'config.hardware.deviceTree.name' set"; } ] ++ concatMap (filename: [ { assertion = !(hasInfix "/" filename); Loading Loading @@ -426,6 +439,7 @@ in { boot.bootspec.extensions."org.nixos.systemd-boot" = { inherit (config.boot.loader.systemd-boot) sortKey; devicetree = lib.mkIf cfg.installDeviceTree "${config.hardware.deviceTree.package}/${config.hardware.deviceTree.name}"; }; system = { Loading nixos/tests/systemd-boot.nix +18 −1 Original line number Diff line number Diff line Loading @@ -172,10 +172,23 @@ rec { imports = [ common ]; specialisation.something.configuration = { boot.loader.systemd-boot.sortKey = "something"; # Since qemu will dynamically create a devicetree blob when starting # up, it is not straight forward to create an export of that devicetree # blob without knowing before-hand all the flags we would pass to qemu # (we would then be able to use `dumpdtb`). Thus, the following config # will not boot, but it does allow us to assert that the boot entry has # the correct contents. boot.loader.systemd-boot.installDeviceTree = pkgs.stdenv.hostPlatform.isAarch64; hardware.deviceTree.name = "dummy.dtb"; hardware.deviceTree.package = lib.mkForce (pkgs.runCommand "dummy-devicetree-package" { } '' mkdir -p $out cp ${pkgs.emptyFile} $out/dummy.dtb ''); }; }; testScript = '' testScript = { nodes, ... }: '' machine.start() machine.wait_for_unit("multi-user.target") Loading @@ -188,6 +201,10 @@ rec { machine.succeed( "grep 'sort-key something' /boot/loader/entries/nixos-generation-1-specialisation-something.conf" ) '' + pkgs.lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 '' machine.succeed( "grep 'devicetree .*dummy' /boot/loader/entries/nixos-generation-1-specialisation-something.conf" ) ''; }; Loading Loading
nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +12 −3 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ class BootSpec: toplevel: str specialisations: dict[str, "BootSpec"] sortKey: str # noqa: N815 devicetree: str | None = None # noqa: N815 initrdSecrets: str | None = None # noqa: N815 @dataclass Loading Loading @@ -85,6 +86,7 @@ class DiskEntry: kernel_params: str | None machine_id: str | None sort_key: str devicetree: str | None @classmethod def from_path(cls: Type["DiskEntry"], path: Path) -> "DiskEntry": Loading @@ -109,7 +111,9 @@ class DiskEntry: initrd=entry_map["initrd"], kernel_params=entry_map.get("options"), machine_id=entry_map.get("machine-id"), sort_key=entry_map.get("sort_key", "nixos")) sort_key=entry_map.get("sort_key", "nixos"), devicetree=entry_map.get("devicetree"), ) return disk_entry def write(self, sorted_first: str) -> None: Loading @@ -128,7 +132,8 @@ class DiskEntry: f"initrd {self.initrd}", f"options {self.kernel_params}" if self.kernel_params is not None else None, f"machine-id {self.machine_id}" if self.machine_id is not None else None, f"sort-key {default_sort_key if self.default else self.sort_key}" f"sort-key {default_sort_key if self.default else self.sort_key}", f"devicetree {self.devicetree}" if self.devicetree is not None else None, ] f.write("\n".join(filter(None, boot_entry))) Loading Loading @@ -236,10 +241,12 @@ def bootspec_from_json(bootspec_json: dict[str, Any]) -> BootSpec: specialisations = {k: bootspec_from_json(v) for k, v in specialisations.items()} systemdBootExtension = bootspec_json.get('org.nixos.systemd-boot', {}) sortKey = systemdBootExtension.get('sortKey', 'nixos') devicetree = systemdBootExtension.get('devicetree') return BootSpec( **bootspec_json['org.nixos.bootspec.v1'], specialisations=specialisations, sortKey=sortKey sortKey=sortKey, devicetree=devicetree, ) Loading @@ -264,6 +271,7 @@ def write_entry(profile: str | None, bootspec = bootspec.specialisations[specialisation] kernel = copy_from_file(bootspec.kernel) initrd = copy_from_file(bootspec.initrd) devicetree = copy_from_file(bootspec.devicetree) if bootspec.devicetree is not None else None title = "{name}{profile}{specialisation}".format( name=DISTRO_NAME, Loading Loading @@ -306,6 +314,7 @@ def write_entry(profile: str | None, machine_id=machine_id, description=f"Generation {generation} {bootspec.label}, built on {build_date}", sort_key=bootspec.sortKey, devicetree=devicetree, default=current ).write(sorted_first) Loading
nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix +14 −0 Original line number Diff line number Diff line Loading @@ -191,6 +191,15 @@ in { ''; }; installDeviceTree = mkOption { default = with config.hardware.deviceTree; enable && name != null; defaultText = ''with config.hardware.deviceTree; enable && name != null''; description = '' Install the devicetree blob specified by `config.hardware.deviceTree.name` to the ESP and instruct systemd-boot to pass this DTB to linux. ''; }; extraInstallCommands = mkOption { default = ""; example = '' Loading Loading @@ -369,6 +378,10 @@ in { assertion = (config.boot.kernelPackages.kernel.features or { efiBootStub = true; }) ? efiBootStub; message = "This kernel does not support the EFI boot stub"; } { assertion = cfg.installDeviceTree -> config.hardware.deviceTree.enable -> config.hardware.deviceTree.name != null; message = "Cannot install devicetree without 'config.hardware.deviceTree.enable' enabled and 'config.hardware.deviceTree.name' set"; } ] ++ concatMap (filename: [ { assertion = !(hasInfix "/" filename); Loading Loading @@ -426,6 +439,7 @@ in { boot.bootspec.extensions."org.nixos.systemd-boot" = { inherit (config.boot.loader.systemd-boot) sortKey; devicetree = lib.mkIf cfg.installDeviceTree "${config.hardware.deviceTree.package}/${config.hardware.deviceTree.name}"; }; system = { Loading
nixos/tests/systemd-boot.nix +18 −1 Original line number Diff line number Diff line Loading @@ -172,10 +172,23 @@ rec { imports = [ common ]; specialisation.something.configuration = { boot.loader.systemd-boot.sortKey = "something"; # Since qemu will dynamically create a devicetree blob when starting # up, it is not straight forward to create an export of that devicetree # blob without knowing before-hand all the flags we would pass to qemu # (we would then be able to use `dumpdtb`). Thus, the following config # will not boot, but it does allow us to assert that the boot entry has # the correct contents. boot.loader.systemd-boot.installDeviceTree = pkgs.stdenv.hostPlatform.isAarch64; hardware.deviceTree.name = "dummy.dtb"; hardware.deviceTree.package = lib.mkForce (pkgs.runCommand "dummy-devicetree-package" { } '' mkdir -p $out cp ${pkgs.emptyFile} $out/dummy.dtb ''); }; }; testScript = '' testScript = { nodes, ... }: '' machine.start() machine.wait_for_unit("multi-user.target") Loading @@ -188,6 +201,10 @@ rec { machine.succeed( "grep 'sort-key something' /boot/loader/entries/nixos-generation-1-specialisation-something.conf" ) '' + pkgs.lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 '' machine.succeed( "grep 'devicetree .*dummy' /boot/loader/entries/nixos-generation-1-specialisation-something.conf" ) ''; }; Loading