From: Zhuang Yanying <ann.zhuangyanying@xxxxxxxxxx> Some applications inside VM need to access SMBIOS Chassis Asset Tag, which should be emulated. It has already been realized in qemu, SMBIOS: Build aggregate smbios tables and entry point https://git.qemu.org/?p=qemu.git;a=commit;h=c97294ec1b9e36887e119589d456557d72ab37b5 but not in libvirt. we realize it here. As an example, you could use something like <chassis> <entry name='manufacturer'>LENOVO</entry> <entry name='version'>0B98401 Pro</entry> <entry name='serial'>W1KS427111E</entry> <entry name='asset'>344dfTYH#</entry> </chassis> --- src/conf/domain_conf.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_command.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virsysinfo.c | 37 +++++++++++++++++++++++++++++++++++ src/util/virsysinfo.h | 13 +++++++++++++ 4 files changed, 151 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 34aae82..b0d5d68 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14506,6 +14506,47 @@ virSysinfoBaseBoardParseXML(xmlXPathContextPtr ctxt, return ret; } +static int +virSysinfoChassisParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, + virSysinfoChassisDefPtr *chassisdef) +{ + int ret = -1; + virSysinfoChassisDefPtr def; + + if (!xmlStrEqual(node->name, BAD_CAST "chassis")) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("XML does not contain expected 'chassis' element")); + return ret; + } + + if (VIR_ALLOC(def) < 0) + goto cleanup; + + def->manufacturer = + virXPathString("string(entry[@name='manufacturer'])", ctxt); + def->version = + virXPathString("string(entry[@name='version'])", ctxt); + def->serial = + virXPathString("string(entry[@name='serial'])", ctxt); + def->asset = + virXPathString("string(entry[@name='asset'])", ctxt); + def->sku = + virXPathString("string(entry[@name='sku'])", ctxt); + + if (!def->manufacturer && !def->version && + !def->serial && !def->asset && !def->sku) { + virSysinfoChassisDefFree(def); + def = NULL; + } + + *chassisdef = def; + def = NULL; + ret = 0; + cleanup: + virSysinfoChassisDefFree(def); + return ret; +} static int virSysinfoOEMStringsParseXML(xmlXPathContextPtr ctxt, @@ -14600,6 +14641,17 @@ virSysinfoParseXML(xmlNodePtr node, if (virSysinfoBaseBoardParseXML(ctxt, &def->baseBoard, &def->nbaseBoard) < 0) goto error; + /* Extract chassis metadata */ + if ((tmpnode = virXPathNode("./chassis[1]", ctxt)) != NULL) { + oldnode = ctxt->node; + ctxt->node = tmpnode; + if (virSysinfoChassisParseXML(tmpnode, ctxt, &def->chassis) < 0) { + ctxt->node = oldnode; + goto error; + } + ctxt->node = oldnode; + } + /* Extract system related metadata */ if ((tmpnode = virXPathNode("./oemStrings[1]", ctxt)) != NULL) { oldnode = ctxt->node; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 24b434a..cf88e75 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5813,6 +5813,49 @@ qemuBuildSmbiosBaseBoardStr(virSysinfoBaseBoardDefPtr def) return NULL; } +static char * +qemuBuildSmbiosChassisStr(virSysinfoChassisDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (!def) + return NULL; + + virBufferAddLit(&buf, "type=3"); + + /* 2:Manufacturer */ + virBufferAddLit(&buf, ",manufacturer="); + virQEMUBuildBufferEscapeComma(&buf, def->manufacturer); + /* 2:Version */ + if (def->version) { + virBufferAddLit(&buf, ",version="); + virQEMUBuildBufferEscapeComma(&buf, def->version); + } + /* 2:Serial Number */ + if (def->serial) { + virBufferAddLit(&buf, ",serial="); + virQEMUBuildBufferEscapeComma(&buf, def->serial); + } + /* 2:Asset Tag */ + if (def->asset) { + virBufferAddLit(&buf, ",asset="); + virQEMUBuildBufferEscapeComma(&buf, def->asset); + } + /* 2:Sku */ + if (def->sku) { + virBufferAddLit(&buf, ",sku="); + virQEMUBuildBufferEscapeComma(&buf, def->sku); + } + + if (virBufferCheckError(&buf) < 0) + goto error; + + return virBufferContentAndReset(&buf); + + error: + virBufferFreeAndReset(&buf); + return NULL; +} static char * qemuBuildSmbiosOEMStringsStr(virSysinfoOEMStringsDefPtr def) @@ -5905,6 +5948,12 @@ qemuBuildSmbiosCommandLine(virCommandPtr cmd, VIR_FREE(smbioscmd); } + smbioscmd = qemuBuildSmbiosChassisStr(source->chassis); + if (smbioscmd != NULL) { + virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL); + VIR_FREE(smbioscmd); + } + if (source->oemStrings) { if (!(smbioscmd = qemuBuildSmbiosOEMStringsStr(source->oemStrings))) return -1; diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c index e8d3371..af434e0 100644 --- a/src/util/virsysinfo.c +++ b/src/util/virsysinfo.c @@ -108,6 +108,18 @@ void virSysinfoBaseBoardDefClear(virSysinfoBaseBoardDefPtr def) VIR_FREE(def->location); } +void virSysinfoChassisDefFree(virSysinfoChassisDefPtr def) +{ + if (def == NULL) + return; + + VIR_FREE(def->manufacturer); + VIR_FREE(def->version); + VIR_FREE(def->serial); + VIR_FREE(def->asset); + VIR_FREE(def->sku); +} + void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDefPtr def) { size_t i; @@ -143,6 +155,8 @@ void virSysinfoDefFree(virSysinfoDefPtr def) virSysinfoBaseBoardDefClear(def->baseBoard + i); VIR_FREE(def->baseBoard); + virSysinfoChassisDefFree(def->chassis); + for (i = 0; i < def->nprocessor; i++) { VIR_FREE(def->processor[i].processor_socket_destination); VIR_FREE(def->processor[i].processor_type); @@ -1203,6 +1217,28 @@ virSysinfoBaseBoardFormat(virBufferPtr buf, } static void +virSysinfoChassisFormat(virBufferPtr buf, virSysinfoChassisDefPtr def) +{ + if (!def) + return; + + virBufferAddLit(buf, "<chassis>\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n", + def->manufacturer); + virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n", + def->version); + virBufferEscapeString(buf, "<entry name='serial'>%s</entry>\n", + def->serial); + virBufferEscapeString(buf, "<entry name='asset'>%s</entry>\n", + def->asset); + virBufferEscapeString(buf, "<entry name='sku'>%s</entry>\n", + def->sku); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</chassis>\n"); +} + +static void virSysinfoProcessorFormat(virBufferPtr buf, virSysinfoDefPtr def) { size_t i; @@ -1354,6 +1390,7 @@ virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def) virSysinfoBIOSFormat(&childrenBuf, def->bios); virSysinfoSystemFormat(&childrenBuf, def->system); virSysinfoBaseBoardFormat(&childrenBuf, def->baseBoard, def->nbaseBoard); + virSysinfoChassisFormat(&childrenBuf, def->chassis); virSysinfoProcessorFormat(&childrenBuf, def); virSysinfoMemoryFormat(&childrenBuf, def); virSysinfoOEMStringsFormat(&childrenBuf, def->oemStrings); diff --git a/src/util/virsysinfo.h b/src/util/virsysinfo.h index ecb3a36..00a15db 100644 --- a/src/util/virsysinfo.h +++ b/src/util/virsysinfo.h @@ -98,6 +98,16 @@ struct _virSysinfoBaseBoardDef { /* XXX board type */ }; +typedef struct _virSysinfoChassisDef virSysinfoChassisDef; +typedef virSysinfoChassisDef *virSysinfoChassisDefPtr; +struct _virSysinfoChassisDef { + char *manufacturer; + char *version; + char *serial; + char *asset; + char *sku; +}; + typedef struct _virSysinfoOEMStringsDef virSysinfoOEMStringsDef; typedef virSysinfoOEMStringsDef *virSysinfoOEMStringsDefPtr; struct _virSysinfoOEMStringsDef { @@ -116,6 +126,8 @@ struct _virSysinfoDef { size_t nbaseBoard; virSysinfoBaseBoardDefPtr baseBoard; + virSysinfoChassisDefPtr chassis; + size_t nprocessor; virSysinfoProcessorDefPtr processor; @@ -130,6 +142,7 @@ virSysinfoDefPtr virSysinfoRead(void); void virSysinfoBIOSDefFree(virSysinfoBIOSDefPtr def); void virSysinfoSystemDefFree(virSysinfoSystemDefPtr def); void virSysinfoBaseBoardDefClear(virSysinfoBaseBoardDefPtr def); +void virSysinfoChassisDefFree(virSysinfoChassisDefPtr def); void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDefPtr def); void virSysinfoDefFree(virSysinfoDefPtr def); -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list