On 11/13/24 18:39, Stefan Berger wrote: > Extend the parser and XML builder with support for the profile parameter > and its remove_disabled attribute. > > Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> > --- > src/conf/domain_conf.c | 36 ++++++++++++++++++++++++++++++++++++ > src/conf/domain_conf.h | 2 ++ > src/conf/domain_validate.c | 7 +++++++ > 3 files changed, 45 insertions(+) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index a5627ada88..7d91e3e958 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -3478,6 +3478,7 @@ void virDomainTPMDefFree(virDomainTPMDef *def) > g_free(def->data.emulator.source_path); > g_free(def->data.emulator.logfile); > virBitmapFree(def->data.emulator.activePcrBanks); > + g_free(def->data.emulator.profile_source); > break; > case VIR_DOMAIN_TPM_TYPE_EXTERNAL: > virObjectUnref(def->data.external.source); > @@ -10786,6 +10787,15 @@ virDomainSmartcardDefParseXML(virDomainXMLOption *xmlopt, > * <tpm model='tpm-tis'> > * <backend type='emulator' version='2.0' persistent_state='yes'> > * </tpm> > + * > + * A profile for a TPM 2.0 can be added like this: > + * > + * <tpm model='tpm-crb'> > + * <backend type='emulator' version='2.0'> > + * <profile source='local:restricted' remove_disabled='check'/> > + * </backend> > + * </tpm> > + * > */ > static virDomainTPMDef * > virDomainTPMDefParseXML(virDomainXMLOption *xmlopt, > @@ -10805,6 +10815,8 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt, > g_autofree xmlNodePtr *backends = NULL; > g_autofree xmlNodePtr *nodes = NULL; > g_autofree char *type = NULL; > + virDomainTPMProfileRemoveDisabled profile_remove_disabled; > + xmlNodePtr profile; > int bank; > > if (!(def = virDomainTPMDefNew(xmlopt))) > @@ -10911,6 +10923,22 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt, > } > virBitmapSetBitExpand(def->data.emulator.activePcrBanks, bank); > } > + > + if ((profile = virXPathNode("./backend/profile[1]", ctxt))) { > + def->data.emulator.profile_source = virXMLPropString(profile, "source"); > + if (!def->data.emulator.profile_source) { > + virReportError(VIR_ERR_XML_ERROR, "%s", _("missing profile source")); > + goto error; > + } > + if (virXMLPropEnum(profile, "remove_disabled", > + virDomainTPMProfileRemoveDisabledTypeFromString, > + VIR_XML_PROP_NONZERO, > + &profile_remove_disabled) < 0) > + goto error; > + if (profile_remove_disabled != VIR_DOMAIN_TPM_PROFILE_REMOVE_DISABLED_NONE) > + def->data.emulator.profile_remove_disabled = > + virDomainTPMProfileRemoveDisabledTypeToString(profile_remove_disabled); > + } > break; > case VIR_DOMAIN_TPM_TYPE_EXTERNAL: > if (!(type = virXPathString("string(./backend/source/@type)", ctxt))) { > @@ -25106,6 +25134,14 @@ virDomainTPMDefFormat(virBuffer *buf, > virDomainTPMSourceTypeTypeToString(def->data.emulator.source_type)); > virBufferEscapeString(&backendChildBuf, " path='%s'/>\n", def->data.emulator.source_path); > } > + if (def->data.emulator.profile_source) { > + virBufferAsprintf(&backendChildBuf, "<profile source='%s'", > + def->data.emulator.profile_source); > + if (def->data.emulator.profile_remove_disabled) > + virBufferAsprintf(&backendChildBuf, " remove_disabled='%s'", > + def->data.emulator.profile_remove_disabled); > + virBufferAddLit(&backendChildBuf, "/>\n"); Alternatively, virXMLFormatElement() makes this simpler. > + } > break; > case VIR_DOMAIN_TPM_TYPE_EXTERNAL: > if (def->data.external.source->type == VIR_DOMAIN_CHR_TYPE_UNIX) { > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index e1103c3655..bd2740af26 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -1492,6 +1492,8 @@ struct _virDomainTPMEmulatorDef { > bool hassecretuuid; > bool persistent_state; > virBitmap *activePcrBanks; > + char *profile_source; /* 'source' profile was created from */ > + const char *profile_remove_disabled; Why not store the enum instead of this const string? Oh, and while at it, these two (soon three) variables can be moved into a separate struct so that their "profile_" prefix can be dropped. E.g. struct { char *source; virDomainTPMProfileRemoveDisabled removeDisabled; } profile; > }; > > struct _virDomainTPMDef { > diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c > index b8ae9ed79d..7573430b6b 100644 > --- a/src/conf/domain_validate.c > +++ b/src/conf/domain_validate.c > @@ -3026,6 +3026,13 @@ virDomainTPMDevValidate(const virDomainTPMDef *tpm) > virDomainTPMVersionTypeToString(VIR_DOMAIN_TPM_VERSION_2_0)); > return -1; > } > + if (tpm->data.emulator.profile_source && > + tpm->data.emulator.version != VIR_DOMAIN_TPM_VERSION_2_0) { > + virReportError(VIR_ERR_XML_ERROR, > + _("<profile/> requires TPM version '%1$s'"), > + virDomainTPMVersionTypeToString(VIR_DOMAIN_TPM_VERSION_2_0)); > + return -1; > + } > break; > > case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: Michal