diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index d272cc1ba6..41ba4d41e3 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -411,6 +411,10 @@
<entry name='version'>0B98401 Pro</entry>
<entry name='serial'>W1KS427111E</entry>
</baseBoard>
+ <oemStrings>
+ <entry>myappname:some arbitrary data</entry>
+ <entry>otherappname:more arbitrary data</entry>
+ </oemStrings>
</sysinfo>
...
@@ -498,6 +502,15 @@
validation and date
format checking, all values are
passed as strings to the hypervisor driver.
+
oemStrings
+
+ This is block 11 of SMBIOS. This element should appear once and
+ can have multiple entry
child elements, each providing
+ arbitrary string data. There are no restrictions on what data can
+ be provided in the entries, however, if the data is intended to be
+ consumed by an application in the guest, it is recommended to use
+ the application name as a prefix in the string. (Since 4.1.0)
+
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index f22c932f6c..a154b5a462 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4857,6 +4857,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a1c25060f9..90a58686cb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -14461,6 +14461,42 @@ virSysinfoBaseBoardParseXML(xmlXPathContextPtr ctxt,
return ret;
}
+
+static int
+virSysinfoOEMStringsParseXML(xmlXPathContextPtr ctxt,
+ virSysinfoOEMStringsDefPtr *oem)
+{
+ int ret = -1;
+ virSysinfoOEMStringsDefPtr def;
+ xmlNodePtr *strings = NULL;
+ int nstrings;
+ size_t i;
+
+ nstrings = virXPathNodeSet("./entry", ctxt, &strings);
+ if (nstrings < 0)
+ return -1;
+ if (nstrings == 0)
+ return 0;
+
+ if (VIR_ALLOC(def) < 0)
+ goto cleanup;
+
+ if (VIR_ALLOC_N(def->values, nstrings) < 0)
+ goto cleanup;
+
+ def->nvalues = nstrings;
+ for (i = 0; i < nstrings; i++)
+ def->values[i] = virXMLNodeContentString(strings[i]);
+
+ *oem = def;
+ def = NULL;
+ ret = 0;
+ cleanup:
+ VIR_FREE(strings);
+ virSysinfoOEMStringsDefFree(def);
+ return ret;
+}
+
static virSysinfoDefPtr
virSysinfoParseXML(xmlNodePtr node,
xmlXPathContextPtr ctxt,
@@ -14519,6 +14555,17 @@ virSysinfoParseXML(xmlNodePtr node,
if (virSysinfoBaseBoardParseXML(ctxt, &def->baseBoard, &def->nbaseBoard) < 0)
goto error;
+ /* Extract system related metadata */
+ if ((tmpnode = virXPathNode("./oemStrings[1]", ctxt)) != NULL) {
+ oldnode = ctxt->node;
+ ctxt->node = tmpnode;
+ if (virSysinfoOEMStringsParseXML(ctxt, &def->oemStrings) < 0) {
+ ctxt->node = oldnode;
+ goto error;
+ }
+ ctxt->node = oldnode;
+ }
+
cleanup:
VIR_FREE(type);
return def;
diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c
index 1fbdd778f9..855580d446 100644
--- a/src/util/virsysinfo.c
+++ b/src/util/virsysinfo.c
@@ -108,6 +108,20 @@ void virSysinfoBaseBoardDefClear(virSysinfoBaseBoardDefPtr def)
VIR_FREE(def->location);
}
+void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDefPtr def)
+{
+ size_t i;
+
+ if (def == NULL)
+ return;
+
+ for (i = 0; i < def->nvalues; i++)
+ VIR_FREE(def->values[i]);
+ VIR_FREE(def->values);
+
+ VIR_FREE(def);
+}
+
/**
* virSysinfoDefFree:
* @def: a sysinfo structure
@@ -157,6 +171,8 @@ void virSysinfoDefFree(virSysinfoDefPtr def)
}
VIR_FREE(def->memory);
+ virSysinfoOEMStringsDefFree(def->oemStrings);
+
VIR_FREE(def);
}
@@ -1294,6 +1310,24 @@ virSysinfoMemoryFormat(virBufferPtr buf, virSysinfoDefPtr def)
}
}
+static void
+virSysinfoOEMStringsFormat(virBufferPtr buf, virSysinfoOEMStringsDefPtr def)
+{
+ size_t i;
+
+ if (!def)
+ return;
+
+ virBufferAddLit(buf, "\n");
+ virBufferAdjustIndent(buf, 2);
+ for (i = 0; i < def->nvalues; i++) {
+ virBufferEscapeString(buf, "%s\n",
+ def->values[i]);
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "\n");
+}
+
/**
* virSysinfoFormat:
* @buf: buffer to append output to (may use auto-indentation)
@@ -1324,6 +1358,7 @@ virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def)
virSysinfoBaseBoardFormat(&childrenBuf, def->baseBoard, def->nbaseBoard);
virSysinfoProcessorFormat(&childrenBuf, def);
virSysinfoMemoryFormat(&childrenBuf, def);
+ virSysinfoOEMStringsFormat(&childrenBuf, def->oemStrings);
virBufferAsprintf(buf, "