From: Bjorn Andersson Date: Thu, 29 Feb 2024 15:00:13 +0000 (+0100) Subject: Introduce support for overriding system's DeviceTree X-Git-Tag: v25~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5618eafa031aba2ddf61c4e70588a7f44898b7a8;p=thirdparty%2Fmkosi.git Introduce support for overriding system's DeviceTree 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 --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 5435279ab..85f8fbb8b 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -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 diff --git a/mkosi/config.py b/mkosi/config.py index c78b3c55f..b50150d46 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -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)} diff --git a/mkosi/resources/man/mkosi.1.md b/mkosi/resources/man/mkosi.1.md index b3edb7dff..718e4552d 100644 --- a/mkosi/resources/man/mkosi.1.md +++ b/mkosi/resources/man/mkosi.1.md @@ -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 `/.dtb`. + `MicrocodeHost=`, `--microcode-host=` : When set to true only include microcode for the host's CPU in the image. diff --git a/tests/test_json.py b/tests/test_json.py index 9178429c4..b107467af 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -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,