Unverified Commit 97ebf115 authored by Franz Pletz's avatar Franz Pletz Committed by GitHub
Browse files

Merge pull request #319422 from jmbaur/systemd-boot-devicetree

parents 7acc375b 22199c70
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -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
@@ -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":
@@ -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:
@@ -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)))
@@ -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,
    )


@@ -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,
@@ -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)

+14 −0
Original line number Diff line number Diff line
@@ -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 = ''
@@ -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);
@@ -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 = {
+18 −1
Original line number Diff line number Diff line
@@ -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")

@@ -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"
      )
    '';
  };