From: Daan De Meyer Date: Wed, 15 Oct 2025 19:39:02 +0000 (+0200) Subject: Look for .sdmagic before we consider a PE binary a UKI/addon X-Git-Tag: v26~77 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d1b84f5fb3f62e9867aab1c6bac6583d6b112415;p=thirdparty%2Fmkosi.git Look for .sdmagic before we consider a PE binary a UKI/addon In ubuntu devel they started using the stubble bootloader for their kernel images which includes a .linux and a .osrel section which means it identifies as a UKI so we skip it. Let's additionally look for .sdmagic as a workaround to fix this for now. To implement this we can't make use of bootctl kernel-identify anymore so we reimplement the logic ourselves with pefile. While we're at it, we move KernelType to bootloader.py as it makes more sense to live there than in qemu.py. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index be4338ee7..bbe56b1ae 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -29,6 +29,7 @@ from typing import Any, Optional, Union, cast from mkosi.archive import can_extract_tar, extract_tar, make_cpio, make_tar from mkosi.bootloader import ( + KernelType, efi_boot_binary, extract_pe_section, gen_kernel_images, @@ -106,7 +107,6 @@ from mkosi.mounts import ( from mkosi.pager import page from mkosi.partition import Partition, finalize_root, finalize_roothash from mkosi.qemu import ( - KernelType, copy_ephemeral, finalize_credentials, finalize_kernel_command_line_extra, diff --git a/mkosi/bootloader.py b/mkosi/bootloader.py index c7af8a8bd..4ebf1d8f5 100644 --- a/mkosi/bootloader.py +++ b/mkosi/bootloader.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later +import enum import itertools import logging import os @@ -30,13 +31,52 @@ from mkosi.context import Context from mkosi.distributions import Distribution from mkosi.log import complete_step, die, log_step from mkosi.partition import Partition -from mkosi.qemu import KernelType from mkosi.run import CompletedProcess, run, workdir from mkosi.sandbox import umask -from mkosi.util import _FILE, PathString, flatten +from mkosi.util import _FILE, PathString, StrEnum, flatten from mkosi.versioncomp import GenericVersion +class KernelType(StrEnum): + pe = enum.auto() + uki = enum.auto() + addon = enum.auto() + unknown = enum.auto() + + @classmethod + def identify(cls, config: Config, path: Path) -> "KernelType": + pefile = textwrap.dedent( + f"""\ + import pefile + + try: + pe = pefile.PE("{workdir(path)}", fast_load=True) + sections = {{s.Name.decode().strip("\\0") for s in pe.sections}} + + if all(s in sections for s in (".linux", ".sdmagic", ".osrel")): + print("{KernelType.uki}") + elif ( + all(s in sections for s in (".linux", ".sdmagic")) and + any(s in sections for s in (".cmdline", ".dtb", ".initrd", ".ucode")) + ): + print("{KernelType.addon}") + else: + print("{KernelType.pe}") + except pefile.PEFormatError: + print("{KernelType.unknown}") + """ + ) + + result = run( + [python_binary(config)], + input=pefile, + stdout=subprocess.PIPE, + sandbox=config.sandbox(options=["--ro-bind", path, workdir(path)]), + ) + + return KernelType(result.stdout.strip()) + + def want_efi(config: Config) -> bool: # Do we want to make the image bootable on EFI firmware? # Note that this returns True also in the case where autodetection might later cause the system to not be diff --git a/mkosi/qemu.py b/mkosi/qemu.py index c3d3a7b2d..d3ea1924d 100644 --- a/mkosi/qemu.py +++ b/mkosi/qemu.py @@ -28,6 +28,7 @@ from collections.abc import Iterator, Sequence from pathlib import Path from typing import Optional +from mkosi.bootloader import KernelType from mkosi.config import ( Args, Config, @@ -157,34 +158,6 @@ def find_unused_vsock_cid(config: Config, vfd: int) -> int: die("Failed to find an unused VSock connection ID") -class KernelType(StrEnum): - pe = enum.auto() - uki = enum.auto() - unknown = enum.auto() - - @classmethod - def identify(cls, config: Config, path: Path) -> "KernelType": - if not config.find_binary("bootctl"): - logging.warning("bootctl is not installed, assuming 'unknown' kernel type") - return KernelType.unknown - - if (v := systemd_tool_version("bootctl", sandbox=config.sandbox)) < 253: - logging.warning(f"bootctl {v} doesn't know kernel-identify verb, assuming 'unknown' kernel type") - return KernelType.unknown - - type = run( - ["bootctl", "kernel-identify", workdir(path)], - stdout=subprocess.PIPE, - sandbox=config.sandbox(options=["--ro-bind", path, workdir(path)]), - ).stdout.strip() - - try: - return cls(type) - except ValueError: - logging.warning(f"Unknown kernel type '{type}', assuming 'unknown'") - return KernelType.unknown - - def find_qemu_binary(config: Config) -> Path: options = [f"qemu-system-{config.architecture.to_qemu()}"]