nixos/systemd-boot: add support for devicetree entry

The [Boot Loader Specification](https://uapi-group.org/specifications/specs/boot_loader_specification/)
allows for using a key called "devicetree" for specifying which
devicetree the bootloader should use during boot. With regards to
systemd-boot, this key is used to specify which file should be picked up
from the ESP to install to the EFI DTB Configuration Table. Linux then uses
this Configuration Table to setup the machine. This change is similar to
the one done in https://github.com/NixOS/nixpkgs/pull/295096, where that
change was for adding DTB support to systemd-stub, and this is for
systemd-boot.
This commit is contained in:
Jared Baur 2024-06-12 17:02:35 -07:00
parent 6614b28fa9
commit fca8ee915d
No known key found for this signature in database
2 changed files with 26 additions and 3 deletions

View File

@ -47,6 +47,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
@ -84,6 +85,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":
@ -108,7 +110,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:
@ -127,7 +131,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)))
@ -233,10 +238,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,
)
@ -261,6 +268,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,
@ -303,6 +311,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)

View File

@ -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 = ''
@ -353,6 +362,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);
@ -410,6 +423,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 = {