grub = enum.auto()
+class QemuFirmware(StrEnum):
+ direct = enum.auto()
+ uefi = enum.auto()
+ bios = enum.auto()
+
+
def parse_boolean(s: str) -> bool:
"Parse 1/true/yes/y/t/on as true and 0/false/no/n/f/off/None as false"
s_l = s.lower()
qemu_vsock: ConfigFeature
qemu_swtpm: ConfigFeature
qemu_cdrom: bool
- qemu_bios: bool
+ qemu_firmware: QemuFirmware
qemu_args: Sequence[str]
preset: Optional[str]
help="Attach the image as a CD-ROM to the virtual machine",
),
MkosiConfigSetting(
- dest="qemu_bios",
- metavar="BOOLEAN",
- nargs="?",
+ dest="qemu_firmware",
+ metavar="FIRMWARE",
section="Host",
- parse=config_parse_boolean,
- help="Boot QEMU with SeaBIOS instead of EDK2",
+ parse=config_make_enum_parser(QemuFirmware),
+ default=QemuFirmware.uefi,
+ help="Set qemu firmware to use",
+ choices=QemuFirmware.values(),
),
MkosiConfigSetting(
dest="qemu_args",
QEMU Use VSock: {config.qemu_vsock}
QEMU Use Swtpm: {config.qemu_swtpm}
QEMU Use CD-ROM: {yes_no(config.qemu_cdrom)}
- QEMU BIOS: {yes_no(config.qemu_bios)}
+ QEMU Firmware: {config.qemu_firmware}
QEMU Extra Arguments: {line_join_list(config.qemu_args)}
"""
from typing import Iterator, Optional
from mkosi.architecture import Architecture
-from mkosi.config import ConfigFeature, MkosiArgs, MkosiConfig, OutputFormat
+from mkosi.config import (
+ ConfigFeature,
+ MkosiArgs,
+ MkosiConfig,
+ OutputFormat,
+ QemuFirmware,
+)
from mkosi.log import die
from mkosi.run import MkosiAsyncioThread, run, spawn
from mkosi.tree import copy_tree, rmtree
die("Couldn't find QEMU/KVM binary")
-def find_qemu_firmware(config: MkosiConfig) -> tuple[Path, bool]:
+def find_ovmf_firmware(config: MkosiConfig) -> tuple[Path, bool]:
FIRMWARE_LOCATIONS = {
Architecture.x86_64: ["/usr/share/ovmf/x64/OVMF_CODE.secboot.fd"],
Architecture.x86: [
if config.qemu_kvm == ConfigFeature.enabled or auto:
accel = "kvm"
- firmware, fw_supports_sb = find_qemu_firmware(config)
- smm = "on" if fw_supports_sb and not config.qemu_bios else "off"
+ firmware, fw_supports_sb = find_ovmf_firmware(config)
+ smm = "on" if config.qemu_firmware == QemuFirmware.uefi and fw_supports_sb else "off"
if config.architecture == Architecture.arm64:
machine = f"type=virt,accel={accel}"
cmdline += ["-smbios", f"type=11,value=io.systemd.stub.kernel-cmdline-extra={' '.join(config.kernel_command_line_extra)}"]
# QEMU has built-in logic to look for the BIOS firmware so we don't need to do anything special for that.
- if not config.qemu_bios:
+ if config.qemu_firmware == QemuFirmware.uefi:
cmdline += ["-drive", f"if=pflash,format=raw,readonly=on,file={firmware}"]
notifications: dict[str, str] = {}
with contextlib.ExitStack() as stack:
- if fw_supports_sb and not config.qemu_bios:
+ if config.qemu_firmware == QemuFirmware.uefi and fw_supports_sb:
ovmf_vars = stack.enter_context(tempfile.NamedTemporaryFile(prefix=".mkosi-"))
shutil.copy2(find_ovmf_vars(config), Path(ovmf_vars.name))
cmdline += [
"--offline=yes",
fname])
- if config.output_format == OutputFormat.cpio:
+ if config.qemu_firmware == QemuFirmware.direct or config.output_format == OutputFormat.cpio:
kernel = config.output_dir / config.output_split_kernel
if not kernel.exists() and "-kernel" not in args.cmdline:
- die("No kernel found, please install a kernel in the cpio or provide a -kernel argument to mkosi qemu")
+ die("No kernel found, please install a kernel in the image or provide a -kernel argument to mkosi qemu")
+
cmdline += ["-kernel", kernel,
- "-initrd", fname,
"-append", " ".join(config.kernel_command_line + config.kernel_command_line_extra)]
- cmdline += ["-drive", f"if=none,id=mkosi,file={fname},format=raw",
- "-device", "virtio-scsi-pci,id=scsi",
- "-device", f"scsi-{'cd' if config.qemu_cdrom else 'hd'},drive=mkosi,bootindex=1"]
+ if config.output_format == OutputFormat.cpio:
+ cmdline += ["-initrd", fname]
+ else:
+ cmdline += ["-drive", f"if=none,id=mkosi,file={fname},format=raw",
+ "-device", "virtio-scsi-pci,id=scsi",
+ "-device", f"scsi-{'cd' if config.qemu_cdrom else 'hd'},drive=mkosi,bootindex=1"]
- if config.qemu_swtpm != ConfigFeature.disabled and shutil.which("swtpm") is not None and not config.qemu_bios:
+ if config.qemu_firmware == QemuFirmware.uefi and config.qemu_swtpm != ConfigFeature.disabled and shutil.which("swtpm") is not None:
sock = stack.enter_context(start_swtpm())
cmdline += ["-chardev", f"socket,id=chrtpm,path={sock}",
"-tpmdev", "emulator,id=tpm0,chardev=chrtpm"]
attach the image to the virtual machine as a CD-ROM device. Takes a
boolean. Defaults to `no`.
-`QemuBios=`, `--qemu-bios=`
-
-: When used with the `qemu` verb, this option specifies whether to use
- the BIOS firmware instead of the UEFI firmware. Takes a boolean.
- Defaults to `no`.
+`QemuFirmware=`, `--qemu-firmware=`
+
+: When used with the `qemu` verb, this option which firmware to use.
+ Takes one of `uefi`, `bios` or `direct`. Defaults to `uefi`. When set
+ to `uefi`, the OVMF firmware is used. When set to `bios`, the default
+ SeaBIOS firmware is used. When set to `direct`, direct kernel boot is
+ used. The kernel used for direct kernel boot can either be provided by
+ passing qemu's `-kernel` option on the mkosi command line or by
+ installing a kernel into the image, in which case it will be picked up
+ automatically.
+
+: Note that when the `cpio` output format is used, direct kernel boot is
+ used regardless of the configured firmware. Depending on the
+ configured firmware, qemu might boot the kernel itself or using the
+ configured firmware.
`QemuArgs=`