Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
libvirt
32b9d8b0-qemu-support-fw-descriptor-mode.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 32b9d8b0-qemu-support-fw-descriptor-mode.patch of Package libvirt
commit 32b9d8b0ae00669555f01f91ee11612a636c4b69 Author: Daniel P. Berrangé <berrange@redhat.com> Date: Thu Feb 3 13:43:18 2022 +0000 qemu: support firmware descriptor flash 'mode' for optional NVRAM Currently the 'nvram_template' entry is mandatory when parsing the firmware descriptor based on flash. QEMU is extending the firmware descriptor spec to make the 'nvram_template' optional, depending on the value of a new 'mode' field: - "split" * "executable" contains read-only CODE * "nvram_template" contains read-write VARS - "combined" * "executable" contains read-write CODE and VARs * "nvram_template" not present - "stateless" * "executable" contains read-only CODE and VARs * "nvram_template" not present In the latter case, the guest OS can write vars but the firmware will make no attempt to persist them, so any changes will be lost at poweroff. For now we parse this new 'mode' but discard any firmware which is not 'mode=split' when matching for a domain. In the tests we have a mixture of files with and without the mode attribute. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Index: libvirt-8.0.0/src/qemu/qemu_firmware.c =================================================================== --- libvirt-8.0.0.orig/src/qemu/qemu_firmware.c +++ libvirt-8.0.0/src/qemu/qemu_firmware.c @@ -59,6 +59,22 @@ VIR_ENUM_IMPL(qemuFirmwareOSInterface, ); +typedef enum { + QEMU_FIRMWARE_FLASH_MODE_SPLIT, + QEMU_FIRMWARE_FLASH_MODE_COMBINED, + QEMU_FIRMWARE_FLASH_MODE_STATELESS, + + QEMU_FIRMWARE_FLASH_MODE_LAST, +} qemuFirmwareFlashMode; + +VIR_ENUM_DECL(qemuFirmwareFlashMode); +VIR_ENUM_IMPL(qemuFirmwareFlashMode, + QEMU_FIRMWARE_FLASH_MODE_LAST, + "split", + "combined", + "stateless", +); + typedef struct _qemuFirmwareFlashFile qemuFirmwareFlashFile; struct _qemuFirmwareFlashFile { char *filename; @@ -68,6 +84,7 @@ struct _qemuFirmwareFlashFile { typedef struct _qemuFirmwareMappingFlash qemuFirmwareMappingFlash; struct _qemuFirmwareMappingFlash { + qemuFirmwareFlashMode mode; qemuFirmwareFlashFile executable; qemuFirmwareFlashFile nvram_template; }; @@ -359,9 +376,31 @@ qemuFirmwareMappingFlashParse(const char virJSONValue *doc, qemuFirmwareMappingFlash *flash) { + virJSONValue *mode; virJSONValue *executable; virJSONValue *nvram_template; + if (!(mode = virJSONValueObjectGet(doc, "mode"))) { + /* Historical default */ + flash->mode = QEMU_FIRMWARE_FLASH_MODE_SPLIT; + } else { + const char *modestr = virJSONValueGetString(mode); + int modeval; + if (!modestr) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Firmware flash mode value was malformed")); + return -1; + } + modeval = qemuFirmwareFlashModeTypeFromString(modestr); + if (modeval < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Firmware flash mode value '%s' unexpected"), + modestr); + return -1; + } + flash->mode = modeval; + } + if (!(executable = virJSONValueObjectGet(doc, "executable"))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("missing 'executable' in '%s'"), @@ -372,15 +411,17 @@ qemuFirmwareMappingFlashParse(const char if (qemuFirmwareFlashFileParse(path, executable, &flash->executable) < 0) return -1; - if (!(nvram_template = virJSONValueObjectGet(doc, "nvram-template"))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("missing 'nvram-template' in '%s'"), - path); - return -1; - } + if (flash->mode == QEMU_FIRMWARE_FLASH_MODE_SPLIT) { + if (!(nvram_template = virJSONValueObjectGet(doc, "nvram-template"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing 'nvram-template' in '%s'"), + path); + return -1; + } - if (qemuFirmwareFlashFileParse(path, nvram_template, &flash->nvram_template) < 0) - return -1; + if (qemuFirmwareFlashFileParse(path, nvram_template, &flash->nvram_template) < 0) + return -1; + } return 0; } @@ -693,10 +734,12 @@ qemuFirmwareMappingFlashFormat(virJSONVa g_autoptr(virJSONValue) executable = NULL; g_autoptr(virJSONValue) nvram_template = NULL; - if (!(executable = qemuFirmwareFlashFileFormat(flash->executable))) + if (virJSONValueObjectAppendString(mapping, + "mode", + qemuFirmwareFlashModeTypeToString(flash->mode)) < 0) return -1; - if (!(nvram_template = qemuFirmwareFlashFileFormat(flash->nvram_template))) + if (!(executable = qemuFirmwareFlashFileFormat(flash->executable))) return -1; if (virJSONValueObjectAppend(mapping, @@ -704,11 +747,15 @@ qemuFirmwareMappingFlashFormat(virJSONVa &executable) < 0) return -1; + if (flash->mode == QEMU_FIRMWARE_FLASH_MODE_SPLIT) { + if (!(nvram_template = qemuFirmwareFlashFileFormat(flash->nvram_template))) + return -1; - if (virJSONValueObjectAppend(mapping, + if (virJSONValueObjectAppend(mapping, "nvram-template", - &nvram_template) < 0) - return -1; + &nvram_template) < 0) + return -1; + } return 0; } @@ -1053,6 +1100,12 @@ qemuFirmwareMatchDomain(const virDomainD return false; } + if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_FLASH && + fw->mapping.data.flash.mode != QEMU_FIRMWARE_FLASH_MODE_SPLIT) { + VIR_DEBUG("Discarding loader without split flash"); + return false; + } + if (def->sec) { switch ((virDomainLaunchSecurity) def->sec->sectype) { case VIR_DOMAIN_LAUNCH_SECURITY_SEV: Index: libvirt-8.0.0/tests/qemufirmwaredata/out/usr/share/qemu/firmware/50-ovmf-sb-keys.json =================================================================== --- /dev/null +++ libvirt-8.0.0/tests/qemufirmwaredata/out/usr/share/qemu/firmware/50-ovmf-sb-keys.json @@ -0,0 +1,33 @@ +{ + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "mode": "split", + "executable": { + "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/OVMF/OVMF_VARS.secboot.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "enrolled-keys", + "requires-smm", + "secure-boot", + "verbose-dynamic" + ] +} Index: libvirt-8.0.0/tests/qemufirmwaredata/out/usr/share/qemu/firmware/61-ovmf.json =================================================================== --- /dev/null +++ libvirt-8.0.0/tests/qemufirmwaredata/out/usr/share/qemu/firmware/61-ovmf.json @@ -0,0 +1,31 @@ +{ + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "mode": "split", + "executable": { + "filename": "/usr/share/OVMF/OVMF_CODE.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/OVMF/OVMF_VARS.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-i440fx-*", + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "verbose-dynamic" + ] +} Index: libvirt-8.0.0/tests/qemufirmwaredata/out/usr/share/qemu/firmware/70-aavmf.json =================================================================== --- /dev/null +++ libvirt-8.0.0/tests/qemufirmwaredata/out/usr/share/qemu/firmware/70-aavmf.json @@ -0,0 +1,28 @@ +{ + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "mode": "split", + "executable": { + "filename": "/usr/share/AAVMF/AAVMF_CODE.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/AAVMF/AAVMF_VARS.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + + ] +} Index: libvirt-8.0.0/tests/qemufirmwaredata/usr/share/qemu/firmware/45-ovmf-sev-stateless.json =================================================================== --- /dev/null +++ libvirt-8.0.0/tests/qemufirmwaredata/usr/share/qemu/firmware/45-ovmf-sev-stateless.json @@ -0,0 +1,31 @@ +{ + "description": "OVMF for x86_64, with SEV, without SB, without SMM, with NO varstore", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "mode": "stateless", + "executable": { + "filename": "/usr/share/OVMF/OVMF.sev.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "amd-sev-es", + "verbose-dynamic" + ], + "tags": [ + + ] +} Index: libvirt-8.0.0/tests/qemufirmwaredata/usr/share/qemu/firmware/55-ovmf-sb-combined.json =================================================================== --- /dev/null +++ libvirt-8.0.0/tests/qemufirmwaredata/usr/share/qemu/firmware/55-ovmf-sb-combined.json @@ -0,0 +1,33 @@ +{ + "description": "OVMF with SB+SMM, SB enabled, MS certs enrolled", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "mode": "combined", + "executable": { + "filename": "/usr/share/OVMF/OVMF.secboot.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "enrolled-keys", + "requires-smm", + "secure-boot", + "verbose-dynamic" + ], + "tags": [ + + ] +} Index: libvirt-8.0.0/tests/qemufirmwaredata/usr/share/qemu/firmware/60-ovmf-sb.json =================================================================== --- libvirt-8.0.0.orig/tests/qemufirmwaredata/usr/share/qemu/firmware/60-ovmf-sb.json +++ libvirt-8.0.0/tests/qemufirmwaredata/usr/share/qemu/firmware/60-ovmf-sb.json @@ -5,6 +5,7 @@ ], "mapping": { "device": "flash", + "mode": "split", "executable": { "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd", "format": "raw" Index: libvirt-8.0.0/tests/qemufirmwaretest.c =================================================================== --- libvirt-8.0.0.orig/tests/qemufirmwaretest.c +++ libvirt-8.0.0/tests/qemufirmwaretest.c @@ -17,22 +17,31 @@ static int testParseFormatFW(const void *opaque) { const char *filename = opaque; - g_autofree char *path = NULL; + g_autofree char *inpath = NULL; + g_autofree char *outpath = NULL; g_autoptr(qemuFirmware) fw = NULL; - g_autofree char *buf = NULL; g_autoptr(virJSONValue) json = NULL; g_autofree char *expected = NULL; g_autofree char *actual = NULL; + g_autofree char *buf = NULL; - path = g_strdup_printf("%s/qemufirmwaredata/%s", abs_srcdir, filename); + inpath = g_strdup_printf("%s/qemufirmwaredata/%s", abs_srcdir, filename); + outpath = g_strdup_printf("%s/qemufirmwaredata/out/%s", abs_srcdir, filename); - if (!(fw = qemuFirmwareParse(path))) + if (!(fw = qemuFirmwareParse(inpath))) return -1; - if (virFileReadAll(path, - 1024 * 1024, /* 1MiB */ - &buf) < 0) - return -1; + if (virFileExists(outpath)) { + if (virFileReadAll(outpath, + 1024 * 1024, /* 1MiB */ + &buf) < 0) + return -1; + } else { + if (virFileReadAll(inpath, + 1024 * 1024, /* 1MiB */ + &buf) < 0) + return -1; + } if (!(json = virJSONValueFromString(buf))) return -1; @@ -60,7 +69,9 @@ testFWPrecedence(const void *opaque G_GN const char *expected[] = { PREFIX "/share/qemu/firmware/40-bios.json", SYSCONFDIR "/qemu/firmware/40-ovmf-sb-keys.json", + PREFIX "/share/qemu/firmware/45-ovmf-sev-stateless.json", PREFIX "/share/qemu/firmware/50-ovmf-sb-keys.json", + PREFIX "/share/qemu/firmware/55-ovmf-sb-combined.json", PREFIX "/share/qemu/firmware/61-ovmf.json", PREFIX "/share/qemu/firmware/70-aavmf.json", NULL @@ -218,7 +229,9 @@ mymain(void) } while (0) DO_PARSE_TEST("usr/share/qemu/firmware/40-bios.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/45-ovmf-sev-stateless.json"); DO_PARSE_TEST("usr/share/qemu/firmware/50-ovmf-sb-keys.json"); + DO_PARSE_TEST("usr/share/qemu/firmware/55-ovmf-sb-combined.json"); DO_PARSE_TEST("usr/share/qemu/firmware/60-ovmf-sb.json"); DO_PARSE_TEST("usr/share/qemu/firmware/61-ovmf.json"); DO_PARSE_TEST("usr/share/qemu/firmware/70-aavmf.json"); @@ -250,6 +263,8 @@ mymain(void) DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64, true, "/usr/share/seabios/bios-256k.bin:NULL:" "/usr/share/OVMF/OVMF_CODE.secboot.fd:/usr/share/OVMF/OVMF_VARS.secboot.fd:" + "/usr/share/OVMF/OVMF.sev.fd:NULL:" + "/usr/share/OVMF/OVMF.secboot.fd:NULL:" "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd", VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor