]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Implement linux-noinitrd firmware
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 20 Mar 2025 13:20:50 +0000 (14:20 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 20 Mar 2025 19:45:26 +0000 (20:45 +0100)
Useful for direct kernel booting without an initrd even if one was
built.

mkosi/config.py
mkosi/qemu.py
mkosi/resources/man/mkosi.1.md
mkosi/vmspawn.py

index 8a80e9783f03a766c014dc8bd5467ab7f2c586dd..77d25e997bd296bf22ebb21242778d28ff5bf968 100644 (file)
@@ -321,6 +321,7 @@ class Cacheonly(StrEnum):
 class Firmware(StrEnum):
     auto = enum.auto()
     linux = enum.auto()
+    linux_noinitrd = enum.auto()
     uefi = enum.auto()
     uefi_secure_boot = enum.auto()
     bios = enum.auto()
@@ -328,6 +329,9 @@ class Firmware(StrEnum):
     def is_uefi(self) -> bool:
         return self in (Firmware.uefi, Firmware.uefi_secure_boot)
 
+    def is_linux(self) -> bool:
+        return self in (Firmware.linux, Firmware.linux_noinitrd)
+
 
 class ConsoleMode(StrEnum):
     interactive = enum.auto()
index 865a758e0b4ef1e9c8ec8f0c53967ad7e19e56cf..b9605286f21f83d01d31f7c6b2975863d15ba64b 100644 (file)
@@ -812,6 +812,20 @@ def finalize_drive(drive: Drive) -> Iterator[Path]:
         yield Path(file.name)
 
 
+@contextlib.contextmanager
+def finalize_initrd(config: Config) -> Iterator[Optional[Path]]:
+    with contextlib.ExitStack() as stack:
+        if (config.output_dir_or_cwd() / config.output_split_initrd).exists():
+            yield config.output_dir_or_cwd() / config.output_split_initrd
+        elif config.initrds:
+            initrd = config.output_dir_or_cwd() / f"initrd-{uuid.uuid4().hex}"
+            join_initrds(config, config.initrds, initrd)
+            stack.callback(lambda: initrd.unlink())
+            yield initrd
+        else:
+            yield None
+
+
 @contextlib.contextmanager
 def finalize_state(config: Config, cid: int) -> Iterator[None]:
     (INVOKING_USER.runtime_dir() / "machine").mkdir(parents=True, exist_ok=True)
@@ -1100,8 +1114,9 @@ def run_qemu(args: Args, config: Config) -> None:
 
     if (
         config.output_format in (OutputFormat.cpio, OutputFormat.uki, OutputFormat.esp)
-        and config.firmware not in (Firmware.auto, Firmware.linux)
+        and not config.firmware.is_linux()
         and not config.firmware.is_uefi()
+        and config.firmware != Firmware.auto
     ):
         die(f"{config.output_format} images cannot be booted with the '{config.firmware}' firmware")
 
@@ -1169,7 +1184,7 @@ def run_qemu(args: Args, config: Config) -> None:
     firmware = finalize_firmware(config, kernel, kerneltype)
 
     if not kernel and (
-        firmware == Firmware.linux
+        firmware.is_linux()
         or config.output_format in (OutputFormat.cpio, OutputFormat.directory, OutputFormat.uki)
     ):
         if firmware.is_uefi():
@@ -1433,14 +1448,14 @@ def run_qemu(args: Args, config: Config) -> None:
 
         if config.output_format == OutputFormat.cpio:
             cmdline += ["-initrd", fname]
-        elif kernel and kerneltype != KernelType.uki and "-initrd" not in args.cmdline:
-            if (config.output_dir_or_cwd() / config.output_split_initrd).exists():
-                cmdline += ["-initrd", config.output_dir_or_cwd() / config.output_split_initrd]
-            elif config.initrds:
-                initrd = config.output_dir_or_cwd() / f"initrd-{uuid.uuid4().hex}"
-                join_initrds(config, config.initrds, initrd)
-                stack.callback(lambda: initrd.unlink())
-                cmdline += ["-initrd", initrd]
+        elif (
+            kernel
+            and kerneltype != KernelType.uki
+            and "-initrd" not in args.cmdline
+            and firmware != Firmware.linux_noinitrd
+            and (initrd := stack.enter_context(finalize_initrd(config)))
+        ):
+            cmdline += ["-initrd", initrd]
 
         if config.output_format in (OutputFormat.disk, OutputFormat.esp):
             blockdev = [
index 80c4a0f22718d2bbe84cd1be872f5d9cbd1fcccc..faa08d2bd526adea149062cdd04c1c57f4d1dc10 100644 (file)
@@ -1736,14 +1736,16 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
 
 `Firmware=`, `--firmware=`
 :   Configures the virtual machine firmware to use. Takes one of `uefi`,
-    `uefi-secure-boot`, `bios`, `linux`, or `auto`. Defaults to `auto`.
-    When set to `uefi`, the OVMF firmware without secure boot support
-    is used. When set to `uefi-secure-boot`, the OVMF firmware with
-    secure boot support is used. When set to `bios`, the default SeaBIOS
-    firmware is used. When set to `linux`, direct kernel boot is used.
-    See the `Linux=` option for more details on which kernel image is
-    used with direct kernel boot. When set to `auto`, `uefi-secure-boot`
-    is used if possible and `linux` otherwise.
+    `uefi-secure-boot`, `bios`, `linux`, `linux-noinitrd` or `auto`.
+    Defaults to `auto`. When set to `uefi`, the OVMF firmware without
+    secure boot support is used. When set to `uefi-secure-boot`, the
+    OVMF firmware with secure boot support is used. When set to `bios`,
+    the default SeaBIOS firmware is used. When set to `linux`, direct
+    kernel boot is used. See the `Linux=` option for more details on
+    which kernel image is used with direct kernel boot.
+    `linux-noinitrd` is identical to `linux` except that no initrd is
+    used. When set to `auto`, `uefi-secure-boot` is used if possible and
+    `linux` otherwise.
 
 `FirmwareVariables=`, `--firmware-variables=`
 :   Configures the path to the the virtual machine firmware variables file
index dd56232563fce2c598c4e137838e17197cdcf328..0d04d12c8590f6c48942c70d5cfcdcf1de8a1167 100644 (file)
@@ -19,6 +19,7 @@ from mkosi.qemu import (
     copy_ephemeral,
     finalize_credentials,
     finalize_firmware,
+    finalize_initrd,
     finalize_kernel_command_line_extra,
     finalize_register,
 )
@@ -42,7 +43,7 @@ def run_vmspawn(args: Args, config: Config) -> None:
     kernel = config.expand_linux_specifiers() if config.linux else None
     firmware = finalize_firmware(config, kernel)
 
-    if not kernel and firmware == Firmware.linux:
+    if not kernel and firmware.is_linux():
         kernel = config.output_dir_or_cwd() / config.output_split_kernel
         if not kernel.exists():
             die(
@@ -92,6 +93,11 @@ def run_vmspawn(args: Args, config: Config) -> None:
         if kernel:
             cmdline += ["--linux", kernel]
 
+            if firmware != Firmware.linux_noinitrd and (
+                initrd := stack.enter_context(finalize_initrd(config))
+            ):
+                cmdline += ["--initrd", initrd]
+
         if config.output_format == OutputFormat.directory:
             cmdline += ["--directory", fname]