Add a firmware descriptor support for TDVF, then libvirt can
auto match TDVF fimware with td-guest.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan(a)intel.com>
---
docs/schemas/domaincommon.rng | 1 +
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_firmware.c | 101 +++++++++++++++++++++++++++++++++-
src/qemu/qemu_validate.c | 7 +++
4 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9d0b51ee12..8232025bf7 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -275,6 +275,7 @@
<choice>
<value>bios</value>
<value>efi</value>
+ <value>generic</value>
</choice>
</attribute>
</optional>
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index d3c30a17e7..a01d4c26db 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -5934,6 +5934,8 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os,
VIR_DOMAIN_CAPS_ENUM_SET(os->firmware, VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS);
if (autoFirmwares & (1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI))
VIR_DOMAIN_CAPS_ENUM_SET(os->firmware, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
+ if (autoFirmwares & (1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC))
+ VIR_DOMAIN_CAPS_ENUM_SET(os->firmware, VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC);
if (virQEMUCapsFillDomainLoaderCaps(capsLoader, secure,
firmwaresAlt ? firmwaresAlt : firmwares,
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index e144b36f94..28e006eb82 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -84,12 +84,18 @@ struct _qemuFirmwareMappingMemory {
char *filename;
};
+typedef struct _qemuFirmwareMappingGeneric qemuFirmwareMappingGeneric;
+struct _qemuFirmwareMappingGeneric {
+ char *filename;
+};
+
typedef enum {
QEMU_FIRMWARE_DEVICE_NONE = 0,
QEMU_FIRMWARE_DEVICE_FLASH,
QEMU_FIRMWARE_DEVICE_KERNEL,
QEMU_FIRMWARE_DEVICE_MEMORY,
+ QEMU_FIRMWARE_DEVICE_GENERIC,
QEMU_FIRMWARE_DEVICE_LAST
} qemuFirmwareDevice;
@@ -101,6 +107,7 @@ VIR_ENUM_IMPL(qemuFirmwareDevice,
"flash",
"kernel",
"memory",
+ "generic",
);
@@ -112,6 +119,7 @@ struct _qemuFirmwareMapping {
qemuFirmwareMappingFlash flash;
qemuFirmwareMappingKernel kernel;
qemuFirmwareMappingMemory memory;
+ qemuFirmwareMappingGeneric generic;
} data;
};
@@ -135,6 +143,7 @@ typedef enum {
QEMU_FIRMWARE_FEATURE_SECURE_BOOT,
QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC,
QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC,
+ QEMU_FIRMWARE_FEATURE_INTEL_TDX,
QEMU_FIRMWARE_FEATURE_LAST
} qemuFirmwareFeature;
@@ -151,7 +160,8 @@ VIR_ENUM_IMPL(qemuFirmwareFeature,
"requires-smm",
"secure-boot",
"verbose-dynamic",
- "verbose-static"
+ "verbose-static",
+ "intel-tdx"
);
@@ -213,6 +223,13 @@ qemuFirmwareMappingMemoryFreeContent(qemuFirmwareMappingMemory
*memory)
}
+static void
+qemuFirmwareMappingGenericFreeContent(qemuFirmwareMappingGeneric *generic)
+{
+ g_free(generic->filename);
+}
+
+
static void
qemuFirmwareMappingFreeContent(qemuFirmwareMapping *mapping)
{
@@ -226,6 +243,9 @@ qemuFirmwareMappingFreeContent(qemuFirmwareMapping *mapping)
case QEMU_FIRMWARE_DEVICE_MEMORY:
qemuFirmwareMappingMemoryFreeContent(&mapping->data.memory);
break;
+ case QEMU_FIRMWARE_DEVICE_GENERIC:
+ qemuFirmwareMappingGenericFreeContent(&mapping->data.generic);
+ break;
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
break;
@@ -424,6 +444,25 @@ qemuFirmwareMappingMemoryParse(const char *path,
}
+static int
+qemuFirmwareMappingGenericParse(const char *path,
+ virJSONValue *doc,
+ qemuFirmwareMappingGeneric *generic)
+{
+ const char *filename;
+
+ if (!(filename = virJSONValueObjectGetString(doc, "filename"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("missing 'filename' in '%s'"),
+ path);
+ }
+
+ generic->filename = g_strdup(filename);
+
+ return 0;
+}
+
+
static int
qemuFirmwareMappingParse(const char *path,
virJSONValue *doc,
@@ -469,6 +508,10 @@ qemuFirmwareMappingParse(const char *path,
if (qemuFirmwareMappingMemoryParse(path, mapping,
&fw->mapping.data.memory) < 0)
return -1;
break;
+ case QEMU_FIRMWARE_DEVICE_GENERIC:
+ if (qemuFirmwareMappingGenericParse(path, mapping,
&fw->mapping.data.generic) < 0)
+ return -1;
+ break;
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
@@ -740,6 +783,19 @@ qemuFirmwareMappingMemoryFormat(virJSONValue *mapping,
}
+static int
+qemuFirmwareMappingGenericFormat(virJSONValue *mapping,
+ qemuFirmwareMappingGeneric *generic)
+{
+ if (virJSONValueObjectAppendString(mapping,
+ "filename",
+ generic->filename) < 0)
+ return -1;
+
+ return 0;
+}
+
+
static int
qemuFirmwareMappingFormat(virJSONValue *doc,
qemuFirmware *fw)
@@ -764,6 +820,10 @@ qemuFirmwareMappingFormat(virJSONValue *doc,
if (qemuFirmwareMappingMemoryFormat(mapping, &fw->mapping.data.memory)
< 0)
return -1;
break;
+ case QEMU_FIRMWARE_DEVICE_GENERIC:
+ if (qemuFirmwareMappingGenericFormat(mapping, &fw->mapping.data.generic)
< 0)
+ return -1;
+ break;
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
@@ -905,6 +965,7 @@ qemuFirmwareOSInterfaceTypeFromOsDefFirmware(int fw)
case VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS:
return QEMU_FIRMWARE_OS_INTERFACE_BIOS;
case VIR_DOMAIN_OS_DEF_FIRMWARE_EFI:
+ case VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC:
return QEMU_FIRMWARE_OS_INTERFACE_UEFI;
case VIR_DOMAIN_OS_DEF_FIRMWARE_NONE:
case VIR_DOMAIN_OS_DEF_FIRMWARE_LAST:
@@ -932,6 +993,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
bool supportsSEVES = false;
bool supportsSecureBoot = false;
bool hasEnrolledKeys = false;
+ bool supportsTDX = false;
int reqSecureBoot;
int reqEnrolledKeys;
@@ -995,6 +1057,10 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
hasEnrolledKeys = true;
break;
+ case QEMU_FIRMWARE_FEATURE_INTEL_TDX:
+ supportsTDX = true;
+ break;
+
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
case QEMU_FIRMWARE_FEATURE_NONE:
@@ -1069,8 +1135,14 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
return false;
}
break;
- case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
+ if (!supportsTDX) {
+ VIR_DEBUG("Domain requires TDX, firmware '%s' doesn't
support it",
+ path);
+ return false;
+ }
+ break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
@@ -1093,6 +1165,7 @@ qemuFirmwareEnableFeatures(virQEMUDriver *driver,
const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
const qemuFirmwareMappingKernel *kernel = &fw->mapping.data.kernel;
const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
+ const qemuFirmwareMappingGeneric *generic = &fw->mapping.data.generic;
size_t i;
switch (fw->mapping.device) {
@@ -1149,6 +1222,17 @@ qemuFirmwareEnableFeatures(virQEMUDriver *driver,
def->os.loader->path);
break;
+ case QEMU_FIRMWARE_DEVICE_GENERIC:
+ if (!def->os.loader)
+ def->os.loader = g_new0(virDomainLoaderDef, 1);
+
+ def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_GENERIC;
+ def->os.loader->path = g_strdup(generic->filename);
+
+ VIR_DEBUG("decided on loader '%s'",
+ def->os.loader->path);
+ break;
+
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
break;
@@ -1183,6 +1267,7 @@ qemuFirmwareEnableFeatures(virQEMUDriver *driver,
case QEMU_FIRMWARE_FEATURE_SECURE_BOOT:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
+ case QEMU_FIRMWARE_FEATURE_INTEL_TDX:
case QEMU_FIRMWARE_FEATURE_LAST:
break;
}
@@ -1216,6 +1301,7 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw,
case QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
+ case QEMU_FIRMWARE_FEATURE_INTEL_TDX:
case QEMU_FIRMWARE_FEATURE_LAST:
break;
}
@@ -1411,6 +1497,7 @@ qemuFirmwareGetSupported(const char *machine,
qemuFirmware *fw = firmwares[i];
const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
+ const qemuFirmwareMappingGeneric *generic = &fw->mapping.data.generic;
const char *fwpath = NULL;
const char *nvrampath = NULL;
size_t j;
@@ -1421,7 +1508,10 @@ qemuFirmwareGetSupported(const char *machine,
for (j = 0; j < fw->ninterfaces; j++) {
switch (fw->interfaces[j]) {
case QEMU_FIRMWARE_OS_INTERFACE_UEFI:
- *supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI;
+ if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_GENERIC)
+ *supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC;
+ else
+ *supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI;
break;
case QEMU_FIRMWARE_OS_INTERFACE_BIOS:
*supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS;
@@ -1449,6 +1539,7 @@ qemuFirmwareGetSupported(const char *machine,
case QEMU_FIRMWARE_FEATURE_SECURE_BOOT:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
+ case QEMU_FIRMWARE_FEATURE_INTEL_TDX:
case QEMU_FIRMWARE_FEATURE_LAST:
break;
}
@@ -1464,6 +1555,10 @@ qemuFirmwareGetSupported(const char *machine,
fwpath = memory->filename;
break;
+ case QEMU_FIRMWARE_DEVICE_GENERIC:
+ fwpath = generic->filename;
+ break;
+
case QEMU_FIRMWARE_DEVICE_KERNEL:
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 2cb05dc5b2..ca507868ad 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1254,6 +1254,13 @@ qemuValidateDomainDef(const virDomainDef *def,
_("INTEL TDX launch security needs split kernel
irqchip"));
return -1;
}
+ if ((!def->os.loader ||
+ def->os.loader->type != VIR_DOMAIN_LOADER_TYPE_GENERIC) &&
+ def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("INTEL TDX launch security needs generic loader
type"));
+ return -1;
+ }
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
break;
--
2.25.1