This lacks the saving of the smbios data, should not be hard really,
and the parsing is rather trivial, the data structures follow the XML
format:
Daniel
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5499f28..9dff0f7 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -606,6 +606,29 @@ struct _virDomainMemballoonDef {
};
+
+typedef struct _virSmbiosEntry virSmbiosEntry;
+typedef virSmbiosEntry *virSmbiosEntryPtr;
+struct _virSmbiosEntry {
+ virSmbiosEntryPtr next;
+ char *name;
+ char *value;
+};
+
+typedef struct _virSmbiosBlock virSmbiosBlock;
+typedef virSmbiosBlock *virSmbiosBlockPtr;
+struct _virSmbiosBlock {
+ unsigned int type;
+ virSmbiosEntryPtr entries;
+};
+
+typedef struct _virSmbiosDef virSmbiosDef;
+typedef virSmbiosDef *virSmbiosDefPtr;
+struct _virSmbiosDef {
+ unsigned int nbblocks;
+ virSmbiosBlockPtr *blocks;
+};
+
/* Flags for the 'type' field in next struct */
enum virDomainDeviceType {
VIR_DOMAIN_DEVICE_DISK,
@@ -943,6 +966,7 @@ struct _virDomainDef {
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
virCPUDefPtr cpu;
+ virSmbiosDefPtr smbios;
void *namespaceData;
virDomainXMLNamespace ns;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a997e06..fd85398 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -712,6 +712,48 @@ virDomainClockDefClear(virDomainClockDefPtr def)
VIR_FREE(def->timers);
}
+static void virSmbiosEntriesFree(virSmbiosEntryPtr cur)
+{
+ virSmbiosEntryPtr next;
+
+ if (cur == NULL)
+ return;
+
+ while (cur != NULL) {
+ next = cur->next;
+
+ VIR_FREE(cur->name);
+ VIR_FREE(cur->value);
+ VIR_FREE(cur);
+
+ cur = next;
+ }
+}
+
+static void virSmbiosBlockFree(virSmbiosBlockPtr block)
+{
+ if (block == NULL)
+ return;
+
+ virSmbiosEntriesFree(block->entries);
+ VIR_FREE(block);
+}
+
+static void virSmbiosDefFree(virSmbiosDefPtr def)
+{
+ unsigned int i;
+
+ if (def == NULL)
+ return;
+
+ if (def->blocks != NULL) {
+ for (i = 0;i < def->nbblocks;i++)
+ virSmbiosBlockFree(def->blocks[i]);
+ VIR_FREE(def->blocks);
+ }
+ VIR_FREE(def);
+}
+
void virDomainDefFree(virDomainDefPtr def)
{
unsigned int i;
@@ -796,6 +838,8 @@ void virDomainDefFree(virDomainDefPtr def)
virCPUDefFree(def->cpu);
+ virSmbiosDefFree(def->smbios);
+
if (def->namespaceData && def->ns.free)
(def->ns.free)(def->namespaceData);
@@ -3341,6 +3385,150 @@ error:
goto cleanup;
}
+static virSmbiosEntryPtr
+virSmbiosEntryParseXML(xmlXPathContextPtr ctxt)
+{
+ char *name, *value;
+ virSmbiosEntryPtr def;
+
+ name = virXPathString("string(./@name)", ctxt);
+ if (name == NULL) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("XML element 'entry' requires a 'name'
attrbute"));
+ return(NULL);
+ }
+ value = virXPathString("string(.)", ctxt);
+ if (value == NULL) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("failed to get content of element 'entry'"));
+ VIR_FREE(name);
+ return(NULL);
+ }
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ VIR_FREE(name);
+ VIR_FREE(value);
+ return(NULL);
+ }
+ def->name = name;
+ def->value = value;
+ def->next = NULL;
+
+ return(def);
+}
+
+static virSmbiosBlockPtr
+virSmbiosBlockParseXML(xmlXPathContextPtr ctxt)
+{
+ virSmbiosBlockPtr def;
+ virSmbiosEntryPtr cur, next;
+ xmlNodePtr *nodes = NULL;
+ int n;
+ unsigned int i;
+ long type;
+
+ if (virXPathLong("string(./@type)", ctxt, &type) < 0) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("XML element 'table' requires a numeric 'type'
attrbute"));
+ return(NULL);
+ }
+ if ((type < 0) || (type > 32)) {
+ virDomainReportError(VIR_ERR_XML_ERROR,
+ _("XML 'type' attribute on 'table' out of 0..32 range
got %ld"),
+ type);
+ return(NULL);
+ }
+ n = virXPathNodeSet("./entry", ctxt, &nodes);
+ if (n <= 0)
+ return(NULL);
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ def->type = (unsigned int) type;
+ def->entries = NULL;
+ cur = NULL;
+
+ for (i = 0;i < n;i++) {
+ if (nodes[i] != NULL) {
+ ctxt->node = nodes[i];
+ next = virSmbiosEntryParseXML(ctxt);
+ if (next == NULL)
+ goto error;
+ if (cur == NULL) {
+ def->entries = next;
+ cur = next;
+ } else {
+ cur->next = next;
+ cur = next;
+ }
+ cur->next = NULL;
+ }
+ }
+
+cleanup:
+ xmlFree(nodes);
+ return(def);
+
+error:
+ virSmbiosBlockFree(def);
+ def = NULL;
+ goto cleanup;
+}
+
+static virSmbiosDefPtr
+virSmbiosParseXML(const xmlNodePtr node,
+ xmlXPathContextPtr ctxt)
+{
+ virSmbiosDefPtr def;
+ virSmbiosBlockPtr block;
+ xmlNodePtr *nodes = NULL;
+ int n;
+ unsigned int i, j;
+
+ if (!xmlStrEqual(node->name, BAD_CAST "smbios")) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("XML does not contain expected 'smbios'
element"));
+ return(NULL);
+ }
+
+ n = virXPathNodeSet("./table", ctxt, &nodes);
+ if (n <= 0)
+ return(NULL);
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ if (VIR_ALLOC_N(def->blocks, n) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+
+ for (i = 0, j = 0;i < n;i++) {
+ if (nodes[i] != NULL) {
+ ctxt->node = nodes[i];
+ block = virSmbiosBlockParseXML(ctxt);
+ if (block != NULL)
+ def->blocks[j++] = block;
+ else
+ goto error;
+ def->nbblocks = j;
+ }
+ }
+
+
+cleanup:
+ xmlFree(nodes);
+ return(def);
+
+error:
+ virSmbiosDefFree(def);
+ def = NULL;
+ goto cleanup;
+}
int
virDomainVideoDefaultRAM(virDomainDefPtr def,
@@ -4970,6 +5158,16 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
goto error;
}
+ if ((node = virXPathNode("./smbios[1]", ctxt)) != NULL) {
+ xmlNodePtr oldnode = ctxt->node;
+ ctxt->node = node;
+ def->smbios = virSmbiosParseXML(node, ctxt);
+ ctxt->node = oldnode;
+
+ if (def->smbios == NULL)
+ goto error;
+ }
+
/* we have to make a copy of all of the callback pointers here since
* we won't have the virCaps structure available during free
*/
--
Daniel Veillard | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/