}
}
+static virDomainTPMDef *
+virDomainTPMDefNew(virDomainXMLOption *xmlopt)
+{
+ virDomainTPMDef *def;
+
+ def = g_new0(virDomainTPMDef, 1);
+
+ if (xmlopt && xmlopt->privateData.tpmNew &&
+ !(def->privateData = xmlopt->privateData.tpmNew())) {
+ VIR_FREE(def);
+ return NULL;
+ }
+
+ return def;
+}
+
void virDomainTPMDefFree(virDomainTPMDef *def)
{
if (!def)
}
virDomainDeviceInfoClear(&def->info);
+ virObjectUnref(def->privateData);
g_free(def);
}
g_autofree xmlNodePtr *nodes = NULL;
int bank;
- def = g_new0(virDomainTPMDef, 1);
+ if (!(def = virDomainTPMDefNew(xmlopt)))
+ return NULL;
if (virXMLPropEnum(node, "model",
virDomainTPMModelTypeFromString,
if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
goto error;
+ if (flags & VIR_DOMAIN_DEF_PARSE_STATUS &&
+ xmlopt && xmlopt->privateData.tpmParse) {
+ if ((ctxt->node = virXPathNode("./privateData", ctxt))) {
+ if (xmlopt->privateData.tpmParse(ctxt, def) < 0)
+ goto error;
+ }
+ }
+
return def;
error:
return 0;
}
-static void
+static int
+virDomainTPMDefFormatPrivateData(virBuffer *buf,
+ const virDomainTPMDef *tpm,
+ unsigned int flags,
+ virDomainXMLOption *xmlopt)
+{
+ g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
+
+ if (!(flags & VIR_DOMAIN_DEF_FORMAT_STATUS) ||
+ !xmlopt ||
+ !xmlopt->privateData.tpmFormat)
+ return 0;
+
+ if (xmlopt->privateData.tpmFormat(tpm, &childBuf) < 0)
+ return -1;
+
+ virXMLFormatElement(buf, "privateData", NULL, &childBuf);
+ return 0;
+}
+
+
+static int
virDomainTPMDefFormat(virBuffer *buf,
const virDomainTPMDef *def,
- unsigned int flags)
+ unsigned int flags,
+ virDomainXMLOption *xmlopt)
{
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
virXMLFormatElement(&childBuf, "backend", &backendAttrBuf, &backendChildBuf);
virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
+ if (virDomainTPMDefFormatPrivateData(&childBuf, def, flags, xmlopt) < 0)
+ return -1;
virXMLFormatElement(buf, "tpm", &attrBuf, &childBuf);
+
+ return 0;
}
}
for (n = 0; n < def->ntpms; n++) {
- virDomainTPMDefFormat(buf, def->tpms[n], flags);
+ if (virDomainTPMDefFormat(buf, def->tpms[n], flags, xmlopt) < 0)
+ return -1;
}
for (n = 0; n < def->ngraphics; n++) {
rc = virDomainChrDefFormat(&buf, src->data.chr, flags);
break;
case VIR_DOMAIN_DEVICE_TPM:
- virDomainTPMDefFormat(&buf, src->data.tpm, flags);
+ virDomainTPMDefFormat(&buf, src->data.tpm, flags, xmlopt);
rc = 0;
break;
case VIR_DOMAIN_DEVICE_PANIC:
#define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0"
struct _virDomainTPMDef {
+ virObject *privateData;
+
virDomainTPMModel model;
virDomainTPMBackendType type;
virDomainDeviceInfo info;
typedef int (*virDomainXMLPrivateDataStorageSourceFormatFunc)(virStorageSource *src,
virBuffer *buf);
+typedef int (*virDomainXMLPrivateDataTPMParseFunc)(xmlXPathContextPtr ctxt,
+ virDomainTPMDef *disk);
+typedef int (*virDomainXMLPrivateDataTPMFormatFunc)(const virDomainTPMDef *tpm,
+ virBuffer *buf);
struct _virDomainXMLPrivateDataCallbacks {
virDomainXMLPrivateDataAllocFunc alloc;
virDomainXMLPrivateDataNewFunc networkNew;
virDomainXMLPrivateDataNewFunc videoNew;
virDomainXMLPrivateDataNewFunc fsNew;
+ virDomainXMLPrivateDataTPMParseFunc tpmParse;
+ virDomainXMLPrivateDataTPMFormatFunc tpmFormat;
+ virDomainXMLPrivateDataNewFunc tpmNew;
virDomainXMLPrivateDataFormatFunc format;
virDomainXMLPrivateDataParseFunc parse;
/* following function shall return a pointer which will be used as the
}
+static virClass *qemuDomainTPMPrivateClass;
+static void qemuDomainTPMPrivateDispose(void *obj);
+
+
+static int
+qemuDomainTPMPrivateOnceInit(void)
+{
+ if (!VIR_CLASS_NEW(qemuDomainTPMPrivate, virClassForObject()))
+ return -1;
+
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(qemuDomainTPMPrivate);
+
+
+static virObject *
+qemuDomainTPMPrivateNew(void)
+{
+ qemuDomainTPMPrivate *priv;
+
+ if (qemuDomainTPMPrivateInitialize() < 0)
+ return NULL;
+
+ if (!(priv = virObjectNew(qemuDomainTPMPrivateClass)))
+ return NULL;
+
+ return (virObject *) priv;
+}
+
+
+static void
+qemuDomainTPMPrivateDispose(void *obj G_GNUC_UNUSED)
+{
+}
+
+
+static int
+qemuDomainTPMPrivateParse(xmlXPathContextPtr ctxt,
+ virDomainTPMDef *tpm)
+{
+ qemuDomainTPMPrivate *priv = QEMU_DOMAIN_TPM_PRIVATE(tpm);
+
+ priv->swtpm.can_migrate_shared_storage =
+ virXPathBoolean("string(./swtpm/@can_migrate_shared_storage)", ctxt);
+
+ return 0;
+}
+
+
+static int
+qemuDomainTPMPrivateFormat(const virDomainTPMDef *tpm,
+ virBuffer *buf)
+{
+ qemuDomainTPMPrivate *priv = QEMU_DOMAIN_TPM_PRIVATE(tpm);
+
+ switch (tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ if (priv->swtpm.can_migrate_shared_storage)
+ virBufferAddLit(buf, "<swtpm can_migrate_shared_storage='yes'/>\n");
+ break;
+
+ case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ }
+
+ return 0;
+}
+
+
/* qemuDomainSecretInfoSetup:
* @priv: pointer to domain private object
* @alias: alias of the secret
.graphicsNew = qemuDomainGraphicsPrivateNew,
.networkNew = qemuDomainNetworkPrivateNew,
.videoNew = qemuDomainVideoPrivateNew,
+ .tpmNew = qemuDomainTPMPrivateNew,
+ .tpmParse = qemuDomainTPMPrivateParse,
+ .tpmFormat = qemuDomainTPMPrivateFormat,
.parse = qemuDomainObjPrivateXMLParse,
.format = qemuDomainObjPrivateXMLFormat,
.getParseOpaque = qemuDomainObjPrivateXMLGetParseOpaque,
qemuFDPass *vdpafd;
};
+
+#define QEMU_DOMAIN_TPM_PRIVATE(dev) \
+ ((qemuDomainTPMPrivate *) (dev)->privateData)
+
+typedef struct _qemuDomainTPMPrivate qemuDomainTPMPrivate;
+struct _qemuDomainTPMPrivate {
+ virObject parent;
+
+ struct {
+ bool can_migrate_shared_storage;
+ } swtpm;
+};
+
+
void
qemuDomainNetworkPrivateClearFDs(qemuDomainNetworkPrivate *priv);