]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Introduce support for overriding system's DeviceTree
authorBjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Thu, 29 Feb 2024 15:00:13 +0000 (16:00 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 15 Jan 2025 22:14:49 +0000 (23:14 +0100)
While experimenting with OS images on development boards where either
the bootloader doesn't load a Flattened DeviceTree Blob, or if one wants
to replace the one provided by the bootloader with a specific/new one
for development/experimentation/testing purposes, it's convenient to use
the OS-loaders ability to load a specific DeviceTree blob.

Add a new option to mkosi, to cause a specified DeviceTree blob to be
baked into the UKI, or copied into /boot and added to the systemd loader
entry.

As different distributions store the dtb files in different locations
the requested file is searched for in the locations spotted in Debian,
Fedora, Arch Linux packages (both from distro and kernel build system -
as these differs as well).

Resolves #2439
Based on initial effort by Manuel Traut.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
mkosi/__init__.py
mkosi/config.py
mkosi/resources/man/mkosi.1.md
tests/test_json.py

index 5435279ab50a8efa077c49bf81ae0a20c95538a4..85f8fbb8bfbb1615542b7e44b58f1ce66ec9b375 100644 (file)
@@ -1457,6 +1457,21 @@ def build_kernel_modules_initrd(context: Context, kver: str) -> Path:
     return kmods
 
 
+def find_devicetree(context: Context, kver: str) -> Path:
+    assert context.config.devicetree
+
+    for d in (
+        context.root / f"usr/lib/firmware/{kver}/device-tree",
+        context.root / f"usr/lib/linux-image-{kver}",
+        context.root / f"usr/lib/modules/{kver}/dtb",
+    ):
+        dtb = d / context.config.devicetree
+        if dtb.exists():
+            return dtb
+
+    die(f"Requested devicetree {context.config.devicetree} not found")
+
+
 def join_initrds(initrds: Sequence[Path], output: Path) -> Path:
     assert initrds
 
@@ -1606,6 +1621,11 @@ def build_uki(
         *flatten(["--ro-bind", os.fspath(profile), os.fspath(workdir(profile))] for profile in profiles),
     ]  # fmt: skip
 
+    if context.config.devicetree:
+        dtb = find_devicetree(context, kver)
+        arguments += ["--devicetree", workdir(dtb)]
+        options += ["--ro-bind", dtb, workdir(dtb)]
+
     if context.config.secure_boot:
         assert context.config.secure_boot_key
         assert context.config.secure_boot_certificate
@@ -1811,6 +1831,12 @@ def install_type1(
 
     kmods = build_kernel_modules_initrd(context, kver)
 
+    dtb = None
+    if context.config.devicetree:
+        dtb = dst / context.config.devicetree
+        with umask(~0o700):
+            dtb.parent.mkdir(parents=True, exist_ok=True)
+
     with umask(~0o600):
         if (
             want_efi(context.config)
@@ -1828,6 +1854,9 @@ def install_type1(
         ]
         initrds += [Path(shutil.copy2(kmods, dst / "kernel-modules.initrd"))]
 
+        if dtb:
+            shutil.copy2(find_devicetree(context, kver), dtb)
+
         with entry.open("w") as f:
             f.write(
                 textwrap.dedent(
@@ -1843,6 +1872,9 @@ def install_type1(
             for initrd in initrds:
                 f.write(f"initrd /{initrd.relative_to(context.root / 'boot')}\n")
 
+            if dtb:
+                f.write(f"devicetree /{dtb.relative_to(context.root / 'boot')}\n")
+
     if want_grub_efi(context) or want_grub_bios(context, partitions):
         config = prepare_grub_config(context)
         assert config
index c78b3c55fc0b8f8bb1c49b30e1e344da75d4ba2b..b50150d4699fea2d1a8a58c672f94a50201dc7cb 100644 (file)
@@ -1807,6 +1807,7 @@ class Config:
     initrd_packages: list[str]
     initrd_volatile_packages: list[str]
     microcode_host: bool
+    devicetree: Optional[Path]
     kernel_command_line: list[str]
     kernel_modules_include: list[str]
     kernel_modules_exclude: list[str]
@@ -2776,6 +2777,12 @@ SETTINGS: list[ConfigSetting[Any]] = [
         parse=config_make_list_parser(delimiter=","),
         help="Packages to install in the initrd that are not cached",
     ),
+    ConfigSetting(
+        dest="devicetree",
+        section="Content",
+        parse=config_parse_string,
+        help="Devicetree to be used by the booting kernel",
+    ),
     ConfigSetting(
         dest="kernel_command_line",
         metavar="OPTIONS",
@@ -4829,6 +4836,7 @@ def summary(config: Config) -> str:
                             Initrds: {line_join_list(config.initrds)}
                     Initrd Packages: {line_join_list(config.initrd_packages)}
            Initrd Volatile Packages: {line_join_list(config.initrd_volatile_packages)}
+                         Devicetree: {none_to_none(config.devicetree)}
                 Kernel Command Line: {line_join_list(config.kernel_command_line)}
              Kernel Modules Include: {line_join_list(config.kernel_modules_include)}
              Kernel Modules Exclude: {line_join_list(config.kernel_modules_exclude)}
index b3edb7dff7e91e7c39baa8fe93f64d21adb79d98..718e4552de4a02645255f20369206c9535fa3981 100644 (file)
@@ -996,6 +996,12 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
 :   Similar to `VolatilePackages=`, except it applies to the default
     initrd.
 
+`Devicetree=`, `--devicetree=`
+:   When set, specifies a Devicetree blob to be used by the booting system,
+    instead of the one provided by firmware. **mkosi** will search for the
+    specified file relative to common paths where Linux distributions install
+    Devicetree files. It should typically have the format `<vendor>/<board>.dtb`.
+
 `MicrocodeHost=`, `--microcode-host=`
 :   When set to true only include microcode for the host's CPU in the image.
 
index 9178429c451384bf5b103ce3219e6d8aa97d298d..b107467af1a1146b39313db00bb3dc7d1eda2713 100644 (file)
@@ -139,6 +139,7 @@ def test_config() -> None:
             "Dependencies": [
                 "dep1"
             ],
+            "Devicetree": "freescale/imx8mm-verdin-nonwifi-dev.dtb",
             "Distribution": "fedora",
             "Drives": [
                 {
@@ -480,6 +481,7 @@ def test_config() -> None:
         make_initrd=False,
         manifest_format=[ManifestFormat.json, ManifestFormat.changelog],
         microcode_host=True,
+        devicetree=Path("freescale/imx8mm-verdin-nonwifi-dev.dtb"),
         minimum_version=GenericVersion("123"),
         mirror=None,
         nspawn_settings=None,