[PATCH 00/29] qemu: Implement support for uefi-vars device and firmwares
This series makes it possible to use Secure Boot with aarch64 VMs. https://issues.redhat.com/browse/RHEL-82645 It needs a prerequisite series[1] to be applied first. Note that, while I consider the entire series to be ready for review, there are two patches that are marked as DONOTMERGE: that's because they respectively implement support for a JSON firmware descriptor syntax extension that has not yet been approved, and import into the tree firmware descriptor that are not yet part of the Fedora edk2 package. The latter depends on the former, of course, for which patches have been posted[2] to the QEMU mailing list. [1] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/N2ETT... [2] https://mail.gnu.org/archive/html/qemu-devel/2025-12/msg03462.html Andrea Bolognani (29): schemas: Drop pflashFormat schemas: Introduce firmware(Loader|Nvram)Formats schemas: Allow JSON format for NVRAM conf: Introduce VIR_STORAGE_FILE_JSON conf: Allow JSON format for NVRAM in the parser qemu_firmware: Rename qemuFirmwareFlashFile to qemuFirmwareFile qemu_firmware: Use qemuFirmwareFile in qemuFirmwareMappingMemory DONOTMERGE: qemu_firmware: Support extended syntax for ROM firmware descriptors qemu_firmware: Report NVRAM template path for ROMs qemu_firmware: Fill in more information for ROMs qemu_firmware: Don't skip EnsureNVRAM() for ROMs qemu_firmware: Parse host-uefi-vars firmware feature qemu_firmware: Split sanity check qemu_firmware: Consider host-uefi-vars feature in sanity check tests: Add firmware-manual-efi-qemuvars-q35 tests: Add firmware-manual-efi-qemuvars-aarch64 tests: Add firmware-manual-efi-qemuvars-nvram-network-nbd tests: Add firmware-auto-efi-enrolled-keys-aarch64 tests: Add firmware-auto-efi-format-nvram-json qemu_capabilities: Introduce QEMU_CAPS_DEVICE_UEFI_VARS qemu: Validate presence of uefi-vars device qemu: Don't allow remote locations for JSON format NVRAM qemu_firmware: Generate correct name for JSON format NVRAM qemu_firmware: Update matching logic for ROMs qemu_firmware: Require host-uefi-vars feature for JSON NVRAM qemu_firmware: Allow JSON format for NVRAM DONOTMERGE: tests: Add firmware descriptors for uefi-vars builds qemu_command: Use uefi-vars device where appropriate news: Document support for uefi-vars device and firmwares NEWS.rst | 10 + src/conf/domain_conf.c | 6 +- src/conf/schemas/domaincommon.rng | 22 +- src/conf/storage_source_conf.c | 2 +- src/conf/storage_source_conf.h | 1 + src/qemu/qemu_block.c | 2 + src/qemu/qemu_capabilities.c | 3 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 36 ++ src/qemu/qemu_firmware.c | 353 +++++++++++++++--- src/qemu/qemu_validate.c | 13 + .../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_x86_64+mshv.xml | 1 + .../caps_10.2.0_x86_64.xml | 1 + ...tdx.json => 50-edk2-ovmf-x64-microvm.json} | 12 +- .../firmware/60-edk2-ovmf-x64-inteltdx.json | 6 +- .../out/usr/share/qemu/firmware/91-bios.json | 33 ++ ...70-edk2-ovmf-qemuvars-x64-sb-enrolled.json | 35 ++ .../70-edk2-qemuvars-aarch64-sb-enrolled.json | 33 ++ tests/qemufirmwaretest.c | 10 +- ...ware-auto-bios-stateless.x86_64-latest.xml | 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 | 32 ++ ...i-enrolled-keys-aarch64.aarch64-latest.xml | 32 ++ ...irmware-auto-efi-enrolled-keys-aarch64.xml | 20 + ...uto-efi-format-nvram-json.x86_64-8.2.0.err | 1 + ...o-efi-format-nvram-json.x86_64-latest.args | 35 ++ ...o-efi-format-nvram-json.x86_64-latest.xml} | 11 +- .../firmware-auto-efi-format-nvram-json.xml | 18 + ...l-efi-qemuvars-aarch64.aarch64-latest.args | 33 ++ ...l-efi-qemuvars-aarch64.aarch64-latest.xml} | 24 +- .../firmware-manual-efi-qemuvars-aarch64.xml | 19 + ...muvars-nvram-network-nbd.x86_64-latest.err | 1 + ...-manual-efi-qemuvars-nvram-network-nbd.xml | 23 ++ ...manual-efi-qemuvars-q35.x86_64-latest.args | 35 ++ ...manual-efi-qemuvars-q35.x86_64-latest.xml} | 11 +- .../firmware-manual-efi-qemuvars-q35.xml | 19 + ...-manual-efi-tdx.x86_64-latest+inteltdx.xml | 2 +- tests/qemuxmlconftest.c | 8 + .../storagepoolcapsschemadata/poolcaps-fs.xml | 5 + .../poolcaps-full.xml | 5 + .../out/qcow2-qcow2_qcow2-qcow2_qcow2-auto | 2 +- .../out/qcow2-qcow2_qcow2-qcow2_raw-auto | 2 +- .../out/qcow2-qcow2_qcow2-qcow2_raw-raw | 2 +- tests/virstoragetestdata/out/qcow2-symlinks | 2 +- .../out/qcow2datafile-qcow2_qcow2-datafile | 2 +- 52 files changed, 824 insertions(+), 111 deletions(-) copy tests/qemufirmwaredata/out/usr/share/qemu/firmware/{60-edk2-ovmf-x64-inteltdx.json => 50-edk2-ovmf-x64-microvm.json} (56%) create mode 100644 tests/qemufirmwaredata/out/usr/share/qemu/firmware/91-bios.json 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/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.args copy tests/qemuxmlconfdata/{firmware-auto-bios-stateless.x86_64-latest.xml => firmware-auto-efi-format-nvram-json.x86_64-latest.xml} (71%) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.args copy tests/qemuxmlconfdata/{firmware-auto-bios.x86_64-latest.xml => firmware-manual-efi-qemuvars-aarch64.aarch64-latest.xml} (52%) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.args copy tests/qemuxmlconfdata/{firmware-auto-bios-stateless.x86_64-latest.xml => firmware-manual-efi-qemuvars-q35.x86_64-latest.xml} (74%) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.xml -- 2.52.0
It offers very little savings (dropping it actually reduces the numbers of lines in the file slightly) and gets in the way of upcoming changes. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/schemas/domaincommon.rng | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index c7346526ef..400e7eec22 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -341,7 +341,9 @@ </attribute> </optional> <optional> - <ref name="pflashFormat"/> + <attribute name="format"> + <ref name="pflashFormatTypes"/> + </attribute> </optional> <optional> <ref name="absFilePath"/> @@ -361,7 +363,9 @@ </attribute> </optional> <optional> - <ref name="pflashFormat"/> + <attribute name="format"> + <ref name="pflashFormatTypes"/> + </attribute> </optional> <optional> <choice> @@ -8027,12 +8031,6 @@ </choice> </define> - <define name="pflashFormat"> - <attribute name="format"> - <ref name="pflashFormatTypes"/> - </attribute> - </define> - <!-- Optional HyperV Enlightenment features --> <define name="hyperv"> <element name="hyperv"> -- 2.52.0
The name "pflashFormatTypes" was already inaccurate, since the format attribute applies to ROM loaders too. Additionally, we are soon going to introduce support for formats that can be used for NVRAMs and their templates but not for the corresponding executables, so we need two distinct lists despite the partial overlap. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/schemas/domaincommon.rng | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 400e7eec22..c799bf04b7 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -342,7 +342,7 @@ </optional> <optional> <attribute name="format"> - <ref name="pflashFormatTypes"/> + <ref name="firmwareLoaderFormats"/> </attribute> </optional> <optional> @@ -359,12 +359,12 @@ </optional> <optional> <attribute name="templateFormat"> - <ref name="pflashFormatTypes"/> + <ref name="firmwareNvramFormats"/> </attribute> </optional> <optional> <attribute name="format"> - <ref name="pflashFormatTypes"/> + <ref name="firmwareNvramFormats"/> </attribute> </optional> <optional> @@ -8024,7 +8024,14 @@ </element> </define> - <define name="pflashFormatTypes"> + <define name="firmwareLoaderFormats"> + <choice> + <value>raw</value> + <value>qcow2</value> + </choice> + </define> + + <define name="firmwareNvramFormats"> <choice> <value>raw</value> <value>qcow2</value> -- 2.52.0
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/schemas/domaincommon.rng | 1 + 1 file changed, 1 insertion(+) diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index c799bf04b7..ea5f8dac85 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -8035,6 +8035,7 @@ <choice> <value>raw</value> <value>qcow2</value> + <value>json</value> </choice> </define> -- 2.52.0
On Mon, Dec 29, 2025 at 12:40:22AM +0100, Andrea Bolognani via Devel wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/schemas/domaincommon.rng | 1 + 1 file changed, 1 insertion(+)
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index c799bf04b7..ea5f8dac85 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -8035,6 +8035,7 @@ <choice> <value>raw</value> <value>qcow2</value> + <value>json</value> </choice> </define>
The firmware JSON files are not providing NVRAM storage, and 'json' is not a valid QEMU blockdev driver either. This is overloading different concepts and doesn't make sense IMHO. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
We will need to handle storage files using JSON format soon. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/storage_source_conf.c | 2 +- src/conf/storage_source_conf.h | 1 + src/qemu/qemu_block.c | 2 ++ tests/storagepoolcapsschemadata/poolcaps-fs.xml | 5 +++++ tests/storagepoolcapsschemadata/poolcaps-full.xml | 5 +++++ .../out/qcow2-qcow2_qcow2-qcow2_qcow2-auto | 2 +- .../virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-auto | 2 +- tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-raw | 2 +- tests/virstoragetestdata/out/qcow2-symlinks | 2 +- .../out/qcow2datafile-qcow2_qcow2-datafile | 2 +- 10 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index 087de1eaf2..e62707ba9b 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -57,7 +57,7 @@ VIR_ENUM_IMPL(virStorageFileFormat, "none", "raw", "dir", "bochs", "cloop", "dmg", "iso", - "vpc", "vdi", + "vpc", "vdi", "json", /* Not direct file formats, but used for various drivers */ "fat", "vhd", "ploop", /* Formats with backing file below here */ diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h index fc868b31af..0682da27f0 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -63,6 +63,7 @@ typedef enum { VIR_STORAGE_FILE_ISO, VIR_STORAGE_FILE_VPC, VIR_STORAGE_FILE_VDI, + VIR_STORAGE_FILE_JSON, /* Not direct file formats, but used for various drivers */ VIR_STORAGE_FILE_FAT, diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index a7062d3e96..66384a8159 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1322,6 +1322,7 @@ qemuBlockStorageSourceGetBlockdevFormatProps(virStorageSource *src) case VIR_STORAGE_FILE_COW: case VIR_STORAGE_FILE_ISO: case VIR_STORAGE_FILE_DIR: + case VIR_STORAGE_FILE_JSON: virReportError(VIR_ERR_INTERNAL_ERROR, _("mishandled storage format '%1$s'"), virStorageFileFormatTypeToString(src->format)); @@ -2317,6 +2318,7 @@ qemuBlockStorageSourceCreateGetFormatProps(virStorageSource *src, case VIR_STORAGE_FILE_COW: case VIR_STORAGE_FILE_ISO: case VIR_STORAGE_FILE_DIR: + case VIR_STORAGE_FILE_JSON: return 0; case VIR_STORAGE_FILE_AUTO_SAFE: diff --git a/tests/storagepoolcapsschemadata/poolcaps-fs.xml b/tests/storagepoolcapsschemadata/poolcaps-fs.xml index eee75af746..1f59d33aef 100644 --- a/tests/storagepoolcapsschemadata/poolcaps-fs.xml +++ b/tests/storagepoolcapsschemadata/poolcaps-fs.xml @@ -12,6 +12,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -55,6 +56,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -88,6 +90,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -167,6 +170,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -193,6 +197,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> diff --git a/tests/storagepoolcapsschemadata/poolcaps-full.xml b/tests/storagepoolcapsschemadata/poolcaps-full.xml index 805950a937..a4f532cbb8 100644 --- a/tests/storagepoolcapsschemadata/poolcaps-full.xml +++ b/tests/storagepoolcapsschemadata/poolcaps-full.xml @@ -12,6 +12,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -55,6 +56,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -88,6 +90,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -167,6 +170,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> @@ -193,6 +197,7 @@ <value>iso</value> <value>vpc</value> <value>vdi</value> + <value>json</value> <value>fat</value> <value>vhd</value> <value>ploop</value> diff --git a/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_qcow2-auto b/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_qcow2-auto index 79943f432e..c9db352af8 100644 --- a/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_qcow2-auto +++ b/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_qcow2-auto @@ -1,6 +1,6 @@ path:ABS_SRCDIR/virstoragetestdata/images/qcow2_qcow2-qcow2_qcow2-auto.qcow2 backingStoreRaw: qcow2_qcow2-auto.qcow2 -backingStoreRawFormat: qcow2(14) +backingStoreRawFormat: qcow2(15) dataFileRaw: <null> capacity: 1024 encryption: 0 diff --git a/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-auto b/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-auto index 02e2c5a966..713df6086d 100644 --- a/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-auto +++ b/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-auto @@ -1,6 +1,6 @@ path:ABS_SRCDIR/virstoragetestdata/images/qcow2_qcow2-qcow2_raw-auto.qcow2 backingStoreRaw: qcow2_raw-auto.qcow2 -backingStoreRawFormat: qcow2(14) +backingStoreRawFormat: qcow2(15) dataFileRaw: <null> capacity: 1024 encryption: 0 diff --git a/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-raw b/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-raw index 843a013ef5..fb741133df 100644 --- a/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-raw +++ b/tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-raw @@ -1,6 +1,6 @@ path:ABS_BUILDDIR/virstoragedata/wrap backingStoreRaw: ABS_BUILDDIR/virstoragedata/qcow2 -backingStoreRawFormat: qcow2(14) +backingStoreRawFormat: qcow2(15) dataFileRaw: <null> capacity: 1024 encryption: 0 diff --git a/tests/virstoragetestdata/out/qcow2-symlinks b/tests/virstoragetestdata/out/qcow2-symlinks index c74cf6be53..8cc5d43e8f 100644 --- a/tests/virstoragetestdata/out/qcow2-symlinks +++ b/tests/virstoragetestdata/out/qcow2-symlinks @@ -1,6 +1,6 @@ path:ABS_SRCDIR/virstoragetestdata/images/sub/link2 backingStoreRaw: ../sub/link1 -backingStoreRawFormat: qcow2(14) +backingStoreRawFormat: qcow2(15) dataFileRaw: <null> capacity: 1024 encryption: 0 diff --git a/tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile b/tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile index a200ba98fa..51dacec39c 100644 --- a/tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile +++ b/tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile @@ -1,6 +1,6 @@ path:ABS_SRCDIR/virstoragetestdata/images/qcow2datafile-datafile.qcow2 backingStoreRaw: datafile.qcow2 -backingStoreRawFormat: qcow2(14) +backingStoreRawFormat: qcow2(15) dataFileRaw: raw capacity: 1024 encryption: 0 -- 2.52.0
On Mon, Dec 29, 2025 at 12:40:23AM +0100, Andrea Bolognani via Devel wrote:
We will need to handle storage files using JSON format soon.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/storage_source_conf.c | 2 +- src/conf/storage_source_conf.h | 1 + src/qemu/qemu_block.c | 2 ++ tests/storagepoolcapsschemadata/poolcaps-fs.xml | 5 +++++ tests/storagepoolcapsschemadata/poolcaps-full.xml | 5 +++++ .../out/qcow2-qcow2_qcow2-qcow2_qcow2-auto | 2 +- .../virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-auto | 2 +- tests/virstoragetestdata/out/qcow2-qcow2_qcow2-qcow2_raw-raw | 2 +- tests/virstoragetestdata/out/qcow2-symlinks | 2 +- .../out/qcow2datafile-qcow2_qcow2-datafile | 2 +- 10 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index 087de1eaf2..e62707ba9b 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -57,7 +57,7 @@ VIR_ENUM_IMPL(virStorageFileFormat, "none", "raw", "dir", "bochs", "cloop", "dmg", "iso", - "vpc", "vdi", + "vpc", "vdi", "json", /* Not direct file formats, but used for various drivers */ "fat", "vhd", "ploop", /* Formats with backing file below here */ diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h index fc868b31af..0682da27f0 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -63,6 +63,7 @@ typedef enum { VIR_STORAGE_FILE_ISO, VIR_STORAGE_FILE_VPC, VIR_STORAGE_FILE_VDI, + VIR_STORAGE_FILE_JSON,
I have the same comments as the previous patch, only it is even more critical here. 'json' is not a block device format. It is a config file format for the UEFI vars service, so it has no business being anywhere near the virStorageFileFormat code. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/domain_conf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 25494cb01a..6fad82c026 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -17766,7 +17766,8 @@ virDomainLoaderDefParseXMLNvram(virDomainLoaderDef *loader, if (loader->nvramTemplateFormat != VIR_STORAGE_FILE_NONE && loader->nvramTemplateFormat != VIR_STORAGE_FILE_RAW && - loader->nvramTemplateFormat != VIR_STORAGE_FILE_QCOW2) { + loader->nvramTemplateFormat != VIR_STORAGE_FILE_QCOW2 && + loader->nvramTemplateFormat != VIR_STORAGE_FILE_JSON) { virReportError(VIR_ERR_XML_ERROR, _("Unsupported nvram template format '%1$s'"), virStorageFileFormatTypeToString(loader->nvramTemplateFormat)); @@ -17782,7 +17783,8 @@ virDomainLoaderDefParseXMLNvram(virDomainLoaderDef *loader, if (src->format != VIR_STORAGE_FILE_NONE && src->format != VIR_STORAGE_FILE_RAW && - src->format != VIR_STORAGE_FILE_QCOW2) { + src->format != VIR_STORAGE_FILE_QCOW2 && + src->format != VIR_STORAGE_FILE_JSON) { virReportError(VIR_ERR_XML_ERROR, _("Unsupported nvram format '%1$s'"), virStorageFileFormatTypeToString(src->format)); -- 2.52.0
This type is currently only used when working with pflash firmware builds, so the name is accurate, but we are about to extend its usage to ROM builds as well. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 47 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 52205b72f8..e3471d9adb 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -61,6 +61,13 @@ VIR_ENUM_IMPL(qemuFirmwareOSInterface, ); +typedef struct _qemuFirmwareFile qemuFirmwareFile; +struct _qemuFirmwareFile { + char *filename; + char *format; +}; + + typedef enum { QEMU_FIRMWARE_FLASH_MODE_SPLIT, QEMU_FIRMWARE_FLASH_MODE_COMBINED, @@ -77,18 +84,12 @@ VIR_ENUM_IMPL(qemuFirmwareFlashMode, "stateless", ); -typedef struct _qemuFirmwareFlashFile qemuFirmwareFlashFile; -struct _qemuFirmwareFlashFile { - char *filename; - char *format; -}; - typedef struct _qemuFirmwareMappingFlash qemuFirmwareMappingFlash; struct _qemuFirmwareMappingFlash { qemuFirmwareFlashMode mode; - qemuFirmwareFlashFile executable; - qemuFirmwareFlashFile nvram_template; + qemuFirmwareFile executable; + qemuFirmwareFile nvram_template; }; @@ -198,7 +199,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuFirmwareOSInterface, qemuFirmwareOSInterfaceFr static void -qemuFirmwareFlashFileFreeContent(qemuFirmwareFlashFile *flash) +qemuFirmwareFileFreeContent(qemuFirmwareFile *flash) { g_free(flash->filename); g_free(flash->format); @@ -208,8 +209,8 @@ qemuFirmwareFlashFileFreeContent(qemuFirmwareFlashFile *flash) static void qemuFirmwareMappingFlashFreeContent(qemuFirmwareMappingFlash *flash) { - qemuFirmwareFlashFileFreeContent(&flash->executable); - qemuFirmwareFlashFileFreeContent(&flash->nvram_template); + qemuFirmwareFileFreeContent(&flash->executable); + qemuFirmwareFileFreeContent(&flash->nvram_template); } @@ -325,9 +326,9 @@ qemuFirmwareInterfaceParse(const char *path, static int -qemuFirmwareFlashFileParse(const char *path, - virJSONValue *doc, - qemuFirmwareFlashFile *flash) +qemuFirmwareFileParse(const char *path, + virJSONValue *doc, + qemuFirmwareFile *fwfile) { const char *filename; const char *format; @@ -337,14 +338,14 @@ qemuFirmwareFlashFileParse(const char *path, return -1; } - flash->filename = g_strdup(filename); + fwfile->filename = g_strdup(filename); if (!(format = virJSONValueObjectGetString(doc, "format"))) { VIR_DEBUG("missing 'format' in '%s'", path); return -1; } - flash->format = g_strdup(format); + fwfile->format = g_strdup(format); return 0; } @@ -382,7 +383,7 @@ qemuFirmwareMappingFlashParse(const char *path, return -1; } - if (qemuFirmwareFlashFileParse(path, executable, &flash->executable) < 0) + if (qemuFirmwareFileParse(path, executable, &flash->executable) < 0) return -1; if (flash->mode == QEMU_FIRMWARE_FLASH_MODE_SPLIT) { @@ -391,7 +392,7 @@ qemuFirmwareMappingFlashParse(const char *path, return -1; } - if (qemuFirmwareFlashFileParse(path, nvram_template, &flash->nvram_template) < 0) + if (qemuFirmwareFileParse(path, nvram_template, &flash->nvram_template) < 0) return -1; } @@ -637,19 +638,19 @@ qemuFirmwareInterfaceFormat(virJSONValue *doc, static virJSONValue * -qemuFirmwareFlashFileFormat(qemuFirmwareFlashFile flash) +qemuFirmwareFileFormat(qemuFirmwareFile fwfile) { g_autoptr(virJSONValue) json = virJSONValueNewObject(); virJSONValue *ret; if (virJSONValueObjectAppendString(json, "filename", - flash.filename) < 0) + fwfile.filename) < 0) return NULL; if (virJSONValueObjectAppendString(json, "format", - flash.format) < 0) + fwfile.format) < 0) return NULL; ret = g_steal_pointer(&json); @@ -669,7 +670,7 @@ qemuFirmwareMappingFlashFormat(virJSONValue *mapping, qemuFirmwareFlashModeTypeToString(flash->mode)) < 0) return -1; - if (!(executable = qemuFirmwareFlashFileFormat(flash->executable))) + if (!(executable = qemuFirmwareFileFormat(flash->executable))) return -1; if (virJSONValueObjectAppend(mapping, @@ -678,7 +679,7 @@ qemuFirmwareMappingFlashFormat(virJSONValue *mapping, return -1; if (flash->mode == QEMU_FIRMWARE_FLASH_MODE_SPLIT) { - if (!(nvram_template = qemuFirmwareFlashFileFormat(flash->nvram_template))) + if (!(nvram_template = qemuFirmwareFileFormat(flash->nvram_template))) return -1; if (virJSONValueObjectAppend(mapping, -- 2.52.0
Not very useful for now, but sets the stage for further changes. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index e3471d9adb..5f5550424f 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -95,7 +95,7 @@ struct _qemuFirmwareMappingFlash { typedef struct _qemuFirmwareMappingMemory qemuFirmwareMappingMemory; struct _qemuFirmwareMappingMemory { - char *filename; + qemuFirmwareFile executable; }; @@ -217,7 +217,7 @@ qemuFirmwareMappingFlashFreeContent(qemuFirmwareMappingFlash *flash) static void qemuFirmwareMappingMemoryFreeContent(qemuFirmwareMappingMemory *memory) { - g_free(memory->filename); + qemuFirmwareFileFreeContent(&memory->executable); } @@ -412,7 +412,8 @@ qemuFirmwareMappingMemoryParse(const char *path, return -1; } - memory->filename = g_strdup(filename); + memory->executable.filename = g_strdup(filename); + memory->executable.format = g_strdup("raw"); return 0; } @@ -698,7 +699,7 @@ qemuFirmwareMappingMemoryFormat(virJSONValue *mapping, { if (virJSONValueObjectAppendString(mapping, "filename", - memory->filename) < 0) + memory->executable.filename) < 0) return -1; return 0; @@ -890,7 +891,7 @@ qemuFirmwareMatchesPaths(const qemuFirmware *fw, break; case QEMU_FIRMWARE_DEVICE_MEMORY: if (loader && loader->path && - !virFileComparePaths(loader->path, memory->filename)) + !virFileComparePaths(loader->path, memory->executable.filename)) return false; break; case QEMU_FIRMWARE_DEVICE_NONE: @@ -1481,7 +1482,7 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def, loader->format = VIR_STORAGE_FILE_RAW; VIR_FREE(loader->path); - loader->path = g_strdup(memory->filename); + loader->path = g_strdup(memory->executable.filename); VIR_DEBUG("decided on loader '%s'", loader->path); @@ -2078,7 +2079,7 @@ qemuFirmwareGetSupported(const char *machine, break; case QEMU_FIRMWARE_DEVICE_MEMORY: - fwpath = memory->filename; + fwpath = memory->executable.filename; break; case QEMU_FIRMWARE_DEVICE_NONE: -- 2.52.0
The legacy syntax can only describe stateless firmware builds, while the extended one can additionally describe split builds where an NVRAM file is used for variable storage. The extended syntax is basically identical to the one that we already have to support for flash firmware descriptors. It's a strict superset of the legacy one, so we can always store the former one internally and not worry about the differences past the parse phase. Some of the output files for qemufirmwaretest are updated as a consequence of this, but the changes are not semantically meaningful. DONOTMERGE: The extended syntax has not been accepted into the official spec yet. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 130 ++++++++++++++++-- ...tdx.json => 50-edk2-ovmf-x64-microvm.json} | 12 +- .../firmware/60-edk2-ovmf-x64-inteltdx.json | 6 +- .../out/usr/share/qemu/firmware/91-bios.json | 33 +++++ 4 files changed, 166 insertions(+), 15 deletions(-) copy tests/qemufirmwaredata/out/usr/share/qemu/firmware/{60-edk2-ovmf-x64-inteltdx.json => 50-edk2-ovmf-x64-microvm.json} (56%) create mode 100644 tests/qemufirmwaredata/out/usr/share/qemu/firmware/91-bios.json diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 5f5550424f..bf6090fac0 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -93,9 +93,26 @@ struct _qemuFirmwareMappingFlash { }; +typedef enum { + QEMU_FIRMWARE_MEMORY_MODE_SPLIT, + QEMU_FIRMWARE_MEMORY_MODE_STATELESS, + + QEMU_FIRMWARE_MEMORY_MODE_LAST, +} qemuFirmwareMemoryMode; + +VIR_ENUM_DECL(qemuFirmwareMemoryMode); +VIR_ENUM_IMPL(qemuFirmwareMemoryMode, + QEMU_FIRMWARE_MEMORY_MODE_LAST, + "split", + "stateless", +); + + typedef struct _qemuFirmwareMappingMemory qemuFirmwareMappingMemory; struct _qemuFirmwareMappingMemory { + qemuFirmwareMemoryMode mode; qemuFirmwareFile executable; + qemuFirmwareFile nvram_template; }; @@ -218,6 +235,7 @@ static void qemuFirmwareMappingMemoryFreeContent(qemuFirmwareMappingMemory *memory) { qemuFirmwareFileFreeContent(&memory->executable); + qemuFirmwareFileFreeContent(&memory->nvram_template); } @@ -405,15 +423,90 @@ qemuFirmwareMappingMemoryParse(const char *path, virJSONValue *doc, qemuFirmwareMappingMemory *memory) { - const char *filename; - - if (!(filename = virJSONValueObjectGetString(doc, "filename"))) { - VIR_DEBUG("missing 'filename' in '%s'", path); + virJSONValue *mode; + virJSONValue *executable; + virJSONValue *nvram_template; + virJSONValue *filename; + + mode = virJSONValueObjectGet(doc, "mode"); + executable = virJSONValueObjectGet(doc, "executable"); + nvram_template = virJSONValueObjectGet(doc, "nvram-template"); + filename = virJSONValueObjectGet(doc, "filename"); + + /* Firmware descriptors can use either the legacy syntax (filename) or + * the extended one (mode, executable and optionally nvram-template), + * but mixing and matching the two is not allowed. Malformed firmware + * descriptors will be ignored */ + if (!executable && !filename) { + VIR_DEBUG("Must have one of 'executable' and 'filename' in '%s'", path); + return -1; + } + if (executable && filename) { + VIR_DEBUG("Cannot have both 'executable' and 'filename' in '%s'", path); return -1; } + if (executable && !mode) { + VIR_DEBUG("Must have 'mode' with 'executable' in '%s'", path); + return -1; + } + if (filename && mode) { + VIR_DEBUG("Cannot have 'mode' with 'filename' in '%s'", path); + return -1; + } + if (filename && nvram_template) { + VIR_DEBUG("Cannot have 'nvram_template' with 'filename' in '%s'", path); + return -1; + } + + if (mode) { + const char *modestr; + int modeval; + + modestr = virJSONValueGetString(mode); + if (!modestr) { + VIR_DEBUG("Value of 'mode' is not a string in '%s'", path); + return -1; + } - memory->executable.filename = g_strdup(filename); - memory->executable.format = g_strdup("raw"); + modeval = qemuFirmwareMemoryModeTypeFromString(modestr); + if (modeval < 0) { + VIR_DEBUG("Unrecognized value '%s' for 'mode' in '%s'", modestr, path); + return -1; + } + + memory->mode = modeval; + } else { + /* Default for legacy syntax */ + memory->mode = QEMU_FIRMWARE_MEMORY_MODE_STATELESS; + } + + if (executable) { + if (qemuFirmwareFileParse(path, executable, &memory->executable) < 0) + return -1; + } + + if (memory->mode == QEMU_FIRMWARE_MEMORY_MODE_SPLIT) { + if (!nvram_template) { + VIR_DEBUG("Missing mandatory 'nvram-template' for mode=split in '%s'", path); + return -1; + } + + if (qemuFirmwareFileParse(path, nvram_template, &memory->nvram_template) < 0) + return -1; + } + + if (filename) { + const char *filenameval; + + filenameval = virJSONValueGetString(filename); + if (!filenameval) { + VIR_DEBUG("Value of 'filename' is not a string in '%s'", path); + return -1; + } + + memory->executable.filename = g_strdup(filenameval); + memory->executable.format = g_strdup("raw"); + } return 0; } @@ -697,11 +790,32 @@ static int qemuFirmwareMappingMemoryFormat(virJSONValue *mapping, qemuFirmwareMappingMemory *memory) { + g_autoptr(virJSONValue) executable = NULL; + g_autoptr(virJSONValue) nvram_template = NULL; + if (virJSONValueObjectAppendString(mapping, - "filename", - memory->executable.filename) < 0) + "mode", + qemuFirmwareMemoryModeTypeToString(memory->mode)) < 0) + return -1; + + if (!(executable = qemuFirmwareFileFormat(memory->executable))) + return -1; + + if (virJSONValueObjectAppend(mapping, + "executable", + &executable) < 0) return -1; + if (memory->mode == QEMU_FIRMWARE_MEMORY_MODE_SPLIT) { + if (!(nvram_template = qemuFirmwareFileFormat(memory->nvram_template))) + return -1; + + if (virJSONValueObjectAppend(mapping, + "nvram-template", + &nvram_template) < 0) + return -1; + } + return 0; } diff --git a/tests/qemufirmwaredata/out/usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json b/tests/qemufirmwaredata/out/usr/share/qemu/firmware/50-edk2-ovmf-x64-microvm.json similarity index 56% copy from tests/qemufirmwaredata/out/usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json copy to tests/qemufirmwaredata/out/usr/share/qemu/firmware/50-edk2-ovmf-x64-microvm.json index 2630b57b05..ebe1c2db55 100644 --- a/tests/qemufirmwaredata/out/usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json +++ b/tests/qemufirmwaredata/out/usr/share/qemu/firmware/50-edk2-ovmf-x64-microvm.json @@ -4,20 +4,20 @@ ], "mapping": { "device": "memory", - "filename": "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd" + "mode": "stateless", + "executable": { + "filename": "/usr/share/edk2/ovmf/MICROVM.fd", + "format": "raw" + } }, "targets": [ { "architecture": "x86_64", "machines": [ - "pc-q35-*" + "microvm" ] } ], "features": [ - "enrolled-keys", - "intel-tdx", - "secure-boot", - "verbose-dynamic" ] } diff --git a/tests/qemufirmwaredata/out/usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json b/tests/qemufirmwaredata/out/usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json index 2630b57b05..68a1cb4ee0 100644 --- a/tests/qemufirmwaredata/out/usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json +++ b/tests/qemufirmwaredata/out/usr/share/qemu/firmware/60-edk2-ovmf-x64-inteltdx.json @@ -4,7 +4,11 @@ ], "mapping": { "device": "memory", - "filename": "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd" + "mode": "stateless", + "executable": { + "filename": "/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd", + "format": "raw" + } }, "targets": [ { diff --git a/tests/qemufirmwaredata/out/usr/share/qemu/firmware/91-bios.json b/tests/qemufirmwaredata/out/usr/share/qemu/firmware/91-bios.json new file mode 100644 index 0000000000..10a22969f4 --- /dev/null +++ b/tests/qemufirmwaredata/out/usr/share/qemu/firmware/91-bios.json @@ -0,0 +1,33 @@ +{ + "interface-types": [ + "bios" + ], + "mapping": { + "device": "memory", + "mode": "stateless", + "executable": { + "filename": "/usr/share/seabios/bios-256k.bin", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "i386", + "machines": [ + "pc-i440fx-*", + "pc-q35-*" + ] + }, + { + "architecture": "x86_64", + "machines": [ + "pc-i440fx-*", + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "acpi-s4" + ] +} -- 2.52.0
This was not necessary until now since ROMs couldn't have an associate NVRAM template, but that's a possibility now and we have to account for it. 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 bf6090fac0..770c886136 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2194,6 +2194,7 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_DEVICE_MEMORY: fwpath = memory->executable.filename; + nvrampath = memory->nvram_template.filename; break; case QEMU_FIRMWARE_DEVICE_NONE: -- 2.52.0
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 30 +++++++++++++++++-- ...ware-auto-bios-stateless.x86_64-latest.xml | 2 +- .../firmware-auto-bios.x86_64-latest.xml | 2 +- ...-manual-efi-tdx.x86_64-latest+inteltdx.xml | 2 +- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 770c886136..fc78433100 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1588,18 +1588,42 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def, break; case QEMU_FIRMWARE_DEVICE_MEMORY: + if ((format = virStorageFileFormatTypeFromString(memory->executable.format)) < 0) + return -1; + if (!def->os.loader) def->os.loader = virDomainLoaderDefNew(); loader = def->os.loader; loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; - loader->format = VIR_STORAGE_FILE_RAW; + loader->format = format; + + loader->readonly = VIR_TRISTATE_BOOL_YES; + + if (memory->mode == QEMU_FIRMWARE_MEMORY_MODE_STATELESS) + loader->stateless = VIR_TRISTATE_BOOL_YES; VIR_FREE(loader->path); loader->path = g_strdup(memory->executable.filename); - VIR_DEBUG("decided on loader '%s'", - loader->path); + if (memory->mode == QEMU_FIRMWARE_MEMORY_MODE_SPLIT) { + /* Only fill in nvramTemplate if the NVRAM location is already + * known to be a local path or hasn't been provided, in which + * case a local path will be generated by libvirt later. + * + * We can't create or reset non-local NVRAM files, so filling + * in nvramTemplate for those would be misleading */ + VIR_FREE(loader->nvramTemplate); + loader->nvramTemplateFormat = VIR_STORAGE_FILE_NONE; + + if (!loader->nvram || virStorageSourceIsLocalStorage(loader->nvram)) { + loader->nvramTemplate = g_strdup(memory->nvram_template.filename); + loader->nvramTemplateFormat = virStorageFileFormatTypeFromString(memory->nvram_template.format); + } + } + + VIR_DEBUG("decided on firmware '%s' template '%s'", + loader->path, NULLSTR(loader->nvramTemplate)); break; case QEMU_FIRMWARE_DEVICE_NONE: 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..ca4ffb0e6c 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 readonly='yes' type='rom' stateless='yes' format='raw'>/usr/share/seabios/bios-256k.bin</loader> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-bios.x86_64-latest.xml index ae9c9f56d9..ca4ffb0e6c 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 readonly='yes' type='rom' stateless='yes' format='raw'>/usr/share/seabios/bios-256k.bin</loader> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml b/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml index 5b87857425..6dc8496d3d 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml +++ b/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml @@ -10,7 +10,7 @@ <feature enabled='yes' name='enrolled-keys'/> <feature enabled='yes' name='secure-boot'/> </firmware> - <loader readonly='yes' type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd</loader> + <loader readonly='yes' type='rom' stateless='yes' format='raw'>/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd</loader> <boot dev='hd'/> </os> <features> -- 2.52.0
Now that we expect NVRAM to be used together with ROM firmware builds, we need to ensure that the corresponding configuration is always populated correctly. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index fc78433100..1b97cdb316 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1076,9 +1076,6 @@ qemuFirmwareEnsureNVRAM(virDomainDef *def, if (!loader) return; - if (loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH) - return; - if (loader->readonly != VIR_TRISTATE_BOOL_YES) return; -- 2.52.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 1b97cdb316..309ec3f349 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -163,6 +163,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, @@ -182,6 +183,7 @@ VIR_ENUM_IMPL(qemuFirmwareFeature, "enrolled-keys", "requires-smm", "secure-boot", + "host-uefi-vars", "verbose-dynamic", "verbose-static" ); @@ -1294,6 +1296,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: @@ -1652,6 +1655,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: @@ -1707,6 +1711,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: @@ -2200,6 +2205,7 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_FEATURE_INTEL_TDX: case QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS: case QEMU_FIRMWARE_FEATURE_SECURE_BOOT: + case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_LAST: -- 2.52.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 309ec3f349..68563b8083 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1726,16 +1726,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.52.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 68563b8083..962d6cdee7 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1689,6 +1689,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++) { @@ -1702,6 +1703,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: @@ -1711,7 +1715,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: @@ -1725,14 +1728,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.52.0
This test case demonstrates how to manually configure an x86_64 guest to use the uefi-vars device. It currently fails because the QEMU driver does not yet allow the use of JSON for NVRAM. That will change in a future commit. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...-manual-efi-qemuvars-q35.x86_64-latest.err | 1 + ...-manual-efi-qemuvars-q35.x86_64-latest.xml | 36 +++++++++++++++++++ .../firmware-manual-efi-qemuvars-q35.xml | 19 ++++++++++ tests/qemuxmlconftest.c | 2 ++ 4 files changed, 58 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.xml diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err new file mode 100644 index 0000000000..e5f67f8d09 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err @@ -0,0 +1 @@ +unsupported configuration: Unsupported nvram format 'json' diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml new file mode 100644 index 0000000000..a16c404eaf --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml @@ -0,0 +1,36 @@ +<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-q35-10.0'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram format='json'>/path/to/guest.json</nvram> + <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-qemuvars-q35.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.xml new file mode 100644 index 0000000000..07b744d490 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.xml @@ -0,0 +1,19 @@ +<domain type='qemu'> + <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-10.0'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram format='json'>/path/to/guest.json</nvram> + </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 89b8ad1a35..1e20957656 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1560,6 +1560,8 @@ mymain(void) ARG_CAPS_VARIANT, "+inteltdx", ARG_END); + DO_TEST_CAPS_LATEST_FAILURE("firmware-manual-efi-qemuvars-q35"); + /* 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.52.0
On Mon, Dec 29, 2025 at 12:40:34AM +0100, Andrea Bolognani via Devel wrote:
This test case demonstrates how to manually configure an x86_64 guest to use the uefi-vars device.
It currently fails because the QEMU driver does not yet allow the use of JSON for NVRAM. That will change in a future commit.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...-manual-efi-qemuvars-q35.x86_64-latest.err | 1 + ...-manual-efi-qemuvars-q35.x86_64-latest.xml | 36 +++++++++++++++++++ .../firmware-manual-efi-qemuvars-q35.xml | 19 ++++++++++ tests/qemuxmlconftest.c | 2 ++ 4 files changed, 58 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.xml
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err new file mode 100644 index 0000000000..e5f67f8d09 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err @@ -0,0 +1 @@ +unsupported configuration: Unsupported nvram format 'json' diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml new file mode 100644 index 0000000000..a16c404eaf --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml @@ -0,0 +1,36 @@ +<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-q35-10.0'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram format='json'>/path/to/guest.json</nvram>
IMHO it is wrong to be trying to squash the JSON vars storage concept into the <nvram> element. It isn't providing NVRAM to the guest and "json" is not a valid -blockdev format type, so this is overloading concepts. IMHO there needs to be a new config element to represent the new UEFI vars service persistence concept. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
[adding Gerd] On Wed, Jan 07, 2026 at 10:14:51AM +0000, Daniel P. Berrangé wrote:
On Mon, Dec 29, 2025 at 12:40:34AM +0100, Andrea Bolognani via Devel wrote:
+ <os> + <type arch='x86_64' machine='pc-q35-10.0'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram format='json'>/path/to/guest.json</nvram>
IMHO it is wrong to be trying to squash the JSON vars storage concept into the <nvram> element. It isn't providing NVRAM to the guest and "json" is not a valid -blockdev format type, so this is overloading concepts. IMHO there needs to be a new config element to represent the new UEFI vars service persistence concept.
I went with the existing element because, from a user's perspective, regardless of the underlying implementation details the experience is effectively the same. But I see your point. If we want to introduce a new element, perhaps it could look like this: <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> <varstore type='uefi-vars'> <template path='/usr/share/edk2/ovmf/OVMF_VARS.qemuvars.json'/> <source path='/path/to/guest.json'/> </varstore> This leaves room to implement fine-grained certificate management as an extension: <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> <varstore type='uefi-vars'> <source path='/path/to/guest.json'/> <pk path='/path/to/microsoft-pk.pem'/> <kek path='/path/to/microsoft-kek.pem'/> <db path='/path/to/redhat.pem'/> <db path='/path/to/fedora.pem'/> </varstore> Thoughts? Suggestion on better names for the elements/attributes? :) -- Andrea Bolognani / Red Hat / Virtualization
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> --- ...al-efi-qemuvars-aarch64.aarch64-latest.err | 1 + .../firmware-manual-efi-qemuvars-aarch64.xml | 19 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 3 files changed, 21 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.xml diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.err new file mode 100644 index 0000000000..4fe79bdacf --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.err @@ -0,0 +1 @@ +unsupported configuration: ACPI requires UEFI on this architecture diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.xml new file mode 100644 index 0000000000..28e3343eec --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.xml @@ -0,0 +1,19 @@ +<domain type='qemu'> + <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-4.0'>hvm</type> + <loader type='rom'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <nvram format='json'>/path/to/guest.json</nvram> + </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 1e20957656..fa768df1a2 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1561,6 +1561,7 @@ mymain(void) ARG_END); DO_TEST_CAPS_LATEST_FAILURE("firmware-manual-efi-qemuvars-q35"); + DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-aarch64", "aarch64"); /* Make sure all combinations of ACPI and UEFI behave as expected */ DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-acpi-aarch64", "aarch64"); -- 2.52.0
This test case demonstrates how to manually configure an x86_64 guest to use the uefi-vars device, with the backing file for the NVRAM residing on a remote location accessed via NBD. It currently fails because the QEMU driver does not yet allow the use of JSON for NVRAM. That will change in a future commit. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...muvars-nvram-network-nbd.x86_64-latest.err | 1 + ...muvars-nvram-network-nbd.x86_64-latest.xml | 40 +++++++++++++++++++ ...-manual-efi-qemuvars-nvram-network-nbd.xml | 23 +++++++++++ tests/qemuxmlconftest.c | 1 + 4 files changed, 65 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.xml diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err new file mode 100644 index 0000000000..e5f67f8d09 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err @@ -0,0 +1 @@ +unsupported configuration: Unsupported nvram format 'json' diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml new file mode 100644 index 0000000000..14f2800174 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml @@ -0,0 +1,40 @@ +<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-q35-10.0'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram type='network' format='json'> + <source protocol='nbd' name='bar'> + <host name='example.org' port='6000'/> + </source> + </nvram> + <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-qemuvars-nvram-network-nbd.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.xml new file mode 100644 index 0000000000..202fe89815 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.xml @@ -0,0 +1,23 @@ +<domain type='qemu'> + <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-10.0'>hvm</type> + <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram format='json' type='network'> + <source protocol='nbd' name='bar'> + <host name='example.org' port='6000'/> + </source> + </nvram> + </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 fa768df1a2..ec3c53cf67 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1562,6 +1562,7 @@ mymain(void) DO_TEST_CAPS_LATEST_FAILURE("firmware-manual-efi-qemuvars-q35"); DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-aarch64", "aarch64"); + DO_TEST_CAPS_LATEST_FAILURE("firmware-manual-efi-qemuvars-nvram-network-nbd"); /* Make sure all combinations of ACPI and UEFI behave as expected */ DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-acpi-aarch64", "aarch64"); -- 2.52.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..e1b1417cbc --- /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-4.0'>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..e1b1417cbc --- /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-4.0'>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.xml b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.xml new file mode 100644 index 0000000000..4e075e560f --- /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-4.0'>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 ec3c53cf67..85c35af515 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1598,6 +1598,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.52.0
This test case demonstrates how to force libvirt to use the uefi-vars device for an x86_64 guest, despite that not being the default firmware build for the architecture at this point in time. It currently fails because the QEMU driver does not yet allow the use of JSON for NVRAM. 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 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> --- ...uto-efi-format-nvram-json.x86_64-8.2.0.err | 1 + ...uto-efi-format-nvram-json.x86_64-8.2.0.xml | 35 +++++++++++++++++++ ...to-efi-format-nvram-json.x86_64-latest.err | 1 + ...to-efi-format-nvram-json.x86_64-latest.xml | 35 +++++++++++++++++++ .../firmware-auto-efi-format-nvram-json.xml | 18 ++++++++++ tests/qemuxmlconftest.c | 2 ++ 6 files changed, 92 insertions(+) create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.xml diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err new file mode 100644 index 0000000000..e5f67f8d09 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err @@ -0,0 +1 @@ +unsupported configuration: Unsupported nvram format 'json' diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.xml b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.xml new file mode 100644 index 0000000000..cc7fdfad79 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.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='efi'> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <nvram format='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-auto-efi-format-nvram-json.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err new file mode 100644 index 0000000000..e5f67f8d09 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err @@ -0,0 +1 @@ +unsupported configuration: Unsupported nvram format 'json' diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.xml new file mode 100644 index 0000000000..cc7fdfad79 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.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='efi'> + <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> + <nvram format='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-auto-efi-format-nvram-json.xml b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.xml new file mode 100644 index 0000000000..8c7a268910 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.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> + <nvram format='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 85c35af515..a109ae99d6 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1630,6 +1630,8 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-format-nvramtemplate-qcow2"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-mismatch"); DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-format-mismatch-nvramtemplate"); + DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-format-nvram-json"); + DO_TEST_CAPS_VER_FAILURE("firmware-auto-efi-format-nvram-json", "8.2.0"); /* This test passes, but the outcome is not the desired one: the * generic edk2 build gets selected instead of the AMD SEV one */ -- 2.52.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_x86_64+mshv.xml | 1 + tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml | 1 + 10 files changed, 12 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 92b863a826..0d02032401 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -755,6 +755,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "disk-timed-stats", /* QEMU_CAPS_DISK_TIMED_STATS */ "query-accelerators", /* QEMU_CAPS_QUERY_ACCELERATORS */ "mshv", /* QEMU_CAPS_MSHV */ + "uefi-vars", /* QEMU_CAPS_DEVICE_UEFI_VARS */ ); @@ -1462,6 +1463,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-emulator", QEMU_CAPS_DEVICE_TPM_EMULATOR }, { "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH }, { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, + { "uefi-vars-x64", QEMU_CAPS_DEVICE_UEFI_VARS }, + { "uefi-vars-sysbus", QEMU_CAPS_DEVICE_UEFI_VARS }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index f180844e66..25e7fe68ca 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -730,6 +730,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_DISK_TIMED_STATS, /* timed stats support ('stats-intervals' property of disk frontends) */ QEMU_CAPS_QUERY_ACCELERATORS, /* query-accelerators command */ QEMU_CAPS_MSHV, /* -accel mshv */ + 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 90e8d868cc..a8ed9bf357 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -163,6 +163,7 @@ <flag name='nvme-ns'/> <flag name='usb-bot'/> <flag name='acpi-generic-initiator'/> + <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 cfce1c963d..fa3b480249 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -209,6 +209,7 @@ <flag name='amd-iommu'/> <flag name='usb-bot'/> <flag name='acpi-generic-initiator'/> + <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 f94c8388d6..922a38135b 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -209,6 +209,7 @@ <flag name='amd-iommu.pci-id'/> <flag name='usb-bot'/> <flag name='acpi-generic-initiator'/> + <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 8d59566cc0..1598b5c08a 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml @@ -140,6 +140,7 @@ <flag name='nvme-ns'/> <flag name='usb-bot'/> <flag name='qom-list-get'/> + <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 8e989a139f..d7951adfb9 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml @@ -191,6 +191,7 @@ <flag name='usb-bot'/> <flag name='tdx-guest'/> <flag name='acpi-generic-initiator'/> + <flag name='uefi-vars'/> <version>10000050</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.0.0-1724-gf9a3def17b</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml index 520a3d8ee8..0e407a9e3a 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml @@ -214,6 +214,7 @@ <flag name='tdx-guest'/> <flag name='qom-list-get'/> <flag name='acpi-generic-initiator'/> + <flag name='uefi-vars'/> <version>10001000</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.1.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 874fd7bddb..fe3ab5e5f8 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml @@ -201,6 +201,7 @@ <flag name='acpi-generic-initiator'/> <flag name='query-accelerators'/> <flag name='mshv'/> + <flag name='uefi-vars'/> <version>10001050</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.1.0-1778-ge090e0312d</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml index 7cff2c2291..2346bb4bbe 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml @@ -215,6 +215,7 @@ <flag name='acpi-generic-initiator'/> <flag name='disk-timed-stats'/> <flag name='query-accelerators'/> + <flag name='uefi-vars'/> <version>10001091</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.2.0-rc1-38-gfb241d0a1f</package> -- 2.52.0
The use of JSON format for NVRAM requires the uefi-vars device to be present. The firmware-auto-efi-format-nvram-json test case starts failing in a different way after this change. The new error message is the correct one. The variant of the firmware-auto-efi-enrolled-keys-aarch64 test case that is run against QEMU 8.2.0 does not see the same change, for now. That is because libvirt does not yet recognize that enabling Secure Boot on aarch64 requires using the uefi-vars device. After some upcoming changes, this test case will start behaving the same as the one mentioned above too. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_validate.c | 8 +++++ ...uto-efi-format-nvram-json.x86_64-8.2.0.err | 2 +- ...uto-efi-format-nvram-json.x86_64-8.2.0.xml | 35 ------------------- tests/qemuxmlconftest.c | 2 +- 4 files changed, 10 insertions(+), 37 deletions(-) delete mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.xml diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index da08fd17cd..40676bef39 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -728,6 +728,14 @@ qemuValidateDomainDefNvram(const virDomainDef *def, return -1; } + if (src->format == VIR_STORAGE_FILE_JSON) { + 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; + } + } + if (src->sliceStorage) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("slices are not supported with NVRAM")); diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err index e5f67f8d09..e64c2b21aa 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.err @@ -1 +1 @@ -unsupported configuration: Unsupported nvram format 'json' +unsupported configuration: The uefi-vars device is not supported by this QEMU binary diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.xml b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.xml deleted file mode 100644 index cc7fdfad79..0000000000 --- a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-8.2.0.xml +++ /dev/null @@ -1,35 +0,0 @@ -<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> - <nvram format='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/qemuxmlconftest.c b/tests/qemuxmlconftest.c index a109ae99d6..500cbbd45b 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1631,7 +1631,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-format-mismatch"); DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-format-mismatch-nvramtemplate"); DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-format-nvram-json"); - DO_TEST_CAPS_VER_FAILURE("firmware-auto-efi-format-nvram-json", "8.2.0"); + DO_TEST_CAPS_VER_PARSE_ERROR("firmware-auto-efi-format-nvram-json", "8.2.0"); /* This test passes, but the outcome is not the desired one: the * generic edk2 build gets selected instead of the AMD SEV one */ -- 2.52.0
JSON format NVRAM files are accessed through the uefi-vars QEMU device, and at least currently that only supports local files, so we need to forbid the use for remote locations for the format. The firmware-manual-efi-qemuvars-nvram-network-nbd test case starts failing earlier and with a different error message after this change. This is expected and desirable. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_validate.c | 5 +++ ...muvars-nvram-network-nbd.x86_64-latest.err | 2 +- ...muvars-nvram-network-nbd.x86_64-latest.xml | 40 ------------------- tests/qemuxmlconftest.c | 2 +- 4 files changed, 7 insertions(+), 42 deletions(-) delete mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 40676bef39..5ecf34f622 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -734,6 +734,11 @@ qemuValidateDomainDefNvram(const virDomainDef *def, _("The uefi-vars device is not supported by this QEMU binary")); return -1; } + if (!virStorageSourceIsLocalStorage(src)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Remote JSON files are not supported with NVRAM")); + return -1; + } } if (src->sliceStorage) { diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err index e5f67f8d09..424b06199a 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.err @@ -1 +1 @@ -unsupported configuration: Unsupported nvram format 'json' +unsupported configuration: Remote JSON files are not supported with NVRAM diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml deleted file mode 100644 index 14f2800174..0000000000 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-nvram-network-nbd.x86_64-latest.xml +++ /dev/null @@ -1,40 +0,0 @@ -<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-q35-10.0'>hvm</type> - <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> - <nvram type='network' format='json'> - <source protocol='nbd' name='bar'> - <host name='example.org' port='6000'/> - </source> - </nvram> - <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 500cbbd45b..4934afd02d 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1562,7 +1562,7 @@ mymain(void) DO_TEST_CAPS_LATEST_FAILURE("firmware-manual-efi-qemuvars-q35"); DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-aarch64", "aarch64"); - DO_TEST_CAPS_LATEST_FAILURE("firmware-manual-efi-qemuvars-nvram-network-nbd"); + DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-nvram-network-nbd"); /* Make sure all combinations of ACPI and UEFI behave as expected */ DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-acpi-aarch64", "aarch64"); -- 2.52.0
The file extension needs to match the format. In the case of JSON, we're ditching the _VARS part of the filename too. Having that in there made a lot of sense in the beginning, when OVMF_CODE.fd and OVMF_VARS.fd were used for the executable and NVRAM template respectively, and a similar pattern was used for AAVMF (aka edk2 on aarch64) as well. These days, the aarch64 build of edk2 has ditched the pattern, so the only remaining holdout is the x86_64 build; the uefi-vars build doesn't use _CODE and _VARS on any architecture. It's a good time to get rid of this vestigial part of the filename. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 962d6cdee7..0504eef727 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1073,7 +1073,7 @@ qemuFirmwareEnsureNVRAM(virDomainDef *def, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); virDomainLoaderDef *loader = def->os.loader; virStorageFileFormat nvramFormat = VIR_STORAGE_FILE_NONE; - const char *ext = NULL; + const char *suffix = NULL; if (!loader) return; @@ -1134,16 +1134,18 @@ qemuFirmwareEnsureNVRAM(virDomainDef *def, if (abiUpdate && loader->nvramTemplate && virStringHasSuffix(loader->nvramTemplate, ".raw")) - ext = ".raw"; + suffix = "_VARS.raw"; else - ext = ".fd"; + suffix = "_VARS.fd"; } if (loader->nvram->format == VIR_STORAGE_FILE_QCOW2) - ext = ".qcow2"; + suffix = "_VARS.qcow2"; + if (loader->nvram->format == VIR_STORAGE_FILE_JSON) + suffix = ".json"; - loader->nvram->path = g_strdup_printf("%s/%s_VARS%s", + loader->nvram->path = g_strdup_printf("%s/%s%s", cfg->nvramDir, def->name, - NULLSTR_EMPTY(ext)); + NULLSTR_EMPTY(suffix)); } -- 2.52.0
Now that NVRAM can be used together with ROM firmware builds, we need to update the matching logic so that it behaves correctly in all scenarios. This effectively involves taking the logic we currently use when matching firmware descriptors for pflash builds and replicating it pretty much verbatim. The only real difference is that read/write loaders can, by definition, never match. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 76 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 0504eef727..f56a4977cf 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1009,6 +1009,12 @@ qemuFirmwareMatchesPaths(const qemuFirmware *fw, if (loader && loader->path && !virFileComparePaths(loader->path, memory->executable.filename)) return false; + if (loader && loader->nvramTemplate) { + if (memory->mode != QEMU_FIRMWARE_MEMORY_MODE_SPLIT) + return false; + if (!virFileComparePaths(loader->nvramTemplate, memory->nvram_template.filename)) + return false; + } break; case QEMU_FIRMWARE_DEVICE_NONE: case QEMU_FIRMWARE_DEVICE_LAST: @@ -1457,32 +1463,88 @@ qemuFirmwareMatchDomain(const virDomainDef *def, } } } else if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_MEMORY) { + const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory; + 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 */ + if (loader && + loader->stateless == VIR_TRISTATE_BOOL_NO && + memory->mode == QEMU_FIRMWARE_MEMORY_MODE_STATELESS) { VIR_DEBUG("Discarding stateless loader"); return false; } + if (loader && + loader->stateless == VIR_TRISTATE_BOOL_YES && + memory->mode != QEMU_FIRMWARE_MEMORY_MODE_STATELESS) { + VIR_DEBUG("Discarding non-stateless loader"); + return false; + } if (loader && loader->readonly == VIR_TRISTATE_BOOL_NO) { VIR_DEBUG("Discarding readonly loader"); return false; } - if (loader && loader->nvram && - (loader->nvram->path || loader->nvram->format)) { - VIR_DEBUG("Discarding rom loader (nvram configured)"); + if (STRNEQ(memory->executable.format, "raw")) { + VIR_DEBUG("Discarding loader with unsupported executable format '%s'", + memory->executable.format); return false; } - if (loader && - (loader->nvramTemplate || loader->nvramTemplateFormat)) { - VIR_DEBUG("Discarding rom loader (nvram template configured)"); + if (loader && loader->format && + STRNEQ(memory->executable.format, virStorageFileFormatTypeToString(loader->format))) { + VIR_DEBUG("Discarding loader with mismatching executable format '%s' != '%s'", + memory->executable.format, + virStorageFileFormatTypeToString(loader->format)); return false; } + if (memory->mode == QEMU_FIRMWARE_MEMORY_MODE_SPLIT) { + if (STRNEQ(memory->nvram_template.format, "json")) { + VIR_DEBUG("Discarding loader with unsupported nvram template format '%s'", + memory->nvram_template.format); + return false; + } + if (loader && loader->nvramTemplateFormat && + STRNEQ(memory->nvram_template.format, virStorageFileFormatTypeToString(loader->nvramTemplateFormat))) { + VIR_DEBUG("Discarding loader with mismatching nvram template format '%s' != '%s'", + memory->nvram_template.format, + virStorageFileFormatTypeToString(loader->format)); + return false; + } + /* If nvram.format was specified and no other information + * that can influence firmware selection was, then treat it + * the same as if nvram.templateFormat had been specified. + * This ensures that <nvram format='foo'/> continues to work + * as a shorthand while not getting in the way otherwise */ + if (loader && loader->nvram && loader->nvram->format && + !loader->readonly && !loader->type && !loader->secure && + !loader->stateless && !loader->format && !loader->path && + !loader->nvramTemplateFormat && !loader->nvramTemplate && + STRNEQ(memory->nvram_template.format, virStorageFileFormatTypeToString(loader->nvram->format))) { + VIR_DEBUG("Discarding loader with mismatching nvram template format '%s' != '%s'", + memory->nvram_template.format, + virStorageFileFormatTypeToString(loader->nvram->format)); + return false; + } + } else { + if (loader && loader->nvram && + (loader->nvram->path || loader->nvram->format)) { + VIR_DEBUG("Discarding non split loader (nvram configured)"); + return false; + } + if (loader && + (loader->nvramTemplate || loader->nvramTemplateFormat)) { + VIR_DEBUG("Discarding non split loader (nvram template configured)"); + return false; + } + } } if (def->sec) { -- 2.52.0
NVRAM files in JSON format can only be used together with the uefi-vars QEMU device, and the firmware descriptor is required to advertise the host-uefi-vars feature in that case. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index f56a4977cf..ce90f95d0a 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1217,6 +1217,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def, bool supportsTDX = false; bool supportsSecureBoot = false; bool hasEnrolledKeys = false; + bool usesUefiVarsDevice = false; int reqSecureBoot; int reqEnrolledKeys; @@ -1305,6 +1306,9 @@ qemuFirmwareMatchDomain(const virDomainDef *def, break; case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS: + usesUefiVarsDevice = true; + break; + case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_NONE: @@ -1533,6 +1537,11 @@ qemuFirmwareMatchDomain(const virDomainDef *def, virStorageFileFormatTypeToString(loader->nvram->format)); return false; } + + if (!usesUefiVarsDevice) { + VIR_DEBUG("Discarding loader with nvram template format 'json' and no 'host-uefi-vars' feature"); + return false; + } } else { if (loader && loader->nvram && (loader->nvram->path || loader->nvram->format)) { -- 2.52.0
At this point, the QEMU driver is ready to correctly handle NVRAM files in JSON format, so we can lift the restriction that has existed until now. The firmware-manual-efi-qemuvars-q35 test case now passes, since all the necessary information was already provided in the domain XML and the driver actively rejecting use of JSON was the only thing getting in the way. The firmware-auto-efi-format-nvram-json test case still fails because there are still no firmware descriptors that match the requested configuration. That will change in a future commit. https://issues.redhat.com/browse/RHEL-82645 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_firmware.c | 3 +- ...to-efi-format-nvram-json.x86_64-latest.err | 2 +- ...manual-efi-qemuvars-q35.x86_64-latest.args | 34 +++++++++++++++++++ ...-manual-efi-qemuvars-q35.x86_64-latest.err | 1 - ...-manual-efi-qemuvars-q35.x86_64-latest.xml | 2 +- tests/qemuxmlconftest.c | 2 +- 6 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index ce90f95d0a..e45081eadb 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -2145,7 +2145,8 @@ qemuFirmwareFillDomain(virQEMUDriver *driver, loader->nvram && loader->nvram->format && loader->nvram->format != VIR_STORAGE_FILE_RAW && - loader->nvram->format != VIR_STORAGE_FILE_QCOW2) { + loader->nvram->format != VIR_STORAGE_FILE_QCOW2 && + loader->nvram->format != VIR_STORAGE_FILE_JSON) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported nvram format '%1$s'"), virStorageFileFormatTypeToString(loader->nvram->format)); diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err index e5f67f8d09..3edb2b3451 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err @@ -1 +1 @@ -unsupported configuration: Unsupported nvram format 'json' +operation failed: Unable to find 'efi' firmware that is compatible with the current configuration diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.args new file mode 100644 index 0000000000..ffc3d3c86d --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-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-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ +-accel tcg \ +-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-qemuvars-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err deleted file mode 100644 index e5f67f8d09..0000000000 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.err +++ /dev/null @@ -1 +0,0 @@ -unsupported configuration: Unsupported nvram format 'json' diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml index a16c404eaf..16cdac6c51 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml @@ -6,7 +6,7 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='x86_64' machine='pc-q35-10.0'>hvm</type> - <loader type='rom'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <loader type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> <nvram format='json'>/path/to/guest.json</nvram> <boot dev='hd'/> </os> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 4934afd02d..886e676d9e 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1560,7 +1560,7 @@ mymain(void) ARG_CAPS_VARIANT, "+inteltdx", ARG_END); - DO_TEST_CAPS_LATEST_FAILURE("firmware-manual-efi-qemuvars-q35"); + DO_TEST_CAPS_LATEST("firmware-manual-efi-qemuvars-q35"); DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-aarch64", "aarch64"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-nvram-network-nbd"); -- 2.52.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 and JSON format NVRAM templates. Several existing test cases are affected by this. The firmware-auto-efi-format-nvram-json test case can now succeed, since the only thing preventing it from doing so was that a suitable firmware build could not be found. The firmware-manual-efi-qemuvars-aarch64 test case also succeeds, because libvirt now picks a UEFI firmware for it and that satisfies the requirement for using ACPI on the architecture. Finally, the firmware-auto-efi-enrolled-keys-aarch64 test case succeeds in its default variant, but its QEMU 8.2.0 variant starts failing in a different way than before. Since libvirt now picks the firmware build that requires use of the uefi-vars QEMU device, and QEMU 8.2.0 is too old to have it, we get the corresponding error message. Note that the firmware-auto-efi-format-nvram-json test case, in its QEMU 8.2.0 variant, had already started failing with the very same error message several commits earlier. https://issues.redhat.com/browse/RHEL-82645 DONOTMERGE: The firmware descriptors have not been added to the Fedora edk2 package yet. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- ...70-edk2-ovmf-qemuvars-x64-sb-enrolled.json | 35 +++++++++++++++++++ .../70-edk2-qemuvars-aarch64-sb-enrolled.json | 33 +++++++++++++++++ tests/qemufirmwaretest.c | 10 ++++-- ...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-format-nvram-json.x86_64-latest.args | 34 ++++++++++++++++++ ...to-efi-format-nvram-json.x86_64-latest.err | 1 - ...to-efi-format-nvram-json.x86_64-latest.xml | 7 +++- ...l-efi-qemuvars-aarch64.aarch64-latest.args | 32 +++++++++++++++++ ...al-efi-qemuvars-aarch64.aarch64-latest.err | 1 - ...l-efi-qemuvars-aarch64.aarch64-latest.xml} | 11 ++++-- ...-manual-efi-qemuvars-q35.x86_64-latest.xml | 10 ++++-- tests/qemuxmlconftest.c | 8 ++--- 15 files changed, 202 insertions(+), 18 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/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-format-nvram-json.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.args delete mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.err rename tests/qemuxmlconfdata/{firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml => firmware-manual-efi-qemuvars-aarch64.aarch64-latest.xml} (64%) 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..991c4340f8 --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-ovmf-qemuvars-x64-sb-enrolled.json @@ -0,0 +1,35 @@ +{ + "description": "OVMF for qemuvars, SB enabled, MS certs enrolled", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "mode" : "split", + "executable": { + "filename": "/usr/share/edk2/ovmf/OVMF.qemuvars.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/edk2/ovmf/OVMF_VARS.qemuvars.json", + "format": "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..d03ff9e27b --- /dev/null +++ b/tests/qemufirmwaredata/usr/share/qemu/firmware/70-edk2-qemuvars-aarch64-sb-enrolled.json @@ -0,0 +1,33 @@ +{ + "description": "UEFI firmware for ARM64 virtual machines", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "memory", + "mode" : "split", + "executable": { + "filename": "/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/edk2/aarch64/vars-template-qemuvars.json", + "format": "json" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "enrolled-keys", + "secure-boot", + "host-uefi-vars" + ], + "tags": [ + ] +} diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c index a4fb5c9b9c..6a537981e8 100644 --- a/tests/qemufirmwaretest.c +++ b/tests/qemufirmwaretest.c @@ -101,6 +101,8 @@ testFWPrecedence(const void *opaque G_GNUC_UNUSED) SYSCONFDIR "/qemu/firmware/59-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/90-combined.json", PREFIX "/share/qemu/firmware/91-bios.json", PREFIX "/share/qemu/firmware/93-invalid.json", @@ -280,6 +282,8 @@ 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/90-combined.json"); DO_PARSE_TEST("usr/share/qemu/firmware/91-bios.json"); DO_PARSE_FAILURE_TEST("usr/share/qemu/firmware/93-invalid.json"); @@ -319,7 +323,8 @@ 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.qemuvars.json", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false, @@ -332,7 +337,8 @@ mymain(void) "/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-qemuvars.json", VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); DO_SUPPORTED_TEST("virt", VIR_ARCH_RISCV64, 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..d12949dbf2 --- /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-4.0,usb=off,gic-version=3,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 e1b1417cbc..46ba916116 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-4.0'>hvm</type> <firmware> <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> </firmware> - <loader format='raw'/> + <loader readonly='yes' type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <nvram template='/usr/share/edk2/aarch64/vars-template-qemuvars.json' templateFormat='json' format='json'>/var/lib/libvirt/qemu/nvram/guest.json</nvram> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.args new file mode 100644 index 0000000000..9a899c2a65 --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.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-format-nvram-json.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.err deleted file mode 100644 index 3edb2b3451..0000000000 --- a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.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-format-nvram-json.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.xml index cc7fdfad79..aaa4e37e7b 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.xml @@ -6,7 +6,12 @@ <vcpu placement='static'>1</vcpu> <os firmware='efi'> <type arch='x86_64' machine='pc-q35-8.2'>hvm</type> - <nvram format='json'/> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> + </firmware> + <loader readonly='yes' type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram template='/usr/share/edk2/ovmf/OVMF_VARS.qemuvars.json' templateFormat='json' format='json'>/var/lib/libvirt/qemu/nvram/guest.json</nvram> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.args new file mode 100644 index 0000000000..575ffdb42b --- /dev/null +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-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-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-4.0,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \ +-accel tcg \ +-cpu cortex-a15 \ +-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-qemuvars-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.err deleted file mode 100644 index 4fe79bdacf..0000000000 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-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-qemuvars-aarch64.aarch64-latest.xml similarity index 64% rename from tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml rename to tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.xml index e1b1417cbc..5d6d2dac9a 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-8.2.0.xml +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.xml @@ -1,4 +1,4 @@ -<domain type='kvm'> +<domain type='qemu'> <name>guest</name> <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid> <memory unit='KiB'>1048576</memory> @@ -8,14 +8,19 @@ <type arch='aarch64' machine='virt-4.0'>hvm</type> <firmware> <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> </firmware> - <loader format='raw'/> + <loader readonly='yes' type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader> + <nvram template='/usr/share/edk2/aarch64/vars-template-qemuvars.json' templateFormat='json' format='json'>/path/to/guest.json</nvram> <boot dev='hd'/> </os> <features> <acpi/> - <gic version='3'/> + <gic version='2'/> </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>cortex-a15</model> + </cpu> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml index 16cdac6c51..197530e5df 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-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-10.0'>hvm</type> - <loader type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> - <nvram format='json'>/path/to/guest.json</nvram> + <firmware> + <feature enabled='yes' name='enrolled-keys'/> + <feature enabled='yes' name='secure-boot'/> + </firmware> + <loader readonly='yes' type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.qemuvars.fd</loader> + <nvram template='/usr/share/edk2/ovmf/OVMF_VARS.qemuvars.json' templateFormat='json' format='json'>/path/to/guest.json</nvram> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 886e676d9e..e4d9fd2c07 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1561,7 +1561,7 @@ mymain(void) ARG_END); DO_TEST_CAPS_LATEST("firmware-manual-efi-qemuvars-q35"); - DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-aarch64", "aarch64"); + DO_TEST_CAPS_ARCH_LATEST("firmware-manual-efi-qemuvars-aarch64", "aarch64"); DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-efi-qemuvars-nvram-network-nbd"); /* Make sure all combinations of ACPI and UEFI behave as expected */ @@ -1598,8 +1598,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"); @@ -1630,7 +1630,7 @@ mymain(void) DO_TEST_CAPS_LATEST("firmware-auto-efi-format-nvramtemplate-qcow2"); DO_TEST_CAPS_LATEST("firmware-auto-efi-format-mismatch"); DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-format-mismatch-nvramtemplate"); - DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-format-nvram-json"); + DO_TEST_CAPS_LATEST("firmware-auto-efi-format-nvram-json"); DO_TEST_CAPS_VER_PARSE_ERROR("firmware-auto-efi-format-nvram-json", "8.2.0"); /* This test passes, but the outcome is not the desired one: the -- 2.52.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 | 36 +++++++++++++++++++ ...-enrolled-keys-aarch64.aarch64-latest.args | 1 + ...o-efi-format-nvram-json.x86_64-latest.args | 1 + ...l-efi-qemuvars-aarch64.aarch64-latest.args | 1 + ...manual-efi-qemuvars-q35.x86_64-latest.args | 1 + 5 files changed, 40 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 98229d7cf9..2e98710548 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9731,6 +9731,39 @@ qemuBuildDomainLoaderCommandLine(virCommand *cmd, } +static int +qemuBuildUefiVarsCommandLine(virCommand *cmd, + const virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + virDomainLoaderDef *loader = def->os.loader; + g_autoptr(virJSONValue) props = NULL; + const char *model = NULL; + + if (!loader || !loader->nvram) + return 0; + + if (loader->nvram->format != VIR_STORAGE_FILE_JSON) + 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", loader->nvram->path, + NULL) < 0) + return -1; + + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) < 0) + return -1; + + return 0; +} + + static int qemuBuildTPMDevCmd(virCommand *cmd, const virDomainDef *def, @@ -10805,6 +10838,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 d12949dbf2..de5745ddd4 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-4.0,usb=off,gic-version=3,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/nvram/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-format-nvram-json.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.args index 9a899c2a65..1ff6a45599 100644 --- a/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-nvram-json.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/nvram/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-qemuvars-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.args index 575ffdb42b..8c780f7f78 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.args +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-aarch64.aarch64-latest.args @@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -accel tcg \ -cpu cortex-a15 \ -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-qemuvars-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.args index ffc3d3c86d..10eab01ef8 100644 --- a/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.args +++ b/tests/qemuxmlconfdata/firmware-manual-efi-qemuvars-q35.x86_64-latest.args @@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ -accel tcg \ -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.52.0
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- NEWS.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 6ca49a4c1b..f4915cd8d9 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -17,6 +17,16 @@ v12.0.0 (unreleased) * **New features** + * qemu: Add support for uefi-vars device and firmware builds using it + + This is particularly noteworthy for people running aarch64 VMs, as it makes + it finally possible to use Secure Boot on the architecture. + + 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. + * **Improvements** * qemu: Improvements and fixes to firmware selection -- 2.52.0
On 12/29/25 00:40, Andrea Bolognani via Devel wrote:
This series makes it possible to use Secure Boot with aarch64 VMs.
https://issues.redhat.com/browse/RHEL-82645
It needs a prerequisite series[1] to be applied first.
Note that, while I consider the entire series to be ready for review, there are two patches that are marked as DONOTMERGE: that's because they respectively implement support for a JSON firmware descriptor syntax extension that has not yet been approved, and import into the tree firmware descriptor that are not yet part of the Fedora edk2 package. The latter depends on the former, of course, for which patches have been posted[2] to the QEMU mailing list.
[1] https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/N2ETT... [2] https://mail.gnu.org/archive/html/qemu-devel/2025-12/msg03462.html
Andrea Bolognani (29): schemas: Drop pflashFormat schemas: Introduce firmware(Loader|Nvram)Formats schemas: Allow JSON format for NVRAM conf: Introduce VIR_STORAGE_FILE_JSON conf: Allow JSON format for NVRAM in the parser qemu_firmware: Rename qemuFirmwareFlashFile to qemuFirmwareFile qemu_firmware: Use qemuFirmwareFile in qemuFirmwareMappingMemory DONOTMERGE: qemu_firmware: Support extended syntax for ROM firmware descriptors qemu_firmware: Report NVRAM template path for ROMs qemu_firmware: Fill in more information for ROMs qemu_firmware: Don't skip EnsureNVRAM() for ROMs qemu_firmware: Parse host-uefi-vars firmware feature qemu_firmware: Split sanity check qemu_firmware: Consider host-uefi-vars feature in sanity check tests: Add firmware-manual-efi-qemuvars-q35 tests: Add firmware-manual-efi-qemuvars-aarch64 tests: Add firmware-manual-efi-qemuvars-nvram-network-nbd tests: Add firmware-auto-efi-enrolled-keys-aarch64 tests: Add firmware-auto-efi-format-nvram-json qemu_capabilities: Introduce QEMU_CAPS_DEVICE_UEFI_VARS qemu: Validate presence of uefi-vars device qemu: Don't allow remote locations for JSON format NVRAM qemu_firmware: Generate correct name for JSON format NVRAM qemu_firmware: Update matching logic for ROMs qemu_firmware: Require host-uefi-vars feature for JSON NVRAM qemu_firmware: Allow JSON format for NVRAM DONOTMERGE: tests: Add firmware descriptors for uefi-vars builds qemu_command: Use uefi-vars device where appropriate news: Document support for uefi-vars device and firmwares
52 files changed, 824 insertions(+), 111 deletions(-)
Once QEMU part is merged then you have my: Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (3)
-
Andrea Bolognani -
Daniel P. Berrangé -
Michal Prívozník