mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 22:55:23 +00:00
Parse TPM passthrough XML in the domain XML
Parse the domain XML with TPM passthrough support. The TPM passthrough XML may look like this: <tpm model='tpm-tis'> <backend type='passthrough'> <device path='/dev/tpm0'/> </backend> </tpm> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com> Tested-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
This commit is contained in:
parent
06ba4bff91
commit
6ecff413e1
@ -51,6 +51,7 @@
|
||||
#include "netdev_bandwidth_conf.h"
|
||||
#include "netdev_vlan_conf.h"
|
||||
#include "device_conf.h"
|
||||
#include "virtpm.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
||||
|
||||
@ -721,6 +722,13 @@ VIR_ENUM_IMPL(virDomainRNGBackend,
|
||||
"random",
|
||||
"egd");
|
||||
|
||||
VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST,
|
||||
"tpm-tis")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST,
|
||||
"passthrough")
|
||||
|
||||
|
||||
#define VIR_DOMAIN_XML_WRITE_FLAGS VIR_DOMAIN_XML_SECURE
|
||||
#define VIR_DOMAIN_XML_READ_FLAGS VIR_DOMAIN_XML_INACTIVE
|
||||
|
||||
@ -1619,6 +1627,23 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
|
||||
}
|
||||
}
|
||||
|
||||
void virDomainTPMDefFree(virDomainTPMDefPtr def)
|
||||
{
|
||||
if (!def)
|
||||
return;
|
||||
|
||||
switch (def->type) {
|
||||
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
|
||||
VIR_FREE(def->data.passthrough.source.data.file.path);
|
||||
break;
|
||||
case VIR_DOMAIN_TPM_TYPE_LAST:
|
||||
break;
|
||||
}
|
||||
|
||||
virDomainDeviceInfoClear(&def->info);
|
||||
VIR_FREE(def);
|
||||
}
|
||||
|
||||
void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
|
||||
{
|
||||
if (!def)
|
||||
@ -1880,6 +1905,8 @@ void virDomainDefFree(virDomainDefPtr def)
|
||||
|
||||
virDomainRNGDefFree(def->rng);
|
||||
|
||||
virDomainTPMDefFree(def->tpm);
|
||||
|
||||
VIR_FREE(def->os.type);
|
||||
VIR_FREE(def->os.machine);
|
||||
VIR_FREE(def->os.init);
|
||||
@ -6771,6 +6798,103 @@ error:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Parse the XML definition for a TPM device
|
||||
*
|
||||
* The XML looks like this:
|
||||
*
|
||||
* <tpm model='tpm-tis'>
|
||||
* <backend type='passthrough'>
|
||||
* <device path='/dev/tpm0'/>
|
||||
* </backend>
|
||||
* </tpm>
|
||||
*
|
||||
*/
|
||||
static virDomainTPMDefPtr
|
||||
virDomainTPMDefParseXML(const xmlNodePtr node,
|
||||
xmlXPathContextPtr ctxt,
|
||||
unsigned int flags)
|
||||
{
|
||||
char *type = NULL;
|
||||
char *path = NULL;
|
||||
char *model = NULL;
|
||||
char *backend = NULL;
|
||||
virDomainTPMDefPtr def;
|
||||
xmlNodePtr save = ctxt->node;
|
||||
xmlNodePtr *backends = NULL;
|
||||
int nbackends;
|
||||
|
||||
if (VIR_ALLOC(def) < 0) {
|
||||
virReportOOMError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
model = virXMLPropString(node, "model");
|
||||
if (model != NULL &&
|
||||
(int)(def->model = virDomainTPMModelTypeFromString(model)) < 0) {
|
||||
virReportError(VIR_ERR_INVALID_ARG,
|
||||
_("Unknown TPM frontend model '%s'"), model);
|
||||
goto error;
|
||||
} else {
|
||||
def->model = VIR_DOMAIN_TPM_MODEL_TIS;
|
||||
}
|
||||
|
||||
ctxt->node = node;
|
||||
|
||||
if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) < 0)
|
||||
goto error;
|
||||
|
||||
if (nbackends > 1) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("only one TPM backend is supported"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(backend = virXMLPropString(backends[0], "type"))) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("missing TPM device backend type"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((int)(def->type = virDomainTPMBackendTypeFromString(backend)) < 0) {
|
||||
virReportError(VIR_ERR_XML_ERROR,
|
||||
_("Unknown TPM backend type '%s'"),
|
||||
backend);
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (def->type) {
|
||||
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
|
||||
path = virXPathString("string(./backend/device/@path)", ctxt);
|
||||
if (!path && !(path = strdup(VIR_DOMAIN_TPM_DEFAULT_DEVICE))) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
def->data.passthrough.source.data.file.path = path;
|
||||
def->data.passthrough.source.type = VIR_DOMAIN_CHR_TYPE_DEV;
|
||||
path = NULL;
|
||||
break;
|
||||
case VIR_DOMAIN_TPM_TYPE_LAST:
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
|
||||
goto error;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(type);
|
||||
VIR_FREE(path);
|
||||
VIR_FREE(model);
|
||||
VIR_FREE(backend);
|
||||
VIR_FREE(backends);
|
||||
ctxt->node = save;
|
||||
return def;
|
||||
|
||||
error:
|
||||
virDomainTPMDefFree(def);
|
||||
def = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Parse the XML definition for an input device */
|
||||
static virDomainInputDefPtr
|
||||
virDomainInputDefParseXML(const char *ostype,
|
||||
@ -11099,6 +11223,23 @@ virDomainDefParseXML(xmlDocPtr xml,
|
||||
goto error;
|
||||
VIR_FREE(nodes);
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
/* Parse the TPM devices */
|
||||
if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0)
|
||||
goto error;
|
||||
|
||||
if (n > 1) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("only a single TPM device is supported"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
if (!(def->tpm = virDomainTPMDefParseXML(nodes[0], ctxt, flags)))
|
||||
goto error;
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
/* analysis of the hub devices */
|
||||
if ((n = virXPathNodeSet("./devices/hub", ctxt, &nodes)) < 0) {
|
||||
@ -14082,6 +14223,39 @@ virDomainSoundCodecDefFormat(virBufferPtr buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virDomainTPMDefFormat(virBufferPtr buf,
|
||||
virDomainTPMDefPtr def,
|
||||
unsigned int flags)
|
||||
{
|
||||
virBufferAsprintf(buf, " <tpm model='%s'>\n",
|
||||
virDomainTPMModelTypeToString(def->model));
|
||||
|
||||
virBufferAsprintf(buf, " <backend type='%s'>\n",
|
||||
virDomainTPMBackendTypeToString(def->type));
|
||||
|
||||
switch (def->type) {
|
||||
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
|
||||
virBufferEscapeString(buf, " <device path='%s'/>\n",
|
||||
def->data.passthrough.source.data.file.path);
|
||||
break;
|
||||
case VIR_DOMAIN_TPM_TYPE_LAST:
|
||||
break;
|
||||
}
|
||||
|
||||
virBufferAddLit(buf, " </backend>\n");
|
||||
|
||||
if (virDomainDeviceInfoIsSet(&def->info, flags)) {
|
||||
if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
virBufferAddLit(buf, " </tpm>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virDomainSoundDefFormat(virBufferPtr buf,
|
||||
virDomainSoundDefPtr def,
|
||||
@ -15408,6 +15582,11 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
||||
virDomainInputDefFormat(buf, def->inputs[n], flags) < 0)
|
||||
goto error;
|
||||
|
||||
if (def->tpm) {
|
||||
if (virDomainTPMDefFormat(buf, def->tpm, flags) < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (def->ngraphics > 0) {
|
||||
/* If graphics is enabled, add the implicit mouse */
|
||||
virDomainInputDef autoInput = {
|
||||
|
@ -1097,6 +1097,33 @@ struct _virDomainHubDef {
|
||||
virDomainDeviceInfo info;
|
||||
};
|
||||
|
||||
enum virDomainTPMModel {
|
||||
VIR_DOMAIN_TPM_MODEL_TIS,
|
||||
|
||||
VIR_DOMAIN_TPM_MODEL_LAST
|
||||
};
|
||||
|
||||
enum virDomainTPMBackendType {
|
||||
VIR_DOMAIN_TPM_TYPE_PASSTHROUGH,
|
||||
|
||||
VIR_DOMAIN_TPM_TYPE_LAST
|
||||
};
|
||||
|
||||
# define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0"
|
||||
|
||||
typedef struct _virDomainTPMDef virDomainTPMDef;
|
||||
typedef virDomainTPMDef *virDomainTPMDefPtr;
|
||||
struct _virDomainTPMDef {
|
||||
enum virDomainTPMBackendType type;
|
||||
virDomainDeviceInfo info;
|
||||
enum virDomainTPMModel model;
|
||||
union {
|
||||
struct {
|
||||
virDomainChrSourceDef source;
|
||||
} passthrough;
|
||||
} data;
|
||||
};
|
||||
|
||||
enum virDomainInputType {
|
||||
VIR_DOMAIN_INPUT_TYPE_MOUSE,
|
||||
VIR_DOMAIN_INPUT_TYPE_TABLET,
|
||||
@ -1883,6 +1910,7 @@ struct _virDomainDef {
|
||||
/* Only 1 */
|
||||
virDomainWatchdogDefPtr watchdog;
|
||||
virDomainMemballoonDefPtr memballoon;
|
||||
virDomainTPMDefPtr tpm;
|
||||
virCPUDefPtr cpu;
|
||||
virSysinfoDefPtr sysinfo;
|
||||
virDomainRedirFilterDefPtr redirfilter;
|
||||
@ -2062,6 +2090,7 @@ void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
|
||||
void virDomainDefClearPCIAddresses(virDomainDefPtr def);
|
||||
void virDomainDefClearCCWAddresses(virDomainDefPtr def);
|
||||
void virDomainDefClearDeviceAliases(virDomainDefPtr def);
|
||||
void virDomainTPMDefFree(virDomainTPMDefPtr def);
|
||||
|
||||
typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def,
|
||||
virDomainDeviceDefPtr dev,
|
||||
@ -2433,6 +2462,8 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode)
|
||||
VIR_ENUM_DECL(virDomainHyperv)
|
||||
VIR_ENUM_DECL(virDomainRNGModel)
|
||||
VIR_ENUM_DECL(virDomainRNGBackend)
|
||||
VIR_ENUM_DECL(virDomainTPMModel)
|
||||
VIR_ENUM_DECL(virDomainTPMBackend)
|
||||
/* from libvirt.h */
|
||||
VIR_ENUM_DECL(virDomainState)
|
||||
VIR_ENUM_DECL(virDomainNostateReason)
|
||||
|
@ -320,6 +320,11 @@ virDomainTimerTickpolicyTypeFromString;
|
||||
virDomainTimerTickpolicyTypeToString;
|
||||
virDomainTimerTrackTypeFromString;
|
||||
virDomainTimerTrackTypeToString;
|
||||
virDomainTPMBackendTypeFromString;
|
||||
virDomainTPMBackendTypeToString;
|
||||
virDomainTPMDefFree;
|
||||
virDomainTPMModelTypeFromString;
|
||||
virDomainTPMModelTypeToString;
|
||||
virDomainVcpuPinAdd;
|
||||
virDomainVcpuPinDefArrayFree;
|
||||
virDomainVcpuPinDefCopy;
|
||||
|
Loading…
Reference in New Issue
Block a user