[PATCH v2 00/38] 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 Note that, while I consider the entire series to be ready for review, there are two patches that are marked as DONOTMERGE: that's because they respectively implement support for a JSON firmware descriptor syntax extension that has not yet been approved, and import into the tree firmware descriptor that are not yet part of the Fedora edk2 package. The latter depends on the former, of course, for which patches have been posted[1] to the QEMU mailing list. 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. [1] https://mail.gnu.org/archive/html/qemu-devel/2026-02/msg02498.html [v1] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/TGLFM... Andrea Bolognani (38): qemu_firmware: Only set format for custom loader if path is present conf: Move type=rom default for loader to drivers qemu_firmware: Improve matching when loader.type is absent tests: Rename custom JSON firmware descriptors tests: Update JSON firmware descriptor for BIOS schema: Add varstore element 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 DONOTMERGE: qemu_firmware: Support extended syntax for ROM firmware descriptors qemu_firmware: Report NVRAM template path for ROMs schema: Add varstore element for domcaps 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 DONOTMERGE: tests: Add firmware descriptors for uefi-vars builds qemu_command: Use uefi-vars device where appropriate qemu: Introduce qemuPrepareNVRAMFileCommon() qemu: Create and delete varstore file security: Mark ROMs as read only when using AppArmor security: Handle varstore file include: Mention varstore where applicable virsh: Update for varstore handling docs: Update for varstore and improve news: Document support for uefi-vars device and firmwares NEWS.rst | 16 ++ docs/formatcaps.rst | 2 +- docs/formatdomain.rst | 47 +++-- docs/formatdomaincaps.rst | 81 +++++--- docs/kbase/secureboot.rst | 46 +++-- docs/manpages/virsh.rst | 44 +++-- 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 | 64 +++--- 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 | 31 ++- src/qemu/qemu_capabilities.h | 3 + src/qemu/qemu_command.c | 34 ++++ src/qemu/qemu_conf.c | 4 + src/qemu/qemu_conf.h | 1 + src/qemu/qemu_driver.c | 27 ++- src/qemu/qemu_firmware.c | 182 ++++++++++++++++-- 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 | 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 + .../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 ...0-edk2-ovmf-qemuvars-x64-sb-enrolled.json} | 15 +- .../70-edk2-qemuvars-aarch64-sb-enrolled.json | 28 +++ ...json => 71-edk2-ovmf-qemuvars-x64-sb.json} | 16 +- .../firmware/71-edk2-qemuvars-aarch64-sb.json | 27 +++ ...combined.json => 90-libvirt-combined.json} | 0 .../{91-bios.json => 91-libvirt-bios.json} | 2 +- ...{92-masked.json => 92-libvirt-masked.json} | 0 ...3-invalid.json => 93-libvirt-invalid.json} | 0 tests/qemufirmwaretest.c | 71 ++++--- ...-auto-bios-not-stateless.x86_64-latest.err | 2 +- ...auto-bios-not-stateless.x86_64-latest.xml} | 6 +- ...firmware-auto-bios-nvram.x86_64-latest.err | 2 +- ...are-auto-bios-stateless.x86_64-latest.args | 2 +- ...ware-auto-bios-stateless.x86_64-latest.xml | 2 +- .../firmware-auto-bios.x86_64-latest.args | 2 +- .../firmware-auto-bios.x86_64-latest.xml | 2 +- ...fi-enrolled-keys-aarch64.aarch64-8.2.0.err | 1 + ...enrolled-keys-aarch64.aarch64-latest.args} | 12 +- ...i-enrolled-keys-aarch64.aarch64-latest.xml | 32 +++ ...irmware-auto-efi-enrolled-keys-aarch64.xml | 20 ++ ...-efi-varstore-aarch64.aarch64-latest.args} | 12 +- ...to-efi-varstore-aarch64.aarch64-latest.xml | 32 +++ .../firmware-auto-efi-varstore-aarch64.xml | 18 ++ ...-auto-efi-varstore-q35.x86_64-latest.args} | 5 +- ...e-auto-efi-varstore-q35.x86_64-latest.xml} | 11 +- .../firmware-auto-efi-varstore-q35.xml | 18 ++ ...ual-bios-not-stateless.x86_64-latest.args} | 8 +- ...anual-bios-not-stateless.x86_64-latest.err | 1 - ...nual-bios-not-stateless.x86_64-latest.xml} | 2 +- ...re-manual-bios-stateless.x86_64-latest.xml | 6 +- .../firmware-manual-bios.x86_64-latest.xml | 6 +- ...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 + ...-efi-varstore-aarch64.aarch64-latest.args} | 12 +- ...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 + ...anual-efi-varstore-q35.x86_64-latest.args} | 5 +- ...manual-efi-varstore-q35.x86_64-latest.xml} | 11 +- .../firmware-manual-efi-varstore-q35.xml | 19 ++ tests/qemuxmlconftest.c | 16 +- tests/testutilsqemu.c | 2 + tools/virsh-domain.c | 55 ++++-- tools/virsh-snapshot.c | 9 +- 179 files changed, 1296 insertions(+), 380 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%) copy tests/qemufirmwaredata/usr/share/qemu/firmware/{90-combined.json => 70-edk2-ovmf-qemuvars-x64-sb-enrolled.json} (55%) create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-qemuvars-aarch64-sb-enrolled.json copy tests/qemufirmwaredata/usr/share/qemu/firmware/{90-combined.json => 71-edk2-ovmf-qemuvars-x64-sb.json} (51%) create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-qemuvars-aarch64-sb.json 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} (90%) 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%) copy tests/qemuxmlconfdata/{firmware-auto-bios.x86_64-latest.xml => firmware-auto-bios-not-stateless.x86_64-latest.xml} (84%) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err copy tests/qemuxmlconfdata/{firmware-auto-bios.x86_64-latest.args => firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args} (72%) 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 copy tests/qemuxmlconfdata/{firmware-auto-bios.x86_64-latest.args => firmware-auto-efi-varstore-aarch64.aarch64-latest.args} (72%) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml copy tests/qemuxmlconfdata/{firmware-auto-bios-stateless.x86_64-latest.args => firmware-auto-efi-varstore-q35.x86_64-latest.args} (83%) copy tests/qemuxmlconfdata/{firmware-auto-bios-stateless.x86_64-latest.xml => firmware-auto-efi-varstore-q35.x86_64-latest.xml} (73%) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml copy tests/qemuxmlconfdata/{firmware-auto-bios.x86_64-latest.args => firmware-manual-bios-not-stateless.x86_64-latest.args} (84%) delete mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err copy tests/qemuxmlconfdata/{firmware-manual-bios.x86_64-latest.xml => firmware-manual-bios-not-stateless.x86_64-latest.xml} (90%) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err copy tests/qemuxmlconfdata/{firmware-auto-bios.x86_64-latest.args => firmware-manual-efi-varstore-aarch64.aarch64-latest.args} (73%) 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 copy tests/qemuxmlconfdata/{firmware-auto-bios.x86_64-latest.args => firmware-manual-efi-varstore-q35.x86_64-latest.args} (85%) copy tests/qemuxmlconfdata/{firmware-auto-bios-stateless.x86_64-latest.xml => firmware-manual-efi-varstore-q35.x86_64-latest.xml} (74%) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml -- 2.53.0
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> --- 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 52205b72f8..183fdd7ea9 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> --- 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 183fdd7ea9..e0e6a3a557 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
Right now we don't allow any match in that scenario, but really if a specific type hasn't been requested it means that any type is considered acceptable and we should allow matching against both UEFI and BIOS. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index e0e6a3a557..1d414da601 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1104,16 +1104,17 @@ qemuFirmwareMatchDomain(const virDomainDef *def, * not present, we can still infer this information from * other factors. Specifically, the pflash loader type is * only used for UEFI, while the rom loader type can be used - * both for UEFI and BIOS */ + * both for UEFI and BIOS. If the loader type has not been + * specified, we keep our options open */ switch (loader->type) { case VIR_DOMAIN_LOADER_TYPE_PFLASH: wantUEFI = true; break; case VIR_DOMAIN_LOADER_TYPE_ROM: + case VIR_DOMAIN_LOADER_TYPE_NONE: wantUEFI = true; wantBIOS = true; break; - case VIR_DOMAIN_LOADER_TYPE_NONE: case VIR_DOMAIN_LOADER_TYPE_LAST: default: break; -- 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> --- .../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 a4fb5c9b9c..830aae951a 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; @@ -280,9 +280,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 is one of our custom descriptors. The firmware binary it advertises really exists, but looking at the qemuxmlconf test cases we use a slightly different path there. As a consequence of this change, the firmware-manual-bios* test cases behave more realistically, in that the JSON firmware descriptor is picked up and the additional information that can be figured out from it is filled in. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- .../usr/share/qemu/firmware/91-libvirt-bios.json | 2 +- tests/qemufirmwaretest.c | 8 ++++---- .../firmware-auto-bios-stateless.x86_64-latest.args | 2 +- .../firmware-auto-bios-stateless.x86_64-latest.xml | 2 +- .../qemuxmlconfdata/firmware-auto-bios.x86_64-latest.args | 2 +- .../qemuxmlconfdata/firmware-auto-bios.x86_64-latest.xml | 2 +- .../firmware-manual-bios-stateless.x86_64-latest.xml | 6 +++++- .../firmware-manual-bios.x86_64-latest.xml | 6 +++++- 8 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/91-libvirt-bios.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/91-libvirt-bios.json index 378e6d93a5..de09927437 100644 --- a/tests/qemufirmwaredata/usr/share/qemu/firmware/91-libvirt-bios.json +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/91-libvirt-bios.json @@ -5,7 +5,7 @@ ], "mapping": { "device": "memory", - "filename": "/usr/share/seabios/bios-256k.bin" + "filename": "/usr/share/seabios/bios.bin" }, "targets": [ { diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c index 830aae951a..04d11efb8e 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -301,16 +301,16 @@ mymain(void) } while (0) DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_X86_64, false, - "/usr/share/seabios/bios-256k.bin:NULL:" + "/usr/share/seabios/bios.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, - "/usr/share/seabios/bios-256k.bin:NULL", + "/usr/share/seabios/bios.bin:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS); DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64, true, - "/usr/share/seabios/bios-256k.bin:NULL:" + "/usr/share/seabios/bios.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:" "/usr/share/edk2/ovmf/OVMF_CODE_4M.secboot.qcow2:/usr/share/edk2/ovmf/OVMF_VARS_4M.qcow2:" @@ -323,7 +323,7 @@ mymain(void) VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false, - "/usr/share/seabios/bios-256k.bin:NULL", + "/usr/share/seabios/bios.bin:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS); DO_SUPPORTED_TEST("microvm", VIR_ARCH_X86_64, false, "/usr/share/edk2/ovmf/MICROVM.fd:NULL", diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.args index a6a52e2b52..a96a0e1bbf 100644 --- a/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.args @@ -13,7 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine pc-q35-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ -accel kvm \ -cpu qemu64 \ --bios /usr/share/seabios/bios-256k.bin \ +-bios /usr/share/seabios/bios.bin \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.xml index 547dff5ed3..de0d3c7560 100644 --- a/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-auto-bios-stateless.x86_64-latest.xml @@ -10,7 +10,7 @@ <feature enabled='no' name='enrolled-keys'/> <feature enabled='no' name='secure-boot'/> </firmware> - <loader type='rom' stateless='yes' format='raw'>/usr/share/seabios/bios-256k.bin</loader> + <loader type='rom' stateless='yes' format='raw'>/usr/share/seabios/bios.bin</loader> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.args index a6a52e2b52..a96a0e1bbf 100644 --- a/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.args @@ -13,7 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine pc-q35-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ -accel kvm \ -cpu qemu64 \ --bios /usr/share/seabios/bios-256k.bin \ +-bios /usr/share/seabios/bios.bin \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.xml index ae9c9f56d9..ea0cf0134a 100644 --- a/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.xml @@ -10,7 +10,7 @@ <feature enabled='no' name='enrolled-keys'/> <feature enabled='no' name='secure-boot'/> </firmware> - <loader type='rom' format='raw'>/usr/share/seabios/bios-256k.bin</loader> + <loader type='rom' format='raw'>/usr/share/seabios/bios.bin</loader> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-stateless.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-bios-stateless.x86_64-latest.xml index dc641ff9f6..4aaa13e668 100644 --- a/tests/qemuxmlconfdata/firmware-manual-bios-stateless.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-manual-bios-stateless.x86_64-latest.xml @@ -4,8 +4,12 @@ <memory unit='KiB'>1048576</memory> <currentMemory unit='KiB'>1048576</currentMemory> <vcpu placement='static'>1</vcpu> - <os> + <os firmware='bios'> <type arch='x86_64' machine='pc-i440fx-10.0'>hvm</type> + <firmware> + <feature enabled='no' name='enrolled-keys'/> + <feature enabled='no' name='secure-boot'/> + </firmware> <loader type='rom' stateless='yes' format='raw'>/usr/share/seabios/bios.bin</loader> <boot dev='hd'/> </os> diff --git a/tests/qemuxmlconfdata/firmware-manual-bios.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-bios.x86_64-latest.xml index 7c06d8e8b8..85dec8ca8e 100644 --- a/tests/qemuxmlconfdata/firmware-manual-bios.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-manual-bios.x86_64-latest.xml @@ -4,8 +4,12 @@ <memory unit='KiB'>1048576</memory> <currentMemory unit='KiB'>1048576</currentMemory> <vcpu placement='static'>1</vcpu> - <os> + <os firmware='bios'> <type arch='x86_64' machine='pc-i440fx-10.0'>hvm</type> + <firmware> + <feature enabled='no' name='enrolled-keys'/> + <feature enabled='no' name='secure-boot'/> + </firmware> <loader type='rom' format='raw'>/usr/share/seabios/bios.bin</loader> <boot dev='hd'/> </os> -- 2.53.0
This will be used to configure the backing storage used by the uefi-vars QEMU device. Best viewed with 'git show -w'. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/schemas/domaincommon.rng | 64 +++++++++++++++++++------------ 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index e659900687..be1da54526 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -349,31 +349,47 @@ </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> + <choice> + <element name="nvram"> + <optional> + <attribute name="template"> <ref name="absFilePath"/> - </group> - <group> - <ref name="diskSource"/> - </group> - </choice> - </optional> - </element> + </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> + <element name="varstore"> + <interleave> + <optional> + <attribute name="template"> + <ref name="absFilePath"/> + </attribute> + </optional> + <optional> + <attribute name="path"> + <ref name="absFilePath"/> + </attribute> + </optional> + </interleave> + </element> + </choice> </optional> <optional> <ref name="osbootkernel"/> -- 2.53.0
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> --- src/conf/domain_conf.c | 79 ++++++++++++++++++++++++++++++++++++---- src/conf/domain_conf.h | 9 +++++ src/conf/virconftypes.h | 2 + src/libvirt_private.syms | 2 + 4 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e88dc62520..65a1919519 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3943,6 +3943,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) @@ -4045,6 +4066,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); } @@ -17954,6 +17976,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, @@ -18401,16 +18434,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; } @@ -28046,6 +28092,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) { @@ -29518,6 +29578,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 1e16310ef9..ceb0053317 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2414,6 +2414,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, @@ -2567,6 +2575,7 @@ struct _virDomainOSDef { size_t nacpiTables; virDomainOSACPITableDef **acpiTables; virDomainLoaderDef *loader; + virDomainVarstoreDef *varstore; char *bootloader; char *bootloaderArgs; int smbios_mode; 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 d81b30f0b6..e5b16f93fa 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -718,6 +718,8 @@ virDomainTPMProfileRemoveDisabledTypeToString; virDomainTPMVersionTypeFromString; virDomainTPMVersionTypeToString; virDomainUSBDeviceDefForeach; +virDomainVarstoreDefFree; +virDomainVarstoreDefNew; virDomainVideoDefaultRAM; virDomainVideoDefClear; virDomainVideoDefFree; -- 2.53.0
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> --- 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 5f34682992..e723d1e838 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1555,7 +1555,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"); @@ -1608,7 +1611,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> --- src/qemu/qemu_capabilities.c | 5 +++++ src/qemu/qemu_capabilities.h | 3 +++ 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, 19 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b4d52eebcd..ce3e288b15 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -756,6 +756,9 @@ VIR_ENUM_IMPL(virQEMUCaps, "query-accelerators", /* QEMU_CAPS_QUERY_ACCELERATORS */ "mshv", /* QEMU_CAPS_MSHV */ "virtio-iommu.aw-bits", /* QEMU_CAPS_VIRTIO_IOMMU_AW_BITS */ + + /* 490 */ + "uefi-vars", /* QEMU_CAPS_DEVICE_UEFI_VARS */ ); @@ -1463,6 +1466,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-emulator", QEMU_CAPS_DEVICE_TPM_EMULATOR }, { "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH }, { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, + { "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 b02385ab0f..fce31d3873 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -732,6 +732,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_MSHV, /* -accel mshv */ QEMU_CAPS_VIRTIO_IOMMU_AW_BITS, /* virtio-iommu.aw-bits */ + /* 490 */ + 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 c2bffe88ad..730d6b3e6e 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -164,6 +164,7 @@ <flag name='usb-bot'/> <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> + <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 a7166aba44..b5dfd78b6b 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -210,6 +210,7 @@ <flag name='usb-bot'/> <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> + <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 4177eb06b6..a2e7d48f49 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -210,6 +210,7 @@ <flag name='usb-bot'/> <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> + <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 9faa853da2..5cec5b08de 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml @@ -141,6 +141,7 @@ <flag name='usb-bot'/> <flag name='qom-list-get'/> <flag name='virtio-iommu.aw-bits'/> + <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 d5566234a2..c8b7572f04 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml @@ -193,6 +193,7 @@ <flag name='qom-list-get'/> <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> + <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 12d2b262a5..a470968fd3 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml @@ -215,6 +215,7 @@ <flag name='qom-list-get'/> <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> + <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 7154cdb66c..7762ae1548 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml @@ -183,6 +183,7 @@ <flag name='disk-timed-stats'/> <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> + <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 0d627136e8..3d978a408f 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml @@ -203,6 +203,7 @@ <flag name='query-accelerators'/> <flag name='mshv'/> <flag name='virtio-iommu.aw-bits'/> + <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 5eae704512..1d649f3f0b 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml @@ -216,6 +216,7 @@ <flag name='disk-timed-stats'/> <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> + <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 3600be0301..399681c5bd 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml @@ -183,6 +183,7 @@ <flag name='disk-timed-stats'/> <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> + <flag name='uefi-vars'/> <version>10002050</version> <microcodeVersion>61700286</microcodeVersion> <package>v10.2.0-476-gcf3e71d8fc</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml index 6aa17de843..c09ede3275 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml @@ -216,6 +216,7 @@ <flag name='disk-timed-stats'/> <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> + <flag name='uefi-vars'/> <version>10002050</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.2.0-476-gcf3e71d8fc</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> --- 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 0bad299996..72c347eed9 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -752,6 +752,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) @@ -795,6 +812,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> --- ...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 e723d1e838..adcfc5bbdc 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1592,6 +1592,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> --- ...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 adcfc5bbdc..95a890909d 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1594,6 +1594,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> --- ...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 95a890909d..c1542ae9b0 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1645,6 +1645,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> --- ...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 c1542ae9b0..f659faf49a 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1646,6 +1646,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> --- ...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 f659faf49a..b6cc7d4dfe 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1631,6 +1631,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> --- 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 1d414da601..fd3e57d425 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" ); @@ -1182,6 +1184,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: @@ -1516,6 +1519,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: @@ -1571,6 +1575,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: @@ -2071,6 +2076,7 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_FEATURE_INTEL_TDX: case QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS: case QEMU_FIRMWARE_FEATURE_SECURE_BOOT: + 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> --- 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 fd3e57d425..c1e8065e2b 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1590,16 +1590,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> --- 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 c1e8065e2b..fff6c81177 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1553,6 +1553,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++) { @@ -1566,6 +1567,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: @@ -1575,7 +1579,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: @@ -1589,14 +1592,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. DONOTMERGE: The extended syntax has not been accepted into the official spec yet. Signed-off-by: Andrea Bolognani <abologna@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 fff6c81177..f41c09db72 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> --- 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 f41c09db72..d9f2ee4889 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2138,6 +2138,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> --- src/conf/schemas/domaincaps.rng | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/conf/schemas/domaincaps.rng b/src/conf/schemas/domaincaps.rng index 8d0380951d..6b953cae2b 100644 --- a/src/conf/schemas/domaincaps.rng +++ b/src/conf/schemas/domaincaps.rng @@ -78,6 +78,12 @@ </element> </define> + <define name="varstore"> + <element name="varstore"> + <ref name="supported"/> + </element> + </define> + <define name="os"> <element name="os"> <interleave> @@ -86,6 +92,9 @@ <optional> <ref name="loader"/> </optional> + <optional> + <ref name="varstore"/> + </optional> </interleave> </element> </define> -- 2.53.0
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/domain_capabilities.c | 10 ++++++++++ src/conf/domain_capabilities.h | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index f843124695..9b6f0b3e1b 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -436,17 +436,27 @@ 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 virDomainCapsLoader *loader = &os->loader; + const virDomainCapsVarstore *varstore = &os->varstore; FORMAT_PROLOGUE(os); ENUM_PROCESS(os, firmware, virDomainOsDefFirmwareTypeToString); virDomainCapsLoaderFormat(&childBuf, loader); + virDomainCapsVarstoreFormat(&childBuf, varstore); FORMAT_EPILOGUE(os); } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 437981c711..920646ba41 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -54,12 +54,18 @@ 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 { virTristateBool supported; virDomainCapsEnum firmware; /* Info about virDomainOsDefFirmware */ virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ + virDomainCapsVarstore varstore; }; STATIC_ASSERT_ENUM(VIR_DOMAIN_MEMORY_SOURCE_LAST); -- 2.53.0
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> --- 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 ce3e288b15..ccc19e1ed4 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6512,8 +6512,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, @@ -6521,8 +6539,10 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, size_t nfirmwares) { virDomainCapsLoader *capsLoader = &os->loader; + virDomainCapsVarstore *capsVarstore = &os->varstore; uint64_t autoFirmwares = 0; bool secure = false; + bool varstore = false; virFirmware **firmwaresAlt = NULL; size_t nfirmwaresAlt = 0; int ret = -1; @@ -6531,7 +6551,7 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, os->firmware.report = true; if (qemuFirmwareGetSupported(machine, arch, privileged, - &autoFirmwares, &secure, + &autoFirmwares, &secure, &varstore, &firmwaresAlt, &nfirmwaresAlt) < 0) return -1; @@ -6545,6 +6565,9 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, firmwaresAlt ? nfirmwaresAlt : nfirmwares) < 0) goto cleanup; + if (virQEMUCapsFillDomainVarstoreCaps(capsVarstore, varstore, qemuCaps) < 0) + goto cleanup; + ret = 0; cleanup: virFirmwareFreeList(firmwaresAlt, nfirmwaresAlt); @@ -7256,6 +7279,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 d9f2ee4889..1d7b5b58b7 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2032,6 +2032,7 @@ qemuFirmwareFillDomain(virQEMUDriver *driver, * @privileged: whether running as privileged user * @supported: returned bitmap of supported interfaces * @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 * @@ -2061,6 +2062,7 @@ qemuFirmwareGetSupported(const char *machine, bool privileged, uint64_t *supported, bool *secure, + bool *varstore, virFirmware ***fws, size_t *nfws) { @@ -2070,6 +2072,7 @@ qemuFirmwareGetSupported(const char *machine, *supported = VIR_DOMAIN_OS_DEF_FIRMWARE_NONE; *secure = false; + *varstore = false; if (fws) { *fws = NULL; @@ -2139,6 +2142,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 39572d979d..8b14a4cdb8 100644 --- a/src/qemu/qemu_firmware.h +++ b/src/qemu/qemu_firmware.h @@ -53,6 +53,7 @@ qemuFirmwareGetSupported(const char *machine, bool privileged, uint64_t *supported, 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 8cb51d795c..9a19d0aa0d 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 @@ -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-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml index 56192354ac..70263ace5f 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.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-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml index 4242f2fe9c..287316da41 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 @@ -25,6 +25,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 76d5fdd0d9..289a794f24 100644 --- a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml @@ -25,6 +25,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 30863d3d6b..8af13c9061 100644 --- a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml @@ -24,6 +24,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 30863d3d6b..8af13c9061 100644 --- a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml @@ -24,6 +24,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 5136e7a20d..48b487a4e1 100644 --- a/tests/domaincapsdata/qemu_10.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.ppc64.xml @@ -22,6 +22,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 3bbdbd68d0..a7da5401f7 100644 --- a/tests/domaincapsdata/qemu_10.0.0.s390x.xml +++ b/tests/domaincapsdata/qemu_10.0.0.s390x.xml @@ -22,6 +22,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 8b02db8802..6538c8484e 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.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_10.0.0.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0.x86_64.xml index 6dac17808c..e156d16868 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64.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_10.1.0-q35.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml index 31d4fab043..7dbb4c22ef 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 @@ -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-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml index 6213908152..76e62a1898 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.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-tcg.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml index cace9f109a..8b526899a9 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 @@ -25,6 +25,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 804848b8a7..9a8e0f86b8 100644 --- a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml @@ -25,6 +25,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 9d773385c4..0f29f72111 100644 --- a/tests/domaincapsdata/qemu_10.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_10.1.0.s390x.xml @@ -22,6 +22,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 6320200c20..dbd6d6281e 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.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_10.1.0.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0.x86_64.xml index 35c9b8c6d3..d3f44a5a65 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64.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_10.2.0-q35.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml index ebba8fd49f..7ae632edfd 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 @@ -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_10.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml index 5ce911d62f..a22283ae95 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.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.2.0-tcg.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml index 6c6f1e84c3..d33de415d5 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 @@ -25,6 +25,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 14e8e30f1c..fabc91a371 100644 --- a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml @@ -25,6 +25,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 84d3022006..a813a63282 100644 --- a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml @@ -24,6 +24,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 84d3022006..a813a63282 100644 --- a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml @@ -24,6 +24,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 c8f2585d7d..33721f8604 100644 --- a/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml @@ -24,6 +24,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 333bbaa698..d1faa825c9 100644 --- a/tests/domaincapsdata/qemu_10.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.x86_64.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_11.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml index be89b0a4f2..88b80ccbb7 100644 --- a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.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_11.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml index bb611142b3..47b05b16f4 100644 --- a/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml @@ -25,6 +25,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 906e3c1e68..c37401a04d 100644 --- a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml @@ -24,6 +24,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 906e3c1e68..c37401a04d 100644 --- a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml @@ -24,6 +24,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 956d59f877..4b7ac8019f 100644 --- a/tests/domaincapsdata/qemu_11.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.x86_64.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_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index b14cbddc59..44a93b4d92 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.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-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index 51547bf505..a232cf6aa8 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -25,6 +25,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 411925ad66..66c5e62d06 100644 --- a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml @@ -22,6 +22,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 ab387c862e..a4265c123f 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.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.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml index 4bbcb516ec..a510b198a8 100644 --- a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.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-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml index 839f0600c2..937028be67 100644 --- a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml @@ -25,6 +25,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 147d1bf7fb..d3a69fb64d 100644 --- a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml @@ -22,6 +22,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 612b5a44cc..ce65357b25 100644 --- a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.x86_64.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.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml index a031b673dd..30e4fc2b95 100644 --- a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.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-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml index 9360f8fadf..4c24fb7f69 100644 --- a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml @@ -25,6 +25,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 f3a2dfe6ff..db04bc1b04 100644 --- a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml @@ -22,6 +22,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 6738d8f852..8acb84dbe9 100644 --- a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.x86_64.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-hvf.x86_64+hvf.xml b/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml index b338bcc470..c2e1da8a3a 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 @@ -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-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml index 39eb10dc7a..d7ba18021b 100644 --- a/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.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.2.0-tcg.x86_64+hvf.xml b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml index 77fce0eb95..6c5c792377 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 @@ -25,6 +25,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 77fce0eb95..6c5c792377 100644 --- a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml @@ -25,6 +25,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 8bda6af431..6f949f2ef2 100644 --- a/tests/domaincapsdata/qemu_7.2.0.ppc.xml +++ b/tests/domaincapsdata/qemu_7.2.0.ppc.xml @@ -21,6 +21,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 16708c3d85..7a6526f05b 100644 --- a/tests/domaincapsdata/qemu_7.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0.x86_64.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.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml index 4acd9b76b2..1fdb2e214a 100644 --- a/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.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.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml index c8efc8f183..657d2e0efd 100644 --- a/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml @@ -25,6 +25,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 cfa00f3150..1ea0380a2d 100644 --- a/tests/domaincapsdata/qemu_8.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0.x86_64.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.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml index 83a703da52..d9e8c5bc66 100644 --- a/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.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-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml index 725002966d..6e0c2d1e39 100644 --- a/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml @@ -25,6 +25,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 0872931dd7..a65b42e451 100644 --- a/tests/domaincapsdata/qemu_8.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_8.1.0.s390x.xml @@ -22,6 +22,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 6a3cb84342..4f3b15846b 100644 --- a/tests/domaincapsdata/qemu_8.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0.x86_64.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-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml index a25cf01799..6faf0db84c 100644 --- a/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.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-tcg-virt.loongarch64.xml b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml index eead5ff076..e90ab2ccb6 100644 --- a/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml @@ -24,6 +24,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 3b986eb386..9553942985 100644 --- a/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml @@ -25,6 +25,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 bb563d6e6c..48148a352e 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml @@ -24,6 +24,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 4d441289a4..4c99753d5e 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml @@ -24,6 +24,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 bb563d6e6c..48148a352e 100644 --- a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml @@ -24,6 +24,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 5c467d4a14..75117a5ac7 100644 --- a/tests/domaincapsdata/qemu_8.2.0.armv7l.xml +++ b/tests/domaincapsdata/qemu_8.2.0.armv7l.xml @@ -21,6 +21,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 5126dd4d00..75148c1250 100644 --- a/tests/domaincapsdata/qemu_8.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_8.2.0.s390x.xml @@ -22,6 +22,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 57cd4d63de..3a35234cfe 100644 --- a/tests/domaincapsdata/qemu_8.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.x86_64.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-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml index c7932014ad..db49fcb31f 100644 --- a/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.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.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml index 3593d70166..13f2cd611a 100644 --- a/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml @@ -25,6 +25,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 6b4dd3c3b5..87e2118272 100644 --- a/tests/domaincapsdata/qemu_9.0.0.sparc.xml +++ b/tests/domaincapsdata/qemu_9.0.0.sparc.xml @@ -21,6 +21,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 96303a31cd..48f4ebb6b8 100644 --- a/tests/domaincapsdata/qemu_9.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0.x86_64.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.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml index 518a6811fe..f0802d16d3 100644 --- a/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.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-tcg-virt.riscv64.xml b/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml index ce7fe71141..f900c7bae7 100644 --- a/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml @@ -24,6 +24,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 70928471b3..e18447971b 100644 --- a/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml @@ -25,6 +25,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 fabb09bf72..f707650201 100644 --- a/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml @@ -23,6 +23,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 d4649de513..9c3f75494f 100644 --- a/tests/domaincapsdata/qemu_9.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_9.1.0.s390x.xml @@ -22,6 +22,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 ee101364cc..daeafa98ea 100644 --- a/tests/domaincapsdata/qemu_9.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0.x86_64.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.2.0-hvf.aarch64+hvf.xml b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml index ae657c7f72..eab6116cc4 100644 --- a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml +++ b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml @@ -24,6 +24,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 35dc5785bc..d18d72f96a 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 @@ -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-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml index baaaf4f91c..2cfec98f10 100644 --- a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.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-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml index 033004a1f4..9db9e93045 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 @@ -25,6 +25,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 f20fe882c6..97671f67ea 100644 --- a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml @@ -25,6 +25,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 21a1b4f5a9..997179b353 100644 --- a/tests/domaincapsdata/qemu_9.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_9.2.0.s390x.xml @@ -22,6 +22,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 39390d2ab6..6654a7340d 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.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.2.0.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0.x86_64.xml index c477a1d2c4..9e7bf20833 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64.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/qemufirmwaretest.c b/tests/qemufirmwaretest.c index 04d11efb8e..4dd04b22a0 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; @@ -156,6 +157,7 @@ testSupportedFW(const void *opaque) uint64_t actualInterfaces; uint64_t expectedInterfaces = 0; bool actualSecure; + bool actualVarstore; virFirmware **expFWs = NULL; size_t nexpFWs = 0; virFirmware **actFWs = NULL; @@ -182,7 +184,8 @@ testSupportedFW(const void *opaque) } if (qemuFirmwareGetSupported(data->machine, data->arch, false, - &actualInterfaces, &actualSecure, &actFWs, &nactFWs) < 0) { + &actualInterfaces, &actualSecure, + &actualVarstore, &actFWs, &nactFWs) < 0) { fprintf(stderr, "Unable to get list of supported interfaces\n"); goto cleanup; } @@ -203,6 +206,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; @@ -290,26 +301,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.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.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.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:" @@ -322,19 +333,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.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> --- 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 1d7b5b58b7..d308dba262 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1289,13 +1289,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> --- 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 d308dba262..45b2f03298 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; @@ -1167,7 +1174,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; } @@ -1280,6 +1287,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"); @@ -1378,16 +1388,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 b6cc7d4dfe..18dbb97332 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1647,8 +1647,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> --- 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 45b2f03298..efa7477a05 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1493,6 +1493,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; @@ -1553,8 +1554,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> --- 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 22c9975d9f..d852bc0c12 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -2341,6 +2341,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 cdd333c882..f3c2988751 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> --- 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 efa7477a05..0fb463a228 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: @@ -2064,10 +2096,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
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 DONOTMERGE: The firmware descriptors have not been added to the Fedora edk2 package yet. Signed-off-by: Andrea Bolognani <abologna@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 | 2 +- tests/domaincapsdata/qemu_10.0.0.aarch64.xml | 2 +- .../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 | 2 +- tests/domaincapsdata/qemu_10.2.0.aarch64.xml | 2 +- .../domaincapsdata/qemu_11.0.0-q35.x86_64.xml | 2 +- .../qemu_11.0.0-virt.aarch64.xml | 2 +- tests/domaincapsdata/qemu_11.0.0.aarch64.xml | 2 +- ...70-edk2-ovmf-qemuvars-x64-sb-enrolled.json | 30 ++++++++++++++++ .../70-edk2-qemuvars-aarch64-sb-enrolled.json | 28 +++++++++++++++ .../71-edk2-ovmf-qemuvars-x64-sb.json | 29 ++++++++++++++++ .../firmware/71-edk2-qemuvars-aarch64-sb.json | 27 +++++++++++++++ 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 +++--- 34 files changed, 302 insertions(+), 37 deletions(-) create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-ovmf-qemuvars-x64-sb-enrolled.json create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-qemuvars-aarch64-sb-enrolled.json create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-ovmf-qemuvars-x64-sb.json create mode 100644 tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-qemuvars-aarch64-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} (75%) 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 9a19d0aa0d..a01d7f5342 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 @@ -26,7 +26,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 70263ace5f..49b1845c6e 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml @@ -26,7 +26,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 8af13c9061..1f3d9e00de 100644 --- a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml @@ -24,7 +24,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 8af13c9061..1f3d9e00de 100644 --- a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml @@ -24,7 +24,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 7dbb4c22ef..8e8d0ecbb9 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 @@ -26,7 +26,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 76e62a1898..5cdbdf351e 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml @@ -26,7 +26,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 7ae632edfd..b860c60110 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 @@ -25,7 +25,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 a22283ae95..9835f9336b 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml @@ -26,7 +26,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 a813a63282..44903218c8 100644 --- a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml @@ -24,7 +24,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 a813a63282..44903218c8 100644 --- a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml @@ -24,7 +24,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 88b80ccbb7..1fe6c2a76f 100644 --- a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml @@ -26,7 +26,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 c37401a04d..70438e1477 100644 --- a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml @@ -24,7 +24,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 c37401a04d..70438e1477 100644 --- a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml @@ -24,7 +24,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-ovmf-qemuvars-x64-sb-enrolled.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-ovmf-qemuvars-x64-sb-enrolled.json new file mode 100644 index 0000000000..a173c3e63a --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-ovmf-qemuvars-x64-sb-enrolled.json @@ -0,0 +1,30 @@ +{ + "description": "OVMF for qemuvars, 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/OVMF_VARS.enrolled.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/70-edk2-qemuvars-aarch64-sb-enrolled.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-qemuvars-aarch64-sb-enrolled.json new file mode 100644 index 0000000000..b9dd623584 --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-qemuvars-aarch64-sb-enrolled.json @@ -0,0 +1,28 @@ +{ + "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-template.enrolled.json" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "enrolled-keys", + "secure-boot", + "host-uefi-vars" + ], + "tags": [ + ] +} diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-ovmf-qemuvars-x64-sb.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-ovmf-qemuvars-x64-sb.json new file mode 100644 index 0000000000..9972c34337 --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-ovmf-qemuvars-x64-sb.json @@ -0,0 +1,29 @@ +{ + "description": "OVMF for qemuvars, SB enabled, empty varstore", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "filename": "/usr/share/edk2/ovmf/OVMF.qemuvars.fd", + "uefi-vars": { + "template": "/usr/share/edk2/ovmf/OVMF_VARS.empty.json" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "secure-boot", + "host-uefi-vars", + "verbose-dynamic" + ], + "tags": [ + ] +} diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-qemuvars-aarch64-sb.json b/tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-qemuvars-aarch64-sb.json new file mode 100644 index 0000000000..58a81a1de6 --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/71-edk2-qemuvars-aarch64-sb.json @@ -0,0 +1,27 @@ +{ + "description": "UEFI firmware for ARM64 virtual machines, SB enabled, empty varstore", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "filename": "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd", + "uefi-vars": { + "template": "/usr/share/edk2/aarch64/vars-template.empty.json" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "secure-boot", + "host-uefi-vars" + ], + "tags": [ + ] +} diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c index 4dd04b22a0..6a33db5d40 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -101,6 +101,10 @@ 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/70-edk2-ovmf-qemuvars-x64-sb-enrolled.json", + PREFIX "/share/qemu/firmware/70-edk2-qemuvars-aarch64-sb-enrolled.json", + PREFIX "/share/qemu/firmware/71-edk2-ovmf-qemuvars-x64-sb.json", + PREFIX "/share/qemu/firmware/71-edk2-qemuvars-aarch64-sb.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", @@ -291,6 +295,10 @@ 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/70-edk2-ovmf-qemuvars-x64-sb-enrolled.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/70-edk2-qemuvars-aarch64-sb-enrolled.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/71-edk2-ovmf-qemuvars-x64-sb.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/71-edk2-qemuvars-aarch64-sb.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"); @@ -320,7 +328,7 @@ mymain(void) DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_I686, false, false, "/usr/share/seabios/bios.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.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:" @@ -330,7 +338,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/OVMF_VARS.enrolled.json:" + "/usr/share/edk2/ovmf/OVMF.qemuvars.fd:/usr/share/edk2/ovmf/OVMF_VARS.empty.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, @@ -339,11 +349,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-template.enrolled.json:" + "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd:/usr/share/edk2/aarch64/vars-template.empty.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..3fd52d75f3 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-template.enrolled.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..3fd52d75f3 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-template.enrolled.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..21bb42a3f7 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/OVMF_VARS.enrolled.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 75% 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..1d533fb1dd 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-template.enrolled.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..1cb556fe9b 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/OVMF_VARS.enrolled.json' path='/path/to/guest.json'/> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 18dbb97332..77f2005916 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1594,7 +1594,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 */ @@ -1631,8 +1631,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"); @@ -1647,8 +1647,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 069211e139..4aa63d0f5c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9825,6 +9825,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, @@ -10899,6 +10930,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
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> --- 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 c5b2a5fda8..997b1d383b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4919,45 +4919,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, @@ -4969,6 +4964,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 works. A few user-visible messages are updated to reflect the fact that they apply both to NVRAM and varstore. https://issues.redhat.com/browse/RHEL-82645 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_driver.c | 15 ++++++++++----- src/qemu/qemu_process.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f3c2988751..3bbc04945c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6648,22 +6648,27 @@ 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); + } + 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 997b1d383b..37866c33ea 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5030,6 +5030,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, @@ -7829,6 +7850,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 @@ -7838,8 +7860,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> --- 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
Best viewed with 'git show -w'. Signed-off-by: Andrea Bolognani <abologna@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 d0ed22db2d..a8d5c23f97 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 834383a7de..7b831e228d 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
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> --- 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 893359aaae..9e2bd5e3f8 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
Provide a new set of command line flags named after varstore, mirroring the ones that already exist for NVRAM. Users will not need to worry about whether the guest uses one or the other, since either version will seamlessly apply to both scenarios, meaning among other things that existing scripts will continue working as expected. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/manpages/virsh.rst | 44 ++++++++++++++++++++------------- tools/virsh-domain.c | 55 ++++++++++++++++++++++++++++++++--------- tools/virsh-snapshot.c | 9 +++++-- 3 files changed, 78 insertions(+), 30 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index a9d691824e..c6858a7af9 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1699,7 +1699,7 @@ create :: create FILE [--console] [--paused] [--autodestroy] - [--pass-fds N,M,...] [--validate] [--reset-nvram] + [--pass-fds N,M,...] [--validate] [--reset-nvram] [--reset-varstore] Create a domain from an XML <file>. Optionally, *--validate* option can be passed to validate the format of the input XML file against an internal RNG @@ -1722,8 +1722,9 @@ 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* or *--reset-varstore* is specified, any existing +NVRAM/varstore file will be deleted and re-initialized from its pristine +template. **Example:** @@ -4255,7 +4256,8 @@ restore :: restore state-file [--bypass-cache] [--xml file] - [{--running | --paused}] [--reset-nvram] [--parallel-channels] + [{--running | --paused}] [--reset-nvram] [--reset-varstore] + [--parallel-channels] Restores a domain from a ``virsh save`` state file. See *save* for more info. @@ -4274,8 +4276,9 @@ 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* or *--reset-varstore* 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 @@ -4899,7 +4902,7 @@ start start domain-name-or-uuid [--console] [--paused] [--autodestroy] [--bypass-cache] [--force-boot] - [--pass-fds N,M,...] [--reset-nvram] + [--pass-fds N,M,...] [--reset-nvram] [--reset-varstore] Start a (previously defined) inactive domain, either from the last ``managedsave`` state, or via a fresh boot if no managedsave state is @@ -4918,8 +4921,9 @@ 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* or *--reset-varstore* is specified, any existing +NVRAM/varstore file will be deleted and re-initialized from its pristine +template. suspend @@ -4955,8 +4959,9 @@ undefine :: - undefine domain [--managed-save] [--snapshots-metadata] - [--checkpoints-metadata] [--nvram] [--keep-nvram] + undefine domain [--managed-save] + [--snapshots-metadata] [--checkpoints-metadata] + [--nvram] [--keep-nvram] [--varstore] [--keep-varstore] [ {--storage volumes | --remove-all-storage [--delete-storage-volume-snapshots]} --wipe-storage] [--tpm] [--keep-tpm] @@ -4981,9 +4986,13 @@ 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* / *--varstore* and *--keep-nvram* / *--keep-varstore* flags +specify whether to delete or keep the NVRAM (/domain/os/nvram/) or +varstore (/domain/os/varstore) file respectively. The two sets of names are +provided for convenience and consistency, but they're effectively aliases: +that is, *--nvram* will work on a domain configured to use varstore and +vice versa. 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 @@ -8121,7 +8130,7 @@ snapshot-revert :: snapshot-revert domain {snapshot | --current} [{--running | --paused}] - [--force] [--reset-nvram] + [--force] [--reset-nvram] [--reset-varstore] Revert the given domain to the snapshot specified by *snapshot*, or to the current snapshot with *--current*. Be aware @@ -8167,8 +8176,9 @@ 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* or *--reset-varstore* 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 cb9dd069b6..8f06238875 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -3981,11 +3981,19 @@ 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 = "varstore", + .type = VSH_OT_BOOL, + .help = N_("remove NVRAM/varstore file") + }, + {.name = "keep-varstore", + .type = VSH_OT_BOOL, + .help = N_("keep NVRAM/varstore file") }, {.name = "tpm", .type = VSH_OT_BOOL, @@ -4020,10 +4028,10 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) bool wipe_storage = vshCommandOptBool(cmd, "wipe-storage"); bool remove_all_storage = vshCommandOptBool(cmd, "remove-all-storage"); bool delete_snapshots = vshCommandOptBool(cmd, "delete-storage-volume-snapshots"); - bool nvram = vshCommandOptBool(cmd, "nvram"); - bool keep_nvram = vshCommandOptBool(cmd, "keep-nvram"); bool tpm = vshCommandOptBool(cmd, "tpm"); bool keep_tpm = vshCommandOptBool(cmd, "keep-tpm"); + bool nvram = false; + bool keep_nvram = false; /* Positive if these items exist. */ int has_managed_save = 0; int has_snapshots_metadata = 0; @@ -4048,8 +4056,18 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) virshControl *priv = ctl->privData; VSH_REQUIRE_OPTION("delete-storage-volume-snapshots", "remove-all-storage"); - VSH_EXCLUSIVE_OPTIONS("nvram", "keep-nvram"); VSH_EXCLUSIVE_OPTIONS("tpm", "keep-tpm"); + VSH_EXCLUSIVE_OPTIONS("nvram", "keep-nvram"); + VSH_EXCLUSIVE_OPTIONS("varstore", "keep-varstore"); + VSH_EXCLUSIVE_OPTIONS("nvram", "keep-varstore"); + VSH_EXCLUSIVE_OPTIONS("varstore", "keep-nvram"); + + if (vshCommandOptBool(cmd, "nvram") || + vshCommandOptBool(cmd, "varstore")) + nvram = true; + if (vshCommandOptBool(cmd, "keep-nvram") || + vshCommandOptBool(cmd, "keep-varstore")) + keep_nvram = true; ignore_value(vshCommandOptStringQuiet(ctl, cmd, "storage", &vol_string)); @@ -4401,7 +4419,11 @@ 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 = "reset-varstore", + .type = VSH_OT_BOOL, + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; @@ -4461,7 +4483,8 @@ cmdStart(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_START_BYPASS_CACHE; if (vshCommandOptBool(cmd, "force-boot")) flags |= VIR_DOMAIN_START_FORCE_BOOT; - if (vshCommandOptBool(cmd, "reset-nvram")) + if (vshCommandOptBool(cmd, "reset-nvram") || + vshCommandOptBool(cmd, "reset-varstore")) flags |= VIR_DOMAIN_START_RESET_NVRAM; /* We can emulate force boot, even for older servers that reject it. */ @@ -5728,7 +5751,11 @@ 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 = "reset-varstore", + .type = VSH_OT_BOOL, + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; @@ -5753,7 +5780,8 @@ cmdRestore(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_SAVE_RUNNING; if (vshCommandOptBool(cmd, "paused")) flags |= VIR_DOMAIN_SAVE_PAUSED; - if (vshCommandOptBool(cmd, "reset-nvram")) + if (vshCommandOptBool(cmd, "reset-nvram") || + vshCommandOptBool(cmd, "reset-varstore")) flags |= VIR_DOMAIN_SAVE_RESET_NVRAM; if (vshCommandOptString(ctl, cmd, "file", &from) < 0) @@ -8520,7 +8548,11 @@ 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 = "reset-varstore", + .type = VSH_OT_BOOL, + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; @@ -8575,7 +8607,8 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_START_AUTODESTROY; if (vshCommandOptBool(cmd, "validate")) flags |= VIR_DOMAIN_START_VALIDATE; - if (vshCommandOptBool(cmd, "reset-nvram")) + if (vshCommandOptBool(cmd, "reset-nvram") || + vshCommandOptBool(cmd, "reset-varstore")) flags |= VIR_DOMAIN_START_RESET_NVRAM; dom = virshDomainCreateXMLHelper(priv->conn, buffer, nfds, fds, flags); diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index 8e5b9d635c..3d5880b1d5 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -1714,7 +1714,11 @@ 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 = "reset-varstore", + .type = VSH_OT_BOOL, + .help = N_("re-initialize NVRAM/varstore from its pristine template") }, {.name = NULL} }; @@ -1733,7 +1737,8 @@ cmdDomainSnapshotRevert(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING; if (vshCommandOptBool(cmd, "paused")) flags |= VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED; - if (vshCommandOptBool(cmd, "reset-nvram")) + if (vshCommandOptBool(cmd, "reset-nvram") || + vshCommandOptBool(cmd, "reset-varstore")) flags |= VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM; /* We want virsh snapshot-revert --force to work even when talking * to older servers that did the unsafe revert by default but -- 2.53.0
In addition to documenting the new element, rework the documentation to encourage the use of firmware autoselection and discourage configuring the firmware manually; moreover, rename the "BIOS bootloader" section to the far more accurate "guest firmware". Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatcaps.rst | 2 +- docs/formatdomain.rst | 47 ++++++++++++++++------- docs/formatdomaincaps.rst | 81 +++++++++++++++++++++++---------------- docs/kbase/secureboot.rst | 46 ++++++++++++++-------- 4 files changed, 114 insertions(+), 62 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 87644ad42a..ccd284b8c6 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 is here 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. :: @@ -192,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 @@ -307,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 @@ -411,10 +432,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. @@ -3699,7 +3720,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 @@ -4864,7 +4885,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 @@ -5088,7 +5109,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 @@ -6344,7 +6365,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 8b4f0ecff3..1d6b80dff7 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 is here 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. :: @@ -126,41 +131,53 @@ be passed to its children. <value>no</value> </enum> </loader> + <varstore supported='yes'/> </os> ... <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 ``<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. -For the ``loader`` element, the following can occur: +The ``<loader/>`` element contains the following information: ``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. + + This information is exposed primarily for backwards compatibility reasons. + It is recommended to ignore it and use firmware autoselection instead. ``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 only 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. CPU configuration ~~~~~~~~~~~~~~~~~ diff --git a/docs/kbase/secureboot.rst b/docs/kbase/secureboot.rst index 6c22b08d22..0c8143bfba 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-template.enrolled.json' path='/var/lib/libvirt/qemu/nvram/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 -- 2.53.0
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- NEWS.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 54f541cdbc..2bbdc52c03 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -17,6 +17,22 @@ v12.1.0 (unreleased) * **New features** + * qemu: Add support for uefi-vars device and firmware builds using it + + This is particularly noteworthy for people running aarch64 VMs, as it makes + it finally possible to use Secure Boot on the architecture. + + 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
participants (1)
-
Andrea Bolognani