]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Detect kernel ver from modules sub dir if unable to extract from filename
authorClayton Craft <clayton@craftyguy.net>
Wed, 4 Jun 2025 22:44:50 +0000 (15:44 -0700)
committerClayton Craft <clayton@craftyguy.net>
Tue, 23 Sep 2025 15:24:11 +0000 (08:24 -0700)
postmarketOS doesn't include the kernel version in the filename of the
kernel image. It would be cleaner to update kernel packages to make a
symlink for the kernel under /usr/lib/modules/<ver>, but this would be
difficult to implement in postmarketOS where we ship something like >400
kernel packages for a huge array of different devices / kernel versions.

Currently Alpine/pmOS only support having 1 kernel / version installed
at one time, so this fails if, for some reason, multiple kernel dirs
are found since there's no way to determine which one maps to the kernel
binary mkosi is using.

mkosi/__init__.py

index 8a95a72e82f3483c1fffb5cbf9a647c221702a13..566e8ce54272554ee066b03e6e423097757cc186 100644 (file)
@@ -170,6 +170,9 @@ from mkosi.util import (
 from mkosi.versioncomp import GenericVersion
 from mkosi.vmspawn import run_vmspawn
 
+# Allowed characters from https://uapi-group.org/specifications/specs/version_format_specification
+KERNEL_VERSION_PATTERN = r"\d+\.\d+[\w.\-~^+]*"
+
 
 @contextlib.contextmanager
 def mount_base_trees(context: Context) -> Iterator[None]:
@@ -1292,6 +1295,23 @@ def gzip_binary(context: Context) -> str:
     return "pigz" if context.config.find_binary("pigz") else "gzip"
 
 
+def kernel_get_ver_from_modules(context: Context) -> Optional[str]:
+    # Try to get version from the first dir under usr/lib/modules but fail if multiple versions are found
+    versions = [
+        p.name
+        for p in (context.root / "usr/lib/modules").glob("*")
+        if re.match(KERNEL_VERSION_PATTERN, p.name)
+    ]
+    if len(versions) > 1:
+        die(
+            "Multiple kernel module directories found in /usr/lib/modules, unable to determine correct version to use"  # noqa: E501
+        )
+    elif len(versions) == 0:
+        return None
+
+    return versions[0]
+
+
 def fixup_vmlinuz_location(context: Context) -> None:
     # Some architectures ship an uncompressed vmlinux (ppc64el, riscv64)
     for type in ("vmlinuz", "vmlinux"):
@@ -1299,7 +1319,14 @@ def fixup_vmlinuz_location(context: Context) -> None:
             if d.is_symlink():
                 continue
 
-            kver = d.name.removeprefix(f"{type}-")
+            # Extract kernel version pattern from filename
+            filename = d.name.removeprefix(f"{type}-")
+            match = re.search(KERNEL_VERSION_PATTERN, filename)
+            kver = match.group(0) if match else kernel_get_ver_from_modules(context)
+            if kver is None:
+                logging.debug("Unable to get kernel version from modules directory")
+                continue
+
             vmlinuz = context.root / "usr/lib/modules" / kver / type
             if not vmlinuz.parent.exists():
                 continue