[PATCH v3 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 is one patch that is marked as DONOTMERGE: that's because it imports into the tree firmware descriptor that are not yet part of the Fedora edk2 package. Changes from [v2]: * changes to the schema for JSON firmware descriptors have been queued for merge in QEMU, so the corresponding patch is no longer marked as DONOTMERGE; * improve documentation; * rebase on top of master, addressing conflicts that I have caused with some recent changes related to this work. Changes from [v1]: * rewrite based on review feedback: the <nvram> element is no longer used, and a dedicated <varstore> element is introduced instead; * additional test coverage, as well as fixes and improvements related to firmware selection and its documentation, are present as well. [v2] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/WVWT3... [v1] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/TGLFM... Andrea Bolognani (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 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 | 85 +++++--- 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 | 29 ++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 34 ++++ src/qemu/qemu_conf.c | 4 + src/qemu/qemu_conf.h | 1 + src/qemu/qemu_driver.c | 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 | 3 + tests/domaincapsdata/qemu_10.0.0.aarch64.xml | 3 + tests/domaincapsdata/qemu_10.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_10.0.0.s390x.xml | 1 + .../qemu_10.0.0.x86_64+amdsev.xml | 1 + tests/domaincapsdata/qemu_10.0.0.x86_64.xml | 1 + .../qemu_10.1.0-q35.x86_64+inteltdx.xml | 1 + .../domaincapsdata/qemu_10.1.0-q35.x86_64.xml | 1 + .../qemu_10.1.0-tcg.x86_64+inteltdx.xml | 1 + .../domaincapsdata/qemu_10.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_10.1.0.s390x.xml | 1 + .../qemu_10.1.0.x86_64+inteltdx.xml | 1 + tests/domaincapsdata/qemu_10.1.0.x86_64.xml | 1 + .../qemu_10.2.0-q35.x86_64+mshv.xml | 1 + .../domaincapsdata/qemu_10.2.0-q35.x86_64.xml | 1 + .../qemu_10.2.0-tcg.x86_64+mshv.xml | 1 + .../domaincapsdata/qemu_10.2.0-tcg.x86_64.xml | 1 + .../qemu_10.2.0-virt.aarch64.xml | 3 + tests/domaincapsdata/qemu_10.2.0.aarch64.xml | 3 + .../qemu_10.2.0.x86_64+mshv.xml | 1 + tests/domaincapsdata/qemu_10.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_11.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_11.0.0-tcg.x86_64.xml | 1 + .../qemu_11.0.0-virt.aarch64.xml | 3 + tests/domaincapsdata/qemu_11.0.0.aarch64.xml | 3 + tests/domaincapsdata/qemu_11.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 1 + .../qemu_7.2.0-hvf.x86_64+hvf.xml | 1 + .../domaincapsdata/qemu_7.2.0-q35.x86_64.xml | 1 + .../qemu_7.2.0-tcg.x86_64+hvf.xml | 1 + .../domaincapsdata/qemu_7.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.2.0.ppc.xml | 1 + tests/domaincapsdata/qemu_7.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_8.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_8.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_8.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_8.1.0.s390x.xml | 1 + tests/domaincapsdata/qemu_8.1.0.x86_64.xml | 1 + .../domaincapsdata/qemu_8.2.0-q35.x86_64.xml | 1 + .../qemu_8.2.0-tcg-virt.loongarch64.xml | 1 + .../domaincapsdata/qemu_8.2.0-tcg.x86_64.xml | 1 + .../qemu_8.2.0-virt.aarch64.xml | 3 + .../qemu_8.2.0-virt.loongarch64.xml | 1 + tests/domaincapsdata/qemu_8.2.0.aarch64.xml | 3 + tests/domaincapsdata/qemu_8.2.0.armv7l.xml | 1 + tests/domaincapsdata/qemu_8.2.0.s390x.xml | 1 + tests/domaincapsdata/qemu_8.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_9.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_9.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_9.0.0.sparc.xml | 1 + tests/domaincapsdata/qemu_9.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_9.1.0-q35.x86_64.xml | 1 + .../qemu_9.1.0-tcg-virt.riscv64.xml | 1 + .../domaincapsdata/qemu_9.1.0-tcg.x86_64.xml | 1 + .../qemu_9.1.0-virt.riscv64.xml | 1 + tests/domaincapsdata/qemu_9.1.0.s390x.xml | 1 + tests/domaincapsdata/qemu_9.1.0.x86_64.xml | 1 + .../qemu_9.2.0-hvf.aarch64+hvf.xml | 3 + .../qemu_9.2.0-q35.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_9.2.0-q35.x86_64.xml | 1 + .../qemu_9.2.0-tcg.x86_64+amdsev.xml | 1 + .../domaincapsdata/qemu_9.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_9.2.0.s390x.xml | 1 + .../qemu_9.2.0.x86_64+amdsev.xml | 1 + tests/domaincapsdata/qemu_9.2.0.x86_64.xml | 1 + .../caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + .../caps_10.0.0_x86_64.xml | 1 + .../caps_10.1.0_s390x.xml | 1 + .../caps_10.1.0_x86_64+inteltdx.xml | 1 + .../caps_10.1.0_x86_64.xml | 1 + .../caps_10.2.0_aarch64.xml | 1 + .../caps_10.2.0_x86_64+mshv.xml | 1 + .../caps_10.2.0_x86_64.xml | 1 + .../caps_11.0.0_aarch64.xml | 1 + .../caps_11.0.0_x86_64.xml | 1 + .../etc/qemu/firmware/20-bios.json | 1 - .../etc/qemu/firmware/20-libvirt-bios.json | 1 + .../etc/qemu/firmware/59-combined.json | 1 - .../qemu/firmware/59-libvirt-combined.json | 1 + ...{92-masked.json => 92-libvirt-masked.json} | 0 .../{10-bios.json => 10-libvirt-bios.json} | 0 ...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, 1314 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 436b06c388..519828f6f9 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1662,8 +1662,10 @@ qemuFirmwareFillDomainCustom(virDomainDef *def) if (!loader) return; - if (!loader->format) + if (loader->path && + !loader->format) { loader->format = VIR_STORAGE_FILE_RAW; + } if (loader->nvramTemplate && !loader->nvramTemplateFormat) { -- 2.53.0
Right now we set this default in the common parsing code, which is not a big problem per se but would get in the way of some upcoming changes. Leave this choice to individual drivers instead. Only the QEMU and Xen drivers use the value for anything, so we can limit the amount of code duplication this change causes. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/domain_postparse.c | 19 ------------------- src/libxl/libxl_domain.c | 6 ++++++ src/qemu/qemu_firmware.c | 5 +++++ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c index 38e731348d..cbaae75c02 100644 --- a/src/conf/domain_postparse.c +++ b/src/conf/domain_postparse.c @@ -89,22 +89,6 @@ virDomainDefPostParseMemory(virDomainDef *def, } -static int -virDomainDefPostParseOs(virDomainDef *def) -{ - if (!def->os.loader) - return 0; - - if (def->os.loader->path && - def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_NONE) { - /* By default, loader is type of 'rom' */ - def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; - } - - return 0; -} - - static void virDomainDefPostParseMemtune(virDomainDef *def) { @@ -1251,9 +1235,6 @@ virDomainDefPostParseCommon(virDomainDef *def, if (virDomainDefPostParseMemory(def, data->parseFlags) < 0) return -1; - if (virDomainDefPostParseOs(def) < 0) - return -1; - virDomainDefPostParseMemtune(def); if (virDomainDefRejectDuplicateControllers(def) < 0) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 9842d6fece..c6717e31cf 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -279,6 +279,12 @@ libxlDomainDefPostParse(virDomainDef *def, def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON; } + if (def->os.loader && + def->os.loader->path && + !def->os.loader->type) { + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; + } + /* add implicit balloon device */ if (def->memballoon == NULL) { virDomainMemballoonDef *memballoon; diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 519828f6f9..6a074055ca 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1662,6 +1662,11 @@ qemuFirmwareFillDomainCustom(virDomainDef *def) if (!loader) return; + if (loader->path && + !loader->type) { + loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; + } + if (loader->path && !loader->format) { loader->format = VIR_STORAGE_FILE_RAW; -- 2.53.0
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 6a074055ca..9f7c981c25 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 2eb9d8e701..e09f50592b 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -84,7 +84,7 @@ testFWPrecedence(const void *opaque G_GNUC_UNUSED) g_autofree char *fakehome = NULL; g_auto(GStrv) fwList = NULL; const char *expected[] = { - SYSCONFDIR "/qemu/firmware/20-bios.json", + SYSCONFDIR "/qemu/firmware/20-libvirt-bios.json", PREFIX "/share/qemu/firmware/30-edk2-ovmf-4m-qcow2-x64-sb-enrolled.json", PREFIX "/share/qemu/firmware/31-edk2-ovmf-2m-raw-x64-sb-enrolled.json", PREFIX "/share/qemu/firmware/40-edk2-ovmf-4m-qcow2-x64-sb.json", @@ -98,12 +98,12 @@ testFWPrecedence(const void *opaque G_GNUC_UNUSED) PREFIX "/share/qemu/firmware/51-edk2-ovmf-2m-raw-x64-nosb.json", PREFIX "/share/qemu/firmware/52-edk2-aarch64-verbose-qcow2.json", PREFIX "/share/qemu/firmware/53-edk2-aarch64-verbose-raw.json", - SYSCONFDIR "/qemu/firmware/59-combined.json", + SYSCONFDIR "/qemu/firmware/59-libvirt-combined.json", PREFIX "/share/qemu/firmware/60-edk2-ovmf-x64-amdsev.json", PREFIX "/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json", - PREFIX "/share/qemu/firmware/90-combined.json", - PREFIX "/share/qemu/firmware/91-bios.json", - PREFIX "/share/qemu/firmware/93-invalid.json", + PREFIX "/share/qemu/firmware/90-libvirt-combined.json", + PREFIX "/share/qemu/firmware/91-libvirt-bios.json", + PREFIX "/share/qemu/firmware/93-libvirt-invalid.json", NULL }; const char **e; @@ -285,9 +285,9 @@ mymain(void) DO_PARSE_TEST("usr/share/qemu/firmware/53-edk2-aarch64-verbose-raw.json"); DO_PARSE_TEST("usr/share/qemu/firmware/60-edk2-ovmf-x64-amdsev.json"); DO_PARSE_TEST("usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json"); - DO_PARSE_TEST("usr/share/qemu/firmware/90-combined.json"); - DO_PARSE_TEST("usr/share/qemu/firmware/91-bios.json"); - DO_PARSE_FAILURE_TEST("usr/share/qemu/firmware/93-invalid.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/90-libvirt-combined.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/91-libvirt-bios.json"); + DO_PARSE_FAILURE_TEST("usr/share/qemu/firmware/93-libvirt-invalid.json"); if (virTestRun("QEMU FW precedence test", testFWPrecedence, NULL) < 0) ret = -1; -- 2.53.0
This 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 e09f50592b..922d32b74d 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -306,16 +306,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:" @@ -328,7 +328,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 dafbdc63e7..e793bc5b1e 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 453e301041..1384e9f3ab 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3960,6 +3960,27 @@ virDomainLoaderDefFree(virDomainLoaderDef *loader) g_free(loader); } +virDomainVarstoreDef * +virDomainVarstoreDefNew(void) +{ + virDomainVarstoreDef *def = NULL; + + def = g_new0(virDomainVarstoreDef, 1); + + return def; +} + +void +virDomainVarstoreDefFree(virDomainVarstoreDef *varstore) +{ + if (!varstore) + return; + + g_free(varstore->path); + g_free(varstore->template); + g_free(varstore); +} + static void virDomainResctrlMonDefFree(virDomainResctrlMonDef *domresmon) @@ -4062,6 +4083,7 @@ virDomainOSDefClear(virDomainOSDef *os) virDomainOSACPITableDefFree(os->acpiTables[i]); g_free(os->acpiTables); virDomainLoaderDefFree(os->loader); + virDomainVarstoreDefFree(os->varstore); g_free(os->bootloader); g_free(os->bootloaderArgs); } @@ -18088,6 +18110,17 @@ virDomainLoaderDefParseXMLLoader(virDomainLoaderDef *loader, } +static int +virDomainVarstoreDefParseXML(virDomainVarstoreDef *varstore, + xmlNodePtr varstoreNode) +{ + varstore->path = virXMLPropString(varstoreNode, "path"); + varstore->template = virXMLPropString(varstoreNode, "template"); + + return 0; +} + + static int virDomainLoaderDefParseXML(virDomainLoaderDef *loader, xmlNodePtr loaderNode, @@ -18535,16 +18568,29 @@ virDomainDefParseBootLoaderOptions(virDomainDef *def, xmlNodePtr loaderNode = virXPathNode("./os/loader[1]", ctxt); xmlNodePtr nvramNode = virXPathNode("./os/nvram[1]", ctxt); xmlNodePtr nvramSourceNode = virXPathNode("./os/nvram/source[1]", ctxt); + xmlNodePtr varstoreNode = virXPathNode("./os/varstore[1]", ctxt); - if (!loaderNode && !nvramNode) - return 0; + if (nvramNode && varstoreNode) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Cannot have both <nvram> and <varstore>")); + return -1; + } - def->os.loader = virDomainLoaderDefNew(); + if (loaderNode || nvramNode) { + def->os.loader = virDomainLoaderDefNew(); - if (virDomainLoaderDefParseXML(def->os.loader, - loaderNode, nvramNode, nvramSourceNode, - ctxt, xmlopt, flags) < 0) - return -1; + if (virDomainLoaderDefParseXML(def->os.loader, + loaderNode, nvramNode, nvramSourceNode, + ctxt, xmlopt, flags) < 0) + return -1; + } + + if (varstoreNode) { + def->os.varstore = virDomainVarstoreDefNew(); + + if (virDomainVarstoreDefParseXML(def->os.varstore, varstoreNode) < 0) + return -1; + } return 0; } @@ -28248,6 +28294,20 @@ virDomainLoaderDefFormat(virBuffer *buf, return 0; } +static int +virDomainVarstoreDefFormat(virBuffer *buf, + virDomainVarstoreDef *varstore) +{ + g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + + virBufferEscapeString(&attrBuf, " template='%s'", varstore->template); + virBufferEscapeString(&attrBuf, " path='%s'", varstore->path); + + virXMLFormatElementEmpty(buf, "varstore", &attrBuf, NULL); + + return 0; +} + static void virDomainKeyWrapDefFormat(virBuffer *buf, virDomainKeyWrapDef *keywrap) { @@ -29720,6 +29780,11 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, if (def->os.loader && virDomainLoaderDefFormat(buf, def->os.loader, xmlopt, flags) < 0) return -1; + + if (def->os.varstore && + virDomainVarstoreDefFormat(buf, def->os.varstore) < 0) + return -1; + virBufferEscapeString(buf, "<kernel>%s</kernel>\n", def->os.kernel); virBufferEscapeString(buf, "<initrd>%s</initrd>\n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a13f6d79e9..e63230beec 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2423,6 +2423,14 @@ struct _virDomainLoaderDef { virDomainLoaderDef *virDomainLoaderDefNew(void); void virDomainLoaderDefFree(virDomainLoaderDef *loader); +struct _virDomainVarstoreDef { + char *path; + char *template; +}; + +virDomainVarstoreDef *virDomainVarstoreDefNew(void); +void virDomainVarstoreDefFree(virDomainVarstoreDef *varstore); + typedef enum { VIR_DOMAIN_IOAPIC_NONE = 0, VIR_DOMAIN_IOAPIC_QEMU, @@ -2576,6 +2584,7 @@ struct _virDomainOSDef { size_t nacpiTables; virDomainOSACPITableDef **acpiTables; virDomainLoaderDef *loader; + virDomainVarstoreDef *varstore; char *bootloader; char *bootloaderArgs; int smbios_mode; diff --git a/src/conf/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 d8ae4f46cd..9853ece557 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -719,6 +719,8 @@ virDomainTPMProfileRemoveDisabledTypeToString; virDomainTPMVersionTypeFromString; virDomainTPMVersionTypeToString; virDomainUSBDeviceDefForeach; +virDomainVarstoreDefFree; +virDomainVarstoreDefNew; virDomainVideoDefaultRAM; virDomainVideoDefClear; virDomainVideoDefFree; -- 2.53.0
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 d2ab4a71b5..18c2ac5701 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1581,7 +1581,10 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-manual-bios"); DO_TEST_CAPS_LATEST("firmware-manual-bios-stateless"); - DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-not-stateless"); + /* This combination doesn't make sense (BIOS is stateless by definition) + * but unfortunately there's no way for libvirt to report an error in this + * scenario. The stateless=no attribute will effectively be ignored */ + DO_TEST_CAPS_LATEST("firmware-manual-bios-not-stateless"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-rw"); DO_TEST_CAPS_LATEST("firmware-manual-efi"); DO_TEST_CAPS_LATEST("firmware-manual-efi-features"); @@ -1634,7 +1637,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-bios"); DO_TEST_CAPS_LATEST("firmware-auto-bios-stateless"); DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-bios-rw"); - DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-bios-not-stateless"); + DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-bios-not-stateless"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-bios-nvram"); DO_TEST_CAPS_LATEST("firmware-auto-efi"); DO_TEST_CAPS_LATEST_ABI_UPDATE("firmware-auto-efi"); -- 2.53.0
This capability indicates the availability of the uefi-vars device. The actual name of the QEMU device varies slightly depending on the architecture: it's uefi-vars-x64 on x86_64, uefi-vars-sysbus on other UEFI architectures (aarch64, riscv64, loongarch64). Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_capabilities.c | 3 +++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml | 1 + tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml | 1 + 13 files changed, 15 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 9af58c912a..048ef66c12 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -761,6 +761,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 490 */ "scsi-block.migrate-pr", /* QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR */ "iommufd", /* QEMU_CAPS_OBJECT_IOMMUFD */ + "uefi-vars", /* QEMU_CAPS_DEVICE_UEFI_VARS */ ); @@ -1469,6 +1470,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH }, { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, { "iommufd", QEMU_CAPS_OBJECT_IOMMUFD }, + { "uefi-vars-x64", QEMU_CAPS_DEVICE_UEFI_VARS }, + { "uefi-vars-sysbus", QEMU_CAPS_DEVICE_UEFI_VARS }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 8d5c5cc94c..a48e1d0367 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -735,6 +735,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 490 */ QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, /* persistent reservation migration support */ QEMU_CAPS_OBJECT_IOMMUFD, /* -object iommufd */ + QEMU_CAPS_DEVICE_UEFI_VARS, /* -device uefi-vars-{x64,sysbus} */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml index e5f55f461a..b6434e6019 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -165,6 +165,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10000000</version> <microcodeVersion>61700285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml index 74a68c8402..43f848db25 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -211,6 +211,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml index d593dd1ab8..138c34fd47 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -211,6 +211,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml index 3e271824c6..f33b366db8 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml @@ -142,6 +142,7 @@ <flag name='qom-list-get'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10001000</version> <microcodeVersion>39100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml index 512186a341..2a7cd9cac1 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml @@ -194,6 +194,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10001000</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml index d6f1009c77..71311fceaf 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml @@ -216,6 +216,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10001000</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml index 54d10e1433..ac8f50b984 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml @@ -184,6 +184,7 @@ <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002000</version> <microcodeVersion>61700287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml index 38f6a0f6c3..d7a556b4a6 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml @@ -204,6 +204,7 @@ <flag name='mshv'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002000</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml index 1ed21b9bf7..699dad3e20 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml @@ -217,6 +217,7 @@ <flag name='query-accelerators'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002000</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml index 4e6edf8df9..233f325224 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml @@ -185,6 +185,7 @@ <flag name='virtio-iommu.aw-bits'/> <flag name='scsi-block.migrate-pr'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002050</version> <microcodeVersion>61700286</microcodeVersion> <package>v10.2.0-1114-gb3abdfa486</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml index 22eaff6545..85d2790b49 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml @@ -218,6 +218,7 @@ <flag name='virtio-iommu.aw-bits'/> <flag name='scsi-block.migrate-pr'/> <flag name='iommufd'/> + <flag name='uefi-vars'/> <version>10002050</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.2.0-1114-gb3abdfa486</package> -- 2.53.0
The use of varstore requires the uefi-vars device to be present in the QEMU binary. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_validate.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 16dd5fef1a..0eb5d5ea3b 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -753,6 +753,23 @@ qemuValidateDomainDefNvram(const virDomainDef *def, } +static int +qemuValidateDomainDefVarstore(const virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + if (!def->os.varstore) + return 0; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_UEFI_VARS)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("The uefi-vars device is not supported by this QEMU binary")); + return -1; + } + + return 0; +} + + static int qemuValidateDomainDefBoot(const virDomainDef *def, virQEMUCaps *qemuCaps) @@ -796,6 +813,9 @@ qemuValidateDomainDefBoot(const virDomainDef *def, if (qemuValidateDomainDefNvram(def, qemuCaps) < 0) return -1; + + if (qemuValidateDomainDefVarstore(def, qemuCaps) < 0) + return -1; } for (i = 0; i < def->os.nacpiTables; i++) { -- 2.53.0
This test case demonstrates how to manually configure an x86_64 guest to use the uefi-vars device. It fails when using an older version of QEMU which didn't have the device, and succeeds when using the latest version. The relevant bits of the QEMU command line are not generated yet, but that will come in a later commit. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...e-manual-efi-varstore-q35.x86_64-8.2.0.err | 1 + ...manual-efi-varstore-q35.x86_64-latest.args | 34 ++++++++++++++++++ ...-manual-efi-varstore-q35.x86_64-latest.xml | 36 +++++++++++++++++++ .../firmware-manual-efi-varstore-q35.xml | 19 ++++++++++ tests/qemuxmlconftest.c | 3 ++ 5 files changed, 93 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err new file mode 100644 index 0000000000..e64c2b21aa --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-8.2.0.err @@ -0,0 +1 @@ +unsupported configuration: The uefi-vars device is not supported by this QEMU binary diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args new file mode 100644 index 0000000000..9a899c2a65 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args @@ -0,0 +1,34 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine pc-q35-8.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ +-accel kvm \ +-cpu qemu64 \ +-bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-global ICH9-LPC.noreboot=off \ +-watchdog-action reset \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml new file mode 100644 index 0000000000..296c6e8f59 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.xml @@ -0,0 +1,36 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <loader type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <varstore path='/path/to/guest.json'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pcie-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <watchdog model='itco' action='reset'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml new file mode 100644 index 0000000000..c1dc00fde8 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.xml @@ -0,0 +1,19 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <varstore path='/path/to/guest.json'/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 18c2ac5701..d75540042e 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1618,6 +1618,9 @@ mymain(void) ARG_CAPS_VARIANT, "+inteltdx", ARG_END); + DO_TEST_CAPS_LATEST("firmware-manual-efi-varstore-q35"); + DO_TEST_CAPS_VER_PARSE_ERROR("firmware-manual-efi-varstore-q35", "8.2.0"); + /* Make sure all combinations of ACPI and UEFI behave as expected */ DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-acpi-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-manual-efi-acpi-q35"); -- 2.53.0
This test case demonstrates how to manually configure an aarch64 guest to use the uefi-vars device. It currently fails because the QEMU driver does not yet recognize the firmware type as EFI, and so rejects the attempt to use ACPI together with it. That will change in a future commit. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...ual-efi-varstore-aarch64.aarch64-8.2.0.err | 1 + ...al-efi-varstore-aarch64.aarch64-latest.err | 1 + .../firmware-manual-efi-varstore-aarch64.xml | 19 +++++++++++++++++++ tests/qemuxmlconftest.c | 2 ++ 4 files changed, 23 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err new file mode 100644 index 0000000000..4fe79bdacf --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-8.2.0.err @@ -0,0 +1 @@ +unsupported configuration: ACPI requires UEFI on this architecture diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err new file mode 100644 index 0000000000..4fe79bdacf --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.err @@ -0,0 +1 @@ +unsupported configuration: ACPI requires UEFI on this architecture diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml new file mode 100644 index 0000000000..5c545fe0ab --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.xml @@ -0,0 +1,19 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <loader type='rom'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <varstore path='/path/to/guest.json'/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index d75540042e..615a30fd38 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1620,6 +1620,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-manual-efi-varstore-q35"); DO_TEST_CAPS_VER_PARSE_ERROR("firmware-manual-efi-varstore-q35", "8.2.0"); + DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64", "8.2.0"); /* Make sure all combinations of ACPI and UEFI behave as expected */ DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-acpi-aarch64", "aarch64"); -- 2.53.0
This test case demonstrates how to explicitly opt into using the uefi-vars device for an x86_64 guest. Normally the firmware autoselection process will pick a UEFI build that is loaded via pflash, but by including the <varstore> element in the input XML we can tell the QEMU driver that we want want the uefi-vars device to be used instead. Currently this results in an error, because the firmware autoselection algorithm doesn't yet know how to properly handle the scenario. A future commit will address this and make things work as expected. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...are-auto-efi-varstore-q35.x86_64-latest.err | 1 + .../firmware-auto-efi-varstore-q35.xml | 18 ++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 3 files changed, 20 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err new file mode 100644 index 0000000000..b45d304221 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err @@ -0,0 +1 @@ +Only one of NVRAM/varstore can be used diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml new file mode 100644 index 0000000000..9cda95403e --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.xml @@ -0,0 +1,18 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <varstore/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 615a30fd38..9e330e2935 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1671,6 +1671,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-file"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); + DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-q35"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
This test case demonstrates how to explicitly opt into using the uefi-vars device for an aarch64 guest. Normally the firmware autoselection process will pick a UEFI build that is loaded via pflash, but by including the <varstore> element in the input XML we can tell the QEMU driver that we want want the uefi-vars device to be used instead. Currently this results in an error, because the firmware autoselection algorithm doesn't yet know how to properly handle the scenario. A future commit will address this and make things work as expected. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...uto-efi-varstore-aarch64.aarch64-latest.err | 1 + .../firmware-auto-efi-varstore-aarch64.xml | 18 ++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 3 files changed, 20 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err new file mode 100644 index 0000000000..b45d304221 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err @@ -0,0 +1 @@ +Only one of NVRAM/varstore can be used diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml new file mode 100644 index 0000000000..e403c60643 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.xml @@ -0,0 +1,18 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <varstore/> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 9e330e2935..24168b98af 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1672,6 +1672,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-q35"); + DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
This test case demonstrates how to automatically configure an aarch64 guest so that Secure Boot support is available and only signed operating systems are allowed to boot. It currently fails because there is no firmware descriptor that describes a suitable firmware build yet. That will change in a future commit. In addition to the latest version, the test case is also executed against QEMU 8.2.0 specifically. This version of the test case is intended to fail, because the uefi-vars device that we need to support Secure Boot on aarch64 was not yet available in that version of QEMU. The exact error message will change down the line. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...fi-enrolled-keys-aarch64.aarch64-8.2.0.err | 1 + ...fi-enrolled-keys-aarch64.aarch64-8.2.0.xml | 30 +++++++++++++++++++ ...i-enrolled-keys-aarch64.aarch64-latest.err | 1 + ...i-enrolled-keys-aarch64.aarch64-latest.xml | 30 +++++++++++++++++++ ...irmware-auto-efi-enrolled-keys-aarch64.xml | 20 +++++++++++++ tests/qemuxmlconftest.c | 2 ++ 6 files changed, 84 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err new file mode 100644 index 0000000000..3edb2b3451 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err @@ -0,0 +1 @@ +operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml new file mode 100644 index 0000000000..5213a41b90 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml @@ -0,0 +1,30 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + </firmware> + <loader format='raw'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <gic version='3'/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err new file mode 100644 index 0000000000..3edb2b3451 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.err @@ -0,0 +1 @@ +operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml new file mode 100644 index 0000000000..908a8435f9 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml @@ -0,0 +1,30 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + </firmware> + <loader format='raw'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <gic version='2'/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml new file mode 100644 index 0000000000..6cd382d0fa --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml @@ -0,0 +1,20 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os firmware='efi'> + <type arch='aarch64' machine='virt-8.2'>hvm</type> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + </firmware> + </os> + <features> + <acpi/> + </features> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 24168b98af..ca00dc96f0 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1657,6 +1657,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-enrolled-keys"); + DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_VER_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64", "8.2.0"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-enrolled-keys"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-enrolled-keys-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-smm-off"); -- 2.53.0
When present in a firmware descriptor, this feature indicates that the corresponding executable expects to access variable storage through the uefi-vars QEMU device. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- 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 9f7c981c25..04e81355df 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: @@ -2085,6 +2090,7 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_FEATURE_AMD_SEV_ES: case QEMU_FIRMWARE_FEATURE_AMD_SEV_SNP: case QEMU_FIRMWARE_FEATURE_INTEL_TDX: + case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_LAST: -- 2.53.0
The two checks are semantically different, so it makes sense to perform them separately. We will soon extend the first one. While at it, start printing out the value of isConfidential. We could print the value of each firmware feature it's derived from, but that would make things unnecessarily verbose; at the same time, knowing that libvirt believes that the firmware build is targeting the confidential use case can be useful for debugging so it's worth including it. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- 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 04e81355df..c78e8e7833 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 c78e8e7833..4b2155f311 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. 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 4b2155f311..f64ea287b4 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 f64ea287b4..56f03bc907 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2162,6 +2162,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 3b24caeca6..4682abbf41 100644 --- a/src/conf/schemas/domaincaps.rng +++ b/src/conf/schemas/domaincaps.rng @@ -87,6 +87,12 @@ </element> </define> + <define name="varstore"> + <element name="varstore"> + <ref name="supported"/> + </element> + </define> + <define name="os"> <element name="os"> <interleave> @@ -98,6 +104,9 @@ <optional> <ref name="loader"/> </optional> + <optional> + <ref name="varstore"/> + </optional> </interleave> </element> </define> -- 2.53.0
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 9b3577cd08..78b8e6e6e1 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -449,12 +449,21 @@ virDomainCapsLoaderFormat(virBuffer *buf, FORMAT_EPILOGUE(loader); } +static void +virDomainCapsVarstoreFormat(virBuffer *buf, + const virDomainCapsVarstore *varstore) +{ + FORMAT_PROLOGUE(varstore); + FORMAT_EPILOGUE(varstore); +} + static void virDomainCapsOSFormat(virBuffer *buf, const virDomainCapsOS *os) { const virDomainCapsFirmwareFeatures *firmwareFeatures = &os->firmwareFeatures; const virDomainCapsLoader *loader = &os->loader; + const virDomainCapsVarstore *varstore = &os->varstore; FORMAT_PROLOGUE(os); @@ -462,6 +471,7 @@ virDomainCapsOSFormat(virBuffer *buf, virDomainCapsFirmwareFeaturesFormat(&childBuf, firmwareFeatures); virDomainCapsLoaderFormat(&childBuf, loader); + virDomainCapsVarstoreFormat(&childBuf, varstore); FORMAT_EPILOGUE(os); } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index a68fafe235..02344fd9b6 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -61,6 +61,11 @@ struct _virDomainCapsLoader { virDomainCapsEnum secure; /* Info about secure:virTristateBool */ }; +typedef struct _virDomainCapsVarstore virDomainCapsVarstore; +struct _virDomainCapsVarstore { + virTristateBool supported; +}; + STATIC_ASSERT_ENUM(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST); typedef struct _virDomainCapsOS virDomainCapsOS; struct _virDomainCapsOS { @@ -68,6 +73,7 @@ struct _virDomainCapsOS { virDomainCapsEnum firmware; /* Info about virDomainOsDefFirmware */ virDomainCapsFirmwareFeatures firmwareFeatures; virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ + virDomainCapsVarstore varstore; }; STATIC_ASSERT_ENUM(VIR_DOMAIN_MEMORY_SOURCE_LAST); -- 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 048ef66c12..5d75c23072 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6518,8 +6518,26 @@ virQEMUCapsFillDomainLoaderCaps(virDomainCapsLoader *capsLoader, } +static int +virQEMUCapsFillDomainVarstoreCaps(virDomainCapsVarstore *capsVarstore, + bool varstore, + virQEMUCaps *qemuCaps) +{ + /* varstore is advertised as supported only if firmware + * descriptors that use it exist and the QEMU binary has the + * necessary device compiled in */ + if (varstore && virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_UEFI_VARS)) + capsVarstore->supported = VIR_TRISTATE_BOOL_YES; + else + capsVarstore->supported = VIR_TRISTATE_BOOL_NO; + + return 0; +} + + static int virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, + virQEMUCaps *qemuCaps, const char *machine, virArch arch, bool privileged, @@ -6528,10 +6546,12 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, { virDomainCapsFirmwareFeatures *firmwareFeatures = &os->firmwareFeatures; virDomainCapsLoader *capsLoader = &os->loader; + virDomainCapsVarstore *capsVarstore = &os->varstore; uint64_t autoFirmwares = 0; uint64_t featureSecureBoot = 0; uint64_t featureEnrolledKeys = 0; bool secure = false; + bool varstore = false; virFirmware **firmwaresAlt = NULL; size_t nfirmwaresAlt = 0; int ret = -1; @@ -6541,7 +6561,7 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, if (qemuFirmwareGetSupported(machine, arch, privileged, &autoFirmwares, &featureSecureBoot, &featureEnrolledKeys, - &secure, + &secure, &varstore, &firmwaresAlt, &nfirmwaresAlt) < 0) return -1; @@ -6568,6 +6588,9 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, firmwaresAlt ? nfirmwaresAlt : nfirmwares) < 0) goto cleanup; + if (virQEMUCapsFillDomainVarstoreCaps(capsVarstore, varstore, qemuCaps) < 0) + goto cleanup; + ret = 0; cleanup: virFirmwareFreeList(firmwaresAlt, nfirmwaresAlt); @@ -7289,6 +7312,7 @@ virQEMUCapsFillDomainCaps(virQEMUDriverConfig *cfg, } if (virQEMUCapsFillDomainOSCaps(os, + qemuCaps, domCaps->machine, domCaps->arch, privileged, diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 56f03bc907..1ecbee0c96 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2034,6 +2034,7 @@ qemuFirmwareFillDomain(virQEMUDriver *driver, * @featureSecureBoot: bitmap of virTristateBool values for secure-boot feature * @featureEnrolledKeys: bitmap of virTristateBool values for enrolled-keys feature * @secure: true if at least one secure boot enabled FW was found + * @varstore: true if at least one FW using varstore was found * @fws: (optional) list of found firmwares * @nfws: (optional) number of members in @fws * @@ -2065,6 +2066,7 @@ qemuFirmwareGetSupported(const char *machine, uint64_t *featureSecureBoot, uint64_t *featureEnrolledKeys, bool *secure, + bool *varstore, virFirmware ***fws, size_t *nfws) { @@ -2076,6 +2078,7 @@ qemuFirmwareGetSupported(const char *machine, *featureSecureBoot = VIR_TRISTATE_BOOL_ABSENT; *featureEnrolledKeys = VIR_TRISTATE_BOOL_ABSENT; *secure = false; + *varstore = false; if (fws) { *fws = NULL; @@ -2163,6 +2166,9 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_DEVICE_MEMORY: fwpath = memory->filename; nvrampath = memory->template; + + if (memory->template) + *varstore = true; break; case QEMU_FIRMWARE_DEVICE_NONE: diff --git a/src/qemu/qemu_firmware.h b/src/qemu/qemu_firmware.h index 6789ec83f7..bcd3801da8 100644 --- a/src/qemu/qemu_firmware.h +++ b/src/qemu/qemu_firmware.h @@ -55,6 +55,7 @@ qemuFirmwareGetSupported(const char *machine, uint64_t *featureSecureBoot, uint64_t *featureEnrolledKeys, bool *secure, + bool *varstore, virFirmware ***fws, size_t *nfws); diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml index b68767d7b3..1fff8c7fc7 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml index 70da32ccf1..6c26e5b422 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml index 6d2723f950..fb031b916e 100644 --- a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml index cbddffef6b..8a5348d2a8 100644 --- a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml index bacd5665ad..97064ea009 100644 --- a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml index bacd5665ad..97064ea009 100644 --- a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.ppc64.xml b/tests/domaincapsdata/qemu_10.0.0.ppc64.xml index a913d20b3e..8082fb9556 100644 --- a/tests/domaincapsdata/qemu_10.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.s390x.xml b/tests/domaincapsdata/qemu_10.0.0.s390x.xml index 22a4bee3fd..ca741192ba 100644 --- a/tests/domaincapsdata/qemu_10.0.0.s390x.xml +++ b/tests/domaincapsdata/qemu_10.0.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml index 7227638020..6a4ea003f7 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0.x86_64.xml index 38edf287f4..f12dd845ba 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml index 1bca29f971..3537dd01f6 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml index c48ba4e218..e55d7d8ba6 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml index e75c2e2234..4afecf627f 100644 --- a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml index 50087d531f..b3c7bc60b5 100644 --- a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.1.0.s390x.xml b/tests/domaincapsdata/qemu_10.1.0.s390x.xml index 1b4ff5c35d..976943491e 100644 --- a/tests/domaincapsdata/qemu_10.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_10.1.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml index 5e2b2b47c6..7d33362f0e 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0.x86_64.xml index 8f7bff70f3..9cb65712a4 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml index 313e7c24a4..43fe2bff93 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml @@ -35,6 +35,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml index 4955ad7ac5..2c1b38b4ec 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml index cc3427cef7..771ef3a0f6 100644 --- a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64+mshv.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml index 4c90f1d7be..f0e08907ff 100644 --- a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml index 808cf0226e..fa1d3c490b 100644 --- a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml index 808cf0226e..fa1d3c490b 100644 --- a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml index 84be18497b..87c35d229c 100644 --- a/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0.x86_64+mshv.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0.x86_64.xml index 013317b4f2..a838126991 100644 --- a/tests/domaincapsdata/qemu_10.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml index cd4e05cdca..109f3ae0ae 100644 --- a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml index 3d4d62ca95..0bfe92db7d 100644 --- a/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml index 6c10d43386..db47c5ee98 100644 --- a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml index 6c10d43386..db47c5ee98 100644 --- a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0.x86_64.xml index f44fc12f90..29e15817c8 100644 --- a/tests/domaincapsdata/qemu_11.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index 4465574814..96dcc32019 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index ba9ad68ad2..a92050ad5b 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml index 9f3e6a7f3f..958d20e74c 100644 --- a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml index d804bd64ce..eb347adce9 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml index 40170cea50..0c3d00865e 100644 --- a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml index 6f424760a8..6b5dff857b 100644 --- a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml index 604aa5e0ad..d6a6e75bec 100644 --- a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml index a67e929551..c568ae3d80 100644 --- a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml index 71c48d74dc..5e13f1f7fb 100644 --- a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml index 682137ec8d..f9114422bd 100644 --- a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml index 399eeb3b18..0b3518a5a8 100644 --- a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml index 966abb1b0a..f574894ad0 100644 --- a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml b/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml index c8d889287c..1fdde871f8 100644 --- a/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml +++ b/tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml index 995ad7f220..b4c4153953 100644 --- a/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml index 1bbd737021..989c3e274c 100644 --- a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml +++ b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml index 1bbd737021..989c3e274c 100644 --- a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_7.2.0.ppc.xml b/tests/domaincapsdata/qemu_7.2.0.ppc.xml index 223387444c..b4bdf3b651 100644 --- a/tests/domaincapsdata/qemu_7.2.0.ppc.xml +++ b/tests/domaincapsdata/qemu_7.2.0.ppc.xml @@ -25,6 +25,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.2.0.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0.x86_64.xml index be0ee62910..6efa244ffa 100644 --- a/tests/domaincapsdata/qemu_7.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml index f225cf0a8e..70a3b9c7d7 100644 --- a/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml index e770746f74..0010cfa60e 100644 --- a/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.0.0.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0.x86_64.xml index 4c8a36eeb0..ac8c8980e7 100644 --- a/tests/domaincapsdata/qemu_8.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml index 5d08abbe3b..e9d807828a 100644 --- a/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml index ea506799bf..e834e3eb82 100644 --- a/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.1.0.s390x.xml b/tests/domaincapsdata/qemu_8.1.0.s390x.xml index 4237262f31..37417ec648 100644 --- a/tests/domaincapsdata/qemu_8.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_8.1.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.1.0.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0.x86_64.xml index bab985379c..5de8bc1cd8 100644 --- a/tests/domaincapsdata/qemu_8.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml index c5c08d8fd1..a2f9591382 100644 --- a/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml index 6228916208..1625ddf4e0 100644 --- a/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml index da3121b8de..ac1c1b840e 100644 --- a/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml index c1dceda12d..420fbedd72 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml index 8206dc0486..af75894ff1 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml index c1dceda12d..420fbedd72 100644 --- a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.armv7l.xml b/tests/domaincapsdata/qemu_8.2.0.armv7l.xml index b64779c84a..a1ad0529e5 100644 --- a/tests/domaincapsdata/qemu_8.2.0.armv7l.xml +++ b/tests/domaincapsdata/qemu_8.2.0.armv7l.xml @@ -25,6 +25,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.s390x.xml b/tests/domaincapsdata/qemu_8.2.0.s390x.xml index 9f92c3c192..84be7cd967 100644 --- a/tests/domaincapsdata/qemu_8.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_8.2.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0.x86_64.xml index 83ea8565d8..e423689076 100644 --- a/tests/domaincapsdata/qemu_8.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml index a4521f150e..2851138ffe 100644 --- a/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml index 00d3e1b8d1..253bed40ed 100644 --- a/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.0.0.sparc.xml b/tests/domaincapsdata/qemu_9.0.0.sparc.xml index 7eb384d512..f999c8ed71 100644 --- a/tests/domaincapsdata/qemu_9.0.0.sparc.xml +++ b/tests/domaincapsdata/qemu_9.0.0.sparc.xml @@ -25,6 +25,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.0.0.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0.x86_64.xml index d61070b968..2316859d5b 100644 --- a/tests/domaincapsdata/qemu_9.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml index 226aad41b2..1cf269504c 100644 --- a/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml b/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml index c32d4380aa..85dffd3455 100644 --- a/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml index d18c62d268..76b2707b9c 100644 --- a/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml b/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml index 7a013e77c4..c052b8329b 100644 --- a/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml @@ -31,6 +31,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0.s390x.xml b/tests/domaincapsdata/qemu_9.1.0.s390x.xml index e26cab26f3..bc62fdfaa4 100644 --- a/tests/domaincapsdata/qemu_9.1.0.s390x.xml +++ b/tests/domaincapsdata/qemu_9.1.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.1.0.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0.x86_64.xml index a27712673a..baaa17f68d 100644 --- a/tests/domaincapsdata/qemu_9.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml index 06bb829a2a..f998177636 100644 --- a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml +++ b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml @@ -32,6 +32,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml index aac1d4d923..a21c69e416 100644 --- a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml index ef6ee01d00..df0d995276 100644 --- a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml @@ -36,6 +36,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml index 0ec1a9900d..2b860a23ca 100644 --- a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml index c8a0da3d22..24113a3514 100644 --- a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='no'/> diff --git a/tests/domaincapsdata/qemu_9.2.0.s390x.xml b/tests/domaincapsdata/qemu_9.2.0.s390x.xml index e00d7efd99..bba9ce7558 100644 --- a/tests/domaincapsdata/qemu_9.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_9.2.0.s390x.xml @@ -26,6 +26,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml index d6e3f8dc12..f12c89f40b 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_9.2.0.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0.x86_64.xml index 89e081a0e1..529415bcb4 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64.xml @@ -33,6 +33,7 @@ <value>no</value> </enum> </loader> + <varstore supported='no'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c index 922d32b74d..e434121834 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -143,6 +143,7 @@ struct supportedData { const char *machine; virArch arch; bool secure; + bool varstore; const char *fwlist; unsigned int *interfaces; size_t ninterfaces; @@ -158,6 +159,7 @@ testSupportedFW(const void *opaque) uint64_t actualFeatureSecureBoot; uint64_t actualFeatureEnrolledKeys; bool actualSecure; + bool actualVarstore; virFirmware **expFWs = NULL; size_t nexpFWs = 0; virFirmware **actFWs = NULL; @@ -187,7 +189,8 @@ testSupportedFW(const void *opaque) &actualInterfaces, &actualFeatureSecureBoot, &actualFeatureEnrolledKeys, - &actualSecure, &actFWs, &nactFWs) < 0) { + &actualSecure, &actualVarstore, + &actFWs, &nactFWs) < 0) { fprintf(stderr, "Unable to get list of supported interfaces\n"); goto cleanup; } @@ -208,6 +211,14 @@ testSupportedFW(const void *opaque) goto cleanup; } + if (actualVarstore != data->varstore) { + fprintf(stderr, + "Mismatch in varstore support. " + "Expected %d got %d\n", + data->varstore, actualVarstore); + goto cleanup; + } + for (i = 0; i < nactFWs; i++) { virFirmware *actFW = actFWs[i]; virFirmware *expFW = NULL; @@ -295,26 +306,26 @@ mymain(void) /* The @fwlist contains pairs of ${FW}:${NVRAM}. If there's * no NVRAM expected pass literal "NULL" and test fixes that * later. */ -#define DO_SUPPORTED_TEST(machine, arch, secure, fwlist, ...) \ +#define DO_SUPPORTED_TEST(machine, arch, secure, varstore, fwlist, ...) \ do { \ unsigned int interfaces[] = {__VA_ARGS__}; \ - struct supportedData data = {machine, arch, secure, fwlist, \ + struct supportedData data = {machine, arch, secure, varstore, fwlist, \ interfaces, G_N_ELEMENTS(interfaces)}; \ if (virTestRun("QEMU FW SUPPORTED " machine " " #arch, \ testSupportedFW, &data) < 0) \ ret = -1; \ } while (0) - DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_X86_64, false, + DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_X86_64, false, false, "/usr/share/seabios/bios.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:" @@ -327,19 +338,19 @@ mymain(void) "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); - DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false, + DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false, false, "/usr/share/seabios/bios.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 1ecbee0c96..d1eba31103 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 d1eba31103..094dd023f9 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 ca00dc96f0..43e994fc93 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1673,8 +1673,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-file"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); - DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-q35"); - DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-varstore-q35"); + DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
If the matching firmware requires the use of varstore, we have to bubble up information about it, namely the path to the template. If the struct member doesn't exist yet, we need to allocate it. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- 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 094dd023f9..24f12c0cf1 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 0ba7bf4197..00316a03f2 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -2349,6 +2349,7 @@ exit 0 %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ram/ %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/save/ %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/snapshot/ +%dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/varstore/ %dir %attr(0750, root, root) %{_localstatedir}/cache/libvirt/qemu/ %{_datadir}/augeas/lenses/libvirtd_qemu.aug %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug diff --git a/src/qemu/meson.build b/src/qemu/meson.build index ff9a904277..b4fb62f14f 100644 --- a/src/qemu/meson.build +++ b/src/qemu/meson.build @@ -223,6 +223,7 @@ if conf.has('WITH_QEMU') localstatedir / 'lib' / 'libvirt' / 'qemu' / 'ram', localstatedir / 'lib' / 'libvirt' / 'qemu' / 'save', localstatedir / 'lib' / 'libvirt' / 'qemu' / 'snapshot', + localstatedir / 'lib' / 'libvirt' / 'qemu' / 'varstore', localstatedir / 'lib' / 'libvirt' / 'swtpm', localstatedir / 'log' / 'libvirt' / 'qemu', localstatedir / 'log' / 'swtpm' / 'libvirt' / 'qemu', diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index de6e51177a..3ea42da502 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -167,6 +167,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir); cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir); cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir); + cfg->varstoreDir = g_strdup_printf("%s/varstore", cfg->libDir); cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir); } else if (privileged) { cfg->logDir = g_strdup_printf("%s/log/libvirt/qemu", LOCALSTATEDIR); @@ -188,6 +189,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir); cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir); cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir); + cfg->varstoreDir = g_strdup_printf("%s/varstore", cfg->libDir); cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir); cfg->swtpmStorageDir = g_strdup_printf("%s/lib/libvirt/swtpm", LOCALSTATEDIR); @@ -215,6 +217,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->configBaseDir); cfg->autoDumpPath = g_strdup_printf("%s/qemu/dump", cfg->configBaseDir); cfg->nvramDir = g_strdup_printf("%s/qemu/nvram", cfg->configBaseDir); + cfg->varstoreDir = g_strdup_printf("%s/qemu/varstore", cfg->configBaseDir); cfg->memoryBackingDir = g_strdup_printf("%s/qemu/ram", cfg->configBaseDir); cfg->swtpmStorageDir = g_strdup_printf("%s/qemu/swtpm", cfg->configBaseDir); @@ -367,6 +370,7 @@ static void virQEMUDriverConfigDispose(void *obj) g_free(cfg->checkpointDir); g_free(cfg->channelTargetDir); g_free(cfg->nvramDir); + g_free(cfg->varstoreDir); g_free(cfg->defaultTLSx509certdir); g_free(cfg->defaultTLSx509secretUUID); diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index c284e108a1..aa2bac6891 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -121,6 +121,7 @@ struct _virQEMUDriverConfig { char *checkpointDir; char *channelTargetDir; char *nvramDir; + char *varstoreDir; char *swtpmStorageDir; char *defaultTLSx509certdir; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7f08fd05e9..9620f737ba 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 24f12c0cf1..3b48ba575e 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. --- .../qemu_10.0.0-q35.x86_64+amdsev.xml | 2 +- .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml | 2 +- .../qemu_10.0.0-virt.aarch64.xml | 4 ++- tests/domaincapsdata/qemu_10.0.0.aarch64.xml | 4 ++- .../qemu_10.1.0-q35.x86_64+inteltdx.xml | 2 +- .../domaincapsdata/qemu_10.1.0-q35.x86_64.xml | 2 +- .../qemu_10.2.0-q35.x86_64+mshv.xml | 2 +- .../domaincapsdata/qemu_10.2.0-q35.x86_64.xml | 2 +- .../qemu_10.2.0-virt.aarch64.xml | 4 ++- tests/domaincapsdata/qemu_10.2.0.aarch64.xml | 4 ++- .../domaincapsdata/qemu_11.0.0-q35.x86_64.xml | 2 +- .../qemu_11.0.0-virt.aarch64.xml | 4 ++- tests/domaincapsdata/qemu_11.0.0.aarch64.xml | 4 ++- .../qemu_8.2.0-virt.aarch64.xml | 2 ++ tests/domaincapsdata/qemu_8.2.0.aarch64.xml | 2 ++ .../qemu_9.2.0-hvf.aarch64+hvf.xml | 2 ++ ...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 +++--- 37 files changed, 320 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 1fff8c7fc7..bf6393dc03 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml index 6c26e5b422..d6f710e56e 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml index 97064ea009..334aa5e31f 100644 --- a/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml index 97064ea009..334aa5e31f 100644 --- a/tests/domaincapsdata/qemu_10.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml index 3537dd01f6..6c370de5dd 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml index e55d7d8ba6..60cc9eee3d 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml index 43fe2bff93..e30b64e068 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64+mshv.xml @@ -35,7 +35,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml index 2c1b38b4ec..fde3055148 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml index fa1d3c490b..beb9a49ee3 100644 --- a/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml index fa1d3c490b..beb9a49ee3 100644 --- a/tests/domaincapsdata/qemu_10.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml index 109f3ae0ae..aa62aa1502 100644 --- a/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-q35.x86_64.xml @@ -36,7 +36,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml index db47c5ee98..4d41b6427d 100644 --- a/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml index db47c5ee98..4d41b6427d 100644 --- a/tests/domaincapsdata/qemu_11.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_11.0.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> @@ -32,7 +34,7 @@ <value>no</value> </enum> </loader> - <varstore supported='no'/> + <varstore supported='yes'/> </os> <cpu> <mode name='host-passthrough' supported='yes'> diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml index 420fbedd72..83fc9e37a7 100644 --- a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> diff --git a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml index 420fbedd72..83fc9e37a7 100644 --- a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> diff --git a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml index f998177636..65bb9dc9bd 100644 --- a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml +++ b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml @@ -11,9 +11,11 @@ </enum> <firmwareFeatures supported='yes'> <enum name='secureBoot'> + <value>yes</value> <value>no</value> </enum> <enum name='enrolledKeys'> + <value>yes</value> <value>no</value> </enum> </firmwareFeatures> diff --git a/tests/qemufirmwaredata/usr/share/qemu/firmware/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 e434121834..abe6e75120 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", @@ -296,6 +300,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"); @@ -325,7 +333,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:" @@ -335,7 +343,9 @@ mymain(void) "/usr/share/edk2/ovmf/OVMF_CODE.fd:/usr/share/edk2/ovmf/OVMF_VARS.fd:" "/usr/share/edk2/ovmf/OVMF.combined.fd:NULL:" "/usr/share/edk2/ovmf/OVMF.amdsev.fd:NULL:" - "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd:NULL", + "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd:NULL:" + "/usr/share/edk2/ovmf/OVMF.qemuvars.fd:/usr/share/edk2/ovmf/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, @@ -344,11 +354,13 @@ mymain(void) DO_SUPPORTED_TEST("microvm", VIR_ARCH_X86_64, false, false, "/usr/share/edk2/ovmf/MICROVM.fd:NULL", VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); - DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64, false, false, + DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64, false, true, "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2:/usr/share/edk2/aarch64/vars-template-pflash.qcow2:" "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw:" "/usr/share/edk2/aarch64/QEMU_EFI-pflash.qcow2:/usr/share/edk2/aarch64/vars-template-pflash.qcow2:" - "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw", + "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw:/usr/share/edk2/aarch64/vars-template-pflash.raw:" + "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd:/usr/share/edk2/aarch64/vars-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 43e994fc93..187f90c9dc 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1620,7 +1620,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-manual-efi-varstore-q35"); DO_TEST_CAPS_VER_PARSE_ERROR("firmware-manual-efi-varstore-q35", "8.2.0"); - DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("firmware-manual-efi-varstore-aarch64", "aarch64", "8.2.0"); /* Make sure all combinations of ACPI and UEFI behave as expected */ @@ -1657,8 +1657,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-enrolled-keys"); - DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64"); - DO_TEST_CAPS_ARCH_VER_FAILURE("firmware-auto-efi-enrolled-keys-aarch64", "aarch64", "8.2.0"); + DO_TEST_CAPS_ARCH_LATEST("firmware-auto-efi-enrolled-keys-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("firmware-auto-efi-enrolled-keys-aarch64", "aarch64", "8.2.0"); DO_TEST_CAPS_LATEST("firmware-auto-efi-no-enrolled-keys"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-enrolled-keys-no-secboot"); DO_TEST_CAPS_LATEST("firmware-auto-efi-smm-off"); @@ -1673,8 +1673,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-file"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd"); DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi"); - DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-varstore-q35"); - DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-varstore-aarch64", "aarch64"); + DO_TEST_CAPS_LATEST("firmware-auto-efi-varstore-q35"); + DO_TEST_CAPS_ARCH_LATEST("firmware-auto-efi-varstore-aarch64", "aarch64"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom"); -- 2.53.0
This makes guests actually functional. https://issues.redhat.com/browse/RHEL-82645 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_command.c | 34 +++++++++++++++++++ ...-enrolled-keys-aarch64.aarch64-latest.args | 1 + ...o-efi-varstore-aarch64.aarch64-latest.args | 1 + ...e-auto-efi-varstore-q35.x86_64-latest.args | 1 + ...l-efi-varstore-aarch64.aarch64-latest.args | 1 + ...manual-efi-varstore-q35.x86_64-latest.args | 1 + 6 files changed, 39 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index a742998e4c..ba300f3551 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9815,6 +9815,37 @@ qemuBuildDomainLoaderCommandLine(virCommand *cmd, } +static int +qemuBuildUefiVarsCommandLine(virCommand *cmd, + const virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + virDomainLoaderDef *loader = def->os.loader; + virDomainVarstoreDef *varstore = def->os.varstore; + g_autoptr(virJSONValue) props = NULL; + const char *model = NULL; + + if (!loader || !varstore || !varstore->path) + return 0; + + if (ARCH_IS_X86(def->os.arch)) + model = "uefi-vars-x64"; + else + model = "uefi-vars-sysbus"; + + if (virJSONValueObjectAdd(&props, + "s:driver", model, + "s:jsonfile", varstore->path, + NULL) < 0) + return -1; + + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) < 0) + return -1; + + return 0; +} + + static int qemuBuildTPMDevCmd(virCommand *cmd, const virDomainDef *def, @@ -10889,6 +10920,9 @@ qemuBuildCommandLine(virDomainObj *vm, qemuBuildDomainLoaderCommandLine(cmd, def); + if (qemuBuildUefiVarsCommandLine(cmd, def, qemuCaps) < 0) + return NULL; + if (qemuBuildMemCommandLine(cmd, def, qemuCaps, priv) < 0) return NULL; diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args index abc934692a..10f1a5a6a4 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args @@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ -accel kvm \ -bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-device '{"driver":"uefi-vars-sysbus","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args index abc934692a..10f1a5a6a4 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args @@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ -accel kvm \ -bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-device '{"driver":"uefi-vars-sysbus","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args index 9a899c2a65..392ea77c28 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args @@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -accel kvm \ -cpu qemu64 \ -bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \ +-device '{"driver":"uefi-vars-x64","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args index abc934692a..894bab7ffe 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args @@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -machine virt-8.2,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ -accel kvm \ -bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \ +-device '{"driver":"uefi-vars-sysbus","jsonfile":"/path/to/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args index 9a899c2a65..6c04c8c39f 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args @@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -accel kvm \ -cpu qemu64 \ -bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \ +-device '{"driver":"uefi-vars-x64","jsonfile":"/path/to/guest.json"}' \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ -overcommit mem-lock=off \ -- 2.53.0
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 371b64faac..db43b035c1 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4918,45 +4918,40 @@ qemuPrepareNVRAMBlock(virDomainLoaderDef *loader, static int -qemuPrepareNVRAMFile(virQEMUDriver *driver, - virDomainLoaderDef *loader, - bool reset_nvram) +qemuPrepareNVRAMFileCommon(virQEMUDriver *driver, + const char *path, + const char *template, + bool reset_nvram) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_AUTOCLOSE srcFD = -1; struct qemuPrepareNVRAMHelperData data; - if (virFileExists(loader->nvram->path) && !reset_nvram) + if (!path) return 0; - if (!loader->nvramTemplate) { + if (virFileExists(path) && !reset_nvram) + return 0; + + if (!template) { virReportError(VIR_ERR_OPERATION_FAILED, _("unable to find any master var store for loader: %1$s"), - loader->path); + path); return -1; } - /* If 'nvramTemplateFormat' is empty it means that it's a user-provided - * template which we couldn't verify. Assume the user knows what they're doing */ - if (loader->nvramTemplateFormat != VIR_STORAGE_FILE_NONE && - loader->nvram->format != loader->nvramTemplateFormat) { - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("conversion of the nvram template to another target format is not supported")); - return -1; - } - - if ((srcFD = virFileOpenAs(loader->nvramTemplate, O_RDONLY, + if ((srcFD = virFileOpenAs(template, O_RDONLY, 0, -1, -1, 0)) < 0) { virReportSystemError(-srcFD, _("Failed to open file '%1$s'"), - loader->nvramTemplate); + template); return -1; } data.srcFD = srcFD; - data.srcPath = loader->nvramTemplate; + data.srcPath = template; - if (virFileRewrite(loader->nvram->path, + if (virFileRewrite(path, S_IRUSR | S_IWUSR, cfg->user, cfg->group, qemuPrepareNVRAMHelper, @@ -4968,6 +4963,29 @@ qemuPrepareNVRAMFile(virQEMUDriver *driver, } +static int +qemuPrepareNVRAMFile(virQEMUDriver *driver, + virDomainLoaderDef *loader, + bool reset_nvram) +{ + /* If 'nvramTemplateFormat' is empty it means that it's a user-provided + * template which we couldn't verify. Assume the user knows what they're doing */ + if (loader && loader->nvram && + loader->nvramTemplateFormat != VIR_STORAGE_FILE_NONE && + loader->nvram->format != loader->nvramTemplateFormat) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("conversion of the nvram template to another target format is not supported")); + return -1; + } + + if (qemuPrepareNVRAMFileCommon(driver, loader->nvram->path, + loader->nvramTemplate, reset_nvram) < 0) + return -1; + + return 0; +} + + int qemuPrepareNVRAM(virQEMUDriver *driver, virDomainDef *def, -- 2.53.0
Simply mimicking what is currently done for NVRAM files 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 9620f737ba..c9e9e970e7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6646,22 +6646,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 db43b035c1..a82ee4b15e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5029,6 +5029,27 @@ qemuPrepareNVRAM(virQEMUDriver *driver, } +static int +qemuPrepareVarstore(virQEMUDriver *driver, + virDomainDef *def, + bool reset_nvram) +{ + virDomainLoaderDef *loader = def->os.loader; + virDomainVarstoreDef *varstore = def->os.varstore; + + if (!loader || !varstore) + return 0; + + VIR_DEBUG("varstore='%s'", NULLSTR(varstore->path)); + + if (qemuPrepareNVRAMFileCommon(driver, varstore->path, + varstore->template, reset_nvram) < 0) + return -1; + + return 0; +} + + static void qemuLogOperation(virDomainObj *vm, const char *msg, @@ -7799,6 +7820,7 @@ qemuProcessPrepareHost(virQEMUDriver *driver, unsigned int hostdev_flags = 0; qemuDomainObjPrivate *priv = vm->privateData; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + bool reset_nvram = !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM); /* * Create all per-domain directories in order to make sure domain @@ -7808,8 +7830,10 @@ qemuProcessPrepareHost(virQEMUDriver *driver, qemuProcessMakeDir(driver, vm, priv->channelTargetDir) < 0) return -1; - if (qemuPrepareNVRAM(driver, vm->def, - !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM)) < 0) + if (qemuPrepareNVRAM(driver, vm->def, reset_nvram) < 0) + return -1; + + if (qemuPrepareVarstore(driver, vm->def, reset_nvram) < 0) return -1; if (vm->def->vsock) { -- 2.53.0
Before this, attempting to use a ROM that was not explictly marked at read only resulted in an error at startup time. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- 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 704c8dbfec..390dfc7578 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -2061,11 +2061,17 @@ virSecurityDACRestoreAllLabel(virSecurityManager *mgr, rc = -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecurityDACRestoreImageLabelInt(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecurityDACRestoreImageLabelInt(mgr, sharedFilesystems, def, def->os.loader->nvram, migrated) < 0) rc = -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecurityDACRestoreFileLabel(mgr, def->os.varstore->path) < 0) + rc = -1; } if (def->os.kernel && @@ -2310,12 +2316,20 @@ virSecurityDACSetAllLabel(virSecurityManager *mgr, return -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecurityDACSetImageLabel(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecurityDACSetImageLabel(mgr, sharedFilesystems, def, def->os.loader->nvram, VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN | VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP) < 0) return -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecurityDACSetOwnership(mgr, NULL, + def->os.varstore->path, + user, group, true) < 0) + return -1; } if (def->os.kernel && diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 4a5f61d16b..9c498ab5f8 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2993,11 +2993,18 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManager *mgr, rc = -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecuritySELinuxRestoreImageLabelInt(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecuritySELinuxRestoreImageLabelInt(mgr, sharedFilesystems, def, def->os.loader->nvram, migrated) < 0) rc = -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecuritySELinuxRestoreFileLabel(mgr, def->os.varstore->path, + true, false) < 0) + rc = -1; } if (def->os.kernel && @@ -3341,6 +3348,22 @@ virSecuritySELinuxSetSysinfoLabel(virSecurityManager *mgr, } +static int +virSecuritySELinuxDomainSetPathLabel(virSecurityManager *mgr, + virDomainDef *def, + const char *path, + bool allowSubtree G_GNUC_UNUSED) +{ + virSecurityLabelDef *seclabel; + + seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); + if (!seclabel || !seclabel->relabel) + return 0; + + return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel, true); +} + + static int virSecuritySELinuxSetAllLabel(virSecurityManager *mgr, char *const *sharedFilesystems, @@ -3421,12 +3444,19 @@ virSecuritySELinuxSetAllLabel(virSecurityManager *mgr, return -1; } - if (def->os.loader && def->os.loader->nvram) { - if (virSecuritySELinuxSetImageLabel(mgr, sharedFilesystems, + if (def->os.loader) { + if (def->os.loader->nvram && + virSecuritySELinuxSetImageLabel(mgr, sharedFilesystems, def, def->os.loader->nvram, VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN | VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP) < 0) return -1; + + if (def->os.varstore && + def->os.varstore->path && + virSecuritySELinuxDomainSetPathLabel(mgr, def, + def->os.varstore->path, true) < 0) + return -1; } if (def->os.kernel && @@ -3593,21 +3623,6 @@ virSecuritySELinuxGetSecurityMountOptions(virSecurityManager *mgr, return opts; } -static int -virSecuritySELinuxDomainSetPathLabel(virSecurityManager *mgr, - virDomainDef *def, - const char *path, - bool allowSubtree G_GNUC_UNUSED) -{ - virSecurityLabelDef *seclabel; - - seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); - if (!seclabel || !seclabel->relabel) - return 0; - - return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel, true); -} - static int virSecuritySELinuxDomainSetPathLabelRO(virSecurityManager *mgr, virDomainDef *def, diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 3ac4740fb5..e932e79dab 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1019,27 +1019,35 @@ get_files(vahControl * ctl) return -1; } - if (ctl->def->os.loader && ctl->def->os.loader->path) { - bool readonly = false; - - /* Look at the readonly attribute, but also keep in mind that ROMs - * are always loaded read-only regardless of whether the attribute - * is present. Validation ensures that nonsensical configurations - * (type=rom readonly=no) are rejected long before we get here */ - virTristateBoolToBool(ctl->def->os.loader->readonly, &readonly); - if (ctl->def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) - readonly = true; - - if (vah_add_file(&buf, - ctl->def->os.loader->path, - readonly ? "rk" : "rwk") != 0) { + if (ctl->def->os.loader) { + if (ctl->def->os.loader->path) { + bool readonly = false; + + /* Look at the readonly attribute, but also keep in mind that ROMs + * are always loaded read-only regardless of whether the attribute + * is present. Validation ensures that nonsensical configurations + * (type=rom readonly=no) are rejected long before we get here */ + virTristateBoolToBool(ctl->def->os.loader->readonly, &readonly); + if (ctl->def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) + readonly = true; + + if (vah_add_file(&buf, + ctl->def->os.loader->path, + readonly ? "rk" : "rwk") != 0) { + return -1; + } + } + + if (ctl->def->os.loader->nvram && + storage_source_add_files(ctl->def->os.loader->nvram, &buf, 0) < 0) { return -1; } - } - if (ctl->def->os.loader && ctl->def->os.loader->nvram && - storage_source_add_files(ctl->def->os.loader->nvram, &buf, 0) < 0) { - return -1; + if (ctl->def->os.varstore && + ctl->def->os.varstore->path && + vah_add_file(&buf, ctl->def->os.varstore->path, "rw") != 0) { + return -1; + } } for (i = 0; i < ctl->def->ngraphics; i++) { -- 2.53.0
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 56c21dcf25..d82406fe05 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -371,7 +371,7 @@ typedef enum { VIR_DOMAIN_START_BYPASS_CACHE = 1 << 2, /* Avoid file system cache pollution (Since: 0.9.4) */ VIR_DOMAIN_START_FORCE_BOOT = 1 << 3, /* Boot, discarding any managed save (Since: 0.9.5) */ VIR_DOMAIN_START_VALIDATE = 1 << 4, /* Validate the XML document against schema (Since: 1.2.12) */ - VIR_DOMAIN_START_RESET_NVRAM = 1 << 5, /* Re-initialize NVRAM from template (Since: 8.1.0) */ + VIR_DOMAIN_START_RESET_NVRAM = 1 << 5, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */ } virDomainCreateFlags; @@ -1652,7 +1652,7 @@ typedef enum { VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution (Since: 0.9.4) */ VIR_DOMAIN_SAVE_RUNNING = 1 << 1, /* Favor running over paused (Since: 0.9.5) */ VIR_DOMAIN_SAVE_PAUSED = 1 << 2, /* Favor paused over running (Since: 0.9.5) */ - VIR_DOMAIN_SAVE_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM from template (Since: 8.1.0) */ + VIR_DOMAIN_SAVE_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */ } virDomainSaveRestoreFlags; int virDomainSave (virDomainPtr domain, -- 2.53.0
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 ff0cf1a715..7ce51d0e32 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:** @@ -4262,7 +4263,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. @@ -4281,8 +4283,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 @@ -4906,7 +4909,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 @@ -4925,8 +4928,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 @@ -4962,8 +4966,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] @@ -4988,9 +4993,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 @@ -8128,7 +8137,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 @@ -8174,8 +8183,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 | 85 ++++++++++++++++++++++++--------------- docs/kbase/secureboot.rst | 46 +++++++++++++-------- 4 files changed, 118 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 82788c15a2..7871613017 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -103,12 +103,16 @@ Operating system booting There are a number of different ways to boot virtual machines each with their own pros and cons. +Guest firmware +~~~~~~~~~~~~~~ -BIOS bootloader -~~~~~~~~~~~~~~~ +.. container:: + :name: bios-bootloader + + .. this container only exists to keep old links working -Booting via the BIOS is available for hypervisors supporting full -virtualization. In this case the BIOS has a boot order priority (floppy, +Booting via a guest firmware is available for hypervisors supporting full +virtualization. In this case the firmware has a boot order priority (floppy, harddisk, cdrom, network) determining where to obtain/find the boot image. :: @@ -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. @@ -3752,7 +3773,7 @@ paravirtualized driver is specified via the ``disk`` element. attribute is an 8 character string which can be queried by guests on S390 via sclp or diag 308. Linux guests on S390 can use ``loadparm`` to select a boot entry. :since:`Since 3.5.0` The per-device ``boot`` elements cannot be used - together with general boot elements in `BIOS bootloader`_ + together with general boot elements in `guest firmware`_ section. :since:`Since 0.8.8` ``encryption`` since:`Since 3.9.0` the ``encryption`` element is preferred @@ -4917,7 +4938,7 @@ or: Specifies that the device is bootable. The ``order`` attribute determines the order in which devices will be tried during boot sequence. The per-device ``boot`` elements cannot be used together with general boot elements in - `BIOS bootloader`_ section. :since:`Since 0.8.8` for PCI + `guest firmware`_ section. :since:`Since 0.8.8` for PCI devices, :since:`Since 1.0.1` for USB devices. ``rom`` The ``rom`` element is used to change how a PCI device's ROM is presented to @@ -5144,7 +5165,7 @@ USB device redirection through a character device is supported Specifies that the device is bootable. The ``order`` attribute determines the order in which devices will be tried during boot sequence. The per-device ``boot`` elements cannot be used together with general boot elements in - `BIOS bootloader`_ section. ( :since:`Since 1.0.1` ) + `guest firmware`_ section. ( :since:`Since 1.0.1` ) ``redirfilter`` The\ ``redirfilter``\ element is used for creating the filter rule to filter out certain devices from redirection. It uses sub-element ``<usbdev>`` to @@ -6400,7 +6421,7 @@ Specifying boot order For hypervisors which support this, you can set a specific NIC to be used for network boot. The ``order`` attribute determines the order in which devices will be tried during boot sequence. The per-device ``boot`` elements cannot be used -together with general boot elements in `BIOS bootloader`_ +together with general boot elements in `guest firmware`_ section. :since:`Since 0.8.8` Interface ROM BIOS configuration diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index cca827923c..5a1d3f2670 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -72,11 +72,11 @@ The root element that emulator capability XML document starts with has name Describes the `virtualization type <formatdomain.html#element-and-attribute-overview>`__ (or so called domain type). ``machine`` - The domain's `machine type <formatdomain.html#bios-bootloader>`__. Since not + The domain's `machine type <formatdomain.html#guest-firmware>`__. Since not every hypervisor has a sense of machine types this element might be omitted in such drivers. ``arch`` - The domain's `architecture <formatdomain.html#bios-bootloader>`__. + The domain's `architecture <formatdomain.html#guest-firmware>`__. CPU Allocation ~~~~~~~~~~~~~~ @@ -95,12 +95,17 @@ capabilities, e.g. virtual CPUs: ``vcpu`` The maximum number of supported virtual CPUs -BIOS bootloader -~~~~~~~~~~~~~~~ +Guest firmware +~~~~~~~~~~~~~~ + +.. container:: + :name: bios-bootloader + + .. this container only exists to keep old links working -Sometimes users might want to tweak some BIOS knobs or use UEFI. For cases like -that, `os <formatdomain.html#bios-bootloader>`__ element exposes what values can -be passed to its children. +Exposes information about supported +`guest firmware <formatdomain.html#guest-firmware>`__ configurations for +domains. :: @@ -136,19 +141,22 @@ 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 ``<firmwareFeatures/>`` element :since:`(since 12.1.0)` contains one enum for each of the features that can be used to fine-tune the firmware @@ -191,27 +199,40 @@ such as: would not work, since ``no`` is not one of the valid values advertised by the ``secureBoot`` enum. -For the ``loader`` element, the following can occur: +The information contained in the ``<loader/>`` element is not relevant when +using firmware autoselection, which is the recommended approach to guest +firmware configuration, and as such can largely be ignored. Its subelements +are the following: ``value`` - List of known firmware binary paths. Currently this is used only to advertise - the known location of OVMF binaries for QEMU. OVMF binaries will only be - listed if they actually exist on host. + One element for each known firmware binary present on the system. + + Note that a binary being present here indicates that the file exists and it + is compatible with the architecture/machine type, but does not provide any + insight into which mechanism (see ``type`` below) should be used to load it. ``type`` - Whether the boot loader is a typical BIOS (``rom``) or a UEFI firmware - (``pflash``). Each ``value`` sub-element under the ``type`` enum represents a - possible value for the ``type`` attribute for the <loader/> element in the - domain XML. E.g. the presence of ``pfalsh`` under the ``type`` enum means - that a domain XML can use UEFI firmware via: <loader/> type="pflash" - ...>/path/to/the/firmware/binary/</loader>. + Whether firmware can be loaded using a ``pflash`` device (UEFI only) or as + a ``rom`` (either UEFI or BIOS). ``readonly`` - Options for the ``readonly`` attribute of the <loader/> element in the domain - XML. + Supported values for the ``readonly`` attribute of the ``<loader/>`` element + in the domain XML. ``secure`` - Options for the ``secure`` attribute of the <loader/> element in the domain - XML. Note that the value ``yes`` is listed only if libvirt detects a firmware - descriptor file that has path to an OVMF binary that supports Secure boot, - and lists its architecture and supported machine type. + Supported values for the ``secure`` attribute of the ``<loader/>`` element + in the domain XML. + + Note that the value ``yes`` is listed if libvirt detects a firmware + descriptor file that points to a firmware binary that implements Secure + Boot and is compatible with the architecture/machine type, but the UEFI + variable store template associated with it might not have the usual set of + Secure Boot certificates enrolled. To figure out whether it's actually + possible to enforce Secure Boot, look at the ``enrolledKeys`` enum inside + the ``<firmwareFeatures/>`` element instead. + +The ``<varstore/>`` element :since:`(since 12.1.0)` indicates whether UEFI +variable storage backed by the ``uefi-vars`` QEMU device can be used as an +alternative to pflash-based NVRAM storage. This is the only type of variable +storage compatible with Secure Boot on non-x86 architectures, but it can be +used on x86 too. CPU configuration ~~~~~~~~~~~~~~~~~ diff --git a/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 7a80116de3..de54203dfc 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -24,6 +24,22 @@ v12.1.0 (unreleased) example Secure Boot support, is available for the selected architecture and machine type. + * qemu: Add support for uefi-vars device and firmware builds using it + + This is particularly noteworthy for people running aarch64 VMs, 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
On 2/18/26 13:05, Andrea Bolognani via Devel wrote:
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 is one patch that is marked as DONOTMERGE: that's because it imports into the tree firmware descriptor that are not yet part of the Fedora edk2 package.
Changes from [v2]:
* changes to the schema for JSON firmware descriptors have been queued for merge in QEMU, so the corresponding patch is no longer marked as DONOTMERGE;
* improve documentation;
* rebase on top of master, addressing conflicts that I have caused with some recent changes related to this work.
Changes from [v1]:
* rewrite based on review feedback: the <nvram> element is no longer used, and a dedicated <varstore> element is introduced instead;
* additional test coverage, as well as fixes and improvements related to firmware selection and its documentation, are present as well.
[v2] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/WVWT3... [v1] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/TGLFM...
Andrea Bolognani (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 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
179 files changed, 1314 insertions(+), 380 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
On Wed, Feb 18, 2026 at 01:05:23PM +0100, Andrea Bolognani via Devel wrote:
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 is one patch that is marked as DONOTMERGE: that's because it imports into the tree firmware descriptor that are not yet part of the Fedora edk2 package.
Not being a libvirt expert I can't really comment library internals. The test case data looks sane to me though, and I have not spotted anything else which looks wrong to me. Acked-by: Gerd Hoffmann <kraxel@redhat.com> take care, Gerd
participants (3)
-
Andrea Bolognani -
Gerd Hoffmann -
Michal Prívozník