[PATCH v4 00/36] qemu: Implement support for uefi-vars device (varstore element)
This series makes it possible to use Secure Boot with aarch64 VMs. https://issues.redhat.com/browse/RHEL-82645 Changes from [v3]: * changes to JSON firmware descriptors shipped by the edk2 package have been merged in Fedora, so the corresponding patch is no longer marked as DONOTMERGE; * drop new varstore-specific flags from virsh, the existing NVRAM-related flags will work for varstore too; * drop some changes to firmware selection that were not related to varstore support, to be reworked and submitted again at a later date; * split, join and shuffle around patches; * tweak things according to review feedback. Changes from [v2]: * changes to the schema for JSON firmware descriptors have been queued for merge in QEMU, so the corresponding patch is no longer marked as DONOTMERGE; * improve documentation; * rebase on top of master, addressing conflicts that I have caused with some recent changes related to this work. Changes from [v1]: * rewrite based on review feedback: the <nvram> element is no longer used, and a dedicated <varstore> element is introduced instead; * additional test coverage, as well as fixes and improvements related to firmware selection and its documentation, are present as well. [v3] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/5JTQA... [v2] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/WVWT3... [v1] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/TGLFM... Andrea Bolognani (36): docs: Rename "BIOS bootloader" section to "guest firmware" docs: Improvement related to firmware selection qemu_firmware: Only set format for custom loader if path is present conf: Move type=rom default for loader to drivers tests: Rename custom JSON firmware descriptors schema: Introduce osnvram define conf: Parse and format varstore element conf: Update validation to consider varstore element qemu_capabilities: Introduce QEMU_CAPS_DEVICE_UEFI_VARS qemu: Validate presence of uefi-vars device tests: Add firmware-manual-efi-varstore-q35 tests: Add firmware-manual-efi-varstore-aarch64 tests: Add firmware-auto-efi-varstore-q35 tests: Add firmware-auto-efi-varstore-aarch64 tests: Add firmware-auto-efi-enrolled-keys-aarch64 qemu_firmware: Parse host-uefi-vars firmware feature qemu_firmware: Split sanity check qemu_firmware: Consider host-uefi-vars feature in sanity check qemu_firmware: Support extended syntax for ROM firmware descriptors qemu_firmware: Report NVRAM template path for ROMs conf: Include varstore element in domcaps qemu: Fill in varstore element in domcaps qemu_firmware: Use of NVRAM implies stateful firmware qemu_firmware: Allow matching stateful ROMs qemu_firmware: Fill in varstore information qemu: Introduce varstoreDir qemu_firmware: Generate varstore path when necessary qemu: Introduce qemuPrepareNVRAMFileCommon() qemu: Create and delete varstore file security: Mark ROMs as read only when using AppArmor security: Handle varstore file tests: Add firmware descriptors for uefi-vars builds qemu_command: Use uefi-vars device where appropriate include: Mention varstore where applicable virsh: Update for varstore handling news: Document support for uefi-vars device and firmwares NEWS.rst | 17 ++ docs/formatcaps.rst | 2 +- docs/formatdomain.rst | 47 +++-- docs/formatdomaincaps.rst | 85 +++++---- docs/kbase/secureboot.rst | 46 +++-- docs/manpages/virsh.rst | 23 +-- include/libvirt/libvirt-domain-snapshot.h | 2 +- include/libvirt/libvirt-domain.h | 4 +- libvirt.spec.in | 1 + src/conf/domain_capabilities.c | 10 + src/conf/domain_capabilities.h | 6 + src/conf/domain_conf.c | 79 +++++++- src/conf/domain_conf.h | 9 + src/conf/domain_postparse.c | 19 -- src/conf/domain_validate.c | 82 +++----- src/conf/schemas/domaincaps.rng | 9 + src/conf/schemas/domaincommon.rng | 74 +++++--- src/conf/virconftypes.h | 2 + src/libvirt_private.syms | 2 + src/libxl/libxl_domain.c | 6 + src/qemu/meson.build | 1 + src/qemu/qemu_capabilities.c | 29 ++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 34 ++++ src/qemu/qemu_conf.c | 4 + src/qemu/qemu_conf.h | 1 + src/qemu/qemu_driver.c | 26 ++- src/qemu/qemu_firmware.c | 177 ++++++++++++++++-- src/qemu/qemu_firmware.h | 1 + src/qemu/qemu_process.c | 84 ++++++--- src/qemu/qemu_validate.c | 20 ++ src/security/security_dac.c | 22 ++- src/security/security_selinux.c | 53 ++++-- src/security/virt-aa-helper.c | 36 +++- .../qemu_10.0.0-q35.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml | 1 + .../qemu_10.0.0-tcg.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_10.0.0-tcg.x86_64.xml | 1 + .../qemu_10.0.0-virt.aarch64.xml | 3 + tests/domaincapsdata/qemu_10.0.0.aarch64.xml | 3 + tests/domaincapsdata/qemu_10.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_10.0.0.s390x.xml | 1 + .../qemu_10.0.0.x86_64+amdsev.xml | 1 + tests/domaincapsdata/qemu_10.0.0.x86_64.xml | 1 + .../qemu_10.1.0-q35.x86_64+inteltdx.xml | 1 + .../domaincapsdata/qemu_10.1.0-q35.x86_64.xml | 1 + .../qemu_10.1.0-tcg.x86_64+inteltdx.xml | 1 + .../domaincapsdata/qemu_10.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_10.1.0.s390x.xml | 1 + .../qemu_10.1.0.x86_64+inteltdx.xml | 1 + tests/domaincapsdata/qemu_10.1.0.x86_64.xml | 1 + .../qemu_10.2.0-q35.x86_64+mshv.xml | 1 + .../domaincapsdata/qemu_10.2.0-q35.x86_64.xml | 1 + .../qemu_10.2.0-tcg.x86_64+mshv.xml | 1 + .../domaincapsdata/qemu_10.2.0-tcg.x86_64.xml | 1 + .../qemu_10.2.0-virt.aarch64.xml | 3 + tests/domaincapsdata/qemu_10.2.0.aarch64.xml | 3 + .../qemu_10.2.0.x86_64+mshv.xml | 1 + tests/domaincapsdata/qemu_10.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_11.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_11.0.0-tcg.x86_64.xml | 1 + .../qemu_11.0.0-virt.aarch64.xml | 3 + tests/domaincapsdata/qemu_11.0.0.aarch64.xml | 3 + tests/domaincapsdata/qemu_11.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 1 + .../qemu_7.2.0-hvf.x86_64+hvf.xml | 1 + .../domaincapsdata/qemu_7.2.0-q35.x86_64.xml | 1 + .../qemu_7.2.0-tcg.x86_64+hvf.xml | 1 + .../domaincapsdata/qemu_7.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.2.0.ppc.xml | 1 + tests/domaincapsdata/qemu_7.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_8.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_8.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_8.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_8.1.0.s390x.xml | 1 + tests/domaincapsdata/qemu_8.1.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.2.0-q35.x86_64.xml | 1 + .../qemu_8.2.0-tcg-virt.loongarch64.xml | 1 + .../domaincapsdata/qemu_8.2.0-tcg.x86_64.xml | 1 + .../qemu_8.2.0-virt.aarch64.xml | 3 + .../qemu_8.2.0-virt.loongarch64.xml | 1 + tests/domaincapsdata/qemu_8.2.0.aarch64.xml | 3 + tests/domaincapsdata/qemu_8.2.0.armv7l.xml | 1 + tests/domaincapsdata/qemu_8.2.0.s390x.xml | 1 + tests/domaincapsdata/qemu_8.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_9.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_9.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_9.0.0.sparc.xml | 1 + tests/domaincapsdata/qemu_9.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_9.1.0-q35.x86_64.xml | 1 + .../qemu_9.1.0-tcg-virt.riscv64.xml | 1 + .../domaincapsdata/qemu_9.1.0-tcg.x86_64.xml | 1 + .../qemu_9.1.0-virt.riscv64.xml | 1 + tests/domaincapsdata/qemu_9.1.0.s390x.xml | 1 + tests/domaincapsdata/qemu_9.1.0.x86_64.xml | 1 + .../qemu_9.2.0-hvf.aarch64+hvf.xml | 3 + .../qemu_9.2.0-q35.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_9.2.0-q35.x86_64.xml | 1 + .../qemu_9.2.0-tcg.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_9.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_9.2.0.s390x.xml | 1 + .../qemu_9.2.0.x86_64+amdsev.xml | 1 + tests/domaincapsdata/qemu_9.2.0.x86_64.xml | 1 + .../caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + .../caps_10.0.0_x86_64.xml | 1 + .../caps_10.1.0_s390x.xml | 1 + .../caps_10.1.0_x86_64+inteltdx.xml | 1 + .../caps_10.1.0_x86_64.xml | 1 + .../caps_10.2.0_aarch64.xml | 1 + .../caps_10.2.0_x86_64+mshv.xml | 1 + .../caps_10.2.0_x86_64.xml | 1 + .../caps_11.0.0_aarch64.xml | 1 + .../caps_11.0.0_x86_64.xml | 1 + .../etc/qemu/firmware/20-bios.json | 1 - .../etc/qemu/firmware/20-libvirt-bios.json | 1 + .../etc/qemu/firmware/59-combined.json | 1 - .../qemu/firmware/59-libvirt-combined.json | 1 + ...{92-masked.json => 92-libvirt-masked.json} | 0 .../{10-bios.json => 10-libvirt-bios.json} | 0 .../90-edk2-aarch64-qemuvars-sb-enrolled.json | 29 +++ ...0-edk2-ovmf-qemuvars-x64-sb-enrolled.json} | 14 +- ...combined.json => 90-libvirt-combined.json} | 0 .../firmware/91-edk2-aarch64-qemuvars-sb.json | 28 +++ ...json => 91-edk2-ovmf-qemuvars-x64-sb.json} | 15 +- .../{91-bios.json => 91-libvirt-bios.json} | 0 ...{92-masked.json => 92-libvirt-masked.json} | 0 ...3-invalid.json => 93-libvirt-invalid.json} | 0 tests/qemufirmwaretest.c | 63 +++++-- ...-auto-bios-not-stateless.x86_64-latest.err | 2 +- ...-auto-bios-not-stateless.x86_64-latest.xml | 35 ++++ ...firmware-auto-bios-nvram.x86_64-latest.err | 2 +- ...fi-enrolled-keys-aarch64.aarch64-8.2.0.err | 1 + ...-enrolled-keys-aarch64.aarch64-latest.args | 32 ++++ ...i-enrolled-keys-aarch64.aarch64-latest.xml | 32 ++++ ...irmware-auto-efi-enrolled-keys-aarch64.xml | 20 ++ ...o-efi-varstore-aarch64.aarch64-latest.args | 32 ++++ ...to-efi-varstore-aarch64.aarch64-latest.xml | 32 ++++ .../firmware-auto-efi-varstore-aarch64.xml | 18 ++ ...e-auto-efi-varstore-q35.x86_64-latest.args | 35 ++++ ...re-auto-efi-varstore-q35.x86_64-latest.xml | 40 ++++ .../firmware-auto-efi-varstore-q35.xml | 18 ++ ...nual-bios-not-stateless.x86_64-latest.args | 32 ++++ ...anual-bios-not-stateless.x86_64-latest.err | 1 - ...anual-bios-not-stateless.x86_64-latest.xml | 28 +++ ...nual-efi-nvram-stateless.x86_64-latest.err | 2 +- ...nvram-template-stateless.x86_64-latest.err | 2 +- ...ware-manual-efi-rw-nvram.x86_64-latest.err | 2 +- ...ual-efi-varstore-aarch64.aarch64-8.2.0.err | 1 + ...l-efi-varstore-aarch64.aarch64-latest.args | 32 ++++ ...al-efi-varstore-aarch64.aarch64-latest.xml | 32 ++++ .../firmware-manual-efi-varstore-aarch64.xml | 19 ++ ...e-manual-efi-varstore-q35.x86_64-8.2.0.err | 1 + ...manual-efi-varstore-q35.x86_64-latest.args | 35 ++++ ...-manual-efi-varstore-q35.x86_64-latest.xml | 40 ++++ .../firmware-manual-efi-varstore-q35.xml | 19 ++ tests/qemuxmlconftest.c | 16 +- tests/testutilsqemu.c | 2 + tools/virsh-domain.c | 10 +- tools/virsh-snapshot.c | 2 +- 173 files changed, 1546 insertions(+), 307 deletions(-) delete mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/20-bios.json create mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/20-libvirt-bios.json delete mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/59-combined.json create mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/59-libvirt-combined.json rename tests/qemufirmwaredata/etc/qemu/firmware/{92-masked.json => 92-libvirt-masked.json} (100%) rename tests/qemufirmwaredata/home/user/.config/qemu/firmware/{10-bios.json => 10-libvirt-bios.json} (100%) create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-aarch64-qemuvars-sb-enrolled.json copy tests/qemufirmwaredata/usr/share/qemu/firmware/{90-combined.json => 90-edk2-ovmf-qemuvars-x64-sb-enrolled.json} (55%) copy tests/qemufirmwaredata/usr/share/qemu/firmware/{90-combined.json => 90-libvirt-combined.json} (100%) create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json rename tests/qemufirmwaredata/usr/share/qemu/firmware/{90-combined.json => 91-edk2-ovmf-qemuvars-x64-sb.json} (52%) rename tests/qemufirmwaredata/usr/share/qemu/firmware/{91-bios.json => 91-libvirt-bios.json} (100%) rename tests/qemufirmwaredata/usr/share/qemu/firmware/{92-masked.json => 92-libvirt-masked.json} (100%) rename tests/qemufirmwaredata/usr/share/qemu/firmware/{93-invalid.json => 93-libvirt-invalid.json} (100%) create mode 100644 tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml -- 2.53.0
The new name is much more accurate since the documentation is applicable to firmware other than BIOS, notably UEFI. An empty container is used to keep old links working. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatcaps.rst | 2 +- docs/formatdomain.rst | 24 ++++++++++++++---------- docs/formatdomaincaps.rst | 19 ++++++++++++------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/docs/formatcaps.rst b/docs/formatcaps.rst index fa8ab5197f..9458e1289a 100644 --- a/docs/formatcaps.rst +++ b/docs/formatcaps.rst @@ -172,7 +172,7 @@ The ``<guest/>`` element will typically wrap up the following elements: Emulator (device model) path, for use in `emulator <formatdomain.html#devices>`__ element of domain XML. ``loader`` - Loader path, for use in `loader <formatdomain.html#bios-bootloader>`__ + Loader path, for use in `loader <formatdomain.html#guest-firmware>`__ element of domain XML. ``machine`` Machine type, for use in diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 82788c15a2..db664857af 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -103,12 +103,16 @@ Operating system booting There are a number of different ways to boot virtual machines each with their own pros and cons. +Guest firmware +~~~~~~~~~~~~~~ -BIOS bootloader -~~~~~~~~~~~~~~~ +.. container:: + :name: bios-bootloader + + .. this container only exists to keep old links working -Booting via the BIOS is available for hypervisors supporting full -virtualization. In this case the BIOS has a boot order priority (floppy, +Booting via a guest firmware is available for hypervisors supporting full +virtualization. In this case the firmware has a boot order priority (floppy, harddisk, cdrom, network) determining where to obtain/find the boot image. :: @@ -411,10 +415,10 @@ and full virtualized guests. ``type`` This element has the same semantics as described earlier in the - `BIOS bootloader`_ section. + `guest firmware`_ section. ``loader`` This element has the same semantics as described earlier in the - `BIOS bootloader`_ section. + `guest firmware`_ section. ``kernel`` The contents of this element specify the fully-qualified path to the kernel image in the host OS. @@ -3752,7 +3756,7 @@ paravirtualized driver is specified via the ``disk`` element. attribute is an 8 character string which can be queried by guests on S390 via sclp or diag 308. Linux guests on S390 can use ``loadparm`` to select a boot entry. :since:`Since 3.5.0` The per-device ``boot`` elements cannot be used - together with general boot elements in `BIOS bootloader`_ + together with general boot elements in `guest firmware`_ section. :since:`Since 0.8.8` ``encryption`` since:`Since 3.9.0` the ``encryption`` element is preferred @@ -4917,7 +4921,7 @@ or: Specifies that the device is bootable. The ``order`` attribute determines the order in which devices will be tried during boot sequence. The per-device ``boot`` elements cannot be used together with general boot elements in - `BIOS bootloader`_ section. :since:`Since 0.8.8` for PCI + `guest firmware`_ section. :since:`Since 0.8.8` for PCI devices, :since:`Since 1.0.1` for USB devices. ``rom`` The ``rom`` element is used to change how a PCI device's ROM is presented to @@ -5144,7 +5148,7 @@ USB device redirection through a character device is supported Specifies that the device is bootable. The ``order`` attribute determines the order in which devices will be tried during boot sequence. The per-device ``boot`` elements cannot be used together with general boot elements in - `BIOS bootloader`_ section. ( :since:`Since 1.0.1` ) + `guest firmware`_ section. ( :since:`Since 1.0.1` ) ``redirfilter`` The\ ``redirfilter``\ element is used for creating the filter rule to filter out certain devices from redirection. It uses sub-element ``<usbdev>`` to @@ -6400,7 +6404,7 @@ Specifying boot order For hypervisors which support this, you can set a specific NIC to be used for network boot. The ``order`` attribute determines the order in which devices will be tried during boot sequence. The per-device ``boot`` elements cannot be used -together with general boot elements in `BIOS bootloader`_ +together with general boot elements in `guest firmware`_ section. :since:`Since 0.8.8` Interface ROM BIOS configuration diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index cca827923c..22a6d5d067 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -72,11 +72,11 @@ The root element that emulator capability XML document starts with has name Describes the `virtualization type <formatdomain.html#element-and-attribute-overview>`__ (or so called domain type). ``machine`` - The domain's `machine type <formatdomain.html#bios-bootloader>`__. Since not + The domain's `machine type <formatdomain.html#guest-firmware>`__. Since not every hypervisor has a sense of machine types this element might be omitted in such drivers. ``arch`` - The domain's `architecture <formatdomain.html#bios-bootloader>`__. + The domain's `architecture <formatdomain.html#guest-firmware>`__. CPU Allocation ~~~~~~~~~~~~~~ @@ -95,12 +95,17 @@ capabilities, e.g. virtual CPUs: ``vcpu`` The maximum number of supported virtual CPUs -BIOS bootloader -~~~~~~~~~~~~~~~ +Guest firmware +~~~~~~~~~~~~~~ + +.. container:: + :name: bios-bootloader + + .. this container only exists to keep old links working -Sometimes users might want to tweak some BIOS knobs or use UEFI. For cases like -that, `os <formatdomain.html#bios-bootloader>`__ element exposes what values can -be passed to its children. +Exposes information about supported +`guest firmware <formatdomain.html#guest-firmware>`__ configurations for +domains. :: -- 2.53.0
On Mon, Feb 23, 2026 at 07:30:44PM +0100, Andrea Bolognani via Devel wrote:
The new name is much more accurate since the documentation is applicable to firmware other than BIOS, notably UEFI.
An empty container is used to keep old links working.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatcaps.rst | 2 +- docs/formatdomain.rst | 24 ++++++++++++++---------- docs/formatdomaincaps.rst | 19 ++++++++++++------- 3 files changed, 27 insertions(+), 18 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
Recommend that users take advantage of firmware autoselection and discourage providing paths manually. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomaincaps.rst | 59 ++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index 22a6d5d067..3426b7c9cd 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -145,15 +145,17 @@ domains. ... <domainCapabilities> -The ``firmware`` enum corresponds to the ``firmware`` attribute of the ``os`` -element in the domain XML. The presence of this enum means libvirt is capable of -the so-called firmware auto-selection feature. And the listed firmware values -represent the accepted input in the domain XML. Note that the ``firmware`` enum -reports only those values for which a firmware "descriptor file" exists on the -host. Firmware descriptor file is a small JSON document that describes details -about a given BIOS or UEFI binary on the host, e.g. the firmware binary path, -its architecture, supported machine types, NVRAM template, etc. This ensures -that the reported values won't cause a failure on guest boot. +The presence of the ``firmware`` enum means that libvirt can perform firmware +autoselection, and each of the values is guaranteed to be usable. In the +domain XML, firmware autoselection is enabled as follows: + +:: + + <os firmware='efi'> + ... + +Autoselection is the recommended mechanism for configuring the guest firmware. +Providing paths and other information manually is discouraged. The ``<firmwareFeatures/>`` element :since:`(since 12.1.0)` contains one enum for each of the features that can be used to fine-tune the firmware @@ -196,27 +198,34 @@ such as: would not work, since ``no`` is not one of the valid values advertised by the ``secureBoot`` enum. -For the ``loader`` element, the following can occur: +The information contained in the ``<loader/>`` element is not relevant when +using firmware autoselection, which is the recommended approach to guest +firmware configuration, and as such can largely be ignored. Its subelements +are the following: ``value`` - List of known firmware binary paths. Currently this is used only to advertise - the known location of OVMF binaries for QEMU. OVMF binaries will only be - listed if they actually exist on host. + One element for each known firmware binary present on the system. + + Note that a binary being present here indicates that the file exists and it + is compatible with the architecture/machine type, but does not provide any + insight into which mechanism (see ``type`` below) should be used to load it. ``type`` - Whether the boot loader is a typical BIOS (``rom``) or a UEFI firmware - (``pflash``). Each ``value`` sub-element under the ``type`` enum represents a - possible value for the ``type`` attribute for the <loader/> element in the - domain XML. E.g. the presence of ``pfalsh`` under the ``type`` enum means - that a domain XML can use UEFI firmware via: <loader/> type="pflash" - ...>/path/to/the/firmware/binary/</loader>. + Whether firmware can be loaded using a ``pflash`` device (UEFI only) or as + a ``rom`` (either UEFI or BIOS). ``readonly`` - Options for the ``readonly`` attribute of the <loader/> element in the domain - XML. + Supported values for the ``readonly`` attribute of the ``<loader/>`` element + in the domain XML. ``secure`` - Options for the ``secure`` attribute of the <loader/> element in the domain - XML. Note that the value ``yes`` is listed only if libvirt detects a firmware - descriptor file that has path to an OVMF binary that supports Secure boot, - and lists its architecture and supported machine type. + Supported values for the ``secure`` attribute of the ``<loader/>`` element + in the domain XML. + + Note that the value ``yes`` is listed if libvirt detects a firmware + descriptor file that points to a firmware binary that implements Secure + Boot and is compatible with the architecture/machine type, but the UEFI + variable store template associated with it might not have the usual set of + Secure Boot certificates enrolled. To figure out whether it's actually + possible to enforce Secure Boot, look at the ``enrolledKeys`` enum inside + the ``<firmwareFeatures/>`` element instead. CPU configuration ~~~~~~~~~~~~~~~~~ -- 2.53.0
On Mon, Feb 23, 2026 at 07:30:45PM +0100, Andrea Bolognani via Devel wrote:
Recommend that users take advantage of firmware autoselection and discourage providing paths manually.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomaincaps.rst | 59 ++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 25 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
We only set the template format if the template path is present, and we should be consistent with that. The format on its own is not very interesting anyway. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 436b06c388..519828f6f9 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1662,8 +1662,10 @@ qemuFirmwareFillDomainCustom(virDomainDef *def) if (!loader) return; - if (!loader->format) + if (loader->path && + !loader->format) { loader->format = VIR_STORAGE_FILE_RAW; + } if (loader->nvramTemplate && !loader->nvramTemplateFormat) { -- 2.53.0
Right now we set this default in the common parsing code, which is not a big problem per se but would get in the way of some upcoming changes. Leave this choice to individual drivers instead. Only the QEMU and Xen drivers use the value for anything, so we can limit the amount of code duplication this change causes. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_postparse.c | 19 ------------------- src/libxl/libxl_domain.c | 6 ++++++ src/qemu/qemu_firmware.c | 5 +++++ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c index 38e731348d..cbaae75c02 100644 --- a/src/conf/domain_postparse.c +++ b/src/conf/domain_postparse.c @@ -89,22 +89,6 @@ virDomainDefPostParseMemory(virDomainDef *def, } -static int -virDomainDefPostParseOs(virDomainDef *def) -{ - if (!def->os.loader) - return 0; - - if (def->os.loader->path && - def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_NONE) { - /* By default, loader is type of 'rom' */ - def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; - } - - return 0; -} - - static void virDomainDefPostParseMemtune(virDomainDef *def) { @@ -1251,9 +1235,6 @@ virDomainDefPostParseCommon(virDomainDef *def, if (virDomainDefPostParseMemory(def, data->parseFlags) < 0) return -1; - if (virDomainDefPostParseOs(def) < 0) - return -1; - virDomainDefPostParseMemtune(def); if (virDomainDefRejectDuplicateControllers(def) < 0) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 9842d6fece..c6717e31cf 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -279,6 +279,12 @@ libxlDomainDefPostParse(virDomainDef *def, def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON; } + if (def->os.loader && + def->os.loader->path && + !def->os.loader->type) { + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; + } + /* add implicit balloon device */ if (def->memballoon == NULL) { virDomainMemballoonDef *memballoon; diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 519828f6f9..6a074055ca 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1662,6 +1662,11 @@ qemuFirmwareFillDomainCustom(virDomainDef *def) if (!loader) return; + if (loader->path && + !loader->type) { + loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; + } + if (loader->path && !loader->format) { loader->format = VIR_STORAGE_FILE_RAW; -- 2.53.0
Most of the JSON firmware descriptors in our test suite come from the Fedora package for edk2, but there are a few additional ones that we have created ourselves to ensure coverage of uncommon or problematic scenarios. In order to make sure that such descriptors are clearly marked as custom, rename them to include the string "libvirt" in the path. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- .../etc/qemu/firmware/20-bios.json | 1 - .../etc/qemu/firmware/20-libvirt-bios.json | 1 + .../etc/qemu/firmware/59-combined.json | 1 - .../etc/qemu/firmware/59-libvirt-combined.json | 1 + .../{92-masked.json => 92-libvirt-masked.json} | 0 .../{10-bios.json => 10-libvirt-bios.json} | 0 ...90-combined.json => 90-libvirt-combined.json} | 0 .../{91-bios.json => 91-libvirt-bios.json} | 0 .../{92-masked.json => 92-libvirt-masked.json} | 0 .../{93-invalid.json => 93-libvirt-invalid.json} | 0 tests/qemufirmwaretest.c | 16 ++++++++-------- 11 files changed, 10 insertions(+), 10 deletions(-) delete mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/20-bios.json create mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/20-libvirt-bios.json delete mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/59-combined.json create mode 120000 tests/qemufirmwaredata/etc/qemu/firmware/59-libvirt-combined.json rename tests/qemufirmwaredata/etc/qemu/firmware/{92-masked.json => 92-libvirt-masked.json} (100%) rename tests/qemufirmwaredata/home/user/.config/qemu/firmware/{10-bios.json => 10-libvirt-bios.json} (100%) rename tests/qemufirmwaredata/usr/share/qemu/firmware/{90-combined.json => 90-libvirt-combined.json} (100%) rename tests/qemufirmwaredata/usr/share/qemu/firmware/{91-bios.json => 91-libvirt-bios.json} (100%) rename tests/qemufirmwaredata/usr/share/qemu/firmware/{92-masked.json => 92-libvirt-masked.json} (100%) rename tests/qemufirmwaredata/usr/share/qemu/firmware/{93-invalid.json => 93-libvirt-invalid.json} (100%) diff --git a/tests/qemufirmwaredata/etc/qemu/firmware/20-bios.json b/tests/qemufirmwaredata/etc/qemu/firmware/20-bios.json deleted file mode 120000 index 2c274dddc2..0000000000 --- a/tests/qemufirmwaredata/etc/qemu/firmware/20-bios.json +++ /dev/null @@ -1 +0,0 @@ -../../../usr/share/qemu/firmware/91-bios.json \ No newline at end of file diff --git a/tests/qemufirmwaredata/etc/qemu/firmware/20-libvirt-bios.json b/tests/qemufirmwaredata/etc/qemu/firmware/20-libvirt-bios.json new file mode 120000 index 0000000000..fab8877c3e --- /dev/null +++ b/tests/qemufirmwaredata/etc/qemu/firmware/20-libvirt-bios.json @@ -0,0 +1 @@ +../../../usr/share/qemu/firmware/91-libvirt-bios.json \ No newline at end of file diff --git a/tests/qemufirmwaredata/etc/qemu/firmware/59-combined.json b/tests/qemufirmwaredata/etc/qemu/firmware/59-combined.json deleted file mode 120000 index da9099ffb7..0000000000 --- a/tests/qemufirmwaredata/etc/qemu/firmware/59-combined.json +++ /dev/null @@ -1 +0,0 @@ -../../../usr/share/qemu/firmware/90-combined.json \ No newline at end of file diff --git a/tests/qemufirmwaredata/etc/qemu/firmware/59-libvirt-combined.json b/tests/qemufirmwaredata/etc/qemu/firmware/59-libvirt-combined.json new file mode 120000 index 0000000000..74e63c4574 --- /dev/null +++ b/tests/qemufirmwaredata/etc/qemu/firmware/59-libvirt-combined.json @@ -0,0 +1 @@ +../../../usr/share/qemu/firmware/90-libvirt-combined.json \ No newline at end of file diff --git a/tests/qemufirmwaredata/etc/qemu/firmware/92-masked.json b/tests/qemufirmwaredata/etc/qemu/firmware/92-libvirt-masked.json similarity index 100% rename from tests/qemufirmwaredata/etc/qemu/firmware/92-masked.json rename to tests/qemufirmwaredata/etc/qemu/firmware/92-libvirt-masked.json diff --git a/tests/qemufirmwaredata/home/user/.config/qemu/firmware/10-bios.json b/tests/qemufirmwaredata/home/user/.config/qemu/firmware/10-libvirt-bios.json similarity index 100% rename from tests/qemufirmwaredata/home/user/.config/qemu/firmware/10-bios.json rename to tests/qemufirmwaredata/home/user/.config/qemu/firmware/10-libvirt-bios.json diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/90-combined.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/90-libvirt-combined.json similarity index 100% rename from tests/qemufirmwaredata/usr/share/qemu/firmware/90-combined.json rename to tests/qemufirmwaredata/usr/share/qemu/firmware/90-libvirt-combined.json diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/91-bios.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/91-libvirt-bios.json similarity index 100% rename from tests/qemufirmwaredata/usr/share/qemu/firmware/91-bios.json rename to tests/qemufirmwaredata/usr/share/qemu/firmware/91-libvirt-bios.json diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/92-masked.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/92-libvirt-masked.json similarity index 100% rename from tests/qemufirmwaredata/usr/share/qemu/firmware/92-masked.json rename to tests/qemufirmwaredata/usr/share/qemu/firmware/92-libvirt-masked.json diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/93-invalid.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/93-libvirt-invalid.json similarity index 100% rename from tests/qemufirmwaredata/usr/share/qemu/firmware/93-invalid.json rename to tests/qemufirmwaredata/usr/share/qemu/firmware/93-libvirt-invalid.json diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c index 2eb9d8e701..e09f50592b 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -84,7 +84,7 @@ testFWPrecedence(const void *opaque G_GNUC_UNUSED) g_autofree char *fakehome = NULL; g_auto(GStrv) fwList = NULL; const char *expected[] = { - SYSCONFDIR "/qemu/firmware/20-bios.json", + SYSCONFDIR "/qemu/firmware/20-libvirt-bios.json", PREFIX "/share/qemu/firmware/30-edk2-ovmf-4m-qcow2-x64-sb-enrolled.json", PREFIX "/share/qemu/firmware/31-edk2-ovmf-2m-raw-x64-sb-enrolled.json", PREFIX "/share/qemu/firmware/40-edk2-ovmf-4m-qcow2-x64-sb.json", @@ -98,12 +98,12 @@ testFWPrecedence(const void *opaque G_GNUC_UNUSED) PREFIX "/share/qemu/firmware/51-edk2-ovmf-2m-raw-x64-nosb.json", PREFIX "/share/qemu/firmware/52-edk2-aarch64-verbose-qcow2.json", PREFIX "/share/qemu/firmware/53-edk2-aarch64-verbose-raw.json", - SYSCONFDIR "/qemu/firmware/59-combined.json", + SYSCONFDIR "/qemu/firmware/59-libvirt-combined.json", PREFIX "/share/qemu/firmware/60-edk2-ovmf-x64-amdsev.json", PREFIX "/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json", - PREFIX "/share/qemu/firmware/90-combined.json", - PREFIX "/share/qemu/firmware/91-bios.json", - PREFIX "/share/qemu/firmware/93-invalid.json", + PREFIX "/share/qemu/firmware/90-libvirt-combined.json", + PREFIX "/share/qemu/firmware/91-libvirt-bios.json", + PREFIX "/share/qemu/firmware/93-libvirt-invalid.json", NULL }; const char **e; @@ -285,9 +285,9 @@ mymain(void) DO_PARSE_TEST("usr/share/qemu/firmware/53-edk2-aarch64-verbose-raw.json"); DO_PARSE_TEST("usr/share/qemu/firmware/60-edk2-ovmf-x64-amdsev.json"); DO_PARSE_TEST("usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json"); - DO_PARSE_TEST("usr/share/qemu/firmware/90-combined.json"); - DO_PARSE_TEST("usr/share/qemu/firmware/91-bios.json"); - DO_PARSE_FAILURE_TEST("usr/share/qemu/firmware/93-invalid.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/90-libvirt-combined.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/91-libvirt-bios.json"); + DO_PARSE_FAILURE_TEST("usr/share/qemu/firmware/93-libvirt-invalid.json"); if (virTestRun("QEMU FW precedence test", testFWPrecedence, NULL) < 0) ret = -1; -- 2.53.0
This moves the definition of the <nvram> element out of the fairly complex oshvm define and will make it easier to later add the <varstore> element without making things unmanageable. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/schemas/domaincommon.rng | 54 +++++++++++++++++-------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index dafbdc63e7..e09f6e80f3 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -349,31 +349,7 @@ </element> </optional> <optional> - <element name="nvram"> - <optional> - <attribute name="template"> - <ref name="absFilePath"/> - </attribute> - </optional> - <optional> - <attribute name="templateFormat"> - <ref name="pflashFormatTypes"/> - </attribute> - </optional> - <optional> - <ref name="pflashFormat"/> - </optional> - <optional> - <choice> - <group> - <ref name="absFilePath"/> - </group> - <group> - <ref name="diskSource"/> - </group> - </choice> - </optional> - </element> + <ref name="osnvram"/> </optional> <optional> <ref name="osbootkernel"/> @@ -452,6 +428,34 @@ </element> </define> + <define name="osnvram"> + <element name="nvram"> + <optional> + <attribute name="template"> + <ref name="absFilePath"/> + </attribute> + </optional> + <optional> + <attribute name="templateFormat"> + <ref name="pflashFormatTypes"/> + </attribute> + </optional> + <optional> + <ref name="pflashFormat"/> + </optional> + <optional> + <choice> + <group> + <ref name="absFilePath"/> + </group> + <group> + <ref name="diskSource"/> + </group> + </choice> + </optional> + </element> + </define> + <define name="osexe"> <element name="os"> <interleave> -- 2.53.0
On Mon, Feb 23, 2026 at 07:30:49PM +0100, Andrea Bolognani via Devel wrote:
This moves the definition of the <nvram> element out of the fairly complex oshvm define and will make it easier to later add the <varstore> element without making things unmanageable.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/schemas/domaincommon.rng | 54 +++++++++++++++++-------------- 1 file changed, 29 insertions(+), 25 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
This will be used to configure the backing storage used by the uefi-vars QEMU device. Dealing with the element itself is trivial, however we have to refactor the existing code which deals with the loader and nvram elements slightly: in particular, we can no longer perform an early exit if those elements are absent. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomain.rst | 23 +++++++-- docs/kbase/secureboot.rst | 46 +++++++++++------- src/conf/domain_conf.c | 79 ++++++++++++++++++++++++++++--- src/conf/domain_conf.h | 9 ++++ src/conf/schemas/domaincommon.rng | 22 ++++++++- src/conf/virconftypes.h | 2 + src/libvirt_private.syms | 2 + 7 files changed, 156 insertions(+), 27 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index db664857af..7871613017 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -196,9 +196,9 @@ harddisk, cdrom, network) determining where to obtain/find the boot image. ``firmware`` The ``firmware`` attribute allows management applications to automatically - fill ``<loader/>`` and ``<nvram/>`` elements and possibly enable some - features required by selected firmware. Accepted values are ``bios`` and - ``efi``. + fill ``<loader/>`` and ``<nvram/>`` or ``<varstore/>`` elements and possibly + enable some features required by selected firmware. Accepted values are + ``bios`` and ``efi``. The selection process scans for files describing installed firmware images in specified location and uses the most specific one which fulfills domain requirements. The locations in order of preference (from generic to most @@ -311,6 +311,23 @@ harddisk, cdrom, network) determining where to obtain/find the boot image. It is not valid to provide this element if the loader is marked as stateless. +``varstore`` + This works much the same way as the ``<nvram/>`` element described above, + except that variable storage is handled by the ``uefi-vars`` QEMU device + instead of being backed by a pflash device. :since:`Since 12.1.0 (QEMU only)` + + The ``path`` attribute contains the path of the domain-specific file where + variables are stored, while the ``template`` attribute points to a template + that the domain-specific file can be (re)generated from. Assuming that the + necessary JSON firmware descriptor files are present, both attributes will + be filled in automatically by libvirt. + + Using ``<varstore/>`` instead of ``<nvram/>`` is particularly useful on + non-x86 architectures such as aarch64, where it represent the only way to + get Secure Boot working. It can be used on x86 too, and doing so will make + it possible to keep UEFI authenticated variables safe from tampering without + requiring the use of SMM emulation. + ``boot`` The ``dev`` attribute takes one of the values "fd", "hd", "cdrom" or "network" and is used to specify the next boot device to consider. The diff --git a/docs/kbase/secureboot.rst b/docs/kbase/secureboot.rst index 6c22b08d22..b411b65f00 100644 --- a/docs/kbase/secureboot.rst +++ b/docs/kbase/secureboot.rst @@ -74,8 +74,8 @@ Changing an existing VM When a VM is defined, libvirt will pick the firmware that best satisfies the provided criteria and record this information for use -on subsequent boots. The resulting XML configuration will look like -this: +on subsequent boots. The resulting XML configuration will look either +like this: :: @@ -88,14 +88,28 @@ this: <nvram template='/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/vm_VARS.fd</nvram> </os> +or like this: + +:: + + <os firmware='efi'> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> + </firmware> + <loader type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <varstore template='/usr/share/edk2/aarch64/vars.secboot.json' path='/var/lib/libvirt/qemu/varstore/vm.json'/> + </os> + In order to force libvirt to repeat the firmware autoselection -process, it's necessary to remove the ``<loader>`` and ``<nvram>`` -elements. Failure to do so will likely result in an error. +process, it's necessary to remove the ``<loader>`` as well as the +``<nvram>`` or ``<varstore>`` elements, depending on what's +applicable. Failure to do so will likely result in an error. Note that updating the XML configuration as described above is -**not** enough to change the Secure Boot status: the NVRAM file -associated with the VM has to be regenerated from its template as -well. +**not** enough to change the Secure Boot status: the NVRAM/varstore +file associated with the VM has to be regenerated from its template +as well. In order to do that, update the XML and then start the VM with @@ -107,9 +121,9 @@ This option is only available starting with libvirt 8.1.0, so if your version of libvirt is older than that you will have to delete the NVRAM file manually before starting the VM. -Most guest operating systems will be able to cope with the NVRAM file -being reinitialized, but in some cases the VM will be unable to boot -after the change. +Most guest operating systems will be able to cope with the +NVRAM/varstore file being reinitialized, but in some cases the VM +will be unable to boot after the change. Additional information @@ -126,15 +140,15 @@ can be used to validate the operating system signature need to be provided as well. Asking for the ``enrolled-keys`` firmware feature to be enabled will -cause libvirt to initialize the NVRAM file associated with the VM -from a template that contains a suitable set of keys. These keys -being present will cause the firmware to enforce the Secure Boot +cause libvirt to initialize the NVRAM/varstore file associated with +the VM from a template that contains a suitable set of keys. These +keys being present will cause the firmware to enforce the Secure Boot signing requirements. The opposite configuration, where the feature is explicitly disabled, -will result in no keys being present in the NVRAM file. Unable to -verify signatures, the firmware will allow even unsigned operating -systems to run. +will result in no keys being present in the NVRAM/varstore file. +Unable to verify signatures, the firmware will allow even unsigned +operating systems to run. If running unsigned code is desired, it's also possible to ask for the ``secure-boot`` feature to be disabled, which will cause libvirt diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 453e301041..1384e9f3ab 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3960,6 +3960,27 @@ virDomainLoaderDefFree(virDomainLoaderDef *loader) g_free(loader); } +virDomainVarstoreDef * +virDomainVarstoreDefNew(void) +{ + virDomainVarstoreDef *def = NULL; + + def = g_new0(virDomainVarstoreDef, 1); + + return def; +} + +void +virDomainVarstoreDefFree(virDomainVarstoreDef *varstore) +{ + if (!varstore) + return; + + g_free(varstore->path); + g_free(varstore->template); + g_free(varstore); +} + static void virDomainResctrlMonDefFree(virDomainResctrlMonDef *domresmon) @@ -4062,6 +4083,7 @@ virDomainOSDefClear(virDomainOSDef *os) virDomainOSACPITableDefFree(os->acpiTables[i]); g_free(os->acpiTables); virDomainLoaderDefFree(os->loader); + virDomainVarstoreDefFree(os->varstore); g_free(os->bootloader); g_free(os->bootloaderArgs); } @@ -18088,6 +18110,17 @@ virDomainLoaderDefParseXMLLoader(virDomainLoaderDef *loader, } +static int +virDomainVarstoreDefParseXML(virDomainVarstoreDef *varstore, + xmlNodePtr varstoreNode) +{ + varstore->path = virXMLPropString(varstoreNode, "path"); + varstore->template = virXMLPropString(varstoreNode, "template"); + + return 0; +} + + static int virDomainLoaderDefParseXML(virDomainLoaderDef *loader, xmlNodePtr loaderNode, @@ -18535,16 +18568,29 @@ virDomainDefParseBootLoaderOptions(virDomainDef *def, xmlNodePtr loaderNode = virXPathNode("./os/loader[1]", ctxt); xmlNodePtr nvramNode = virXPathNode("./os/nvram[1]", ctxt); xmlNodePtr nvramSourceNode = virXPathNode("./os/nvram/source[1]", ctxt); + xmlNodePtr varstoreNode = virXPathNode("./os/varstore[1]", ctxt); - if (!loaderNode && !nvramNode) - return 0; + if (nvramNode && varstoreNode) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Cannot have both <nvram> and <varstore>")); + return -1; + } - def->os.loader = virDomainLoaderDefNew(); + if (loaderNode || nvramNode) { + def->os.loader = virDomainLoaderDefNew(); - if (virDomainLoaderDefParseXML(def->os.loader, - loaderNode, nvramNode, nvramSourceNode, - ctxt, xmlopt, flags) < 0) - return -1; + if (virDomainLoaderDefParseXML(def->os.loader, + loaderNode, nvramNode, nvramSourceNode, + ctxt, xmlopt, flags) < 0) + return -1; + } + + if (varstoreNode) { + def->os.varstore = virDomainVarstoreDefNew(); + + if (virDomainVarstoreDefParseXML(def->os.varstore, varstoreNode) < 0) + return -1; + } return 0; } @@ -28248,6 +28294,20 @@ virDomainLoaderDefFormat(virBuffer *buf, return 0; } +static int +virDomainVarstoreDefFormat(virBuffer *buf, + virDomainVarstoreDef *varstore) +{ + g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + + virBufferEscapeString(&attrBuf, " template='%s'", varstore->template); + virBufferEscapeString(&attrBuf, " path='%s'", varstore->path); + + virXMLFormatElementEmpty(buf, "varstore", &attrBuf, NULL); + + return 0; +} + static void virDomainKeyWrapDefFormat(virBuffer *buf, virDomainKeyWrapDef *keywrap) { @@ -29720,6 +29780,11 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, if (def->os.loader && virDomainLoaderDefFormat(buf, def->os.loader, xmlopt, flags) < 0) return -1; + + if (def->os.varstore && + virDomainVarstoreDefFormat(buf, def->os.varstore) < 0) + return -1; + virBufferEscapeString(buf, "<kernel>%s</kernel>\n", def->os.kernel); virBufferEscapeString(buf, "<initrd>%s</initrd>\n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a13f6d79e9..e63230beec 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2423,6 +2423,14 @@ struct _virDomainLoaderDef { virDomainLoaderDef *virDomainLoaderDefNew(void); void virDomainLoaderDefFree(virDomainLoaderDef *loader); +struct _virDomainVarstoreDef { + char *path; + char *template; +}; + +virDomainVarstoreDef *virDomainVarstoreDefNew(void); +void virDomainVarstoreDefFree(virDomainVarstoreDef *varstore); + typedef enum { VIR_DOMAIN_IOAPIC_NONE = 0, VIR_DOMAIN_IOAPIC_QEMU, @@ -2576,6 +2584,7 @@ struct _virDomainOSDef { size_t nacpiTables; virDomainOSACPITableDef **acpiTables; virDomainLoaderDef *loader; + virDomainVarstoreDef *varstore; char *bootloader; char *bootloaderArgs; int smbios_mode; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index e09f6e80f3..376218118d 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -349,7 +349,10 @@ </element> </optional> <optional> - <ref name="osnvram"/> + <choice> + <ref name="osnvram"/> + <ref name="osvarstore"/> + </choice> </optional> <optional> <ref name="osbootkernel"/> @@ -456,6 +459,23 @@ </element> </define> + <define name="osvarstore"> + <element name="varstore"> + <interleave> + <optional> + <attribute name="template"> + <ref name="absFilePath"/> + </attribute> + </optional> + <optional> + <attribute name="path"> + <ref name="absFilePath"/> + </attribute> + </optional> + </interleave> + </element> + </define> + <define name="osexe"> <element name="os"> <interleave> diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 6e2573035a..0596791a4d 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -164,6 +164,8 @@ typedef struct _virDomainLeaseDef virDomainLeaseDef; typedef struct _virDomainLoaderDef virDomainLoaderDef; +typedef struct _virDomainVarstoreDef virDomainVarstoreDef; + typedef struct _virDomainMemballoonDef virDomainMemballoonDef; typedef struct _virDomainMemoryDef virDomainMemoryDef; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b200037189..19edf7eb12 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -719,6 +719,8 @@ virDomainTPMProfileRemoveDisabledTypeToString; virDomainTPMVersionTypeFromString; virDomainTPMVersionTypeToString; virDomainUSBDeviceDefForeach; +virDomainVarstoreDefFree; +virDomainVarstoreDefNew; virDomainVideoDefaultRAM; virDomainVideoDefClear; virDomainVideoDefFree; -- 2.53.0
On Mon, Feb 23, 2026 at 07:30:50PM +0100, Andrea Bolognani via Devel wrote:
This will be used to configure the backing storage used by the uefi-vars QEMU device.
Dealing with the element itself is trivial, however we have to refactor the existing code which deals with the loader and nvram elements slightly: in particular, we can no longer perform an early exit if those elements are absent.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomain.rst | 23 +++++++-- docs/kbase/secureboot.rst | 46 +++++++++++------- src/conf/domain_conf.c | 79 ++++++++++++++++++++++++++++--- src/conf/domain_conf.h | 9 ++++ src/conf/schemas/domaincommon.rng | 22 ++++++++- src/conf/virconftypes.h | 2 + src/libvirt_private.syms | 2 + 7 files changed, 156 insertions(+), 27 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index db664857af..7871613017 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst
@@ -311,6 +311,23 @@ harddisk, cdrom, network) determining where to obtain/find the boot image. It is not valid to provide this element if the loader is marked as stateless.
+``varstore`` + This works much the same way as the ``<nvram/>`` element described above, + except that variable storage is handled by the ``uefi-vars`` QEMU device + instead of being backed by a pflash device. :since:`Since 12.1.0 (QEMU only)` + + The ``path`` attribute contains the path of the domain-specific file where + variables are stored, while the ``template`` attribute points to a template + that the domain-specific file can be (re)generated from. Assuming that the + necessary JSON firmware descriptor files are present, both attributes will + be filled in automatically by libvirt. + + Using ``<varstore/>`` instead of ``<nvram/>`` is particularly useful on + non-x86 architectures such as aarch64, where it represent the only way to
s/represent/represents/
+ get Secure Boot working. It can be used on x86 too, and doing so will make + it possible to keep UEFI authenticated variables safe from tampering without + requiring the use of SMM emulation. + ``boot`` The ``dev`` attribute takes one of the values "fd", "hd", "cdrom" or "network" and is used to specify the next boot device to consider. The
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
The code is reworked quite significantly, but most of the existing checks are preserved. Those that aren't, notably the one that allowed pflash as the only acceptable non-stateless firmware type, are intentionally removed because they will no longer reflect reality once support for the uefi-vars QEMU device is introduced. As a side effect, reworking the function in this fashion resolves a subtle bug: due to the early exits that were being performed when the loader element was missing, the checks at the bottom of the function (related to the shim and kernel elements) were effectively never performed. This is no longer the case. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_validate.c | 82 +++++++------------ ...-auto-bios-not-stateless.x86_64-latest.err | 2 +- ...-auto-bios-not-stateless.x86_64-latest.xml | 35 ++++++++ ...firmware-auto-bios-nvram.x86_64-latest.err | 2 +- ...nual-bios-not-stateless.x86_64-latest.args | 32 ++++++++ ...anual-bios-not-stateless.x86_64-latest.err | 1 - ...anual-bios-not-stateless.x86_64-latest.xml | 28 +++++++ ...nual-efi-nvram-stateless.x86_64-latest.err | 2 +- ...nvram-template-stateless.x86_64-latest.err | 2 +- ...ware-manual-efi-rw-nvram.x86_64-latest.err | 2 +- tests/qemuxmlconftest.c | 7 +- 11 files changed, 135 insertions(+), 60 deletions(-) create mode 100644 tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 1ad614935f..7e3da84767 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -1723,100 +1723,78 @@ virDomainDefOSValidate(const virDomainDef *def, virDomainXMLOption *xmlopt) { virDomainLoaderDef *loader = def->os.loader; + virDomainVarstoreDef *varstore = def->os.varstore; + virDomainOsDefFirmware firmware = def->os.firmware; + int *firmwareFeatures = def->os.firmwareFeatures; + bool usesNvram = loader && (loader->nvram || loader->nvramTemplate || loader->nvramTemplateFormat); - if (def->os.firmware) { + if (firmware) { if (xmlopt && !(xmlopt->config.features & VIR_DOMAIN_DEF_FEATURE_FW_AUTOSELECT)) { virReportError(VIR_ERR_XML_DETAIL, "%s", _("firmware auto selection not implemented for this driver")); return -1; } - if (def->os.firmwareFeatures && - def->os.firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_ENROLLED_KEYS] == VIR_TRISTATE_BOOL_YES && - def->os.firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_SECURE_BOOT] == VIR_TRISTATE_BOOL_NO) { + if (firmwareFeatures && + firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_ENROLLED_KEYS] == VIR_TRISTATE_BOOL_YES && + firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_SECURE_BOOT] == VIR_TRISTATE_BOOL_NO) { virReportError(VIR_ERR_XML_DETAIL, "%s", _("firmware feature 'enrolled-keys' cannot be enabled when firmware feature 'secure-boot' is disabled")); return -1; } - - if (!loader) - return 0; - - if (loader->nvram && def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) { - virReportError(VIR_ERR_XML_DETAIL, - _("firmware type '%1$s' does not support nvram"), - virDomainOsDefFirmwareTypeToString(def->os.firmware)); - return -1; - } } else { - if (def->os.firmwareFeatures) { + if (firmwareFeatures) { virReportError(VIR_ERR_XML_DETAIL, "%s", _("cannot use feature-based firmware autoselection when firmware autoselection is disabled")); return -1; } - if (!loader) - return 0; - - if (!loader->path) { + if (loader && !loader->path) { virReportError(VIR_ERR_XML_DETAIL, "%s", _("no loader path specified and firmware auto selection disabled")); return -1; } } - if (loader->readonly == VIR_TRISTATE_BOOL_NO) { - if (loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) { + if (loader && loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) { + if (loader->readonly == VIR_TRISTATE_BOOL_NO) { virReportError(VIR_ERR_XML_DETAIL, "%s", _("ROM loader type cannot be used as read/write")); return -1; } - if (loader->nvramTemplate) { - virReportError(VIR_ERR_XML_DETAIL, "%s", - _("NVRAM template is not permitted when loader is read/write")); + if (loader->format && + loader->format != VIR_STORAGE_FILE_RAW) { + virReportError(VIR_ERR_XML_DETAIL, + _("Invalid format '%1$s' for ROM loader type"), + virStorageFileFormatTypeToString(loader->format)); return -1; } + } - if (loader->nvram) { + if (usesNvram && varstore) { virReportError(VIR_ERR_XML_DETAIL, "%s", - _("NVRAM is not permitted when loader is read/write")); + _("Only one of NVRAM/varstore can be used")); return -1; - } } - if (loader->stateless == VIR_TRISTATE_BOOL_YES) { - if (loader->nvramTemplate) { - virReportError(VIR_ERR_XML_DETAIL, "%s", - _("NVRAM template is not permitted when loader is stateless")); + if (usesNvram || varstore) { + if (firmware && firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) { + virReportError(VIR_ERR_XML_DETAIL, + _("Firmware type '%1$s' does not support variable storage (NVRAM/varstore)"), + virDomainOsDefFirmwareTypeToString(firmware)); return -1; } - if (loader->nvram) { - virReportError(VIR_ERR_XML_DETAIL, "%s", - _("NVRAM is not permitted when loader is stateless")); - return -1; - } - } else if (loader->stateless == VIR_TRISTATE_BOOL_NO) { - if (def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_NONE) { - if (def->os.loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH) { - virReportError(VIR_ERR_XML_DETAIL, "%s", - _("Only pflash loader type permits NVRAM")); - return -1; - } - } else if (def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) { + if (loader && loader->stateless == VIR_TRISTATE_BOOL_YES) { virReportError(VIR_ERR_XML_DETAIL, "%s", - _("Only EFI firmware permits NVRAM")); + _("Variable storage (NVRAM/varstore) is not permitted when loader is stateless")); return -1; } - } - if (loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) { - if (loader->format && - loader->format != VIR_STORAGE_FILE_RAW) { - virReportError(VIR_ERR_XML_DETAIL, - _("Invalid format '%1$s' for ROM loader type"), - virStorageFileFormatTypeToString(loader->format)); + if (loader && loader->readonly == VIR_TRISTATE_BOOL_NO) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("Variable storage (NVRAM/varstore) is not permitted when loader is read/write")); return -1; } } diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err index b058f970a4..743fe27a97 100644 --- a/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err @@ -1 +1 @@ -Only EFI firmware permits NVRAM +operation failed: Unable to find 'bios' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml new file mode 100644 index 0000000000..062835e351 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml @@ -0,0 +1,35 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os firmware='bios'> + <type arch='x86_64' machine='pc-q35-10.0'>hvm</type> + <loader stateless='no' format='raw'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pcie-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <watchdog model='itco' action='reset'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err index 772beb49e2..c4eeb92788 100644 --- a/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err @@ -1 +1 @@ -firmware type 'bios' does not support nvram +Firmware type 'bios' does not support variable storage (NVRAM/varstore) diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args new file mode 100644 index 0000000000..969c7ad68c --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args @@ -0,0 +1,32 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine pc-i440fx-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-bios /usr/share/seabios/bios.bin \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err deleted file mode 100644 index 188a5a4180..0000000000 --- a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err +++ /dev/null @@ -1 +0,0 @@ -Only pflash loader type permits NVRAM diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml new file mode 100644 index 0000000000..075da36d00 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml @@ -0,0 +1,28 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-10.0'>hvm</type> + <loader type='rom' stateless='no' format='raw'>/usr/share/seabios/bios.bin</loader> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err index de8db3763d..9bfd4465ab 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err @@ -1 +1 @@ -NVRAM is not permitted when loader is stateless +Variable storage (NVRAM/varstore) is not permitted when loader is stateless diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err index 95ec794c17..9bfd4465ab 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err @@ -1 +1 @@ -NVRAM template is not permitted when loader is stateless +Variable storage (NVRAM/varstore) is not permitted when loader is stateless diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err index d0cf62061a..708b4838d4 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err @@ -1 +1 @@ -NVRAM is not permitted when loader is read/write +Variable storage (NVRAM/varstore) is not permitted when loader is read/write diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index d2ab4a71b5..18c2ac5701 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1581,7 +1581,10 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-manual-bios"); DO_TEST_CAPS_LATEST("firmware-manual-bios-stateless"); - DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-not-stateless"); + /* This combination doesn't make sense (BIOS is stateless by definition) + * but unfortunately there's no way for libvirt to report an error in this + * scenario. The stateless=no attribute will effectively be ignored */ + DO_TEST_CAPS_LATEST("firmware-manual-bios-not-stateless"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-rw"); DO_TEST_CAPS_LATEST("firmware-manual-efi"); DO_TEST_CAPS_LATEST("firmware-manual-efi-features"); @@ -1634,7 +1637,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-bios"); DO_TEST_CAPS_LATEST("firmware-auto-bios-stateless"); DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-bios-rw"); - DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-bios-not-stateless"); + DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-bios-not-stateless"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-bios-nvram"); DO_TEST_CAPS_LATEST("firmware-auto-efi"); DO_TEST_CAPS_LATEST_ABI_UPDATE("firmware-auto-efi"); -- 2.53.0
This capability indicates the availability of the uefi-vars device. The actual name of the QEMU device varies slightly depending on the architecture: it's uefi-vars-x64 on x86_64, uefi-vars-sysbus on other UEFI architectures (aarch64, riscv64, loongarch64). Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 3 +++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml | 1 + tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml | 1 + 13 files changed, 15 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 9af58c912a..048ef66c12 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -761,6 +761,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 490 */ "scsi-block.migrate-pr", /* QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR */ "iommufd", /* QEMU_CAPS_OBJECT_IOMMUFD */ + "uefi-vars", /* QEMU_CAPS_DEVICE_UEFI_VARS */ ); @@ -1469,6 +1470,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH }, { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, { "iommufd", QEMU_CAPS_OBJECT_IOMMUFD }, + { "uefi-vars-x64", QEMU_CAPS_DEVICE_UEFI_VARS }, + { "uefi-vars-sysbus", QEMU_CAPS_DEVICE_UEFI_VARS }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 8d5c5cc94c..a48e1d0367 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -735,6 +735,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 490 */ QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, /* persistent reservation migration support */ QEMU_CAPS_OBJECT_IOMMUFD, /* -object iommufd */ + QEMU_CAPS_DEVICE_UEFI_VARS, /* -device uefi-vars-{x64,sysbus} */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml index e5f55f461a..b6434e6019 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -165,6 +165,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10000000</version> <microcodeVersion>61700285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml index 74a68c8402..43f848db25 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -211,6 +211,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml index d593dd1ab8..138c34fd47 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -211,6 +211,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml index 3e271824c6..f33b366db8 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml @@ -142,6 +142,7 @@ <flag name='qom-list-get'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10001000</version> <microcodeVersion>39100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml index 512186a341..2a7cd9cac1 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml @@ -194,6 +194,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10001000</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml index d6f1009c77..71311fceaf 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml @@ -216,6 +216,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10001000</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml index 54d10e1433..ac8f50b984 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml @@ -184,6 +184,7 @@ <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002000</version> <microcodeVersion>61700287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml index 38f6a0f6c3..d7a556b4a6 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml @@ -204,6 +204,7 @@ <flag name='mshv'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002000</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml index 1ed21b9bf7..699dad3e20 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml @@ -217,6 +217,7 @@ <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002000</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml index 4e6edf8df9..233f325224 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml @@ -185,6 +185,7 @@ <flag name='virtio-iommu.aw-bits'/> <flag name='scsi-block.migrate-pr'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002050</version> <microcodeVersion>61700286</microcodeVersion> <package>v10.2.0-1114-gb3abdfa486</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml index 22eaff6545..85d2790b49 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml @@ -218,6 +218,7 @@ <flag name='virtio-iommu.aw-bits'/> <flag name='scsi-block.migrate-pr'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002050</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.2.0-1114-gb3abdfa486</package> -- 2.53.0
The use of varstore requires the uefi-vars device to be present in the QEMU binary. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_validate.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 16dd5fef1a..0eb5d5ea3b 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -753,6 +753,23 @@ qemuValidateDomainDefNvram(const virDomainDef *def, } +static int +qemuValidateDomainDefVarstore(const virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + if (!def->os.varstore) + return 0; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_UEFI_VARS)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("The uefi-vars device is not supported by this QEMU binary")); + return -1; + } + + return 0; +} + + static int qemuValidateDomainDefBoot(const virDomainDef *def, virQEMUCaps *qemuCaps) @@ -796,6 +813,9 @@ qemuValidateDomainDefBoot(const virDomainDef *def, if (qemuValidateDomainDefNvram(def, qemuCaps) < 0) return -1; + + if (qemuValidateDomainDefVarstore(def, qemuCaps) < 0) + return -1; } for (i = 0; i < def->os.nacpiTables; i++) { -- 2.53.0
This test case demonstrates how to manually configure an x86_64 guest to use the uefi-vars device. It fails when using an older version of QEMU which didn't have the device, and succeeds when using the latest version. The relevant bits of the QEMU command line are not generated yet, but that will come in a later commit. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- ...e-manual-efi-varstore-q35.x86_64-8.2.0.err | 1 + ...manual-efi-varstore-q35.x86_64-latest.args | 34 ++++++++++++++++++ ...-manual-efi-varstore-q35.x86_64-latest.xml | 36 +++++++++++++++++++ .../firmware-manual-efi-varstore-q35.xml | 19 ++++++++++ tests/qemuxmlconftest.c | 3 ++ 5 files changed, 93 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err new file mode 100644 index 0000000000..e64c2b21aa --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err @@ -0,0 +1 @@ +unsupported configuration: The uefi-vars device is not supported by this QEMU binary diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args new file mode 100644 index 0000000000..9a899c2a65 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args @@ -0,0 +1,34 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine pc-q35-8.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ +-accel kvm \ +-cpu qemu64 \ +-bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-global ICH9-LPC.noreboot=off \ +-watchdog-action reset \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml new file mode 100644 index 0000000000..296c6e8f59 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml @@ -0,0 +1,36 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <loader type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <varstore path='/path/to/guest.json'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pcie-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <watchdog model='itco' action='reset'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml new file mode 100644 index 0000000000..c1dc00fde8 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml @@ -0,0 +1,19 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <varstore path='/path/to/guest.json'/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 18c2ac5701..d75540042e 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1618,6 +1618,9 @@ mymain(void) ARG_CAPS_VARIANT, "+inteltdx", ARG_END); + DO_TEST_CAPS_LATEST("firmware-manual-efi-varstore-q35"); + DO_TEST_CAPS_VER_PARSE_ERROR("firmware-manual-efi-varstore-q35", "8.2.0"); + /* Make sure all combinations of ACPI and UEFI behave as expected */ DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-acpi-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-manual-efi-acpi-q35"); -- 2.53.0
This test case demonstrates how to manually configure an aarch64 guest to use the uefi-vars device. It currently fails because the QEMU driver does not yet recognize the firmware type as EFI, and so rejects the attempt to use ACPI together with it. That will change in a future commit. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- ...ual-efi-varstore-aarch64.aarch64-8.2.0.err | 1 + ...al-efi-varstore-aarch64.aarch64-latest.err | 1 + .../firmware-manual-efi-varstore-aarch64.xml | 19 +++++++++++++++++++ tests/qemuxmlconftest.c | 2 ++ 4 files changed, 23 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err new file mode 100644 index 0000000000..4fe79bdacf --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err @@ -0,0 +1 @@ +unsupported configuration: ACPI requires UEFI on this architecture diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err new file mode 100644 index 0000000000..4fe79bdacf --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err @@ -0,0 +1 @@ +unsupported configuration: ACPI requires UEFI on this architecture diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml new file mode 100644 index 0000000000..5c545fe0ab --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml @@ -0,0 +1,19 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <loader type='rom'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <varstore path='/path/to/guest.json'/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index d75540042e..615a30fd38 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1620,6 +1620,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-manual-efi-varstore-q35"); DO_TEST_CAPS_VER_PARSE_ERROR("firmware-manual-efi-varstore-q35", "8.2.0"); + DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64", "8.2.0"); /* Make sure all combinations of ACPI and UEFI behave as expected */ DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-acpi-aarch64", "aarch64"); -- 2.53.0
This test case demonstrates how to explicitly opt into using the uefi-vars device for an x86_64 guest. Normally the firmware autoselection process will pick a UEFI build that is loaded via pflash, but by including the <varstore> element in the input XML we can tell the QEMU driver that we want want the uefi-vars device to be used instead. Currently this results in an error, because the firmware autoselection algorithm doesn't yet know how to properly handle the scenario. A future commit will address this and make things work as expected. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- ...are-auto-efi-varstore-q35.x86_64-latest.err | 1 + .../firmware-auto-efi-varstore-q35.xml | 18 ++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 3 files changed, 20 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err new file mode 100644 index 0000000000..b45d304221 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err @@ -0,0 +1 @@ +Only one of NVRAM/varstore can be used diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml new file mode 100644 index 0000000000..9cda95403e --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml @@ -0,0 +1,18 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <varstore/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 615a30fd38..9e330e2935 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1671,6 +1671,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-file"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); + DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-q35"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
This test case demonstrates how to explicitly opt into using the uefi-vars device for an aarch64 guest. Normally the firmware autoselection process will pick a UEFI build that is loaded via pflash, but by including the <varstore> element in the input XML we can tell the QEMU driver that we want want the uefi-vars device to be used instead. Currently this results in an error, because the firmware autoselection algorithm doesn't yet know how to properly handle the scenario. A future commit will address this and make things work as expected. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- ...uto-efi-varstore-aarch64.aarch64-latest.err | 1 + .../firmware-auto-efi-varstore-aarch64.xml | 18 ++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 3 files changed, 20 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err new file mode 100644 index 0000000000..b45d304221 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err @@ -0,0 +1 @@ +Only one of NVRAM/varstore can be used diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml new file mode 100644 index 0000000000..e403c60643 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml @@ -0,0 +1,18 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <varstore/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 9e330e2935..24168b98af 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1672,6 +1672,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-q35"); + DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
This test case demonstrates how to automatically configure an aarch64 guest so that Secure Boot support is available and only signed operating systems are allowed to boot. It currently fails because there is no firmware descriptor that describes a suitable firmware build yet. That will change in a future commit. In addition to the latest version, the test case is also executed against QEMU 8.2.0 specifically. This version of the test case is intended to fail, because the uefi-vars device that we need to support Secure Boot on aarch64 was not yet available in that version of QEMU. The exact error message will change down the line. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- ...fi-enrolled-keys-aarch64.aarch64-8.2.0.err | 1 + ...fi-enrolled-keys-aarch64.aarch64-8.2.0.xml | 30 +++++++++++++++++++ ...i-enrolled-keys-aarch64.aarch64-latest.err | 1 + ...i-enrolled-keys-aarch64.aarch64-latest.xml | 30 +++++++++++++++++++ ...irmware-auto-efi-enrolled-keys-aarch64.xml | 20 +++++++++++++ tests/qemuxmlconftest.c | 2 ++ 6 files changed, 84 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err new file mode 100644 index 0000000000..3edb2b3451 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err @@ -0,0 +1 @@ +operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml new file mode 100644 index 0000000000..5213a41b90 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml @@ -0,0 +1,30 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + </firmware> + <loader format='raw'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <gic version='3'/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err new file mode 100644 index 0000000000..3edb2b3451 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err @@ -0,0 +1 @@ +operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml new file mode 100644 index 0000000000..908a8435f9 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml @@ -0,0 +1,30 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + </firmware> + <loader format='raw'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <gic version='2'/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml new file mode 100644 index 0000000000..6cd382d0fa --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml @@ -0,0 +1,20 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + </firmware> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 24168b98af..ca00dc96f0 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1657,6 +1657,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-enrolled-keys"); + DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_VER_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64", "8.2.0"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-enrolled-keys"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-enrolled-keys-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-smm-off"); -- 2.53.0
When present in a firmware descriptor, this feature indicates that the corresponding executable expects to access variable storage through the uefi-vars QEMU device. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 6a074055ca..8b9b0d91ff 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -145,6 +145,7 @@ typedef enum { QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS, QEMU_FIRMWARE_FEATURE_REQUIRES_SMM, QEMU_FIRMWARE_FEATURE_SECURE_BOOT, + QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS, QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC, QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC, @@ -164,6 +165,7 @@ VIR_ENUM_IMPL(qemuFirmwareFeature, "enrolled-keys", "requires-smm", "secure-boot", + "host-uefi-vars", "verbose-dynamic", "verbose-static" ); @@ -1181,6 +1183,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def, hasEnrolledKeys = true; break; + case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_NONE: @@ -1515,6 +1518,7 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def, case QEMU_FIRMWARE_FEATURE_AMD_SEV_ES: case QEMU_FIRMWARE_FEATURE_AMD_SEV_SNP: case QEMU_FIRMWARE_FEATURE_INTEL_TDX: + case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_NONE: @@ -1570,6 +1574,7 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw, case QEMU_FIRMWARE_FEATURE_NONE: case QEMU_FIRMWARE_FEATURE_ACPI_S3: case QEMU_FIRMWARE_FEATURE_ACPI_S4: + case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_LAST: @@ -2084,6 +2089,7 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_FEATURE_AMD_SEV_ES: case QEMU_FIRMWARE_FEATURE_AMD_SEV_SNP: case QEMU_FIRMWARE_FEATURE_INTEL_TDX: + case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_LAST: -- 2.53.0
The two checks are semantically different, so it makes sense to perform them separately. We will soon extend the first one. While at it, start printing out the value of isConfidential. We could print the value of each firmware feature it's derived from, but that would make things unnecessarily verbose; at the same time, knowing that libvirt believes that the firmware build is targeting the confidential use case can be useful for debugging so it's worth including it. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 8b9b0d91ff..5c923b5a02 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1589,16 +1589,23 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw, * VMs also don't support EFI variable storage in NVRAM, instead * the secureboot state is hardcoded to enabled. */ - if ((!isConfidential && - (supportsSecureBoot != requiresSMM)) || - (hasEnrolledKeys && !supportsSecureBoot)) { + if (!isConfidential && + supportsSecureBoot != requiresSMM) { VIR_WARN("Firmware description '%s' has invalid set of features: " - "%s = %d, %s = %d, %s = %d", + "%s = %d, %s = %d (isConfidential = %d)", filename, qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_REQUIRES_SMM), requiresSMM, qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_SECURE_BOOT), supportsSecureBoot, + isConfidential); + } + if (hasEnrolledKeys && !supportsSecureBoot) { + VIR_WARN("Firmware description '%s' has invalid set of features: " + "%s = %d, %s = %d", + filename, + qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_SECURE_BOOT), + supportsSecureBoot, qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS), hasEnrolledKeys); } -- 2.53.0
Just like with firmware builds targeting the confidential use case, use of the uefi-vars device obviates the need to have SMM emulation enabled while still guaranteeing that protected EFI variables work as intended. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 5c923b5a02..f9cb9058ac 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1552,6 +1552,7 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw, bool requiresSMM = false; bool supportsSecureBoot = false; bool hasEnrolledKeys = false; + bool usesUefiVarsDevice = false; bool isConfidential = false; for (i = 0; i < fw->nfeatures; i++) { @@ -1565,6 +1566,9 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw, case QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS: hasEnrolledKeys = true; break; + case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: + usesUefiVarsDevice = true; + break; case QEMU_FIRMWARE_FEATURE_AMD_SEV: case QEMU_FIRMWARE_FEATURE_AMD_SEV_ES: case QEMU_FIRMWARE_FEATURE_AMD_SEV_SNP: @@ -1574,7 +1578,6 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw, case QEMU_FIRMWARE_FEATURE_NONE: case QEMU_FIRMWARE_FEATURE_ACPI_S3: case QEMU_FIRMWARE_FEATURE_ACPI_S4: - case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_LAST: @@ -1588,14 +1591,21 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw, * support SMM. This is OK, because EFI binaries for confidential * VMs also don't support EFI variable storage in NVRAM, instead * the secureboot state is hardcoded to enabled. + * + * Similarly, use of the uefi-vars QEMU device guarantees that + * protected EFI variables work as expected without requiring SMM + * emulation. */ if (!isConfidential && + !usesUefiVarsDevice && supportsSecureBoot != requiresSMM) { VIR_WARN("Firmware description '%s' has invalid set of features: " - "%s = %d, %s = %d (isConfidential = %d)", + "%s = %d, %s = %d, %s = %d (isConfidential = %d)", filename, qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_REQUIRES_SMM), requiresSMM, + qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS), + usesUefiVarsDevice, qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_SECURE_BOOT), supportsSecureBoot, isConfidential); -- 2.53.0
The existing syntax can only describe stateless firmware builds, while the extended one can additionally describe builds intended for use with the uefi-vars device. This involves including the path to the corresponding varstore template. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index f9cb9058ac..7af3f32b85 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -95,6 +95,7 @@ struct _qemuFirmwareMappingFlash { typedef struct _qemuFirmwareMappingMemory qemuFirmwareMappingMemory; struct _qemuFirmwareMappingMemory { char *filename; + char *template; }; @@ -219,6 +220,7 @@ static void qemuFirmwareMappingMemoryFreeContent(qemuFirmwareMappingMemory *memory) { g_free(memory->filename); + g_free(memory->template); } @@ -406,7 +408,11 @@ qemuFirmwareMappingMemoryParse(const char *path, virJSONValue *doc, qemuFirmwareMappingMemory *memory) { + virJSONValue *uefi_vars; const char *filename; + const char *template; + + uefi_vars = virJSONValueObjectGet(doc, "uefi-vars"); if (!(filename = virJSONValueObjectGetString(doc, "filename"))) { VIR_DEBUG("missing 'filename' in '%s'", path); @@ -415,6 +421,15 @@ qemuFirmwareMappingMemoryParse(const char *path, memory->filename = g_strdup(filename); + if (uefi_vars) { + if (!(template = virJSONValueObjectGetString(uefi_vars, "template"))) { + VIR_DEBUG("missing 'template' for 'uefi-vars' in '%s'", path); + return -1; + } + + memory->template = g_strdup(template); + } + return 0; } @@ -702,6 +717,20 @@ qemuFirmwareMappingMemoryFormat(virJSONValue *mapping, memory->filename) < 0) return -1; + if (memory->template) { + g_autoptr(virJSONValue) uefi_vars = virJSONValueNewObject(); + + if (virJSONValueObjectAppendString(uefi_vars, + "template", + memory->template) < 0) + return -1; + + if (virJSONValueObjectAppend(mapping, + "uefi-vars", + &uefi_vars) < 0) + return -1; + } + return 0; } -- 2.53.0
This was not necessary until now since ROMs couldn't have an associate NVRAM template, and technically speaking they still can't; however, the varstore template serves essentialy the same purpose. The qemuFirmwareGetSupported() helper is used in two places: one is the code that is responsible for filling in domaincaps, where templates are ignored so this change has no impact on it; the other is the qemufirmware test program, where this value being reported is useful as it will allow us to confirm that the JSON firmware descriptors for uefi-vars enabled builds are parsed correctly. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 7af3f32b85..72aae73dcb 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2161,6 +2161,7 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_DEVICE_MEMORY: fwpath = memory->filename; + nvrampath = memory->template; break; case QEMU_FIRMWARE_DEVICE_NONE: -- 2.53.0
We want to advertise whether the element is usable when defining new domains. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomaincaps.rst | 7 +++++++ src/conf/domain_capabilities.c | 10 ++++++++++ src/conf/domain_capabilities.h | 6 ++++++ src/conf/schemas/domaincaps.rng | 9 +++++++++ 4 files changed, 32 insertions(+) diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index 3426b7c9cd..5a1d3f2670 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -141,6 +141,7 @@ domains. <value>no</value> </enum> </loader> + <varstore supported='yes'/> </os> ... <domainCapabilities> @@ -227,6 +228,12 @@ are the following: possible to enforce Secure Boot, look at the ``enrolledKeys`` enum inside the ``<firmwareFeatures/>`` element instead. +The ``<varstore/>`` element :since:`(since 12.1.0)` indicates whether UEFI +variable storage backed by the ``uefi-vars`` QEMU device can be used as an +alternative to pflash-based NVRAM storage. This is the only type of variable +storage compatible with Secure Boot on non-x86 architectures, but it can be +used on x86 too. + CPU configuration ~~~~~~~~~~~~~~~~~ diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 9b3577cd08..78b8e6e6e1 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -449,12 +449,21 @@ virDomainCapsLoaderFormat(virBuffer *buf, FORMAT_EPILOGUE(loader); } +static void +virDomainCapsVarstoreFormat(virBuffer *buf, + const virDomainCapsVarstore *varstore) +{ + FORMAT_PROLOGUE(varstore); + FORMAT_EPILOGUE(varstore); +} + static void virDomainCapsOSFormat(virBuffer *buf, const virDomainCapsOS *os) { const virDomainCapsFirmwareFeatures *firmwareFeatures = &os->firmwareFeatures; const virDomainCapsLoader *loader = &os->loader; + const virDomainCapsVarstore *varstore = &os->varstore; FORMAT_PROLOGUE(os); @@ -462,6 +471,7 @@ virDomainCapsOSFormat(virBuffer *buf, virDomainCapsFirmwareFeaturesFormat(&childBuf, firmwareFeatures); virDomainCapsLoaderFormat(&childBuf, loader); + virDomainCapsVarstoreFormat(&childBuf, varstore); FORMAT_EPILOGUE(os); } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index a68fafe235..02344fd9b6 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -61,6 +61,11 @@ struct _virDomainCapsLoader { virDomainCapsEnum secure; /* Info about secure:virTristateBool */ }; +typedef struct _virDomainCapsVarstore virDomainCapsVarstore; +struct _virDomainCapsVarstore { + virTristateBool supported; +}; + STATIC_ASSERT_ENUM(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST); typedef struct _virDomainCapsOS virDomainCapsOS; struct _virDomainCapsOS { @@ -68,6 +73,7 @@ struct _virDomainCapsOS { virDomainCapsEnum firmware; /* Info about virDomainOsDefFirmware */ virDomainCapsFirmwareFeatures firmwareFeatures; virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ + virDomainCapsVarstore varstore; }; STATIC_ASSERT_ENUM(VIR_DOMAIN_MEMORY_SOURCE_LAST); diff --git a/src/conf/schemas/domaincaps.rng b/src/conf/schemas/domaincaps.rng index 3b24caeca6..4682abbf41 100644 --- a/src/conf/schemas/domaincaps.rng +++ b/src/conf/schemas/domaincaps.rng @@ -87,6 +87,12 @@ </element> </define> + <define name="varstore"> + <element name="varstore"> + <ref name="supported"/> + </element> + </define> + <define name="os"> <element name="os"> <interleave> @@ -98,6 +104,9 @@ <optional> <ref name="loader"/> </optional> + <optional> + <ref name="varstore"/> + </optional> </interleave> </element> </define> -- 2.53.0
On Mon, Feb 23, 2026 at 07:31:04PM +0100, Andrea Bolognani via Devel wrote:
We want to advertise whether the element is usable when defining new domains.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomaincaps.rst | 7 +++++++ src/conf/domain_capabilities.c | 10 ++++++++++ src/conf/domain_capabilities.h | 6 ++++++ src/conf/schemas/domaincaps.rng | 9 +++++++++ 4 files changed, 32 insertions(+)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
The element should only be advertised as supported if the QEMU binary contains the necessary device and a suitable JSON firmware descriptor is found on the system. Right now the latter requirement is not satisfied, so it's marked as not supported across the board. The qemufirmware test is extended to cover the new attribute. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 26 +++++++++++++++- src/qemu/qemu_firmware.c | 6 ++++ src/qemu/qemu_firmware.h | 1 + .../qemu_10.0.0-q35.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml | 1 + .../qemu_10.0.0-tcg.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_10.0.0-tcg.x86_64.xml | 1 + .../qemu_10.0.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_10.0.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_10.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_10.0.0.s390x.xml | 1 + .../qemu_10.0.0.x86_64+amdsev.xml | 1 + tests/domaincapsdata/qemu_10.0.0.x86_64.xml | 1 + .../qemu_10.1.0-q35.x86_64+inteltdx.xml | 1 + .../domaincapsdata/qemu_10.1.0-q35.x86_64.xml | 1 + .../qemu_10.1.0-tcg.x86_64+inteltdx.xml | 1 + .../domaincapsdata/qemu_10.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_10.1.0.s390x.xml | 1 + .../qemu_10.1.0.x86_64+inteltdx.xml | 1 + tests/domaincapsdata/qemu_10.1.0.x86_64.xml | 1 + .../qemu_10.2.0-q35.x86_64+mshv.xml | 1 + .../domaincapsdata/qemu_10.2.0-q35.x86_64.xml | 1 + .../qemu_10.2.0-tcg.x86_64+mshv.xml | 1 + .../domaincapsdata/qemu_10.2.0-tcg.x86_64.xml | 1 + .../qemu_10.2.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_10.2.0.aarch64.xml | 1 + .../qemu_10.2.0.x86_64+mshv.xml | 1 + tests/domaincapsdata/qemu_10.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_11.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_11.0.0-tcg.x86_64.xml | 1 + .../qemu_11.0.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_11.0.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_11.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 1 + .../qemu_7.2.0-hvf.x86_64+hvf.xml | 1 + .../domaincapsdata/qemu_7.2.0-q35.x86_64.xml | 1 + .../qemu_7.2.0-tcg.x86_64+hvf.xml | 1 + .../domaincapsdata/qemu_7.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.2.0.ppc.xml | 1 + tests/domaincapsdata/qemu_7.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_8.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_8.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_8.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_8.1.0.s390x.xml | 1 + tests/domaincapsdata/qemu_8.1.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.2.0-q35.x86_64.xml | 1 + .../qemu_8.2.0-tcg-virt.loongarch64.xml | 1 + .../domaincapsdata/qemu_8.2.0-tcg.x86_64.xml | 1 + .../qemu_8.2.0-virt.aarch64.xml | 1 + .../qemu_8.2.0-virt.loongarch64.xml | 1 + tests/domaincapsdata/qemu_8.2.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_8.2.0.armv7l.xml | 1 + tests/domaincapsdata/qemu_8.2.0.s390x.xml | 1 + tests/domaincapsdata/qemu_8.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_9.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_9.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_9.0.0.sparc.xml | 1 + tests/domaincapsdata/qemu_9.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_9.1.0-q35.x86_64.xml | 1 + .../qemu_9.1.0-tcg-virt.riscv64.xml | 1 + .../domaincapsdata/qemu_9.1.0-tcg.x86_64.xml | 1 + .../qemu_9.1.0-virt.riscv64.xml | 1 + tests/domaincapsdata/qemu_9.1.0.s390x.xml | 1 + tests/domaincapsdata/qemu_9.1.0.x86_64.xml | 1 + .../qemu_9.2.0-hvf.aarch64+hvf.xml | 1 + .../qemu_9.2.0-q35.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_9.2.0-q35.x86_64.xml | 1 + .../qemu_9.2.0-tcg.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_9.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_9.2.0.s390x.xml | 1 + .../qemu_9.2.0.x86_64+amdsev.xml | 1 + tests/domaincapsdata/qemu_9.2.0.x86_64.xml | 1 + tests/qemufirmwaretest.c | 31 +++++++++++++------ 86 files changed, 135 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 048ef66c12..5d75c23072 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6518,8 +6518,26 @@ virQEMUCapsFillDomainLoaderCaps(virDomainCapsLoader *capsLoader, } +static int +virQEMUCapsFillDomainVarstoreCaps(virDomainCapsVarstore *capsVarstore, + bool varstore, + virQEMUCaps *qemuCaps) +{ + /* varstore is advertised as supported only if firmware + * descriptors that use it exist and the QEMU binary has the + * necessary device compiled in */ + if (varstore && virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_UEFI_VARS)) + capsVarstore->supported = VIR_TRISTATE_BOOL_YES; + else + capsVarstore->supported = VIR_TRISTATE_BOOL_NO; + + return 0; +} + + static int virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, + virQEMUCaps *qemuCaps, const char *machine, virArch arch, bool privileged, @@ -6528,10 +6546,12 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, { virDomainCapsFirmwareFeatures *firmwareFeatures = &os->firmwareFeatures; virDomainCapsLoader *capsLoader = &os->loader; + virDomainCapsVarstore *capsVarstore = &os->varstore; uint64_t autoFirmwares = 0; uint64_t featureSecureBoot = 0; uint64_t featureEnrolledKeys = 0; bool secure = false; + bool varstore = false; virFirmware **firmwaresAlt = NULL; size_t nfirmwaresAlt = 0; int ret = -1; @@ -6541,7 +6561,7 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, if (qemuFirmwareGetSupported(machine, arch, privileged, &autoFirmwares, &featureSecureBoot, &featureEnrolledKeys, - &secure, + &secure, &varstore, &firmwaresAlt, &nfirmwaresAlt) < 0) return -1; @@ -6568,6 +6588,9 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, firmwaresAlt ? nfirmwaresAlt : nfirmwares) < 0) goto cleanup; + if (virQEMUCapsFillDomainVarstoreCaps(capsVarstore, varstore, qemuCaps) < 0) + goto cleanup; + ret = 0; cleanup: virFirmwareFreeList(firmwaresAlt, nfirmwaresAlt); @@ -7289,6 +7312,7 @@ virQEMUCapsFillDomainCaps(virQEMUDriverConfig *cfg, } if (virQEMUCapsFillDomainOSCaps(os, + qemuCaps, domCaps->machine, domCaps->arch, privileged, diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 72aae73dcb..60cc92e46a 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2033,6 +2033,7 @@ qemuFirmwareFillDomain(virQEMUDriver *driver, * @featureSecureBoot: bitmap of virTristateBool values for secure-boot feature * @featureEnrolledKeys: bitmap of virTristateBool values for enrolled-keys feature * @secure: true if at least one secure boot enabled FW was found + * @varstore: true if at least one FW using varstore was found * @fws: (optional) list of found firmwares * @nfws: (optional) number of members in @fws * @@ -2064,6 +2065,7 @@ qemuFirmwareGetSupported(const char *machine, uint64_t *featureSecureBoot, uint64_t *featureEnrolledKeys, bool *secure, + bool *varstore, virFirmware ***fws, size_t *nfws) { @@ -2075,6 +2077,7 @@ qemuFirmwareGetSupported(const char *machine, *featureSecureBoot = VIR_TRISTATE_BOOL_ABSENT; *featureEnrolledKeys = VIR_TRISTATE_BOOL_ABSENT; *secure = false; + *varstore = false; if (fws) { *fws = NULL; @@ -2162,6 +2165,9 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_DEVICE_MEMORY: fwpath = memory->filename; nvrampath = memory->template; + + if (memory->template) + *varstore = true; break; case QEMU_FIRMWARE_DEVICE_NONE: diff --git a/src/qemu/qemu_firmware.h b/src/qemu/qemu_firmware.h index 6789ec83f7..bcd3801da8 100644 --- a/src/qemu/qemu_firmware.h +++ b/src/qemu/qemu_firmware.h @@ -55,6 +55,7 @@ qemuFirmwareGetSupported(const char *machine, uint64_t *featureSecureBoot, uint64_t *featureEnrolledKeys, bool *secure, + bool *varstore, virFirmware ***fws, size_t *nfws); diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml index b68767d7b3..1fff8c7fc7 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml index 70da32ccf1..6c26e5b422 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml index 6d2723f950..fb031b916e 100644 --- a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml index cbddffef6b..8a5348d2a8 100644 --- a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml index bacd5665ad..97064ea009 100644 --- a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml index bacd5665ad..97064ea009 100644 --- a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.ppc64.xml b/tests/domaincapsdata/qemu_10.0.0.ppc64.xml index a913d20b3e..8082fb9556 100644 --- a/tests/domaincapsdata/qemu_10.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.s390x.xml b/tests/domaincapsdata/qemu_10.0.0.s390x.xml index 22a4bee3fd..ca741192ba 100644 --- a/tests/domaincapsdata/qemu_10.0.0.s390x.xml +++ b/tests/domaincapsdata/qemu_10.0.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml index 7227638020..6a4ea003f7 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0.x86_64.xml index 38edf287f4..f12dd845ba 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml index 1bca29f971..3537dd01f6 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml index c48ba4e218..e55d7d8ba6 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml index e75c2e2234..4afecf627f 100644 --- a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml index 50087d531f..b3c7bc60b5 100644 --- a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.1.0.s390x.xml b/tests/domaincapsdata/qemu_10.1.0.s390x.xml index 1b4ff5c35d..976943491e 100644 --- a/tests/domaincapsdata/qemu_10.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_10.1.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml index 5e2b2b47c6..7d33362f0e 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0.x86_64.xml index 8f7bff70f3..9cb65712a4 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml index 313e7c24a4..43fe2bff93 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml @@ -35,6 +35,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml index 4955ad7ac5..2c1b38b4ec 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml index cc3427cef7..771ef3a0f6 100644 --- a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml index 4c90f1d7be..f0e08907ff 100644 --- a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml index 808cf0226e..fa1d3c490b 100644 --- a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml index 808cf0226e..fa1d3c490b 100644 --- a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml index 84be18497b..87c35d229c 100644 --- a/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0.x86_64.xml index 013317b4f2..a838126991 100644 --- a/tests/domaincapsdata/qemu_10.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml index cd4e05cdca..109f3ae0ae 100644 --- a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml index 3d4d62ca95..0bfe92db7d 100644 --- a/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml index 6c10d43386..db47c5ee98 100644 --- a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml index 6c10d43386..db47c5ee98 100644 --- a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0.x86_64.xml index f44fc12f90..29e15817c8 100644 --- a/tests/domaincapsdata/qemu_11.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index 4465574814..96dcc32019 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index ba9ad68ad2..a92050ad5b 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml index 9f3e6a7f3f..958d20e74c 100644 --- a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml index d804bd64ce..eb347adce9 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml index 40170cea50..0c3d00865e 100644 --- a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml index 6f424760a8..6b5dff857b 100644 --- a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml index 604aa5e0ad..d6a6e75bec 100644 --- a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml index a67e929551..c568ae3d80 100644 --- a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml index 71c48d74dc..5e13f1f7fb 100644 --- a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml index 682137ec8d..f9114422bd 100644 --- a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml index 399eeb3b18..0b3518a5a8 100644 --- a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml index 966abb1b0a..f574894ad0 100644 --- a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml b/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml index c8d889287c..1fdde871f8 100644 --- a/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml +++ b/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml index 995ad7f220..b4c4153953 100644 --- a/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml index 1bbd737021..989c3e274c 100644 --- a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml +++ b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml index 1bbd737021..989c3e274c 100644 --- a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.2.0.ppc.xml b/tests/domaincapsdata/qemu_7.2.0.ppc.xml index 223387444c..b4bdf3b651 100644 --- a/tests/domaincapsdata/qemu_7.2.0.ppc.xml +++ b/tests/domaincapsdata/qemu_7.2.0.ppc.xml @@ -25,6 +25,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0.x86_64.xml index be0ee62910..6efa244ffa 100644 --- a/tests/domaincapsdata/qemu_7.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml index f225cf0a8e..70a3b9c7d7 100644 --- a/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml index e770746f74..0010cfa60e 100644 --- a/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.0.0.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0.x86_64.xml index 4c8a36eeb0..ac8c8980e7 100644 --- a/tests/domaincapsdata/qemu_8.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml index 5d08abbe3b..e9d807828a 100644 --- a/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml index ea506799bf..e834e3eb82 100644 --- a/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.1.0.s390x.xml b/tests/domaincapsdata/qemu_8.1.0.s390x.xml index 4237262f31..37417ec648 100644 --- a/tests/domaincapsdata/qemu_8.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_8.1.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.1.0.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0.x86_64.xml index bab985379c..5de8bc1cd8 100644 --- a/tests/domaincapsdata/qemu_8.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml index c5c08d8fd1..a2f9591382 100644 --- a/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml index 6228916208..1625ddf4e0 100644 --- a/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml index da3121b8de..ac1c1b840e 100644 --- a/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml index c1dceda12d..420fbedd72 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml index 8206dc0486..af75894ff1 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml index c1dceda12d..420fbedd72 100644 --- a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.armv7l.xml b/tests/domaincapsdata/qemu_8.2.0.armv7l.xml index b64779c84a..a1ad0529e5 100644 --- a/tests/domaincapsdata/qemu_8.2.0.armv7l.xml +++ b/tests/domaincapsdata/qemu_8.2.0.armv7l.xml @@ -25,6 +25,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.s390x.xml b/tests/domaincapsdata/qemu_8.2.0.s390x.xml index 9f92c3c192..84be7cd967 100644 --- a/tests/domaincapsdata/qemu_8.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_8.2.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0.x86_64.xml index 83ea8565d8..e423689076 100644 --- a/tests/domaincapsdata/qemu_8.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml index a4521f150e..2851138ffe 100644 --- a/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml index 00d3e1b8d1..253bed40ed 100644 --- a/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.0.0.sparc.xml b/tests/domaincapsdata/qemu_9.0.0.sparc.xml index 7eb384d512..f999c8ed71 100644 --- a/tests/domaincapsdata/qemu_9.0.0.sparc.xml +++ b/tests/domaincapsdata/qemu_9.0.0.sparc.xml @@ -25,6 +25,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.0.0.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0.x86_64.xml index d61070b968..2316859d5b 100644 --- a/tests/domaincapsdata/qemu_9.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml index 226aad41b2..1cf269504c 100644 --- a/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml b/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml index c32d4380aa..85dffd3455 100644 --- a/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml index d18c62d268..76b2707b9c 100644 --- a/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml b/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml index 7a013e77c4..c052b8329b 100644 --- a/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml @@ -31,6 +31,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0.s390x.xml b/tests/domaincapsdata/qemu_9.1.0.s390x.xml index e26cab26f3..bc62fdfaa4 100644 --- a/tests/domaincapsdata/qemu_9.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_9.1.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0.x86_64.xml index a27712673a..baaa17f68d 100644 --- a/tests/domaincapsdata/qemu_9.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml index 06bb829a2a..f998177636 100644 --- a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml +++ b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml index aac1d4d923..a21c69e416 100644 --- a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml index ef6ee01d00..df0d995276 100644 --- a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml index 0ec1a9900d..2b860a23ca 100644 --- a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml index c8a0da3d22..24113a3514 100644 --- a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.2.0.s390x.xml b/tests/domaincapsdata/qemu_9.2.0.s390x.xml index e00d7efd99..bba9ce7558 100644 --- a/tests/domaincapsdata/qemu_9.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_9.2.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml index d6e3f8dc12..f12c89f40b 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0.x86_64.xml index 89e081a0e1..529415bcb4 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c index e09f50592b..ee585b67d2 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -143,6 +143,7 @@ struct supportedData { const char *machine; virArch arch; bool secure; + bool varstore; const char *fwlist; unsigned int *interfaces; size_t ninterfaces; @@ -158,6 +159,7 @@ testSupportedFW(const void *opaque) uint64_t actualFeatureSecureBoot; uint64_t actualFeatureEnrolledKeys; bool actualSecure; + bool actualVarstore; virFirmware **expFWs = NULL; size_t nexpFWs = 0; virFirmware **actFWs = NULL; @@ -187,7 +189,8 @@ testSupportedFW(const void *opaque) &actualInterfaces, &actualFeatureSecureBoot, &actualFeatureEnrolledKeys, - &actualSecure, &actFWs, &nactFWs) < 0) { + &actualSecure, &actualVarstore, + &actFWs, &nactFWs) < 0) { fprintf(stderr, "Unable to get list of supported interfaces\n"); goto cleanup; } @@ -208,6 +211,14 @@ testSupportedFW(const void *opaque) goto cleanup; } + if (actualVarstore != data->varstore) { + fprintf(stderr, + "Mismatch in varstore support. " + "Expected %d got %d\n", + data->varstore, actualVarstore); + goto cleanup; + } + for (i = 0; i < nactFWs; i++) { virFirmware *actFW = actFWs[i]; virFirmware *expFW = NULL; @@ -295,26 +306,26 @@ mymain(void) /* The @fwlist contains pairs of ${FW}:${NVRAM}. If there's * no NVRAM expected pass literal "NULL" and test fixes that * later. */ -#define DO_SUPPORTED_TEST(machine, arch, secure, fwlist, ...) \ +#define DO_SUPPORTED_TEST(machine, arch, secure, varstore, fwlist, ...) \ do { \ unsigned int interfaces[] = {__VA_ARGS__}; \ - struct supportedData data = {machine, arch, secure, fwlist, \ + struct supportedData data = {machine, arch, secure, varstore, fwlist, \ interfaces, G_N_ELEMENTS(interfaces)}; \ if (virTestRun("QEMU FW SUPPORTED " machine " " #arch, \ testSupportedFW, &data) < 0) \ ret = -1; \ } while (0) - DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_X86_64, false, + DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_X86_64, false, false, "/usr/share/seabios/bios-256k.bin:NULL:" "/usr/share/edk2/ovmf/OVMF_CODE_4M.qcow2:/usr/share/edk2/ovmf/OVMF_VARS_4M.qcow2:" "/usr/share/edk2/ovmf/OVMF_CODE.fd:/usr/share/edk2/ovmf/OVMF_VARS.fd", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); - DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_I686, false, + DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_I686, false, false, "/usr/share/seabios/bios-256k.bin:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS); - DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64, true, + DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64, true, false, "/usr/share/seabios/bios-256k.bin:NULL:" "/usr/share/edk2/ovmf/OVMF_CODE_4M.secboot.qcow2:/usr/share/edk2/ovmf/OVMF_VARS_4M.secboot.qcow2:" "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd:/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd:" @@ -327,19 +338,19 @@ mymain(void) "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); - DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false, + DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false, false, "/usr/share/seabios/bios-256k.bin:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS); - DO_SUPPORTED_TEST("microvm", VIR_ARCH_X86_64, false, + DO_SUPPORTED_TEST("microvm", VIR_ARCH_X86_64, false, false, "/usr/share/edk2/ovmf/MICROVM.fd:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); - DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64, false, + DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64, false, false, "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2:/usr/share/edk2/aarch64/vars-template-pflash.qcow2:" "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw:" "/usr/share/edk2/aarch64/QEMU_EFI-pflash.qcow2:/usr/share/edk2/aarch64/vars-template-pflash.qcow2:" "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw", VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); - DO_SUPPORTED_TEST("virt", VIR_ARCH_RISCV64, false, + DO_SUPPORTED_TEST("virt", VIR_ARCH_RISCV64, false, false, "/usr/share/edk2/riscv/RISCV_VIRT_CODE.qcow2:/usr/share/edk2/riscv/RISCV_VIRT_VARS.qcow2", VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); -- 2.53.0
Currently we only look at the value for the stateless attribute itself when matching, but the <nvram> element being included in the input XML is likewise a clear sign that a stateless firmware build will not satisfy the user's requirements. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 60cc92e46a..1851ed4a80 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1288,13 +1288,19 @@ qemuFirmwareMatchDomain(const virDomainDef *def, /* Explicit requests for either a stateless or stateful * firmware should be fulfilled, but if no preference is * provided either one is fine as long as the other match - * criteria are satisfied */ + * criteria are satisfied. NVRAM implies stateful */ if (loader && loader->stateless == VIR_TRISTATE_BOOL_NO && flash->mode == QEMU_FIRMWARE_FLASH_MODE_STATELESS) { VIR_DEBUG("Discarding stateless loader"); return false; } + if (loader && + loader->nvram && + flash->mode == QEMU_FIRMWARE_FLASH_MODE_STATELESS) { + VIR_DEBUG("Discarding stateless loader"); + return false; + } if (loader && loader->stateless == VIR_TRISTATE_BOOL_YES && flash->mode != QEMU_FIRMWARE_FLASH_MODE_STATELESS) { -- 2.53.0
Stateful ROMs are those that use the uefi-vars QEMU device to implement access to UEFI variable storage. Matching works much the same as it does for pflash-based firmware images. Notably, the <varstore> element is only allowed for ROM and the <nvram> element is only allowed for pflash. The firmware-auto-efi-varstore-q35 and firmware-auto-efi-varstore-aarch64 fail in a different way after this change: the input XML is now considered valid, and the only remaining issue is that the firmware autoselection process is unable to find a match. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 40 +++++++++++++++++-- ...to-efi-varstore-aarch64.aarch64-latest.err | 2 +- ...to-efi-varstore-aarch64.aarch64-latest.xml | 28 +++++++++++++ ...re-auto-efi-varstore-q35.x86_64-latest.err | 2 +- ...re-auto-efi-varstore-q35.x86_64-latest.xml | 36 +++++++++++++++++ tests/qemuxmlconftest.c | 4 +- 6 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 1851ed4a80..60635b559f 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -893,15 +893,18 @@ qemuFirmwareMatchesMachineArch(const qemuFirmware *fw, * qemuFirmwareMatchesPaths: * @fw: firmware definition * @loader: loader definition + * @varstore: varstore definition * * Checks whether @fw is compatible with the information provided as * part of the domain definition. * - * Returns: true if @fw is compatible with @loader, false otherwise + * Returns: true if @fw is compatible with @loader and @varstore, + * false otherwise */ static bool qemuFirmwareMatchesPaths(const qemuFirmware *fw, - const virDomainLoaderDef *loader) + const virDomainLoaderDef *loader, + const virDomainVarstoreDef *varstore) { const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash; const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory; @@ -922,6 +925,9 @@ qemuFirmwareMatchesPaths(const qemuFirmware *fw, if (loader && loader->path && !virFileComparePaths(loader->path, memory->filename)) return false; + if (varstore && varstore->template && + !virFileComparePaths(varstore->template, memory->template)) + return false; break; case QEMU_FIRMWARE_DEVICE_NONE: case QEMU_FIRMWARE_DEVICE_LAST: @@ -1112,6 +1118,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def, const char *path) { const virDomainLoaderDef *loader = def->os.loader; + const virDomainVarstoreDef *varstore = def->os.varstore; size_t i; qemuFirmwareOSInterface want; bool wantUEFI = false; @@ -1166,7 +1173,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def, return false; } - if (!qemuFirmwareMatchesPaths(fw, def->os.loader)) { + if (!qemuFirmwareMatchesPaths(fw, def->os.loader, def->os.varstore)) { VIR_DEBUG("No matching path in '%s'", path); return false; } @@ -1279,6 +1286,9 @@ qemuFirmwareMatchDomain(const virDomainDef *def, if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_FLASH) { const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash; + if (varstore) + return false; + if (loader && loader->type && loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH) { VIR_DEBUG("Discarding flash loader"); @@ -1377,16 +1387,38 @@ qemuFirmwareMatchDomain(const virDomainDef *def, } } } else if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_MEMORY) { + const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory; + + if (loader && loader->nvram) + return false; + if (loader && loader->type && loader->type != VIR_DOMAIN_LOADER_TYPE_ROM) { VIR_DEBUG("Discarding rom loader"); return false; } - if (loader && loader->stateless == VIR_TRISTATE_BOOL_NO) { + /* Explicit requests for either a stateless or stateful + * firmware should be fulfilled, but if no preference is + * provided either one is fine as long as the other match + * criteria are satisfied. varstore implies stateful */ + if (loader && + loader->stateless == VIR_TRISTATE_BOOL_NO && + !memory->template) { + VIR_DEBUG("Discarding stateless loader"); + return false; + } + if (varstore && + !memory->template) { VIR_DEBUG("Discarding stateless loader"); return false; } + if (loader && + loader->stateless == VIR_TRISTATE_BOOL_YES && + memory->template) { + VIR_DEBUG("Discarding non-stateless loader"); + return false; + } if (loader && loader->readonly == VIR_TRISTATE_BOOL_NO) { VIR_DEBUG("Discarding readonly loader"); diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err index b45d304221..3edb2b3451 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err @@ -1 +1 @@ -Only one of NVRAM/varstore can be used +operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml new file mode 100644 index 0000000000..b0fa092509 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml @@ -0,0 +1,28 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <loader format='raw'/> + <varstore/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <gic version='2'/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err index b45d304221..3edb2b3451 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err @@ -1 +1 @@ -Only one of NVRAM/varstore can be used +operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml new file mode 100644 index 0000000000..c4d70c9fc5 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml @@ -0,0 +1,36 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <loader format='raw'/> + <varstore/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pcie-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <watchdog model='itco' action='reset'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index ca00dc96f0..43e994fc93 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1673,8 +1673,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-file"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); - DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-q35"); - DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-varstore-q35"); + DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
If the matching firmware requires the use of varstore, we have to bubble up information about it, namely the path to the template. If the struct member doesn't exist yet, we need to allocate it. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 60635b559f..5a07e3181f 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1492,6 +1492,7 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def, const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash; const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory; virDomainLoaderDef *loader = NULL; + virDomainVarstoreDef *varstore = NULL; virStorageFileFormat format; bool hasSecureBoot = false; bool hasEnrolledKeys = false; @@ -1552,8 +1553,17 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def, VIR_FREE(loader->path); loader->path = g_strdup(memory->filename); - VIR_DEBUG("decided on loader '%s'", - loader->path); + if (memory->template) { + if (!def->os.varstore) + def->os.varstore = virDomainVarstoreDefNew(); + varstore = def->os.varstore; + + VIR_FREE(varstore->template); + varstore->template = g_strdup(memory->template); + } + + VIR_DEBUG("decided on loader '%s' template '%s'", + loader->path, NULLSTR(varstore ? varstore->template : NULL)); break; case QEMU_FIRMWARE_DEVICE_NONE: -- 2.53.0
This is the same as the existing nvramDir, except it will be used to store the files used with the uefi-vars QEMU device. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- libvirt.spec.in | 1 + src/qemu/meson.build | 1 + src/qemu/qemu_conf.c | 4 ++++ src/qemu/qemu_conf.h | 1 + src/qemu/qemu_driver.c | 12 ++++++++++++ tests/testutilsqemu.c | 2 ++ 6 files changed, 21 insertions(+) diff --git a/libvirt.spec.in b/libvirt.spec.in index 0ba7bf4197..00316a03f2 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -2349,6 +2349,7 @@ exit 0 %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ram/ %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/save/ %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/snapshot/ +%dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/varstore/ %dir %attr(0750, root, root) %{_localstatedir}/cache/libvirt/qemu/ %{_datadir}/augeas/lenses/libvirtd_qemu.aug %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug diff --git a/src/qemu/meson.build b/src/qemu/meson.build index ff9a904277..b4fb62f14f 100644 --- a/src/qemu/meson.build +++ b/src/qemu/meson.build @@ -223,6 +223,7 @@ if conf.has('WITH_QEMU') localstatedir / 'lib' / 'libvirt' / 'qemu' / 'ram', localstatedir / 'lib' / 'libvirt' / 'qemu' / 'save', localstatedir / 'lib' / 'libvirt' / 'qemu' / 'snapshot', + localstatedir / 'lib' / 'libvirt' / 'qemu' / 'varstore', localstatedir / 'lib' / 'libvirt' / 'swtpm', localstatedir / 'log' / 'libvirt' / 'qemu', localstatedir / 'log' / 'swtpm' / 'libvirt' / 'qemu', diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index de6e51177a..3ea42da502 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -167,6 +167,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir); cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir); cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir); + cfg->varstoreDir = g_strdup_printf("%s/varstore", cfg->libDir); cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir); } else if (privileged) { cfg->logDir = g_strdup_printf("%s/log/libvirt/qemu", LOCALSTATEDIR); @@ -188,6 +189,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir); cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir); cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir); + cfg->varstoreDir = g_strdup_printf("%s/varstore", cfg->libDir); cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir); cfg->swtpmStorageDir = g_strdup_printf("%s/lib/libvirt/swtpm", LOCALSTATEDIR); @@ -215,6 +217,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->configBaseDir); cfg->autoDumpPath = g_strdup_printf("%s/qemu/dump", cfg->configBaseDir); cfg->nvramDir = g_strdup_printf("%s/qemu/nvram", cfg->configBaseDir); + cfg->varstoreDir = g_strdup_printf("%s/qemu/varstore", cfg->configBaseDir); cfg->memoryBackingDir = g_strdup_printf("%s/qemu/ram", cfg->configBaseDir); cfg->swtpmStorageDir = g_strdup_printf("%s/qemu/swtpm", cfg->configBaseDir); @@ -367,6 +370,7 @@ static void virQEMUDriverConfigDispose(void *obj) g_free(cfg->checkpointDir); g_free(cfg->channelTargetDir); g_free(cfg->nvramDir); + g_free(cfg->varstoreDir); g_free(cfg->defaultTLSx509certdir); g_free(cfg->defaultTLSx509secretUUID); diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index c284e108a1..aa2bac6891 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -121,6 +121,7 @@ struct _virQEMUDriverConfig { char *checkpointDir; char *channelTargetDir; char *nvramDir; + char *varstoreDir; char *swtpmStorageDir; char *defaultTLSx509certdir; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3126d997de..8a4947b60b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -626,6 +626,11 @@ qemuStateInitialize(bool privileged, cfg->nvramDir); goto error; } + if (g_mkdir_with_parents(cfg->varstoreDir, 0777) < 0) { + virReportSystemError(errno, _("Failed to create varstore dir %1$s"), + cfg->varstoreDir); + goto error; + } if (g_mkdir_with_parents(cfg->memoryBackingDir, 0777) < 0) { virReportSystemError(errno, _("Failed to create memory backing dir %1$s"), cfg->memoryBackingDir); @@ -784,6 +789,13 @@ qemuStateInitialize(bool privileged, (int)cfg->group); goto error; } + if (chown(cfg->varstoreDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%1$s' to %2$d:%3$d"), + cfg->varstoreDir, (int)cfg->user, + (int)cfg->group); + goto error; + } if (chown(cfg->memoryBackingDir, cfg->user, cfg->group) < 0) { virReportSystemError(errno, _("unable to set ownership of '%1$s' to %2$d:%3$d"), diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 78ec521266..21dfd3141d 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -336,6 +336,8 @@ int qemuTestDriverInit(virQEMUDriver *driver) cfg->memoryBackingDir = g_strdup("/var/lib/libvirt/qemu/ram"); VIR_FREE(cfg->nvramDir); cfg->nvramDir = g_strdup("/var/lib/libvirt/qemu/nvram"); + VIR_FREE(cfg->varstoreDir); + cfg->varstoreDir = g_strdup("/var/lib/libvirt/qemu/varstore"); VIR_FREE(cfg->passtStateDir); cfg->passtStateDir = g_strdup("/var/run/libvirt/qemu/passt"); VIR_FREE(cfg->dbusStateDir); -- 2.53.0
Introduce qemuFirmwareEnsureVarstore(), which performs the same task as the existing qemuFirmwareEnsureNVRAM() but for the varstore element. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_firmware.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 5a07e3181f..d8633c6b28 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1069,6 +1069,38 @@ qemuFirmwareEnsureNVRAM(virDomainDef *def, } +/** + * qemuFirmwareEnsureVarstore: + * @def: domain definition + * @driver: QEMU driver + * + * Make sure that information for the varstore is present. This might + * involve automatically generating the corresponding path. + */ +static void +qemuFirmwareEnsureVarstore(virDomainDef *def, + virQEMUDriver *driver) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + virDomainLoaderDef *loader = def->os.loader; + virDomainVarstoreDef *varstore = def->os.varstore; + + if (!loader) + return; + + if (loader->type != VIR_DOMAIN_LOADER_TYPE_ROM) + return; + + if (!varstore) + return; + + if (varstore->path) + return; + + varstore->path = g_strdup_printf("%s/%s.json", + cfg->varstoreDir, def->name); +} + /** * qemuFirmwareSetOsFeatures: @@ -2063,10 +2095,11 @@ qemuFirmwareFillDomain(virQEMUDriver *driver, } } - /* Always ensure that the NVRAM path is present, even if we - * haven't found a match: the configuration might simply be - * referring to a custom firmware build */ + /* Always ensure that the NVRAM/varstore is configured where + * appropriate, even if we haven't found a match: the configuration + * might simply be referring to a custom firmware build */ qemuFirmwareEnsureNVRAM(def, driver, abiUpdate); + qemuFirmwareEnsureVarstore(def, driver); return 0; } -- 2.53.0
Most of the code in the qemuPrepareNVRAMFile() function can be reused to create a varstore file from template. Move the common parts to a generic helper, leaving only the parts that are NVRAM-specific in the original function. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_process.c | 56 +++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 371b64faac..db43b035c1 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4918,45 +4918,40 @@ qemuPrepareNVRAMBlock(virDomainLoaderDef *loader, static int -qemuPrepareNVRAMFile(virQEMUDriver *driver, - virDomainLoaderDef *loader, - bool reset_nvram) +qemuPrepareNVRAMFileCommon(virQEMUDriver *driver, + const char *path, + const char *template, + bool reset_nvram) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_AUTOCLOSE srcFD = -1; struct qemuPrepareNVRAMHelperData data; - if (virFileExists(loader->nvram->path) && !reset_nvram) + if (!path) return 0; - if (!loader->nvramTemplate) { + if (virFileExists(path) && !reset_nvram) + return 0; + + if (!template) { virReportError(VIR_ERR_OPERATION_FAILED, _("unable to find any master var store for loader: %1$s"), - loader->path); + path); return -1; } - /* If 'nvramTemplateFormat' is empty it means that it's a user-provided - * template which we couldn't verify. Assume the user knows what they're doing */ - if (loader->nvramTemplateFormat != VIR_STORAGE_FILE_NONE && - loader->nvram->format != loader->nvramTemplateFormat) { - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("conversion of the nvram template to another target format is not supported")); - return -1; - } - - if ((srcFD = virFileOpenAs(loader->nvramTemplate, O_RDONLY, + if ((srcFD = virFileOpenAs(template, O_RDONLY, 0, -1, -1, 0)) < 0) { virReportSystemError(-srcFD, _("Failed to open file '%1$s'"), - loader->nvramTemplate); + template); return -1; } data.srcFD = srcFD; - data.srcPath = loader->nvramTemplate; + data.srcPath = template; - if (virFileRewrite(loader->nvram->path, + if (virFileRewrite(path, S_IRUSR | S_IWUSR, cfg->user, cfg->group, qemuPrepareNVRAMHelper, @@ -4968,6 +4963,29 @@ qemuPrepareNVRAMFile(virQEMUDriver *driver, } +static int +qemuPrepareNVRAMFile(virQEMUDriver *driver, + virDomainLoaderDef *loader, + bool reset_nvram) +{ + /* If 'nvramTemplateFormat' is empty it means that it's a user-provided + * template which we couldn't verify. Assume the user knows what they're doing */ + if (loader && loader->nvram && + loader->nvramTemplateFormat != VIR_STORAGE_FILE_NONE && + loader->nvram->format != loader->nvramTemplateFormat) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("conversion of the nvram template to another target format is not supported")); + return -1; + } + + if (qemuPrepareNVRAMFileCommon(driver, loader->nvram->path, + loader->nvramTemplate, reset_nvram) < 0) + return -1; + + return 0; +} + + int qemuPrepareNVRAM(virQEMUDriver *driver, virDomainDef *def, -- 2.53.0
Simply mimicking what is currently done for NVRAM files does the trick. A few user-visible messages are updated to reflect the fact that they apply both to NVRAM and varstore. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_driver.c | 14 +++++++++----- src/qemu/qemu_process.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8a4947b60b..9e4d0f8640 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6644,22 +6644,26 @@ qemuDomainUndefineFlags(virDomainPtr dom, } } - if (vm->def->os.loader && vm->def->os.loader->nvram && - virStorageSourceIsLocalStorage(vm->def->os.loader->nvram)) { - nvram_path = g_strdup(vm->def->os.loader->nvram->path); + if (vm->def->os.loader) { + if (vm->def->os.loader->nvram && + virStorageSourceIsLocalStorage(vm->def->os.loader->nvram)) { + nvram_path = g_strdup(vm->def->os.loader->nvram->path); + } else if (vm->def->os.varstore && vm->def->os.varstore->path) { + nvram_path = g_strdup(vm->def->os.varstore->path); + } } if (nvram_path && virFileExists(nvram_path)) { if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) { if (unlink(nvram_path) < 0) { virReportSystemError(errno, - _("failed to remove nvram: %1$s"), + _("Failed to remove NVRAM/varstore: %1$s"), nvram_path); goto endjob; } } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot undefine domain with nvram")); + _("Cannot undefine domain with NVRAM/varstore")); goto endjob; } } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index db43b035c1..a82ee4b15e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5029,6 +5029,27 @@ qemuPrepareNVRAM(virQEMUDriver *driver, } +static int +qemuPrepareVarstore(virQEMUDriver *driver, + virDomainDef *def, + bool reset_nvram) +{ + virDomainLoaderDef *loader = def->os.loader; + virDomainVarstoreDef *varstore = def->os.varstore; + + if (!loader || !varstore) + return 0; + + VIR_DEBUG("varstore='%s'", NULLSTR(varstore->path)); + + if (qemuPrepareNVRAMFileCommon(driver, varstore->path, + varstore->template, reset_nvram) < 0) + return -1; + + return 0; +} + + static void qemuLogOperation(virDomainObj *vm, const char *msg, @@ -7799,6 +7820,7 @@ qemuProcessPrepareHost(virQEMUDriver *driver, unsigned int hostdev_flags = 0; qemuDomainObjPrivate *priv = vm->privateData; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + bool reset_nvram = !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM); /* * Create all per-domain directories in order to make sure domain @@ -7808,8 +7830,10 @@ qemuProcessPrepareHost(virQEMUDriver *driver, qemuProcessMakeDir(driver, vm, priv->channelTargetDir) < 0) return -1; - if (qemuPrepareNVRAM(driver, vm->def, - !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM)) < 0) + if (qemuPrepareNVRAM(driver, vm->def, reset_nvram) < 0) + return -1; + + if (qemuPrepareVarstore(driver, vm->def, reset_nvram) < 0) return -1; if (vm->def->vsock) { -- 2.53.0
Before this, attempting to use a ROM that was not explictly marked at read only resulted in an error at startup time. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/security/virt-aa-helper.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index f4ec6b7826..3ac4740fb5 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1021,7 +1021,15 @@ get_files(vahControl * ctl) if (ctl->def->os.loader && ctl->def->os.loader->path) { bool readonly = false; + + /* Look at the readonly attribute, but also keep in mind that ROMs + * are always loaded read-only regardless of whether the attribute + * is present. Validation ensures that nonsensical configurations + * (type=rom readonly=no) are rejected long before we get here */ virTristateBoolToBool(ctl->def->os.loader->readonly, &readonly); + if (ctl->def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) + readonly = true; + if (vah_add_file(&buf, ctl->def->os.loader->path, readonly ? "rk" : "rwk") != 0) { -- 2.53.0
Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- src/security/security_dac.c | 22 +++++++++++--- src/security/security_selinux.c | 53 +++++++++++++++++++++------------ src/security/virt-aa-helper.c | 44 ++++++++++++++++----------- 3 files changed, 78 insertions(+), 41 deletions(-) diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 704c8dbfec..390dfc7578 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -2061,11 +2061,17 @@ virSecurityDACRestoreAllLabel(virSecurityManager *mgr, rc = -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecurityDACRestoreImageLabelInt(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecurityDACRestoreImageLabelInt(mgr, sharedFilesystems, def, def->os.loader->nvram, migrated) < 0) rc = -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecurityDACRestoreFileLabel(mgr, def->os.varstore->path) < 0) + rc = -1; } if (def->os.kernel && @@ -2310,12 +2316,20 @@ virSecurityDACSetAllLabel(virSecurityManager *mgr, return -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecurityDACSetImageLabel(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecurityDACSetImageLabel(mgr, sharedFilesystems, def, def->os.loader->nvram, VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN | VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP) < 0) return -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecurityDACSetOwnership(mgr, NULL, + def->os.varstore->path, + user, group, true) < 0) + return -1; } if (def->os.kernel && diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 4a5f61d16b..9c498ab5f8 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2993,11 +2993,18 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManager *mgr, rc = -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecuritySELinuxRestoreImageLabelInt(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecuritySELinuxRestoreImageLabelInt(mgr, sharedFilesystems, def, def->os.loader->nvram, migrated) < 0) rc = -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecuritySELinuxRestoreFileLabel(mgr, def->os.varstore->path, + true, false) < 0) + rc = -1; } if (def->os.kernel && @@ -3341,6 +3348,22 @@ virSecuritySELinuxSetSysinfoLabel(virSecurityManager *mgr, } +static int +virSecuritySELinuxDomainSetPathLabel(virSecurityManager *mgr, + virDomainDef *def, + const char *path, + bool allowSubtree G_GNUC_UNUSED) +{ + virSecurityLabelDef *seclabel; + + seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); + if (!seclabel || !seclabel->relabel) + return 0; + + return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel, true); +} + + static int virSecuritySELinuxSetAllLabel(virSecurityManager *mgr, char *const *sharedFilesystems, @@ -3421,12 +3444,19 @@ virSecuritySELinuxSetAllLabel(virSecurityManager *mgr, return -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecuritySELinuxSetImageLabel(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecuritySELinuxSetImageLabel(mgr, sharedFilesystems, def, def->os.loader->nvram, VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN | VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP) < 0) return -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecuritySELinuxDomainSetPathLabel(mgr, def, + def->os.varstore->path, true) < 0) + return -1; } if (def->os.kernel && @@ -3593,21 +3623,6 @@ virSecuritySELinuxGetSecurityMountOptions(virSecurityManager *mgr, return opts; } -static int -virSecuritySELinuxDomainSetPathLabel(virSecurityManager *mgr, - virDomainDef *def, - const char *path, - bool allowSubtree G_GNUC_UNUSED) -{ - virSecurityLabelDef *seclabel; - - seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); - if (!seclabel || !seclabel->relabel) - return 0; - - return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel, true); -} - static int virSecuritySELinuxDomainSetPathLabelRO(virSecurityManager *mgr, virDomainDef *def, diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 3ac4740fb5..e932e79dab 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1019,27 +1019,35 @@ get_files(vahControl * ctl) return -1; } - if (ctl->def->os.loader && ctl->def->os.loader->path) { - bool readonly = false; - - /* Look at the readonly attribute, but also keep in mind that ROMs - * are always loaded read-only regardless of whether the attribute - * is present. Validation ensures that nonsensical configurations - * (type=rom readonly=no) are rejected long before we get here */ - virTristateBoolToBool(ctl->def->os.loader->readonly, &readonly); - if (ctl->def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) - readonly = true; - - if (vah_add_file(&buf, - ctl->def->os.loader->path, - readonly ? "rk" : "rwk") != 0) { + if (ctl->def->os.loader) { + if (ctl->def->os.loader->path) { + bool readonly = false; + + /* Look at the readonly attribute, but also keep in mind that ROMs + * are always loaded read-only regardless of whether the attribute + * is present. Validation ensures that nonsensical configurations + * (type=rom readonly=no) are rejected long before we get here */ + virTristateBoolToBool(ctl->def->os.loader->readonly, &readonly); + if (ctl->def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) + readonly = true; + + if (vah_add_file(&buf, + ctl->def->os.loader->path, + readonly ? "rk" : "rwk") != 0) { + return -1; + } + } + + if (ctl->def->os.loader->nvram && + storage_source_add_files(ctl->def->os.loader->nvram, &buf, 0) < 0) { return -1; } - } - if (ctl->def->os.loader && ctl->def->os.loader->nvram && - storage_source_add_files(ctl->def->os.loader->nvram, &buf, 0) < 0) { - return -1; + if (ctl->def->os.varstore && + ctl->def->os.varstore->path && + vah_add_file(&buf, ctl->def->os.varstore->path, "rw") != 0) { + return -1; + } } for (i = 0; i < ctl->def->ngraphics; i++) { -- 2.53.0
Now that everything else is in place, we can finally add the firmware descriptors for the edk2 builds that use the uefi-vars QEMU device. Several existing test cases that were failing up until this point can pass now. This includes firmware-auto-efi-varstore-q35, firmware-auto-efi-varstore-aarch64 and firmware-auto-efi-enrolled-keys-aarch64, which were only failing because a matching firmware descriptor could not be found. firmware-manual-efi-varstore-aarch64 also passes now, because with the firmware descriptor in place libvirt is able to figure out that the manually-provided path corresponds to a UEFI firmware build, which means that the use of ACPI is fine. The test cases using older version of QEMU still fail, as is expected, though the error message is now slightly different and reflect the actual reason why that is. The qemufirmware and domaincaps tests are updated in the expected ways. In particular, versions QEMU 10.0 and newer now advertise varstore support as available. https://issues.redhat.com/browse/RHEL-82645 Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- .../qemu_10.0.0-q35.x86_64+amdsev.xml | 2 +- .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml | 2 +- .../qemu_10.0.0-virt.aarch64.xml | 4 ++- tests/domaincapsdata/qemu_10.0.0.aarch64.xml | 4 ++- .../qemu_10.1.0-q35.x86_64+inteltdx.xml | 2 +- .../domaincapsdata/qemu_10.1.0-q35.x86_64.xml | 2 +- .../qemu_10.2.0-q35.x86_64+mshv.xml | 2 +- .../domaincapsdata/qemu_10.2.0-q35.x86_64.xml | 2 +- .../qemu_10.2.0-virt.aarch64.xml | 4 ++- tests/domaincapsdata/qemu_10.2.0.aarch64.xml | 4 ++- .../domaincapsdata/qemu_11.0.0-q35.x86_64.xml | 2 +- .../qemu_11.0.0-virt.aarch64.xml | 4 ++- tests/domaincapsdata/qemu_11.0.0.aarch64.xml | 4 ++- .../qemu_8.2.0-virt.aarch64.xml | 2 ++ tests/domaincapsdata/qemu_8.2.0.aarch64.xml | 2 ++ .../qemu_9.2.0-hvf.aarch64+hvf.xml | 2 ++ .../90-edk2-aarch64-qemuvars-sb-enrolled.json | 29 ++++++++++++++++ ...90-edk2-ovmf-qemuvars-x64-sb-enrolled.json | 31 +++++++++++++++++ .../firmware/91-edk2-aarch64-qemuvars-sb.json | 28 +++++++++++++++ .../91-edk2-ovmf-qemuvars-x64-sb.json | 30 ++++++++++++++++ tests/qemufirmwaretest.c | 20 ++++++++--- ...fi-enrolled-keys-aarch64.aarch64-8.2.0.err | 2 +- ...-enrolled-keys-aarch64.aarch64-latest.args | 31 +++++++++++++++++ ...i-enrolled-keys-aarch64.aarch64-latest.err | 1 - ...i-enrolled-keys-aarch64.aarch64-latest.xml | 4 ++- ...o-efi-varstore-aarch64.aarch64-latest.args | 31 +++++++++++++++++ ...to-efi-varstore-aarch64.aarch64-latest.err | 1 - ...to-efi-varstore-aarch64.aarch64-latest.xml | 8 +++-- ...e-auto-efi-varstore-q35.x86_64-latest.args | 34 +++++++++++++++++++ ...re-auto-efi-varstore-q35.x86_64-latest.err | 1 - ...re-auto-efi-varstore-q35.x86_64-latest.xml | 8 +++-- ...ual-efi-varstore-aarch64.aarch64-8.2.0.err | 2 +- ...l-efi-varstore-aarch64.aarch64-latest.args | 31 +++++++++++++++++ ...al-efi-varstore-aarch64.aarch64-latest.err | 1 - ...l-efi-varstore-aarch64.aarch64-latest.xml} | 6 ++-- ...-manual-efi-varstore-q35.x86_64-latest.xml | 8 +++-- tests/qemuxmlconftest.c | 10 +++--- 37 files changed, 324 insertions(+), 37 deletions(-) create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-aarch64-qemuvars-sb-enrolled.json create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-ovmf-qemuvars-x64-sb-enrolled.json create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-ovmf-qemuvars-x64-sb.json create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err rename tests/qemuxmlconfdata/{firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml => firmware-manual-efi-varstore-aarch64.aarch64-latest.xml} (76%) diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml index 1fff8c7fc7..bf6393dc03 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml index 6c26e5b422..d6f710e56e 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml index 97064ea009..334aa5e31f 100644 --- a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml index 97064ea009..334aa5e31f 100644 --- a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml index 3537dd01f6..6c370de5dd 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml index e55d7d8ba6..60cc9eee3d 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml index 43fe2bff93..e30b64e068 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml @@ -35,7 +35,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml index 2c1b38b4ec..fde3055148 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml index fa1d3c490b..beb9a49ee3 100644 --- a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml index fa1d3c490b..beb9a49ee3 100644 --- a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml index 109f3ae0ae..aa62aa1502 100644 --- a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml index db47c5ee98..4d41b6427d 100644 --- a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml index db47c5ee98..4d41b6427d 100644 --- a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml index 420fbedd72..83fc9e37a7 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> diff --git a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml index 420fbedd72..83fc9e37a7 100644 --- a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> diff --git a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml index f998177636..65bb9dc9bd 100644 --- a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml +++ b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-aarch64-qemuvars-sb-enrolled.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-aarch64-qemuvars-sb-enrolled.json new file mode 100644 index 0000000000..9142d8fecd --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-aarch64-qemuvars-sb-enrolled.json @@ -0,0 +1,29 @@ +{ + "description": "UEFI firmware for ARM64 virtual machines, SB enabled, MS certs enrolled", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "filename": "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd", + "uefi-vars": { + "template": "/usr/share/edk2/aarch64/vars.secboot.json" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "enrolled-keys", + "secure-boot", + "host-uefi-vars" + ], + "tags": [ + + ] +} diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-ovmf-qemuvars-x64-sb-enrolled.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-ovmf-qemuvars-x64-sb-enrolled.json new file mode 100644 index 0000000000..5b1b483c1c --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/90-edk2-ovmf-qemuvars-x64-sb-enrolled.json @@ -0,0 +1,31 @@ +{ + "description": "OVMF for qemu uefi-vars, SB enabled, MS certs enrolled", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "filename": "/usr/share/edk2/ovmf/OVMF.qemuvars.fd", + "uefi-vars": { + "template": "/usr/share/edk2/ovmf/vars.secboot.json" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "enrolled-keys", + "secure-boot", + "host-uefi-vars", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json new file mode 100644 index 0000000000..95c25981dd --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json @@ -0,0 +1,28 @@ +{ + "description": "UEFI firmware for ARM64 virtual machines, SB disabled", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "filename": "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd", + "uefi-vars": { + "template": "/usr/share/edk2/aarch64/vars.blank.json" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "secure-boot", + "host-uefi-vars" + ], + "tags": [ + + ] +} diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-ovmf-qemuvars-x64-sb.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-ovmf-qemuvars-x64-sb.json new file mode 100644 index 0000000000..b3fb98cbce --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/91-edk2-ovmf-qemuvars-x64-sb.json @@ -0,0 +1,30 @@ +{ + "description": "OVMF for qemu uefi-vars, SB disabled", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "filename": "/usr/share/edk2/ovmf/OVMF.qemuvars.fd", + "uefi-vars": { + "template": "/usr/share/edk2/ovmf/vars.blank.json" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "secure-boot", + "host-uefi-vars", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c index ee585b67d2..075e3e1d4c 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -101,7 +101,11 @@ testFWPrecedence(const void *opaque G_GNUC_UNUSED) SYSCONFDIR "/qemu/firmware/59-libvirt-combined.json", PREFIX "/share/qemu/firmware/60-edk2-ovmf-x64-amdsev.json", PREFIX "/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json", + PREFIX "/share/qemu/firmware/90-edk2-aarch64-qemuvars-sb-enrolled.json", + PREFIX "/share/qemu/firmware/90-edk2-ovmf-qemuvars-x64-sb-enrolled.json", PREFIX "/share/qemu/firmware/90-libvirt-combined.json", + PREFIX "/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json", + PREFIX "/share/qemu/firmware/91-edk2-ovmf-qemuvars-x64-sb.json", PREFIX "/share/qemu/firmware/91-libvirt-bios.json", PREFIX "/share/qemu/firmware/93-libvirt-invalid.json", NULL @@ -296,7 +300,11 @@ mymain(void) DO_PARSE_TEST("usr/share/qemu/firmware/53-edk2-aarch64-verbose-raw.json"); DO_PARSE_TEST("usr/share/qemu/firmware/60-edk2-ovmf-x64-amdsev.json"); DO_PARSE_TEST("usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/90-edk2-ovmf-qemuvars-x64-sb-enrolled.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/90-edk2-aarch64-qemuvars-sb-enrolled.json"); DO_PARSE_TEST("usr/share/qemu/firmware/90-libvirt-combined.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/91-edk2-ovmf-qemuvars-x64-sb.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json"); DO_PARSE_TEST("usr/share/qemu/firmware/91-libvirt-bios.json"); DO_PARSE_FAILURE_TEST("usr/share/qemu/firmware/93-libvirt-invalid.json"); @@ -325,7 +333,7 @@ mymain(void) DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_I686, false, false, "/usr/share/seabios/bios-256k.bin:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS); - DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64, true, false, + DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64, true, true, "/usr/share/seabios/bios-256k.bin:NULL:" "/usr/share/edk2/ovmf/OVMF_CODE_4M.secboot.qcow2:/usr/share/edk2/ovmf/OVMF_VARS_4M.secboot.qcow2:" "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd:/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd:" @@ -335,7 +343,9 @@ mymain(void) "/usr/share/edk2/ovmf/OVMF_CODE.fd:/usr/share/edk2/ovmf/OVMF_VARS.fd:" "/usr/share/edk2/ovmf/OVMF.combined.fd:NULL:" "/usr/share/edk2/ovmf/OVMF.amdsev.fd:NULL:" - "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd:NULL", + "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd:NULL:" + "/usr/share/edk2/ovmf/OVMF.qemuvars.fd:/usr/share/edk2/ovmf/vars.secboot.json:" + "/usr/share/edk2/ovmf/OVMF.qemuvars.fd:/usr/share/edk2/ovmf/vars.blank.json", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false, false, @@ -344,11 +354,13 @@ mymain(void) DO_SUPPORTED_TEST("microvm", VIR_ARCH_X86_64, false, false, "/usr/share/edk2/ovmf/MICROVM.fd:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); - DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64, false, false, + DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64, false, true, "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2:/usr/share/edk2/aarch64/vars-template-pflash.qcow2:" "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw:" "/usr/share/edk2/aarch64/QEMU_EFI-pflash.qcow2:/usr/share/edk2/aarch64/vars-template-pflash.qcow2:" - "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw", + "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw:" + "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd:/usr/share/edk2/aarch64/vars.secboot.json:" + "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd:/usr/share/edk2/aarch64/vars.blank.json", VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); DO_SUPPORTED_TEST("virt", VIR_ARCH_RISCV64, false, false, "/usr/share/edk2/riscv/RISCV_VIRT_CODE.qcow2:/usr/share/edk2/riscv/RISCV_VIRT_VARS.qcow2", diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err index 3edb2b3451..e64c2b21aa 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err @@ -1 +1 @@ -operation failed: Unable to find 'efi' firmware that is compatible with the current configuration +unsupported configuration: The uefi-vars device is not supported by this QEMU binary diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args new file mode 100644 index 0000000000..abc934692a --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-aarch64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ +-accel kvm \ +-bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err deleted file mode 100644 index 3edb2b3451..0000000000 --- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err +++ /dev/null @@ -1 +0,0 @@ -operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml index 908a8435f9..8c288d7d0c 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml @@ -8,8 +8,10 @@ <type arch='aarch64' machine='virt-8.2'>hvm</type> <firmware> <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> </firmware> - <loader format='raw'/> + <loader type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <varstore template='/usr/share/edk2/aarch64/vars.secboot.json' path='/var/lib/libvirt/qemu/varstore/guest.json'/> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args new file mode 100644 index 0000000000..abc934692a --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-aarch64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ +-accel kvm \ +-bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err deleted file mode 100644 index 3edb2b3451..0000000000 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err +++ /dev/null @@ -1 +0,0 @@ -operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml index b0fa092509..8c288d7d0c 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml @@ -6,8 +6,12 @@ <vcpu placement='static'>1</vcpu> <os firmware='efi'> <type arch='aarch64' machine='virt-8.2'>hvm</type> - <loader format='raw'/> - <varstore/> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> + </firmware> + <loader type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <varstore template='/usr/share/edk2/aarch64/vars.secboot.json' path='/var/lib/libvirt/qemu/varstore/guest.json'/> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args new file mode 100644 index 0000000000..9a899c2a65 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args @@ -0,0 +1,34 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine pc-q35-8.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ +-accel kvm \ +-cpu qemu64 \ +-bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-global ICH9-LPC.noreboot=off \ +-watchdog-action reset \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err deleted file mode 100644 index 3edb2b3451..0000000000 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err +++ /dev/null @@ -1 +0,0 @@ -operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml index c4d70c9fc5..cfce35de3f 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml @@ -6,8 +6,12 @@ <vcpu placement='static'>1</vcpu> <os firmware='efi'> <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> - <loader format='raw'/> - <varstore/> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> + </firmware> + <loader type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <varstore template='/usr/share/edk2/ovmf/vars.secboot.json' path='/var/lib/libvirt/qemu/varstore/guest.json'/> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err index 4fe79bdacf..e64c2b21aa 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err @@ -1 +1 @@ -unsupported configuration: ACPI requires UEFI on this architecture +unsupported configuration: The uefi-vars device is not supported by this QEMU binary diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args new file mode 100644 index 0000000000..abc934692a --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-aarch64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ +-accel kvm \ +-bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err deleted file mode 100644 index 4fe79bdacf..0000000000 --- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err +++ /dev/null @@ -1 +0,0 @@ -unsupported configuration: ACPI requires UEFI on this architecture diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.xml similarity index 76% rename from tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml rename to tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.xml index 5213a41b90..83faf68426 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.xml @@ -8,13 +8,15 @@ <type arch='aarch64' machine='virt-8.2'>hvm</type> <firmware> <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> </firmware> - <loader format='raw'/> + <loader type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <varstore template='/usr/share/edk2/aarch64/vars.secboot.json' path='/path/to/guest.json'/> <boot dev='hd'/> </os> <features> <acpi/> - <gic version='3'/> + <gic version='2'/> </features> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml index 296c6e8f59..a7b54a3fac 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml @@ -4,10 +4,14 @@ <memory unit='KiB'>1048576</memory> <currentMemory unit='KiB'>1048576</currentMemory> <vcpu placement='static'>1</vcpu> - <os> + <os firmware='efi'> <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> + </firmware> <loader type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> - <varstore path='/path/to/guest.json'/> + <varstore template='/usr/share/edk2/ovmf/vars.secboot.json' path='/path/to/guest.json'/> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 43e994fc93..187f90c9dc 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1620,7 +1620,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-manual-efi-varstore-q35"); DO_TEST_CAPS_VER_PARSE_ERROR("firmware-manual-efi-varstore-q35", "8.2.0"); - DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64", "8.2.0"); /* Make sure all combinations of ACPI and UEFI behave as expected */ @@ -1657,8 +1657,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-enrolled-keys"); - DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64"); - DO_TEST_CAPS_ARCH_VER_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64", "8.2.0"); + DO_TEST_CAPS_ARCH_LATEST("firmware-auto-efi-enrolled-keys-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("firmware-auto-efi-enrolled-keys-aarch64", "aarch64", "8.2.0"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-enrolled-keys"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-enrolled-keys-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-smm-off"); @@ -1673,8 +1673,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-file"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); - DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-varstore-q35"); - DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_LATEST("firmware-auto-efi-varstore-q35"); + DO_TEST_CAPS_ARCH_LATEST("firmware-auto-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
This makes guests actually functional. https://issues.redhat.com/browse/RHEL-82645 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_command.c | 34 +++++++++++++++++++ ...-enrolled-keys-aarch64.aarch64-latest.args | 1 + ...o-efi-varstore-aarch64.aarch64-latest.args | 1 + ...e-auto-efi-varstore-q35.x86_64-latest.args | 1 + ...l-efi-varstore-aarch64.aarch64-latest.args | 1 + ...manual-efi-varstore-q35.x86_64-latest.args | 1 + 6 files changed, 39 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index a742998e4c..ba300f3551 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9815,6 +9815,37 @@ qemuBuildDomainLoaderCommandLine(virCommand *cmd, } +static int +qemuBuildUefiVarsCommandLine(virCommand *cmd, + const virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + virDomainLoaderDef *loader = def->os.loader; + virDomainVarstoreDef *varstore = def->os.varstore; + g_autoptr(virJSONValue) props = NULL; + const char *model = NULL; + + if (!loader || !varstore || !varstore->path) + return 0; + + if (ARCH_IS_X86(def->os.arch)) + model = "uefi-vars-x64"; + else + model = "uefi-vars-sysbus"; + + if (virJSONValueObjectAdd(&props, + "s:driver", model, + "s:jsonfile", varstore->path, + NULL) < 0) + return -1; + + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) < 0) + return -1; + + return 0; +} + + static int qemuBuildTPMDevCmd(virCommand *cmd, const virDomainDef *def, @@ -10889,6 +10920,9 @@ qemuBuildCommandLine(virDomainObj *vm, qemuBuildDomainLoaderCommandLine(cmd, def); + if (qemuBuildUefiVarsCommandLine(cmd, def, qemuCaps) < 0) + return NULL; + if (qemuBuildMemCommandLine(cmd, def, qemuCaps, priv) < 0) return NULL; diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args index abc934692a..10f1a5a6a4 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args @@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ -accel kvm \ -bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-device '{"driver":"uefi-vars-sysbus","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args index abc934692a..10f1a5a6a4 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args @@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ -accel kvm \ -bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-device '{"driver":"uefi-vars-sysbus","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args index 9a899c2a65..392ea77c28 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args @@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -accel kvm \ -cpu qemu64 \ -bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \ +-device '{"driver":"uefi-vars-x64","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args index abc934692a..894bab7ffe 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args @@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ -accel kvm \ -bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-device '{"driver":"uefi-vars-sysbus","jsonfile":"/path/to/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args index 9a899c2a65..6c04c8c39f 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args @@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -accel kvm \ -cpu qemu64 \ -bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \ +-device '{"driver":"uefi-vars-x64","jsonfile":"/path/to/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ -overcommit mem-lock=off \ -- 2.53.0
On Mon, Feb 23, 2026 at 07:31:16PM +0100, Andrea Bolognani via Devel wrote:
This makes guests actually functional.
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_command.c | 34 +++++++++++++++++++ ...-enrolled-keys-aarch64.aarch64-latest.args | 1 + ...o-efi-varstore-aarch64.aarch64-latest.args | 1 + ...e-auto-efi-varstore-q35.x86_64-latest.args | 1 + ...l-efi-varstore-aarch64.aarch64-latest.args | 1 + ...manual-efi-varstore-q35.x86_64-latest.args | 1 + 6 files changed, 39 insertions(+)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
We are not introducing additional API flags for varstore handling since that would require unnecessary churn in all libvirt-based apps, and the intent is the same: recreate the UEFI variable storage, be it NVRAM or varstore, from its template. In order to clarify that the existing flags affect varstore too, update their documentation. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- include/libvirt/libvirt-domain-snapshot.h | 2 +- include/libvirt/libvirt-domain.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/libvirt/libvirt-domain-snapshot.h b/include/libvirt/libvirt-domain-snapshot.h index a11cd3f823..e14b661e37 100644 --- a/include/libvirt/libvirt-domain-snapshot.h +++ b/include/libvirt/libvirt-domain-snapshot.h @@ -217,7 +217,7 @@ typedef enum { VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING = 1 << 0, /* Run after revert (Since: 0.9.5) */ VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED = 1 << 1, /* Pause after revert (Since: 0.9.5) */ VIR_DOMAIN_SNAPSHOT_REVERT_FORCE = 1 << 2, /* Allow risky reverts (Since: 0.9.7) */ - VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM from template (Since: 8.1.0) */ + VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */ } virDomainSnapshotRevertFlags; /* Revert the domain to a point-in-time snapshot. The diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 56c21dcf25..d82406fe05 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -371,7 +371,7 @@ typedef enum { VIR_DOMAIN_START_BYPASS_CACHE = 1 << 2, /* Avoid file system cache pollution (Since: 0.9.4) */ VIR_DOMAIN_START_FORCE_BOOT = 1 << 3, /* Boot, discarding any managed save (Since: 0.9.5) */ VIR_DOMAIN_START_VALIDATE = 1 << 4, /* Validate the XML document against schema (Since: 1.2.12) */ - VIR_DOMAIN_START_RESET_NVRAM = 1 << 5, /* Re-initialize NVRAM from template (Since: 8.1.0) */ + VIR_DOMAIN_START_RESET_NVRAM = 1 << 5, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */ } virDomainCreateFlags; @@ -1652,7 +1652,7 @@ typedef enum { VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution (Since: 0.9.4) */ VIR_DOMAIN_SAVE_RUNNING = 1 << 1, /* Favor running over paused (Since: 0.9.5) */ VIR_DOMAIN_SAVE_PAUSED = 1 << 2, /* Favor paused over running (Since: 0.9.5) */ - VIR_DOMAIN_SAVE_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM from template (Since: 8.1.0) */ + VIR_DOMAIN_SAVE_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */ } virDomainSaveRestoreFlags; int virDomainSave (virDomainPtr domain, -- 2.53.0
Document the fact that the existing flags which apply to NVRAM files also do the right thing when varstore files are used instead. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/manpages/virsh.rst | 23 ++++++++++++----------- tools/virsh-domain.c | 10 +++++----- tools/virsh-snapshot.c | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index ff0cf1a715..b3e9289894 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1722,8 +1722,8 @@ of open file descriptors which should be pass on into the guest. The file descriptors will be re-numbered in the guest, starting from 3. This is only supported with container based virtualization. -If *--reset-nvram* is specified, any existing NVRAM file will be deleted -and re-initialized from its pristine template. +If *--reset-nvram* is specified, any existing NVRAM/varstore file will be +deleted and re-initialized from its pristine template. **Example:** @@ -4281,8 +4281,8 @@ save image to decide between running or paused; passing either the *--running* or *--paused* flag will allow overriding which state the domain should be started in. -If *--reset-nvram* is specified, any existing NVRAM file will be deleted -and re-initialized from its pristine template. +If *--reset-nvram* is specified, any existing NVRAM/varstore file will be +deleted and re-initialized from its pristine template. *--parallel-channels* option can specify number of parallel IO channels to be used when loading memory from file. Parallel save may significantly @@ -4925,8 +4925,8 @@ of open file descriptors which should be pass on into the guest. The file descriptors will be re-numbered in the guest, starting from 3. This is only supported with container based virtualization. -If *--reset-nvram* is specified, any existing NVRAM file will be deleted -and re-initialized from its pristine template. +If *--reset-nvram* is specified, any existing NVRAM/varstore file will be +deleted and re-initialized from its pristine template. suspend @@ -4988,9 +4988,10 @@ domain. Without the flag, attempts to undefine an inactive domain with checkpoint metadata will fail. If the domain is active, this flag is ignored. -*--nvram* and *--keep-nvram* specify accordingly to delete or keep nvram -(/domain/os/nvram/) file. If the domain has an nvram file and the flags are -omitted, the undefine will fail. +The *--nvram* and *--keep-nvram* flags specify whether to delete or keep the +NVRAM (/domain/os/nvram/) or varstore (/domain/os/varstore) file respectively. +If the domain has an NVRAM/varstore file and the flags are omitted, the +undefine operation will fail. The *--storage* flag takes a parameter ``volumes``, which is a comma separated list of volume target names or source paths of storage volumes to be removed @@ -8174,8 +8175,8 @@ requires the use of *--force* to proceed: likely cause extensive filesystem corruption or crashes due to swap content mismatches when run. -If *--reset-nvram* is specified, any existing NVRAM file will be deleted -and re-initialized from its pristine template. +If *--reset-nvram* is specified, any existing NVRAM/varstore file will be +deleted and re-initialized from its pristine template. snapshot-delete diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index a7f6a97dd7..5a2ae75379 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -3981,11 +3981,11 @@ static const vshCmdOptDef opts_undefine[] = { }, {.name = "nvram", .type = VSH_OT_BOOL, - .help = N_("remove nvram file") + .help = N_("remove NVRAM/varstore file") }, {.name = "keep-nvram", .type = VSH_OT_BOOL, - .help = N_("keep nvram file") + .help = N_("keep NVRAM/varstore file") }, {.name = "tpm", .type = VSH_OT_BOOL, @@ -4401,7 +4401,7 @@ static const vshCmdOptDef opts_start[] = { }, {.name = "reset-nvram", .type = VSH_OT_BOOL, - .help = N_("re-initialize NVRAM from its pristine template") + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; @@ -5728,7 +5728,7 @@ static const vshCmdOptDef opts_restore[] = { }, {.name = "reset-nvram", .type = VSH_OT_BOOL, - .help = N_("re-initialize NVRAM from its pristine template") + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; @@ -8520,7 +8520,7 @@ static const vshCmdOptDef opts_create[] = { }, {.name = "reset-nvram", .type = VSH_OT_BOOL, - .help = N_("re-initialize NVRAM from its pristine template") + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index 8e5b9d635c..08184576a7 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -1714,7 +1714,7 @@ static const vshCmdOptDef opts_snapshot_revert[] = { }, {.name = "reset-nvram", .type = VSH_OT_BOOL, - .help = N_("re-initialize NVRAM from its pristine template") + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; -- 2.53.0
On Mon, Feb 23, 2026 at 07:31:18PM +0100, Andrea Bolognani via Devel wrote:
Document the fact that the existing flags which apply to NVRAM files also do the right thing when varstore files are used instead.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/manpages/virsh.rst | 23 ++++++++++++----------- tools/virsh-domain.c | 10 +++++----- tools/virsh-snapshot.c | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- NEWS.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 7a80116de3..71f1f21472 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -24,6 +24,23 @@ v12.1.0 (unreleased) example Secure Boot support, is available for the selected architecture and machine type. + * qemu: Add support for uefi-vars device and firmware builds using it + + This is particularly noteworthy for people running aarch64 VMs with the + 'virt' machine type, as it makes it finally possible to use Secure Boot + with that combination. + + In most cases, no special steps are needed to take advantage of this: + assuming that you have installed a recent version of QEMU, as well as a + build of edk2 that includes the necessary binaries, you can just `enable + Secure Boot <kbase/secureboot.html>`__ as you normally would. + + To explicitly request that the uefi-vars device is used even for scenarios + where that would normally not be the case, it's enough to add an empty + ``<varstore/>`` element in the domain XML. More details are available in + the `guest firmware configuration <formatdomain.html#guest-firmware>`__ + section of the documentation. + * **Improvements** * **Bug fixes** -- 2.53.0
On Mon, Feb 23, 2026 at 07:31:19PM +0100, Andrea Bolognani via Devel wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- NEWS.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
On 2/23/26 19:30, Andrea Bolognani via Devel wrote:
This series makes it possible to use Secure Boot with aarch64 VMs.
https://issues.redhat.com/browse/RHEL-82645
Changes from [v3]:
* changes to JSON firmware descriptors shipped by the edk2 package have been merged in Fedora, so the corresponding patch is no longer marked as DONOTMERGE;
* drop new varstore-specific flags from virsh, the existing NVRAM-related flags will work for varstore too;
* drop some changes to firmware selection that were not related to varstore support, to be reworked and submitted again at a later date;
* split, join and shuffle around patches;
* tweak things according to review feedback.
Changes from [v2]:
* changes to the schema for JSON firmware descriptors have been queued for merge in QEMU, so the corresponding patch is no longer marked as DONOTMERGE;
* improve documentation;
* rebase on top of master, addressing conflicts that I have caused with some recent changes related to this work.
Changes from [v1]:
* rewrite based on review feedback: the <nvram> element is no longer used, and a dedicated <varstore> element is introduced instead;
* additional test coverage, as well as fixes and improvements related to firmware selection and its documentation, are present as well.
[v3] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/5JTQA... [v2] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/WVWT3... [v1] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/TGLFM...
Andrea Bolognani (36): docs: Rename "BIOS bootloader" section to "guest firmware" docs: Improvement related to firmware selection qemu_firmware: Only set format for custom loader if path is present conf: Move type=rom default for loader to drivers tests: Rename custom JSON firmware descriptors schema: Introduce osnvram define conf: Parse and format varstore element conf: Update validation to consider varstore element qemu_capabilities: Introduce QEMU_CAPS_DEVICE_UEFI_VARS qemu: Validate presence of uefi-vars device tests: Add firmware-manual-efi-varstore-q35 tests: Add firmware-manual-efi-varstore-aarch64 tests: Add firmware-auto-efi-varstore-q35 tests: Add firmware-auto-efi-varstore-aarch64 tests: Add firmware-auto-efi-enrolled-keys-aarch64 qemu_firmware: Parse host-uefi-vars firmware feature qemu_firmware: Split sanity check qemu_firmware: Consider host-uefi-vars feature in sanity check qemu_firmware: Support extended syntax for ROM firmware descriptors qemu_firmware: Report NVRAM template path for ROMs conf: Include varstore element in domcaps qemu: Fill in varstore element in domcaps qemu_firmware: Use of NVRAM implies stateful firmware qemu_firmware: Allow matching stateful ROMs qemu_firmware: Fill in varstore information qemu: Introduce varstoreDir qemu_firmware: Generate varstore path when necessary qemu: Introduce qemuPrepareNVRAMFileCommon() qemu: Create and delete varstore file security: Mark ROMs as read only when using AppArmor security: Handle varstore file tests: Add firmware descriptors for uefi-vars builds qemu_command: Use uefi-vars device where appropriate include: Mention varstore where applicable virsh: Update for varstore handling news: Document support for uefi-vars device and firmwares
173 files changed, 1546 insertions(+), 307 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (3)
-
Andrea Bolognani -
Daniel P. Berrangé -
Michal Prívozník