);
+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;
typedef struct _qemuFirmwareMappingFlash qemuFirmwareMappingFlash;
struct _qemuFirmwareMappingFlash {
+ qemuFirmwareFlashMode mode;
qemuFirmwareFlashFile executable;
qemuFirmwareFlashFile nvram_template;
};
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'"),
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;
}
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,
&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;
}
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:
--- /dev/null
+{
+ "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"
+ ]
+}
--- /dev/null
+{
+ "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"
+ ]
+}
--- /dev/null
+{
+ "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": [
+
+ ]
+}
--- /dev/null
+{
+ "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": [
+
+ ]
+}
--- /dev/null
+{
+ "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": [
+
+ ]
+}
],
"mapping": {
"device": "flash",
+ "mode": "split",
"executable": {
"filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd",
"format": "raw"
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;
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
} 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");
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);