QEMU and Firmware Detection
Cubic needs two things from the host that it does not ship itself, the QEMU binaries and the UEFI firmware that boots a guest. Both are installed in a different place by every platform and every packager. This page explains how Cubic finds them and why it looks the way it does.
Install Cubic lists the packages to install, QEMU or Firmware Not Found helps when the search fails, and Environment Variables documents the variables named here.
One Search List
Cubic builds a single ordered list of directories where QEMU may live:
CUBIC_QEMU_DIR, when it is setevery directory on your
PATHbuilt in fallback locations, which are
C:\Program Files\qemuon Windows and/usr/bin,/usr/local/bin,/opt/homebrew/bin,/home/linuxbrew/.linuxbrew/binand/opt/local/binon Unix
The fallbacks matter because a graphical session or a launcher often has a
shorter PATH than your shell, and because Homebrew and MacPorts install
outside the system directories.
That one list serves both purposes. For the binaries Cubic hands the list to
QEMU as its PATH and starts qemu-system-x86_64, qemu-system-aarch64
or qemu-img by name, letting the operating system resolve it. Only the child
process gets that PATH, your own environment is never touched. For the
firmware Cubic takes the first directory of the list that holds a QEMU binary
and treats its parent as the QEMU install prefix, so /usr/bin gives
/usr. On Windows the directory itself is the prefix.
Descriptors Instead of File Names
Firmware files are named differently everywhere. One distribution ships
OVMF_CODE_4M.fd, another OVMF_CODE.fd, and Homebrew and Windows ship
edk2-x86_64-code.fd. Guessing from a list of names breaks on the next
distribution that picks another one.
QEMU and the distributions ship firmware descriptors instead, JSON files that
state what each firmware image is and what it targets. Cubic collects them from
the configuration directory of QEMU, from /etc/qemu/firmware and from the
install prefix, and QEMU or Firmware Not Found lists that order in full.
A descriptor is used when it maps a flash device with a UEFI interface and names
a target that matches the architecture and the machine type of the VM instance,
q35 for amd64 and virt for arm64. Descriptors with a feature that needs
setup a plain guest does not have are skipped, which covers secure boot, SMM,
AMD SEV-SNP and Intel TDX.
This is why Cubic works on distributions it has never seen. The distribution describes its own firmware and Cubic reads that description.
Paths Anchored on the QEMU Install
A descriptor records an absolute path to its firmware image, and that path is
not always the truth. Inside a strictly confined snap the real file sits under
$SNAP. A relocated Windows build does not live where its packager built it.
Cubic therefore resolves the file relative to the QEMU install it found,
anchored on the share directory of the prefix. The descriptor still says
which file to use, while the install says where that file is.
Setup |
QEMU install prefix |
Firmware file |
|---|---|---|
Linux package manager |
|
|
snap, strict confinement |
|
|
macOS Homebrew or MacPorts |
|
|
Windows, winget |
|
|
On Linux the firmware and its descriptor come in a separate package from QEMU,
ovmf or edk2 depending on the distribution, which is why QEMU can be
installed and the firmware still missing. On macOS and Windows both ship
together.
When Detection Is Wrong
Two escape hatches exist, and they work at different levels.
CUBIC_QEMU_DIR names a QEMU install. It goes to the front of the search list
and is used for the binaries and for the firmware descriptors, so it moves the
whole detection to another install.
CUBIC_QEMU_FW_AMD64 and CUBIC_QEMU_FW_ARM64 name a firmware file
directly and skip the descriptors entirely. Cubic trusts such a path as it is
and never checks that the file exists, so a typo turns this error into a QEMU
startup failure later on.
Prefer the first when a whole QEMU install lives somewhere unusual, and the second only when the descriptors themselves are unusable. QEMU or Firmware Not Found walks through both.