Skip to content

Commit 70d9021

Browse files
DaanDeMeyercraftyguy
authored andcommitted
fixup! Add devicetree-auto support for UKI
1 parent a6cf5c6 commit 70d9021

File tree

5 files changed

+89
-77
lines changed

5 files changed

+89
-77
lines changed

mkosi/__init__.py

Lines changed: 26 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,13 @@
9191
from mkosi.installer import clean_package_manager_metadata
9292
from mkosi.installer.pacman import Pacman
9393
from mkosi.installer.zypper import Zypper
94-
from mkosi.kmod import gen_required_kernel_modules, is_valid_kdir, loaded_modules, process_kernel_modules, globs_match_filename
94+
from mkosi.kmod import (
95+
filter_devicetrees,
96+
gen_required_kernel_modules,
97+
is_valid_kdir,
98+
loaded_modules,
99+
process_kernel_modules,
100+
)
95101
from mkosi.log import ARG_DEBUG, complete_step, die, log_notice, log_step
96102
from mkosi.manifest import Manifest
97103
from mkosi.mounts import (
@@ -1597,54 +1603,6 @@ def build_kernel_modules_initrd(context: Context, kver: str) -> Path:
15971603
return kmods
15981604

15991605

1600-
def find_devicetree(context: Context, kver: str) -> Path:
1601-
assert context.config.devicetree
1602-
assert not glob.has_magic(os.fspath(context.config.devicetree))
1603-
1604-
for d in (
1605-
context.root / f"usr/lib/firmware/{kver}/device-tree",
1606-
context.root / f"usr/lib/linux-image-{kver}",
1607-
context.root / f"usr/lib/modules/{kver}/dtb",
1608-
):
1609-
dtb = d / context.config.devicetree
1610-
if dtb.exists():
1611-
return dtb
1612-
1613-
die(f"Requested devicetree {context.config.devicetree} not found")
1614-
1615-
1616-
1617-
def find_devicetrees(context: Context, kver: str) -> list[Path]:
1618-
assert context.config.devicetree
1619-
1620-
if not glob.has_magic(os.fspath(context.config.devicetree)):
1621-
# Single devicetree
1622-
return [find_devicetree(context, kver)]
1623-
1624-
# Glob pattern - search all directories
1625-
dtb_dirs = [
1626-
context.root / f"usr/lib/firmware/{kver}/device-tree",
1627-
context.root / f"usr/lib/linux-image-{kver}",
1628-
context.root / f"usr/lib/modules/{kver}/dtb",
1629-
]
1630-
1631-
matched_dtbs = []
1632-
for dtb_dir in dtb_dirs:
1633-
if not dtb_dir.exists():
1634-
continue
1635-
1636-
all_dtbs = [p for p in dtb_dir.rglob("*.dtb") if p.is_file()]
1637-
for dtb in all_dtbs:
1638-
rel_path = os.fspath(dtb.relative_to(dtb_dir))
1639-
if globs_match_filename(rel_path, [os.fspath(context.config.devicetree)], match_default=False):
1640-
matched_dtbs.append(dtb)
1641-
1642-
if not matched_dtbs:
1643-
logging.warning(f"Devicetree glob '{context.config.devicetree}' matched 0 files")
1644-
1645-
return matched_dtbs
1646-
1647-
16481606
def want_signed_pcrs(config: Config) -> bool:
16491607
return config.sign_expected_pcr == ConfigFeature.enabled or (
16501608
config.sign_expected_pcr == ConfigFeature.auto
@@ -1802,15 +1760,17 @@ def build_uki(
18021760
*flatten(["--ro-bind", os.fspath(profile), os.fspath(workdir(profile))] for profile in profiles),
18031761
] # fmt: skip
18041762

1805-
if context.config.devicetree:
1806-
if glob.has_magic(os.fspath(context.config.devicetree)):
1807-
for dtb in find_devicetrees(context, kver):
1808-
arguments += ["--devicetree-auto", workdir(dtb)]
1809-
options += ["--ro-bind", dtb, workdir(dtb)]
1810-
else:
1811-
dtb = find_devicetree(context, kver)
1763+
if context.config.devicetrees:
1764+
dtbs = filter_devicetrees(context.root, kver, include=context.config.devicetrees)
1765+
if len(dtbs) == 1:
1766+
dtb = context.root / dtbs[0]
18121767
arguments += ["--devicetree", workdir(dtb)]
18131768
options += ["--ro-bind", dtb, workdir(dtb)]
1769+
else:
1770+
for dtb_rel in dtbs:
1771+
dtb = context.root / dtb_rel
1772+
arguments += ["--devicetree-auto", workdir(dtb)]
1773+
options += ["--ro-bind", dtb, workdir(dtb)]
18141774

18151775
if context.config.splash:
18161776
splash = context.root / os.fspath(context.config.splash).lstrip("/")
@@ -2054,10 +2014,14 @@ def install_type1(
20542014
entry.parent.mkdir(parents=True, exist_ok=True)
20552015

20562016
dtb = None
2057-
if context.config.devicetree:
2058-
if glob.has_magic(os.fspath(context.config.devicetree)):
2059-
die("Devicetree globs are not supported with Type 1 boot entries, use UKI builds instead")
2060-
dtb = dst / context.config.devicetree
2017+
source_dtb = None
2018+
if context.config.devicetrees:
2019+
dtbs = filter_devicetrees(context.root, kver, include=context.config.devicetrees)
2020+
if len(dtbs) != 1:
2021+
die("Type 1 boot entries support only single devicetree, use UKI builds for multiple devicetrees")
2022+
2023+
source_dtb = context.root / dtbs[0]
2024+
dtb = dst / dtbs[0].relative_to(f"usr/lib/modules/{kver}/dtb")
20612025
with umask(~0o700):
20622026
dtb.parent.mkdir(parents=True, exist_ok=True)
20632027

@@ -2080,8 +2044,8 @@ def install_type1(
20802044
Path(shutil.copy2(initrd, dst.parent / initrd.name)) for initrd in microcode + initrds
20812045
] + [Path(shutil.copy2(kmods, dst / "kernel-modules.initrd"))]
20822046

2083-
if dtb:
2084-
shutil.copy2(find_devicetree(context, kver), dtb)
2047+
if dtb and source_dtb is not None:
2048+
shutil.copy2(source_dtb, dtb)
20852049

20862050
with entry.open("w") as f:
20872051
f.write(

mkosi/config.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,7 +2014,7 @@ class Config:
20142014
initrd_packages: list[str]
20152015
initrd_volatile_packages: list[str]
20162016
microcode_host: bool
2017-
devicetree: Optional[str]
2017+
devicetrees: list[str]
20182018
splash: Optional[Path]
20192019
kernel_command_line: list[str]
20202020
kernel_modules_include: list[str]
@@ -3165,10 +3165,10 @@ def parse_kernel_module_filter_regexp(p: str) -> str:
31653165
help="Packages to install in the initrd that are not cached",
31663166
),
31673167
ConfigSetting(
3168-
dest="devicetree",
3168+
dest="devicetrees",
31693169
section="Content",
3170-
parse=config_parse_string,
3171-
help="Devicetree to be used by the booting kernel",
3170+
parse=config_make_list_parser(delimiter=","),
3171+
help="Devicetree(s) to be used by the booting kernel",
31723172
),
31733173
ConfigSetting(
31743174
dest="splash",
@@ -5473,7 +5473,7 @@ def summary(config: Config) -> str:
54735473
Initrd Profiles: {line_join_list(config.initrd_profiles)}
54745474
Initrd Packages: {line_join_list(config.initrd_packages)}
54755475
Initrd Volatile Packages: {line_join_list(config.initrd_volatile_packages)}
5476-
Devicetree: {none_to_none(config.devicetree)}
5476+
Devicetrees: {line_join_list(config.devicetrees)}
54775477
Splash: {none_to_none(config.splash)}
54785478
Kernel Command Line: {line_join_list(config.kernel_command_line)}
54795479
Kernel Modules: {line_join_list(config.kernel_modules_include)}

mkosi/kmod.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,3 +510,48 @@ def is_valid_kdir(kdir: Path) -> bool:
510510

511511
# check that kdir contains more than just updates
512512
return dircontent != [kdir / "updates"]
513+
514+
515+
def filter_devicetrees(
516+
root: Path,
517+
kver: str,
518+
*,
519+
include: Iterable[str],
520+
) -> list[Path]:
521+
if not include:
522+
return []
523+
524+
logging.debug(f"Devicetrees include: {' '.join(include)}")
525+
526+
# Search standard DTB locations
527+
dtb_dirs = [
528+
Path("usr/lib/firmware") / kver / "device-tree",
529+
Path(f"usr/lib/linux-image-{kver}"),
530+
Path("usr/lib/modules") / kver / "dtb",
531+
]
532+
533+
matched_dtbs = []
534+
patterns = [p[3:] for p in include if p.startswith("re:")]
535+
regex = re.compile("|".join(patterns)) if patterns else None
536+
globs = [p for p in include if not p.startswith("re:")]
537+
538+
with chdir(root):
539+
for d in dtb_dirs:
540+
if not d.exists():
541+
continue
542+
543+
all_dtbs = [p for p in d.rglob("*.dtb") if p.is_file() or p.is_symlink()]
544+
logging.debug(f"Found {len(all_dtbs)} DTB files in {d}")
545+
546+
for d in all_dtbs:
547+
rel_path = os.fspath(d.relative_to(d))
548+
if (regex and regex.search(rel_path)) or globs_match_filename(rel_path, globs):
549+
logging.debug(f"Matched DTB: {rel_path} in {d}")
550+
matched_dtbs.append(d)
551+
552+
if not matched_dtbs:
553+
logging.warning(f"Devicetrees patterns {list(include)} matched 0 files")
554+
else:
555+
logging.debug(f"Including {len(matched_dtbs)} devicetree files")
556+
557+
return sorted(matched_dtbs)

mkosi/resources/man/mkosi.1.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,14 +1080,17 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
10801080
: Similar to `VolatilePackages=`, except it applies to the default
10811081
initrd.
10821082

1083-
`Devicetree=`, `--devicetree=`
1084-
: When set, specifies a Devicetree blob to be used by the booting system,
1085-
instead of the one provided by firmware. **mkosi** will search for the
1086-
specified file relative to common paths where Linux distributions install
1087-
Devicetree files. It should typically have the format `<vendor>/<board>.dtb`.
1088-
When this includes globs, multiple dtbs may be included **only** when building a UKI.
1089-
Internally this uses the dtbauto feature. Using globs/dtbauto is is **not**
1090-
supported for Type 1 booting.
1083+
`Devicetrees=`, `--devicetrees=`
1084+
: Comma-separated list of devicetree patterns for automatic hardware-based selection.
1085+
Patterns can be glob expressions or regex prefixed with `re:`. **mkosi** searches
1086+
for devicetree files in standard locations relative to `/usr/lib/modules/<kver>/dtb/`,
1087+
`/usr/lib/firmware/<kver>/device-tree/`, and `/usr/lib/linux-image-<kver>/`.
1088+
1089+
For UKI builds, multiple matches enable automatic hardware-based selection using
1090+
the `.dtbauto` sections. Type 1 boot entries require exactly one match.
1091+
1092+
Examples: `Devicetrees=rockchip/*,re:imx.*` would include all Rockchip devicetrees
1093+
and any devicetrees matching the regex pattern `imx.*`.
10911094

10921095
`Splash=`, `--splash=`
10931096
: When set, the boot splash for any unified kernel image built by **mkosi** will

tests/test_json.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def test_config() -> None:
150150
"Dependencies": [
151151
"dep1"
152152
],
153-
"Devicetree": "freescale/imx8mm-verdin-nonwifi-dev.dtb",
153+
"Devicetrees": ["freescale/imx8mm-verdin-nonwifi-dev.dtb"],
154154
"Distribution": "fedora",
155155
"Drives": [
156156
{
@@ -510,7 +510,7 @@ def test_config() -> None:
510510
make_initrd=False,
511511
manifest_format=[ManifestFormat.json, ManifestFormat.changelog],
512512
microcode_host=True,
513-
devicetree="freescale/imx8mm-verdin-nonwifi-dev.dtb",
513+
devicetrees=["freescale/imx8mm-verdin-nonwifi-dev.dtb"],
514514
minimum_version="123",
515515
mirror=None,
516516
nspawn_settings=None,

0 commit comments

Comments
 (0)