summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.h39
-rw-r--r--src/dmidecode.c8809
-rw-r--r--src/dmidecode.h39
-rw-r--r--src/dmidecodemodule.c964
-rw-r--r--src/dmidecodemodule.h87
-rw-r--r--src/dmidump.c168
-rw-r--r--src/dmidump.h37
-rw-r--r--src/dmierror.c79
-rw-r--r--src/dmierror.h54
-rw-r--r--src/dmihelper.c115
-rw-r--r--src/dmihelper.h189
-rw-r--r--src/dmioem.c125
-rw-r--r--src/dmioem.h1
-rw-r--r--src/dmixml.c360
-rw-r--r--src/dmixml.h79
-rw-r--r--src/efi.c83
-rw-r--r--src/efi.h35
-rw-r--r--src/libxml_wrap.h280
-rw-r--r--src/pymap.xml864
-rw-r--r--src/setup-dbg.py77
-rw-r--r--src/setup.py77
-rw-r--r--src/setup_common.py93
-rw-r--r--src/types.h46
-rw-r--r--src/util.c235
-rw-r--r--src/util.h3
-rw-r--r--src/version.h2
-rw-r--r--src/xmlpythonizer.c1183
-rw-r--r--src/xmlpythonizer.h60
28 files changed, 9186 insertions, 4997 deletions
diff --git a/src/config.h b/src/config.h
index c1d7d03..2876788 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,4 +1,39 @@
/*
+ * © 2007-2009 Nima Talebi <nima@autonomy.net.au>
+ * © 2009 David Sommerseth <davids@redhat.com>
+ *
+ * This file is part of Python DMI-Decode.
+ *
+ * Python DMI-Decode is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Python DMI-Decode is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ * AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ *
+ */
+
+/*
* Configuration
*/
@@ -22,4 +57,8 @@
#define ALIGNMENT_WORKAROUND
#endif
+#ifndef PYTHON_XML_MAP
+#define PYTHON_XML_MAP "/usr/share/python-dmidecode/pymap.xml"
+#endif
+
#endif
diff --git a/src/dmidecode.c b/src/dmidecode.c
index bbf05cf..aa2332d 100644
--- a/src/dmidecode.c
+++ b/src/dmidecode.c
@@ -1,30 +1,48 @@
+
+/*. ******* coding:utf-8 AUTOHEADER START v1.1 *******
+ *. vim: fileencoding=utf-8 syntax=c sw=2 ts=2 et
+ *.
+ *. © 2007-2009 Nima Talebi <nima@autonomy.net.au>
+ *. © 2009 David Sommerseth <davids@redhat.com>
+ *. © 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *. © 2000-2002 Alan Cox <alan@redhat.com>
+ *.
+ *. This file is part of Python DMI-Decode.
+ *.
+ *. Python DMI-Decode is free software: you can redistribute it and/or modify
+ *. it under the terms of the GNU General Public License as published by
+ *. the Free Software Foundation, either version 2 of the License, or
+ *. (at your option) any later version.
+ *.
+ *. Python DMI-Decode is distributed in the hope that it will be useful,
+ *. but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *. GNU General Public License for more details.
+ *.
+ *. You should have received a copy of the GNU General Public License
+ *. along with Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ *.
+ *. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ *. EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ *. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *.
+ *. ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ *. AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ *.
+ *. $AutoHeaderSerial::20090522 $
+ *. ******* AUTOHEADER END v1.1 ******* */
+
/*
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DMI Decode
*
- * Copyright 2000-2002 Alan Cox <alan@redhat.com>
- * Copyright 2002-2008 Jean Delvare <khali@linux-fr.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For the avoidance of doubt the "preferred form" of this code is one which
- * is in an open unpatent encumbered format. Where cryptographic key signing
- * forms part of the process of creating an executable the information
- * including keys needed to generate an equivalently functional executable
- * are deemed to be part of the source code.
- *
* Unless specified otherwise, all references are aimed at the "System
* Management BIOS Reference Specification, Version 2.6" document,
* available from http://www.dmtf.org/standards/smbios/.
@@ -49,334 +67,384 @@
* - BIOS Integrity Services Application Programming Interface version 1.0
* http://www.intel.com/design/archives/wfm/downloads/bisspec.htm
*
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * DMI Decode Python Module (Extension)
- *
- * Copyright: 2007-2008 Nima Talebi <nima@autonomy.net.au>
- * License: GPLv3
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
-#include <Python.h>
-
-/*
-#undef NDEBUG
#include <assert.h>
-*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <libxml/tree.h>
#include "version.h"
#include "config.h"
#include "types.h"
#include "util.h"
+#include "dmixml.h"
#include "dmidecode.h"
#include "dmioem.h"
+#include "efi.h"
+#include "dmidump.h"
#include "dmihelper.h"
-#define EFI_NOT_FOUND (-1)
-#define EFI_NO_SMBIOS (-2)
-
-static const char *out_of_spec = "<OUT OF SPEC>";
-static const char *bad_index = "<BAD INDEX>";
-#define BAD_INDEX PyString_FromString("<BAD INDEX>")
-#define OUT_OF_SPEC PyString_FromString("<OUT OF SPEC>")
-
/*******************************************************************************
** Type-independant Stuff
*/
-static PyObject *dmi_string_py(const struct dmi_header *dm, u8 s) {
- char *bp=(char *)dm->data;
- size_t i, len;
-
- PyObject *data;
-
- if(s==0) data = PyString_FromString("Not Specified");
- else {
- bp += dm->length;
- while(s>1 && *bp) { bp += strlen(bp); bp++; s--; }
-
- if(!*bp) data = BAD_INDEX;
- else {
- /* ASCII filtering */
- len=strlen(bp);
- for(i=0; i<len; i++)
- if(bp[i]<32 || bp[i]==127)
- bp[i]='.';
- data = PyString_FromString(bp);
- }
- }
- return data;
-}
-
-const char *dmi_string(const struct dmi_header *dm, u8 s) {
- char *bp = (char *)dm->data;
- size_t i, len;
-
- if(s == 0) return "Not Specified";
-
- bp += dm->length;
- while(s>1 && *bp) {
- bp+=strlen(bp);
- bp++;
- s--;
- }
-
- if(!*bp) return bad_index;
-
- /* ASCII filtering */
- len = strlen(bp);
- for(i=0; i<len; i++)
- if(bp[i]<32 || bp[i]==127)
- bp[i]='.';
-
- return bp;
-}
-
-
-
-
-static const char *dmi_smbios_structure_type(u8 code) {
- static const char *type[] = {
- "BIOS", /* 0 */
- "System",
- "Base Board",
- "Chassis",
- "Processor",
- "Memory Controller",
- "Memory Module",
- "Cache",
- "Port Connector",
- "System Slots",
- "On Board Devices",
- "OEM Strings",
- "System Configuration Options",
- "BIOS Language",
- "Group Associations",
- "System Event Log",
- "Physical Memory Array",
- "Memory Device",
- "32-bit Memory Error",
- "Memory Array Mapped Address",
- "Memory Device Mapped Address",
- "Built-in Pointing Device",
- "Portable Battery",
- "System Reset",
- "Hardware Security",
- "System Power Controls",
- "Voltage Probe",
- "Cooling Device",
- "Temperature Probe",
- "Electrical Current Probe",
- "Out-of-band Remote Access",
- "Boot Integrity Services",
- "System Boot",
- "64-bit Memory Error",
- "Management Device",
- "Management Device Component",
- "Management Device Threshold Data",
- "Memory Channel",
- "IPMI Device",
- "Power Supply" /* 39 */
- };
-
- if(code<=39) return(type[code]);
- return out_of_spec;
-}
-
-static int dmi_bcd_range(u8 value, u8 low, u8 high) {
- if(value>0x99 || (value&0x0F)>0x09) return 0;
- if(value<low || value>high) return 0;
- return 1;
-}
-
-PyObject* dmi_dump(struct dmi_header *h) {
- int row, i;
- const char *s;
-
- PyObject *data = PyDict_New();
- PyObject *data1 = PyList_New(0);
- for(row=0; row<((h->length-1)>>4)+1; row++) {
- for(i=0; i<16 && i<h->length-(row<<4); i++)
- PyList_Append(data1, PyString_FromFormat("0x%02x", (h->data)[(row<<4)+i]));
- }
- PyDict_SetItemString(data, "Header and Data", data1);
-
- if((h->data)[h->length] || (h->data)[h->length+1]) {
- i=1;
- PyObject *data2 = PyList_New(0);
- while((s=dmi_string(h, i++))!=bad_index) {
- //. FIXME: DUMP
- /*
- if(opt.flags & FLAG_DUMP) {
- int j, l = strlen(s)+1;
- for(row=0; row<((l-1)>>4)+1; row++) {
- for(j=0; j<16 && j<l-(row<<4); j++)
- PyList_Append(data1, PyString_FromFormat("0x%02x", s[(row<<4)+j]));
- }
- fprintf(stderr, "\"%s\"|", s);
- }
- else fprintf(stderr, "%s|", s);
- */
- PyList_Append(data1, PyString_FromFormat("%s", s));
- }
- PyDict_SetItemString(data, "Strings", data2);
- }
- return data;
+const char *dmi_string(const struct dmi_header *dm, u8 s)
+{
+ char *bp = (char *)dm->data;
+ size_t i, len;
+
+ if(s == 0)
+ return "Not Specified";
+
+ bp += dm->length;
+ while(s > 1 && *bp) {
+ bp += strlen(bp);
+ bp++;
+ s--;
+ }
+
+ if(!*bp)
+ return NULL;
+
+ /* ASCII filtering */
+ len = strlen(bp);
+ for(i = 0; i < len; i++)
+ if(bp[i] < 32 || bp[i] == 127)
+ bp[i] = '.';
+
+ return bp;
+}
+
+xmlNode *dmi_smbios_structure_type(xmlNode *node, u8 code)
+{
+ static struct {
+ const char *descr;
+ const char *tagname;
+ const char *attrname;
+ const char *attrvalue;
+ } types[] = {
+ /* *INDENT-OFF* */
+ {"BIOS", "BIOS", NULL, NULL}, /* 0 */
+ {"System", "System", NULL, NULL},
+ {"Base Board", "BaseBoard", NULL, NULL},
+ {"Chassis", "Chassis", NULL, NULL},
+ {"Processor", "Processor", NULL, NULL},
+ {"Memory Controller", "Memory", "type", "controller"},
+ {"Memory Module", "Memory", "type", "module"},
+ {"Cache", "Cache", NULL, NULL},
+ {"Port Connector", "PortConnectors", NULL, NULL},
+ {"System Slots", "Slots", NULL, NULL},
+ {"On Board Devices", "OnBoardDevices", NULL, NULL},
+ {"OEM Strings", "OEMstrings", NULL, NULL},
+ {"System Configuration Options", "SysConfigOpts", NULL, NULL},
+ {"BIOS Language", "BIOS", "type", "language"},
+ {"Group Associations", "GroupAssociations", NULL, NULL},
+ {"System Event Log", "EventLog", NULL, NULL},
+ {"Physical Memory Array", "PhysicalMemoryArray", NULL, NULL},
+ {"Memory Device", "Memory", "type", "device"},
+ {"32-bit Memory Error", "MemoryError", "bit", "32"},
+ {"Memory Array Mapped Address", "MemoryAddressMap", "type", "MemoryArray"},
+ {"Memory Device Mapped Address", "MemoryAddressMap", "type", "Device"},
+ {"Built-in Pointing Device", "BuiltinPointingDevice",NULL, NULL},
+ {"Portable Battery", "PortableBattery", NULL, NULL},
+ {"System Reset", "SystemReset", NULL, NULL},
+ {"Hardware Security", "HWsecurity", NULL, NULL},
+ {"System Power Controls", "SysPowerCtrl", NULL, NULL},
+ {"Voltage Probe", "Probe", "type", "Voltage"},
+ {"Cooling Device", "CoolingDevice", NULL, NULL},
+ {"Temperature Probe", "Probe", "type", "Temperature"},
+ {"Electrical Current Probe", "Probe", "type", "ElectricalCurrent"},
+ {"Out-of-band Remote Access", "RemoteAccess", NULL, NULL},
+ {"Boot Integrity Services", "BootIntegritySrv", NULL, NULL},
+ {"System Boot", "SystemBoot", NULL, NULL},
+ {"64-bit Memory Error", "MemoryError", "bit", "64"},
+ {"Management Device", "ManagementDevice", NULL, NULL},
+ {"Management Device Component", "ManagementDevice", "type", "component"},
+ {"Management Device Threshold Data","ManagementDevice", "type", "Threshold Data"},
+ {"Memory Channel", "MemoryChannel", NULL, NULL},
+ {"IPMI Device", "IPMIdevice", NULL, NULL},
+ {"Power Supply", "PowerSupply", NULL, NULL} /* 39 */
+ /* *INDENT-ON* */
+ };
+ xmlNode *type_n = NULL;
+
+ if(code <= 39) {
+ type_n = xmlNewChild(node, NULL, (xmlChar *)types[code].tagname, NULL);
+ assert( type_n != NULL );
+
+ dmixml_AddAttribute(type_n, "flags", "0x%04x", code);
+ dmixml_AddTextChild(type_n, "Description", "%s", types[code].descr);
+
+ if( (types[code].attrname != NULL) && (types[code].attrvalue != NULL) ) {
+ dmixml_AddAttribute(type_n, types[code].attrname, "%s", types[code].attrvalue);
+ }
+ } else {
+ type_n = xmlNewChild(node, NULL, (xmlChar *) "UnknownSMBiosType", NULL);
+ dmixml_AddAttribute(type_n, "flags", "0x%04x", code);
+ }
+
+ return type_n;
+}
+
+static int dmi_bcd_range(u8 value, u8 low, u8 high)
+{
+ if(value > 0x99 || (value & 0x0F) > 0x09)
+ return 0;
+ if(value < low || value > high)
+ return 0;
+ return 1;
+}
+
+void dmi_dump(xmlNode *node, struct dmi_header * h)
+{
+ int row, i;
+ const char *s;
+ xmlNode *dump_n = NULL, *row_n = NULL;
+ char *tmp_s = NULL;
+
+ dump_n = xmlNewChild(node, NULL, (xmlChar *) "HeaderAndData", NULL);
+ assert( dump_n != NULL );
+
+ tmp_s = (char *) malloc((h->length * 2) + 2);
+ for(row = 0; row < ((h->length - 1) >> 4) + 1; row++) {
+ memset(tmp_s, 0, (h->length * 2) + 2);
+
+ for(i = 0; i < (16 && i < h->length - (row << 4)); i++) {
+ snprintf(tmp_s + strlen(tmp_s), (h->length * 2)-strlen(tmp_s),
+ "0x%02x", (h->data)[(row << 4) + i]);
+ }
+ row_n = dmixml_AddTextChild(dump_n, "Row", "%s", tmp_s);
+ dmixml_AddAttribute(row_n, "index", "%i", row);
+ row_n = NULL;
+ }
+ free(tmp_s); tmp_s = NULL;
+ dump_n = NULL;
+
+ dump_n = xmlNewChild(node, NULL, (xmlChar *) "Strings", NULL);
+ assert( dump_n != NULL );
+
+ if((h->data)[h->length] || (h->data)[h->length + 1]) {
+ i = 1;
+ while((s = dmi_string(h, i++)) != NULL) {
+ //. FIXME: DUMP
+ /*
+ * opt->flags will need to be transported to the function somehow
+ * when this feature is implemented completely.
+ *
+ * if(opt->flags & FLAG_DUMP) {
+ * int j, l = strlen(s)+1;
+ * for(row=0; row<((l-1)>>4)+1; row++) {
+ * for(j=0; j<16 && j<l-(row<<4); j++)
+ * PyList_Append(data1, PyString_FromFormat("0x%02x", s[(row<<4)+j]));
+ * }
+ * fprintf(stderr, "\"%s\"|", s);
+ * }
+ * else fprintf(stderr, "%s|", s);
+ */
+ row_n = dmixml_AddTextChild(dump_n, "String", "%s", s);
+ dmixml_AddAttribute(row_n, "index", "%i", i);
+ row_n = NULL;
+ }
+ }
+ dump_n = NULL;
}
/*******************************************************************************
** 3.3.1 BIOS Information (Type 0)
*/
-static PyObject* dmi_bios_runtime_size(u32 code) {
- if(code&0x000003FF) return PyString_FromFormat("%i bytes", code);
- else return PyString_FromFormat("%i kB", code>>10);
+void dmi_bios_runtime_size(xmlNode *node, u32 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "RuntimeSize", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code & 0x000003FF) {
+ dmixml_AddAttribute(data_n, "unit", "bytes");
+ dmixml_AddTextContent(data_n, "%i", code);
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "KB");
+ dmixml_AddTextContent(data_n, "%i", code >> 10);
+ }
}
/* 3.3.1.1 */
-static PyObject* dmi_bios_characteristics(u64 code) {
- static const char *characteristics[] = {
- "BIOS characteristics not supported", /* 3 */
- "ISA is supported",
- "MCA is supported",
- "EISA is supported",
- "PCI is supported",
- "PC Card (PCMCIA) is supported",
- "PNP is supported",
- "APM is supported",
- "BIOS is upgradeable",
- "BIOS shadowing is allowed",
- "VLB is supported",
- "ESCD support is available",
- "Boot from CD is supported",
- "Selectable boot is supported",
- "BIOS ROM is socketed",
- "Boot from PC Card (PCMCIA) is supported",
- "EDD is supported",
- "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)",
- "Japanese floppy for Toshiba 1.2 MB is supported (int 13h)",
- "5.25\"/360 KB floppy services are supported (int 13h)",
- "5.25\"/1.2 MB floppy services are supported (int 13h)",
- "3.5\"/720 KB floppy services are supported (int 13h)",
- "3.5\"/2.88 MB floppy services are supported (int 13h)",
- "Print screen service is supported (int 5h)",
- "8042 keyboard services are supported (int 9h)",
- "Serial services are supported (int 14h)",
- "Printer services are supported (int 17h)",
- "CGA/mono video services are supported (int 10h)",
- "NEC PC-98" /* 31 */
- };
-
- PyObject *data;
- if(code.l&(1<<3)) {
- data = PyString_FromString(characteristics[0]);
- } else {
- int i;
- data = PyDict_New();
- for(i=4; i<=31; i++)
- PyDict_SetItemString(data, characteristics[i-3], code.l&(1<<i)?Py_True:Py_False);
- }
- return data;
+void dmi_bios_characteristics(xmlNode *node, u64 code)
+{
+ static const char *characteristics[] = {
+ "BIOS characteristics not supported", /* 3 */
+ "ISA is supported",
+ "MCA is supported",
+ "EISA is supported",
+ "PCI is supported",
+ "PC Card (PCMCIA) is supported",
+ "PNP is supported",
+ "APM is supported",
+ "BIOS is upgradeable",
+ "BIOS shadowing is allowed",
+ "VLB is supported",
+ "ESCD support is available",
+ "Boot from CD is supported",
+ "Selectable boot is supported",
+ "BIOS ROM is socketed",
+ "Boot from PC Card (PCMCIA) is supported",
+ "EDD is supported",
+ "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)",
+ "Japanese floppy for Toshiba 1.2 MB is supported (int 13h)",
+ "5.25\"/360 KB floppy services are supported (int 13h)",
+ "5.25\"/1.2 MB floppy services are supported (int 13h)",
+ "3.5\"/720 KB floppy services are supported (int 13h)",
+ "3.5\"/2.88 MB floppy services are supported (int 13h)",
+ "Print screen service is supported (int 5h)",
+ "8042 keyboard services are supported (int 9h)",
+ "Serial services are supported (int 14h)",
+ "Printer services are supported (int 17h)",
+ "CGA/mono video services are supported (int 10h)",
+ "NEC PC-98" /* 31 */
+ };
+ dmixml_AddAttribute(node, "dmispec", "3.3.1.1");
+ dmixml_AddAttribute(node, "flags", "0x%04x", code);
+
+ if(code.l&(1<<3)) {
+ dmixml_AddAttribute(node, "unavailable", "1");
+ dmixml_AddTextContent(node, characteristics[0]);
+ } else {
+ int i = 0;
+ xmlNode *flags_n = xmlNewChild(node, NULL, (xmlChar *) "flags", NULL);
+ assert( flags_n != NULL );
+
+ for(i = 4; i <= 31; i++) {
+ xmlNode *flg_n = dmixml_AddTextChild(flags_n, "flag", characteristics[i - 3]);
+ dmixml_AddAttribute(flg_n, "enabled", "%i", (code.l & (1 << i) ? 1 : 0 ));
+ }
+ }
}
/* 3.3.1.2.1 */
-static PyObject* dmi_bios_characteristics_x1(u8 code) {
- static const char *characteristics[] = {
- "ACPI", /* 0 */
- "USB legacy",
- "AGP",
- "I2O boot",
- "LS-120 boot",
- "ATAPI Zip drive boot",
- "IEEE 1394 boot",
- "Smart battery" /* 7 */
- };
-
- int i;
- PyObject *data = PyDict_New();
- for(i=0; i<=7; i++)
- PyDict_SetItemString(data, characteristics[i], code&(1<<i)?Py_True:Py_False);
- return data;
-
+void dmi_bios_characteristics_x1(xmlNode *node, u8 code)
+{
+ int i = 0;
+ static const char *characteristics[] = {
+ "ACPI", /* 0 */
+ "USB legacy",
+ "AGP",
+ "I2O boot",
+ "LS-120 boot",
+ "ATAPI Zip drive boot",
+ "IEEE 1394 boot",
+ "Smart battery" /* 7 */
+ };
+
+ dmixml_AddAttribute(node, "dmispec", "3.3.1.2.1");
+ dmixml_AddAttribute(node, "flags", "0x%04x", code);
+
+ for(i = 0; i <= 7; i++) {
+ xmlNode *chr_n = dmixml_AddTextChild(node, "characteristic", characteristics[i]);
+ dmixml_AddAttribute(chr_n, "enabled", "%i", (code & (1 << i) ? 1: 0));
+ }
}
/* 3.3.1.2.2 */
-static PyObject* dmi_bios_characteristics_x2(u8 code) {
- static const char *characteristics[]={
- "BIOS boot specification", /* 0 */
- "Function key-initiated network boot",
- "Targeted content distribution" /* 2 */
- };
-
- int i;
- PyObject *data = PyDict_New();
- for(i=0; i<=2; i++)
- PyDict_SetItemString(data, characteristics[i], code&(1<<i)?Py_True:Py_False);
- return data;
+void dmi_bios_characteristics_x2(xmlNode *node, u8 code)
+{
+ int i = 0;
+ static const char *characteristics[] = {
+ "BIOS boot specification", /* 0 */
+ "Function key-initiated network boot",
+ "Targeted content distribution" /* 2 */
+ };
+
+ dmixml_AddAttribute(node, "dmispec", "3.3.1.2.2");
+ dmixml_AddAttribute(node, "flags", "0x%04x", code);
+
+ for(i = 0; i <= 2; i++) {
+ xmlNode *chr_n = dmixml_AddTextChild(node, "characteristic", characteristics[i]);
+ dmixml_AddAttribute(chr_n, "enabled", "%i", (code & (1 << i) ? 1: 0));
+ }
}
/*******************************************************************************
** 3.3.2 System Information (Type 1)
*/
-PyObject *dmi_system_uuid_py(const u8 *p, u16 ver) {
- int only0xFF=1, only0x00=1;
- int i;
-
- for(i=0; i<16 && (only0x00 || only0xFF); i++) {
- if(p[i]!=0x00) only0x00=0;
- if(p[i]!=0xFF) only0xFF=0;
- }
-
- if(only0xFF)
- return PyString_FromString("Not Present");
-
- if(only0x00)
- return PyString_FromString("Not Settable");
-
- /*
- * As off version 2.6 of the SMBIOS specification, the first 3
- * fields of the UUID are supposed to be encoded on little-endian.
- * The specification says that this is the defacto standard,
- * however I've seen systems following RFC 4122 instead and use
- * network byte order, so I am reluctant to apply the byte-swapping
- * for older versions.
- */
- if (ver >= 0x0206)
- return PyString_FromFormat("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
- p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
- );
- else
- return PyString_FromFormat("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
- p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
- );
+void dmi_system_uuid(xmlNode *node, const u8 * p, u16 ver)
+{
+ int only0xFF = 1, only0x00 = 1;
+ int i;
+ xmlNode *uuid_n = NULL;
+
+ for(i = 0; i < 16 && (only0x00 || only0xFF); i++) {
+ if(p[i] != 0x00)
+ only0x00 = 0;
+ if(p[i] != 0xFF)
+ only0xFF = 0;
+ }
+
+ uuid_n = xmlNewChild(node, NULL, (xmlChar *) "SystemUUID", NULL);
+ dmixml_AddAttribute(uuid_n, "dmispec", "3.3.2");
+
+ if(only0xFF ) {
+ dmixml_AddAttribute(uuid_n, "unavailable", "1");
+ dmixml_AddTextContent(uuid_n, "Not Present");
+ return;
+ }
+
+ if(only0x00){
+ dmixml_AddAttribute(uuid_n, "unavailable", "1");
+ dmixml_AddTextContent(uuid_n,"Not Settable");
+ return;
+ }
+
+ /*
+ * As off version 2.6 of the SMBIOS specification, the first 3
+ * fields of the UUID are supposed to be encoded on little-endian.
+ * The specification says that this is the defacto standard,
+ * however I've seen systems following RFC 4122 instead and use
+ * network byte order, so I am reluctant to apply the byte-swapping
+ * for older versions.
+ */
+ if(ver >= 0x0206) {
+ dmixml_AddTextContent(uuid_n,
+ "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6], p[8], p[9], p[10],
+ p[11], p[12], p[13], p[14], p[15]);
+ } else {
+ dmixml_AddTextContent(uuid_n,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10],
+ p[11], p[12], p[13], p[14], p[15]);
+ }
}
/* 3.3.2.1 */
-static PyObject *dmi_system_wake_up_type(u8 code) {
- static const char *type[]={
- "Reserved", /* 0x00 */
- "Other",
- "Unknown",
- "APM Timer",
- "Modem Ring",
- "LAN Remote",
- "Power Switch",
- "PCI PME#",
- "AC Power Restored" /* 0x08 */
- };
-
- if(code<=0x08) return PyString_FromString(type[code]);
- return OUT_OF_SPEC;
+void dmi_system_wake_up_type(xmlNode *node, u8 code)
+{
+ static const char *type[] = {
+ "Reserved", /* 0x00 */
+ "Other",
+ "Unknown",
+ "APM Timer",
+ "Modem Ring",
+ "LAN Remote",
+ "Power Switch",
+ "PCI PME#",
+ "AC Power Restored" /* 0x08 */
+ };
+ xmlNode *swut_n = xmlNewChild(node, NULL, (xmlChar *) "SystemWakeUpType", NULL);
+ assert( swut_n != NULL );
+ dmixml_AddAttribute(swut_n, "dmispec", "3.3.2.1");
+ dmixml_AddAttribute(swut_n, "flags", "0x%04x", code);
+
+ if(code <= 0x08) {
+ dmixml_AddTextContent(swut_n, type[code]);
+ } else {
+ dmixml_AddAttribute(swut_n, "outofspec", "1");
+ }
}
/*******************************************************************************
@@ -384,64 +452,79 @@ static PyObject *dmi_system_wake_up_type(u8 code) {
*/
/* 3.3.3.1 */
-static PyObject *dmi_base_board_features(u8 code) {
- static const char *features[] = {
- "Board is a hosting board", /* 0 */
- "Board requires at least one daughter board",
- "Board is removable",
- "Board is replaceable",
- "Board is hot swappable" /* 4 */
- };
-
- PyObject *data;
- if((code&0x1F)==0) data = Py_None;
- else {
- int i;
- data = PyList_New(5);
- for(i=0; i<=4; i++) {
- if(code&(1<<i)) PyList_SET_ITEM(data, i, PyString_FromString(features[i]));
- else PyList_SET_ITEM(data, i, Py_None);
- }
- }
- return data;
-}
-
-static PyObject *dmi_base_board_type(u8 code) {
- /* 3.3.3.2 */
- static const char *type[] = {
- "Unknown", /* 0x01 */
- "Other",
- "Server Blade",
- "Connectivity Switch",
- "System Management Module",
- "Processor Module",
- "I/O Module",
- "Memory Module",
- "Daughter Board",
- "Motherboard",
- "Processor+Memory Module",
- "Processor+I/O Module",
- "Interconnect Board" /* 0x0D */
- };
-
- if(code>=0x01 && code<=0x0D)
- return PyString_FromString(type[code-0x01]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_base_board_handles(u8 count, const u8 *p) {
- int i;
-
- PyObject *dict = PyDict_New();
- PyObject *list = PyList_New(count);
-
- for(i=0; i<count; i++)
- PyList_SET_ITEM(list, i, PyString_FromFormat("0x%04x", WORD(p+sizeof(u16)*i)));
-
- PyDict_SetItemString(dict, "Contained Object Handles", list);
- Py_DECREF(list);
-
- return dict;
+void dmi_base_board_features(xmlNode *node, u8 code)
+{
+ static const char *features[] = {
+ "Board is a hosting board", /* 0 */
+ "Board requires at least one daughter board",
+ "Board is removable",
+ "Board is replaceable",
+ "Board is hot swappable" /* 4 */
+ };
+
+ xmlNode *feat_n = xmlNewChild(node, NULL, (xmlChar *) "Features", NULL);
+ assert( feat_n != NULL );
+ dmixml_AddAttribute(feat_n, "dmispec", "3.3.3.1");
+ dmixml_AddAttribute(feat_n, "flags", "0x%04x", code);
+
+ if((code & 0x1F) != 0) {
+ int i;
+
+ for(i = 0; i <= 4; i++) {
+ if(code & (1 << i)) {
+ dmixml_AddTextChild(feat_n, "feature", features[i]);
+ }
+ }
+ } else {
+ dmixml_AddAttribute(feat_n, "unavailable", "1");
+ }
+}
+
+void dmi_base_board_type(xmlNode *node, const char *tagname, u8 code)
+{
+ /* 3.3.3.2 */
+ static const char *type[] = {
+ "Unknown", /* 0x01 */
+ "Other",
+ "Server Blade",
+ "Connectivity Switch",
+ "System Management Module",
+ "Processor Module",
+ "I/O Module",
+ "Memory Module",
+ "Daughter Board",
+ "Motherboard",
+ "Processor+Memory Module",
+ "Processor+I/O Module",
+ "Interconnect Board" /* 0x0D */
+ };
+ xmlNode *type_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( type_n != NULL );
+ dmixml_AddAttribute(type_n, "dmispec", "3.3.3.2");
+ dmixml_AddAttribute(type_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0D) {
+ dmixml_AddTextContent(type_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(type_n, "unavailable", "1");
+ }
+}
+
+void dmi_base_board_handles(xmlNode *node, u8 count, const u8 * p)
+{
+ int i;
+ xmlNode *dict_n = NULL;
+
+ dict_n = xmlNewChild(node, NULL, (xmlChar *) "ContainedObjectHandles", NULL);
+ assert( dict_n != NULL );
+
+ dmixml_AddAttribute(dict_n, "count", "%i", count);
+
+ for(i = 0; i < count; i++) {
+ xmlNode *elmt_n = xmlNewChild(dict_n, NULL, (xmlChar *) "Handle", NULL);
+ assert( elmt_n != NULL );
+ dmixml_AddTextContent(elmt_n, "0x%04x", WORD(p + sizeof(u16) * i));
+ }
}
/*******************************************************************************
@@ -449,732 +532,889 @@ static PyObject *dmi_base_board_handles(u8 count, const u8 *p) {
*/
/* 3.3.4.1 */
-const char *dmi_chassis_type(u8 code) {
- static const char *type[] = {
- "Other", /* 0x01 */
- "Unknown",
- "Desktop",
- "Low Profile Desktop",
- "Pizza Box",
- "Mini Tower",
- "Tower",
- "Portable",
- "Laptop",
- "Notebook",
- "Hand Held",
- "Docking Station",
- "All In One",
- "Sub Notebook",
- "Space-saving",
- "Lunch Box",
- "Main Server Chassis", /* CIM_Chassis.ChassisPackageType says "Main System Chassis" */
- "Expansion Chassis",
- "Sub Chassis",
- "Bus Expansion Chassis",
- "Peripheral Chassis",
- "RAID Chassis",
- "Rack Mount Chassis",
- "Sealed-case PC",
- "Multi-system",
- "CompactPCI",
- "AdvancedTCA", /* 0x1B */
- "Blade",
- "Blade Enclosing" /* 0x1D */
- };
-
- if(code>=0x01 && code<=0x1B)
- return type[code-0x01];
- return out_of_spec;
-}
-
-static PyObject *dmi_chassis_type_py(u8 code) {
- return PyString_FromString(dmi_chassis_type(code));
-}
-
-static PyObject *dmi_chassis_lock(u8 code) {
- static const char *lock[] = {
- "Not Present", /* 0x00 */
- "Present" /* 0x01 */
- };
-
- return PyString_FromString(lock[code]);
+void dmi_chassis_type(xmlNode *node, u8 code)
+{
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Desktop",
+ "Low Profile Desktop",
+ "Pizza Box",
+ "Mini Tower",
+ "Tower",
+ "Portable",
+ "Laptop",
+ "Notebook",
+ "Hand Held",
+ "Docking Station",
+ "All In One",
+ "Sub Notebook",
+ "Space-saving",
+ "Lunch Box",
+ "Main Server Chassis", /* CIM_Chassis.ChassisPackageType says "Main System Chassis" */
+ "Expansion Chassis",
+ "Sub Chassis",
+ "Bus Expansion Chassis",
+ "Peripheral Chassis",
+ "RAID Chassis",
+ "Rack Mount Chassis",
+ "Sealed-case PC",
+ "Multi-system",
+ "CompactPCI",
+ "AdvancedTCA", /* 0x1B */
+ "Blade",
+ "Blade Enclosing" /* 0x1D */
+ };
+ xmlNode *type_n = xmlNewChild(node, NULL, (xmlChar *)"ChassisType", NULL);
+ assert( type_n != NULL );
+ dmixml_AddAttribute(type_n, "dmispec", "3.3.4.1");
+ dmixml_AddAttribute(type_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x1B) {
+ dmixml_AddAttribute(type_n, "available", "1");
+ dmixml_AddTextContent(type_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(type_n, "available", "0");
+ }
}
-/* 3.3.4.2 */
-static PyObject *dmi_chassis_state(u8 code) {
- static const char *state[]={
- "Other", /* 0x01 */
- "Unknown",
- "Safe", /* master.mif says OK */
- "Warning",
- "Critical",
- "Non-recoverable" /* 0x06 */
- };
+void dmi_chassis_lock(xmlNode *node, u8 code)
+{
+ static const char *lock[] = {
+ "Not Present", /* 0x00 */
+ "Present" /* 0x01 */
+ };
+ xmlNode *lock_n = xmlNewChild(node, NULL, (xmlChar *) "ChassisLock", NULL);
+ assert( lock_n != NULL );
+ dmixml_AddAttribute(lock_n, "dmispec", "3.3.4");
+ dmixml_AddAttribute(lock_n, "flags", "0x%04x", code);
+ dmixml_AddTextContent(lock_n, "%s", lock[code]);
+}
- if(code>=0x01 && code<=0x06)
- return PyString_FromString(state[code-0x01]);
- return OUT_OF_SPEC;
+/* 3.3.4.2 */
+void dmi_chassis_state(xmlNode *node, const char *tagname, u8 code)
+{
+ static const char *state[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Safe", /* master.mif says OK */
+ "Warning",
+ "Critical",
+ "Non-recoverable" /* 0x06 */
+ };
+ xmlNode *state_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( state_n != NULL );
+ dmixml_AddAttribute(state_n, "dmispec", "3.3.4.2");
+ dmixml_AddAttribute(state_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x06) {
+ dmixml_AddTextContent(state_n, "%s", state[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(state_n, "unavailable", "1");
+ }
}
/* 3.3.4.3 */
-static const char *dmi_chassis_security_status(u8 code) {
- static const char *status[]={
- "Other", /* 0x01 */
- "Unknown",
- "None",
- "External Interface Locked Out",
- "External Interface Enabled" /* 0x05 */
- };
+void dmi_chassis_security_status(xmlNode *node, u8 code)
+{
+ static const char *status[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "None",
+ "External Interface Locked Out",
+ "External Interface Enabled" /* 0x05 */
+ };
+ xmlNode *secstat_n = xmlNewChild(node, NULL, (xmlChar *) "SecurityStatus", NULL);
+ assert( secstat_n != NULL );
+ dmixml_AddAttribute(secstat_n, "dmispec", "3.3.4.3");
+ dmixml_AddAttribute(secstat_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x05) {
+ dmixml_AddTextContent(secstat_n, "%s", status[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(secstat_n, "unavailable", "1");
+ }
+}
+
+void dmi_chassis_height(xmlNode *node, u8 code)
+{
+ xmlNode *hght_n = xmlNewChild(node, NULL, (xmlChar *) "ChassisHeight", NULL);
+ assert( hght_n != NULL );
- if(code>=0x01 && code<=0x05)
- return(status[code-0x01]);
- return out_of_spec;
+ if(code == 0x00) {
+ dmixml_AddAttribute(hght_n, "unspecified", "1");
+ } else {
+ dmixml_AddAttribute(hght_n, "unit", "U");
+ dmixml_AddTextContent(hght_n, "%i", code);
+ }
}
-static PyObject *dmi_chassis_height(u8 code) {
- if(code==0x00) return PyString_FromString("Unspecified");
- else return PyString_FromFormat("%i U", code);
+void dmi_chassis_power_cords(xmlNode *node, u8 code)
+{
+ xmlNode *pwrc_n = xmlNewChild(node, NULL, (xmlChar *) "PowerCords", NULL);
+ assert( pwrc_n != NULL );
+
+ if(code == 0x00) {
+ dmixml_AddAttribute(pwrc_n, "unspecified", "1");
+ } else {
+ dmixml_AddTextContent(pwrc_n, "%i", code);
+ }
}
-static PyObject *dmi_chassis_power_cords(u8 code) {
- if(code==0x00) return PyString_FromString("Unspecified");
- else return PyString_FromFormat("%i", code);
+void dmi_chassis_elements(xmlNode *node, u8 count, u8 len, const u8 * p)
+{
+ int i;
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "ChassisElements", NULL);
+ assert( data_n != NULL );
+
+ dmixml_AddAttribute(data_n, "count", "%i", count);
+
+ for(i = 0; i < count; i++) {
+ if(len >= 0x03) {
+ xmlNode *key_n = NULL;
+
+ if( p[i * len] & 0x80 ) {
+ key_n = dmi_smbios_structure_type(data_n, p[i * len] & 0x7F);
+ } else {
+ key_n = xmlNewChild(data_n, NULL, (xmlChar *) "BaseboardElement", NULL);
+ dmi_base_board_type(key_n, "Description", p[i * len] & 0x7F);
+ }
+ assert( key_n != NULL );
+
+ if(p[1 + i * len] == p[2 + i * len]) {
+ dmixml_AddTextChild(key_n, "Value", "%i", p[1 + i * len]);
+ } else {
+ dmixml_AddTextChild(key_n, "Value", "%i-%i", p[1 + i * len], p[2 + i * len]);
+ }
+ }
+ }
}
-static PyObject *dmi_chassis_elements(u8 count, u8 len, const u8 *p) {
- int i;
+/*******************************************************************************
+** 3.3.5 Processor Information (Type 4)
+*/
- PyObject *data = PyDict_New();
- PyDict_SetItemString(data, "Contained Elements", PyInt_FromLong(count));
+void dmi_processor_type(xmlNode *node, u8 code)
+{
+ /* 3.3.5.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Central Processor",
+ "Math Processor",
+ "DSP Processor",
+ "Video Processor" /* 0x06 */
+ };
+ xmlNode *proct_n = xmlNewChild(node, NULL, (xmlChar *) "Type", NULL);
+ assert( proct_n != NULL );
+ dmixml_AddAttribute(proct_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x06) {
+ dmixml_AddTextContent(proct_n, type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(proct_n, "outofspec", "1");
+ }
+}
- PyObject *_key, *_val;
- for(i=0; i<count; i++) {
- if(len>=0x03) {
+void dmi_processor_family(xmlNode *node, const struct dmi_header *h)
+{
+ const u8 *data = h->data;
+ unsigned int i, low, high;
+ u16 code;
+
+ /* 3.3.5.2 */
+ static struct {
+ int value;
+ const char *name;
+ } family2[] = {
+ /* *INDENT-OFF* */
+ { 0x01, "Other" },
+ { 0x02, "Unknown" },
+ { 0x03, "8086" },
+ { 0x04, "80286" },
+ { 0x05, "80386" },
+ { 0x06, "80486" },
+ { 0x07, "8087" },
+ { 0x08, "80287" },
+ { 0x09, "80387" },
+ { 0x0A, "80487" },
+ { 0x0B, "Pentium" },
+ { 0x0C, "Pentium Pro" },
+ { 0x0D, "Pentium II" },
+ { 0x0E, "Pentium MMX" },
+ { 0x0F, "Celeron" },
+ { 0x10, "Pentium II Xeon" },
+ { 0x11, "Pentium III" },
+ { 0x12, "M1" },
+ { 0x13, "M2" },
+ { 0x14, "Celeron M" }, /* From CIM_Processor.Family */
+ { 0x15, "Pentium 4 HT" }, /* From CIM_Processor.Family */
+
+ { 0x18, "Duron" },
+ { 0x19, "K5" },
+ { 0x1A, "K6" },
+ { 0x1B, "K6-2" },
+ { 0x1C, "K6-3" },
+ { 0x1D, "Athlon" },
+ { 0x1E, "AMD29000" },
+ { 0x1F, "K6-2+" },
+ { 0x20, "Power PC" },
+ { 0x21, "Power PC 601" },
+ { 0x22, "Power PC 603" },
+ { 0x23, "Power PC 603+" },
+ { 0x24, "Power PC 604" },
+ { 0x25, "Power PC 620" },
+ { 0x26, "Power PC x704" },
+ { 0x27, "Power PC 750" },
+ { 0x28, "Core Duo" }, /* From CIM_Processor.Family */
+ { 0x29, "Core Duo Mobile" }, /* From CIM_Processor.Family */
+ { 0x2A, "Core Solo Mobile" }, /* From CIM_Processor.Family */
+ { 0x2B, "Atom" }, /* From CIM_Processor.Family */
+
+ { 0x30, "Alpha" },
+ { 0x31, "Alpha 21064" },
+ { 0x32, "Alpha 21066" },
+ { 0x33, "Alpha 21164" },
+ { 0x34, "Alpha 21164PC" },
+ { 0x35, "Alpha 21164a" },
+ { 0x36, "Alpha 21264" },
+ { 0x37, "Alpha 21364" },
+
+ { 0x40, "MIPS" },
+ { 0x41, "MIPS R4000" },
+ { 0x42, "MIPS R4200" },
+ { 0x43, "MIPS R4400" },
+ { 0x44, "MIPS R4600" },
+ { 0x45, "MIPS R10000" },
+
+ { 0x50, "SPARC" },
+ { 0x51, "SuperSPARC" },
+ { 0x52, "MicroSPARC II" },
+ { 0x53, "MicroSPARC IIep" },
+ { 0x54, "UltraSPARC" },
+ { 0x55, "UltraSPARC II" },
+ { 0x56, "UltraSPARC IIi" },
+ { 0x57, "UltraSPARC III" },
+ { 0x58, "UltraSPARC IIIi" },
+
+ { 0x60, "68040" },
+ { 0x61, "68xxx" },
+ { 0x62, "68000" },
+ { 0x63, "68010" },
+ { 0x64, "68020" },
+ { 0x65, "68030" },
+
+ { 0x70, "Hobbit" },
+
+ { 0x78, "Crusoe TM5000" },
+ { 0x79, "Crusoe TM3000" },
+ { 0x7A, "Efficeon TM8000" },
+
+ { 0x80, "Weitek" },
+
+ { 0x82, "Itanium" },
+ { 0x83, "Athlon 64" },
+ { 0x84, "Opteron" },
+ { 0x85, "Sempron" },
+ { 0x86, "Turion 64" },
+ { 0x87, "Dual-Core Opteron" },
+ { 0x88, "Athlon 64 X2" },
+ { 0x89, "Turion 64 X2" },
+ { 0x8A, "Quad-Core Opteron" }, /* From CIM_Processor.Family */
+ { 0x8B, "Third-Generation Opteron" }, /* From CIM_Processor.Family */
+ { 0x8C, "Phenom FX" }, /* From CIM_Processor.Family */
+ { 0x8D, "Phenom X4" }, /* From CIM_Processor.Family */
+ { 0x8E, "Phenom X2" }, /* From CIM_Processor.Family */
+ { 0x8F, "Athlon X2" }, /* From CIM_Processor.Family */
+ { 0x90, "PA-RISC" },
+ { 0x91, "PA-RISC 8500" },
+ { 0x92, "PA-RISC 8000" },
+ { 0x93, "PA-RISC 7300LC" },
+ { 0x94, "PA-RISC 7200" },
+ { 0x95, "PA-RISC 7100LC" },
+ { 0x96, "PA-RISC 7100" },
+
+ { 0xA0, "V30" },
+ { 0xA1, "Quad-Core Xeon 3200" }, /* From CIM_Processor.Family */
+ { 0xA2, "Dual-Core Xeon 3000" }, /* From CIM_Processor.Family */
+ { 0xA3, "Quad-Core Xeon 5300" }, /* From CIM_Processor.Family */
+ { 0xA4, "Dual-Core Xeon 5100" }, /* From CIM_Processor.Family */
+ { 0xA5, "Dual-Core Xeon 5000" }, /* From CIM_Processor.Family */
+ { 0xA6, "Dual-Core Xeon LV" }, /* From CIM_Processor.Family */
+ { 0xA7, "Dual-Core Xeon ULV" }, /* From CIM_Processor.Family */
+ { 0xA8, "Dual-Core Xeon 7100" }, /* From CIM_Processor.Family */
+ { 0xA9, "Quad-Core Xeon 5400" }, /* From CIM_Processor.Family */
+ { 0xAA, "Quad-Core Xeon" }, /* From CIM_Processor.Family */
+
+ { 0xB0, "Pentium III Xeon" },
+ { 0xB1, "Pentium III Speedstep" },
+ { 0xB2, "Pentium 4" },
+ { 0xB3, "Xeon" },
+ { 0xB4, "AS400" },
+ { 0xB5, "Xeon MP" },
+ { 0xB6, "Athlon XP" },
+ { 0xB7, "Athlon MP" },
+ { 0xB8, "Itanium 2" },
+ { 0xB9, "Pentium M" },
+ { 0xBA, "Celeron D" },
+ { 0xBB, "Pentium D" },
+ { 0xBC, "Pentium EE" },
+ { 0xBD, "Core Solo" },
+ /* 0xBE handled as a special case */
+ { 0xBF, "Core 2 Duo" },
+ { 0xC0, "Core 2 Solo" }, /* From CIM_Processor.Family */
+ { 0xC1, "Core 2 Extreme" }, /* From CIM_Processor.Family */
+ { 0xC2, "Core 2 Quad" }, /* From CIM_Processor.Family */
+ { 0xC3, "Core 2 Extreme Mobile" }, /* From CIM_Processor.Family */
+ { 0xC4, "Core 2 Duo Mobile" }, /* From CIM_Processor.Family */
+ { 0xC5, "Core 2 Solo Mobile" }, /* From CIM_Processor.Family */
+
+ { 0xC8, "IBM390" },
+ { 0xC9, "G4" },
+ { 0xCA, "G5" },
+ { 0xCB, "ESA/390 G6" },
+ { 0xCC, "z/Architectur" },
+
+ { 0xD2, "C7-M" },
+ { 0xD3, "C7-D" },
+ { 0xD4, "C7" },
+ { 0xD5, "Eden" },
+
+ { 0xFA, "i860" },
+ { 0xFB, "i960" },
+
+ { 0x104, "SH-3" },
+ { 0x105, "SH-4" },
+
+ { 0x118, "ARM" },
+ { 0x119, "StrongARM" },
+
+ { 0x12C, "6x86" },
+ { 0x12D, "MediaGX" },
+ { 0x12E, "MII" },
+
+ { 0x140, "WinChip" },
+
+ { 0x15E, "DSP" },
+
+ { 0x1F4, "Video Processor" },
+ /* *INDENT-ON* */
+ };
+
+ /* Linear Search - Slow
+ * for(i=0; i<ARRAY_SIZE(family2); i++)
+ * if (family2[i].value == code)
+ * return family2[i].name;
+ */
+
+ xmlNode *family_n = xmlNewChild(node, NULL, (xmlChar *) "Family", NULL);
+ assert( family_n != NULL );
+ dmixml_AddAttribute(family_n, "dmispec", "3.3.3.5");
+
+ code = (data[0x06] == 0xFE && h->length >= 0x2A) ? WORD(data + 0x28) : data[0x06];
+
+ dmixml_AddAttribute(family_n, "flags", "0x%04x", code);
+
+ /* Special case for ambiguous value 0xBE */
+ if(code == 0xBE) {
+ const char *manufacturer = dmi_string(h, data[0x07]);
+
+ /* Best bet based on manufacturer string */
+ if(strstr(manufacturer, "Intel") != NULL ||
+ strncasecmp(manufacturer, "Intel", 5) == 0) {
+ dmixml_AddTextContent(family_n, "Core 2");
+ return;
+ }
+
+ if(strstr(manufacturer, "AMD") != NULL
+ || strncasecmp(manufacturer, "AMD", 3) == 0) {
+ dmixml_AddTextContent(family_n, "K7");
+ return;
+ }
+ dmixml_AddTextContent(family_n, "Core 2 or K7");
+ return;
+ }
- _key = PyString_FromFormat("%s",
- p[i*len]&0x80?
- dmi_smbios_structure_type(p[i*len]&0x7F):
- PyString_AS_STRING(dmi_base_board_type(p[i*len]&0x7F))
- );
+ /* Perform a binary search */
+ low = 0;
+ high = ARRAY_SIZE(family2) - 1;
+ while(1) {
+ i = (low + high) / 2;
+ if(family2[i].value == code) {
+ dmixml_AddTextContent(family_n, family2[i].name);
+ return;
+ }
+
+ if(low == high) { /* Not found */
+ dmixml_AddAttribute(family_n, "outofspec", "1");
+ return;
+ }
+
+ if(code < family2[i].value)
+ high = i;
+ else
+ low = i + 1;
+ }
+
+ dmixml_AddAttribute(family_n, "outofspec", "1");
+}
- if (p[1+i*len]==p[2+i*len]) _val = PyString_FromFormat("%i", p[1+i*len]);
- else _val = PyString_FromFormat("%i-%i", p[1+i*len], p[2+i*len]);
+xmlNode *dmi_processor_id(xmlNode *node, u8 type, const u8 * p, const char *version)
+{
+ /* Intel AP-485 revision 31, table 3-4 */
+ static struct _cpuflags {
+ const char *flag;
+ const char *descr;
+ } flags[] = {
+ /* *INDENT-OFF* */
+ {"FPU", "FPU (Floating-point unit on-chip)"}, /* 0 */
+ {"VME", "VME (Virtual mode extension)"},
+ {"DE", "DE (Debugging extension)"},
+ {"PSE", "PSE (Page size extension)"},
+ {"TSC", "TSC (Time stamp counter)"},
+ {"MSR", "MSR (Model specific registers)"},
+ {"PAE", "PAE (Physical address extension)"},
+ {"MCE", "MCE (Machine check exception)"},
+ {"CX8", "CX8 (CMPXCHG8 instruction supported)"},
+ {"APIC", "APIC (On-chip APIC hardware supported)"},
+ {NULL, NULL}, /* 10 */
+ {"SEP", "SEP (Fast system call)"},
+ {"MTRR", "MTRR (Memory type range registers)"},
+ {"PGE", "PGE (Page global enable)"},
+ {"MCA", "MCA (Machine check architecture)"},
+ {"CMOV", "CMOV (Conditional move instruction supported)"},
+ {"PAT", "PAT (Page attribute table)"},
+ {"PSE-36", "PSE-36 (36-bit page size extension)"},
+ {"PSN", "PSN (Processor serial number present and enabled)"},
+ {"CLFSH", "CLFLUSH (CLFLUSH instruction supported)"},
+ {NULL, NULL }, /* 20 */
+ {"DS", "DS (Debug store)"},
+ {"ACPI", "ACPI (ACPI supported)"},
+ {"MMX", "MMX (MMX technology supported)"},
+ {"FXSR", "FXSR (Fast floating-point save and restore)"},
+ {"SSE", "SSE (Streaming SIMD extensions)"},
+ {"SSE2", "SSE2 (Streaming SIMD extensions 2)"},
+ {"SS", "SS (Self-snoop)"},
+ {"HTT", "HTT (Hyper-threading technology)"},
+ {"TM", "TM (Thermal monitor supported)"},
+ {"IA64", "IA64 (IA64 capabilities)"},
+ {"PBE", "PBE (Pending break enabled)"} /* 31 */
+ /* *INDENT-ON* */
+ };
+
+ xmlNode *flags_n = NULL;
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "CPUCore", NULL);
+ assert( data_n != NULL );
+
+ /*
+ ** Extra flags are now returned in the ECX register when one calls
+ ** the CPUID instruction. Their meaning is explained in table 3-5, but
+ ** DMI doesn't support this yet.
+ */
+ u32 eax, edx;
+ int sig = 0;
+
+ /*
+ ** This might help learn about new processors supporting the
+ ** CPUID instruction or another form of identification.
+ */
+
+ //. TODO: PyString_FromFormat does not support %x (yet?)...
+ dmixml_AddTextChild(data_n, "ID",
+ "%02x %02x %02x %02x %02x %02x %02x %02x",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+
+ if(type == 0x05) { /* 80386 */
+ u16 dx = WORD(p);
+
+ /*
+ ** 80386 have a different signature.
+ */
+ dmixml_AddTextChild(data_n, "Signature",
+ "Type %i, Family %i, Major Stepping %i, Minor Stepping %i",
+ dx >> 12, (dx >> 8) & 0xF, (dx >> 4) & 0xF, dx & 0xF);
+ return data_n;
+ }
- PyDict_SetItem(data, _key, _val);
+ if(type == 0x06) { /* 80486 */
+ u16 dx = WORD(p);
+
+ /*
+ ** Not all 80486 CPU support the CPUID instruction, we have to find
+ ** wether the one we have here does or not. Note that this trick
+ ** works only because we know that 80486 must be little-endian.
+ */
+ if( (dx & 0x0F00) == 0x0400
+ && ((dx & 0x00F0) == 0x0040 || (dx & 0x00F0) >= 0x0070)
+ && ((dx & 0x000F) >= 0x0003) ) {
+ sig = 1;
+ } else {
+ dmixml_AddTextChild(data_n, "Signature",
+ "Type %i, Family %i, Model %i, Stepping %i",
+ (dx >> 12) & 0x3, (dx >> 8) & 0xF, (dx >> 4) & 0xF,
+ dx & 0xF);
+ return data_n;
+ }
+ } else if((type >= 0x0B && type <= 0x15) /* Intel, Cyrix */
+ ||(type >= 0x28 && type <= 0x2B) /* Intel */
+ ||(type >= 0xA1 && type <= 0xAA) /* Intel */
+ ||(type >= 0xB0 && type <= 0xB3) /* Intel */
+ ||type == 0xB5 /* Intel */
+ || (type >= 0xB9 && type <= 0xC5) /* Intel */
+ ||(type >= 0xD2 && type <= 0xD5) /* VIA */
+ ) {
+
+ sig = 1;
+
+ } else if((type >= 0x18 && type <= 0x1D) /* AMD */
+ ||type == 0x1F /* AMD */
+ || (type >= 0x83 && type <= 0x8F) /* AMD */
+ ||(type >= 0xB6 && type <= 0xB7) /* AMD */
+ ||(type >= 0xE6 && type <= 0xEB) /* AMD */
+ ) {
+
+ sig = 2;
+
+ } else if(type == 0x01 || type == 0x02) {
+ /*
+ ** Some X86-class CPU have family "Other" or "Unknown". In this case,
+ ** we use the version string to determine if they are known to
+ ** support the CPUID instruction.
+ */
+ if(strncmp(version, "Pentium III MMX", 15) == 0
+ || strncmp(version, "Intel(R) Core(TM)2", 18) == 0
+ || strncmp(version, "Intel(R) Pentium(R)", 19) == 0
+ || strcmp(version, "Genuine Intel(R) CPU U1400") == 0
+ ) {
+
+ sig = 1;
+
+ } else if(strncmp(version, "AMD Athlon(TM)", 14) == 0
+ || strncmp(version, "AMD Opteron(tm)", 15) == 0
+ || strncmp(version, "Dual-Core AMD Opteron(tm)", 25) == 0) {
+
+ sig = 2;
+
+ } else {
+ return data_n;
+ }
+ } else { /* not X86-class */
+ return data_n;
+ }
- Py_DECREF(_key);
- Py_DECREF(_val);
- }
- }
+ eax = DWORD(p);
+ edx = DWORD(p + 4);
+ switch (sig) {
+ case 1: /* Intel */
+ dmixml_AddTextChild(data_n, "Signature",
+ "Type %i, Family %i, Model %i, Stepping %i",
+ (eax >> 12) & 0x3, ((eax >> 20) & 0xFF) + ((eax >> 8) & 0x0F),
+ ((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F), eax & 0xF);
+ break;
+ case 2: /* AMD, publication #25481 revision 2.28 */
+ dmixml_AddTextChild(data_n, "Signature",
+ "Family %i, Model %i, Stepping %i",
+ ((eax >> 8) & 0xF) + (((eax >> 8) & 0xF) == 0xF
+ ? (eax >> 20) & 0xFF : 0),
+ ((eax >> 4) & 0xF) | (((eax >> 8) & 0xF) == 0xF
+ ? (eax >> 12) & 0xF0 : 0),
+ eax & 0xF);
+ break;
+ }
- return data;
+ edx = DWORD(p + 4);
+ flags_n = xmlNewChild(data_n, NULL, (xmlChar *) "cpu_flags", NULL);
+ if((edx & 0xFFEFFBFF) != 0) {
+ int i;
+
+ for(i = 0; i <= 31; i++) {
+ if( flags[i].flag != NULL ) {
+ xmlNode *flg_n = dmixml_AddTextChild(flags_n, "flag", "%s", flags[i].descr);
+ dmixml_AddAttribute(flg_n, "available", "%i",
+ (edx & (1 << i) ? 1 : 0));
+ dmixml_AddAttribute(flg_n, "flag", "%s", flags[i].flag);
+ }
+ }
+ }
+ return data_n;
}
-/*******************************************************************************
-** 3.3.5 Processor Information (Type 4)
-*/
+/* 3.3.5.4 */
+void dmi_processor_voltage(xmlNode *node, u8 code)
+{
+ static const char *voltage[] = {
+ "5.0", /* 0 */
+ "3.3",
+ "2.9" /* 2 */
+ };
+ int i;
+ xmlNode *vltg_n = xmlNewChild(node, NULL, (xmlChar *) "Voltages", NULL);
+ assert( vltg_n != NULL );
+ dmixml_AddAttribute(vltg_n, "dmispec", "3.3.5.4");
+ dmixml_AddAttribute(vltg_n, "flags", "0x%04x", code);
+
+ if(code & 0x80) {
+ xmlNode *v_n = dmixml_AddTextChild(vltg_n, "Voltage", "%.1f", (float)(code & 0x7f) / 10);
+ dmixml_AddAttribute(v_n, "unit", "V");
+ } else if( code == 0x00 ) {
+ dmixml_AddAttribute(vltg_n, "unknown_value", "1");
+ } else {
+ for(i = 0; i <= 2; i++) {
+ xmlNode *v_n = dmixml_AddTextChild(vltg_n, "Voltage", "%s", voltage[i]);
+ dmixml_AddAttribute(v_n, "key_compound", "%s V", voltage[i]);
+ dmixml_AddAttribute(v_n, "available", "%i", (code & (1 << i) ? 1 : 0));
+ dmixml_AddAttribute(v_n, "unit", "V");
+ v_n = NULL;
+ }
+ }
+}
+
+int dmi_processor_frequency(const u8 * p)
+{
+ u16 code = WORD(p);
-static PyObject *dmi_processor_type(u8 code) {
- /* 3.3.5.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "Central Processor",
- "Math Processor",
- "DSP Processor",
- "Video Processor" /* 0x06 */
- };
-
- if(code>=0x01 && code<=0x06) return PyString_FromString(type[code-0x01]);
- return OUT_OF_SPEC;
-}
-
-static const char *dmi_processor_family(const struct dmi_header *h) {
- const u8 *data = h->data;
- unsigned int i, low, high;
- u16 code;
-
- /* 3.3.5.2 */
- static struct {
- int value;
- const char *name;
- } family2[] = {
- { 0x01, "Other" },
- { 0x02, "Unknown" },
- { 0x03, "8086" },
- { 0x04, "80286" },
- { 0x05, "80386" },
- { 0x06, "80486" },
- { 0x07, "8087" },
- { 0x08, "80287" },
- { 0x09, "80387" },
- { 0x0A, "80487" },
- { 0x0B, "Pentium" },
- { 0x0C, "Pentium Pro" },
- { 0x0D, "Pentium II" },
- { 0x0E, "Pentium MMX" },
- { 0x0F, "Celeron" },
- { 0x10, "Pentium II Xeon" },
- { 0x11, "Pentium III" },
- { 0x12, "M1" },
- { 0x13, "M2" },
- { 0x14, "Celeron M" }, /* From CIM_Processor.Family */
- { 0x15, "Pentium 4 HT" }, /* From CIM_Processor.Family */
-
- { 0x18, "Duron" },
- { 0x19, "K5" },
- { 0x1A, "K6" },
- { 0x1B, "K6-2" },
- { 0x1C, "K6-3" },
- { 0x1D, "Athlon" },
- { 0x1E, "AMD29000" },
- { 0x1F, "K6-2+" },
- { 0x20, "Power PC" },
- { 0x21, "Power PC 601" },
- { 0x22, "Power PC 603" },
- { 0x23, "Power PC 603+" },
- { 0x24, "Power PC 604" },
- { 0x25, "Power PC 620" },
- { 0x26, "Power PC x704" },
- { 0x27, "Power PC 750" },
- { 0x28, "Core Duo" }, /* From CIM_Processor.Family */
- { 0x29, "Core Duo Mobile" }, /* From CIM_Processor.Family */
- { 0x2A, "Core Solo Mobile" }, /* From CIM_Processor.Family */
- { 0x2B, "Atom" }, /* From CIM_Processor.Family */
-
- { 0x30, "Alpha" },
- { 0x31, "Alpha 21064" },
- { 0x32, "Alpha 21066" },
- { 0x33, "Alpha 21164" },
- { 0x34, "Alpha 21164PC" },
- { 0x35, "Alpha 21164a" },
- { 0x36, "Alpha 21264" },
- { 0x37, "Alpha 21364" },
-
- { 0x40, "MIPS" },
- { 0x41, "MIPS R4000" },
- { 0x42, "MIPS R4200" },
- { 0x43, "MIPS R4400" },
- { 0x44, "MIPS R4600" },
- { 0x45, "MIPS R10000" },
-
- { 0x50, "SPARC" },
- { 0x51, "SuperSPARC" },
- { 0x52, "MicroSPARC II" },
- { 0x53, "MicroSPARC IIep" },
- { 0x54, "UltraSPARC" },
- { 0x55, "UltraSPARC II" },
- { 0x56, "UltraSPARC IIi" },
- { 0x57, "UltraSPARC III" },
- { 0x58, "UltraSPARC IIIi" },
-
- { 0x60, "68040" },
- { 0x61, "68xxx" },
- { 0x62, "68000" },
- { 0x63, "68010" },
- { 0x64, "68020" },
- { 0x65, "68030" },
-
- { 0x70, "Hobbit" },
-
- { 0x78, "Crusoe TM5000" },
- { 0x79, "Crusoe TM3000" },
- { 0x7A, "Efficeon TM8000" },
-
- { 0x80, "Weitek" },
-
- { 0x82, "Itanium" },
- { 0x83, "Athlon 64" },
- { 0x84, "Opteron" },
- { 0x85, "Sempron" },
- { 0x86, "Turion 64" },
- { 0x87, "Dual-Core Opteron" },
- { 0x88, "Athlon 64 X2" },
- { 0x89, "Turion 64 X2" },
- { 0x8A, "Quad-Core Opteron" }, /* From CIM_Processor.Family */
- { 0x8B, "Third-Generation Opteron" }, /* From CIM_Processor.Family */
- { 0x8C, "Phenom FX" }, /* From CIM_Processor.Family */
- { 0x8D, "Phenom X4" }, /* From CIM_Processor.Family */
- { 0x8E, "Phenom X2" }, /* From CIM_Processor.Family */
- { 0x8F, "Athlon X2" }, /* From CIM_Processor.Family */
- { 0x90, "PA-RISC" },
- { 0x91, "PA-RISC 8500" },
- { 0x92, "PA-RISC 8000" },
- { 0x93, "PA-RISC 7300LC" },
- { 0x94, "PA-RISC 7200" },
- { 0x95, "PA-RISC 7100LC" },
- { 0x96, "PA-RISC 7100" },
-
- { 0xA0, "V30" },
- { 0xA1, "Quad-Core Xeon 3200" }, /* From CIM_Processor.Family */
- { 0xA2, "Dual-Core Xeon 3000" }, /* From CIM_Processor.Family */
- { 0xA3, "Quad-Core Xeon 5300" }, /* From CIM_Processor.Family */
- { 0xA4, "Dual-Core Xeon 5100" }, /* From CIM_Processor.Family */
- { 0xA5, "Dual-Core Xeon 5000" }, /* From CIM_Processor.Family */
- { 0xA6, "Dual-Core Xeon LV" }, /* From CIM_Processor.Family */
- { 0xA7, "Dual-Core Xeon ULV" }, /* From CIM_Processor.Family */
- { 0xA8, "Dual-Core Xeon 7100" }, /* From CIM_Processor.Family */
- { 0xA9, "Quad-Core Xeon 5400" }, /* From CIM_Processor.Family */
- { 0xAA, "Quad-Core Xeon" }, /* From CIM_Processor.Family */
-
- { 0xB0, "Pentium III Xeon" },
- { 0xB1, "Pentium III Speedstep" },
- { 0xB2, "Pentium 4" },
- { 0xB3, "Xeon" },
- { 0xB4, "AS400" },
- { 0xB5, "Xeon MP" },
- { 0xB6, "Athlon XP" },
- { 0xB7, "Athlon MP" },
- { 0xB8, "Itanium 2" },
- { 0xB9, "Pentium M" },
- { 0xBA, "Celeron D" },
- { 0xBB, "Pentium D" },
- { 0xBC, "Pentium EE" },
- { 0xBD, "Core Solo" },
- /* 0xBE handled as a special case */
- { 0xBF, "Core 2 Duo" },
- { 0xC0, "Core 2 Solo" }, /* From CIM_Processor.Family */
- { 0xC1, "Core 2 Extreme" }, /* From CIM_Processor.Family */
- { 0xC2, "Core 2 Quad" }, /* From CIM_Processor.Family */
- { 0xC3, "Core 2 Extreme Mobile" }, /* From CIM_Processor.Family */
- { 0xC4, "Core 2 Duo Mobile" }, /* From CIM_Processor.Family */
- { 0xC5, "Core 2 Solo Mobile" }, /* From CIM_Processor.Family */
-
- { 0xC8, "IBM390" },
- { 0xC9, "G4" },
- { 0xCA, "G5" },
- { 0xCB, "ESA/390 G6" },
- { 0xCC, "z/Architectur" },
-
- { 0xD2, "C7-M" },
- { 0xD3, "C7-D" },
- { 0xD4, "C7" },
- { 0xD5, "Eden" },
-
- { 0xFA, "i860" },
- { 0xFB, "i960" },
-
- { 0x104, "SH-3" },
- { 0x105, "SH-4" },
-
- { 0x118, "ARM" },
- { 0x119, "StrongARM" },
-
- { 0x12C, "6x86" },
- { 0x12D, "MediaGX" },
- { 0x12E, "MII" },
-
- { 0x140, "WinChip" },
-
- { 0x15E, "DSP" },
-
- { 0x1F4, "Video Processor" },
- };
-
- /* Linear Search - Slow
- for(i=0; i<ARRAY_SIZE(family2); i++)
- if (family2[i].value == code)
- return family2[i].name;
- */
-
- code = (data[0x06]==0xFE && h->length>=0x2A)?WORD(data+0x28):data[0x06];
-
- /* Special case for ambiguous value 0xBE */
- if(code == 0xBE) {
- const char *manufacturer = dmi_string(h, data[0x07]);
-
- /* Best bet based on manufacturer string */
- if(strstr(manufacturer, "Intel") != NULL || strncasecmp(manufacturer, "Intel", 5) == 0)
- return "Core 2";
- if(strstr(manufacturer, "AMD") != NULL || strncasecmp(manufacturer, "AMD", 3) == 0)
- return "K7";
- return "Core 2 or K7";
- }
-
- /* Perform a binary search */
- low = 0;
- high = ARRAY_SIZE(family2) - 1;
- while(1) {
- i = (low + high) / 2;
- if (family2[i].value == code) return family2[i].name;
- if (low == high) /* Not found */ return out_of_spec;
- if (code < family2[i].value) high = i;
- else low = i + 1;
- }
-
- return out_of_spec;
-}
-
-static PyObject *dmi_processor_id(u8 type, const u8 *p, const char *version) {
- PyObject *data = PyDict_New();
-
- /* Intel AP-485 revision 31, table 3-4 */
- static const char *flags[32]={
- "FPU (Floating-point unit on-chip)", /* 0 */
- "VME (Virtual mode extension)",
- "DE (Debugging extension)",
- "PSE (Page size extension)",
- "TSC (Time stamp counter)",
- "MSR (Model specific registers)",
- "PAE (Physical address extension)",
- "MCE (Machine check exception)",
- "CX8 (CMPXCHG8 instruction supported)",
- "APIC (On-chip APIC hardware supported)",
- NULL, /* 10 */
- "SEP (Fast system call)",
- "MTRR (Memory type range registers)",
- "PGE (Page global enable)",
- "MCA (Machine check architecture)",
- "CMOV (Conditional move instruction supported)",
- "PAT (Page attribute table)",
- "PSE-36 (36-bit page size extension)",
- "PSN (Processor serial number present and enabled)",
- "CLFSH (CLFLUSH instruction supported)",
- NULL, /* 20 */
- "DS (Debug store)",
- "ACPI (ACPI supported)",
- "MMX (MMX technology supported)",
- "FXSR (Fast floating-point save and restore)",
- "SSE (Streaming SIMD extensions)",
- "SSE2 (Streaming SIMD extensions 2)",
- "SS (Self-snoop)",
- "HTT (Hyper-threading technology)",
- "TM (Thermal monitor supported)",
- "IA64 (IA64 capabilities)",
- "PBE (Pending break enabled)" /* 31 */
- };
- /*
- ** Extra flags are now returned in the ECX register when one calls
- ** the CPUID instruction. Their meaning is explained in table 3-5, but
- ** DMI doesn't support this yet.
- */
- u32 eax, edx;
- int sig=0;
-
- /*
- ** This might help learn about new processors supporting the
- ** CPUID instruction or another form of identification.
- */
-
- //. TODO: PyString_FromFormat does not support %x (yet?)...
- PyDict_SetItemString(data, "ID",
- PyString_FromFormat("%02x %02x %02x %02x %02x %02x %02x %02x",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]
- )
- );
-
- if(type==0x05) /* 80386 */ {
- u16 dx=WORD(p);
- /*
- ** 80386 have a different signature.
- */
- PyDict_SetItemString(data, "Signature",
- PyString_FromFormat(
- "Type %i, Family %i, Major Stepping %i, Minor Stepping %i",
- dx>>12, (dx>>8)&0xF, (dx>>4)&0xF, dx&0xF
- )
- );
- return data;
- }
-
- if(type==0x06) /* 80486 */ {
- u16 dx=WORD(p);
- /*
- ** Not all 80486 CPU support the CPUID instruction, we have to find
- ** wether the one we have here does or not. Note that this trick
- ** works only because we know that 80486 must be little-endian.
- */
- if((dx&0x0F00)==0x0400
- &&((dx&0x00F0)==0x0040 || (dx&0x00F0)>=0x0070)
- &&((dx&0x000F)>=0x0003)) sig=1;
- else {
- PyDict_SetItemString(data, "Signature",
- PyString_FromFormat(
- "Type %i, Family %i, Model %i, Stepping %i",
- (dx>>12)&0x3, (dx>>8)&0xF, (dx>>4)&0xF, dx&0xF
- )
- );
- return data;
- }
- } else if(
- (
- type >= 0x0B && type <= 0x15) /* Intel, Cyrix */
- || (type >= 0x28 && type <= 0x2B) /* Intel */
- || (type >= 0xA1 && type <= 0xAA) /* Intel */
- || (type >= 0xB0 && type <= 0xB3) /* Intel */
- || type == 0xB5 /* Intel */
- || (type >= 0xB9 && type <= 0xC5) /* Intel */
- || (type >= 0xD2 && type <= 0xD5) /* VIA */
- ) sig=1;
- else if(
- (
- type >= 0x18 && type <= 0x1D) /* AMD */
- || type == 0x1F /* AMD */
- || (type >= 0x83 && type <= 0x8F) /* AMD */
- || (type >= 0xB6 && type <= 0xB7) /* AMD */
- || (type >= 0xE6 && type <= 0xEB) /* AMD */
- ) sig=2;
- else if(type==0x01 || type==0x02) {
- /*
- ** Some X86-class CPU have family "Other" or "Unknown". In this case,
- ** we use the version string to determine if they are known to
- ** support the CPUID instruction.
- */
- if(
- strncmp(version, "Pentium III MMX", 15) == 0
- || strncmp(version, "Intel(R) Core(TM)2", 18) == 0
- || strncmp(version, "Intel(R) Pentium(R)", 19) == 0
- || strcmp(version, "Genuine Intel(R) CPU U1400") == 0
- ) sig = 1;
- else if(
- strncmp(version, "AMD Athlon(TM)", 14) == 0
- || strncmp(version, "AMD Opteron(tm)", 15) == 0
- || strncmp(version, "Dual-Core AMD Opteron(tm)", 25) == 0
- ) sig = 2;
- else return data;
- } else /* not X86-class */ return data;
-
- eax=DWORD(p);
- edx=DWORD(p+4);
- switch(sig) {
- case 1: /* Intel */
- PyDict_SetItemString(data, "Signature",
- PyString_FromFormat(
- "Type %i, Family %i, Model %i, Stepping %i",
- (eax>>12)&0x3, ((eax>>20)&0xFF)+((eax>>8)&0x0F),
- ((eax>>12)&0xF0)+((eax>>4)&0x0F), eax&0xF
- )
- );
- break;
- case 2: /* AMD, publication #25481 revision 2.28 */
- PyDict_SetItemString(data, "Signature",
- PyString_FromFormat(
- "Family %i, Model %i, Stepping %i",
- ((eax>>8)&0xF)+(((eax>>8)&0xF)==0xF?(eax>>20)&0xFF:0),
- ((eax>>4)&0xF)|(((eax>>8)&0xF)==0xF?(eax>>12)&0xF0:0),
- eax&0xF
- )
- );
- break;
- }
-
- edx=DWORD(p+4);
- if((edx&0xFFEFFBFF)==0) PyDict_SetItemString(data, "Flags", Py_None);
- else {
- int i;
- PyObject *subdata = PyDict_New();
- for(i=0; i<=31; i++)
- if(flags[i]!=NULL)
- PyDict_SetItemString(subdata, flags[i], (edx&(1<<i))?Py_True:Py_False);
- PyDict_SetItemString(data, "Flags", subdata);
- Py_DECREF(subdata);
- }
-
- return data;
+ if(code)
+ return code; //. Value measured in MHz
+ else
+ return -1; //. Unknown
}
-/* 3.3.5.4 */
-static PyObject *dmi_processor_voltage(u8 code) {
- static const char *voltage[]={
- "5.0 V", /* 0 */
- "3.3 V",
- "2.9 V" /* 2 */
- };
- int i;
-
- PyObject *data;
- if(code&0x80) data = PyString_FromFormat("%.1f V", (float)(code&0x7f)/10);
- else {
- data = PyDict_New();
- for(i=0; i<=2; i++)
- PyDict_SetItemString(data, voltage[i], (code&(1<<i)?Py_True:Py_False));
- if(code==0x00)
- PyDict_SetItemString(data, "VOLTAGE", PyString_FromString("Unknown"));
- }
- return data;
-}
-
-int dmi_processor_frequency(const u8 *p) {
- u16 code = WORD(p);
-
- if(code) return code; //. Value measured in MHz
- else return -1; //. Unknown
-}
-static PyObject *dmi_processor_frequency_py(const u8 *p) {
- return PyInt_FromLong(dmi_processor_frequency(p));
-}
-
-static const char *dmi_processor_status(u8 code) {
- static const char *status[] = {
- "Unknown", /* 0x00 */
- "Enabled",
- "Disabled By User",
- "Disabled By BIOS",
- "Idle", /* 0x04 */
- "Other" /* 0x07 */
- };
-
- if(code<=0x04) return status[code];
- if(code==0x07) return status[0x05];
- return out_of_spec;
-}
-
-static PyObject *dmi_processor_upgrade(u8 code) {
- /* 3.3.5.5 */
- static const char *upgrade[]={
- "Other", /* 0x01 */
- "Unknown",
- "Daughter Board",
- "ZIF Socket",
- "Replaceable Piggy Back",
- "None",
- "LIF Socket",
- "Slot 1",
- "Slot 2",
- "370-pin Socket",
- "Slot A",
- "Slot M",
- "Socket 423",
- "Socket A (Socket 462)",
- "Socket 478",
- "Socket 754",
- "Socket 940",
- "Socket 939",
- "Socket mPGA604",
- "Socket LGA771",
- "Socket LGA775", /* 0x15 */
- "Socket S1",
- "Socket AM2",
- "Socket F (1207)" /* 0x18 */
- };
-
- if(code>=0x01 && code<=0x15) return PyString_FromString(upgrade[code-0x01]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_processor_cache(u16 code, const char *level, u16 ver) {
- PyObject *data;
- if(code==0xFFFF) {
- if(ver>=0x0203) data = PyString_FromString("Not Provided");
- else data = PyString_FromFormat("No %s Cache", level);
- } else data = PyString_FromFormat("0x%04x", code);
- return data;
+void dmi_processor_status(xmlNode *node, u8 code)
+{
+ static const char *status[] = {
+ "Unknown", /* 0x00 */
+ "Enabled",
+ "Disabled By User",
+ "Disabled By BIOS",
+ "Idle", /* 0x04 */
+ "Other" /* 0x07 */
+ };
+ xmlNode *prst_n = xmlNewChild(node, NULL, (xmlChar *) "Populated", NULL);
+ assert( prst_n != NULL );
+
+ dmixml_AddAttribute(prst_n, "flags", "0x%04x", code);
+
+ if(code <= 0x04) {
+ dmixml_AddTextContent(prst_n, "%s", status[code]);
+ } else if( code == 0x07 ) {
+ dmixml_AddTextContent(prst_n, "%s", status[5]);
+ } else {
+ dmixml_AddAttribute(prst_n, "outofspec", "1");
+ }
+}
+
+void dmi_processor_upgrade(xmlNode *node, u8 code)
+{
+ /* 3.3.5.5 */
+ static const char *upgrade[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Daughter Board",
+ "ZIF Socket",
+ "Replaceable Piggy Back",
+ "None",
+ "LIF Socket",
+ "Slot 1",
+ "Slot 2",
+ "370-pin Socket",
+ "Slot A",
+ "Slot M",
+ "Socket 423",
+ "Socket A (Socket 462)",
+ "Socket 478",
+ "Socket 754",
+ "Socket 940",
+ "Socket 939",
+ "Socket mPGA604",
+ "Socket LGA771",
+ "Socket LGA775", /* 0x15 */
+ "Socket S1",
+ "Socket AM2",
+ "Socket F (1207)" /* 0x18 */
+ };
+ xmlNode *upgr_n = xmlNewChild(node, NULL, (xmlChar *) "Upgrade", NULL);
+ assert( upgr_n != NULL );
+ dmixml_AddAttribute(upgr_n, "dmispec", "3.3.5.5");
+ dmixml_AddAttribute(upgr_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x15) {
+ dmixml_AddTextContent(upgr_n, "%s", upgrade[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(upgr_n, "outofspec", "1");
+ }
+}
+
+void dmi_processor_cache(xmlNode *cache_n, u16 code, u16 ver)
+{
+ assert( cache_n != NULL );
+
+ dmixml_AddAttribute(cache_n, "ver", "0x%04x", ver);
+
+ if(code == 0xFFFF) {
+ dmixml_AddAttribute(cache_n, "flags", "0x%04x", code);
+ if(ver >= 0x0203) {
+ dmixml_AddAttribute(cache_n, "provided", "0");
+ dmixml_AddAttribute(cache_n, "available", "1");
+ } else {
+ dmixml_AddAttribute(cache_n, "available", "0");
+ }
+ } else {
+ dmixml_AddAttribute(cache_n, "provided", "1");
+ dmixml_AddAttribute(cache_n, "available", "1");
+ dmixml_AddAttribute(cache_n, "handle", "0x%04x", code);
+ }
}
/* 3.3.5.9 */
-static PyObject *dmi_processor_characteristics(u16 code) {
- static const char *characteristics[]={
- "64-bit capable" /* 2 */
- };
-
- PyObject *data;
- if((code&0x0004)==0) {
- data = Py_None;
- } else {
- data = PyList_New(1);
- int i;
- for(i=2; i<=2; i++)
- if(code&(1<<i))
- PyList_SET_ITEM(data, 0, PyString_FromString(characteristics[i-2]));
- }
- return data;
+void dmi_processor_characteristics(xmlNode *node, u16 code)
+{
+ static const char *characteristics[] = {
+ "Unknown", /* 1 */
+ "64-bit capable" /* 2 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Characteristics", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.5.9");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if((code & 0x0004) != 0) {
+ int i;
+
+ for(i = 1; i <= 2; i++) {
+ if(code & (1 << i)) {
+ dmixml_AddTextChild(data_n, "Flag", "%s", characteristics[i - 1]);
+ }
+ }
+ }
}
/*******************************************************************************
** 3.3.6 Memory Controller Information (Type 5)
*/
-static PyObject *dmi_memory_controller_ed_method(u8 code) {
- /* 3.3.6.1 */
- static const char *method[]={
- "Other", /* 0x01 */
- "Unknown",
- "None",
- "8-bit Parity",
- "32-bit ECC",
- "64-bit ECC",
- "128-bit ECC",
- "CRC" /* 0x08 */
- };
-
- if(code>=0x01 && code<=0x08) return(PyString_FromString(method[code-0x01]));
- return OUT_OF_SPEC;
+void dmi_memory_controller_ed_method(xmlNode *node, u8 code)
+{
+ /* 3.3.6.1 */
+ static const char *method[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "None",
+ "8-bit Parity",
+ "32-bit ECC",
+ "64-bit ECC",
+ "128-bit ECC",
+ "CRC" /* 0x08 */
+ };
+ xmlNode *ercm_n = xmlNewChild(node, NULL, (xmlChar *) "CorrectionMethod", NULL);
+ assert( ercm_n != NULL );
+ dmixml_AddAttribute(ercm_n, "dmispec", "3.3.6.1");
+ dmixml_AddAttribute(ercm_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x08) {
+ dmixml_AddTextContent(ercm_n, method[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(ercm_n, "outofspec", "1");
+ }
}
/* 3.3.6.2 */
-static PyObject *dmi_memory_controller_ec_capabilities(u8 code) {
- static const char *capabilities[]={
- "Other", /* 0 */
- "Unknown",
- "None",
- "Single-bit Error Correcting",
- "Double-bit Error Correcting",
- "Error Scrubbing" /* 5 */
- };
-
- PyObject *data = Py_None;
- if((code&0x3F)==0) return Py_None;
- else {
- int i;
-
- data = PyList_New(6);
- for(i=0; i<=5; i++)
- if(code&(1<<i))
- PyList_SET_ITEM(data, i, PyString_FromString(capabilities[i]));
- else
- PyList_SET_ITEM(data, i, Py_None);
- }
- return data;
-}
-
-static PyObject *dmi_memory_controller_interleave(u8 code) {
- /* 3.3.6.3 */
- static const char *interleave[]={
- "Other", /* 0x01 */
- "Unknown",
- "One-way Interleave",
- "Two-way Interleave",
- "Four-way Interleave",
- "Eight-way Interleave",
- "Sixteen-way Interleave" /* 0x07 */
- };
-
- if(code>=0x01 && code<=0x07) return PyString_FromString(interleave[code-0x01]);
- return OUT_OF_SPEC;
+void dmi_memory_controller_ec_capabilities(xmlNode *node, const char *tagname, u8 code)
+{
+ static const char *capabilities[] = {
+ "Other", /* 0 */
+ "Unknown",
+ "None",
+ "Single-bit Error Correcting",
+ "Double-bit Error Correcting",
+ "Error Scrubbing" /* 5 */
+ };
+
+ xmlNode *cap_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( cap_n != NULL );
+ dmixml_AddAttribute(cap_n, "dmispec", "3.3.6.2");
+ dmixml_AddAttribute(cap_n, "flags", "0x%04x", code);
+
+ if((code & 0x3F) != 0) {
+ int i;
+ for(i = 0; i <= 5; i++) {
+ if(code & (1 << i)) {
+ xmlNode *c_n = dmixml_AddTextChild(cap_n, "Capability", "%s", capabilities[i]);
+ assert( c_n != NULL );
+ dmixml_AddAttribute(c_n, "index", "%i", i+1);
+ }
+ }
+ }
+}
+
+void dmi_memory_controller_interleave(xmlNode *node, const char *tagname, u8 code)
+{
+ /* 3.3.6.3 */
+ static const char *interleave[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "One-way Interleave",
+ "Two-way Interleave",
+ "Four-way Interleave",
+ "Eight-way Interleave",
+ "Sixteen-way Interleave" /* 0x07 */
+ };
+ xmlNode *mci_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( mci_n != NULL );
+ dmixml_AddAttribute(mci_n, "dmispec", "3.3.6.3");
+ dmixml_AddAttribute(mci_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x07) {
+ dmixml_AddTextContent(mci_n, interleave[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(mci_n, "outofspec", "1");
+ }
}
/* 3.3.6.4 */
-static PyObject *dmi_memory_controller_speeds(u16 code) {
- const char *speeds[]={
- "Other", /* 0 */
- "Unknown",
- "70 ns",
- "60 ns",
- "50 ns" /* 4 */
- };
-
- PyObject *data;
- if((code&0x001F)!=0) data = Py_None;
- else {
- int i;
-
- data = PyList_New(5);
- for(i=0; i<=4; i++)
- if(code&(1<<i))
- PyList_SET_ITEM(data, i, PyString_FromString(speeds[i]));
- else
- PyList_SET_ITEM(data, i, Py_None);
- }
- return data;
-}
-
-static PyObject *dmi_memory_controller_slots(u8 count, const u8 *p) {
- int i;
-
- PyObject *data = PyList_New(count);
- for(i=0; i<count; i++)
- PyList_SET_ITEM(data, i, PyString_FromFormat("0x%04x:", WORD(p+sizeof(u16)*i)));
- return data;
+void dmi_memory_controller_speeds(xmlNode *node, u16 code)
+{
+ static struct {
+ const char *value;
+ const char *unit;
+ } const speeds[] = {
+ {"Other", NULL}, /* 0 */
+ {"Unknown", NULL},
+ {"70", "ns"},
+ {"60", "ns"},
+ {"50", "ns"} /* 4 */
+ };
+ xmlNode *mcs_n = xmlNewChild(node, NULL, (xmlChar *) "SupportedSpeeds", NULL);
+ assert( mcs_n != NULL );
+ dmixml_AddAttribute(mcs_n, "dmispec", "3.3.6.4");
+ dmixml_AddAttribute(mcs_n, "flags", "0x%04x", code);
+
+ if((code & 0x001F) == 0) {
+ int i;
+ for(i = 0; i <= 4; i++) {
+ if(code & (1 << i)) {
+ xmlNode *ms_n = dmixml_AddTextChild(mcs_n, "Speed", "%s", speeds[i].value);
+ assert( ms_n != NULL );
+ dmixml_AddAttribute(ms_n, "index", "%i", i);
+ if( speeds[i].unit != NULL ) {
+ dmixml_AddAttribute(ms_n, "unit", speeds[i].unit);
+ }
+ ms_n = NULL;
+ }
+ }
+ }
+}
+
+void dmi_memory_controller_slots(xmlNode *node, u8 count, const u8 * p)
+{
+ int i;
+ xmlNode *mslts_n = xmlNewChild(node, NULL, (xmlChar *) "AssociatedMemorySlots", NULL);
+ assert( mslts_n != NULL );
+
+ for(i = 0; i < count; i++) {
+ xmlNode *sl_n = dmixml_AddTextChild(mslts_n, "Slot", "0x%x:", WORD(p + sizeof(u16) * i));
+ dmixml_AddAttribute(sl_n, "index", "%i", i);
+ }
}
/*******************************************************************************
@@ -1182,1617 +1422,2205 @@ static PyObject *dmi_memory_controller_slots(u8 count, const u8 *p) {
*/
/* 3.3.7.1 */
-static PyObject *dmi_memory_module_types(u16 code) {
- static const char *types[]={
- "Other", /* 0 */
- "Unknown",
- "Standard",
- "FPM",
- "EDO",
- "Parity",
- "ECC",
- "SIMM",
- "DIMM",
- "Burst EDO",
- "SDRAM" /* 10 */
- };
-
- PyObject *data;
- if((code&0x07FF)==0) data = Py_None;
- else {
- int i;
-
- data = PyList_New(11);
- for(i=0; i<=10; i++)
- if(code&(1<<i))
- PyList_SET_ITEM(data, i, PyString_FromString( types[i]));
- else
- PyList_SET_ITEM(data, i, Py_None);
- }
- return data;
-}
-
-static PyObject *dmi_memory_module_connections(u8 code) {
- PyObject * data;
- if(code==0xFF) data = Py_None;
- else {
- data = PyList_New(0);
- if((code&0xF0)!=0xF0) PyList_Append(data, PyInt_FromLong(code>>4));
- if((code&0x0F)!=0x0F) PyList_Append(data, PyInt_FromLong(code&0x0F));
- }
- return data;
-}
-
-static PyObject *dmi_memory_module_speed(u8 code) {
- if(code==0) return PyString_FromString("Unknown");
- else return PyString_FromFormat("%i ns", code);
+void dmi_memory_module_types(xmlNode *node, const char *tagname, u16 code)
+{
+ static const char *types[] = {
+ "Other", /* 0 */
+ "Unknown",
+ "Standard",
+ "FPM",
+ "EDO",
+ "Parity",
+ "ECC",
+ "SIMM",
+ "DIMM",
+ "Burst EDO",
+ "SDRAM" /* 10 */
+ };
+ xmlNode *mmt_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( mmt_n != NULL );
+ dmixml_AddAttribute(mmt_n, "dmispec", "3.3.7.1");
+ dmixml_AddAttribute(mmt_n, "flags", "0x%04x", code);
+
+ if((code & 0x07FF) != 0) {
+ int i;
+
+ for(i = 0; i <= 10; i++) {
+ if(code & (1 << i)) {
+ xmlNode *mt_n = dmixml_AddTextChild(mmt_n, "ModuleType", types[i]);
+ assert( mt_n != NULL );
+ dmixml_AddAttribute(mt_n, "index", "%i", i+1);
+ }
+ }
+ }
+}
+
+void dmi_memory_module_connections(xmlNode *node, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "BankConnections", NULL);
+ assert( data_n != NULL );
+
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code != 0xFF) {
+ if((code & 0xF0) != 0xF0) {
+ dmixml_AddTextChild(data_n, "Connection", "%ld", (code >> 4));
+ }
+ if((code & 0x0F) != 0x0F) {
+ dmixml_AddTextChild(data_n, "Connection", "%ld", (code & 0x0F));
+ }
+ }
+}
+
+void dmi_memory_module_speed(xmlNode *node, const char *tagname, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+
+ dmixml_AddAttribute(data_n, "code", "0x%04x", code);
+
+ if(code != 0) {
+ dmixml_AddAttribute(data_n, "unit", "ns");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
}
/* 3.3.7.2 */
-static PyObject *dmi_memory_module_size(u8 code) {
- PyObject *data = PyDict_New();
- int check_conn = 1;
-
- switch(code&0x7F) {
- case 0x7D:
- PyDict_SetItemString(data, "Size", PyString_FromString("Not Determinable"));
- break;
- case 0x7E:
- PyDict_SetItemString(data, "Size", PyString_FromString("Disabled"));
- break;
- case 0x7F:
- PyDict_SetItemString(data, "Size", PyString_FromString("Not Installed"));
- check_conn = 0;
- default:
- PyDict_SetItemString(data, "Size", PyString_FromFormat("%i MB", 1<<(code&0x7F)));
- }
-
- if(check_conn) {
- if(code&0x80) PyDict_SetItemString(data, "Connection", PyString_FromString("Double-bank"));
- else PyDict_SetItemString(data, "Connection", PyString_FromString("Single-bank"));
- }
- return data;
-}
-
-static PyObject *dmi_memory_module_error(u8 code) {
- PyObject *data = NULL;
- if(code&(1<<2)) data = Py_None; //. TODO: sprintf(_, "See Event Log");
- else {
- if((code&0x03)==0) data = Py_True;
- if(code&(1<<0)) data = PyString_FromString("Uncorrectable Errors");
- if(code&(1<<1)) data = PyString_FromString("Correctable Errors");
- }
- return data;
+void dmi_memory_module_size(xmlNode *node, const char *tagname, u8 code)
+{
+ int check_conn = 1;
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.7.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ switch (code & 0x7F) {
+ case 0x7D:
+ dmixml_AddAttribute(data_n, "Error", "Size not determinable");
+ break;
+ case 0x7E:
+ dmixml_AddAttribute(data_n, "Error", "Disabled");
+ break;
+ case 0x7F:
+ dmixml_AddAttribute(data_n, "installed", "0");
+ check_conn = 0;
+ default:
+ dmixml_AddAttribute(data_n, "installed", "1");
+ dmixml_AddAttribute(data_n, "unit", "MB");
+ dmixml_AddTextContent(data_n, "%i", 1 << (code & 0x7F));
+ }
+
+ if(check_conn) {
+ dmixml_AddAttribute(data_n, "Connection", ((code & 0x80) ? "Double-bank" : "Single-bank"));
+ }
+}
+
+void dmi_memory_module_error(xmlNode *node, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "ModuleErrorStatus", NULL);
+ assert( data_n != NULL );
+
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if( !(code & (1 << 2)) ) {
+ if((code & 0x03) == 0) {
+ dmixml_AddAttribute(data_n, "Error", "1");
+ }
+ if(code & (1 << 0)) {
+ dmixml_AddTextContent(data_n, "Uncorrectable Errors");
+ }
+ if(code & (1 << 1)) {
+ dmixml_AddTextContent(data_n, "Correctable Errors");
+ }
+ }
}
/*******************************************************************************
** 3.3.8 Cache Information (Type 7)
*/
-static PyObject *dmi_cache_mode(u8 code) {
- static const char *mode[]={
- "Write Through", /* 0x00 */
- "Write Back",
- "Varies With Memory Address",
- "Unknown" /* 0x03 */
- };
+static const char *dmi_cache_mode(u8 code)
+{
+ static const char *mode[] = {
+ "Write Through", /* 0x00 */
+ "Write Back",
+ "Varies With Memory Address",
+ "Unknown" /* 0x03 */
+ };
- return PyString_FromString(mode[code]);
+ return mode[code];
}
-static PyObject *dmi_cache_location(u8 code) {
- static const char *location[4]={
- "Internal", /* 0x00 */
- "External",
- NULL, /* 0x02 */
- "Unknown" /* 0x03 */
- };
-
- PyObject *data;
- if(location[code]!=NULL) data = PyString_FromString(location[code]);
- else data = OUT_OF_SPEC;
- return data;
+void dmi_cache_location(xmlNode *node, u8 code)
+{
+ static const char *location[4] = {
+ "Internal", /* 0x00 */
+ "External",
+ NULL, /* 0x02 */
+ "Unknown" /* 0x03 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "CacheLocation", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.8");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(location[code] != NULL) {
+ dmixml_AddTextContent(data_n, location[code]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
-static PyObject *dmi_cache_size(u16 code) {
- PyObject *data;
- if(code&0x8000) data = PyString_FromFormat("%i KB", (code&0x7FFF)<<6);
- else data = PyString_FromFormat("%i KB", code);
- return data;
+void dmi_cache_size(xmlNode *node, const char *tagname, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.8");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code & 0x8000) {
+ dmixml_AddAttribute(data_n, "unit", "KB");
+ dmixml_AddTextContent(data_n, "%i", (code & 0x7FFF) << 6);
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "KB");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
}
/* 3.3.8.2 */
-static PyObject *dmi_cache_types(u16 code) {
- static const char *types[] = {
- "Other", /* 0 */
- "Unknown",
- "Non-burst",
- "Burst",
- "Pipeline Burst",
- "Synchronous",
- "Asynchronous" /* 6 */
- };
- PyObject *data;
-
- if((code&0x007F)==0) data = Py_None;
- else {
- int i;
-
- data = PyList_New(7);
- for(i=0; i<=6; i++)
- if(code&(1<<i))
- PyList_SET_ITEM(data, i, PyString_FromString(types[i]));
- else
- PyList_SET_ITEM(data, i, Py_None);
- }
- return data;
-}
-
-static PyObject *dmi_cache_ec_type(u8 code) {
- /* 3.3.8.3 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "None",
- "Parity",
- "Single-bit ECC",
- "Multi-bit ECC" /* 0x06 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x06) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_cache_type(u8 code) {
- /* 3.3.8.4 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "Instruction",
- "Data",
- "Unified" /* 0x05 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x05) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_cache_associativity(u8 code) {
- /* 3.3.8.5 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "Direct Mapped",
- "2-way Set-associative",
- "4-way Set-associative",
- "Fully Associative",
- "8-way Set-associative",
- "16-way Set-associative" /* 0x08 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x08) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
+void dmi_cache_types(xmlNode *node, const char *tagname, u16 code)
+{
+ static const char *types[] = {
+ "Other", /* 0 */
+ "Unknown",
+ "Non-burst",
+ "Burst",
+ "Pipeline Burst",
+ "Synchronous",
+ "Asynchronous" /* 6 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.8.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+
+ if((code & 0x007F) != 0) {
+ int i;
+ for(i = 0; i <= 6; i++) {
+ if(code & (1 << i)) {
+ xmlNode *n = dmixml_AddTextChild(data_n, "CacheType", "%s", types[i]);
+ dmixml_AddAttribute(n, "index", "%i", i+1);
+ }
+ }
+ }
+}
+
+void dmi_cache_ec_type(xmlNode *node, u8 code)
+{
+ /* 3.3.8.3 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "None",
+ "Parity",
+ "Single-bit ECC",
+ "Multi-bit ECC" /* 0x06 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "ErrorCorrectionType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.8.3");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x06) {
+ dmixml_AddTextContent(data_n, type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_cache_type(xmlNode *node, u8 code)
+{
+ /* 3.3.8.4 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Instruction",
+ "Data",
+ "Unified" /* 0x05 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "SystemType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.8.4");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x05) {
+ dmixml_AddTextContent(data_n, type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_cache_associativity(xmlNode *node, u8 code)
+{
+ /* 3.3.8.5 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Direct Mapped",
+ "2-way Set-associative",
+ "4-way Set-associative",
+ "Fully Associative",
+ "8-way Set-associative",
+ "16-way Set-associative" /* 0x08 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Associativity", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.8.5");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x08) {
+ dmixml_AddTextContent(data_n, type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/*******************************************************************************
** 3.3.9 Port Connector Information (Type 8)
*/
-static PyObject *dmi_port_connector_type(u8 code) {
- /* 3.3.9.2 */
- static const char *type[] = {
- "None", /* 0x00 */
- "Centronics",
- "Mini Centronics",
- "Proprietary",
- "DB-25 male",
- "DB-25 female",
- "DB-15 male",
- "DB-15 female",
- "DB-9 male",
- "DB-9 female",
- "RJ-11",
- "RJ-45",
- "50 Pin MiniSCSI",
- "Mini DIN",
- "Micro DIN",
- "PS/2",
- "Infrared",
- "HP-HIL",
- "Access Bus (USB)",
- "SSA SCSI",
- "Circular DIN-8 male",
- "Circular DIN-8 female",
- "On Board IDE",
- "On Board Floppy",
- "9 Pin Dual Inline (pin 10 cut)",
- "25 Pin Dual Inline (pin 26 cut)",
- "50 Pin Dual Inline",
- "68 Pin Dual Inline",
- "On Board Sound Input From CD-ROM",
- "Mini Centronics Type-14",
- "Mini Centronics Type-26",
- "Mini Jack (headphones)",
- "BNC",
- "IEEE 1394",
- "SAS/SATA Plug Receptacle" /* 0x22 */
- };
- static const char *type_0xA0[]={
- "PC-98", /* 0xA0 */
- "PC-98 Hireso",
- "PC-H98",
- "PC-98 Note",
- "PC-98 Full" /* 0xA4 */
- };
-
- if(code<=0x22) return PyString_FromString(type[code]);
- if(code>=0xA0 && code<=0xA4) return PyString_FromString(type_0xA0[code-0xA0]);
- if(code==0xFF) return PyString_FromString("Other");
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_port_type(u8 code) {
- /* 3.3.9.3 */
- static const char *type[] = {
- "None", /* 0x00 */
- "Parallel Port XT/AT Compatible",
- "Parallel Port PS/2",
- "Parallel Port ECP",
- "Parallel Port EPP",
- "Parallel Port ECP/EPP",
- "Serial Port XT/AT Compatible",
- "Serial Port 16450 Compatible",
- "Serial Port 16550 Compatible",
- "Serial Port 16550A Compatible",
- "SCSI Port",
- "MIDI Port",
- "Joystick Port",
- "Keyboard Port",
- "Mouse Port",
- "SSA SCSI",
- "USB",
- "Firewire (IEEE P1394)",
- "PCMCIA Type I",
- "PCMCIA Type II",
- "PCMCIA Type III",
- "Cardbus",
- "Access Bus Port",
- "SCSI II",
- "SCSI Wide",
- "PC-98",
- "PC-98 Hireso",
- "PC-H98",
- "Video Port",
- "Audio Port",
- "Modem Port",
- "Network Port",
- "SATA",
- "SAS" /* 0x21 */
- };
- static const char *type_0xA0[]={
- "8251 Compatible", /* 0xA0 */
- "8251 FIFO Compatible" /* 0xA1 */
- };
-
- if(code<=0x21) return PyString_FromString(type[code]);
- if(code>=0xA0 && code<=0xA1) return PyString_FromString(type_0xA0[code-0xA0]);
- if(code==0xFF) return PyString_FromString("Other");
- return OUT_OF_SPEC;
+void dmi_port_connector_type(xmlNode *node, const char *tpref, u8 code)
+{
+ /* 3.3.9.2 */
+ static const char *type[] = {
+ "None", /* 0x00 */
+ "Centronics",
+ "Mini Centronics",
+ "Proprietary",
+ "DB-25 male",
+ "DB-25 female",
+ "DB-15 male",
+ "DB-15 female",
+ "DB-9 male",
+ "DB-9 female",
+ "RJ-11",
+ "RJ-45",
+ "50 Pin MiniSCSI",
+ "Mini DIN",
+ "Micro DIN",
+ "PS/2",
+ "Infrared",
+ "HP-HIL",
+ "Access Bus (USB)",
+ "SSA SCSI",
+ "Circular DIN-8 male",
+ "Circular DIN-8 female",
+ "On Board IDE",
+ "On Board Floppy",
+ "9 Pin Dual Inline (pin 10 cut)",
+ "25 Pin Dual Inline (pin 26 cut)",
+ "50 Pin Dual Inline",
+ "68 Pin Dual Inline",
+ "On Board Sound Input From CD-ROM",
+ "Mini Centronics Type-14",
+ "Mini Centronics Type-26",
+ "Mini Jack (headphones)",
+ "BNC",
+ "IEEE 1394",
+ "SAS/SATA Plug Receptacle" /* 0x22 */
+ };
+ static const char *type_0xA0[] = {
+ "PC-98", /* 0xA0 */
+ "PC-98 Hireso",
+ "PC-H98",
+ "PC-98 Note",
+ "PC-98 Full" /* 0xA4 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Connector", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.9.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+ dmixml_AddAttribute(data_n, "type", "%s", tpref);
+
+ if(code <= 0x22) {
+ dmixml_AddTextContent(data_n, type[code]);
+ } else if(code >= 0xA0 && code <= 0xA4) {
+ dmixml_AddTextContent(data_n, type_0xA0[code - 0xA0]);
+ } else if(code == 0xFF) {
+ dmixml_AddTextContent(data_n, "Other");
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_port_type(xmlNode *node, u8 code)
+{
+ /* 3.3.9.3 */
+ static const char *type[] = {
+ "None", /* 0x00 */
+ "Parallel Port XT/AT Compatible",
+ "Parallel Port PS/2",
+ "Parallel Port ECP",
+ "Parallel Port EPP",
+ "Parallel Port ECP/EPP",
+ "Serial Port XT/AT Compatible",
+ "Serial Port 16450 Compatible",
+ "Serial Port 16550 Compatible",
+ "Serial Port 16550A Compatible",
+ "SCSI Port",
+ "MIDI Port",
+ "Joystick Port",
+ "Keyboard Port",
+ "Mouse Port",
+ "SSA SCSI",
+ "USB",
+ "Firewire (IEEE P1394)",
+ "PCMCIA Type I",
+ "PCMCIA Type II",
+ "PCMCIA Type III",
+ "Cardbus",
+ "Access Bus Port",
+ "SCSI II",
+ "SCSI Wide",
+ "PC-98",
+ "PC-98 Hireso",
+ "PC-H98",
+ "Video Port",
+ "Audio Port",
+ "Modem Port",
+ "Network Port",
+ "SATA",
+ "SAS" /* 0x21 */
+ };
+ static const char *type_0xA0[] = {
+ "8251 Compatible", /* 0xA0 */
+ "8251 FIFO Compatible" /* 0xA1 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "PortType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.9.3");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 0x21) {
+ dmixml_AddTextContent(data_n, type[code]);
+ } else if(code >= 0xA0 && code <= 0xA1) {
+ dmixml_AddTextContent(data_n, type_0xA0[code - 0xA0]);
+ } else if(code == 0xFF) {
+ dmixml_AddTextContent(data_n, "Other");
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/*******************************************************************************
** 3.3.10 System Slots (Type 9)
*/
-static PyObject *dmi_slot_type(u8 code) {
- /* 3.3.10.1 */
- static const char *type[] = {
- "Other", /* 0x01 */
- "Unknown",
- "ISA",
- "MCA",
- "EISA",
- "PCI",
- "PC Card (PCMCIA)",
- "VLB",
- "Proprietary",
- "Processor Card",
- "Proprietary Memory Card",
- "I/O Riser Card",
- "NuBus",
- "PCI-66",
- "AGP",
- "AGP 2x",
- "AGP 4x",
- "PCI-X",
- "AGP 8x" /* 0x13 */
- };
- static const char *type_0xA0[]={
- "PC-98/C20", /* 0xA0 */
- "PC-98/C24",
- "PC-98/E",
- "PC-98/Local Bus",
- "PC-98/Card",
- "PCI Express",
- "PCI Express x1",
- "PCI Express x2",
- "PCI Express x4",
- "PCI Express x8",
- "PCI Express x16" /* 0xAA */
- };
-
- if(code>=0x01 && code<=0x13) return PyString_FromString(type[code-0x01]);
- if(code>=0xA0 && code<=0xAA) return PyString_FromString(type_0xA0[code-0xA0]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_slot_bus_width(u8 code) {
- /* 3.3.10.2 */
- static const char *width[]={
- "", /* 0x01, "Other" */
- "", /* "Unknown" */
- "8-bit ",
- "16-bit ",
- "32-bit ",
- "64-bit ",
- "128-bit ",
- "x1 ",
- "x2 ",
- "x4 ",
- "x8 ",
- "x12 ",
- "x16 ",
- "x32 " /* 0x0E */
- };
-
- if(code>=0x01 && code<=0x0E) return PyString_FromString(width[code-0x01]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_slot_current_usage(u8 code) {
- /* 3.3.10.3 */
- static const char *usage[]={
- "Other", /* 0x01 */
- "Unknown",
- "Available",
- "In Use" /* 0x04 */
- };
-
- if(code>=0x01 && code<=0x04) return PyString_FromString(usage[code-0x01]);
- return OUT_OF_SPEC;
+void dmi_slot_type(xmlNode *node, u8 code)
+{
+ /* 3.3.10.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "ISA",
+ "MCA",
+ "EISA",
+ "PCI",
+ "PC Card (PCMCIA)",
+ "VLB",
+ "Proprietary",
+ "Processor Card",
+ "Proprietary Memory Card",
+ "I/O Riser Card",
+ "NuBus",
+ "PCI-66",
+ "AGP",
+ "AGP 2x",
+ "AGP 4x",
+ "PCI-X",
+ "AGP 8x" /* 0x13 */
+ };
+ static const char *type_0xA0[] = {
+ "PC-98/C20", /* 0xA0 */
+ "PC-98/C24",
+ "PC-98/E",
+ "PC-98/Local Bus",
+ "PC-98/Card",
+ "PCI Express",
+ "PCI Express x1",
+ "PCI Express x2",
+ "PCI Express x4",
+ "PCI Express x8",
+ "PCI Express x16" /* 0xAA */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "SlotType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.10.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x13) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else if(code >= 0xA0 && code <= 0xAA) {
+ dmixml_AddTextContent(data_n, "%s", type_0xA0[code - 0xA0]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
-/* 3.3.1O.4 */
-static PyObject *dmi_slot_length(u8 code) {
- static const char *length[]={
- "Other", /* 0x01 */
- "Unknown",
- "Short",
- "Long" /* 0x04 */
- };
+void dmi_slot_bus_width(xmlNode *node, u8 code)
+{
+ /* 3.3.10.2 */
+ static const char *width[] = {
+ "", /* 0x01, "Other" */
+ "", /* "Unknown" */
+ "8-bit ",
+ "16-bit ",
+ "32-bit ",
+ "64-bit ",
+ "128-bit ",
+ "x1 ",
+ "x2 ",
+ "x4 ",
+ "x8 ",
+ "x12 ",
+ "x16 ",
+ "x32 " /* 0x0E */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "SlotWidth", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.10.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if( (code >= 0x01) && (code <= 0x0E) ) {
+ dmixml_AddTextContent(data_n, "%s", width[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_slot_current_usage(xmlNode *node, u8 code)
+{
+ /* 3.3.10.3 */
+ static const char *usage[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Available",
+ "In Use" /* 0x04 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "CurrentUsage", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.10.3");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+
+ if(code >= 0x01 && code <= 0x04) {
+ dmixml_AddTextContent(data_n, usage[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
- if(code>=0x01 && code<=0x04)
- return PyString_FromString(length[code-0x01]);
- return OUT_OF_SPEC;
+/* 3.3.1O.4 */
+void dmi_slot_length(xmlNode *node, u8 code)
+{
+ static const char *length[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Short",
+ "Long" /* 0x04 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "SlotLength", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.10.4");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x04) {
+ dmixml_AddTextContent(data_n, length[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/* 3.3.10.5 */
-static PyObject *dmi_slot_id(u8 code1, u8 code2, u8 type) {
- PyObject *data;
- switch(type) {
- case 0x04: /* MCA */
- data = PyString_FromFormat("%i", code1);
- break;
- case 0x05: /* EISA */
- data = PyString_FromFormat("%i", code1);
- break;
- case 0x06: /* PCI */
- case 0x0E: /* PCI */
- case 0x0F: /* AGP */
- case 0x10: /* AGP */
- case 0x11: /* AGP */
- case 0x12: /* PCI-X */
- case 0x13: /* AGP */
- case 0xA5: /* PCI Express */
- data = PyString_FromFormat("%i", code1);
- break;
- case 0x07: /* PCMCIA */
- data = PyString_FromFormat("Adapter %i, Socket %i", code1, code2);
- break;
- default:
- data = Py_None;
- }
- return data;
-}
-
-static PyObject *dmi_slot_characteristics(u8 code1, u8 code2) {
- /* 3.3.10.6 */
- static const char *characteristics1[]={
- "5.0 V is provided", /* 1 */
- "3.3 V is provided",
- "Opening is shared",
- "PC Card-16 is supported",
- "Cardbus is supported",
- "Zoom Video is supported",
- "Modem ring resume is supported" /* 7 */
- };
-
- /* 3.3.10.7 */
- static const char *characteristics2[]={
- "PME signal is supported", /* 0 */
- "Hot-plug devices are supported",
- "SMBus signal is supported" /* 2 */
- };
-
- PyObject *data;
- if(code1&(1<<0)) data = PyString_FromString("Unknown");
- else if((code1&0xFE)==0 && (code2&0x07)==0) data = Py_None;
- else {
- int i;
-
- data = PyList_New(7+3);
- for(i=1; i<=7; i++) {
- if(code1&(1<<i)) PyList_SET_ITEM(data, i-1, PyString_FromString(characteristics1[i-1]));
- else PyList_SET_ITEM(data, i-1, Py_None);
- }
- for(i=0; i<=2; i++) {
- if(code2&(1<<i)) PyList_SET_ITEM(data, 7+i, PyString_FromString(characteristics2[i]));
- else PyList_SET_ITEM(data, 7+i, Py_None);
- }
- }
- return data;
-}
-
-static PyObject *dmi_slot_segment_bus_func(u16 code1, u8 code2, u8 code3) {
- /* 3.3.10.8 */
- PyObject *data;
- if(!(code1 == 0xFFFF && code2 == 0xFF && code3 == 0xFF))
- data = PyString_FromFormat("%04x:%02x:%02x.%x", code1, code2, code3 >> 3, code3 & 0x7);
- else data = Py_None;
- return data;
+void inline set_slottype(xmlNode *node, u8 type) {
+ switch (type) {
+ case 0x04: /* MCA */
+ dmixml_AddAttribute(node, "slottype", "MCA");
+ break;
+ case 0x05: /* EISA */
+ dmixml_AddAttribute(node, "slottype", "EISA");
+ break;
+ case 0x06: /* PCI */
+ case 0x0E: /* PCI */
+ dmixml_AddAttribute(node, "slottype", "PCI");
+ break;
+ case 0x0F: /* AGP */
+ case 0x10: /* AGP */
+ case 0x11: /* AGP */
+ case 0x13: /* AGP */
+ dmixml_AddAttribute(node, "slottype", "");
+ break;
+ case 0x12: /* PCI-X */
+ dmixml_AddAttribute(node, "slottype", "PCI-X");
+ break;
+ case 0xA5: /* PCI Express */
+ dmixml_AddAttribute(node, "slottype", "PCI Express");
+ break;
+ case 0x07: /* PCMCIA */
+ dmixml_AddAttribute(node, "slottype", "PCMCIA");
+ break;
+ default:
+ break;
+ }
+}
+
+void dmi_slot_id(xmlNode *node, u8 code1, u8 code2, u8 type)
+{
+ xmlNode *slotid_n = xmlNewChild(node, NULL, (xmlChar *) "SlotID", NULL);
+ dmixml_AddAttribute(slotid_n, "dmispec", "3.3.10.5");
+ dmixml_AddAttribute(slotid_n, "flags1", "0x%04x", code1);
+ dmixml_AddAttribute(slotid_n, "flags2", "0x%04x", code2);
+ dmixml_AddAttribute(slotid_n, "type", "0x%04x", type);
+ switch (type) {
+ case 0x04: /* MCA */
+ dmixml_AddAttribute(slotid_n, "id", "%i", code1);
+ break;
+ case 0x05: /* EISA */
+ dmixml_AddAttribute(slotid_n, "id", "%i", code1);
+ break;
+ case 0x06: /* PCI */
+ case 0x0E: /* PCI */
+ case 0x0F: /* AGP */
+ case 0x10: /* AGP */
+ case 0x11: /* AGP */
+ case 0x12: /* PCI-X */
+ case 0x13: /* AGP */
+ case 0xA5: /* PCI Express */
+ dmixml_AddAttribute(slotid_n, "id", "%i", code1);
+ break;
+ case 0x07: /* PCMCIA */
+ dmixml_AddAttribute(slotid_n, "adapter", "%i", code1);
+ dmixml_AddAttribute(slotid_n, "id", "%i", code2);
+ break;
+ default:
+ break;
+ }
+ set_slottype(slotid_n, type);
+}
+
+void dmi_slot_characteristics(xmlNode *node, u8 code1, u8 code2)
+{
+ /* 3.3.10.6 */
+ static const char *characteristics1[] = {
+ "5.0 V is provided", /* 1 */
+ "3.3 V is provided",
+ "Opening is shared",
+ "PC Card-16 is supported",
+ "Cardbus is supported",
+ "Zoom Video is supported",
+ "Modem ring resume is supported" /* 7 */
+ };
+
+ /* 3.3.10.7 */
+ static const char *characteristics2[] = {
+ "PME signal is supported", /* 0 */
+ "Hot-plug devices are supported",
+ "SMBus signal is supported" /* 2 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "SlotCharacteristics", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.10.6");
+ dmixml_AddAttribute(data_n, "flags1", "0x%04x", code1);
+ dmixml_AddAttribute(data_n, "flags2", "0x%04x", code2);
+
+ if(code1 & (1 << 0)) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else if((code1 & 0xFE) == 0 && (code2 & 0x07) == 0) {
+ // Nothing - empty tag
+ } else {
+ int i;
+
+ for(i = 1; i <= 7; i++) {
+ if(code1 & (1 << i)) {
+ xmlNode *c_n = dmixml_AddTextChild(data_n, "Characteristic", "%s",
+ characteristics1[i - 1]);
+ dmixml_AddAttribute(c_n, "index", "%i", i);
+ c_n = NULL;
+ }
+ }
+ for(i = 0; i <= 2; i++) {
+ if(code2 & (1 << i)) {
+ xmlNode *c_n = dmixml_AddTextChild(data_n, "Characteristic", "%s",
+ characteristics2[i]);
+ dmixml_AddAttribute(c_n, "index", "%i", i+8);
+ c_n = NULL;
+ }
+ }
+ }
+}
+
+void dmi_slot_segment_bus_func(xmlNode *node, u16 code1, u8 code2, u8 code3)
+{
+ /* 3.3.10.8 */
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "BusAddress", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.10.8");
+
+ if(!(code1 == 0xFFFF && code2 == 0xFF && code3 == 0xFF)) {
+ dmixml_AddTextContent(data_n, "%04x:%02x:%02x.%x", code1, code2, code3 >> 3, code3 & 0x7);
+ }
}
/*******************************************************************************
** 3.3.11 On Board Devices Information (Type 10)
*/
-static const char *dmi_on_board_devices_type(u8 code) {
- /* 3.3.11.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "Video",
- "SCSI Controller",
- "Ethernet",
- "Token Ring",
- "Sound",
- "PATA Controller",
- "SATA Controller",
- "SAS Controller" /* 0x0A */
- };
-
- if(code>=0x01 && code<=0x0A) return type[code-0x01];
- return out_of_spec;
-}
-
-static PyObject *dmi_on_board_devices(struct dmi_header *h) {
- PyObject *data = NULL;
- u8 *p = h->data+4;
- u8 count = (h->length-0x04)/2;
- int i;
-
- if((data = PyList_New(count))) {
- PyObject *_pydict;
- PyObject *_val;
- for(i=0; i<count; i++) {
- _pydict = PyDict_New();
-
- _val = PyString_FromString(dmi_on_board_devices_type(p[2*i]&0x7F));
- PyDict_SetItemString(_pydict, "Type", _val);
- Py_DECREF(_val);
-
- _val = p[2*i]&0x80?Py_True:Py_False;
- PyDict_SetItemString(_pydict, "Enabled", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, p[2*i+1]);
- PyDict_SetItemString(_pydict, "Description", _val);
- Py_DECREF(_val);
-
- PyList_SET_ITEM(data, i, _pydict);
- }
- }
-
- assert(data != NULL);
- Py_INCREF(data);
- return data;
+void dmi_on_board_devices_type(xmlNode *node, u8 code)
+{
+ /* 3.3.11.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Video",
+ "SCSI Controller",
+ "Ethernet",
+ "Token Ring",
+ "Sound",
+ "PATA Controller",
+ "SATA Controller",
+ "SAS Controller" /* 0x0A */
+ };
+
+ dmixml_AddAttribute(node, "dmispec", "3.3.11.1");
+ dmixml_AddAttribute(node, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0A) {
+ dmixml_AddTextChild(node, "Type", "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(node, "outofspec", "1");
+ }
+}
+
+void dmi_on_board_devices(xmlNode *node, const char *tagname, struct dmi_header *h)
+{
+ u8 *p = h->data + 4;
+ u8 count = (h->length - 0x04) / 2;
+ int i;
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.11");
+
+ for(i = 0; i < count; i++) {
+ xmlNode *dev_n = xmlNewChild(data_n, NULL, (xmlChar *) "Device", NULL);
+ assert( dev_n != NULL );
+
+ dmi_on_board_devices_type(dev_n, p[2 * i] & 0x7F);
+ dmixml_AddAttribute(dev_n, "Enabled", "%i", ((p[2 * i] & 0x80) ? 1 : 0));
+ dmixml_AddTextChild(dev_n, "Description", "%s", dmi_string(h, p[2 * i + 1]));
+ dev_n = NULL;
+ }
}
/*******************************************************************************
* 3.3.12 OEM Strings (Type 11)
*/
-static PyObject *dmi_oem_strings(struct dmi_header *h) {
- u8 *p=h->data+4;
- u8 count=p[0x00];
- int i;
-
- PyObject *data = PyDict_New();
- PyObject *val;
+void dmi_oem_strings(xmlNode *node, struct dmi_header *h)
+{
+ u8 *p = h->data + 4;
+ u8 count = p[0x00];
+ int i;
- for(i=1; i<=count; i++) {
- val = dmi_string_py(h, i);
- PyDict_SetItem(data, PyInt_FromLong(i), val);
- Py_DECREF(val);
- }
+ dmixml_AddAttribute(node, "count", "%i", count);
- return data;
+ for(i = 1; i <= count; i++) {
+ xmlNode *str_n = dmixml_AddTextChild(node, "Record", "%s", dmi_string(h, i));
+ assert( str_n != NULL );
+ dmixml_AddAttribute(str_n, "index", "%i", i);
+ }
}
/*******************************************************************************
** 3.3.13 System Configuration Options (Type 12)
*/
-static PyObject *dmi_system_configuration_options(struct dmi_header *h) {
- u8 *p=h->data+4;
- u8 count=p[0x00];
- int i;
+void dmi_system_configuration_options(xmlNode *node, struct dmi_header *h)
+{
+ u8 *p = h->data + 4;
+ u8 count = p[0x00];
+ int i;
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Options", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.13");
+ dmixml_AddAttribute(data_n, "count", "%i", count);
- PyObject *data = PyDict_New();
- PyObject *val;
- for(i=1; i<=count; i++) {
- val = dmi_string_py(h, i);
- PyDict_SetItem(data, PyInt_FromLong(i), val);
- Py_DECREF(val);
- }
+ for(i = 1; i <= count; i++) {
+ xmlNode *o_n = dmixml_AddTextChild(data_n, "Option", "%s", dmi_string(h, i));
+ assert( o_n != NULL );
- return data;
+ dmixml_AddAttribute(o_n, "index", "%ld", i);
+ }
}
/*******************************************************************************
** 3.3.14 BIOS Language Information (Type 13)
*/
-static PyObject *dmi_bios_languages(struct dmi_header *h) {
- u8 *p = h->data+4;
- u8 count = p[0x00];
- int i;
-
- PyObject *data = PyList_New(count + 1);
- for(i=1; i<=count; i++)
- PyList_SET_ITEM(data, i, dmi_string_py(h, i));
-
- return data;
+void dmi_bios_languages(xmlNode *node, struct dmi_header *h)
+{
+ u8 *p = h->data + 4;
+ u8 count = p[0x00];
+ int i;
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Installed", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.14");
+ dmixml_AddAttribute(data_n, "count", "%i", count);
+
+ for(i = 1; i <= count; i++) {
+ xmlNode *l_n = dmixml_AddTextChild(data_n, "Language", "%s", dmi_string(h, i));
+ assert( l_n != NULL );
+ dmixml_AddAttribute(l_n, "index", "%i", i);
+ }
}
/*******************************************************************************
** 3.3.15 Group Associations (Type 14)
*/
-static PyObject *dmi_group_associations_items(u8 count, const u8 *p) {
- int i;
+void dmi_group_associations_items(xmlNode *node, u8 count, const u8 * p)
+{
+ dmixml_AddAttribute(node, "dmispec", "3.3.15");
+ dmixml_AddAttribute(node, "items", "%i", count);
+
+ int i;
+ for(i = 0; i < count; i++) {
+ xmlNode *grp_n = xmlNewChild(node, NULL, (xmlChar *) "Group", NULL);
+ assert( grp_n != NULL );
- PyObject *data = PyList_New(count);
- PyObject *val;
- for(i=0; i<count; i++) {
- val = PyString_FromFormat("0x%04x (%s)",
- WORD(p+3*i+1),
- dmi_smbios_structure_type(p[3*i])
- );
- PyList_SET_ITEM(data, i, val);
- }
- return data;
+ dmixml_AddAttribute(grp_n, "handle", "0x%04x", WORD(p + 3 * i + 1));
+ dmi_smbios_structure_type(grp_n, p[3 * i]);
+ }
}
/*******************************************************************************
** 3.3.16 System Event Log (Type 15)
*/
-static const char *dmi_event_log_method(u8 code) {
- static const char *method[]={
- "Indexed I/O, one 8-bit index port, one 8-bit data port", /* 0x00 */
- "Indexed I/O, two 8-bit index ports, one 8-bit data port",
- "Indexed I/O, one 16-bit index port, one 8-bit data port",
- "Memory-mapped physical 32-bit address",
- "General-purpose non-volatile data functions" /* 0x04 */
- };
-
- if(code<=0x04) return method[code];
- if(code>=0x80) return "OEM-specific";
- return out_of_spec;
-}
-
-static PyObject *dmi_event_log_status_py(u8 code) {
- static const char *valid[]={
- "Invalid", /* 0 */
- "Valid" /* 1 */
- };
- static const char *full[]={
- "Not Full", /* 0 */
- "Full" /* 1 */
- };
-
- return PyString_FromFormat("%s, %s", valid[(code>>0)&1], full[(code>>1)&1]);
-}
-
-static PyObject *dmi_event_log_address_py(u8 method, const u8 *p) {
- /* 3.3.16.3 */
- switch(method) {
- case 0x00:
- case 0x01:
- case 0x02:
- return PyString_FromFormat("Index 0x%04x, Data 0x%04x", WORD(p), WORD(p+2));
- break;
- case 0x03:
- return PyString_FromFormat("0x%08x", DWORD(p));
- break;
- case 0x04:
- return PyString_FromFormat("0x%04x", WORD(p));
- break;
- default:
- return PyString_FromString("Unknown");
- }
-}
-
-static const char *dmi_event_log_header_type(u8 code) {
- static const char *type[]={
- "No Header", /* 0x00 */
- "Type 1" /* 0x01 */
- };
-
- if(code<=0x01) return type[code];
- if(code>=0x80) return "OEM-specific";
- return out_of_spec;
-}
-
-static PyObject *dmi_event_log_descriptor_type(u8 code) {
- /* 3.3.16.6.1 */
- static const char *type[]={
- NULL, /* 0x00 */
- "Single-bit ECC memory error",
- "Multi-bit ECC memory error",
- "Parity memory error",
- "Bus timeout",
- "I/O channel block",
- "Software NMI",
- "POST memory resize",
- "POST error",
- "PCI parity error",
- "PCI system error",
- "CPU failure",
- "EISA failsafe timer timeout",
- "Correctable memory log disabled",
- "Logging disabled",
- NULL, /* 0x0F */
- "System limit exceeded",
- "Asynchronous hardware timer expired",
- "System configuration information",
- "Hard disk information",
- "System reconfigured",
- "Uncorrectable CPU-complex error",
- "Log area reset/cleared",
- "System boot" /* 0x17 */
- };
-
- const char *data;
- if(code<=0x17 && type[code]!=NULL) data = type[code];
- else if(code>=0x80 && code<=0xFE) data = "OEM-specific";
- else if(code==0xFF) data = "End of log";
- else data = out_of_spec;
- return PyString_FromString(data);
-}
-
-static PyObject *dmi_event_log_descriptor_format(u8 code) {
- /* 3.3.16.6.2 */
- static const char *format[]={
- "None", /* 0x00 */
- "Handle",
- "Multiple-event",
- "Multiple-event handle",
- "POST results bitmap",
- "System management",
- "Multiple-event system management" /* 0x06 */
- };
-
- const char *data;
- if(code<=0x06) data = format[code];
- else if(code>=0x80) data = "OEM-specific";
- else data = out_of_spec;
- return PyString_FromString(data);
-}
-
-static PyObject *dmi_event_log_descriptors(u8 count, const u8 len, const u8 *p) {
- /* 3.3.16.1 */
- int i;
-
- PyObject* data;
- data = PyList_New(count);
- for(i=0; i<count; i++) {
- if(len>=0x02) {
- PyObject *subdata = PyDict_New();
- PyDict_SetItemString(subdata, "Descriptor", dmi_event_log_descriptor_type(p[i*len]));
- PyDict_SetItemString(subdata, "Data Format", dmi_event_log_descriptor_format(p[i*len+1]));
- PyList_SET_ITEM(data, i, subdata);
- }
- }
- return data;
+void dmi_event_log_method(xmlNode *node, u8 code)
+{
+ static const char *method[] = {
+ "Indexed I/O, one 8-bit index port, one 8-bit data port", /* 0x00 */
+ "Indexed I/O, two 8-bit index ports, one 8-bit data port",
+ "Indexed I/O, one 16-bit index port, one 8-bit data port",
+ "Memory-mapped physical 32-bit address",
+ "General-purpose non-volatile data functions" /* 0x04 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "AccessMethod", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.16");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 0x04) {
+ dmixml_AddTextContent(data_n, "%s", method[code]);
+ } else if(code >= 0x80){
+ dmixml_AddTextContent(data_n, "OEM-specific");
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_event_log_status(xmlNode *node, u8 code)
+{
+ static const char *valid[] = {
+ "Invalid", /* 0 */
+ "Valid" /* 1 */
+ };
+ static const char *full[] = {
+ "Not Full", /* 0 */
+ "Full" /* 1 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Status", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.16");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ // FIXME: Should we use 0/1 instead of strings?
+ dmixml_AddAttribute(data_n, "Full", "%s", full[(code >> 1) & 1]);
+ dmixml_AddAttribute(data_n, "Valid", "%s", valid[(code >> 0) & 1]);
+}
+
+void dmi_event_log_address(xmlNode *node, u8 method, const u8 * p)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Address", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.16.3");
+ dmixml_AddAttribute(data_n, "method", "0x%04x", method);
+
+ /* 3.3.16.3 */
+ switch (method) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ dmixml_AddAttribute(data_n, "Index", "0x%04x", WORD(p));
+ dmixml_AddAttribute(data_n, "Data", "0x%04x", WORD(p + 2));
+ break;
+ case 0x03:
+ dmixml_AddAttribute(data_n, "Data", "0x%08x", DWORD(p));
+ break;
+ case 0x04:
+ dmixml_AddAttribute(data_n, "Data", "0x%04x", WORD(p));
+ break;
+ default:
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ }
+}
+
+void dmi_event_log_header_type(xmlNode *node, u8 code)
+{
+ static const char *type[] = {
+ "No Header", /* 0x00 */
+ "Type 1" /* 0x01 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Format", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.16");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 0x01) {
+ dmixml_AddTextContent(data_n, type[code]);
+ } else if(code >= 0x80) {
+ dmixml_AddTextContent(data_n, "OEM-specific");
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_event_log_descriptor_type(xmlNode *node, u8 code)
+{
+ /* 3.3.16.6.1 */
+ static const char *type[] = {
+ NULL, /* 0x00 */
+ "Single-bit ECC memory error",
+ "Multi-bit ECC memory error",
+ "Parity memory error",
+ "Bus timeout",
+ "I/O channel block",
+ "Software NMI",
+ "POST memory resize",
+ "POST error",
+ "PCI parity error",
+ "PCI system error",
+ "CPU failure",
+ "EISA failsafe timer timeout",
+ "Correctable memory log disabled",
+ "Logging disabled",
+ NULL, /* 0x0F */
+ "System limit exceeded",
+ "Asynchronous hardware timer expired",
+ "System configuration information",
+ "Hard disk information",
+ "System reconfigured",
+ "Uncorrectable CPU-complex error",
+ "Log area reset/cleared",
+ "System boot" /* 0x17 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Descriptor", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.16.6.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 0x17 && type[code] != NULL) {
+ dmixml_AddTextContent(data_n, "%s", type[code]);
+ } else if(code >= 0x80 && code <= 0xFE) {
+ dmixml_AddTextContent(data_n, "OEM-specific");
+ } else if(code == 0xFF) {
+ dmixml_AddTextContent(data_n, "End of log");
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_event_log_descriptor_format(xmlNode *node, u8 code)
+{
+ /* 3.3.16.6.2 */
+ static const char *format[] = {
+ "None", /* 0x00 */
+ "Handle",
+ "Multiple-event",
+ "Multiple-event handle",
+ "POST results bitmap",
+ "System management",
+ "Multiple-event system management" /* 0x06 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Format", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.16.6.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 0x06) {
+ dmixml_AddTextContent(data_n, format[code]);
+ } else if(code >= 0x80) {
+ dmixml_AddTextContent(data_n, "OEM-specific");
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_event_log_descriptors(xmlNode *node, u8 count, const u8 len, const u8 * p)
+{
+ /* 3.3.16.1 */
+ int i;
+
+ dmixml_AddAttribute(node, "dmispec", "3.3.16.1");
+
+ for(i = 0; i < count; i++) {
+ if(len >= 0x02) {
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "LogType", NULL);
+ assert( data_n != NULL );
+
+ dmi_event_log_descriptor_type(data_n, p[i * len]);
+ dmi_event_log_descriptor_format(data_n, p[i * len + 1]);
+ }
+ }
}
/*******************************************************************************
** 3.3.17 Physical Memory Array (Type 16)
*/
-static PyObject *dmi_memory_array_location(u8 code) {
- /* 3.3.17.1 */
- static const char *location[]={
- "Other", /* 0x01 */
- "Unknown",
- "System Board Or Motherboard",
- "ISA Add-on Card",
- "EISA Add-on Card",
- "PCI Add-on Card",
- "MCA Add-on Card",
- "PCMCIA Add-on Card",
- "Proprietary Add-on Card",
- "NuBus" /* 0x0A, master.mif says 16 */
- };
- static const char *location_0xA0[]={
- "PC-98/C20 Add-on Card", /* 0xA0 */
- "PC-98/C24 Add-on Card",
- "PC-98/E Add-on Card",
- "PC-98/Local Bus Add-on Card",
- "PC-98/Card Slot Add-on Card" /* 0xA4, from master.mif */
- };
-
- if(code>=0x01 && code<=0x0A) return PyString_FromString(location[code-0x01]);
- if(code>=0xA0 && code<=0xA4) return PyString_FromString(location_0xA0[code-0xA0]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_memory_array_use(u8 code) {
- /* 3.3.17.2 */
- static const char *use[]={
- "Other", /* 0x01 */
- "Unknown",
- "System Memory",
- "Video Memory",
- "Flash Memory",
- "Non-volatile RAM",
- "Cache Memory" /* 0x07 */
- };
-
- if(code>=0x01 && code<=0x07) return PyString_FromString(use[code-0x01]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_memory_array_ec_type(u8 code) {
- /* 3.3.17.3 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "None",
- "Parity",
- "Single-bit ECC",
- "Multi-bit ECC",
- "CRC" /* 0x07 */
- };
-
- if(code>=0x01 && code<=0x07) return PyString_FromString(type[code-0x01]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_memory_array_capacity(u32 code) {
- PyObject *data;
- if(code==0x8000000) data = PyString_FromString("Unknown");
- else {
- if((code&0x000FFFFF)==0) data = PyString_FromFormat("%i GB", code>>20);
- else if((code&0x000003FF)==0) data = PyString_FromFormat("%i MB", code>>10);
- else data = PyString_FromFormat("%i kB", code);
- }
- return data;
-}
-
-static PyObject *dmi_memory_array_error_handle(u16 code) {
- PyObject *data;
- if(code==0xFFFE) data = PyString_FromString("Not Provided");
- else if(code==0xFFFF) data = PyString_FromString("No Error");
- else data = PyString_FromFormat("0x%04x", code);
- return data;
+void dmi_memory_array_location(xmlNode *node, u8 code)
+{
+ /* 3.3.17.1 */
+ static const char *location[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "System Board Or Motherboard",
+ "ISA Add-on Card",
+ "EISA Add-on Card",
+ "PCI Add-on Card",
+ "MCA Add-on Card",
+ "PCMCIA Add-on Card",
+ "Proprietary Add-on Card",
+ "NuBus" /* 0x0A, master.mif says 16 */
+ };
+ static const char *location_0xA0[] = {
+ "PC-98/C20 Add-on Card", /* 0xA0 */
+ "PC-98/C24 Add-on Card",
+ "PC-98/E Add-on Card",
+ "PC-98/Local Bus Add-on Card",
+ "PC-98/Card Slot Add-on Card" /* 0xA4, from master.mif */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Location", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.17.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0A) {
+ dmixml_AddTextContent(data_n, location[code - 0x01]);
+ } else if(code >= 0xA0 && code <= 0xA4) {
+ dmixml_AddTextContent(data_n, location_0xA0[code - 0xA0]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_array_use(xmlNode *node, u8 code)
+{
+ /* 3.3.17.2 */
+ static const char *use[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "System Memory",
+ "Video Memory",
+ "Flash Memory",
+ "Non-volatile RAM",
+ "Cache Memory" /* 0x07 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Use", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.17.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x07) {
+ dmixml_AddTextContent(data_n, use[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_array_ec_type(xmlNode *node, u8 code)
+{
+ /* 3.3.17.3 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "None",
+ "Parity",
+ "Single-bit ECC",
+ "Multi-bit ECC",
+ "CRC" /* 0x07 */
+ };
+
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "ErrorCorrectionType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.17.3");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x07) {
+ dmixml_AddTextContent(data_n, type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_array_capacity(xmlNode *node, u32 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "MaxCapacity", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ if((code & 0x000FFFFF) == 0) {
+ dmixml_AddAttribute(data_n, "unit", "GB");
+ dmixml_AddTextContent(data_n, "%i", code >> 20);
+ } else if((code & 0x000003FF) == 0) {
+ dmixml_AddAttribute(data_n, "unit", "MB");
+ dmixml_AddTextContent(data_n, "%i", code >> 10);
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "KB");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
+ }
+}
+
+void dmi_memory_array_error_handle(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "ErrorInfoHandle", NULL);
+ assert( data_n != NULL );
+
+ if(code == 0xFFFE) {
+ dmixml_AddAttribute(data_n, "not_provided", "1");
+ } else if(code == 0xFFFF) {
+ dmixml_AddAttribute(data_n, "no_error", "1");
+ } else {
+ dmixml_AddTextContent(data_n, "0x%04x", code);
+ }
}
/*******************************************************************************
** 3.3.18 Memory Device (Type 17)
*/
-static PyObject *dmi_memory_device_width(u16 code) {
- /*
- ** If no memory module is present, width may be 0
- */
- PyObject *data;
- if(code==0xFFFF || code==0) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%i bits", code);
- return data;
-}
-
-static PyObject *dmi_memory_device_size(u16 code) {
- PyObject *data = NULL;
- if(code==0) data = Py_None; //. No Module Installed
- else if(code==0xFFFF) data = PyString_FromString("Unknown"); //. Unknown
- else {
- //. Keeping this as String rather than Int as it has KB and MB representations...
- if(code&0x8000) data = PyString_FromFormat("%d KB", code&0x7FFF);
- else data = PyString_FromFormat("%d MB", code);
- }
- return data;
-}
-
-static PyObject *dmi_memory_device_form_factor(u8 code) {
- /* 3.3.18.1 */
- static const char *form_factor[]={
- "Other", /* 0x01 */
- "Unknown",
- "SIMM",
- "SIP",
- "Chip",
- "DIP",
- "ZIP",
- "Proprietary Card",
- "DIMM",
- "TSOP",
- "Row Of Chips",
- "RIMM",
- "SODIMM",
- "SRIMM",
- "FB-DIMM" /* 0x0F */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x0F) return data = PyString_FromString(form_factor[code-0x01]);
- return data = OUT_OF_SPEC;
-}
-
-static PyObject *dmi_memory_device_set(u8 code) {
- PyObject *data;
- if(code==0) data = Py_None;
- else if(code==0xFF) data = PyString_FromString("Unknown");
- else data = PyInt_FromLong(code);
- return data;
-}
-
-static PyObject *dmi_memory_device_type(u8 code) {
- /* 3.3.18.2 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "DRAM",
- "EDRAM",
- "VRAM",
- "SRAM",
- "RAM",
- "ROM",
- "Flash",
- "EEPROM",
- "FEPROM",
- "EPROM",
- "CDRAM",
- "3DRAM",
- "SDRAM",
- "SGRAM",
- "RDRAM",
- "DDR",
- "DDR2",
- "DDR2 FB-DIMM" /* 0x14 */
- };
-
- if(code>=0x01 && code<=0x14) return PyString_FromString(type[code-0x01]);
- return OUT_OF_SPEC;
-}
-
-static PyObject *dmi_memory_device_type_detail(u16 code) {
- /* 3.3.18.3 */
- static const char *detail[]={
- "Other", /* 1 */
- "Unknown",
- "Fast-paged",
- "Static Column",
- "Pseudo-static",
- "RAMBus",
- "Synchronous",
- "CMOS",
- "EDO",
- "Window DRAM",
- "Cache DRAM",
- "Non-Volatile" /* 12 */
- };
-
- PyObject *data;
- if((code&0x1FFE)==0) data = Py_None;
- else {
- int i;
-
- data = PyList_New(12);
- for(i=1; i<=12; i++)
- if(code&(1<<i))
- PyList_SET_ITEM(data, i-1, PyString_FromString(detail[i-1]));
- else
- PyList_SET_ITEM(data, i-1, Py_None);
- }
- return data;
-}
-
-static PyObject *dmi_memory_device_speed(u16 code) {
- PyObject *data;
- if(code==0) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%i MHz (%.1f ns)", code, (float)1000/code);
- return data;
+void dmi_memory_device_width(xmlNode *node, const char *tagname, u16 code)
+{
+ /*
+ ** If no memory module is present, width may be 0
+ */
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+
+ if(code == 0xFFFF || code == 0) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "bit");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
+}
+
+void dmi_memory_device_size(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Size", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0) {
+ dmixml_AddAttribute(data_n, "empty", "1");
+ } else if(code == 0xFFFF) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ //. Keeping this as String rather than Int as it has KB and MB representations...
+ dmixml_AddAttribute(data_n, "unit", "%s", (code & 0x8000 ? "KB" : "MB"));
+ dmixml_AddTextContent(data_n, "%d", (code & 0x8000 ? code & 0x7FFF : code));
+ }
+}
+
+void dmi_memory_device_form_factor(xmlNode *node, u8 code)
+{
+ /* 3.3.18.1 */
+ static const char *form_factor[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "SIMM",
+ "SIP",
+ "Chip",
+ "DIP",
+ "ZIP",
+ "Proprietary Card",
+ "DIMM",
+ "TSOP",
+ "Row Of Chips",
+ "RIMM",
+ "SODIMM",
+ "SRIMM",
+ "FB-DIMM" /* 0x0F */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "FormFactor", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.18.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0F) {
+ dmixml_AddTextContent(data_n, "%s", form_factor[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_device_set(xmlNode *node, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Set", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0xFF) {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ } else if( code > 0 ) {
+ dmixml_AddTextContent(data_n, "%ld", code);
+ }
+}
+
+void dmi_memory_device_type(xmlNode *node, u8 code)
+{
+ /* 3.3.18.2 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "DRAM",
+ "EDRAM",
+ "VRAM",
+ "SRAM",
+ "RAM",
+ "ROM",
+ "Flash",
+ "EEPROM",
+ "FEPROM",
+ "EPROM",
+ "CDRAM",
+ "3DRAM",
+ "SDRAM",
+ "SGRAM",
+ "RDRAM",
+ "DDR",
+ "DDR2",
+ "DDR2 FB-DIMM" /* 0x14 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Type", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.18.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x14) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_device_type_detail(xmlNode *node, u16 code)
+{
+ /* 3.3.18.3 */
+ static const char *detail[] = {
+ "Other", /* 1 */
+ "Unknown",
+ "Fast-paged",
+ "Static Column",
+ "Pseudo-static",
+ "RAMBus",
+ "Synchronous",
+ "CMOS",
+ "EDO",
+ "Window DRAM",
+ "Cache DRAM",
+ "Non-Volatile" /* 12 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "TypeDetails", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.18.3");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if((code & 0x1FFE) != 0) {
+ int i;
+ for(i = 1; i <= 12; i++) {
+ if(code & (1 << i)) {
+ xmlNode *td_n = dmixml_AddTextChild(data_n, "flag", "%s", detail[i - 1]);
+ assert( td_n != NULL );
+ dmixml_AddAttribute(td_n, "index", "%i", i);
+ }
+ }
+ }
+}
+
+void dmi_memory_device_speed(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Speed", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0) {
+ dmixml_AddAttribute(data_n, "unkown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "speed_ns", "%.1f", (float) 1000 / code);
+ dmixml_AddAttribute(data_n, "unit", "MHz");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
}
/*******************************************************************************
* 3.3.19 32-bit Memory Error Information (Type 18)
*/
-static PyObject *dmi_memory_error_type(u8 code) {
- /* 3.3.19.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "OK",
- "Bad Read",
- "Parity Error",
- "Single-bit Error",
- "Double-bit Error",
- "Multi-bit Error",
- "Nibble Error",
- "Checksum Error",
- "CRC Error",
- "Corrected Single-bit Error",
- "Corrected Error",
- "Uncorrectable Error" /* 0x0E */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x0E) data = PyString_FromString(type[code-0x01]);
- data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_memory_error_granularity(u8 code) {
- /* 3.3.19.2 */
- static const char *granularity[]={
- "Other", /* 0x01 */
- "Unknown",
- "Device Level",
- "Memory Partition Level" /* 0x04 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x04) data = PyString_FromString(granularity[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_memory_error_operation(u8 code) {
- /* 3.3.19.3 */
- static const char *operation[]={
- "Other", /* 0x01 */
- "Unknown",
- "Read",
- "Write",
- "Partial Write" /* 0x05 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x05) data = PyString_FromString(operation[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_memory_error_syndrome(u32 code) {
- PyObject *data;
- if(code==0x00000000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("0x%08x", code);
- return data;
-}
-
-static PyObject *dmi_32bit_memory_error_address(u32 code) {
- PyObject *data;
- if(code==0x80000000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("0x%08x", code);
- return data;
+void dmi_memory_error_type(xmlNode *node, u8 code)
+{
+ /* 3.3.19.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "OK",
+ "Bad Read",
+ "Parity Error",
+ "Single-bit Error",
+ "Double-bit Error",
+ "Multi-bit Error",
+ "Nibble Error",
+ "Checksum Error",
+ "CRC Error",
+ "Corrected Single-bit Error",
+ "Corrected Error",
+ "Uncorrectable Error" /* 0x0E */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Type", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.19.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0E) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_error_granularity(xmlNode *node, u8 code)
+{
+ /* 3.3.19.2 */
+ static const char *granularity[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Device Level",
+ "Memory Partition Level" /* 0x04 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Granularity", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.19.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x04) {
+ dmixml_AddTextContent(data_n, "%s", granularity[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_error_operation(xmlNode *node, u8 code)
+{
+ /* 3.3.19.3 */
+ static const char *operation[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Read",
+ "Write",
+ "Partial Write" /* 0x05 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Operation", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.19.3");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x05) {
+ dmixml_AddTextContent(data_n, "%s", operation[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_memory_error_syndrome(xmlNode *node, u32 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "VendorSyndrome", NULL);
+ assert( data_n != NULL );
+
+ if(code == 0x00000000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddTextContent(data_n, "0x%08x", code);
+ }
+}
+
+void dmi_32bit_memory_error_address(xmlNode *node, char *tagname, u32 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+
+ if(code == 0x80000000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddTextContent(data_n, "0x%08x", code);
+ }
}
/*******************************************************************************
** 3.3.20 Memory Array Mapped Address (Type 19)
*/
-static PyObject *dmi_mapped_address_size(u32 code) {
- PyObject *data;
- if(code==0) data = PyString_FromString("Invalid");
- else if((code&0x000FFFFF)==0) data = PyString_FromFormat("%i GB", code>>20);
- else if((code&0x000003FF)==0) data = PyString_FromFormat("%i MB", code>>10);
- else data = PyString_FromFormat("%i kB", code);
- return data;
+void dmi_mapped_address_size(xmlNode *node, u32 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "RangeSize", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.19.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0) {
+ dmixml_AddAttribute(data_n, "invalid", "1");
+ } else if((code & 0x000FFFFF) == 0) {
+ dmixml_AddAttribute(data_n, "unit", "GB");
+ dmixml_AddTextContent(data_n, "%i", code >> 20);
+ } else if((code & 0x000003FF) == 0) {
+ dmixml_AddAttribute(data_n, "unit", "MB");
+ dmixml_AddTextContent(data_n, "%i", code >> 10);
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "KB");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
}
/*******************************************************************************
** 3.3.21 Memory Device Mapped Address (Type 20)
*/
-static PyObject *dmi_mapped_address_row_position(u8 code) {
- PyObject *data;
- if(code==0) data = OUT_OF_SPEC;
- else if(code==0xFF) data = PyString_FromString("Unknown");
- else data = PyInt_FromLong(code);
- return data;
+void dmi_mapped_address_row_position(xmlNode *node, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "PartitionRowPosition", NULL);
+ assert( data_n != NULL );
+
+ if(code == 0) {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ } else if(code == 0xFF) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddTextContent(data_n, "%ld", code);
+ }
}
-static PyObject *dmi_mapped_address_interleave_position(u8 code) {
- PyObject *data;
- if(code!=0) {
- data = PyDict_New();
- PyDict_SetItemString(data, "Interleave Position", (code==0xFF)?PyString_FromString("Unknown"):PyInt_FromLong(code));
- } else data = Py_None;
- return data;
+void dmi_mapped_address_interleave_position(xmlNode *node, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "InterleavePosition", NULL);
+ assert( data_n != NULL );
+
+ if( code <= 0xFE ) {
+ dmixml_AddTextContent(data_n, "%i", code);
+ } else {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ }
}
-static PyObject *dmi_mapped_address_interleaved_data_depth(u8 code) {
- PyObject *data;
- if(code!=0) {
- data = PyDict_New();
- PyDict_SetItemString(data, "Interleave Data Depth", (code==0xFF)?PyString_FromString("Unknown"):PyInt_FromLong(code));
- } else data = Py_None;
- return data;
+void dmi_mapped_address_interleaved_data_depth(xmlNode *node, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "InterleaveDataDepth", NULL);
+ assert( data_n != NULL );
+
+ if( code < 0xFF ) {
+ dmixml_AddTextContent(data_n, "%i", code);
+ } else {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ }
}
/*******************************************************************************
** 3.3.22 Built-in Pointing Device (Type 21)
*/
-static PyObject *dmi_pointing_device_type(u8 code) {
- /* 3.3.22.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "Mouse",
- "Track Ball",
- "Track Point",
- "Glide Point",
- "Touch Pad",
- "Touch Screen",
- "Optical Sensor" /* 0x09 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x09) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_pointing_device_interface(u8 code) {
- /* 3.3.22.2 */
- static const char *interface[]={
- "Other", /* 0x01 */
- "Unknown",
- "Serial",
- "PS/2",
- "Infrared",
- "HIP-HIL",
- "Bus Mouse",
- "ADB (Apple Desktop Bus)" /* 0x08 */
- };
- static const char *interface_0xA0[]={
- "Bus Mouse DB-9", /* 0xA0 */
- "Bus Mouse Micro DIN",
- "USB" /* 0xA2 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x08) data = PyString_FromString(interface[code-0x01]);
- else if(code>=0xA0 && code<=0xA2) data = PyString_FromString(interface_0xA0[code-0xA0]);
- else data = OUT_OF_SPEC;
- return data;
+void dmi_pointing_device_type(xmlNode *node, u8 code)
+{
+ /* 3.3.22.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Mouse",
+ "Track Ball",
+ "Track Point",
+ "Glide Point",
+ "Touch Pad",
+ "Touch Screen",
+ "Optical Sensor" /* 0x09 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "DeviceType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.22.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x09) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_pointing_device_interface(xmlNode *node, u8 code)
+{
+ /* 3.3.22.2 */
+ static const char *interface[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Serial",
+ "PS/2",
+ "Infrared",
+ "HIP-HIL",
+ "Bus Mouse",
+ "ADB (Apple Desktop Bus)" /* 0x08 */
+ };
+ static const char *interface_0xA0[] = {
+ "Bus Mouse DB-9", /* 0xA0 */
+ "Bus Mouse Micro DIN",
+ "USB" /* 0xA2 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "DeviceInterface", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.22.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x08) {
+ dmixml_AddTextContent(data_n, interface[code - 0x01]);
+ } else if(code >= 0xA0 && code <= 0xA2) {
+ dmixml_AddTextContent(data_n, interface_0xA0[code - 0xA0]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/*******************************************************************************
** 3.3.23 Portable Battery (Type 22)
*/
-static PyObject *dmi_battery_chemistry(u8 code) {
- /* 3.3.23.1 */
- static const char *chemistry[]={
- "Other", /* 0x01 */
- "Unknown",
- "Lead Acid",
- "Nickel Cadmium",
- "Nickel Metal Hydride",
- "Lithium Ion",
- "Zinc Air",
- "Lithium Polymer" /* 0x08 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x08) data = PyString_FromString(chemistry[code-0x01]);
- data = OUT_OF_SPEC;
- return data;
+void dmi_battery_chemistry(xmlNode *node, u8 code)
+{
+ /* 3.3.23.1 */
+ static const char *chemistry[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Lead Acid",
+ "Nickel Cadmium",
+ "Nickel Metal Hydride",
+ "Lithium Ion",
+ "Zinc Air",
+ "Lithium Polymer" /* 0x08 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "BatteryChemistry", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.22.2");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x08) {
+ dmixml_AddTextContent(data_n, "%s", chemistry[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
-static PyObject *dmi_battery_capacity(u16 code, u8 multiplier) {
- PyObject *data;
- if(code==0) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%i mWh", code*multiplier);
- return data;
+void dmi_battery_capacity(xmlNode *node, u16 code, u8 multiplier)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "DesignCapacity", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "value", "0x%04x", code);
+ dmixml_AddAttribute(data_n, "multiplier", "0x%04x", multiplier);
+
+ if(code != 0) {
+ dmixml_AddAttribute(data_n, "unit", "mWh");
+ dmixml_AddTextContent(data_n, "%i", code * multiplier);
+ }
}
-static PyObject *dmi_battery_voltage(u16 code) {
- PyObject *data;
- if(code==0) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%i mV", code);
- return data;
+void dmi_battery_voltage(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "DesignVoltage", NULL);
+ assert( data_n != NULL );
+
+ if(code == 0) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "mV");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
}
-static PyObject *dmi_battery_maximum_error(u8 code) {
- PyObject *data;
- if(code==0xFF) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%i%%", code);
- return data;
+void dmi_battery_maximum_error(xmlNode *node, u8 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "MaximumError", NULL);
+ assert( data_n != NULL );
+
+ if(code == 0xFF) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddTextContent(data_n, "%i%%", code);
+ }
}
/*******************************************************************************
** 3.3.24 System Reset (Type 23)
*/
-static PyObject *dmi_system_reset_boot_option(u8 code) {
- static const char *option[]={
- "Operating System", /* 0x1 */
- "System Utilities",
- "Do Not Reboot" /* 0x3 */
- };
- PyObject *data;
-
- if(code>=0x1) data = PyString_FromString(option[code-0x1]);
- else data = OUT_OF_SPEC;
- return data;
+void dmi_system_reset_boot_option(xmlNode *node, const char *tagname, u8 code)
+{
+ static const char *option[] = {
+ "Operating System", /* 0x1 */
+ "System Utilities",
+ "Do Not Reboot" /* 0x3 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if( (code > 0) && (code < 4) ) {
+ dmixml_AddTextContent(data_n, option[code - 0x1]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
-static PyObject *dmi_system_reset_count(u16 code) {
- PyObject *data;
- if(code==0xFFFF) data = PyString_FromString("Unknown");
- else data = PyInt_FromLong(code);
- return data;
+void dmi_system_reset_count(xmlNode *node, const char *tagname, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0xFFFF) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddTextContent(data_n, "%ld", code);
+ }
}
-static PyObject *dmi_system_reset_timer(u16 code) {
- PyObject *data;
- if(code==0xFFFF) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%i min", code);
- return data;
+void dmi_system_reset_timer(xmlNode *node, const char *tagname, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0xFFFF) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "min");
+ dmixml_AddTextContent(data_n, "%i", code);
+ }
}
/*******************************************************************************
* 3.3.25 Hardware Security (Type 24)
*/
-static PyObject *dmi_hardware_security_status(u8 code) {
- static const char *status[]={
- "Disabled", /* 0x00 */
- "Enabled",
- "Not Implemented",
- "Unknown" /* 0x03 */
- };
-
- return PyString_FromString(status[code]);
+void dmi_hardware_security_status(xmlNode *node, const char *tagname, u8 code)
+{
+ static const char *status[] = {
+ "Disabled", /* 0x00 */
+ "Enabled",
+ "Not Implemented",
+ "Unknown" /* 0x03 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+ dmixml_AddTextContent(data_n, "%s", status[code]);
}
/*******************************************************************************
** 3.3.26 System Power Controls (Type 25)
*/
-static PyObject *dmi_power_controls_power_on(const u8 *p) {
- /* 3.3.26.1 */
- PyObject *data = PyList_New(5);
+#define DMI_POWER_CTRL_TIME_STR(dest, variant, data) \
+ if( variant ) { snprintf(dest, 3, "%02x", data); } \
+ else { snprintf(dest, 3, "*"); } \
- PyList_SET_ITEM(data, 0, dmi_bcd_range(p[0], 0x01, 0x12)?PyString_FromFormat(" %02x", p[0]):PyString_FromString(" *"));
- PyList_SET_ITEM(data, 1, dmi_bcd_range(p[1], 0x01, 0x31)?PyString_FromFormat("-%02x", p[1]):PyString_FromString("-*"));
- PyList_SET_ITEM(data, 2, dmi_bcd_range(p[2], 0x00, 0x23)?PyString_FromFormat(" %02x", p[2]):PyString_FromString(" *"));
- PyList_SET_ITEM(data, 3, dmi_bcd_range(p[3], 0x00, 0x59)?PyString_FromFormat(":%02x", p[3]):PyString_FromString(":*"));
- PyList_SET_ITEM(data, 4, dmi_bcd_range(p[4], 0x00, 0x59)?PyString_FromFormat(":%02x", p[4]):PyString_FromString(":*"));
+void dmi_power_controls_power_on(xmlNode *node, const char *tagname, const u8 * p)
+{
+ /* 3.3.26.1 */
+ char timestr[5][5];
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.26.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%08x", p);
- return data;
+ DMI_POWER_CTRL_TIME_STR(timestr[0], dmi_bcd_range(p[0], 0x01, 0x12), p[0])
+ DMI_POWER_CTRL_TIME_STR(timestr[1], dmi_bcd_range(p[1], 0x01, 0x31), p[1])
+ DMI_POWER_CTRL_TIME_STR(timestr[2], dmi_bcd_range(p[2], 0x01, 0x23), p[2])
+ DMI_POWER_CTRL_TIME_STR(timestr[3], dmi_bcd_range(p[3], 0x01, 0x59), p[3])
+ DMI_POWER_CTRL_TIME_STR(timestr[4], dmi_bcd_range(p[4], 0x01, 0x59), p[4])
+
+ dmixml_AddTextContent(data_n, "%s-%s %s:%s:%s",
+ timestr[0], timestr[1],
+ timestr[2], timestr[3], timestr[4]);
}
/*******************************************************************************
* 3.3.27 Voltage Probe (Type 26)
*/
-static PyObject *dmi_voltage_probe_location(u8 code) {
- /* 3.3.27.1 */
- static const char *location[]={
- "Other", /* 0x01 */
- "Unknown",
- "Processor",
- "Disk",
- "Peripheral Bay",
- "System Management Module",
- "Motherboard",
- "Memory Module",
- "Processor Module",
- "Power Unit",
- "Add-in Card" /* 0x0B */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x0B) data = PyString_FromString(location[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_probe_status(u8 code) {
- /* 3.3.27.1 */
- static const char *status[]={
- "Other", /* 0x01 */
- "Unknown",
- "OK",
- "Non-critical",
- "Critical",
- "Non-recoverable" /* 0x06 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x06) data = PyString_FromString(status[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_voltage_probe_value(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.3f V", (float)(i16)code/1000);
- return data;
-}
-
-static PyObject *dmi_voltage_probe_resolution(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.1f mV", (float)code/10);
- return data;
-}
-
-static PyObject *dmi_probe_accuracy(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.2f%%", (float)code/100);
- return data;
+void dmi_voltage_probe_location(xmlNode *node, u8 code)
+{
+ /* 3.3.27.1 */
+ static const char *location[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Processor",
+ "Disk",
+ "Peripheral Bay",
+ "System Management Module",
+ "Motherboard",
+ "Memory Module",
+ "Processor Module",
+ "Power Unit",
+ "Add-in Card" /* 0x0B */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Location", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.27.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0B) {
+ dmixml_AddTextContent(data_n, "%s", location[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_probe_status(xmlNode *node, u8 code)
+{
+ /* 3.3.27.1 */
+ static const char *status[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "OK",
+ "Non-critical",
+ "Critical",
+ "Non-recoverable" /* 0x06 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Status", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.27.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x06) {
+ dmixml_AddTextContent(data_n, "%s", status[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_voltage_probe_value(xmlNode *node, const char *tagname, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "V");
+ dmixml_AddTextContent(data_n, "%.3f", (float)(i16) code / 1000);
+ }
+}
+
+void dmi_voltage_probe_resolution(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Resolution", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "mV");
+ dmixml_AddTextContent(data_n, "%.1f", (float) code / 10);
+ }
+}
+
+void dmi_probe_accuracy(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Accuracy", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "%%");
+ dmixml_AddTextContent(data_n, "%.2f", (float)code / 100);
+ }
}
/*******************************************************************************
** 3.3.28 Cooling Device (Type 27)
*/
-static PyObject *dmi_cooling_device_type(u8 code) {
- /* 3.3.28.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "Fan",
- "Centrifugal Blower",
- "Chip Fan",
- "Cabinet Fan",
- "Power Supply Fan",
- "Heat Pipe",
- "Integrated Refrigeration" /* 0x09 */
- };
- static const char *type_0x10[]={
- "Active Cooling", /* 0x10, master.mif says 32 */
- "Passive Cooling" /* 0x11, master.mif says 33 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x09) data = PyString_FromString(type[code-0x01]);
- else if(code>=0x10 && code<=0x11) data = PyString_FromString(type_0x10[code-0x10]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_cooling_device_speed(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown Or Non-rotating");
- else data = PyString_FromFormat("%i rpm", code);
- return data;
+void dmi_cooling_device_type(xmlNode *node, u8 code)
+{
+ /* 3.3.28.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Fan",
+ "Centrifugal Blower",
+ "Chip Fan",
+ "Cabinet Fan",
+ "Power Supply Fan",
+ "Heat Pipe",
+ "Integrated Refrigeration" /* 0x09 */
+ };
+ static const char *type_0x10[] = {
+ "Active Cooling", /* 0x10, master.mif says 32 */
+ "Passive Cooling" /* 0x11, master.mif says 33 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Type", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.28.1", code);
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x09) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else if(code >= 0x10 && code <= 0x11) {
+ dmixml_AddTextContent(data_n, "%s", type_0x10[code - 0x10]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_cooling_device_speed(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "NominalSpeed", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ }
+
+ dmixml_AddAttribute(data_n, "unit", "rpm");
+ dmixml_AddTextContent(data_n, "%i", code);
}
/*******************************************************************************
** 3.3.29 Temperature Probe (Type 28)
*/
-static PyObject *dmi_temperature_probe_location(u8 code) {
- /* 3.3.29.1 */
- static const char *location[]={
- "Other", /* 0x01 */
- "Unknown",
- "Processor",
- "Disk",
- "Peripheral Bay",
- "System Management Module", /* master.mif says SMB Master */
- "Motherboard",
- "Memory Module",
- "Processor Module",
- "Power Unit",
- "Add-in Card",
- "Front Panel Board",
- "Back Panel Board",
- "Power System Board",
- "Drive Back Plane" /* 0x0F */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x0F) data = PyString_FromString(location[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_temperature_probe_value(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.1f deg C", (float)(i16)code/10);
- return data;
-}
-
-static PyObject *dmi_temperature_probe_resolution(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.3f deg C", (float)code/1000);
- return data;
+void dmi_temperature_probe_location(xmlNode *node, u8 code)
+{
+ /* 3.3.29.1 */
+ static const char *location[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Processor",
+ "Disk",
+ "Peripheral Bay",
+ "System Management Module", /* master.mif says SMB Master */
+ "Motherboard",
+ "Memory Module",
+ "Processor Module",
+ "Power Unit",
+ "Add-in Card",
+ "Front Panel Board",
+ "Back Panel Board",
+ "Power System Board",
+ "Drive Back Plane" /* 0x0F */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Location", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.29.1", code);
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0F) {
+ dmixml_AddTextContent(data_n, "%s", location[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_temperature_probe_value(xmlNode *node, const char *tagname, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "C");
+ dmixml_AddTextContent(data_n, "%.1f", (float)(i16) code / 10);
+ }
+}
+
+void dmi_temperature_probe_resolution(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Resolution", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "C");
+ dmixml_AddTextContent(data_n, "%.3f", (float)code / 1000);
+ }
}
/*******************************************************************************
** 3.3.30 Electrical Current Probe (Type 29)
*/
-static PyObject *dmi_current_probe_value(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.3f A", (float)(i16)code/1000);
- return data;
+void dmi_current_probe_value(xmlNode *node, const char *tagname, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "A");
+ dmixml_AddTextContent(data_n, "%.3f", (float)(i16) code / 1000);
+ }
}
-static PyObject *dmi_current_probe_resolution(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.1f mA", (float)code/10);
- return data;
+void dmi_current_probe_resolution(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Resolution", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "mA");
+ dmixml_AddTextContent(data_n, "%.1f A", (float)code / 10);
+ }
}
/*******************************************************************************
** 3.3.33 System Boot Information (Type 32)
*/
-static PyObject *dmi_system_boot_status(u8 code) {
- static const char *status[]={
- "No errors detected", /* 0 */
- "No bootable media",
- "Operating system failed to load",
- "Firmware-detected hardware failure",
- "Operating system-detected hardware failure",
- "User-requested boot",
- "System security violation",
- "Previously-requested image",
- "System watchdog timer expired" /* 8 */
- };
- PyObject *data;
-
- if(code<=8) data = PyString_FromString(status[code]);
- else if(code>=128 && code<=191) data = PyString_FromString("OEM-specific");
- else if(code>=192) data = PyString_FromString("Product-specific");
- else data = OUT_OF_SPEC;
- return data;
+void dmi_system_boot_status(xmlNode *node, u8 code)
+{
+ static const char *status[] = {
+ "No errors detected", /* 0 */
+ "No bootable media",
+ "Operating system failed to load",
+ "Firmware-detected hardware failure",
+ "Operating system-detected hardware failure",
+ "User-requested boot",
+ "System security violation",
+ "Previously-requested image",
+ "System watchdog timer expired" /* 8 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Status", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 8) {
+ dmixml_AddTextContent(data_n, "%s", status[code]);
+ } else if(code >= 128 && code <= 191) {
+ dmixml_AddTextContent(data_n, "OEM-specific");
+ } else if(code >= 192) {
+ dmixml_AddTextContent(data_n, "Product-specific");
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/*******************************************************************************
** 3.3.34 64-bit Memory Error Information (Type 33)
*/
-static PyObject *dmi_64bit_memory_error_address(u64 code) {
- PyObject *data;
- if(code.h==0x80000000 && code.l==0x00000000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("0x%08x%08x", code.h, code.l);
- return data;
+void dmi_64bit_memory_error_address(xmlNode *node, const char *tagname, u64 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) tagname, NULL);
+ assert( data_n != NULL );
+
+ if(code.h == 0x80000000 && code.l == 0x00000000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddTextContent(data_n, "0x%08x%08x", code.h, code.l);
+ }
}
/*******************************************************************************
** 3.3.35 Management Device (Type 34)
*/
-static PyObject *dmi_management_device_type(u8 code) {
- /* 3.3.35.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "LM75",
- "LM78",
- "LM79",
- "LM80",
- "LM81",
- "ADM9240",
- "DS1780",
- "MAX1617",
- "GL518SM",
- "W83781D",
- "HT82H791" /* 0x0D */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x0D) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_management_device_address_type(u8 code) {
- /* 3.3.35.2 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "I/O Port",
- "Memory",
- "SMBus" /* 0x05 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x05) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
+void dmi_management_device_type(xmlNode *node, u8 code)
+{
+ /* 3.3.35.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "LM75",
+ "LM78",
+ "LM79",
+ "LM80",
+ "LM81",
+ "ADM9240",
+ "DS1780",
+ "MAX1617",
+ "GL518SM",
+ "W83781D",
+ "HT82H791" /* 0x0D */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Type", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.35.1", code);
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x0D) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_management_device_address_type(xmlNode *node, u8 code)
+{
+ /* 3.3.35.2 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "I/O Port",
+ "Memory",
+ "SMBus" /* 0x05 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "AddressType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.35.2", code);
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x05) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/*******************************************************************************
** 3.3.38 Memory Channel (Type 37)
*/
-static PyObject *dmi_memory_channel_type(u8 code) {
- /* 3.3.38.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "RamBus",
- "SyncLink" /* 0x04 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x04) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
+void dmi_memory_channel_type(xmlNode *node, u8 code)
+{
+ /* 3.3.38.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "RamBus",
+ "SyncLink" /* 0x04 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Type", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.38.1", code);
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x04) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
-static PyObject *dmi_memory_channel_devices(u8 count, const u8 *p) {
- PyObject *data = PyDict_New();
- PyObject *subdata, *val;
- int i;
-
- for(i=1; i<=count; i++) {
- subdata = PyList_New(2);
-
- val = PyString_FromFormat("Load: %i", p[3*i]);
- PyList_SET_ITEM(subdata, 0, val);
- Py_DECREF(val);
+void dmi_memory_channel_devices(xmlNode *node, u8 count, const u8 * p)
+{
+ int i;
- val = PyString_FromFormat("Handle: 0x%04x", WORD(p+3*i+1));
- PyList_SET_ITEM(subdata, 1, val);
- Py_DECREF(val);
+ for(i = 1; i <= count; i++) {
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Device", NULL);
+ assert( data_n != NULL );
- PyDict_SetItem(data, PyInt_FromLong(i), subdata);
- Py_DECREF(subdata);
- }
- return data;
+ dmixml_AddAttribute(data_n, "Load", "%i", p[3 * i]);
+ dmixml_AddAttribute(data_n, "Handle", "0x%04x", WORD(p + 3 * i + 1));
+ }
}
/*******************************************************************************
** 3.3.39 IPMI Device Information (Type 38)
*/
-static PyObject *dmi_ipmi_interface_type(u8 code) {
- /* 3.3.39.1 and IPMI 2.0, appendix C1, table C1-2 */
- static const char *type[]={
- "Unknown", /* 0x00 */
- "KCS (Keyboard Control Style)",
- "SMIC (Server Management Interface Chip)",
- "BT (Block Transfer)",
- "SSIF (SMBus System Interface)" /* 0x04 */
- };
- PyObject *data;
-
- if(code<=0x04) data = PyString_FromString(type[code]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_ipmi_base_address(u8 type, const u8 *p, u8 lsb) {
- PyObject *data;
- if(type==0x04) /* SSIF */ {
- data = PyString_FromFormat("0x%02x (SMBus)", (*p)>>1);
- } else {
- u64 address=QWORD(p);
- data = PyString_FromFormat("0x%08x%08x (%s)", address.h, (address.l&~1)|lsb, address.l&1?"I/O":"Memory-mapped");
- }
- return data;
-}
-
-static PyObject *dmi_ipmi_register_spacing(u8 code) {
- /* IPMI 2.0, appendix C1, table C1-1 */
- static const char *spacing[]={
- "Successive Byte Boundaries", /* 0x00 */
- "32-bit Boundaries",
- "16-byte Boundaries" /* 0x02 */
- };
- PyObject *data;
-
- if(code<=0x02) return data = PyString_FromString(spacing[code]);
- return data = OUT_OF_SPEC;
+void dmi_ipmi_interface_type(xmlNode *node, u8 code)
+{
+ /* 3.3.39.1 and IPMI 2.0, appendix C1, table C1-2 */
+ static const char *type[] = {
+ "Unknown", /* 0x00 */
+ "KCS (Keyboard Control Style)",
+ "SMIC (Server Management Interface Chip)",
+ "BT (Block Transfer)",
+ "SSIF (SMBus System Interface)" /* 0x04 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "InterfaceType", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.39.1", code);
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 0x04) {
+ dmixml_AddTextContent(data_n, "%s", type[code]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_ipmi_base_address(xmlNode *node, u8 type, const u8 * p, u8 lsb)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "BaseAddress", NULL);
+ assert( data_n != NULL );
+
+ if(type == 0x04) { /* SSIF */
+ dmixml_AddAttribute(data_n, "interface", "SMBus-SSIF");
+ dmixml_AddTextContent(data_n, "0x%02x", (*p) >> 1);
+ } else {
+ u64 address = QWORD(p);
+ dmixml_AddAttribute(data_n, "interface", "%s",
+ address.l & 1 ? "I/O" : "Memory-mapped");
+ dmixml_AddTextContent(data_n, "0x%08x%08x",
+ address.h, (address.l & ~1) | lsb);
+ }
+}
+
+void dmi_ipmi_register_spacing(xmlNode *node, u8 code)
+{
+ /* IPMI 2.0, appendix C1, table C1-1 */
+ static const char *spacing[] = {
+ "Successive Byte Boundaries", /* 0x00 */
+ "32-bit Boundaries",
+ "16-byte Boundaries" /* 0x02 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "RegisterSpacing", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code <= 0x02) {
+ dmixml_AddTextContent(data_n, "%s", spacing[code]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/*******************************************************************************
** 3.3.40 System Power Supply (Type 39)
*/
-static PyObject *dmi_power_supply_power(u16 code) {
- PyObject *data;
- if(code==0x8000) data = PyString_FromString("Unknown");
- else data = PyString_FromFormat("%.3f W", (float)code/1000);
- return data;
-}
-
-static PyObject *dmi_power_supply_type(u8 code) {
- /* 3.3.40.1 */
- static const char *type[]={
- "Other", /* 0x01 */
- "Unknown",
- "Linear",
- "Switching",
- "Battery",
- "UPS",
- "Converter",
- "Regulator" /* 0x08 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x08) data = PyString_FromString(type[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_power_supply_status(u8 code) {
- /* 3.3.40.1 */
- static const char *status[]={
- "Other", /* 0x01 */
- "Unknown",
- "OK",
- "Non-critical",
- "Critical" /* 0x05 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x05) data = PyString_FromString(status[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
-}
-
-static PyObject *dmi_power_supply_range_switching(u8 code) {
- /* 3.3.40.1 */
- static const char *switching[]={
- "Other", /* 0x01 */
- "Unknown",
- "Manual",
- "Auto-switch",
- "Wide Range",
- "N/A" /* 0x06 */
- };
- PyObject *data;
-
- if(code>=0x01 && code<=0x06) data = PyString_FromString(switching[code-0x01]);
- else data = OUT_OF_SPEC;
- return data;
+void dmi_power_supply_power(xmlNode *node, u16 code)
+{
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "MaxPowerCapacity", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code == 0x8000) {
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ } else {
+ dmixml_AddAttribute(data_n, "unit", "W");
+ dmixml_AddTextContent(data_n, "%.3f", (float)code / 1000);
+ }
+}
+
+void dmi_power_supply_type(xmlNode *node, u8 code)
+{
+ /* 3.3.40.1 */
+ static const char *type[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Linear",
+ "Switching",
+ "Battery",
+ "UPS",
+ "Converter",
+ "Regulator" /* 0x08 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Type", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.40.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x08) {
+ dmixml_AddTextContent(data_n, "%s", type[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_power_supply_status(xmlNode *node, u8 code)
+{
+ /* 3.3.40.1 */
+ static const char *status[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "OK",
+ "Non-critical",
+ "Critical" /* 0x05 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "Status", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.40.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+ dmixml_AddAttribute(data_n, "present", "1");
+
+ if(code >= 0x01 && code <= 0x05) {
+ dmixml_AddTextContent(data_n, "%s", status[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
+}
+
+void dmi_power_supply_range_switching(xmlNode *node, u8 code)
+{
+ /* 3.3.40.1 */
+ static const char *switching[] = {
+ "Other", /* 0x01 */
+ "Unknown",
+ "Manual",
+ "Auto-switch",
+ "Wide Range",
+ "N/A" /* 0x06 */
+ };
+ xmlNode *data_n = xmlNewChild(node, NULL, (xmlChar *) "VoltageRangeSwitching", NULL);
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "dmispec", "3.3.40.1");
+ dmixml_AddAttribute(data_n, "flags", "0x%04x", code);
+
+ if(code >= 0x01 && code <= 0x06) {
+ dmixml_AddTextContent(data_n, "%s", switching[code - 0x01]);
+ } else {
+ dmixml_AddAttribute(data_n, "outofspec", "1");
+ }
}
/*
@@ -2803,1971 +3631,1454 @@ static PyObject *dmi_power_supply_range_switching(u8 code) {
** whether it's worth the effort.
*/
-static PyObject *dmi_additional_info(const struct dmi_header *h, const char *prefix) {
- u8 *p = h->data + 4;
- u8 count = *p++;
- u8 length;
- int i, offset = 5;
- PyObject *data = PyList_New(count);
-
- for(i=0; i<count; i++) {
- PyObject *subdata = PyDict_New();
-
- /* Check for short entries */
- if (h->length < offset + 1) break;
- length = p[0x00];
- if (length < 0x05 || h->length < offset + length) break;
-
- PyDict_SetItemString(subdata,
- "Referenced Handle",
- PyString_FromFormat("0x%04x", WORD(p + 0x01))
- );
-
- PyDict_SetItemString(subdata,
- "Referenced Offset",
- PyString_FromFormat("0x%02x", p[0x03])
- );
-
- PyDict_SetItemString(subdata,
- "String",
- dmi_string_py(h, p[0x04])
- );
-
- PyObject *_val;
- switch (length - 0x05) {
- case 1:
- _val = PyString_FromFormat("0x%02x", p[0x05]);
- break;
- case 2:
- _val = PyString_FromFormat("0x%04x", WORD(p + 0x05));
- break;
- case 4:
- _val = PyString_FromFormat("0x%08x", DWORD(p + 0x05));
- break;
- default:
- _val = PyString_FromString("Unexpected size");
- break;
- }
- PyDict_SetItemString(subdata, "Value", _val);
- Py_DECREF(_val);
-
- p += length;
- offset += length;
- PyList_SET_ITEM(data, i, subdata);
- }
- return data;
+void dmi_additional_info(xmlNode *node, const struct dmi_header *h)
+{
+ u8 *p = h->data + 4;
+ u8 count = *p++;
+ u8 length;
+ int i, offset = 5;
+
+ assert( node != NULL );
+
+ for(i = 0; i < count; i++) {
+ xmlNode *data_n = NULL, *str_n = NULL, *val_n = NULL;
+
+ /* Check for short entries */
+ if(h->length < offset + 1) {
+ break;
+ }
+
+ length = p[0x00];
+ if(length < 0x05 || h->length < offset + length)
+ break;
+
+ data_n = xmlNewChild(node, NULL, (xmlChar *) "Record", NULL);
+ assert( data_n != NULL );
+
+ dmixml_AddAttribute(data_n, "index", "%i", i);
+ dmixml_AddAttribute(data_n, "ReferenceHandle", "0x%04x", WORD(p + 0x01));
+ dmixml_AddAttribute(data_n, "ReferenceOffset", "0x%02x", p[0x03]);
+
+ str_n = dmixml_AddTextChild(data_n, "String", "%s", dmi_string(h, p[0x04]));
+
+ switch (length - 0x05) {
+ case 1:
+ dmixml_AddTextChild(data_n, "Value", "0x%02x", p[0x05]);
+ break;
+ case 2:
+ dmixml_AddTextChild(data_n, "Value", "0x%04x", WORD(p + 0x05));
+ break;
+ case 4:
+ dmixml_AddTextChild(data_n, "Value", "0x%08x", DWORD(p + 0x05));
+ break;
+ default:
+ val_n = xmlNewChild(data_n, NULL, (xmlChar *) "Value", NULL);
+ dmixml_AddAttribute(val_n, "unexpected_size", "1");
+ break;
+ }
+
+ p += length;
+ offset += length;
+ }
}
/*******************************************************************************
** Main
*/
-PyObject* dmi_decode(struct dmi_header *h, u16 ver) {
-
- const u8 *data = h->data;
-
- //. 0xF1 --> 0xF100
- //int minor = h->type<<8;
- char _[2048]; bzero(_, 2048);
- //dmi_codes_major *dmiMajor = (dmi_codes_major *)&dmiCodesMajor[map_maj[h->type]];
- dmi_codes_major *dmiMajor = (dmi_codes_major *)&dmiCodesMajor[h->type];
- PyObject *pylist = PyDict_New();
- PyDict_SetItemString(pylist, "id", PyString_FromString(dmiMajor->id));
- PyDict_SetItemString(pylist, "desc", PyString_FromString(dmiMajor->desc));
- PyObject *_val; //. A Temporary pointer (value)
- PyObject *_key; //. Another temporary pointer (key)
- PyObject *caseData = PyDict_New();
-
- switch(h->type) {
-
- case 0: /* 3.3.1 BIOS Information */
-
- if(h->length<0x12) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Vendor", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x05]);
- PyDict_SetItemString(caseData, "Version", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x08]);
- PyDict_SetItemString(caseData, "Release Date", _val);
- Py_DECREF(_val);
-
- /*
- * On IA-64, the BIOS base address will read 0 because
- * there is no BIOS. Skip the base address and the
- * runtime size in this case.
- */
- if(WORD(data+0x06)!=0) {
- _val = PyString_FromFormat("0x%04x0", WORD(data+0x06));
- PyDict_SetItemString(caseData, "Address", _val);
- Py_DECREF(_val);
-
- _val = dmi_bios_runtime_size((0x10000-WORD(data+0x06))<<4);
- PyDict_SetItemString(caseData, "Runtime Size", _val);
- Py_DECREF(_val);
- }
-
- _val = PyString_FromFormat("%i kB", (data[0x09]+1)<<6);
- PyDict_SetItemString(caseData, "ROM Size", _val);
- Py_DECREF(_val);
-
- _val = dmi_bios_characteristics(QWORD(data+0x0A));
- PyDict_SetItemString(caseData, "Characteristics", _val);
- Py_DECREF(_val);
-
- if(h->length<0x13) break;
- _val = dmi_bios_characteristics_x1(data[0x12]);
- PyDict_SetItemString(caseData, "Characteristics x1", _val);
- Py_DECREF(_val);
-
- if(h->length<0x14) break;
- _val = dmi_bios_characteristics_x2(data[0x13]);
- PyDict_SetItemString(caseData, "Characteristics x2", _val);
- Py_DECREF(_val);
-
- if(h->length<0x18) break;
-
- if(data[0x14]!=0xFF && data[0x15]!=0xFF) {
- _val = PyString_FromFormat("%i.%i", data[0x14], data[0x15]);
- PyDict_SetItemString(caseData, "BIOS Revision", _val);
- Py_DECREF(_val);
- }
-
- if(data[0x16]!=0xFF && data[0x17]!=0xFF) {
- _val = PyString_FromFormat("%i.%i", data[0x16], data[0x17]);
- PyDict_SetItemString(caseData, "Firmware Revision", _val);
- Py_DECREF(_val);
- }
-
- break;
-
- case 1: /* 3.3.2 System Information */
-
- if(h->length<0x08) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Manufacturer", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x05]);
- PyDict_SetItemString(caseData, "Product Name", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x06]);
- PyDict_SetItemString(caseData, "Version", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x07]);
- PyDict_SetItemString(caseData, "Serial Number", _val);
- Py_DECREF(_val);
-
- if(h->length<0x19) break;
- _val = dmi_system_uuid_py(data+0x08, ver);
- PyDict_SetItemString(caseData, "UUID", _val);
- Py_DECREF(_val);
-
- _val = dmi_system_wake_up_type(data[0x18]);
- PyDict_SetItemString(caseData, "Wake-Up Type", _val);
- Py_DECREF(_val);
-
- if(h->length<0x1B) break;
- _val = dmi_string_py(h, data[0x19]);
- PyDict_SetItemString(caseData, "SKU Number", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x1A]);
- PyDict_SetItemString(caseData, "Family", _val);
- Py_DECREF(_val);
- break;
-
- case 2: /* 3.3.3 Base Board Information */
-
- if(h->length<0x08) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Manufacturer", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x05]);
- PyDict_SetItemString(caseData, "Product Name", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x06]);
- PyDict_SetItemString(caseData, "Version", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x07]);
- PyDict_SetItemString(caseData, "Serial Number", _val);
- Py_DECREF(_val);
-
- if(h->length<0x0F) break;
- _val = dmi_string_py(h, data[0x08]);
- PyDict_SetItemString(caseData, "Asset Tag", _val);
- Py_DECREF(_val);
-
- _val = dmi_base_board_features(data[0x09]);
- PyDict_SetItemString(caseData, "Features", _val);
- Py_DECREF(_val);
+xmlNode *dmi_decode(xmlNode *prnt_n, dmi_codes_major *dmiMajor, struct dmi_header * h, u16 ver)
+{
+ const u8 *data = h->data;
+ xmlNode *sect_n = NULL, *sub_n = NULL, *sub2_n = NULL;
+ //. 0xF1 --> 0xF100
+ //int minor = h->type<<8;
+
+ sect_n = xmlNewChild(prnt_n, NULL, (xmlChar *) dmiMajor->tagname, NULL);
+ assert( sect_n != NULL );
+
+ dmixml_AddAttribute(sect_n, "dmispec", "%s", dmiMajor->id);
+ dmixml_AddAttribute(sect_n, "type", "%i", h->type);
+ dmixml_AddTextChild(sect_n, "DMIdescription", "%s", dmiMajor->desc);
+
+ switch (h->type) {
+ case 0: /* 3.3.1 BIOS Information */
+ if(h->length < 0x12) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "Vendor", "%s", dmi_string(h, data[0x04]));
+ dmixml_AddTextChild(sect_n, "Version", "%s", dmi_string(h, data[0x05]));
+ dmixml_AddTextChild(sect_n, "ReleaseDate", "%s", dmi_string(h, data[0x08]));
- _val = dmi_string_py(h, data[0x0A]);
- PyDict_SetItemString(caseData, "Location In Chassis", _val);
- Py_DECREF(_val);
+ /*
+ * On IA-64, the BIOS base address will read 0 because
+ * there is no BIOS. Skip the base address and the
+ * runtime size in this case.
+ */
- _val = PyString_FromFormat("0x%04x", WORD(data+0x0B));
- PyDict_SetItemString(caseData, "Chassis Handle", _val);
- Py_DECREF(_val);
+ if(WORD(data + 0x06) != 0) {
+ dmixml_AddTextChild(sect_n, "Address", "0x%04x0", WORD(data + 0x06));
+ dmi_bios_runtime_size(sect_n, (0x10000 - WORD(data + 0x06)) << 4);
+ }
- _val = dmi_base_board_type(data[0x0D]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
+ sub_n = dmixml_AddTextChild(sect_n, "ROMsize", "%i", (data[0x09] + 1) << 6);
+ dmixml_AddAttribute(sub_n, "unit", "KB");
+ sub_n = NULL;
- if(h->length<0x0F+data[0x0E]*sizeof(u16)) break;
- _val = dmi_base_board_handles(data[0x0E], data+0x0F);
- PyDict_SetItemString(caseData, "Type ???", _val);
- Py_DECREF(_val);
- break;
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Characteristics", NULL);
+ assert( sub_n != NULL );
- case 3: /* 3.3.4 Chassis Information */
+ dmixml_AddAttribute(sub_n, "level", "0");
+ dmi_bios_characteristics(sub_n, QWORD(data + 0x0A));
+ sub_n = NULL;
- if(h->length<0x09) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Manufacturer", _val);
- Py_DECREF(_val);
+ if(h->length < 0x13) {
+ break;
+ }
- _val = dmi_chassis_type_py(data[0x05]&0x7F);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Characteristics", NULL);
+ assert( sub_n != NULL );
- _val = dmi_chassis_lock(data[0x05]>>7);
- PyDict_SetItemString(caseData, "Lock", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x06]);
- PyDict_SetItemString(caseData, "Version", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x07]);
- PyDict_SetItemString(caseData, "Serial Number", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x08]);
- PyDict_SetItemString(caseData, "Asset Tag", _val);
- Py_DECREF(_val);
-
- if(h->length<0x0D) break;
- _val = dmi_chassis_state(data[0x09]);
- PyDict_SetItemString(caseData, "Boot-Up State", _val);
- Py_DECREF(_val);
-
- _val = dmi_chassis_state(data[0x0A]);
- PyDict_SetItemString(caseData, "Power Supply State", _val);
- Py_DECREF(_val);
-
- _val = dmi_chassis_state(data[0x0B]);
- PyDict_SetItemString(caseData, "Thermal State", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromString(dmi_chassis_security_status(data[0x0C]));
- PyDict_SetItemString(caseData, "Security Status", _val);
- Py_DECREF(_val);
-
- if(h->length<0x11) break;
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x0D));
- PyDict_SetItemString(caseData, "OEM Information", _val);
- Py_DECREF(_val);
-
- if(h->length<0x13) break;
- _val = dmi_chassis_height(data[0x11]);
- PyDict_SetItemString(caseData, "Height", _val);
- Py_DECREF(_val);
-
- _val = dmi_chassis_power_cords(data[0x12]);
- PyDict_SetItemString(caseData, "Number Of Power Cords", _val);
- Py_DECREF(_val);
-
- if(h->length < 0x15) break;
- if(h->length<0x15+data[0x13]*data[0x14]) break;
- _val = dmi_chassis_elements(data[0x13], data[0x14], data+0x15);
- PyDict_SetItemString(caseData, "Elements", _val);
- Py_DECREF(_val);
-
- break;
-
-
- case 4: /* 3.3.5 Processor Information */
-
- if(h->length<0x1A) break;
-
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Socket Designation", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_type(data[0x05]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromString(dmi_processor_family(h));
- PyDict_SetItemString(caseData, "Family", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_id(data[0x06], data+8, dmi_string(h, data[0x10]));
- PyDict_SetItemString(_val, "Vendor", dmi_string_py(h, data[0x07]));
- PyDict_SetItemString(caseData, "Manufacturer", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x10]);
- PyDict_SetItemString(caseData, "Version", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_voltage(data[0x11]);
- PyDict_SetItemString(caseData, "Voltage", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_frequency_py(data+0x12);
- PyDict_SetItemString(caseData, "External Clock", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_frequency_py(data+0x14);
- PyDict_SetItemString(caseData, "Max Speed", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_frequency_py(data+0x16);
- PyDict_SetItemString(caseData, "Current Speed", _val);
- Py_DECREF(_val);
-
- if(data[0x18]&(1<<6)) {
- _val = PyString_FromFormat("Populated:%s", dmi_processor_status(data[0x18]&0x07));
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
- } else {
- _val = PyString_FromString("Populated:No");
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
- }
- _val = dmi_processor_upgrade(data[0x19]);
- PyDict_SetItemString(caseData, "Upgrade", _val);
- Py_DECREF(_val);
-
- if(h->length<0x20) break;
- _val = dmi_processor_cache(WORD(data+0x1A), "L1", ver);
- PyDict_SetItemString(caseData, "L1 Cache Handle", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_cache(WORD(data+0x1C), "L2", ver);
- PyDict_SetItemString(caseData, "L2 Cache Handle", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_cache(WORD(data+0x1E), "L3", ver);
- PyDict_SetItemString(caseData, "L3 Cache Handle", _val);
- Py_DECREF(_val);
-
- if(h->length<0x23) break;
- _val = dmi_string_py(h, data[0x20]);
- PyDict_SetItemString(caseData, "Serial Number", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x21]);
- PyDict_SetItemString(caseData, "Asset Tag", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x22]);
- PyDict_SetItemString(caseData, "Part Number", _val);
- Py_DECREF(_val);
-
- if(h->length<0x28) break;
- if(data[0x23]!=0) {
- _val = PyString_FromFormat("%i", data[0x23]);
- PyDict_SetItemString(caseData, "Core Count", _val);
- Py_DECREF(_val);
- }
-
- if(data[0x24]!=0) {
- _val = PyString_FromFormat("%i", data[0x24]);
- PyDict_SetItemString(caseData, "Core Enabled", _val);
- Py_DECREF(_val);
- }
-
- if(data[0x25]!=0) {
- _val = PyString_FromFormat("%i", data[0x25]);
- PyDict_SetItemString(caseData, "Thread Count", _val);
- Py_DECREF(_val);
- }
-
- _val = dmi_processor_characteristics(WORD(data+0x26));
- PyDict_SetItemString(caseData, "Characteristics", _val);
- Py_DECREF(_val);
- break;
-
- case 5: /* 3.3.6 Memory Controller Information */
-
- if(h->length<0x0F) break;
- _val = dmi_memory_controller_ed_method(data[0x04]);
- PyDict_SetItemString(caseData, "Error Detecting Method", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_controller_ec_capabilities(data[0x05]);
- PyDict_SetItemString(caseData, "Error Correcting Capabilities", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_controller_interleave(data[0x06]);
- PyDict_SetItemString(caseData, "Supported Interleave", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_controller_interleave(data[0x07]);
- PyDict_SetItemString(caseData, "Current Interleave", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%i MB", 1<<data[0x08]);
- PyDict_SetItemString(caseData, "Maximum Memory Module Size", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%i MB", data[0x0E]*(1<<data[0x08]));
- PyDict_SetItemString(caseData, "Maximum Total Memory Size", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_controller_speeds(WORD(data+0x09));
- PyDict_SetItemString(caseData, "Supported Speeds", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_module_types(WORD(data+0x0B));
- PyDict_SetItemString(caseData, "Supported Memory Types", _val);
- Py_DECREF(_val);
-
- _val = dmi_processor_voltage(data[0x0D]);
- PyDict_SetItemString(caseData, "Memory Module Voltage", _val);
- Py_DECREF(_val);
-
- if(h->length<0x0F+data[0x0E]*sizeof(u16)) break;
- _val = dmi_memory_controller_slots(data[0x0E], data+0x0F);
- PyDict_SetItemString(caseData, "Associated Memory Sluts", _val);
- Py_DECREF(_val);
-
- if(h->length<0x10+data[0x0E]*sizeof(u16)) break;
- _val = dmi_memory_controller_ec_capabilities(data[0x0F+data[0x0E]*sizeof(u16)]);
- PyDict_SetItemString(caseData, "Enabled Error Correcting Capabilities", _val);
- Py_DECREF(_val);
- break;
-
- case 6: /* 3.3.7 Memory Module Information */
-
- if(h->length<0x0C) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Socket Designation", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_module_connections(data[0x05]);
- PyDict_SetItemString(caseData, "Bank Connections", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_module_speed(data[0x06]);
- PyDict_SetItemString(caseData, "Current Speed", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_module_types(WORD(data+0x07));
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_module_size(data[0x09]);
- PyDict_SetItemString(caseData, "Installed Size", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_module_size(data[0x0A]);
- PyDict_SetItemString(caseData, "Enabled Size", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_module_error(data[0x0B]);
- PyDict_SetItemString(caseData, "Error Status", _val);
- Py_DECREF(_val);
- break;
-
- case 7: /* 3.3.8 Cache Information */
-
- if(h->length<0x0F) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Socket Designation", _val);
- Py_DECREF(_val);
-
- _val = PyDict_New();
- PyDict_SetItemString(_val, "Enabled", WORD(data+0x05)&0x0080?Py_True:Py_False);
- PyDict_SetItemString(_val, "Socketed", WORD(data+0x05)&0x0008?Py_True:Py_False);
- PyDict_SetItemString(_val, "Level", PyInt_FromLong((WORD(data+0x05)&0x0007)+1));
- PyDict_SetItemString(caseData, "Configuration" , _val);
- Py_DECREF(_val);
-
- _val = dmi_cache_mode((WORD(data+0x05)>>8)&0x0003);
- PyDict_SetItemString(caseData, "Operational Mode", _val);
- Py_DECREF(_val);
+ dmixml_AddAttribute(sub_n, "level", "x1");
+ dmi_bios_characteristics_x1(sub_n, data[0x12]);
+ sub_n = NULL;
- _val = dmi_cache_location((WORD(data+0x05)>>5)&0x0003);
- PyDict_SetItemString(caseData, "Location", _val);
- Py_DECREF(_val);
+ if(h->length < 0x14) {
+ break;
+ }
- _val = dmi_cache_size(WORD(data+0x09));
- PyDict_SetItemString(caseData, "Installed Size", _val);
- Py_DECREF(_val);
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Characteristics", NULL);
+ assert( sub_n != NULL );
- _val = dmi_cache_size(WORD(data+0x07));
- PyDict_SetItemString(caseData, "Maximum Size", _val);
- Py_DECREF(_val);
+ dmixml_AddAttribute(sub_n, "level", "x2");
+ dmi_bios_characteristics_x2(sub_n, data[0x13]);
+ sub_n = NULL;
- _val = dmi_cache_types(WORD(data+0x0B));
- PyDict_SetItemString(caseData, "Supported SRAM Types", _val);
- Py_DECREF(_val);
+ if(h->length < 0x18) {
+ break;
+ }
- _val = dmi_cache_types(WORD(data+0x0D));
- PyDict_SetItemString(caseData, "Installed SRAM Type", _val);
- Py_DECREF(_val);
+ if(data[0x14] != 0xFF && data[0x15] != 0xFF) {
+ dmixml_AddTextChild(sect_n, "BIOSrevision", "%i.%i", data[0x14], data[0x15]);
+ }
- if(h->length<0x13) break;
- _val = dmi_memory_module_speed(data[0x0F]);
- PyDict_SetItemString(caseData, "Speed", _val);
- Py_DECREF(_val);
+ if(data[0x16] != 0xFF && data[0x17] != 0xFF) {
+ dmixml_AddTextChild(sect_n, "FirmwareRevision", "%i.%i", data[0x16], data[0x17]);
+ }
+ break;
- _val = dmi_cache_ec_type(data[0x10]);
- PyDict_SetItemString(caseData, "Error Correction Type", _val);
- Py_DECREF(_val);
+ case 1: /* 3.3.2 System Information */
+ if(h->length < 0x08) {
+ break;
+ }
- _val = dmi_cache_type(data[0x11]);
- PyDict_SetItemString(caseData, "System Type", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "Manufacturer", "%s", dmi_string(h, data[0x04]));
+ dmixml_AddTextChild(sect_n, "ProductName", "%s", dmi_string(h, data[0x05]));
+ dmixml_AddTextChild(sect_n, "Version", "%s", dmi_string(h, data[0x06]));
+ dmixml_AddTextChild(sect_n, "SerialNumber", "%s", dmi_string(h, data[0x07]));
- _val = dmi_cache_associativity(data[0x12]);
- PyDict_SetItemString(caseData, "Associativity", _val);
- Py_DECREF(_val);
+ if(h->length < 0x19) {
+ break;
+ }
- break;
+ dmi_system_uuid(sect_n, data + 0x08, ver);
- case 8: /* 3.3.9 Port Connector Information */
+ dmi_system_wake_up_type(sect_n, data[0x18]);
- if(h->length<0x09) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Internal Reference Designator", _val);
- Py_DECREF(_val);
+ if(h->length < 0x1B) {
+ break;
+ }
- _val = dmi_port_connector_type(data[0x05]);
- PyDict_SetItemString(caseData, "Internal Connector Type", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "SKUnumber", "%s", dmi_string(h, data[0x19]));
+ dmixml_AddTextChild(sect_n, "Family", "%s", dmi_string(h, data[0x1A]));
+ break;
- _val = dmi_string_py(h, data[0x06]);
- PyDict_SetItemString(caseData, "External Reference Designator", _val);
- Py_DECREF(_val);
+ case 2: /* 3.3.3 Base Board Information */
+ if(h->length < 0x08) {
+ break;
+ }
- _val = dmi_port_connector_type(data[0x07]);
- PyDict_SetItemString(caseData, "External Connector Type", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "Manufacturer", "%s", dmi_string(h, data[0x04]));
+ dmixml_AddTextChild(sect_n, "ProductName", "%s", dmi_string(h, data[0x05]));
+ dmixml_AddTextChild(sect_n, "Version", "%s", dmi_string(h, data[0x06]));
+ dmixml_AddTextChild(sect_n, "SerialNumber", "%s", dmi_string(h, data[0x07]));
- _val = dmi_port_type(data[0x08]);
- PyDict_SetItemString(caseData, "Port Type", _val);
- Py_DECREF(_val);
+ if(h->length < 0x0F) {
+ break;
+ }
- break;
+ dmixml_AddTextChild(sect_n, "AssetTag", "%s", dmi_string(h, data[0x08]));
- case 9: /* 3.3.10 System Slots */
+ dmi_base_board_features(sect_n, data[0x09]);
- if(h->length<0x0C) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Designation", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "ChassisLocation", "%s", dmi_string(h, data[0x0A]));
+ dmixml_AddTextChild(sect_n, "ChassisHandle", "0x%04x", WORD(data + 0x0B));
- _val = dmi_slot_bus_width(data[0x06]);
- PyDict_SetItemString(caseData, "Type:SlotBusWidth", _val);
- Py_DECREF(_val);
- _val = dmi_slot_type(data[0x05]);
- PyDict_SetItemString(caseData, "Type:SlotType", _val);
- Py_DECREF(_val);
+ dmi_base_board_type(sect_n, "Type", data[0x0D]);
- _val = dmi_slot_current_usage(data[0x07]);
- PyDict_SetItemString(caseData, "Current Usage", _val);
- Py_DECREF(_val);
+ if(h->length < 0x0F + data[0x0E] * sizeof(u16)) {
+ break;
+ }
- _val = dmi_slot_length(data[0x08]);
- PyDict_SetItemString(caseData, "SlotLength", _val);
- Py_DECREF(_val);
- _val = dmi_slot_id(data[0x09], data[0x0A], data[0x05]);
- PyDict_SetItemString(caseData, "SlotId", _val);
- Py_DECREF(_val);
+ dmi_base_board_handles(sect_n, data[0x0E], data + 0x0F);
+ break;
- _val = (h->length<0x0D)?dmi_slot_characteristics(data[0x0B], 0x00):dmi_slot_characteristics(data[0x0B], data[0x0C]);
- PyDict_SetItemString(caseData, "Characteristics", _val);
- Py_DECREF(_val);
- break;
+ case 3: /* 3.3.4 Chassis Information */
+ if(h->length < 0x09) {
+ break;
+ }
- case 10: /* 3.3.11 On Board Devices Information */
+ dmixml_AddTextChild(sect_n, "Manufacturer", "%s", dmi_string(h, data[0x04]));
+ dmi_chassis_type(sect_n, data[0x05] & 0x7F);
+ dmi_chassis_lock(sect_n, data[0x05] >> 7);
+ dmixml_AddTextChild(sect_n, "Version", "%s", dmi_string(h, data[0x06]));
+ dmixml_AddTextChild(sect_n, "SerialNumber", "%s", dmi_string(h, data[0x07]));
+ dmixml_AddTextChild(sect_n, "AssetTag", "%s", dmi_string(h, data[0x08]));
- PyDict_SetItemString(caseData, "dmi_on_board_devices", dmi_on_board_devices(h));
+ if(h->length < 0x0D) {
+ break;
+ }
- break;
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "ChassisStates", NULL);
+ assert( sub_n != NULL );
- case 11: /* 3.3.12 OEM Strings */
+ dmi_chassis_state(sub_n, "BootUp", data[0x09]);
+ dmi_chassis_state(sub_n, "PowerSupply", data[0x0A]);
+ dmi_chassis_state(sub_n, "Thermal", data[0x0B]);
+ sub_n = NULL;
- if(h->length<0x05) break;
- _val = dmi_oem_strings(h);
- PyDict_SetItemString(caseData, "Strings", _val);
- Py_DECREF(_val);
+ dmi_chassis_security_status(sect_n, data[0x0C]);
- break;
+ if(h->length < 0x11) {
+ break;
+ }
- case 12: /* 3.3.13 System Configuration Options */
+ dmixml_AddTextChild(sect_n, "OEMinformation", "0x%08x", DWORD(data + 0x0D));
- if(h->length<0x05) break;
- _val = dmi_system_configuration_options(h);
- PyDict_SetItemString(caseData, "Options", _val);
- Py_DECREF(_val);
+ if(h->length < 0x13) {
+ break;
+ }
- break;
+ dmi_chassis_height(sect_n, data[0x11]);
+ dmi_chassis_power_cords(sect_n, data[0x12]);
- case 13: /* 3.3.14 BIOS Language Information */
+ if((h->length < 0x15) || (h->length < 0x15 + data[0x13] * data[0x14])){
+ break;
+ }
- if(h->length<0x16) break;
- _val = PyString_FromFormat("%i", data[0x04]);
- PyDict_SetItemString(caseData, "Installable Languages", _val);
- Py_DECREF(_val);
+ dmi_chassis_elements(sect_n, data[0x13], data[0x14], data + 0x15);
+ break;
- _val = dmi_bios_languages(h);
- PyList_SET_ITEM(_val, 0, dmi_string_py(h, data[0x15]));
- PyDict_SetItemString(caseData, "Currently Installed Language", _val);
- Py_DECREF(_val);
+ case 4: /* 3.3.5 Processor Information */
+ if(h->length < 0x1A) {
+ break;
+ }
- break;
+ dmixml_AddTextChild(sect_n, "SocketDesignation", "%s", dmi_string(h, data[0x04]));
+ dmi_processor_type(sect_n, data[0x05]);
+ dmi_processor_family(sect_n, h);
- case 14: /* 3.3.15 Group Associations */
+ dmi_processor_id(sect_n, data[0x06], data + 8, dmi_string(h, data[0x10]));
- if(h->length<0x05) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Name", _val);
- Py_DECREF(_val);
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Manufacturer", NULL);
+ assert( sub_n != NULL );
+ dmixml_AddTextChild(sub_n, "Vendor", dmi_string(h, data[0x07]));
- _val = PyString_FromFormat("%i", (h->length-0x05)/3);
- PyDict_SetItemString(caseData, "Items", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sub_n, "Version", dmi_string(h, data[0x10]));
+ sub_n = NULL;
- _val = dmi_group_associations_items((h->length-0x05)/3, data+0x05);
- PyDict_SetItemString(caseData, "Items2", _val); //. FIXME: Title
- Py_DECREF(_val);
- break;
+ dmi_processor_voltage(sect_n, data[0x11]);
- case 15: /* 3.3.16 System Event Log */
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Frequencies", NULL);
+ assert( sub_n != NULL );
- if(h->length<0x14) break;
- _val = PyString_FromFormat("%i bytes", WORD(data+0x04));
- PyDict_SetItemString(caseData, "Area Length", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sub_n, "ExternalClock", "%i", dmi_processor_frequency(data + 0x12));
+ dmixml_AddTextChild(sub_n, "MaxSpeed", "%i", dmi_processor_frequency(data + 0x14));
+ dmixml_AddTextChild(sub_n, "CurrentSpeed", "%i", dmi_processor_frequency(data + 0x16));
+ sub_n = NULL;
- _val = PyString_FromFormat("0x%04x", WORD(data+0x06));
- PyDict_SetItemString(caseData, "Header Start Offset", _val);
- Py_DECREF(_val);
+ /* TODO: Should CurrentSpeed be renamed to BootSpeed? Specification
+ * says this about Current Speed:
+ *
+ * This field identifies the processor's speed at
+ * system boot and the Processor ID field implies the
+ * processor's additional speed characteristics (i.e. single
+ * speed or multiple speed).
+ */
- if(WORD(data+0x08)-WORD(data+0x06)) {
- _val = PyString_FromFormat("%i byte%s", WORD(data+0x08)-WORD(data+0x06), WORD(data+0x08)-WORD(data+0x06)>1?"s":"");
- PyDict_SetItemString(caseData, "Header Length", _val);
- Py_DECREF(_val);
- }
+ if(data[0x18] & (1 << 6)) {
+ dmixml_AddAttribute(sect_n, "populated", "1");
+ dmi_processor_status(sect_n, data[0x18] & 0x07);
+ } else {
+ dmixml_AddAttribute(sect_n, "populated", "0");
+ dmixml_AddTextChild(sect_n, "Populated", "No");
+ }
- _val = PyString_FromFormat("0x%04x", WORD(data+0x08));
- PyDict_SetItemString(caseData, "Data Start Offset", _val);
- Py_DECREF(_val);
+ dmi_processor_upgrade(sect_n, data[0x19]);
- _val = PyString_FromFormat("%s", dmi_event_log_method(data[0x0A]));
- PyDict_SetItemString(caseData, "Access Method", _val);
- Py_DECREF(_val);
+ if(h->length < 0x20) {
+ break;
+ }
- _val = dmi_event_log_address_py(data[0x0A], data+0x10);
- PyDict_SetItemString(caseData, "Access Address", _val);
- Py_DECREF(_val);
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Cache", NULL);
+ assert( sub_n != NULL );
- _val = dmi_event_log_status_py(data[0x0B]);
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
+ sub2_n = xmlNewChild(sub_n, NULL, (xmlChar *) "Level", NULL);
+ assert( sub2_n != NULL );
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x0C));
- PyDict_SetItemString(caseData, "Change Token", _val);
- Py_DECREF(_val);
+ dmixml_AddAttribute(sub2_n, "level", "1");
+ dmi_processor_cache(sub2_n, WORD(data + 0x1A), ver);
+ sub2_n = NULL;
- if(h->length<0x17) break;
- _val = PyString_FromFormat("%s", dmi_event_log_header_type(data[0x14]));
- PyDict_SetItemString(caseData, "Header Format", _val);
- Py_DECREF(_val);
- _val = PyString_FromFormat("%i", data[0x15]);
- PyDict_SetItemString(caseData, "Supported Log Type Descriptors", _val);
- Py_DECREF(_val);
+ sub2_n = xmlNewChild(sub_n, NULL, (xmlChar *) "Level", NULL);
+ assert( sub2_n != NULL );
- if(h->length<0x17+data[0x15]*data[0x16]) break;
- _val = dmi_event_log_descriptors(data[0x15], data[0x16], data+0x17);
- PyDict_SetItemString(caseData, "DMI Event Log Descriptors", _val);
- Py_DECREF(_val);
+ dmixml_AddAttribute(sub2_n, "level", "2");
+ dmi_processor_cache(sub2_n, WORD(data + 0x1C), ver);
+ sub2_n = NULL;
- break;
+ sub2_n = xmlNewChild(sub_n, NULL, (xmlChar *) "Level", NULL);
+ assert( sub2_n != NULL );
- case 16: /* 3.3.17 Physical Memory Array */
+ dmixml_AddAttribute(sub2_n, "level", "3");
+ dmi_processor_cache(sub2_n, WORD(data + 0x1E), ver);
+ sub2_n = NULL;
+ sub_n = NULL;
- if(h->length<0x0F) break;
- _val = dmi_memory_array_location(data[0x04]);
- PyDict_SetItemString(caseData, "Location", _val);
- Py_DECREF(_val);
+ if(h->length < 0x23) {
+ break;
+ }
- _val = dmi_memory_array_use(data[0x05]);
- PyDict_SetItemString(caseData, "Use", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "SerialNumber", "%s", dmi_string(h, data[0x20]));
+ dmixml_AddTextChild(sect_n, "AssetTag", "%s", dmi_string(h, data[0x21]));
+ dmixml_AddTextChild(sect_n, "PartNumber", "%s", dmi_string(h, data[0x22]));
- _val = dmi_memory_array_ec_type(data[0x06]);
- PyDict_SetItemString(caseData, "Error Correction Type", _val);
- Py_DECREF(_val);
+ if(h->length < 0x28) {
+ break;
+ }
- _val = dmi_memory_array_capacity(DWORD(data+0x07));
- PyDict_SetItemString(caseData, "Maximum Capacity", _val);
- Py_DECREF(_val);
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Cores", NULL);
+ assert( sub_n != NULL );
- _val = dmi_memory_array_error_handle(WORD(data+0x0B));
- PyDict_SetItemString(caseData, "Error Information Handle", _val);
- Py_DECREF(_val);
+ if(data[0x23] != 0) {
+ dmixml_AddTextChild(sub_n, "CoreCount", "%i", data[0x23]);
+ }
- _val = PyInt_FromLong(WORD(data+0x0D));
- PyDict_SetItemString(caseData, "Number Of Devices", _val);
- Py_DECREF(_val);
- break;
+ if(data[0x24] != 0) {
+ dmixml_AddTextChild(sub_n, "CoresEnabled", "%i", data[0x24]);
+ }
+ if(data[0x25] != 0) {
+ dmixml_AddTextChild(sub_n, "ThreadCount", "%i", data[0x25]);
+ }
- case 17: /* 3.3.18 Memory Device */
+ dmi_processor_characteristics(sub_n, WORD(data + 0x26));
+ sub_n = NULL;
+ break;
- if(h->length<0x15) break;
- _val = PyString_FromFormat("0x%04x", WORD(data+0x04));
- PyDict_SetItemString(caseData, "Array Handle", _val);
- Py_DECREF(_val);
+ case 5: /* 3.3.6 Memory Controller Information */
+ if(h->length < 0x0F) {
+ break;
+ }
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "ErrorCorrection", NULL);
+ assert( sub_n != NULL );
+
+ dmi_memory_controller_ed_method(sub_n, data[0x04]);
+ dmi_memory_controller_ec_capabilities(sub_n, "Capabilities", data[0x05]);
+ sub_n = NULL;
+
+ dmi_memory_controller_interleave(sect_n, "SupportedInterleave", data[0x06]);
+ dmi_memory_controller_interleave(sect_n, "CurrentInterleave", data[0x07]);
+
+ sub_n = dmixml_AddTextChild(sect_n, "MaxMemoryModuleSize",
+ "%i", (1 << data[0x08]));
+ dmixml_AddAttribute(sub_n, "unit", "MB");
+ sub_n = NULL;
+
+ sub_n = dmixml_AddTextChild(sect_n, "MaxTotalMemorySize",
+ "%i", data[0x0E] * (1 << data[0x08]));
+ dmixml_AddAttribute(sub_n, "unit", "MB");
+ sub_n = NULL;
+
+ dmi_memory_controller_speeds(sect_n, WORD(data + 0x09));
+ dmi_memory_module_types(sect_n, "SupportedTypes", WORD(data + 0x0B));
+ dmi_processor_voltage(sect_n, data[0x0D]);
+
+ if(h->length < 0x0F + data[0x0E] * sizeof(u16)) {
+ break;
+ }
+
+ dmi_memory_controller_slots(sect_n, data[0x0E], data + 0x0F);
- _val = dmi_memory_array_error_handle(WORD(data+0x06));
- PyDict_SetItemString(caseData, "Error Information Handle", _val);
- Py_DECREF(_val);
+ if(h->length < 0x10 + data[0x0E] * sizeof(u16)) {
+ break;
+ }
+
+ dmi_memory_controller_ec_capabilities(sect_n, "EnabledErrorCorrection",
+ data[0x0F + data[0x0E] * sizeof(u16)]);
+ break;
- _val = dmi_memory_device_width(WORD(data+0x08));
- PyDict_SetItemString(caseData, "Total Width", _val);
- Py_DECREF(_val);
+ case 6: /* 3.3.7 Memory Module Information */
+ if(h->length < 0x0C) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "SocketDesignation", "%s", dmi_string(h, data[0x04]));
+ dmi_memory_module_connections(sect_n, data[0x05]);
+ dmi_memory_module_speed(sect_n, "ModuleSpeed", data[0x06]);
+ dmi_memory_module_types(sect_n, "Type", WORD(data + 0x07));
+
+ dmi_memory_module_size(sect_n, "InstalledSize", data[0x09]);
+ dmi_memory_module_size(sect_n, "EnabledSize", data[0x0A]);
+ dmi_memory_module_error(sect_n, data[0x0B]);
+ break;
+
+ case 7: /* 3.3.8 Cache Information */
+ if(h->length < 0x0F) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "SocketDesignation", dmi_string(h, data[0x04]));
+ dmixml_AddAttribute(sect_n, "Enabled", "%i", (WORD(data + 0x05) & 0x0080 ? 1 : 0));
+ dmixml_AddAttribute(sect_n, "Socketed", "%i", (WORD(data + 0x05) & 0x0008 ? 1 : 0));
+ dmixml_AddAttribute(sect_n, "Level", "%ld", ((WORD(data + 0x05) & 0x0007) + 1));
+
+ sub_n = dmixml_AddTextChild(sect_n, "OperationalMode", "%s",
+ dmi_cache_mode((WORD(data + 0x05) >> 8) & 0x0003));
+ dmixml_AddAttribute(sub_n, "flags", "0x%04x", (WORD(data + 0x05) >> 8) & 0x0003);
+ sub_n = NULL;
+
+ dmi_cache_location(sect_n, (WORD(data + 0x05) >> 5) & 0x0003);
+ dmi_cache_size(sect_n, "InstalledSize", WORD(data + 0x09));
+ dmi_cache_size(sect_n, "MaximumSize", WORD(data + 0x07));
+
+ dmi_cache_types(sect_n, "SupportedSRAMtypes", WORD(data + 0x0B));
+ dmi_cache_types(sect_n, "InstalledSRAMtypes", WORD(data + 0x0D));
+
+ if(h->length < 0x13) {
+ break;
+ }
+
+ dmi_memory_module_speed(sect_n, "Speed", data[0x0F]);
+ dmi_cache_ec_type(sect_n, data[0x10]);
+ dmi_cache_type(sect_n, data[0x11]);
+ dmi_cache_associativity(sect_n, data[0x12]);
+ break;
+
+ case 8: /* 3.3.9 Port Connector Information */
+ if(h->length < 0x09) {
+ break;
+ }
+
+ sub_n = dmixml_AddTextChild(sect_n, "DesignatorRef", dmi_string(h, data[0x04]));
+ assert( sub_n != NULL );
+ dmixml_AddAttribute(sub_n, "type", "internal");
+ sub_n = NULL;
+
+ dmi_port_connector_type(sect_n, "internal", data[0x05]);
+
+ sub_n = dmixml_AddTextChild(sect_n, "DesignatorRef", dmi_string(h, data[0x06]));
+ assert( sub_n != NULL );
+ dmixml_AddAttribute(sub_n, "type", "external");
+ sub_n = NULL;
+
+ dmi_port_connector_type(sect_n, "external", data[0x07]);
+ dmi_port_type(sect_n, data[0x08]);
+ break;
+
+ case 9: /* 3.3.10 System Slots */
+ if(h->length < 0x0C) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "Designation", "%s", dmi_string(h, data[0x04]));
+
+ dmi_slot_bus_width(sect_n, data[0x06]);
+ dmi_slot_type(sect_n, data[0x05]);
+ dmi_slot_current_usage(sect_n, data[0x07]);
+ dmi_slot_length(sect_n, data[0x08]);
+ dmi_slot_id(sect_n, data[0x09], data[0x0A], data[0x05]);
- _val = dmi_memory_device_width(WORD(data+0x0A));
- PyDict_SetItemString(caseData, "Data Width", _val);
- Py_DECREF(_val);
+ if( h->length < 0x0D ) {
+ dmi_slot_characteristics(sect_n, data[0x0B], 0x00);
+ } else {
+ dmi_slot_characteristics(sect_n, data[0x0B], data[0x0C]);
+ }
+ break;
- _val = dmi_memory_device_size(WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Size", _val);
- Py_DECREF(_val);
+ case 10: /* 3.3.11 On Board Devices Information */
+ dmi_on_board_devices(sect_n, "dmi_on_board_devices", h);
+ break;
+
+ case 11: /* 3.3.12 OEM Strings */
+ if(h->length < 0x05) {
+ break;
+ }
+
+ dmi_oem_strings(sect_n, h);
+ break;
+
+ case 12: /* 3.3.13 System Configuration Options */
+ if(h->length < 0x05) {
+ break;
+ }
+
+ dmi_system_configuration_options(sect_n, h);
+ break;
+
+ case 13: /* 3.3.14 BIOS Language Information */
+ if(h->length < 0x16) {
+ break;
+ }
+
+ dmixml_AddAttribute(sect_n, "installable_languages", "%i", data[0x04]);
+
+ dmi_bios_languages(sect_n, h);
+ break;
+
+ case 14: /* 3.3.15 Group Associations */
+ if(h->length < 0x05) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "Name", "%s", dmi_string(h, data[0x04]));
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Groups", NULL);
+ assert( sub_n != NULL );
+ dmi_group_associations_items(sub_n, (h->length - 0x05) / 3, data + 0x05);
+ sub_n = NULL;
+ break;
+
+ case 15: /* 3.3.16 System Event Log */
+ // SysEventLog - sect_n
+ if(h->length < 0x14) {
+ break;
+ }
+
+ dmi_event_log_status(sect_n, data[0x0B]);
+
+ // SysEventLog/Access - sub
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Access", NULL);
+ assert( sub_n != NULL );
+
+ dmixml_AddAttribute(sub_n, "AreaLength", "%i", WORD(data + 0x04));
+ dmi_event_log_method(sub_n, data[0x0A]);
+ dmi_event_log_address(sub_n, data[0x0A], data + 0x10);
+
+ // SysEventLog/Access/Header - sub2
+ sub2_n = xmlNewChild(sub_n, NULL, (xmlChar *) "Header", NULL);
+ assert( sub2_n != NULL );
+
+ dmixml_AddTextChild(sub2_n, "OffsetStart", "0x%04x", WORD(data + 0x06));
+
+ if((WORD(data + 0x08) - WORD(data + 0x06)) >= 0) {
+ dmixml_AddTextChild(sub2_n, "Length", "%i", WORD(data + 0x08) - WORD(data + 0x06));
+ }
+
+ dmixml_AddTextChild(sub2_n, "DataOffset", "0x%04x", WORD(data + 0x08));
+ dmixml_AddTextChild(sub2_n, "ChangeToken", "0x%08x", DWORD(data + 0x0C));
+
+ if(h->length < 0x17) {
+ break;
+ }
+
+ // SysEventLog/Access/Header/Format - sub2_n
+ dmi_event_log_header_type(sub2_n, data[0x14]);
+
+ sub2_n = NULL;
+ sub_n = NULL;
+
+ // SysEventLog/LogTypes - resuing sub_n
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "LogTypes", NULL);
+ assert( sub_n != NULL );
+
+ // SysEventLog/LogTypes/@count
+ dmixml_AddAttribute(sub_n, "count", "%i", data[0x15]);
+
+ if(h->length < 0x17 + data[0x15] * data[0x16]) {
+ break;
+ }
+
+ dmixml_AddAttribute(sub_n, "length", "%i", data[0x16]);
+
+ // SysEventLog/LogTypes/LogType
+ dmi_event_log_descriptors(sub_n, data[0x15], data[0x16], data + 0x17);
+ sub_n = NULL;
+ break;
+
+ case 16: /* 3.3.17 Physical Memory Array */
+ if(h->length < 0x0F) {
+ break;
+ }
+
+ dmixml_AddAttribute(sect_n, "NumDevices", "%ld", WORD(data + 0x0D));
+ dmi_memory_array_location(sect_n, data[0x04]);
+ dmi_memory_array_use(sect_n, data[0x05]);
+ dmi_memory_array_ec_type(sect_n, data[0x06]);
+ dmi_memory_array_capacity(sect_n, DWORD(data + 0x07));
+ dmi_memory_array_error_handle(sect_n, WORD(data + 0x0B));
+ break;
+
+ case 17: /* 3.3.18 Memory Device */
+ if(h->length < 0x15) {
+ break;
+ }
+
+ dmixml_AddAttribute(sect_n, "ArrayHandle", "0x%04x", WORD(data + 0x04));
+ dmi_memory_array_error_handle(sect_n, WORD(data + 0x06));
+
+ dmi_memory_device_width(sect_n, "TotalWidth", WORD(data + 0x08));
+ dmi_memory_device_width(sect_n, "DataWidth", WORD(data + 0x0A));
+ dmi_memory_device_size(sect_n, WORD(data + 0x0C));
+ dmi_memory_device_form_factor(sect_n, data[0x0E]);
+ dmi_memory_device_set(sect_n, data[0x0F]);
+ dmixml_AddTextChild(sect_n, "Locator", dmi_string(h, data[0x10]));
+ dmixml_AddTextChild(sect_n, "BankLocator", dmi_string(h, data[0x11]));
+
+ dmi_memory_device_type(sect_n, data[0x12]);
+ dmi_memory_device_type_detail(sect_n, WORD(data + 0x13));
+
+ if(h->length < 0x17) {
+ break;
+ }
+
+ dmi_memory_device_speed(sect_n, WORD(data + 0x15));
+
+ if(h->length < 0x1B) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "Manufacturer", "%s", dmi_string(h, data[0x17]));
+ dmixml_AddTextChild(sect_n, "SerialNumber", "%s", dmi_string(h, data[0x18]));
+ dmixml_AddTextChild(sect_n, "AssetTag", "%s", dmi_string(h, data[0x19]));
+ dmixml_AddTextChild(sect_n, "PartNumber", "%s", dmi_string(h, data[0x1A]));
+ break;
+
+ case 18: /* 3.3.19 32-bit Memory Error Information */
+ case 33: /* 3.3.34 64-bit Memory Error Information */
+ if( h->type == 18 ) {
+ dmixml_AddAttribute(sect_n, "bits", "32");
+ } else {
+ dmixml_AddAttribute(sect_n, "bits", "64");
+ }
+
+ if( ((h->type == 18) && (h->length < 0x17)) /* 32-bit */
+ || ((h->type == 33) && (h->length < 0x1F)) ) /* 64-bit */
+ {
+ break;
+ }
+
+ dmi_memory_error_type(sect_n, data[0x04]);
+ dmi_memory_error_granularity(sect_n, data[0x05]);
+ dmi_memory_error_operation(sect_n, data[0x06]);
+ dmi_memory_error_syndrome(sect_n, DWORD(data + 0x07));
+
+ if( h->type == 18 ) {
+ /* 32-bit */
+ dmi_32bit_memory_error_address(sect_n, "MemArrayAddr", DWORD(data + 0x0B));
+ dmi_32bit_memory_error_address(sect_n, "DeviceAddr", DWORD(data + 0x0F));
+ dmi_32bit_memory_error_address(sect_n, "Resolution", DWORD(data + 0x13));
+ } else if( h->type == 33 ) {
+ /* 64-bit */
+ dmi_64bit_memory_error_address(sect_n, "MemArrayAddr", QWORD(data + 0x0B));
+ dmi_64bit_memory_error_address(sect_n, "DeviceAddr", QWORD(data + 0x13));
+ dmi_32bit_memory_error_address(sect_n, "Resolution", DWORD(data + 0x1B));
+ }
+ break;
+
+ case 19: /* 3.3.20 Memory Array Mapped Address */
+ if(h->length < 0x0F) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "StartAddress", "0x%08x%03x",
+ (DWORD(data + 0x04) >> 2),
+ (DWORD(data + 0x04) & 0x3) << 10);
+ dmixml_AddTextChild(sect_n, "EndAddress", "0x%08x%03x",
+ (DWORD(data + 0x08) >> 2),
+ ((DWORD(data + 0x08) & 0x3) << 10) + 0x3FF);
+ dmi_mapped_address_size(sect_n, DWORD(data + 0x08) - DWORD(data + 0x04) + 1);
+ dmixml_AddTextChild(sect_n, "PhysicalArrayHandle", "0x%04x", WORD(data + 0x0C));
+ dmixml_AddTextChild(sect_n, "PartitionWidth", "%i", data[0x0F]);
+ break;
+
+ case 20: /* 3.3.21 Memory Device Mapped Address */
+ if(h->length < 0x13) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "StartAddress", "0x%08x%03x",
+ (DWORD(data + 0x04) >> 2),
+ (DWORD(data + 0x04) & 0x3) << 10);
+
+ dmixml_AddTextChild(sect_n, "EndAddress", "0x%08x%03x",
+ (DWORD(data + 0x08) >> 2),
+ ((DWORD(data + 0x08) & 0x3) << 10) + 0x3FF);
+
+ dmi_mapped_address_size(sect_n, DWORD(data + 0x08) - DWORD(data + 0x04) + 1);
+
+ dmixml_AddTextChild(sect_n, "PhysicalDeviceHandle", "0x%04x", WORD(data + 0x0C));
+ dmixml_AddTextChild(sect_n, "MemArrayMappedAddrHandle", "0x%04x", WORD(data + 0x0E));
+
+ dmi_mapped_address_row_position(sect_n, data[0x10]);
+
+ dmi_mapped_address_interleave_position(sect_n, data[0x11]);
+ dmi_mapped_address_interleaved_data_depth(sect_n, data[0x12]);
+ break;
+
+ case 21: /* 3.3.22 Built-in Pointing Device */
+ if(h->length < 0x07) {
+ break;
+ }
+
+ dmi_pointing_device_type(sect_n, data[0x04]);
+ dmi_pointing_device_interface(sect_n, data[0x05]);
+ dmixml_AddTextChild(sect_n, "Buttons", "%i", data[0x06]);
+ break;
+
+ case 22: /* 3.3.23 Portable Battery */
+ if(h->length < 0x10) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "Location", "%s", dmi_string(h, data[0x04]));
+ dmixml_AddTextChild(sect_n, "Manufacturer", "%s", dmi_string(h, data[0x05]));
+
+ if(data[0x06] || h->length < 0x1A) {
+ dmixml_AddTextChild(sect_n, "ManufactureDate", "%s", dmi_string(h, data[0x06]));
+ }
+
+ if(data[0x07] || h->length < 0x1A) {
+ dmixml_AddTextChild(sect_n, "SerialNumber", "%s", dmi_string(h, data[0x07]));
+ }
+
+ dmixml_AddTextChild(sect_n, "Name", "%s", dmi_string(h, data[0x08]));
+
+ if(data[0x09] != 0x02 || h->length < 0x1A) {
+ dmi_battery_chemistry(sect_n, data[0x09]);
+ }
+
+ dmi_battery_capacity(sect_n, WORD(data + 0x0A), (h->length < 0x1A ? 1 : data[0x15]));
+ dmi_battery_voltage(sect_n, WORD(data + 0x0C));
+ dmixml_AddTextChild(sect_n, "SBDSversion", "%s", dmi_string(h, data[0x0E]));
+
+ dmi_battery_maximum_error(sect_n, data[0x0F]);
+
+ if(h->length < 0x1A) {
+ break;
+ }
+
+ if(data[0x07] == 0) {
+ dmixml_AddTextChild(sect_n, "SBDSserialNumber", "%04x", WORD(data + 0x10));
+ }
+ if(data[0x06] == 0) {
+ dmixml_AddTextChild(sect_n, "SBDSmanufactureDate", "%i-%02u-%02u",
+ 1980 + (WORD(data + 0x12) >> 9),
+ (WORD(data + 0x12) >> 5) & 0x0F,
+ (WORD(data + 0x12) & 0x1F));
+ }
+ if(data[0x09] == 0x02) {
+ dmixml_AddTextChild(sect_n, "SBDSchemistry", "%s", dmi_string(h, data[0x14]));
+ }
+
+ dmixml_AddTextChild(sect_n, "OEMinformation", "0x%08x", DWORD(data + 0x16));
+ break;
- _val = dmi_memory_device_form_factor(data[0x0E]);
- PyDict_SetItemString(caseData, "Form Factor", _val);
- Py_DECREF(_val);
+ case 23: /* 3.3.24 System Reset */
+ if(h->length < 0x0D) {
+ break;
+ }
- _val = dmi_memory_device_set(data[0x0F]);
- PyDict_SetItemString(caseData, "Set", _val);
- Py_DECREF(_val);
+ sub_n = dmixml_AddTextChild(sect_n, "Status", "%s",
+ data[0x04] & (1 << 0) ? "Enabled" : "Disabled");
+ dmixml_AddAttribute(sub_n, "enabled", "%i", data[0x04] & (1 << 0) ? 1 : 0);
+ sub_n = NULL;
- _val = dmi_string_py(h, data[0x10]);
- PyDict_SetItemString(caseData, "Locator", _val);
- Py_DECREF(_val);
+ sub_n = dmixml_AddTextChild(sect_n, "WatchdogTimer", "%s",
+ data[0x04] & (1 << 5) ? "Present" : "Not Present");
+ dmixml_AddAttribute(sub_n, "present", "%i", data[0x04] & (1 << 5) ? 1 : 0);
+ sub_n = NULL;
- _val = dmi_string_py(h, data[0x11]);
- PyDict_SetItemString(caseData, "Bank Locator", _val);
- Py_DECREF(_val);
+ if(!(data[0x04] & (1 << 5))) {
+ break;
+ }
- _val = dmi_memory_device_type(data[0x12]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
+ dmi_system_reset_boot_option(sect_n, "BootOption", (data[0x04] >> 1) & 0x3);
+ dmi_system_reset_boot_option(sect_n, "BootOptionOnLimit", (data[0x04] >> 3) & 0x3);
- _val = dmi_memory_device_type_detail(WORD(data+0x13));
- PyDict_SetItemString(caseData, "Type Detail", _val);
- Py_DECREF(_val);
+ dmi_system_reset_count(sect_n, "ResetCount", WORD(data + 0x05));
+ dmi_system_reset_count(sect_n, "ResetLimit", WORD(data + 0x07));
- if(h->length<0x17) break;
- _val = dmi_memory_device_speed(WORD(data+0x15));
- PyDict_SetItemString(caseData, "Speed", _val);
- Py_DECREF(_val);
+ dmi_system_reset_timer(sect_n, "TimerInterval", WORD(data + 0x09));
+ dmi_system_reset_timer(sect_n, "Timeout", WORD(data + 0x0B));
+ break;
- if(h->length<0x1B) break;
- _val = dmi_string_py(h, data[0x17]);
- PyDict_SetItemString(caseData, "Manufacturer", _val);
- Py_DECREF(_val);
+ case 24: /* 3.3.25 Hardware Security */
+ if(h->length < 0x05) {
+ break;
+ }
- _val = dmi_string_py(h, data[0x18]);
- PyDict_SetItemString(caseData,"Serial Number" , _val);
- Py_DECREF(_val);
+ dmi_hardware_security_status(sect_n, "PowerOnPassword", data[0x04] >> 6);
+ dmi_hardware_security_status(sect_n, "KeyboardPassword", (data[0x04] >> 4) & 0x3);
+ dmi_hardware_security_status(sect_n, "AdministratorPassword", (data[0x04] >> 2) & 0x3);
+ dmi_hardware_security_status(sect_n, "FronPanelReset", data[0x04] & 0x3);
- _val = dmi_string_py(h, data[0x19]);
- PyDict_SetItemString(caseData, "Asset Tag", _val);
- Py_DECREF(_val);
+ break;
- _val = dmi_string_py(h, data[0x1A]);
- PyDict_SetItemString(caseData, "Part Number", _val);
- Py_DECREF(_val);
- break;
+ case 25: /* 3.3.26 System Power Controls */
+ if(h->length < 0x09) {
+ break;
+ }
- case 18: /* 3.3.19 32-bit Memory Error Information */
+ dmi_power_controls_power_on(sect_n, "NextSchedPowerOn", data + 0x04);
+ break;
- if(h->length<0x17) break;
- _val = dmi_memory_error_type(data[0x04]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
+ case 26: /* 3.3.27 Voltage Probe */
+ dmixml_AddAttribute(sect_n, "probetype", "Voltage");
- _val = dmi_memory_error_granularity(data[0x05]);
- PyDict_SetItemString(caseData, "Granularity", _val);
- Py_DECREF(_val);
+ if(h->length < 0x14) {
+ break;
+ }
- _val = dmi_memory_error_operation(data[0x06]);
- PyDict_SetItemString(caseData, "Operation", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "Description", "%s", dmi_string(h, data[0x04]));
- _val = dmi_memory_error_syndrome(DWORD(data+0x07));
- PyDict_SetItemString(caseData, "Vendor Syndrome", _val);
- Py_DECREF(_val);
+ dmi_voltage_probe_location(sect_n, data[0x05] & 0x1f);
+ dmi_probe_status(sect_n, data[0x05] >> 5);
- _val = dmi_32bit_memory_error_address(DWORD(data+0x0B));
- PyDict_SetItemString(caseData, "Memory Array Address", _val);
- Py_DECREF(_val);
+ dmi_voltage_probe_value(sect_n, "MaxValue", WORD(data + 0x06));
+ dmi_voltage_probe_value(sect_n, "MinValue", WORD(data + 0x08));
+ dmi_voltage_probe_resolution(sect_n, WORD(data + 0x0A));
+ dmi_voltage_probe_value(sect_n, "Tolerance", WORD(data + 0x0C));
- _val = dmi_32bit_memory_error_address(DWORD(data+0x0F));
- PyDict_SetItemString(caseData, "Device Address", _val);
- Py_DECREF(_val);
+ dmi_probe_accuracy(sect_n, WORD(data + 0x0E));
- _val = dmi_32bit_memory_error_address(DWORD(data+0x13));
- PyDict_SetItemString(caseData, "Resolution", _val);
- Py_DECREF(_val);
- break;
-
- case 19: /* 3.3.20 Memory Array Mapped Address */
-
- if(h->length<0x0F) break;
- _val = PyString_FromFormat("0x%08x%03x", DWORD(data+0x04)>>2, (DWORD(data+0x04)&0x3)<<10);
- PyDict_SetItemString(caseData, "Starting Address", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%08x%03x", DWORD(data+0x08)>>2, ((DWORD(data+0x08)&0x3)<<10)+0x3FF);
- PyDict_SetItemString(caseData, "Ending Address", _val);
- Py_DECREF(_val);
-
- _val = dmi_mapped_address_size(DWORD(data+0x08)-DWORD(data+0x04)+1);
- PyDict_SetItemString(caseData, "Range Size", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%04x", WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Physical Array Handle", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%i", data[0x0F]);
- PyDict_SetItemString(caseData, "Partition Width", _val);
- Py_DECREF(_val);
- break;
-
- case 20: /* 3.3.21 Memory Device Mapped Address */
-
- if(h->length<0x13) break;
- _val = PyString_FromFormat("0x%08x%03x", DWORD(data+0x04)>>2, (DWORD(data+0x04)&0x3)<<10);
- PyDict_SetItemString(caseData, "Starting Address", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%08x%03x", DWORD(data+0x08)>>2, ((DWORD(data+0x08)&0x3)<<10)+0x3FF);
- PyDict_SetItemString(caseData, "Ending Address", _val);
- Py_DECREF(_val);
-
- _val = dmi_mapped_address_size(DWORD(data+0x08)-DWORD(data+0x04)+1);
- PyDict_SetItemString(caseData, "Range Size", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%04x", WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Physical Device Handle", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%04x", WORD(data+0x0E));
- PyDict_SetItemString(caseData, "Memory Array Mapped Address Handle", _val);
- Py_DECREF(_val);
-
- _val = dmi_mapped_address_row_position(data[0x10]);
- PyDict_SetItemString(caseData, "Partition Row Position", _val);
- Py_DECREF(_val);
-
- _val = dmi_mapped_address_interleave_position(data[0x11]);
- PyDict_SetItemString(caseData, ">>>", _val);
- Py_DECREF(_val);
-
- _val = dmi_mapped_address_interleaved_data_depth(data[0x12]);
- PyDict_SetItemString(caseData, ">>>", _val);
- Py_DECREF(_val);
- break;
-
- case 21: /* 3.3.22 Built-in Pointing Device */
-
- if(h->length<0x07) break;
- _val = dmi_pointing_device_type(data[0x04]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
-
- _val = dmi_pointing_device_interface(data[0x05]);
- PyDict_SetItemString(caseData, "Interface", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%i", data[0x06]);
- PyDict_SetItemString(caseData, "Buttons", _val);
- Py_DECREF(_val);
- break;
-
- case 22: /* 3.3.23 Portable Battery */
-
- if(h->length<0x10) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Location", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x05]);
- PyDict_SetItemString(caseData, "Manufacturer", _val);
- Py_DECREF(_val);
-
- if(data[0x06] || h->length<0x1A) {
- _val = dmi_string_py(h, data[0x06]);
- PyDict_SetItemString(caseData, "Manufacture Date", _val);
- Py_DECREF(_val);
- }
-
- if(data[0x07] || h->length<0x1A) {
- _val = dmi_string_py(h, data[0x07]);
- PyDict_SetItemString(caseData, "Serial Number", _val);
- Py_DECREF(_val);
- }
-
- _val = dmi_string_py(h, data[0x08]);
- PyDict_SetItemString(caseData, "Name", _val);
- Py_DECREF(_val);
-
- if(data[0x09]!=0x02 || h->length<0x1A) {
- _val = dmi_battery_chemistry(data[0x09]);
- PyDict_SetItemString(caseData, "Chemistry", _val);
- Py_DECREF(_val);
- }
- _val = (h->length<0x1A)?dmi_battery_capacity(WORD(data+0x0A), 1):dmi_battery_capacity(WORD(data+0x0A), data[0x15]);
- PyDict_SetItemString(caseData, "Design Capacity", _val);
- Py_DECREF(_val);
-
- _val = dmi_battery_voltage(WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Design Voltage", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x0E]);
- PyDict_SetItemString(caseData, "SBDS Version", _val);
- Py_DECREF(_val);
-
- _val = dmi_battery_maximum_error(data[0x0F]);
- PyDict_SetItemString(caseData, "Maximum Error", _val);
- Py_DECREF(_val);
-
- if(h->length<0x1A) break;
- if(data[0x07]==0) {
- _val = PyString_FromFormat("%04x", WORD(data+0x10));
- PyDict_SetItemString(caseData, "SBDS Serial Number", _val);
- Py_DECREF(_val);
- }
- if(data[0x06]==0) {
- _val = PyString_FromFormat("%i-%02u-%02u", 1980+(WORD(data+0x12)>>9), (WORD(data+0x12)>>5)&0x0F, WORD(data+0x12)&0x1F);
- PyDict_SetItemString(caseData, "SBDS Manufacture Date", _val);
- Py_DECREF(_val);
- }
- if(data[0x09]==0x02) {
- _val = dmi_string_py(h, data[0x14]);
- PyDict_SetItemString(caseData, "SBDS Chemistry", _val);
- Py_DECREF(_val);
- }
-
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x16));
- PyDict_SetItemString(caseData, "OEM-specific Information", _val);
- Py_DECREF(_val);
- break;
-
- case 23: /* 3.3.24 System Reset */
-
- if(h->length<0x0D) break;
- _val = PyString_FromFormat("%s", data[0x04]&(1<<0)?"Enabled":"Disabled");
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%s", data[0x04]&(1<<5)?"Present":"Not Present");
- PyDict_SetItemString(caseData, "Watchdog Timer", _val);
- Py_DECREF(_val);
-
- if(!(data[0x04]&(1<<5))) break;
- _val = dmi_system_reset_boot_option((data[0x04]>>1)&0x3);
- PyDict_SetItemString(caseData, "Boot Option", _val);
- Py_DECREF(_val);
-
- _val = dmi_system_reset_boot_option((data[0x04]>>3)&0x3);
- PyDict_SetItemString(caseData, "Boot Option On Limit", _val);
- Py_DECREF(_val);
-
- _val = dmi_system_reset_count(WORD(data+0x05));
- PyDict_SetItemString(caseData, "Reset Count", _val);
- Py_DECREF(_val);
-
- _val = dmi_system_reset_count(WORD(data+0x07));
- PyDict_SetItemString(caseData, "Reset Limit", _val);
- Py_DECREF(_val);
-
- _val = dmi_system_reset_timer(WORD(data+0x09));
- PyDict_SetItemString(caseData, "Timer Interval", _val);
- Py_DECREF(_val);
-
- _val = dmi_system_reset_timer(WORD(data+0x0B));
- PyDict_SetItemString(caseData, "Timeout", _val);
- Py_DECREF(_val);
-
- break;
-
- case 24: /* 3.3.25 Hardware Security */
-
- if(h->length<0x05) break;
- _val = dmi_hardware_security_status(data[0x04]>>6);
- PyDict_SetItemString(caseData, "Power-On Password Status", _val);
- Py_DECREF(_val);
-
- _val = dmi_hardware_security_status((data[0x04]>>4)&0x3);
- PyDict_SetItemString(caseData, "Keyboard Password Status", _val);
- Py_DECREF(_val);
-
- _val = dmi_hardware_security_status((data[0x04]>>2)&0x3);
- PyDict_SetItemString(caseData, "Administrator Password Status", _val);
- Py_DECREF(_val);
-
- _val = dmi_hardware_security_status(data[0x04]&0x3);
- PyDict_SetItemString(caseData, "Front Panel Reset Status", _val);
- Py_DECREF(_val);
-
- break;
-
- case 25: /* 3.3.26 System Power Controls */
-
- if(h->length<0x09) break;
- _val = dmi_power_controls_power_on(data+0x04);
- PyDict_SetItemString(caseData, "Next Scheduled Power-on", _val);
- Py_DECREF(_val);
-
- break;
-
- case 26: /* 3.3.27 Voltage Probe */
-
- if(h->length<0x14) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Description", _val);
- Py_DECREF(_val);
-
- _val = dmi_voltage_probe_location(data[0x05]&0x1f);
- PyDict_SetItemString(caseData, "Location", _val);
- Py_DECREF(_val);
-
- _val = dmi_probe_status(data[0x05]>>5);
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "OEMinformation", "0x%08x", DWORD(data + 0x10));
- _val = dmi_voltage_probe_value(WORD(data+0x06));
- PyDict_SetItemString(caseData, "Maximum Value", _val);
- Py_DECREF(_val);
+ if(h->length < 0x16) {
+ break;
+ }
- _val = dmi_voltage_probe_value(WORD(data+0x08));
- PyDict_SetItemString(caseData, "Minimum Value", _val);
- Py_DECREF(_val);
+ dmi_voltage_probe_value(sect_n, "NominalValue", WORD(data + 0x14));
+ break;
- _val = dmi_voltage_probe_resolution(WORD(data+0x0A));
- PyDict_SetItemString(caseData, "Resolution", _val);
- Py_DECREF(_val);
+ case 27: /* 3.3.28 Cooling Device */
+ if(h->length < 0x0C) {
+ break;
+ }
- _val = dmi_voltage_probe_value(WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Tolerance", _val);
- Py_DECREF(_val);
+ if(WORD(data + 0x04) != 0xFFFF) {
+ dmixml_AddTextContent(sect_n, "TemperatureProbeHandle", "0x%04x", WORD(data + 0x04));
+ }
- _val = dmi_probe_accuracy(WORD(data+0x0E));
- PyDict_SetItemString(caseData, "Accuracy", _val);
- Py_DECREF(_val);
+ dmi_cooling_device_type(sect_n, data[0x06] & 0x1f);
+ dmi_probe_status(sect_n, data[0x06] >> 5);
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x10));
- PyDict_SetItemString(caseData, "OEM-specific Information", _val);
- Py_DECREF(_val);
+ if(data[0x07] != 0x00) {
+ dmixml_AddTextChild(sect_n, "UnitGroup", "%i", data[0x07]);
+ }
- if(h->length<0x16) break;
- _val = dmi_voltage_probe_value(WORD(data+0x14));
- PyDict_SetItemString(caseData, "Nominal Value", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "OEMinformation", "0x%08x", DWORD(data + 0x08));
- break;
+ if(h->length < 0x0E) {
+ break;
+ }
- case 27: /* 3.3.28 Cooling Device */
+ dmi_cooling_device_speed(sect_n, WORD(data + 0x0C));
+ break;
- if(h->length<0x0C) break;
- if(WORD(data+0x04)!=0xFFFF) {
- _val = PyString_FromFormat("0x%04x", WORD(data+0x04));
- PyDict_SetItemString(caseData, "Temperature Probe Handle", _val);
- Py_DECREF(_val);
- }
+ case 28: /* 3.3.29 Temperature Probe */
+ dmixml_AddAttribute(sect_n, "probetype", "Temperature");
- _val = dmi_cooling_device_type(data[0x06]&0x1f);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
+ if(h->length < 0x14) {
+ break;
+ }
- _val = dmi_probe_status(data[0x06]>>5);
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "Description", "%s", dmi_string(h, data[0x04]));
+ dmi_temperature_probe_location(sect_n,data[0x05] & 0x1F);
+ dmi_probe_status(sect_n, data[0x05] >> 5);
- if(data[0x07]!=0x00) {
- _val = PyString_FromFormat("%i", data[0x07]);
- PyDict_SetItemString(caseData, "Cooling Unit Group", _val);
- Py_DECREF(_val);
- }
+ dmi_temperature_probe_value(sect_n, "MaxValue", WORD(data + 0x06));
+ dmi_temperature_probe_value(sect_n, "MinValue", WORD(data + 0x08));
+ dmi_temperature_probe_resolution(sect_n, WORD(data + 0x0A));
+ dmi_temperature_probe_value(sect_n, "Tolerance", WORD(data + 0x0C));
+ dmi_probe_accuracy(sect_n, WORD(data + 0x0E));
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x08));
- PyDict_SetItemString(caseData, "OEM-specific Information", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "OEMinformation", "0x%08x", DWORD(data + 0x10));
- if(h->length<0x0E) break;
- _val = dmi_cooling_device_speed(WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Nominal Speed", _val);
- Py_DECREF(_val);
+ if(h->length < 0x16) {
+ break;
+ }
- break;
+ dmi_temperature_probe_value(sect_n, "NominalValue", WORD(data + 0x14));
+ break;
- case 28: /* 3.3.29 Temperature Probe */
+ case 29: /* 3.3.30 Electrical Current Probe */
+ dmixml_AddAttribute(sect_n, "probetype", "Electrical Current");
- if(h->length<0x14) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Description", _val);
- Py_DECREF(_val);
+ if(h->length < 0x14) {
+ break;
+ }
- _val = dmi_temperature_probe_location(data[0x05]&0x1F);
- PyDict_SetItemString(caseData, "Location", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "Description", dmi_string(h, data[0x04]));
+ dmi_voltage_probe_location(sect_n, data[5] & 0x1F);
+ dmi_probe_status(sect_n, data[0x05] >> 5);
- _val = dmi_probe_status(data[0x05]>>5);
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
+ dmi_current_probe_value(sect_n, "MaxValue", WORD(data + 0x06));
+ dmi_current_probe_value(sect_n, "MinValue", WORD(data + 0x08));
+ dmi_current_probe_resolution(sect_n, WORD(data + 0x0A));
+ dmi_current_probe_value(sect_n, "Tolerance", WORD(data + 0x0C));
- _val = dmi_temperature_probe_value(WORD(data+0x06));
- PyDict_SetItemString(caseData, "Maximum Value", _val);
- Py_DECREF(_val);
+ dmi_probe_accuracy(sect_n, WORD(data + 0x0E));
- _val = dmi_temperature_probe_value(WORD(data+0x08));
- PyDict_SetItemString(caseData, "Minimum Value", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "OEMinformation", "0x%08x", DWORD(data + 0x10));
- _val = dmi_temperature_probe_resolution(WORD(data+0x0A));
- PyDict_SetItemString(caseData, "Resolution", _val);
- Py_DECREF(_val);
+ if(h->length < 0x16) {
+ break;
+ }
- _val = dmi_temperature_probe_value(WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Tolerance", _val);
- Py_DECREF(_val);
+ dmi_current_probe_value(sect_n, "NominalValue", WORD(data + 0x14));
+ break;
- _val = dmi_probe_accuracy(WORD(data+0x0E));
- PyDict_SetItemString(caseData, "Accuracy", _val);
- Py_DECREF(_val);
+ case 30: /* 3.3.31 Out-of-band Remote Access */
+ if(h->length < 0x06) {
+ break;
+ }
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x10));
- PyDict_SetItemString(caseData, "OEM-specific Information", _val);
- Py_DECREF(_val);
+ dmixml_AddTextChild(sect_n, "ManufacturerName", "%s", dmi_string(h, data[0x04]));
+ dmixml_AddAttribute(sect_n, "InboundConnectionEnabled", "%i", data[0x05] & (1 << 0) ? 1 : 0);
+ dmixml_AddAttribute(sect_n, "OutboundConnectionEnabled", "%i", data[0x05] & (1 << 1) ? 1 : 0);
+ break;
- if(h->length<0x16) break;
- _val = dmi_temperature_probe_value(WORD(data+0x14));
- PyDict_SetItemString(caseData, "Nominal Value", _val);
- Py_DECREF(_val);
+ case 31: /* 3.3.32 Boot Integrity Services Entry Point */
+ dmixml_AddAttribute(sect_n, "NOT_IMPLEMENTED", "1");
+ break;
- break;
+ case 32: /* 3.3.33 System Boot Information */
+ if(h->length < 0x0B) {
+ break;
+ }
- case 29: /* 3.3.30 Electrical Current Probe */
+ dmi_system_boot_status(sect_n, data[0x0A]);
+ break;
+
+ case 34: /* 3.3.35 Management Device */
+ dmixml_AddAttribute(sect_n, "mgmtype", "");
+
+ if(h->length < 0x0B) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "Description", "%s", dmi_string(h, data[0x04]));
+ dmi_management_device_type(sect_n, data[0x05]);
+ dmixml_AddTextChild(sect_n, "Address", "0x%08x", DWORD(data + 0x06));
+ dmi_management_device_address_type(sect_n, data[0x0A]);
+ break;
- if(h->length<0x14) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Description", _val);
- Py_DECREF(_val);
+ case 35: /* 3.3.36 Management Device Component */
+ dmixml_AddAttribute(sect_n, "mgmtype", "Component");
- _val = dmi_voltage_probe_location(data[5]&0x1F);
- PyDict_SetItemString(caseData, "Location", _val);
- Py_DECREF(_val);
+ if(h->length < 0x0B) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "Description", dmi_string(h, data[0x04]));
+ dmixml_AddTextChild(sect_n, "ManagementDeviceHandle", "0x%04x", WORD(data + 0x05));
+ dmixml_AddTextChild(sect_n, "ComponentHandle", "0x%04x", WORD(data + 0x07));
+
+ if(WORD(data + 0x09) != 0xFFFF) {
+ dmixml_AddTextChild(sect_n, "ThresholdHandle", "0x%04x", WORD(data + 0x09));
+ }
+ break;
+
+ case 36: /* 3.3.37 Management Device Threshold Data */
+ dmixml_AddAttribute(sect_n, "mgmtype", "Threshold Data");
+
+ if(h->length < 0x10) {
+ break;
+ }
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Thresholds", NULL);
+ assert( sub_n != NULL );
+ dmixml_AddAttribute(sub_n, "mode", "non-critical");
+
+ if(WORD(data + 0x04) != 0x8000) {
+ dmixml_AddAttribute(sub_n, "Lower", "%d", (i16) WORD(data + 0x04));
+ }
+ if(WORD(data + 0x06) != 0x8000) {
+ dmixml_AddAttribute(sub_n, "Upper", "%d", (i16) WORD(data + 0x06));
+ }
+ sub_n = NULL;
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Thresholds", NULL);
+ assert( sub_n != NULL );
+ dmixml_AddAttribute(sub_n, "mode", "critical");
+
+ if(WORD(data + 0x08) != 0x8000) {
+ dmixml_AddAttribute(sub_n, "Lower", "%d", (i16) WORD(data + 0x08));
+ }
+ if(WORD(data + 0x0A) != 0x8000) {
+ dmixml_AddAttribute(sub_n, "Upper", "%d", (i16) WORD(data + 0x0A));
+
+ }
+ sub_n = NULL;
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Thresholds", NULL);
+ assert( sub_n != NULL );
+ dmixml_AddAttribute(sub_n, "mode", "non-recoverable");
+
+ if(WORD(data + 0x0C) != 0x8000) {
+ dmixml_AddAttribute(sub_n, "Lower", "%d", (i16) WORD(data + 0x0C));
+ }
+ if(WORD(data + 0x0E) != 0x8000) {
+ dmixml_AddAttribute(sub_n, "Upper", "%d", (i16) WORD(data + 0x0E));
+ }
+ sub_n = NULL;
+ break;
+
+ case 37: /* 3.3.38 Memory Channel */
+ if(h->length < 0x07) {
+ break;
+ }
+
+ dmi_memory_channel_type(sect_n, data[0x04]);
+ dmixml_AddTextChild(sect_n, "MaxLoad", "%i", data[0x05]);
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Devices", NULL);
+ assert( sub_n != NULL );
+ dmixml_AddAttribute(sub_n, "devices", "%i", data[0x06]);
+
+ if(h->length < 0x07 + 3 * data[0x06]) {
+ sub_n = NULL;
+ break;
+ }
+
+ dmi_memory_channel_devices(sub_n, data[0x06], data + 0x07);
+ sub_n = NULL;
+ break;
+
+ case 38: /* 3.3.39 IPMI Device Information */
+ /*
+ * We use the word "Version" instead of "Revision", conforming to
+ * the IPMI specification.
+ */
+ if(h->length < 0x10) {
+ break;
+ }
+
+ dmi_ipmi_interface_type(sect_n, data[0x04]);
+
+ dmixml_AddAttribute(sect_n, "spec_version", "%i.%i", data[0x05] >> 4, data[0x05] & 0x0F);
+ dmixml_AddAttribute(sect_n, "I2CslaveAddr", "0x%02x", data[0x06] >> 1);
+
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "NVstorageDevice", NULL);
+ assert( sub_n != NULL );
+
+ if(data[0x07] != 0xFF) {
+ dmixml_AddAttribute(sub_n, "Address", "%i", data[0x07]);
+ } else {
+ dmixml_AddAttribute(sub_n, "NotPresent", "1");
+ }
+ sub_n = NULL;
+
+ dmi_ipmi_base_address(sect_n, data[0x04], data + 0x08,
+ h->length < 0x12 ? 0 : (data[0x10] >> 5) & 1);
+
+ if(h->length < 0x12) {
+ break;
+ }
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Interrupt", NULL);
+ assert( sub_n != NULL );
+
+ if(data[0x04] != 0x04) {
+ dmi_ipmi_register_spacing(sect_n, data[0x10] >> 6);
+
+ if(data[0x10] & (1 << 3)) {
+ sub2_n = dmixml_AddTextChild(sub_n, "Polarity", "%s",
+ data[0x10] & (1 << 1) ? "Active High" : "Active Low");
+ assert( sub2_n != NULL );
+ dmixml_AddAttribute(sub2_n, "active_high", "%i", data[0x10] & (1 << 1) ? 1: 0);
+ sub2_n = NULL;
+
+ dmixml_AddTextChild(sub_n, "TriggerMode", "%s",
+ data[0x10] & (1 << 0) ? "Level" : "Edge");
+ }
+ }
+ if(data[0x11] != 0x00) {
+ dmixml_AddTextChild(sub_n, "InterruptNumber", "%x", data[0x11]);
+ }
+ sub_n = NULL;
+ break;
+
+ case 39: /* 3.3.40 System Power Supply */
+ if(h->length < 0x10) {
+ break;
+ }
+
+ if(data[0x04] != 0x00) {
+ dmixml_AddAttribute(sect_n, "UnitGroup", "%i", data[0x04]);
+ }
+
+ dmixml_AddTextChild(sect_n, "Location", "%s", dmi_string(h, data[0x05]));
+ dmixml_AddTextChild(sect_n, "Name", "%s", dmi_string(h, data[0x06]));
+ dmixml_AddTextChild(sect_n, "Manufacturer", "%s", dmi_string(h, data[0x07]));
+ dmixml_AddTextChild(sect_n, "SerialNumber", "%s", dmi_string(h, data[0x08]));
+ dmixml_AddTextChild(sect_n, "AssetTag", "%s", dmi_string(h, data[0x09]));
+ dmixml_AddTextChild(sect_n, "ModelPartNumber", "%s", dmi_string(h, data[0x0A]));
+ dmixml_AddTextChild(sect_n, "Revision", "%s", dmi_string(h, data[0x0B]));
+
+ dmi_power_supply_power(sect_n, WORD(data + 0x0C));
+
+ if(WORD(data + 0x0E) & (1 << 1)) {
+ dmi_power_supply_status(sect_n, (WORD(data + 0x0E) >> 7) & 0x07);
+ } else {
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Status", NULL);
+ assert( sub_n != NULL );
+ dmixml_AddAttribute(sub_n, "present", "0");
+ sub_n = NULL;
+ }
+
+ dmi_power_supply_type(sect_n, (WORD(data + 0x0E) >> 10) & 0x0F);
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "Input", NULL);
+ assert( sub_n != NULL );
+
+ dmi_power_supply_range_switching(sub_n, (WORD(data + 0x0E) >> 3) & 0x0F);
+
+ dmixml_AddAttribute(sub_n, "Plugged", "%i", WORD(data + 0x0E) & (1 << 2) ? 0 : 1);
+ dmixml_AddAttribute(sub_n, "HotReplacable", "%i", WORD(data + 0x0E) & (1 << 0) ? 1 : 0);
+
+ if(h->length < 0x16) {
+ sub_n = NULL;
+ break;
+ }
+
+ if(WORD(data + 0x10) != 0xFFFF) {
+ dmixml_AddTextChild(sub_n, "ProbeHandle", "0x%04x", WORD(data + 0x10));
+ }
+
+ if(WORD(data + 0x12) != 0xFFFF) {
+ dmixml_AddTextChild(sect_n, "CoolingDeviceHandle", "0x%04x", WORD(data + 0x12));
+ }
- _val = dmi_probe_status(data[0x05]>>5);
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
+ if(WORD(data + 0x14) != 0xFFFF) {
+ dmixml_AddTextChild(sub_n, "CurrentProbeHandle", "0x%04x", WORD(data + 0x14));
+ }
- _val = dmi_current_probe_value(WORD(data+0x06));
- PyDict_SetItemString(caseData, "Maximum Value", _val);
- Py_DECREF(_val);
+ sub_n = NULL;
+ break;
- _val = dmi_current_probe_value(WORD(data+0x08));
- PyDict_SetItemString(caseData, "Minimum Value", _val);
- Py_DECREF(_val);
+ case 40: /* 3.3.41 Additional Information */
+ dmixml_AddAttribute(sect_n, "subtype", "AdditionalInformation");
+ dmixml_AddAttribute(sect_n, "dmispec", "3.3.41");
+
+ if(h->length < 0x0B) {
+ break;
+ }
+
+ dmi_additional_info(sect_n, h);
+ break;
+
+ case 41: /* 3.3.42 Onboard Device Extended Information */
+ dmixml_AddAttribute(sect_n, "subtype", "OnboardDeviceExtendedInformation");
+ dmixml_AddAttribute(sect_n, "dmispec", "3.3.42");
+
+ if(h->length < 0x0B) {
+ break;
+ }
+
+ dmixml_AddTextChild(sect_n, "ReferenceDesignation", "%s", dmi_string(h, data[0x04]));
+
+ sub_n = xmlNewChild(sect_n, NULL, (xmlChar *) "OnboardDevice", NULL);
+ dmi_on_board_devices_type(sub_n, data[0x05] & 0x7F);
+
+ dmixml_AddAttribute(sub_n, "Enabled", "%i", data[0x05] & 0x80 ? 1 : 0);
+ dmixml_AddAttribute(sub_n, "TypeInstance", "%ld", data[0x06]);
+ dmi_slot_segment_bus_func(sub_n, WORD(data + 0x07), data[0x09], data[0x0A]);
+ sub_n = NULL;
+ break;
+
+ case 126: /* 3.3.43 Inactive */
+ case 127: /* 3.3.44 End Of Table */
+ break;
+
+ default:
+ if(dmi_decode_oem(h))
+ break;
- _val = dmi_current_probe_resolution(WORD(data+0x0A));
- PyDict_SetItemString(caseData, "Resolution", _val);
- Py_DECREF(_val);
+ sect_n = xmlNewChild(sect_n, NULL, (xmlChar *) "DMIdump", NULL);
+ assert( sect_n != NULL );
- _val = dmi_current_probe_value(WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Tolerance", _val);
- Py_DECREF(_val);
+ dmixml_AddAttribute(sect_n, "Type", "%i", h->type);
+ dmixml_AddAttribute(sect_n, "InfoType", "%s", h->type >= 128 ? "OEM-specific" : "Unknown");
- _val = dmi_probe_accuracy(WORD(data+0x0E));
- PyDict_SetItemString(caseData, "Accuracy", _val);
- Py_DECREF(_val);
+ dmi_dump(sect_n, h);
+ break;
+ }
+ return sect_n;
+}
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x10));
- PyDict_SetItemString(caseData, "OEM-specific Information", _val);
- Py_DECREF(_val);
+void to_dmi_header(struct dmi_header *h, u8 * data)
+{
+ h->type = data[0];
+ h->length = data[1];
+ h->handle = WORD(data + 2);
+ h->data = data;
+}
- if(h->length<0x16) break;
- _val = dmi_current_probe_value(WORD(data+0x14));
- PyDict_SetItemString(caseData, "Nominal Value", _val);
- Py_DECREF(_val);
- break;
+dmi_codes_major *find_dmiMajor(const struct dmi_header *h)
+{
+ int i = 0;
+
+ for( i = 0; dmiCodesMajor[i].id != NULL; i++ ) {
+ if( h->type == dmiCodesMajor[i].code ) {
+ return (dmi_codes_major *)&dmiCodesMajor[i];
+ }
+ }
+ return NULL;
+}
- case 30: /* 3.3.31 Out-of-band Remote Access */
+static void dmi_table(int type, u32 base, u16 len, u16 num, u16 ver, const char *devmem, xmlNode *xmlnode)
+{
+ u8 *buf;
+ u8 *data;
+ int i = 0;
+ int decoding_done = 0;
- if(h->length<0x06) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Manufacturer Name", _val);
- Py_DECREF(_val);
+ if( type == -1 ) {
+ xmlNode *info_n = NULL;
- _val = data[0x05]&(1<<0)?Py_True:Py_False;
- PyDict_SetItemString(caseData, "Inbound Connection Enabled", _val);
- Py_DECREF(_val);
+ info_n = dmixml_AddTextChild(xmlnode, "DMIinfo", "%i structures occupying %i bytes", num, len);
+ dmixml_AddAttribute(info_n, "dmi_structures", "%i", num);
+ dmixml_AddAttribute(info_n, "dmi_size", "%i", len);
- _val = data[0x05]&(1<<1)?Py_True:Py_False;
- PyDict_SetItemString(caseData, "Outbound Connection Enabled", _val);
- Py_DECREF(_val);
- break;
+ /* TODO DUMP
+ * if (!(opt->flags & FLAG_FROM_DUMP))
+ * dmixml_AddAttribute(info_n, "dmi_table_base", "0x%08x", base);
+ */
- case 31: /* 3.3.32 Boot Integrity Services Entry Point */
+ dmixml_AddAttribute(info_n, "dmi_table_base", "0x%08x", base);
+ info_n = NULL;
+ }
- break;
+ if((buf = mem_chunk(base, len, devmem)) == NULL) {
+ fprintf(stderr, "Table is unreachable, sorry."
+#ifndef USE_MMAP
+ "Try compiling dmidecode with -DUSE_MMAP.";
+#endif
+ "\n");
+ return;
+ }
- case 32: /* 3.3.33 System Boot Information */
+ data = buf;
+ while(i < num && data + 4 <= buf + len) { /* 4 is the length of an SMBIOS structure header */
+
+ u8 *next;
+ struct dmi_header h;
+
+ to_dmi_header(&h, data);
+
+ /*
+ ** If a short entry is found (less than 4 bytes), not only it
+ ** is invalid, but we cannot reliably locate the next entry.
+ ** Better stop at this point, and let the user know his/her
+ ** table is broken.
+ */
+ if(h.length < 4) {
+ fprintf(stderr, "Invalid entry length (%i). DMI table is broken! Stop.",
+ (unsigned int)h.length);
+ break;
+ }
+
+ /* In quiet mode (FLAG_QUIET - removed for python-dmidecode all together),
+ * stop decoding at end of table marker
+ */
+
+ /* assign vendor for vendor-specific decodes later */
+ if(h.type == 0 && h.length >= 5) {
+ dmi_set_vendor(dmi_string(&h, data[0x04]));
+ }
+
+ /* look for the next handle */
+ next = data + h.length;
+ while(next - buf + 1 < len && (next[0] != 0 || next[1] != 0)) {
+ next++;
+ }
+ next += 2;
+
+ xmlNode *handle_n = NULL;
+ if( h.type == type ) {
+ if(next - buf <= len) {
+ dmi_codes_major *dmiMajor = NULL;
+ /* TODO: ...
+ * if(opt->flags & FLAG_DUMP) {
+ * PyDict_SetItem(hDict, PyString_FromString("lookup"), dmi_dump(&h));
+ * } */
+
+ dmiMajor = find_dmiMajor(&h);
+ if( dmiMajor != NULL ) {
+ handle_n = dmi_decode(xmlnode, dmiMajor, &h, ver);
+ } else {
+ handle_n = xmlNewChild(xmlnode, NULL, (xmlChar *) "DMImessage", NULL);
+ assert( handle_n != NULL );
+ dmixml_AddTextContent(handle_n, "DMI/SMBIOS type 0x%02X is not supported "
+ "by dmidecode", h.type);
+ dmixml_AddAttribute(handle_n, "type", "%i", h.type);
+ dmixml_AddAttribute(handle_n, "unsupported", "1");
+ }
+ } else {
+ handle_n = xmlNewChild(xmlnode, NULL, (xmlChar *) "DMIerror", NULL);
+ assert( handle_n != NULL );
+ dmixml_AddTextContent(handle_n, "Data is truncated");
+ dmixml_AddAttribute(handle_n, "type", "%i", h.type);
+ dmixml_AddAttribute(handle_n, "truncated", "1");
+ }
+ dmixml_AddAttribute(handle_n, "handle", "0x%04x", h.handle);
+ dmixml_AddAttribute(handle_n, "size", "%d", h.length);
+ decoding_done = 1;
+ }
+ data = next;
+ i++;
+ }
- if(h->length<0x0B) break;
- _val = dmi_system_boot_status(data[0x0A]);
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
+ if( decoding_done == 0 ) {
+ xmlNode *handle_n = xmlNewChild(xmlnode, NULL, (xmlChar *) "DMImessage", NULL);
+ assert( handle_n != NULL );
+ dmixml_AddTextContent(handle_n, "DMI/SMBIOS type 0x%02X is not found on this hardware",
+ type);
+ dmixml_AddAttribute(handle_n, "type", "%i", type);
+ dmixml_AddAttribute(handle_n, "notfound", "1");
+ }
- break;
+ if(i != num)
+ fprintf(stderr, "Wrong DMI structures count: %d announced, only %d decoded.\n", num,
+ i);
+ if(data - buf != len)
+ fprintf(stderr,
+ "Wrong DMI structures length: %d bytes announced, structures occupy %d bytes.\n",
+ len, (unsigned int)(data - buf));
- case 33: /* 3.3.34 64-bit Memory Error Information */
- if(h->length<0x1F) break;
-
- _val = dmi_memory_error_type(data[0x04]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_error_granularity(data[0x05]);
- PyDict_SetItemString(caseData, "Granularity", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_error_operation(data[0x06]);
- PyDict_SetItemString(caseData, "Operation", _val);
- Py_DECREF(_val);
-
- _val = dmi_memory_error_syndrome(DWORD(data+0x07));
- PyDict_SetItemString(caseData, "Vendor Syndrome", _val);
- Py_DECREF(_val);
-
- _val = dmi_64bit_memory_error_address(QWORD(data+0x0B));
- PyDict_SetItemString(caseData, "Memory Array Address", _val);
- Py_DECREF(_val);
-
- _val = dmi_64bit_memory_error_address(QWORD(data+0x13));
- PyDict_SetItemString(caseData, "Device Address", _val);
- Py_DECREF(_val);
-
- _val = dmi_32bit_memory_error_address(DWORD(data+0x1B));
- PyDict_SetItemString(caseData, "Resolution", _val);
- Py_DECREF(_val);
-
- break;
-
- case 34: /* 3.3.35 Management Device */
-
- if(h->length<0x0B) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Description", _val);
- Py_DECREF(_val);
-
- _val = dmi_management_device_type(data[0x05]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%08x", DWORD(data+0x06));
- PyDict_SetItemString(caseData, "Address", _val);
- Py_DECREF(_val);
-
- _val = dmi_management_device_address_type(data[0x0A]);
- PyDict_SetItemString(caseData, "Address Type", _val);
- Py_DECREF(_val);
-
- break;
-
- case 35: /* 3.3.36 Management Device Component */
-
- if(h->length<0x0B) break;
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(caseData, "Description", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%04x", WORD(data+0x05));
- PyDict_SetItemString(caseData, "Management Device Handle", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%04x", WORD(data+0x07));
- PyDict_SetItemString(caseData, "Component Handle", _val);
- Py_DECREF(_val);
-
- if(WORD(data+0x09)!=0xFFFF) {
- _val = PyString_FromFormat("0x%04x", WORD(data+0x09));
- PyDict_SetItemString(caseData, "Threshold Handle", _val);
- Py_DECREF(_val);
- }
-
- break;
-
- case 36: /* 3.3.37 Management Device Threshold Data */
-
- if(h->length<0x10) break;
- if(WORD(data+0x04)!=0x8000) {
- _val = PyString_FromFormat("%d", (i16)WORD(data+0x04));
- PyDict_SetItemString(caseData, "Lower Non-critical Threshold", _val);
- Py_DECREF(_val);
- }
- if(WORD(data+0x06)!=0x8000) {
- _val = PyString_FromFormat("%d", (i16)WORD(data+0x06));
- PyDict_SetItemString(caseData, "Upper Non-critical Threshold", _val);
- Py_DECREF(_val);
- }
- if(WORD(data+0x08)!=0x8000) {
- _val = PyString_FromFormat("%d", (i16)WORD(data+0x08));
- PyDict_SetItemString(caseData, "Lower Critical Threshold", _val);
- Py_DECREF(_val);
- }
- if(WORD(data+0x0A)!=0x8000) {
- _val = PyString_FromFormat("%d", (i16)WORD(data+0x0A));
- PyDict_SetItemString(caseData, "Upper Critical Threshold", _val);
- Py_DECREF(_val);
- }
- if(WORD(data+0x0C)!=0x8000) {
- _val = PyString_FromFormat("%d", (i16)WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Lower Non-recoverable Threshold", _val);
- Py_DECREF(_val);
- }
- if(WORD(data+0x0E)!=0x8000) {
- _val = PyString_FromFormat("%d", (i16)WORD(data+0x0E));
- PyDict_SetItemString(caseData, "Upper Non-recoverable Threshold", _val);
- Py_DECREF(_val);
- }
-
- break;
-
- case 37: /* 3.3.38 Memory Channel */
-
- if(h->length<0x07) break;
- _val = dmi_memory_channel_type(data[0x04]);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%i", data[0x05]);
- PyDict_SetItemString(caseData, "Maximal Load", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%i", data[0x06]);
- PyDict_SetItemString(caseData, "Devices", _val);
- Py_DECREF(_val);
-
- if(h->length<0x07+3*data[0x06]) break;
- _val = dmi_memory_channel_devices(data[0x06], data+0x07);
- PyDict_SetItemString(caseData, ">>>", _val);
- Py_DECREF(_val);
-
- break;
-
- case 38: /* 3.3.39 IPMI Device Information */
- /*
- * We use the word "Version" instead of "Revision", conforming to
- * the IPMI specification.
- */
-
- if(h->length<0x10) break;
- _val = dmi_ipmi_interface_type(data[0x04]);
- PyDict_SetItemString(caseData, "Interface Type", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%i.%i", data[0x05]>>4, data[0x05]&0x0F);
- PyDict_SetItemString(caseData, "Specification Version", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("0x%02x", data[0x06]>>1);
- PyDict_SetItemString(caseData, "I2C Slave Address", _val);
- Py_DECREF(_val);
-
- if(data[0x07]!=0xFF) {
- _val = PyString_FromFormat("%i", data[0x07]);
- PyDict_SetItemString(caseData, "NV Storage Device Address", _val);
- Py_DECREF(_val);
- } else {
- _val = Py_None;
- PyDict_SetItemString(caseData, "NV Storage Device: Not Present", _val);
- Py_DECREF(_val);
- }
-
- _val = dmi_ipmi_base_address(data[0x04], data+0x08, h->length<0x12?0:(data[0x10]>>5)&1);
- PyDict_SetItemString(caseData, "Base Address", _val);
- Py_DECREF(_val);
-
- if(h->length<0x12) break;
- if(data[0x04]!=0x04) {
- _val = dmi_ipmi_register_spacing(data[0x10]>>6);
- PyDict_SetItemString(caseData, "Register Spacing", _val);
- Py_DECREF(_val);
-
- if(data[0x10]&(1<<3)) {
- _val = PyString_FromFormat("%s", data[0x10]&(1<<1)?"Active High":"Active Low");
- PyDict_SetItemString(caseData, "Interrupt Polarity", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%s", data[0x10]&(1<<0)?"Level":"Edge");
- PyDict_SetItemString(caseData, "Interrupt Trigger Mode", _val);
- Py_DECREF(_val);
- }
- }
- if(data[0x11]!=0x00) {
- _val = PyString_FromFormat("%x", data[0x11]);
- PyDict_SetItemString(caseData, "Interrupt Number", _val);
- Py_DECREF(_val);
- }
- break;
-
- case 39: /* 3.3.40 System Power Supply */
-
- if(h->length<0x10) break;
- if(data[0x04]!=0x00) {
- _val = PyString_FromFormat("%i", data[0x04]);
- PyDict_SetItemString(caseData, "Power Unit Group", _val);
- Py_DECREF(_val);
- }
-
- _val = dmi_string_py(h, data[0x05]);
- PyDict_SetItemString(caseData, "Location", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x06]);
- PyDict_SetItemString(caseData, "Name", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x07]);
- PyDict_SetItemString(caseData, "Manufacturer", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x08]);
- PyDict_SetItemString(caseData, "Serial Numberr", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x09]);
- PyDict_SetItemString(caseData, "Asset Tag", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x0A]);
- PyDict_SetItemString(caseData, "Model Part Number", _val);
- Py_DECREF(_val);
-
- _val = dmi_string_py(h, data[0x0B]);
- PyDict_SetItemString(caseData, "Revision", _val);
- Py_DECREF(_val);
-
- _val = dmi_power_supply_power(WORD(data+0x0C));
- PyDict_SetItemString(caseData, "Max Power Capacity", _val);
- Py_DECREF(_val);
-
- if(WORD(data+0x0E)&(1<<1)) {
- _val = dmi_power_supply_status((WORD(data+0x0E)>>7)&0x07);
- PyDict_SetItemString(caseData, "Status Present", _val);
- Py_DECREF(_val);
- } else {
- _val = PyString_FromString("Not Present");
- PyDict_SetItemString(caseData, "Status", _val);
- Py_DECREF(_val);
- }
- _val = dmi_power_supply_type((WORD(data+0x0E)>>10)&0x0F);
- PyDict_SetItemString(caseData, "Type", _val);
- Py_DECREF(_val);
-
- _val = dmi_power_supply_range_switching((WORD(data+0x0E)>>3)&0x0F);
- PyDict_SetItemString(caseData, "Input Voltage Range Switching", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%s", WORD(data+0x0E)&(1<<2)?"No":"Yes");
- PyDict_SetItemString(caseData, "Plugged", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromFormat("%s", WORD(data+0x0E)&(1<<0)?"Yes":"No");
- PyDict_SetItemString(caseData, "Hot Replaceable", _val);
- Py_DECREF(_val);
-
- if(h->length<0x16) break;
- if(WORD(data+0x10)!=0xFFFF) {
- _val = PyString_FromFormat("0x%04x", WORD(data+0x10));
- PyDict_SetItemString(caseData, "Input Voltage Probe Handle", _val);
- Py_DECREF(_val);
- }
-
- if(WORD(data+0x12)!=0xFFFF) {
- _val = PyString_FromFormat("0x%04x", WORD(data+0x12));
- PyDict_SetItemString(caseData, "Cooling Device Handle", _val);
- Py_DECREF(_val);
- }
-
- if(WORD(data+0x14)!=0xFFFF) {
- _val = PyString_FromFormat("0x%04x", WORD(data+0x14));
- PyDict_SetItemString(caseData, "Input Current Probe Handle", _val);
- Py_DECREF(_val);
- }
-
- break;
-
- case 40: /* 3.3.41 Additional Information */
- if(h->length < 0x0B) break;
- _key = PyString_FromFormat("Additional Information");
- _val = dmi_additional_info(h, "");
- PyDict_SetItem(caseData, _key, _val);
- Py_DECREF(_key);
- Py_DECREF(_val);
- break;
-
- case 41: /* 3.3.42 Onboard Device Extended Information */
- if (h->length < 0x0B) break;
- PyObject *subdata = PyDict_New();
-
- _val = dmi_string_py(h, data[0x04]);
- PyDict_SetItemString(subdata, "Reference Designation", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromString(dmi_on_board_devices_type(data[0x05] & 0x7F));
- PyDict_SetItemString(subdata, "Type", _val);
- Py_DECREF(_val);
-
- _val = PyString_FromString(data[0x05]&0x80 ? "Enabled" : "Disabled");
- PyDict_SetItemString(subdata, "Status", _val);
- Py_DECREF(_val);
-
- _val = PyInt_FromLong(data[0x06]);
- PyDict_SetItemString(subdata, "Type Instance", _val);
- Py_DECREF(_val);
-
- _val = dmi_slot_segment_bus_func(WORD(data + 0x07), data[0x09], data[0x0A]);
- PyDict_SetItemString(subdata, "Bus Address", _val);
- Py_DECREF(_val);
-
- PyDict_SetItemString(caseData, "Onboard Device", subdata);
- Py_DECREF(subdata);
- break;
-
- case 126: /* 3.3.43 Inactive */
- _val = Py_None;
- PyDict_SetItemString(caseData, "Inactive", _val);
- Py_DECREF(_val);
- break;
-
- case 127: /* 3.3.44 End Of Table */
- _val = Py_None;
- PyDict_SetItemString(caseData, "End Of Table", _val);
- Py_DECREF(_val);
- break;
-
- default:
- if(dmi_decode_oem(h)) break;
- _key = PyString_FromFormat("%s Type", h->type>=128?"OEM-specific":"Unknown");
- _val = dmi_dump(h);
- PyDict_SetItem(caseData, _key, _val);
- Py_DECREF(_key);
- Py_DECREF(_val);
- }
-
- Py_INCREF(caseData);
- return caseData;
-}
-
-void to_dmi_header(struct dmi_header *h, u8 *data) {
- h->type=data[0];
- h->length=data[1];
- h->handle=WORD(data+2);
- h->data=data;
-}
-
-static void dmi_table_string_py(const struct dmi_header *h, const u8 *data, PyObject *hDict, u16 ver) {
- int key;
- u8 offset = opt.string->offset;
-
- if (offset >= h->length) return;
-
- //. TODO: These should have more meaningful dictionary names
- key = (opt.string->type << 8) | offset;
- PyObject *_val;
- switch(key) {
- case 0x108:
- _val = dmi_system_uuid_py(data+offset, ver);
- PyDict_SetItemString(hDict, "0x108", _val);
- break;
- case 0x305:
- _val = dmi_chassis_type_py(data[offset]);
- PyDict_SetItemString(hDict, "0x305", _val);
- case 0x406:
- _val = PyString_FromString(dmi_processor_family(h));
- PyDict_SetItemString(hDict, "0x406", _val);
- break;
- case 0x416:
- _val = dmi_processor_frequency_py((u8 *)data + offset);
- PyDict_SetItemString(hDict, "0x416", _val);
- break;
- default:
- _val = dmi_string_py(h, data[offset]);
- PyDict_SetItemString(hDict, "0x???", _val);
- }
- Py_DECREF(_val);
+ free(buf);
}
-/*
-static void dmi_table_dump(u32 base, u16 len, const char *devmem)
+int _smbios_decode_check(u8 * buf)
{
- u8 *buf;
+ int check = (!checksum(buf, buf[0x05]) || memcmp(buf + 0x10, "_DMI_", 5) != 0 ||
+ !checksum(buf + 0x10, 0x0F)) ? 0 : 1;
+ return check;
+}
- if ((buf = mem_chunk(base, len, devmem)) == NULL)
- {
- fprintf(stderr, "Failed to read table, sorry.\n");
- return;
+xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem)
+{
+ int check = _smbios_decode_check(buf);
+
+ xmlNode *data_n = xmlNewNode(NULL, (xmlChar *) "DMIversion");
+ assert( data_n != NULL );
+
+ dmixml_AddAttribute(data_n, "type", "SMBIOS");
+
+ if(check == 1) {
+ u16 ver = (buf[0x06] << 8) + buf[0x07];
+
+ /* Some BIOS report weird SMBIOS version, fix that up */
+ int _m, _M;
+
+ _m = 0;
+ _M = 0;
+ switch (ver) {
+ case 0x021F:
+ _m = 31;
+ _M = 3;
+ ver = 0x0203;
+ break;
+ case 0x0233:
+ _m = 51;
+ _M = 6;
+ ver = 0x0206;
+ break;
+ }
+ if(_m || _M) {
+ dmixml_AddTextContent(data_n, "SMBIOS %i.%i present (Version fixup 2.%d -> 2.%d)",
+ ver >> 8, ver & 0xFF, _m, _M);
+ dmixml_AddAttribute(data_n, "version", "%i.%i", ver >> 8, ver & 0xFF);
+ dmixml_AddAttribute(data_n, "fixup_version", "2.%d_2.%d", _m, _M);
+ } else {
+ dmixml_AddTextContent(data_n, "SMBIOS %i.%i present", ver >> 8, ver & 0xFF);
+ dmixml_AddAttribute(data_n, "version", "%i.%i", ver >> 8, ver & 0xFF);
+ }
+ } else if(check == 0) {
+ dmixml_AddTextContent(data_n, "No SMBIOS nor DMI entry point found");
+ dmixml_AddAttribute(data_n, "unknown", "1");
}
+ return data_n;
+}
- printf("# Writing %d bytes to %s.\n", len, PyString_AS_STRING(opt.dumpfile));
- write_dump(32, len, buf, PyString_AS_STRING(opt.dumpfile), 0);
- free(buf);
+int smbios_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
+{
+ int check = _smbios_decode_check(buf);
+
+ if(check == 1) {
+ u16 ver = (buf[0x06] << 8) + buf[0x07];
+
+ switch (ver) {
+ case 0x021F:
+ ver = 0x0203;
+ break;
+ case 0x0233:
+ ver = 0x0206;
+ break;
+ }
+ //printf(">>%d @ %d, %d<<\n", DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C));
+ dmi_table(type, DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C), ver, devmem,
+ xmlnode);
+ }
+ return check;
}
-*/
-/*
- * Build a crafted entry point with table address hard-coded to 32,
- * as this is where we will put it in the output file. We adjust the
- * DMI checksum appropriately. The SMBIOS checksum needs no adjustment.
- */
-static void overwrite_dmi_address(u8 *buf) {
- buf[0x05] += buf[0x08] + buf[0x09] + buf[0x0A] + buf[0x0B] - 32;
- buf[0x08] = 32;
- buf[0x09] = 0;
- buf[0x0A] = 0;
- buf[0x0B] = 0;
-}
-
-
-#define NON_LEGACY 0
-#define LEGACY 1
-int dumpling(u8 *buf, const char *dumpfile, u8 mode) {
- u32 base;
- u16 len;
- if(mode == NON_LEGACY) {
- if(!checksum(buf, buf[0x05]) || !memcmp(buf+0x10, "_DMI_", 5)==0 || !checksum(buf+0x10, 0x0F)) return 0;
- base = DWORD(buf+0x18);
- len = WORD(buf+0x16);
- } else {
- if(!checksum(buf, 0x0F)) return 0;
- base = DWORD(buf+0x08);
- len = WORD(buf+0x06);
- }
-
- u8 *buff;
- if((buff = mem_chunk(base, len, DEFAULT_MEM_DEV)) != NULL) {
- //. Part 1.
- printf("# Writing %d bytes to %s.\n", len, dumpfile);
- write_dump(32, len, buff, dumpfile, 0);
- free(buff);
-
- //. Part 2.
- if(mode != LEGACY) {
- u8 crafted[32];
- memcpy(crafted, buf, 32);
- overwrite_dmi_address(crafted+0x10);
- printf("# Writing %d bytes to %s.\n", crafted[0x05], dumpfile);
- write_dump(0, crafted[0x05], crafted, dumpfile, 1);
- } else {
- u8 crafted[16];
- memcpy(crafted, buf, 16);
- overwrite_dmi_address(crafted);
- printf("# Writing %d bytes to %s.\n", 0x0F, dumpfile);
- write_dump(0, 0x0F, crafted, dumpfile, 1);
- }
- } else {
- fprintf(stderr, "Failed to read table, sorry.\n");
- }
-
- //. TODO: Cleanup
- return 1;
-}
-
-int dump(const char *dumpfile) {
- /* On success, return found, otherwise return -1 */
- int ret=0;
- int found=0;
- size_t fp;
- int efi;
- u8 *buf;
-
- /* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
- if(efi == EFI_NOT_FOUND) {
- /* Fallback to memory scan (x86, x86_64) */
- if((buf=mem_chunk(0xF0000, 0x10000, DEFAULT_MEM_DEV))!=NULL) {
- for(fp=0; fp<=0xFFF0; fp+=16) {
- if(memcmp(buf+fp, "_SM_", 4)==0 && fp<=0xFFE0) {
- if(dumpling(buf+fp, dumpfile, NON_LEGACY)) found++;
- fp+=16;
- } else if(memcmp(buf+fp, "_DMI_", 5)==0) {
- if(dumpling(buf+fp, dumpfile, LEGACY)) found++;
- }
- }
- } else ret = -1;
- } else if(efi == EFI_NO_SMBIOS) {
- ret = -1;
- } else {
- if((buf=mem_chunk(fp, 0x20, DEFAULT_MEM_DEV))==NULL) ret = -1;
- else if(dumpling(buf, dumpfile, NON_LEGACY)) found++;
- }
-
- if(ret==0) {
- free(buf);
-
- //. TODO: Exception
- //dmiSetItem(pydata, "detect", "No SMBIOS nor DMI entry point found, sorry G.");
- if(!found) ret = -1;
- }
-
- return ret==0?found:ret;
-}
-
-
-
-static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, PyObject *pydata) {
- u8 *buf;
- u8 *data;
- int i=0;
-
- if(opt.type==NULL) {
- dmiSetItem(pydata, "dmi_table_size", "%i structures occupying %i bytes", num, len);
- /* TODO DUMP
- if (!(opt.flags & FLAG_FROM_DUMP))
- dmiSetItem(pydata, "dmi_table_base", "Table at 0x%08x", base);
- */
- dmiSetItem(pydata, "dmi_table_base", "Table at 0x%08x", base);
- }
-
- if((buf=mem_chunk(base, len, devmem))==NULL) {
- fprintf(stderr, "Table is unreachable, sorry."
-#ifndef USE_MMAP
- "Try compiling dmidecode with -DUSE_MMAP.";
-#endif
- "\n");
- return;
- }
-
- data=buf;
- while(i<num && data+4<=buf+len) /* 4 is the length of an SMBIOS structure header */ {
-
- u8 *next;
- struct dmi_header h;
- int display;
-
- to_dmi_header(&h, data);
- display=((opt.type==NULL || opt.type[h.type])
-// && !(h.type>39 && h.type<=127)
- && !opt.string);
-
- /*
- ** If a short entry is found (less than 4 bytes), not only it
- ** is invalid, but we cannot reliably locate the next entry.
- ** Better stop at this point, and let the user know his/her
- ** table is broken.
- */
- if(h.length<4) {
- fprintf(stderr, "Invalid entry length (%i). DMI table is broken! Stop.", (unsigned int)h.length);
- break;
- }
-
- /* In quiet mode (FLAG_QUIET - removed for python-dmidecode all together), stop decoding at end of table marker */
-
- char hid[7];
- sprintf(hid, "0x%04x", h.handle);
- PyObject *hDict = PyDict_New();
- dmiSetItem(hDict, "dmi_handle", hid);
- dmiSetItem(hDict, "dmi_type", "%d", h.type);
- dmiSetItem(hDict, "dmi_size", "%d", h.length);
-
- /* assign vendor for vendor-specific decodes later */
- if(h.type==0 && h.length>=5)
- dmi_set_vendor(dmi_string(&h, data[0x04]));
-
- /* look for the next handle */
- next=data+h.length;
- while(next-buf+1<len && (next[0]!=0 || next[1]!=0))
- next++;
-
- next+=2;
-
- if(display) {
- if(next-buf<=len) {
- /* TODO: ...
- if(opt.flags & FLAG_DUMP) {
- PyDict_SetItem(hDict, PyString_FromString("lookup"), dmi_dump(&h));
- } else {
- //. TODO: //. Is the value of `i' important?...
- //. TODO: PyDict_SetItem(hDict, PyInt_FromLong(i), dmi_decode(&h, ver));
- //. TODO: ...removed and replaced with `data'...
- PyDict_SetItem(hDict, PyString_FromString("data"), dmi_decode(&h, ver));
- PyDict_SetItem(pydata, PyString_FromString(hid), hDict);
- }*/
- PyDict_SetItem(hDict, PyString_FromString("data"), dmi_decode(&h, ver));
- PyDict_SetItem(pydata, PyString_FromString(hid), hDict);
- } else fprintf(stderr, "<TRUNCATED>");
- } else if(opt.string!=NULL && opt.string->type==h.type) {
- dmi_table_string_py(&h, data, hDict, ver);
- }
-
- data=next;
- i++;
- }
-
- if(i!=num)
- fprintf(stderr, "Wrong DMI structures count: %d announced, only %d decoded.\n", num, i);
- if(data-buf!=len)
- fprintf(stderr, "Wrong DMI structures length: %d bytes announced, structures occupy %d bytes.\n",
- len, (unsigned int)(data-buf));
-
- free(buf);
-}
-
-
-
-
-int _smbios_decode_check(u8 *buf) {
- int check = (!checksum(buf, buf[0x05]) || memcmp(buf + 0x10, "_DMI_", 5)!=0 || !checksum(buf+0x10, 0x0F)) ? 0 : 1;
- return check;
-}
-int smbios_decode_set_version(u8 *buf, const char *devmem, PyObject** pydata) {
- int check = _smbios_decode_check(buf);
- char vbuf[64]; bzero(vbuf, 64);
- if(check == 1) {
- u16 ver = (buf[0x06] << 8) + buf[0x07];
- /* Some BIOS report weird SMBIOS version, fix that up */
- int _m, _M;
- _m = 0;
- _M = 0;
- switch(ver) {
- case 0x021F:
- _m = 31;
- _M = 3;
- ver = 0x0203;
- break;
- case 0x0233:
- _m = 51;
- _M = 6;
- ver = 0x0206;
- break;
- }
- if(_m || _M) sprintf(vbuf, "SMBIOS %i.%i present (Version fixup 2.%d -> 2.%d)", ver>>8, ver&0xFF, _m, _M);
- else sprintf(vbuf, "SMBIOS %i.%i present", ver>>8, ver&0xFF);
- } else if(check == 0) {
- sprintf(vbuf, "No SMBIOS nor DMI entry point found");
- }
- if(check == 1) {
- if(*pydata) { Py_DECREF(*pydata); }
- *pydata = PyString_FromString(vbuf);
- Py_INCREF(*pydata);
- }
- return check;
-}
-int smbios_decode(u8 *buf, const char *devmem, PyObject* pydata) {
- int check = _smbios_decode_check(buf);
- if(check == 1) {
- u16 ver = (buf[0x06] << 8) + buf[0x07];
- switch(ver) {
- case 0x021F:
- ver = 0x0203;
- break;
- case 0x0233:
- ver = 0x0206;
- break;
- }
- //printf(">>%d @ %d, %d<<\n", DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C));
- dmi_table(DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C), ver, devmem, pydata);
- }
- return check;
-}
-
-
-
-
-int _legacy_decode_check(u8 *buf) {
- int check;
- if(!checksum(buf, 0x0F)) check = 0; //. Bad
- else check = 1; //. Good
- return check;
-}
-int legacy_decode_set_version(u8 *buf, const char *devmem, PyObject** pydata) {
- int check = _legacy_decode_check(buf);
- char vbuf[64]; bzero(vbuf, 64);
- if(check == 1) {
- sprintf(vbuf, "Legacy DMI %i.%i present", buf[0x0E]>>4, buf[0x0E]&0x0F);
- } else if(check == 0) {
- sprintf(vbuf, "No SMBIOS nor DMI entry point found");
- }
- if(check == 1) {
- if(*pydata) { Py_DECREF(*pydata); }
- *pydata = PyString_FromString(vbuf);
- Py_INCREF(*pydata);
- }
- return check;
-}
-int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata) {
- int check = _legacy_decode_check(buf);
- if(check == 1)
- dmi_table(DWORD(buf+0x08), WORD(buf+0x06), WORD(buf+0x0C), ((buf[0x0E]&0xF0)<<4)+(buf[0x0E]&0x0F), devmem, pydata);
- return check;
+int _legacy_decode_check(u8 * buf)
+{
+ int check;
+
+ if(!checksum(buf, 0x0F))
+ check = 0; //. Bad
+ else
+ check = 1; //. Good
+ return check;
}
+xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem)
+{
+ int check = _legacy_decode_check(buf);
+
+ xmlNode *data_n = xmlNewNode(NULL, (xmlChar *) "DMIversion");
+ assert( data_n != NULL );
+ dmixml_AddAttribute(data_n, "type", "legacy");
+ if(check == 1) {
+ dmixml_AddTextContent(data_n, "Legacy DMI %i.%i present",
+ buf[0x0E] >> 4, buf[0x0E] & 0x0F);
+ dmixml_AddAttribute(data_n, "version", "%i.%i",
+ buf[0x0E] >> 4, buf[0x0E] & 0x0F);
+ } else if(check == 0) {
+ dmixml_AddTextContent(data_n, "No SMBIOS nor DMI entry point found");
+ dmixml_AddAttribute(data_n, "unknown", "1");
+ }
-/*******************************************************************************
-** Probe for EFI interface
-*/
-int address_from_efi(size_t *address) {
- FILE *efi_systab;
- const char *filename;
- char linebuf[64];
- int ret;
-
- *address = 0; /* Prevent compiler warning */
-
- /*
- ** Linux <= 2.6.6: /proc/efi/systab
- ** Linux >= 2.6.7: /sys/firmware/efi/systab
- */
- if((efi_systab=fopen(filename="/sys/firmware/efi/systab", "r"))==NULL
- && (efi_systab=fopen(filename="/proc/efi/systab", "r"))==NULL) {
- /* No EFI interface, fallback to memory scan */
- return EFI_NOT_FOUND;
- }
- ret=EFI_NO_SMBIOS;
- while((fgets(linebuf, sizeof(linebuf)-1, efi_systab))!=NULL) {
- char *addrp=strchr(linebuf, '=');
- *(addrp++)='\0';
- if(strcmp(linebuf, "SMBIOS")==0) {
- *address=strtoul(addrp, NULL, 0);
- printf("# SMBIOS entry point at 0x%08lx\n", (unsigned long)*address);
- ret=0;
- break;
- }
- }
- if(fclose(efi_systab)!=0)
- perror(filename);
-
- if(ret==EFI_NO_SMBIOS)
- fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
-
- return ret;
+ return data_n;
}
+
+int legacy_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
+{
+ int check = _legacy_decode_check(buf);
+
+ if(check == 1)
+ dmi_table(type, DWORD(buf + 0x08), WORD(buf + 0x06), WORD(buf + 0x0C),
+ ((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F), devmem, xmlnode);
+ return check;
+}
+
diff --git a/src/dmidecode.h b/src/dmidecode.h
index 7e99faa..10412c6 100644
--- a/src/dmidecode.h
+++ b/src/dmidecode.h
@@ -1,3 +1,4 @@
+
/*
* This file is part of the dmidecode project.
*
@@ -17,29 +18,27 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <Python.h>
+
+#include <libxml/tree.h>
+#include "dmihelper.h"
struct dmi_header {
- u8 type;
- u8 length;
- u16 handle;
- u8 *data;
+ u8 type;
+ u8 length;
+ u16 handle;
+ u8 *data;
};
-PyObject *dmi_dump(struct dmi_header *h);
-PyObject* dmi_decode(struct dmi_header *h, u16 ver);
-int address_from_efi(size_t *address);
-void to_dmi_header(struct dmi_header *h, u8 *data);
-int smbios_decode_set_version(u8 *buf, const char *devmem, PyObject** pydata);
-int smbios_decode(u8 *buf, const char *devmem, PyObject* pydata);
-int legacy_decode_set_version(u8 *buf, const char *devmem, PyObject** pydata);
-int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata);
+void dmi_dump(xmlNode *node, struct dmi_header * h);
+xmlNode *dmi_decode(xmlNode *parent_n, dmi_codes_major *dmiMajor, struct dmi_header * h, u16 ver);
+void to_dmi_header(struct dmi_header *h, u8 * data);
-const char *dmi_string(const struct dmi_header *dm, u8 s);
-const char *dmi_system_uuid(u8 *p);
-PyObject *dmi_system_uuid_py(const u8 *p, u16 ver);
-const char *dmi_chassis_type(u8 code);
-int dmi_processor_frequency(const u8 *p);
+xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem);
+xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem);
+int smbios_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
+int legacy_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
-int dump(const char *dumpfile);
-int dumpling(u8 *buf, const char *devmem, u8 mode);
+const char *dmi_string(const struct dmi_header *dm, u8 s);
+void dmi_system_uuid(xmlNode *node, const u8 * p, u16 ver);
+void dmi_chassis_type(xmlNode *node, u8 code);
+int dmi_processor_frequency(const u8 * p);
diff --git a/src/dmidecodemodule.c b/src/dmidecodemodule.c
index 345b151..5c74124 100644
--- a/src/dmidecodemodule.c
+++ b/src/dmidecodemodule.c
@@ -1,305 +1,731 @@
+
+/*. ******* coding:utf-8 AUTOHEADER START v1.1 *******
+ *. vim: fileencoding=utf-8 syntax=c sw=8 ts=8 et
+ *.
+ *. © 2007-2009 Nima Talebi <nima@autonomy.net.au>
+ *. © 2009 David Sommerseth <davids@redhat.com>
+ *. © 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *. © 2000-2002 Alan Cox <alan@redhat.com>
+ *.
+ *. This file is part of Python DMI-Decode.
+ *.
+ *. Python DMI-Decode is free software: you can redistribute it and/or modify
+ *. it under the terms of the GNU General Public License as published by
+ *. the Free Software Foundation, either version 2 of the License, or
+ *. (at your option) any later version.
+ *.
+ *. Python DMI-Decode is distributed in the hope that it will be useful,
+ *. but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *. GNU General Public License for more details.
+ *.
+ *. You should have received a copy of the GNU General Public License
+ *. along with Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ *.
+ *. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ *. EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ *. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *.
+ *. ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ *. AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ *.
+ *. $AutoHeaderSerial::20090522 $
+ *. ******* AUTOHEADER END v1.1 ******* */
+
+#include <Python.h>
+
+#include <libxml/tree.h>
+#include "libxml_wrap.h"
+
+#include "xmlpythonizer.h"
#include "dmidecodemodule.h"
+#include "dmixml.h"
+#include "dmierror.h"
+#include "version.h"
+#include "dmidump.h"
#include <mcheck.h>
-options opt;
-static void init(void) {
- /* sanity check */
- if(sizeof(u8)!=1 || sizeof(u16)!=2 || sizeof(u32)!=4 || '\0'!=0)
- fprintf(stderr, "%s: compiler incompatibility\n", "dmidecodemodule");
+static void init(options *opt)
+{
+ /* sanity check */
+ if(sizeof(u8) != 1 || sizeof(u16) != 2 || sizeof(u32) != 4 || '\0' != 0)
+ fprintf(stderr, "%s: compiler incompatibility\n", "dmidecodemodule");
+
+ opt->devmem = DEFAULT_MEM_DEV;
+ opt->dumpfile = NULL;
+ opt->flags = 0;
+ opt->type = -1;
+ opt->dmiversion_n = NULL;
+ opt->mappingxml = NULL;
+ opt->python_xml_map = strdup(PYTHON_XML_MAP);
+}
- opt.devmem = DEFAULT_MEM_DEV;
- opt.dumpfile = NULL;
- opt.flags=0;
- opt.type = NULL;
+int parse_opt_type(const char *arg)
+{
+ while(*arg != '\0') {
+ int val;
+ char *next;
+
+ val = strtoul(arg, &next, 0);
+ if(next == arg) {
+ fprintf(stderr, "Invalid type keyword: %s\n", arg);
+ return -1;
+ }
+ if(val > 0xff) {
+ fprintf(stderr, "Invalid type number: %i\n", val);
+ return -1;
+ }
+
+ if( val >= 0 ) {
+ return val;
+ }
+ arg = next;
+ while(*arg == ',' || *arg == ' ')
+ arg++;
+ }
+ return -1;
}
-u8 *parse_opt_type(u8 *p, const char *arg) {
-
- /* Allocate memory on first call only */
- if(p == NULL) {
- if(!(p = (u8 *)calloc(256, sizeof(u8)))) {
- perror("calloc");
- return NULL;
- }
- }
-
- unsigned int i, j;
- /* First try as a keyword */
- for(i = 0; i < ARRAY_SIZE(opt_type_keyword); i++) {
- if(!strcasecmp(arg, opt_type_keyword[i].keyword)) {
- j = 0;
- while(opt_type_keyword[i].type[j] != 255)
- p[opt_type_keyword[i].type[j++]] = 1;
- return p;
- }
- }
-
- /* Else try as a number */
- while(*arg != '\0') {
- unsigned long val;
- char *next;
-
- val = strtoul(arg, &next, 0);
- if(next == arg) {
- fprintf(stderr, "Invalid type keyword: %s\n", arg);
- free(p);
- return NULL;
- }
- if (val > 0xff) {
- fprintf(stderr, "Invalid type number: %lu\n", val);
- free(p);
- return NULL;
- }
-
- p[val] = 1;
- arg = next;
- while(*arg == ',' || *arg == ' ')
- arg++;
- }
-
- return p;
+xmlNode *dmidecode_get_version(options *opt)
+{
+ int found = 0;
+ size_t fp;
+ int efi;
+ u8 *buf = NULL;
+ xmlNode *ver_n = NULL;
+
+ /* Set default option values */
+ if( opt->devmem == NULL ) {
+ opt->devmem = DEFAULT_MEM_DEV;
+ }
+
+ /* Read from dump if so instructed */
+ if(opt->dumpfile != NULL) {
+ //. printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
+ if((buf = mem_chunk(0, 0x20, opt->dumpfile)) != NULL) {
+ if(memcmp(buf, "_SM_", 4) == 0) {
+ ver_n = smbios_decode_get_version(buf, opt->dumpfile);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ } else if(memcmp(buf, "_DMI_", 5) == 0) {
+ ver_n = legacy_decode_get_version(buf, opt->dumpfile);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ }
+ }
+ } else { /* Read from /dev/mem */
+ /* First try EFI (ia64, Intel-based Mac) */
+ efi = address_from_efi(&fp);
+ if(efi == EFI_NOT_FOUND) {
+ /* Fallback to memory scan (x86, x86_64) */
+ if((buf = mem_chunk(0xF0000, 0x10000, opt->devmem)) != NULL) {
+ for(fp = 0; fp <= 0xFFF0; fp += 16) {
+ if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) {
+ ver_n = smbios_decode_get_version(buf + fp, opt->devmem);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ fp += 16;
+ } else if(memcmp(buf + fp, "_DMI_", 5) == 0) {
+ ver_n = legacy_decode_get_version (buf + fp, opt->devmem);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ }
+ }
+ }
+ } else if(efi == EFI_NO_SMBIOS) {
+ ver_n = NULL;
+ } else {
+ // Process as EFI
+ if((buf = mem_chunk(fp, 0x20, opt->devmem)) != NULL) {
+ ver_n = smbios_decode_get_version(buf, opt->devmem);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ //. TODO: dmixml_AddAttribute(dmixml_n, "efi_address", efiAddress);
+ }
+ }
+ }
+ if( buf != NULL ) {
+ free(buf);
+ }
+ if( !found ) {
+ fprintf(stderr, "No SMBIOS nor DMI entry point found, sorry.");
+ }
+ return ver_n;
}
+int dmidecode_get_xml(options *opt, xmlNode* dmixml_n)
+{
+ assert(dmixml_n != NULL);
+ if(dmixml_n == NULL) {
+ return 0;
+ }
+ //mtrace();
+
+ int ret = 0;
+ int found = 0;
+ size_t fp;
+ int efi;
+ u8 *buf = NULL;
+
+ const char *f = opt->dumpfile ? opt->dumpfile : opt->devmem;
+ if(access(f, R_OK) < 0) {
+ fprintf(stderr, "Permission denied to memory file/device (%s)", f);
+ return 0;
+ }
+
+ /* Read from dump if so instructed */
+ if(opt->dumpfile != NULL) {
+ // printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
+ if((buf = mem_chunk(0, 0x20, opt->dumpfile)) != NULL) {
+ if(memcmp(buf, "_SM_", 4) == 0) {
+ if(smbios_decode(opt->type, buf, opt->dumpfile, dmixml_n))
+ found++;
+ } else if(memcmp(buf, "_DMI_", 5) == 0) {
+ if(legacy_decode(opt->type, buf, opt->dumpfile, dmixml_n))
+ found++;
+ }
+ } else {
+ ret = 1;
+ }
+ } else { /* Read from /dev/mem */
+ /* First try EFI (ia64, Intel-based Mac) */
+ efi = address_from_efi(&fp);
+ if(efi == EFI_NOT_FOUND) {
+ /* Fallback to memory scan (x86, x86_64) */
+ if((buf = mem_chunk(0xF0000, 0x10000, opt->devmem)) != NULL) {
+ for(fp = 0; fp <= 0xFFF0; fp += 16) {
+ if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) {
+ if(smbios_decode(opt->type, buf + fp, opt->devmem, dmixml_n)) {
+ found++;
+ fp += 16;
+ }
+ } else if(memcmp(buf + fp, "_DMI_", 5) == 0) {
+ if(legacy_decode(opt->type, buf + fp, opt->devmem, dmixml_n))
+ found++;
+ }
+ }
+ } else
+ ret = 1;
+ } else if(efi == EFI_NO_SMBIOS) {
+ ret = 1;
+ } else {
+ if((buf = mem_chunk(fp, 0x20, opt->devmem)) == NULL)
+ ret = 1;
+ else if(smbios_decode(opt->type, buf, opt->devmem, dmixml_n))
+ found++;
+ // TODO: dmixml_AddAttribute(dmixml_n, "efi_address", "0x%08x", efiAddress);
+ }
+ }
+ if(ret == 0) {
+ free(buf);
+ }
+ //muntrace();
+ return ret;
+}
-static int dmidecode_set_version(PyObject** pydata) {
- int ret=0;
- int found=0;
- size_t fp;
- int efi;
- u8 *buf;
-
- /* Set default option values */
- opt.devmem = DEFAULT_MEM_DEV;
-
- /***********************************/
- /* Read from dump if so instructed */
- if(opt.dumpfile != NULL) {
- const char *dumpfile = PyString_AS_STRING(opt.dumpfile);
- //. printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
- if((buf = mem_chunk(0, 0x20, dumpfile))!=NULL) {
- if(memcmp(buf, "_SM_", 4)==0) {
- if(smbios_decode_set_version(buf, dumpfile, pydata)) found++;
- } else if (memcmp(buf, "_DMI_", 5)==0) {
- if(legacy_decode_set_version(buf, dumpfile, pydata)) found++;
- }
- } else ret = 1;
- } else { /* Read from /dev/mem */
- /* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
- if(efi == EFI_NOT_FOUND) {
- /* Fallback to memory scan (x86, x86_64) */
- if((buf=mem_chunk(0xF0000, 0x10000, opt.devmem))!=NULL) {
- for(fp=0; fp<=0xFFF0; fp+=16) {
- if(memcmp(buf+fp, "_SM_", 4)==0 && fp<=0xFFE0) {
- if(smbios_decode_set_version(buf+fp, opt.devmem, pydata)) found++;
- fp+=16;
- } else if(memcmp(buf+fp, "_DMI_", 5)==0) {
- if(legacy_decode_set_version(buf+fp, opt.devmem, pydata)) found++;
- }
- }
- } else ret = 1;
- } else if(efi == EFI_NO_SMBIOS) {
- ret = 1;
- } else {
- if((buf=mem_chunk(fp, 0x20, opt.devmem))==NULL) ret = 1;
- else if(smbios_decode_set_version(buf, opt.devmem, pydata)) found++;
- //. TODO: dmiSetItem(pydata, "efi_address", efiAddress);
- }
- }
-
- if(ret==0) {
- free(buf);
- if(!found) {
- fprintf(stderr, "No SMBIOS nor DMI entry point found, sorry G.");
- }
- }
- free(opt.type);
- return ret;
+xmlNode* load_mappingxml(options *opt) {
+ if( opt->mappingxml == NULL ) {
+ // Load mapping into memory
+ opt->mappingxml = xmlReadFile(opt->python_xml_map, NULL, 0);
+ if( opt->mappingxml == NULL ) {
+ PyReturnError(PyExc_IOError, "Could not open tje XML mapping file '%s'",
+ opt->python_xml_map);
+ }
+ }
+ return dmiMAP_GetRootElement(opt->mappingxml);
}
+xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) {
+ xmlNode *dmixml_n = NULL;
+ xmlNode *group_n = NULL;
+
+ dmixml_n = xmlNewNode(NULL, (xmlChar *) "dmidecode");
+ assert( dmixml_n != NULL );
+ // Append DMI version info
+ if( opt->dmiversion_n != NULL ) {
+ xmlAddChild(dmixml_n, xmlCopyNode(opt->dmiversion_n, 1));
+ }
+
+ // Fetch the Mapping XML file
+ if( (group_n = load_mappingxml(opt)) == NULL) {
+ // Exception already set by calling function
+ return NULL;
+ }
+
+ // Find the section in the XML containing the group mappings
+ if( (group_n = dmixml_FindNode(group_n, "GroupMapping")) == NULL ) {
+ PyReturnError(PyExc_LookupError,
+ "Could not find the GroupMapping section in the XML mapping");
+ }
+
+ // Find the XML node containing the Mapping section requested to be decoded
+ if( (group_n = dmixml_FindNodeByAttr(group_n, "Mapping", "name", section)) == NULL ) {
+ PyReturnError(PyExc_LookupError,
+ "Could not find the XML->Python Mapping section for '%s'", section);
+ }
+
+ if( group_n->children == NULL ) {
+ PyReturnError(PyExc_RuntimeError,
+ "Mapping is empty for the '%s' section in the XML mapping", section);
+ }
-static PyObject* dmidecode_get(PyObject *self, const char* section) {
- //mtrace();
-
- int ret=0;
- int found=0;
- size_t fp;
- int efi;
- u8 *buf;
-
- /* Set default option values */
- opt.devmem = DEFAULT_MEM_DEV;
- opt.flags = 0;
- opt.type = NULL;
- opt.type = parse_opt_type(opt.type, section);
- if(opt.type==NULL) return NULL;
-
- const char *f = opt.dumpfile ? PyString_AsString(opt.dumpfile) : opt.devmem;
- if(access(f, R_OK) < 0)
- PyErr_SetString(PyExc_IOError, "Permission denied to memory file/device");
-
- PyObject* pydata = PyDict_New();
-
- /***********************************/
- /* Read from dump if so instructed */
- if(opt.dumpfile != NULL) {
- const char *dumpfile = PyString_AS_STRING(opt.dumpfile);
- //. printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
- if((buf = mem_chunk(0, 0x20, dumpfile))!=NULL) {
- if(memcmp(buf, "_SM_", 4)==0) {
- if(smbios_decode(buf, dumpfile, pydata)) found++;
- } else if (memcmp(buf, "_DMI_", 5)==0) {
- if(legacy_decode(buf, dumpfile, pydata)) found++;
- }
- } else ret = 1;
- } else { /* Read from /dev/mem */
- /* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
- if(efi == EFI_NOT_FOUND) {
- /* Fallback to memory scan (x86, x86_64) */
- if((buf=mem_chunk(0xF0000, 0x10000, opt.devmem))!=NULL) {
- for(fp=0; fp<=0xFFF0; fp+=16) {
- if(memcmp(buf+fp, "_SM_", 4)==0 && fp<=0xFFE0) {
- if(smbios_decode(buf+fp, opt.devmem, pydata)) {
- found++;
- fp+=16;
- }
- } else if(memcmp(buf+fp, "_DMI_", 5)==0) {
- if(legacy_decode(buf+fp, opt.devmem, pydata)) found++;
- }
- }
- } else ret = 1;
- } else if(efi == EFI_NO_SMBIOS) {
- ret = 1;
- } else {
- if((buf=mem_chunk(fp, 0x20, opt.devmem))==NULL) ret = 1;
- else if(smbios_decode(buf, opt.devmem, pydata)) found++;
- //. TODO: dmiSetItem(pydata, "efi_address", efiAddress);
- }
- }
-
- free(opt.type);
- if(ret==0) {
- free(buf);
- } else {
- Py_DECREF(pydata);
- pydata = NULL;
- }
-
- //muntrace();
- return pydata;
+ // Go through all TypeMap's belonging to this Mapping section
+ foreach_xmlnode(dmixml_FindNode(group_n, "TypeMap"), group_n) {
+ char *typeid = dmixml_GetAttrValue(group_n, "id");
+
+ if( group_n->type != XML_ELEMENT_NODE ) {
+ continue;
+ }
+
+ // The children of <Mapping> tags must only be <TypeMap> and
+ // they must have an 'id' attribute
+ if( (typeid == NULL) || (xmlStrcmp(group_n->name, (xmlChar *) "TypeMap") != 0) ) {
+ PyReturnError(PyExc_RuntimeError, "Invalid TypeMap node in mapping XML");
+ }
+
+ // Parse the typeid string to a an integer
+ opt->type = parse_opt_type(typeid);
+ if(opt->type == -1) {
+ PyReturnError(PyExc_RuntimeError, "Invalid type id '%s'", typeid);
+ }
+
+ // Parse the DMI data and put the result into dmixml_n node chain.
+ if( dmidecode_get_xml(opt, dmixml_n) != 0 ) {
+ PyReturnError(PyExc_RuntimeError, "Error decoding DMI data");
+ }
+ }
+#if 0 // DEBUG - will dump generated XML to stdout
+ xmlDoc *doc = xmlNewDoc((xmlChar *) "1.0");
+ xmlDocSetRootElement(doc, xmlCopyNode(dmixml_n, 1));
+ xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);
+ xmlFreeDoc(doc);
+#endif
+ return dmixml_n;
}
-static PyObject* dmidecode_get_bios(PyObject *self, PyObject *args) { return dmidecode_get(self, "bios"); }
-static PyObject* dmidecode_get_system(PyObject *self, PyObject *args) { return dmidecode_get(self, "system"); }
-static PyObject* dmidecode_get_baseboard(PyObject *self, PyObject *args) { return dmidecode_get(self, "baseboard"); }
-static PyObject* dmidecode_get_chassis(PyObject *self, PyObject *args) { return dmidecode_get(self, "chassis"); }
-static PyObject* dmidecode_get_processor(PyObject *self, PyObject *args) { return dmidecode_get(self, "processor"); }
-static PyObject* dmidecode_get_memory(PyObject *self, PyObject *args) { return dmidecode_get(self, "memory"); }
-static PyObject* dmidecode_get_cache(PyObject *self, PyObject *args) { return dmidecode_get(self, "cache"); }
-static PyObject* dmidecode_get_connector(PyObject *self, PyObject *args) { return dmidecode_get(self, "connector"); }
-static PyObject* dmidecode_get_slot(PyObject *self, PyObject *args) { return dmidecode_get(self, "slot"); }
-static PyObject* dmidecode_get_type(PyObject *self, PyObject *args) {
- long unsigned int lu;
- if(PyArg_ParseTuple(args, (char *)"i", &lu)) {
- if(lu < 256) {
- char s[8];
- sprintf(s, "%lu", lu);
- return dmidecode_get(self, s);
- }
- return Py_False;
- }
- return Py_None;
+static PyObject *dmidecode_get_group(options *opt, const char *section)
+{
+ PyObject *pydata = NULL;
+ xmlNode *dmixml_n = NULL;
+ ptzMAP *mapping = NULL;
+
+ /* Set default option values */
+ if( opt->devmem == NULL ) {
+ opt->devmem = DEFAULT_MEM_DEV;
+ }
+ opt->flags = 0;
+
+ // Decode the dmidata into an XML node
+ dmixml_n = __dmidecode_xml_getsection(opt, section);
+ if( dmixml_n == NULL ) {
+ // Exception already set
+ return NULL;
+ }
+
+ // Convert the retrieved XML nodes to a Python dictionary
+ mapping = dmiMAP_ParseMappingXML_GroupName(opt->mappingxml, section);
+ if( mapping == NULL ) {
+ // Exception already set
+ xmlFreeNode(dmixml_n);
+ return NULL;
+ }
+
+ // Generate Python dict out of XML node
+ pydata = pythonizeXMLnode(mapping, dmixml_n);
+
+ // Clean up and return the resulting Python dictionary
+ ptzmap_Free(mapping);
+ xmlFreeNode(dmixml_n);
+
+ return pydata;
}
-static PyObject* dmidecode_dump(PyObject *self, PyObject *null) {
- const char *f;
- f = opt.dumpfile ? PyString_AsString(opt.dumpfile) : opt.devmem;
- struct stat _buf;
- stat(f, &_buf);
- if((access(f, F_OK) != 0) || ((access(f, W_OK) == 0) && S_ISREG(_buf.st_mode)))
- if(dump(PyString_AS_STRING(opt.dumpfile)))
- Py_RETURN_TRUE;
- Py_RETURN_FALSE;
+xmlNode *__dmidecode_xml_gettypeid(options *opt, int typeid)
+{
+ xmlNode *dmixml_n = NULL;
+
+ /* Set default option values */
+ if( opt->devmem == NULL ) {
+ opt->devmem = DEFAULT_MEM_DEV;
+ }
+ opt->flags = 0;
+
+ dmixml_n = xmlNewNode(NULL, (xmlChar *) "dmidecode");
+ assert( dmixml_n != NULL );
+ // Append DMI version info
+ if( opt->dmiversion_n != NULL ) {
+ xmlAddChild(dmixml_n, xmlCopyNode(opt->dmiversion_n, 1));
+ }
+
+ // Fetch the Mapping XML file
+ if( load_mappingxml(opt) == NULL) {
+ return NULL;
+ }
+
+ // Parse the DMI data and put the result into dmixml_n node chain.
+ opt->type = typeid;
+ if( dmidecode_get_xml(opt, dmixml_n) != 0 ) {
+ PyReturnError(PyExc_RuntimeError, "Error decoding DMI data");
+ }
+
+ return dmixml_n;
}
-static PyObject* dmidecode_get_dev(PyObject *self, PyObject *null) {
- PyObject *dev;
- if(opt.dumpfile != NULL) dev = opt.dumpfile;
- else dev = PyString_FromString(opt.devmem);
- Py_INCREF(dev);
- return dev;
+
+static PyObject *dmidecode_get_typeid(options *opt, int typeid)
+{
+ PyObject *pydata = NULL;
+ xmlNode *dmixml_n = NULL;
+ ptzMAP *mapping = NULL;
+
+ dmixml_n = __dmidecode_xml_gettypeid(opt, typeid);
+ if( dmixml_n == NULL ) {
+ // Exception already set
+ return NULL;
+ }
+
+ // Convert the retrieved XML nodes to a Python dictionary
+ mapping = dmiMAP_ParseMappingXML_TypeID(opt->mappingxml, opt->type);
+ if( mapping == NULL ) {
+ // FIXME: Should we raise an exception here?
+ // Now it passes the unit-test
+ return PyDict_New();
+ }
+
+ // Generate Python dict out of XML node
+ pydata = pythonizeXMLnode(mapping, dmixml_n);
+
+ // Clean up and return the resulting Python dictionary
+ ptzmap_Free(mapping);
+ xmlFreeNode(dmixml_n);
+
+ return pydata;
}
-static PyObject* dmidecode_set_dev(PyObject *self, PyObject *arg) {
- if(PyString_Check(arg)) {
- if(opt.dumpfile == arg) Py_RETURN_TRUE;
- struct stat buf;
- char *f = PyString_AsString(arg);
- stat(f, &buf);
- if(opt.dumpfile) { Py_DECREF(opt.dumpfile); }
+// This global variable should only be available for the "first-entry" functions
+// which is defined in PyMethodDef DMIDataMethods[].
+options *global_options = NULL;
- if(S_ISCHR(buf.st_mode)) {
- if(memcmp(PyString_AsString(arg), "/dev/mem", 8)==0) {
- opt.dumpfile = NULL;
- Py_RETURN_TRUE;
- } else {
+static PyObject *dmidecode_get_bios(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "bios");
+}
+static PyObject *dmidecode_get_system(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "system");
+}
+static PyObject *dmidecode_get_baseboard(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "baseboard");
+}
+static PyObject *dmidecode_get_chassis(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "chassis");
+}
+static PyObject *dmidecode_get_processor(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "processor");
+}
+static PyObject *dmidecode_get_memory(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "memory");
+}
+static PyObject *dmidecode_get_cache(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "cache");
+}
+static PyObject *dmidecode_get_connector(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "connector");
+}
+static PyObject *dmidecode_get_slot(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "slot");
+}
+
+static PyObject *dmidecode_get_section(PyObject *self, PyObject *args)
+{
+ char *section = PyString_AsString(args);
+
+ if( section != NULL ) {
+ return dmidecode_get_group(global_options, section);
+ }
+ PyReturnError(PyExc_RuntimeError, "No section name was given");
+}
+
+static PyObject *dmidecode_get_type(PyObject * self, PyObject * args)
+{
+ int typeid;
+ PyObject *pydata = NULL;
+
+ if( PyArg_ParseTuple(args, (char *)"i", &typeid) ) {
+ if( (typeid < 0) || (typeid > 255) ) {
+ Py_RETURN_FALSE;
+ // FIXME: Should send exception instead
+ // PyReturnError(PyExc_RuntimeError, "Types are bound between 0 and 255 (inclusive)."
+ // "Type value used was '%i'", typeid);
+ }
+ } else {
+ PyReturnError(PyExc_RuntimeError, "Type '%i' is not a valid type identifier%c", typeid);
+ }
+
+ pydata = dmidecode_get_typeid(global_options, typeid);
+ return pydata;
+}
+
+static PyObject *dmidecode_xmlapi(PyObject *self, PyObject *args, PyObject *keywds)
+{
+ static char *keywordlist[] = {"query_type", "result_type", "section", "typeid", NULL};
+ PyObject *pydata = NULL;
+ xmlDoc *dmixml_doc = NULL;
+ xmlNode *dmixml_n = NULL;
+ char *sect_query = NULL, *qtype = NULL, *rtype = NULL;
+ int type_query = -1;
+
+ // Parse the keywords - we only support keywords, as this is an internal API
+ if( !PyArg_ParseTupleAndKeywords(args, keywds, "ss|si", keywordlist,
+ &qtype, &rtype, &sect_query, &type_query) ) {
+ return NULL;
+ }
+
+ // Check for sensible arguments and retrieve the xmlNode with DMI data
+ switch( *qtype ) {
+ case 's': // Section / GroupName
+ if( sect_query == NULL ) {
+ PyReturnError(PyExc_TypeError, "section keyword cannot be NULL")
+ }
+ dmixml_n = __dmidecode_xml_getsection(global_options, sect_query);
+ break;
+
+ case 't': // TypeID / direct TypeMap
+ if( type_query < 0 ) {
+ PyReturnError(PyExc_TypeError,
+ "typeid keyword must be set and must be a positive integer");
+ } else if( type_query > 255 ) {
+ PyReturnError(PyExc_ValueError,
+ "typeid keyword must be an integer between 0 and 255");
+ }
+ dmixml_n = __dmidecode_xml_gettypeid(global_options, type_query);
+ break;
+
+ default:
+ PyReturnError(PyExc_TypeError, "Internal error - invalid query type '%c'", *qtype);
+ }
+
+ // Check if we got any data
+ if( dmixml_n == NULL ) {
+ // Exception already set
+ return NULL;
+ }
+
+ // Check for sensible return type and wrap the correct type into a Python Object
+ switch( *rtype ) {
+ case 'n':
+ pydata = libxml_xmlNodePtrWrap((xmlNode *) dmixml_n);
+ break;
+
+ case 'd':
+ dmixml_doc = xmlNewDoc((xmlChar *) "1.0");
+ if( dmixml_doc == NULL ) {
+ PyReturnError(PyExc_MemoryError, "Could not create new XML document");
+ }
+ xmlDocSetRootElement(dmixml_doc, dmixml_n);
+ pydata = libxml_xmlDocPtrWrap((xmlDoc *) dmixml_doc);
+ break;
+
+ default:
+ PyReturnError(PyExc_TypeError, "Internal error - invalid result type '%c'", *rtype);
+ }
+
+ // Return XML data
+ Py_INCREF(pydata);
+ return pydata;
+}
+
+
+
+static PyObject *dmidecode_dump(PyObject * self, PyObject * null)
+{
+ const char *f;
+ struct stat _buf;
+
+ f = (global_options->dumpfile ? global_options->dumpfile : global_options->devmem);
+ stat(f, &_buf);
+
+ if( (access(f, F_OK) != 0) || ((access(f, W_OK) == 0) && S_ISREG(_buf.st_mode)) ) {
+ if( dump(DEFAULT_MEM_DEV, f) ) {
+ Py_RETURN_TRUE;
+ }
+ }
Py_RETURN_FALSE;
- }
- } else if(!S_ISDIR(buf.st_mode)) {
- opt.dumpfile = arg;
- Py_INCREF(opt.dumpfile);
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- //PyErr_Occurred();
}
-/*
-typedef struct {
- PyObject_HEAD char *version;
-} ivars;
+static PyObject *dmidecode_get_dev(PyObject * self, PyObject * null)
+{
+ PyObject *dev = NULL;
+ dev = PyString_FromString((global_options->dumpfile != NULL
+ ? global_options->dumpfile : global_options->devmem));
+ Py_INCREF(dev);
+ return dev;
+}
+
+static PyObject *dmidecode_set_dev(PyObject * self, PyObject * arg)
+{
+ if(PyString_Check(arg)) {
+ struct stat buf;
+ char *f = PyString_AsString(arg);
+
+ if( (f != NULL) && (global_options->dumpfile != NULL )
+ && (strcmp(global_options->dumpfile, f) == 0) ) {
+ Py_RETURN_TRUE;
+ }
+
+ stat(f, &buf);
+ if(S_ISCHR(buf.st_mode)) {
+ if(memcmp(PyString_AsString(arg), "/dev/mem", 8) == 0) {
+ if( global_options->dumpfile != NULL ) {
+ free(global_options->dumpfile);
+ global_options->dumpfile = NULL;
+ }
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+ } else if(!S_ISDIR(buf.st_mode)) {
+ global_options->dumpfile = strdup(f);
+ Py_RETURN_TRUE;
+ }
+ }
+ Py_RETURN_FALSE;
+}
+
+static PyObject *dmidecode_set_pythonxmlmap(PyObject * self, PyObject * arg)
+{
+ if(PyString_Check(arg)) {
+ struct stat fileinfo;
+ char *fname = PyString_AsString(arg);
+
+ memset(&fileinfo, 0, sizeof(struct stat));
+
+ if( stat(fname, &fileinfo) != 0 ) {
+ PyReturnError(PyExc_IOError, "Could not access the file '%s'", fname);
+ }
+
+ free(global_options->python_xml_map);
+ global_options->python_xml_map = strdup(fname);
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
-static PyMemberDef DMIDataMembers[] = {
- { (char *)"fred", T_STRING, offsetof(ivars, version), 0, "2.10" },
- { NULL }
-};
-*/
static PyMethodDef DMIDataMethods[] = {
- { (char *)"dump", dmidecode_dump, METH_NOARGS, (char *)"Dump dmidata to set file" },
- { (char *)"get_dev", dmidecode_get_dev, METH_NOARGS, (char *)"Get an alternative memory device file" },
- { (char *)"set_dev", dmidecode_set_dev, METH_O, (char *)"Set an alternative memory device file" },
-
- { (char *)"bios", dmidecode_get_bios, METH_VARARGS, (char *)"BIOS Data" },
- { (char *)"system", dmidecode_get_system, METH_VARARGS, (char *)"System Data" },
- { (char *)"baseboard", dmidecode_get_baseboard, METH_VARARGS, (char *)"Baseboard Data" },
- { (char *)"chassis", dmidecode_get_chassis, METH_VARARGS, (char *)"Chassis Data" },
- { (char *)"processor", dmidecode_get_processor, METH_VARARGS, (char *)"Processor Data" },
- { (char *)"memory", dmidecode_get_memory, METH_VARARGS, (char *)"Memory Data" },
- { (char *)"cache", dmidecode_get_cache, METH_VARARGS, (char *)"Cache Data" },
- { (char *)"connector", dmidecode_get_connector, METH_VARARGS, (char *)"Connector Data" },
- { (char *)"slot", dmidecode_get_slot, METH_VARARGS, (char *)"Slot Data" },
-
- { (char *)"type", dmidecode_get_type, METH_VARARGS, (char *)"By Type" },
-
- { NULL, NULL, 0, NULL }
+ {(char *)"dump", dmidecode_dump, METH_NOARGS, (char *)"Dump dmidata to set file"},
+ {(char *)"get_dev", dmidecode_get_dev, METH_NOARGS,
+ (char *)"Get an alternative memory device file"},
+ {(char *)"set_dev", dmidecode_set_dev, METH_O,
+ (char *)"Set an alternative memory device file"},
+
+ {(char *)"bios", dmidecode_get_bios, METH_VARARGS, (char *)"BIOS Data"},
+ {(char *)"system", dmidecode_get_system, METH_VARARGS, (char *)"System Data"},
+ {(char *)"baseboard", dmidecode_get_baseboard, METH_VARARGS, (char *)"Baseboard Data"},
+ {(char *)"chassis", dmidecode_get_chassis, METH_VARARGS, (char *)"Chassis Data"},
+ {(char *)"processor", dmidecode_get_processor, METH_VARARGS, (char *)"Processor Data"},
+ {(char *)"memory", dmidecode_get_memory, METH_VARARGS, (char *)"Memory Data"},
+ {(char *)"cache", dmidecode_get_cache, METH_VARARGS, (char *)"Cache Data"},
+ {(char *)"connector", dmidecode_get_connector, METH_VARARGS, (char *)"Connector Data"},
+ {(char *)"slot", dmidecode_get_slot, METH_VARARGS, (char *)"Slot Data"},
+
+ {(char *)"QuerySection", dmidecode_get_section, METH_O,
+ (char *) "Queries the DMI data structure for a given section name. A section"
+ "can often contain several DMI type elements"
+ },
+
+ {(char *)"type", dmidecode_get_type, METH_VARARGS, (char *)"By Type"},
+
+ {(char *)"QueryTypeId", dmidecode_get_type, METH_VARARGS,
+ (char *) "Queries the DMI data structure for a specific DMI type."
+ },
+
+ {(char *)"pythonmap", dmidecode_set_pythonxmlmap, METH_O,
+ (char *) "Use another python dict map definition. The default file is " PYTHON_XML_MAP},
+
+ {(char *)"xmlapi", dmidecode_xmlapi, METH_KEYWORDS,
+ (char *) "Internal API for retrieving data as raw XML data"},
+
+ {NULL, NULL, 0, NULL}
};
-PyMODINIT_FUNC initdmidecode(void) {
- init();
+void destruct_options(void *ptr)
+{
+ options *opt = (options *) ptr;
+
+ if( opt->mappingxml != NULL ) {
+ xmlFreeDoc(opt->mappingxml);
+ opt->mappingxml = NULL;
+ }
+
+ if( opt->python_xml_map != NULL ) {
+ free(opt->python_xml_map);
+ opt->python_xml_map = NULL;
+ }
+
+ if( opt->dmiversion_n != NULL ) {
+ xmlFreeNode(opt->dmiversion_n);
+ opt->dmiversion_n = NULL;
+ }
+
+ if( opt->dumpfile != NULL ) {
+ free(opt->dumpfile);
+ opt->dumpfile = NULL;
+ }
+
+ free(ptr);
+}
+
+
+PyMODINIT_FUNC initdmidecodemod(void)
+{
+ char *dmiver = NULL;
+ PyObject *module = NULL;
+ PyObject *version = NULL;
+ options *opt;
+
+ xmlInitParser();
+ xmlXPathInit();
+
+ opt = (options *) malloc(sizeof(options)+2);
+ memset(opt, 0, sizeof(options)+2);
+ init(opt);
+ module = Py_InitModule3((char *)"dmidecodemod", DMIDataMethods,
+ "Python extension module for dmidecode");
- PyObject *module = Py_InitModule3((char *)"dmidecode", DMIDataMethods, "Python extension module for dmidecode");
+ version = PyString_FromString(VERSION);
+ Py_INCREF(version);
+ PyModule_AddObject(module, "version", version);
- PyObject *version = PyString_FromString("2.10");
- Py_INCREF(version);
- PyModule_AddObject(module, "version", version);
+ opt->dmiversion_n = dmidecode_get_version(opt);
+ dmiver = dmixml_GetContent(opt->dmiversion_n);
+ PyModule_AddObject(module, "dmi", dmiver ? PyString_FromString(dmiver) : Py_None);
- PyObject *dmi_version = NULL;
- dmidecode_set_version(&dmi_version);
- PyModule_AddObject(module, "dmi", dmi_version?dmi_version:Py_None);
+ // Assign this options struct to the module as well with a destructor, that way it will
+ // clean up the memory for us.
+ PyModule_AddObject(module, "options", PyCObject_FromVoidPtr(opt, destruct_options));
+ global_options = opt;
}
diff --git a/src/dmidecodemodule.h b/src/dmidecodemodule.h
index 2b2bde7..c0be3a1 100644
--- a/src/dmidecodemodule.h
+++ b/src/dmidecodemodule.h
@@ -1,3 +1,44 @@
+/*. ******* coding:utf-8 AUTOHEADER START v1.1 *******
+ *. vim: fileencoding=utf-8 syntax=c sw=8 ts=8 et
+ *.
+ *. © 2007-2009 Nima Talebi <nima@autonomy.net.au>
+ *. © 2009 David Sommerseth <davids@redhat.com>
+ *. © 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *. © 2000-2002 Alan Cox <alan@redhat.com>
+ *.
+ *. This file is part of Python DMI-Decode.
+ *.
+ *. Python DMI-Decode is free software: you can redistribute it and/or modify
+ *. it under the terms of the GNU General Public License as published by
+ *. the Free Software Foundation, either version 2 of the License, or
+ *. (at your option) any later version.
+ *.
+ *. Python DMI-Decode is distributed in the hope that it will be useful,
+ *. but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *. GNU General Public License for more details.
+ *.
+ *. You should have received a copy of the GNU General Public License
+ *. along with Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ *.
+ *. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ *. EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ *. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *.
+ *. ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ *. AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ *.
+ *. $AutoHeaderSerial::20090522 $
+ *. ******* AUTOHEADER END v1.1 ******* */
+
+
#include <Python.h>
#include <structmember.h>
@@ -22,43 +63,15 @@
#include "dmihelper.h"
-//extern void dmi_decode(struct dmi_header *h, u16 ver, PyObject* pydata);
-extern PyObject *dmi_dump(struct dmi_header *h);
-extern PyObject* dmi_decode(struct dmi_header *h, u16 ver);
-extern int address_from_efi(size_t *address);
-extern void to_dmi_header(struct dmi_header *h, u8 *data);
-extern void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem);
-extern int smbios_decode(u8 *buf, const char *devmem, PyObject* pydata);
-extern int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata);
-extern int smbios_decode_set_version(u8 *buf, const char *devmem, PyObject** pydata);
-extern int legacy_decode_set_version(u8 *buf, const char *devmem, PyObject** pydata);
-extern void *mem_chunk(size_t base, size_t len, const char *devmem);
+xmlNode *dmidecode_get_version(options *);
-extern u8 *parse_opt_type(u8 *p, const char *arg);
-static const u8 opt_type_bios[] = { 0, 13, 255 };
-static const u8 opt_type_system[] = { 1, 12, 15, 23, 32, 255 };
-static const u8 opt_type_baseboard[] = { 2, 10, 255 };
-static const u8 opt_type_chassis[] = { 3, 255 };
-static const u8 opt_type_processor[] = { 4, 255 };
-static const u8 opt_type_memory[] = { 5, 6, 16, 17, 255 };
-static const u8 opt_type_cache[] = { 7, 255 };
-static const u8 opt_type_connector[] = { 8, 255 };
-static const u8 opt_type_slot[] = { 9, 255 };
-struct type_keyword {
- const char *keyword;
- const u8 *type;
-};
-
-static const struct type_keyword opt_type_keyword[] = {
- { "bios", opt_type_bios },
- { "system", opt_type_system },
- { "baseboard", opt_type_baseboard },
- { "chassis", opt_type_chassis },
- { "processor", opt_type_processor },
- { "memory", opt_type_memory },
- { "cache", opt_type_cache },
- { "connector", opt_type_connector },
- { "slot", opt_type_slot },
-};
+extern void dmi_dump(xmlNode *node, struct dmi_header *h);
+extern int address_from_efi(size_t * address);
+extern void to_dmi_header(struct dmi_header *h, u8 * data);
+extern int smbios_decode(int type, u8 *buf, const char *devmem, xmlNode *node);
+extern int legacy_decode(int type, u8 *buf, const char *devmem, xmlNode *node);
+extern xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem);
+extern xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem);
+extern void *mem_chunk(size_t base, size_t len, const char *devmem);
PyMODINIT_FUNC initdmidecode(void);
diff --git a/src/dmidump.c b/src/dmidump.c
new file mode 100644
index 0000000..a07c975
--- /dev/null
+++ b/src/dmidump.c
@@ -0,0 +1,168 @@
+/* Simple program for dumping DMI/SMBIOS data
+ * Based on code from python-dmidecode/dmidecode.c
+ *
+ * Copyright 2009 David Sommerseth <davids@redhat.com>
+ * Copyright 2002-2008 Jean Delvare <khali@linux-fr.org>
+ * Copyright 2000-2002 Alan Cox <alan@redhat.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "types.h"
+#include "util.h"
+
+#include "dmidump.h"
+#include "efi.h"
+
+/*
+ * Build a crafted entry point with table address hard-coded to 32,
+ * as this is where we will put it in the output file. We adjust the
+ * DMI checksum appropriately. The SMBIOS checksum needs no adjustment.
+ */
+static void overwrite_dmi_address(u8 * buf)
+{
+ buf[0x05] += buf[0x08] + buf[0x09] + buf[0x0A] + buf[0x0B] - 32;
+ buf[0x08] = 32;
+ buf[0x09] = 0;
+ buf[0x0A] = 0;
+ buf[0x0B] = 0;
+}
+
+int dumpling(u8 * buf, const char *dumpfile, u8 mode)
+{
+ u32 base;
+ u16 len;
+
+ if(mode == NON_LEGACY) {
+ if(!checksum(buf, buf[0x05]) || !memcmp(buf + 0x10, "_DMI_", 5) == 0 ||
+ !checksum(buf + 0x10, 0x0F))
+ return 0;
+ base = DWORD(buf + 0x18);
+ len = WORD(buf + 0x16);
+ } else {
+ if(!checksum(buf, 0x0F))
+ return 0;
+ base = DWORD(buf + 0x08);
+ len = WORD(buf + 0x06);
+ }
+
+ u8 *buff;
+
+ if((buff = mem_chunk(base, len, DEFAULT_MEM_DEV)) != NULL) {
+ //. Part 1.
+#ifdef NDEBUG
+ printf("# Writing %d bytes to %s.\n", len, dumpfile);
+#endif
+ write_dump(32, len, buff, dumpfile, 0);
+ free(buff);
+
+ //. Part 2.
+ if(mode != LEGACY) {
+ u8 crafted[32];
+
+ memcpy(crafted, buf, 32);
+ overwrite_dmi_address(crafted + 0x10);
+#ifdef NDEBUG
+ printf("# Writing %d bytes to %s.\n", crafted[0x05], dumpfile);
+#endif
+ write_dump(0, crafted[0x05], crafted, dumpfile, 1);
+ } else {
+ u8 crafted[16];
+
+ memcpy(crafted, buf, 16);
+ overwrite_dmi_address(crafted);
+#ifdef NDEBUG
+ printf("# Writing %d bytes to %s.\n", 0x0F, dumpfile);
+#endif
+ write_dump(0, 0x0F, crafted, dumpfile, 1);
+ }
+ } else {
+ fprintf(stderr, "Failed to read table, sorry.\n");
+ }
+
+ //. TODO: Cleanup
+ return 1;
+}
+
+
+int dump(const char *memdev, const char *dumpfile)
+{
+ /* On success, return found, otherwise return -1 */
+ int ret = 0;
+ int found = 0;
+ size_t fp;
+ int efi;
+ u8 *buf;
+
+ /* First try EFI (ia64, Intel-based Mac) */
+ efi = address_from_efi(&fp);
+ if(efi == EFI_NOT_FOUND) {
+ /* Fallback to memory scan (x86, x86_64) */
+ if((buf = mem_chunk(0xF0000, 0x10000, memdev)) != NULL) {
+ for(fp = 0; fp <= 0xFFF0; fp += 16) {
+ if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) {
+ if(dumpling(buf + fp, dumpfile, NON_LEGACY))
+ found++;
+ fp += 16;
+ } else if(memcmp(buf + fp, "_DMI_", 5) == 0) {
+ if(dumpling(buf + fp, dumpfile, LEGACY))
+ found++;
+ }
+ }
+ } else
+ ret = -1;
+ } else if(efi == EFI_NO_SMBIOS) {
+ ret = -1;
+ } else {
+ if((buf = mem_chunk(fp, 0x20, memdev)) == NULL)
+ ret = -1;
+ else if(dumpling(buf, dumpfile, NON_LEGACY))
+ found++;
+ }
+
+ if(ret == 0) {
+ free(buf);
+ if(!found) {
+ ret = -1;
+ }
+ }
+
+ return ret == 0 ? found : ret;
+}
+
+
+#ifdef _DMIDUMP_MAIN_
+int main(int argc, char **argv)
+{
+ if( argc != 3 ) {
+ fprintf(stderr, "Usage: %s </dev/mem device> <destfile>\n", argv[0]);
+ return 1;
+ }
+ dump(argv[1], argv[2]);
+
+ return 0;
+}
+#endif
diff --git a/src/dmidump.h b/src/dmidump.h
new file mode 100644
index 0000000..3c12248
--- /dev/null
+++ b/src/dmidump.h
@@ -0,0 +1,37 @@
+/* Simple program for dumping DMI/SMBIOS data
+ * Based on code from python-dmidecode/dmidecode.c
+ *
+ * Copyright 2009 David Sommerseth <davids@redhat.com>
+ * Copyright 2002-2008 Jean Delvare <khali@linux-fr.org>
+ * Copyright 2000-2002 Alan Cox <alan@redhat.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+#ifndef _DMIDUMP_H
+
+#define NON_LEGACY 0
+#define LEGACY 1
+
+int dump(const char *memdev, const char *dumpfile);
+
+#endif
diff --git a/src/dmierror.c b/src/dmierror.c
new file mode 100644
index 0000000..d64b4b9
--- /dev/null
+++ b/src/dmierror.c
@@ -0,0 +1,79 @@
+/* Simpilfied and improved Python Error/Exception functions
+ *
+ * 2009 (C) David Sommerseth <davids@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+/**
+ * @file dmierror.h
+ * @brief Simpilfied and improved Python Error/Exception functions
+ * @author David Sommerseth <davids@redhat.com>
+ */
+
+#include <Python.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+// #define PRINT_ERRORS // Enable for copy of error messages to stderr
+
+/**
+ * A more flexible function for setting error messages. This function
+ * is called via PyReturnError(...) macro which also returns NULL.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param PyObject* A Python Exception object
+ * @param const char* Error message to follow the exception, may be string formated
+ *
+ */
+void _pyReturnError(void *exception, const char *fname, int line, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf = NULL;
+
+ va_start(ap, fmt);
+ buf = (char *) malloc(4098);
+ memset(buf, 0, 4098);
+
+ if( buf == NULL ) {
+ // Backup routine if we can't get the needed memory
+ fprintf(stderr, "\n\n** ERROR ALLOCATING ERROR MESSAGE BUFFER\n\n");
+ fprintf(stderr, "** ERROR: [%s:%i] ", fname, line);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ return;
+ }
+
+ // Set the error state and message
+ snprintf(buf, 4096, "[%s:%i] %s", fname, line, fmt);
+ PyErr_Format(exception, buf, ap);
+
+#ifdef PRINT_ERRORS
+ fprintf(stderr, "\n**\n** ERROR: ");
+ vfprintf(stderr, buf, ap);
+ fprintf(stderr, "\n**\n\n");
+#endif
+ va_end(ap);
+ free(buf); buf = NULL;
+}
+
diff --git a/src/dmierror.h b/src/dmierror.h
new file mode 100644
index 0000000..0fa0858
--- /dev/null
+++ b/src/dmierror.h
@@ -0,0 +1,54 @@
+/* Simpilfied and improved Python Error/Exception functions
+ *
+ * 2009 (C) David Sommerseth <davids@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+/**
+ * @file dmierror.h
+ * @brief Simpilfied and improved Python Error/Exception functions
+ * @author David Sommerseth <davids@redhat.com>
+ */
+
+
+#ifndef DMIERROR_H
+#define DMIERROR_H
+
+#include <stdarg.h>
+
+void _pyReturnError(PyObject *exception, const char *fname, int line, const char *msgfmt, ...);
+
+/**
+ * A more flexible function for setting error messages.
+ * This macro is the one which is supposed to be used in programs, as it will
+ * also exit the calling function with NULL.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param PyObject* A Python Exception object
+ * @param const char* Error message to follow the exception, may be string formated
+ */
+#define PyReturnError(Exception, msg...) { \
+ _pyReturnError(Exception, __FILE__, __LINE__,## msg); \
+ return NULL; \
+ }
+
+
+#endif
diff --git a/src/dmihelper.c b/src/dmihelper.c
deleted file mode 100644
index 6d52e04..0000000
--- a/src/dmihelper.c
+++ /dev/null
@@ -1,115 +0,0 @@
-#include <stdio.h>
-#include <strings.h>
-
-#include "dmihelper.h"
-
-/*
-dmi_minor* dmiAppendObject(long code, char const *key, const char *format, ...) {
- static dmi_minor* last = NULL;
-
- //. int minor = code&0x00FF;
- //. int major = code>>8;
-
- va_list arg;
- va_start(arg, format);
-
- dmi_minor *o = (dmi_minor *)malloc(sizeof(dmi_minor));
- o->next = last;
- o->id = code;
- o->major = (dmi_codes_major *)&dmiCodesMajor[map_maj[code>>8]];
- o->key = (char *)key;
-
- if((format != NULL)&&(vsnprintf(o->value, MAXVAL-1, format, arg) > MAXVAL)) {
- free(o);
- o = NULL;
- //. TODO: Make this a python exception.
- printf("dmidecode: Internal (python module) error; Value too long.\n");
- }
-
- last = o;
- va_end(arg); // cleanup
-
- return o;
-}
-*/
-
-int dmiSetItem(PyObject* dict, const char *key, const char *format, ...) {
- va_list arg;
- va_start(arg, format);
- char buffer[2048];
- vsprintf(buffer, format, arg);
- va_end(arg);
- //printf("DEBUG: Setting k:%s, f:%s s:%s...", key, format, buffer);
- PyDict_SetItem(dict, PyString_FromString(key), PyString_FromString(buffer));
- //printf("Done.\n");
- return 0;
-}
-
-
-/* NOTE: Decomissioned helper function...
-void dmiAppendData(PyObject *pydata, const int count) {
- dmi_minor* last = dmiAppendObject(count, "JUNK", "NODATA");
-
- const char *id = last->major->id;
- PyObject *_key, *_val;
-
- PyObject *pymajor = PyDict_New();
-
- _key = PyString_FromString("code");
- _val = PyInt_FromLong((long)last->major->code);
- PyDict_SetItem(pymajor, _key, _val);
- Py_DECREF(_key);
- Py_DECREF(_val);
-
- _key = PyString_FromString("id");
- _val = PyString_FromString(last->major->id);
- PyDict_SetItem(pymajor, _key, _val);
- Py_DECREF(_key);
- Py_DECREF(_val);
-
- _key = PyString_FromString("name");
- _val = PyString_FromString(last->major->desc);
- PyDict_SetItem(pymajor, _key, _val);
- Py_DECREF(_key);
- Py_DECREF(_val);
-
- PyObject *pyminor = PyDict_New();
- while((last = last->next)) {
- //printf("%d:<%s, %s> | %ld:[%s => %s]\n", last->major->code, last->major->id, last->major->desc, last->id, last->key, last->value);
- _key = PyString_FromString(last->key);
- _val = PyString_FromString(last->value);
- PyDict_SetItem(pyminor, _key, _val);
- Py_DECREF(_key);
- Py_DECREF(_val);
- }
- _key = PyString_FromString("data");
- PyDict_SetItem(pymajor, _key, pyminor);
- Py_DECREF(_key);
- Py_DECREF(pyminor);
-
- _key = PyString_FromString(id);
- PyDict_SetItem(pydata, _key, pymajor);
- Py_DECREF(_key);
- Py_DECREF(pymajor);
-}
-*/
-
-/* NOTE: Decomissioned helper function...
-int catsprintf(char *buf, const char *format, ...) {
- if(format == NULL) {
- bzero(buf, strlen(buf));
- return 0;
- }
-
- va_list arg; // will point to each unnamed argument in turn
- va_start(arg, format); // point to first element after fmt
-
- char b[8192];
- int c = vsprintf (b, format, arg);
-
- strcat(buf, b);
- va_end(arg); // cleanp
-
- return c;
-}
-*/
diff --git a/src/dmihelper.h b/src/dmihelper.h
index a056eb2..d89c024 100644
--- a/src/dmihelper.h
+++ b/src/dmihelper.h
@@ -1,3 +1,44 @@
+/*. ******* coding:utf-8 AUTOHEADER START v1.1 *******
+ *. vim: fileencoding=utf-8 syntax=c sw=8 ts=8 et
+ *.
+ *. © 2007-2009 Nima Talebi <nima@autonomy.net.au>
+ *. © 2009 David Sommerseth <davids@redhat.com>
+ *. © 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *. © 2000-2002 Alan Cox <alan@redhat.com>
+ *.
+ *. This file is part of Python DMI-Decode.
+ *.
+ *. Python DMI-Decode is free software: you can redistribute it and/or modify
+ *. it under the terms of the GNU General Public License as published by
+ *. the Free Software Foundation, either version 2 of the License, or
+ *. (at your option) any later version.
+ *.
+ *. Python DMI-Decode is distributed in the hope that it will be useful,
+ *. but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *. GNU General Public License for more details.
+ *.
+ *. You should have received a copy of the GNU General Public License
+ *. along with Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ *.
+ *. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ *. EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ *. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *.
+ *. ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ *. AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ *.
+ *. $AutoHeaderSerial::20090522 $
+ *. ******* AUTOHEADER END v1.1 ******* */
+
+
#ifndef HELPER
#define HELPER 1
@@ -9,106 +50,84 @@
#include <stdlib.h>
#include <assert.h>
+#include <libxml/tree.h>
+
#include "types.h"
#define MAXVAL 1024
-static const int map_maj[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
- 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
-};
-
typedef struct _dmi_codes_major {
- const unsigned short code;
- const char *id;
- const char *desc;
+ const unsigned short code;
+ const char *id;
+ const char *desc;
+ const char *tagname;
} dmi_codes_major;
static const dmi_codes_major dmiCodesMajor[] = {
- { 0, "3.3.1", "BIOS Information" },
- { 1, "3.3.2", "System Information" },
- { 2, "3.3.3", "Base Board Information" },
- { 3, "3.3.4", "Chassis Information" },
- { 4, "3.3.5", "Processor Information" },
- { 5, "3.3.6", "Memory Controller Information" },
- { 6, "3.3.7", "Memory Module Information" },
- { 7, "3.3.8", "Cache Information" },
- { 8, "3.3.9", "Port Connector Information" },
- { 9, "3.3.10", "System Slots" },
- { 10, "3.3.11", "On Board Devices Information" },
- { 11, "3.3.12", "OEM Strings" },
- { 12, "3.3.13", "System Configuration Options" },
- { 13, "3.3.14", "BIOS Language Information" },
- { 14, "3.3.15", "Group Associations" },
- { 15, "3.3.16", "System Event Log" },
- { 16, "3.3.17", "Physical Memory Array" },
- { 17, "3.3.18", "Memory Device" },
- { 18, "3.3.19", "32-bit Memory Error Information" },
- { 19, "3.3.20", "Memory Array Mapped Address" },
- { 20, "3.3.21", "Memory Device Mapped Address" },
- { 21, "3.3.22", "Built-in Pointing Device" },
- { 22, "3.3.23", "Portable Battery" },
- { 23, "3.3.24", "System Reset" },
- { 24, "3.3.25", "Hardware Security" },
- { 25, "3.3.26", "System Power Controls" },
- { 26, "3.3.27", "Voltage Probe" },
- { 27, "3.3.28", "Cooling Device" },
- { 28, "3.3.29", "Temperature Probe" },
- { 29, "3.3.30", "Electrical Current Probe" },
- { 30, "3.3.31", "Out-of-band Remote Access" },
- { 31, "3.3.32", "Boot Integrity Services Entry Point" },
- { 32, "3.3.33", "System Boot Information" },
- { 33, "3.3.34", "64-bit Memory Error Information" },
- { 34, "3.3.35", "Management Device" },
- { 35, "3.3.36", "Management Device Component" },
- { 36, "3.3.37", "Management Device Threshold Data" },
- { 37, "3.3.38", "Memory Channel" },
- { 38, "3.3.39", "IPMI Device Information" },
- { 39, "3.3.40", "System Power Supply" },
- { 40, "3.3.41", "-------------------" },
- { 41, "3.3.42", "-------------------" },
- { 126, "3.3.41", "Inactive" },
- { 127, "3.3.42", "End Of Table" },
+ {0, "3.3.1", "BIOS Information", "BIOSinfo"},
+ {1, "3.3.2", "System Information", "SystemInfo"},
+ {2, "3.3.3", "Base Board Information", "BaseBoardInfo"},
+ {3, "3.3.4", "Chassis Information", "ChassisInfo"},
+ {4, "3.3.5", "Processor Information", "ProcessorInfo"},
+ {5, "3.3.6", "Memory Controller Information", "MemoryCtrlInfo"},
+ {6, "3.3.7", "Memory Module Information", "MemoryModuleInfo"},
+ {7, "3.3.8", "Cache Information", "CacheInfo"},
+ {8, "3.3.9", "Port Connector Information", "PortConnectorInfo"},
+ {9, "3.3.10", "System Slots", "SystemSlots"},
+ {10, "3.3.11", "On Board Devices Information", "OnBoardDevicesInfo"},
+ {11, "3.3.12", "OEM Strings", "OEMstrings"},
+ {12, "3.3.13", "System Configuration Options", "SysConfigOptions"},
+ {13, "3.3.14", "BIOS Language Information", "BIOSlanguage"},
+ {14, "3.3.15", "Group Associations", "GroupAssoc"},
+ {15, "3.3.16", "System Event Log", "SysEventLog"},
+ {16, "3.3.17", "Physical Memory Array", "PhysicalMemoryArray"},
+ {17, "3.3.18", "Memory Device", "MemoryDevice"},
+ {18, "3.3.19", "32-bit Memory Error Information", "MemoryErrorInfo"},
+ {19, "3.3.20", "Memory Array Mapped Address", "MemoryArrayMappedAddress"},
+ {20, "3.3.21", "Memory Device Mapped Address", "MemoryDeviceMappedAddress"},
+ {21, "3.3.22", "Built-in Pointing Device", "BuiltIntPointingDevice"},
+ {22, "3.3.23", "Portable Battery", "PortableBattery"},
+ {23, "3.3.24", "System Reset", "SystemReset"},
+ {24, "3.3.25", "Hardware Security", "HardwareSecurity"},
+ {25, "3.3.26", "System Power Controls", "SystemPowerCtrls"},
+ {26, "3.3.27", "Voltage Probe", "Probe"},
+ {27, "3.3.28", "Cooling Device", "CoolingDevice"},
+ {28, "3.3.29", "Temperature Probe", "Probe"},
+ {29, "3.3.30", "Electrical Current Probe", "Probe"},
+ {30, "3.3.31", "Out-of-band Remote Access", "RemoteAccess"},
+ {31, "3.3.32", "Boot Integrity Services Entry Point", "BootIntegrity"},
+ {32, "3.3.33", "System Boot Information", "SystemBootInfo"},
+ {33, "3.3.34", "64-bit Memory Error Information", "MemoryErrorInfo"},
+ {34, "3.3.35", "Management Device", "ManagementDevice"},
+ {35, "3.3.36", "Management Device Component", "ManagementDevice"},
+ {36, "3.3.37", "Management Device Threshold Data", "ManagementDevice"},
+ {37, "3.3.38", "Memory Channel", "MemoryChannel"},
+ {38, "3.3.39", "IPMI Device Information", "IPMIdeviceInfo"},
+ {39, "3.3.40", "System Power Supply", "SystemPowerSupply"},
+ {40, "3.3.41", "-------------------", "Unknown"},
+ {41, "3.3.42", "-------------------", "Unknown"},
+ {126, "3.3.41", "Inactive", "Inactive"},
+ {127, "3.3.42", "End Of Table", "EndOfTable"},
+ {-1, NULL, NULL, NULL}
};
typedef struct _dmi_minor {
- long id;
- dmi_codes_major* major;
- char *key;
- char value[MAXVAL];
- struct _dmi_minor* next;
+ long id;
+ dmi_codes_major *major;
+ char *key;
+ char value[MAXVAL];
+ struct _dmi_minor *next;
} dmi_minor;
-void dmiAppendData(PyObject *pydata, const int count);
-int dmiSetItem(PyObject* dict, const char *key, const char *format, ...);
-//dmi_minor* dmiAppendObject(long code, char const *key, const char *format, ...);
-
-/*** dmiopt.h ***/
-struct string_keyword {
- const char *keyword;
- u8 type;
- u8 offset;
-};
-
/*** dmiopt.h ***/
typedef struct _options {
- const char *devmem;
- unsigned int flags;
- u8 *type;
- const struct string_keyword *string;
- PyObject *dumpfile;
+ const char *devmem;
+ unsigned int flags;
+ int type;
+ xmlDoc *mappingxml;
+ char *python_xml_map;
+ xmlNode *dmiversion_n;
+ char *dumpfile;
} options;
-extern options opt;
#endif
diff --git a/src/dmioem.c b/src/dmioem.c
index a2fd2a2..361810a 100644
--- a/src/dmioem.c
+++ b/src/dmioem.c
@@ -1,3 +1,4 @@
+
/*
* Decoding of OEM-specific entries
* This file is part of the dmidecode project.
@@ -32,7 +33,7 @@
enum DMI_VENDORS { VENDOR_UNKNOWN, VENDOR_HP };
-static enum DMI_VENDORS dmi_vendor=VENDOR_UNKNOWN;
+static enum DMI_VENDORS dmi_vendor = VENDOR_UNKNOWN;
/*
* Remember the system vendor for later use. We only actually store the
@@ -41,8 +42,8 @@ static enum DMI_VENDORS dmi_vendor=VENDOR_UNKNOWN;
*/
void dmi_set_vendor(const char *s)
{
- if(strcmp(s, "HP")==0)
- dmi_vendor=VENDOR_HP;
+ if(strcmp(s, "HP") == 0)
+ dmi_vendor = VENDOR_HP;
}
/*
@@ -53,63 +54,60 @@ void dmi_set_vendor(const char *s)
static int dmi_decode_hp(struct dmi_header *h)
{
- u8 *data=h->data;
- int nic, ptr;
+ u8 *data = h->data;
+ int nic, ptr;
- switch(h->type)
- {
- case 204:
- /*
- * Vendor Specific: HP ProLiant System/Rack Locator
- */
- printf("HP ProLiant System/Rack Locator\n");
- if(h->length<0x0B) break;
- printf("\tRack Name: %s\n", dmi_string(h, data[0x04]));
- printf("\tEnclosure Name: %s\n", dmi_string(h, data[0x05]));
- printf("\tEnclosure Model: %s\n", dmi_string(h, data[0x06]));
- printf("\tEnclosure Serial: %s\n", dmi_string(h, data[0x0A]));
- printf("\tEnclosure Bays: %d\n", data[0x08]);
- printf("\tServer Bay: %s\n", dmi_string(h, data[0x07]));
- printf("\tBays Filled: %d\n", data[0x09]);
- break;
+ switch (h->type) {
+ case 204:
+ /*
+ * Vendor Specific: HP ProLiant System/Rack Locator
+ */
+ printf("HP ProLiant System/Rack Locator\n");
+ if(h->length < 0x0B)
+ break;
+ printf("\tRack Name: %s\n", dmi_string(h, data[0x04]));
+ printf("\tEnclosure Name: %s\n", dmi_string(h, data[0x05]));
+ printf("\tEnclosure Model: %s\n", dmi_string(h, data[0x06]));
+ printf("\tEnclosure Serial: %s\n", dmi_string(h, data[0x0A]));
+ printf("\tEnclosure Bays: %d\n", data[0x08]);
+ printf("\tServer Bay: %s\n", dmi_string(h, data[0x07]));
+ printf("\tBays Filled: %d\n", data[0x09]);
+ break;
- case 209:
- case 221:
- /*
- * Vendor Specific: HP ProLiant NIC MAC Information
- *
- * This prints the BIOS NIC number,
- * PCI bus/device/function, and MAC address
- */
- printf(h->type==221?
- "HP BIOS iSCSI NIC PCI and MAC Information\n":
- "HP BIOS NIC PCI and MAC Information\n");
- nic=1;
- ptr=4;
- while(h->length>=ptr+8)
- {
- if(data[ptr]==0x00 && data[ptr+1]==0x00)
- printf("\tNIC %d: Disabled\n", nic);
- else if(data[ptr]==0xFF && data[ptr+1]==0xFF)
- printf("\tNIC %d: Not Installed\n", nic);
- else
- {
- printf("\tNIC %d: PCI device %02x:%02x.%x, "
- "MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
- nic, data[ptr+1], data[ptr]>>3, data[ptr]&7,
- data[ptr+2], data[ptr+3],
- data[ptr+4], data[ptr+5],
- data[ptr+6], data[ptr+7]);
- }
- nic++;
- ptr+=8;
- }
- break;
+ case 209:
+ case 221:
+ /*
+ * Vendor Specific: HP ProLiant NIC MAC Information
+ *
+ * This prints the BIOS NIC number,
+ * PCI bus/device/function, and MAC address
+ */
+ printf(h->type == 221 ?
+ "HP BIOS iSCSI NIC PCI and MAC Information\n" :
+ "HP BIOS NIC PCI and MAC Information\n");
+ nic = 1;
+ ptr = 4;
+ while(h->length >= ptr + 8) {
+ if(data[ptr] == 0x00 && data[ptr + 1] == 0x00)
+ printf("\tNIC %d: Disabled\n", nic);
+ else if(data[ptr] == 0xFF && data[ptr + 1] == 0xFF)
+ printf("\tNIC %d: Not Installed\n", nic);
+ else {
+ printf("\tNIC %d: PCI device %02x:%02x.%x, "
+ "MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
+ nic, data[ptr + 1], data[ptr] >> 3, data[ptr] & 7,
+ data[ptr + 2], data[ptr + 3],
+ data[ptr + 4], data[ptr + 5], data[ptr + 6], data[ptr + 7]);
+ }
+ nic++;
+ ptr += 8;
+ }
+ break;
- default:
- return 0;
- }
- return 1;
+ default:
+ return 0;
+ }
+ return 1;
}
/*
@@ -118,11 +116,10 @@ static int dmi_decode_hp(struct dmi_header *h)
*/
int dmi_decode_oem(struct dmi_header *h)
{
- switch(dmi_vendor)
- {
- case VENDOR_HP:
- return dmi_decode_hp(h);
- default:
- return 0;
- }
+ switch (dmi_vendor) {
+ case VENDOR_HP:
+ return dmi_decode_hp(h);
+ default:
+ return 0;
+ }
}
diff --git a/src/dmioem.h b/src/dmioem.h
index 00483f2..b1b4af8 100644
--- a/src/dmioem.h
+++ b/src/dmioem.h
@@ -1,3 +1,4 @@
+
/*
* Decoding of OEM-specific entries
* This file is part of the dmidecode project.
diff --git a/src/dmixml.c b/src/dmixml.c
new file mode 100644
index 0000000..5d9f1a1
--- /dev/null
+++ b/src/dmixml.c
@@ -0,0 +1,360 @@
+/* Simplified XML API for dmidecode
+ *
+ * Copyright 2009 David Sommerseth <davids@redhat.com>
+ * Copyright 2009 Nima Talebi <nima@autonomy.net.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+/**
+ * @file dmixml.c
+ * @brief Helper functions for XML nodes and documents.
+ * @author David Sommerseth <davids@redhat.com>
+ * @author Nima Talebi <nima@autonomy.net.au>
+ */
+
+
+
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xmlstring.h>
+
+#include "dmixml.h"
+
+/**
+ * Internal function for dmixml_* functions. The function will allocate a buffer and populate it
+ * according to the format string
+ * @author David Sommerseth <davids@redhat.com>
+ * @param size_t The requested size for the new buffer
+ * @param const char* The format of the string being built (uses vsnprintf())
+ * @param ... The needed variables to build up the string
+ * @return xmlChar* Pointer to the buffer of the string
+ */
+xmlChar *dmixml_buildstr(size_t len, const char *fmt, va_list ap) {
+ xmlChar *ret = NULL, *xmlfmt = NULL;
+ xmlChar *ptr = NULL;
+
+ ret = (xmlChar *) malloc(len+2);
+ assert( ret != NULL );
+ memset(ret, 0, len+2);
+
+ xmlfmt = xmlCharStrdup(fmt);
+ assert( xmlfmt != NULL );
+
+ xmlStrVPrintf(ret, len, xmlfmt, ap);
+ free(xmlfmt);
+
+ // Right trim the string
+ ptr = ret + xmlStrlen(ret)-1;
+ while( (ptr >= ret) && (*ptr == ' ') ) {
+ *ptr = 0;
+ ptr--;
+ }
+ return ret;
+}
+
+
+/**
+ * Add an XML property/attribute to the given XML node
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* A pointer to the xmlNode being updated
+ * @param const char* The name of the attribute
+ * @param const char* Value of the string (can make use of string formating options)
+ * @return xmlAttr* Pointer to the new attribute node. On errors an assert is
+ * triggered and return value should be NULL.
+ */
+xmlAttr *dmixml_AddAttribute(xmlNode *node, const char *atrname, const char *fmt, ...)
+{
+ xmlChar *val_s = NULL, *atrname_s = NULL;
+ xmlAttr *res = NULL;
+ va_list ap;
+
+ if( (node == NULL) || (atrname == NULL) || (fmt == NULL) ) {
+ return NULL;
+ }
+
+ atrname_s = xmlCharStrdup(atrname);
+ assert( atrname_s != NULL );
+
+ va_start(ap, fmt);
+ val_s = dmixml_buildstr(2048, fmt, ap);
+ va_end(ap);
+
+ res = xmlNewProp(node, atrname_s,
+ (xmlStrcmp(val_s, (xmlChar *) "(null)") == 0 ? NULL : val_s));
+
+ free(atrname_s);
+ free(val_s);
+
+ assert( res != NULL );
+ return res;
+}
+
+
+/**
+ * Adds a new XML tag to the given node with the given tag name and value.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* Pointer to the parent node for this new node
+ * @param const char* Name of the new tag
+ * @param const char* Contents of the new tag (can make use of string formating options)
+ * @return xmlNode* Pointer to the new tag. On errors an assert is triggered and return
+ * value should be NULL.
+ */
+xmlNode *dmixml_AddTextChild(xmlNode *node, const char *tagname, const char *fmt, ...)
+{
+ xmlChar *val_s = NULL, *tagname_s = NULL;
+ xmlNode *res = NULL;
+ va_list ap;
+
+ if( (node == NULL) || (tagname == NULL) || (fmt == NULL) ) {
+ return NULL;
+ }
+
+ tagname_s = xmlCharStrdup(tagname);
+ assert( tagname_s != NULL );
+
+ va_start(ap, fmt);
+ val_s = dmixml_buildstr(2048, fmt, ap);
+ va_end(ap);
+
+ // Do not add any contents if the string contents is "(null)"
+ res = xmlNewTextChild(node, NULL, tagname_s,
+ (xmlStrcmp(val_s, (xmlChar *) "(null)") == 0 ? NULL : val_s));
+
+ free(tagname_s);
+ free(val_s);
+
+ assert( res != NULL );
+ return res;
+}
+
+/**
+ * Adds a text node child to the given XML node. If input is NULL, the tag contents will be empty.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* Pointer to the current node which will get the text child
+ * @param const char* Contents of the tag (can make use of string formating options)
+ * @return xmlNode* Pointer to the tags content node
+ */
+xmlNode *dmixml_AddTextContent(xmlNode *node, const char *fmt, ...)
+{
+ xmlChar *val_s = NULL;
+ xmlNode *res = NULL;
+ va_list ap;
+
+ if( (node == NULL) || (fmt == NULL) ) {
+ return NULL;
+ }
+
+ va_start(ap, fmt);
+ val_s = dmixml_buildstr(2048, fmt, ap);
+ va_end(ap);
+
+ if( xmlStrcmp(val_s, (xmlChar *) "(null)") != 0 ) {
+ res = xmlAddChild(node, xmlNewText(val_s));
+ } else {
+ res = node;
+ }
+ free(val_s);
+
+ assert( res != NULL );
+ return res;
+}
+
+/**
+ * Retrieve the contents of a named attribute in a given XML node
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* Pointer to the XML node of which we want to extract the attribute value
+ * @param const char* The name of the attribute to be extracted
+ * @return char* Pointer to the attribute contents if found, otherwise NULL. This value
+ * must NOT be freed, as it points directly into the value in the XML document.
+ */
+char *dmixml_GetAttrValue(xmlNode *node, const char *key) {
+ xmlAttr *aptr = NULL;
+ xmlChar *key_s = NULL;
+
+ if( node == NULL ) {
+ return NULL;
+ }
+
+ key_s = xmlCharStrdup(key);
+ assert( key_s != NULL );
+
+ for( aptr = node->properties; aptr != NULL; aptr = aptr->next ) {
+ if( xmlStrcmp(aptr->name, key_s) == 0 ) {
+ free(key_s); key_s = NULL;
+ // FIXME: Should find better way how to return UTF-8 data
+ return (char *)(aptr->children != NULL ? aptr->children->content : NULL);
+ }
+ }
+ free(key_s); key_s = NULL;
+ return NULL;
+}
+
+/**
+ * Internal function - Retrieve a pointer to an XML node based on tag name and a specified attribute
+ * value. To get a hit, tag name and the attribute must be found and the value of the attribute must
+ * match as well. The function will traverse all children nodes of the given input node, but it will
+ * not go deeper.
+ * @author David Sommerseth <davids@redhat.com>
+ * @author Nima Talebi <nima@autonomy.net.au>
+ * @param xmlNode* Pointer to the XML node of where to start searching
+ * @param const char* Tag name the function will search for
+ * @param const char* Attribute to check for in the tag
+ * @param const char* Value of the attribute which must match to have a hit
+ * @param int Be case sensitive or not. 1 == case sensitive, 0 == case insensitive
+ * @return xmlNode* Pointer to the found XML node, NULL if no tag was found.
+ */
+xmlNode *__dmixml_FindNodeByAttr(xmlNode *node, const char *tagkey, const char *attrkey,
+ const char *val, int casesens) {
+ xmlNode *ptr_n = NULL;
+ xmlChar *tag_s = NULL;
+ int (*compare_func) (const char *, const char *);
+
+ assert( node != NULL );
+ if( node->children == NULL ) {
+ return NULL;
+ }
+
+ tag_s = xmlCharStrdup(tagkey);
+ assert( tag_s != NULL );
+
+ compare_func = (casesens == 1 ? strcmp : strcasecmp);
+
+ foreach_xmlnode(node->children, ptr_n) {
+ // To return the correct node, we need to check node type,
+ // tag name and the attribute value of the given attribute.
+ if( (ptr_n->type == XML_ELEMENT_NODE)
+ && (xmlStrcmp(ptr_n->name, tag_s) == 0)
+ && (compare_func(dmixml_GetAttrValue(ptr_n, attrkey), val) == 0 ) ) {
+ goto exit;
+ }
+ }
+ exit:
+ free(tag_s); tag_s = NULL;
+ return ptr_n;
+}
+
+/**
+ * Retrieve a poitner to an XML node with the given name. The function will traverse
+ * all children nodes of the given input node, but it will not go deeper. The function
+ * will only return the first hit.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* Pointer to the XML node of where to start searching
+ * @param const char* Name of the tag name the function will look for.
+ * @return xmlNode* Pointer to the found XML node, NULL if no tag was found.
+ */
+xmlNode *dmixml_FindNode(xmlNode *node, const char *key) {
+ xmlNode *ptr_n = NULL;
+ xmlChar *key_s = NULL;
+
+ if( node->children == NULL ) {
+ return NULL;
+ }
+
+ key_s = xmlCharStrdup(key);
+ assert( key_s != NULL );
+
+ for( ptr_n = node->children; ptr_n != NULL; ptr_n = ptr_n->next ) {
+ if( (ptr_n->type == XML_ELEMENT_NODE)
+ && (xmlStrcmp(ptr_n->name, key_s) == 0) ) {
+ free(key_s); key_s = NULL;
+ return ptr_n;
+ }
+ }
+ free(key_s); key_s = NULL;
+ return NULL;
+}
+
+/**
+ * Retrieve the text contents of the given XML node
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* Pointer to the XML node of which we want to extract the contents
+ * @return char* Pointer to the tag contents if found, otherwise NULL. This value
+ * must NOT be freed, as it points directly into the value in the XML document.
+ */
+inline char *dmixml_GetContent(xmlNode *node) {
+ // FIXME: Should find better way how to return UTF-8 data
+ return (((node != NULL) && (node->children != NULL)) ? (char *) node->children->content : NULL);
+}
+
+/**
+ * Retrieve the text content of a given tag. The function will traverse
+ * all children nodes of the given input node, but it will not go deeper.
+ * The function will only return the first hit.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* Pointer to the XML node of where to start searching
+ * @param const char* Name of the tag the function will look for
+ * @return char* Pointer to the tag contents if found, otherwise NULL. This value
+ * must NOT be freed, as it points directly into the value in the XML document.
+ */
+inline char *dmixml_GetNodeContent(xmlNode *node, const char *key) {
+ return dmixml_GetContent(dmixml_FindNode(node, key));
+}
+
+/**
+ * Retrieve the contents from an XPath object.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param char* Pointer to a buffer where to return the value
+ * @param size_t Size of the return buffer
+ * @param xmlXPathObject* Pointer to the XPath object containing the data
+ * @param int If the XPath object contains a node set, this defines
+ * which of the elements to be extracted.
+ * @return char* Points at the return buffer if a value is found, otherwise NULL is returned.
+ */
+char *dmixml_GetXPathContent(char *buf, size_t buflen, xmlXPathObject *xpo, int idx) {
+ memset(buf, 0, buflen);
+
+ if( xpo == NULL ) {
+ return NULL;
+ }
+
+ switch( xpo->type ) {
+ case XPATH_STRING:
+ strncpy(buf, (char *)xpo->stringval, buflen-1);
+ break;
+
+ case XPATH_NUMBER:
+ snprintf(buf, buflen-1, "%f", xpo->floatval);
+ break;
+
+ case XPATH_NODESET:
+ if( (xpo->nodesetval != NULL) && (xpo->nodesetval->nodeNr >= (idx+1)) ) {
+ char *str = dmixml_GetContent(xpo->nodesetval->nodeTab[idx]);
+ if( str != NULL ) {
+ strncpy(buf, str, buflen-1);
+ } else {
+ memset(buf, 0, buflen);
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr, "dmixml_GetXPathContent(...):: "
+ "Do not know how to handle XPath type %i\n",
+ xpo->type);
+ return NULL;
+ }
+ return buf;
+}
diff --git a/src/dmixml.h b/src/dmixml.h
new file mode 100644
index 0000000..3dc32e5
--- /dev/null
+++ b/src/dmixml.h
@@ -0,0 +1,79 @@
+/* Simplified XML API for dmidecode
+ *
+ * Copyright 2009 David Sommerseth <davids@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+#ifndef _XMLHELPER_H
+#define _XMLHELPER_H
+
+#include <stdarg.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#define foreach_xmlnode(n, itn) for( itn = n; itn != NULL; itn = itn->next )
+
+xmlAttr *dmixml_AddAttribute(xmlNode *node, const char *atrname, const char *fmt, ...);
+xmlNode *dmixml_AddTextChild(xmlNode *node, const char *tagname, const char *fmt, ...);
+xmlNode *dmixml_AddTextContent(xmlNode *node, const char *fmt, ...);
+
+char *dmixml_GetAttrValue(xmlNode *node, const char *key);
+
+xmlNode *__dmixml_FindNodeByAttr(xmlNode *, const char *, const char *, const char *, int);
+
+/**
+ * Retrieve a pointer to an XML node based on tag name and a specified attribute value. To get
+ * a hit, tag name and the attribute must be found and the value of the attribute must match as well.
+ * The function will traverse all children nodes of the given input node, but it will not go deeper.
+ * Matching is case sensitive.
+ * @author David Sommerseth <davids@redhat.com>
+ * @author Nima Talebi <nima@autonomy.net.au>
+ * @param xmlNode* Pointer to the XML node of where to start searching
+ * @param const char* Tag name the function will search for
+ * @param const char* Attribute to check for in the tag
+ * @param const char* Value of the attribute which must match to have a hit
+ * @return xmlNode* Pointer to the found XML node, NULL if no tag was found.
+ */
+#define dmixml_FindNodeByAttr(n, t, a, v) __dmixml_FindNodeByAttr(n, t, a, v, 1)
+
+/**
+ * Retrieve a pointer to an XML node based on tag name and a specified attribute value. To get
+ * a hit, tag name and the attribute must be found and the value of the attribute must match as well.
+ * The function will traverse all children nodes of the given input node, but it will not go deeper.
+ * Matching is case INsensitive.
+ * @author David Sommerseth <davids@redhat.com>
+ * @author Nima Talebi <nima@autonomy.net.au>
+ * @param xmlNode* Pointer to the XML node of where to start searching
+ * @param const char* Tag name the function will search for
+ * @param const char* Attribute to check for in the tag
+ * @param const char* Value of the attribute which must match to have a hit
+ * @return xmlNode* Pointer to the found XML node, NULL if no tag was found.
+ */
+#define dmixml_FindNodeByAttr_NoCase(n, t, a, v) __dmixml_FindNodeByAttr(n, t, a, v, 0)
+
+
+xmlNode *dmixml_FindNode(xmlNode *, const char *key);
+inline char *dmixml_GetContent(xmlNode *node);
+inline char *dmixml_GetNodeContent(xmlNode *node, const char *key);
+char *dmixml_GetXPathContent(char *buf, size_t buflen, xmlXPathObject *xpo, int idx);
+
+#endif
diff --git a/src/efi.c b/src/efi.c
new file mode 100644
index 0000000..9802171
--- /dev/null
+++ b/src/efi.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2009 David Sommerseth <davids@redhat.com>
+ * Copyright 2002-2008 Jean Delvare <khali@linux-fr.org>
+ * Copyright 2000-2002 Alan Cox <alan@redhat.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "efi.h"
+
+/**
+ * @file xmlpythonizer.c
+ * @brief Helper function for EFI support
+ * @author Jean Delvare <khali@linux-fr.org>
+ * @author Alan Cox <alan@redhat.com>
+ */
+
+/**
+ * Probe for EFI interface
+ * @param size_t*
+ * @return returns EFI_NOT_FOUND or EFI_NO_SMBIOS
+ */
+int address_from_efi(size_t * address)
+{
+ FILE *efi_systab;
+ const char *filename;
+ char linebuf[64];
+ int ret;
+
+ *address = 0; /* Prevent compiler warning */
+
+ /*
+ ** Linux <= 2.6.6: /proc/efi/systab
+ ** Linux >= 2.6.7: /sys/firmware/efi/systab
+ */
+ if((efi_systab = fopen(filename = "/sys/firmware/efi/systab", "r")) == NULL
+ && (efi_systab = fopen(filename = "/proc/efi/systab", "r")) == NULL) {
+ /* No EFI interface, fallback to memory scan */
+ return EFI_NOT_FOUND;
+ }
+ ret = EFI_NO_SMBIOS;
+ while((fgets(linebuf, sizeof(linebuf) - 1, efi_systab)) != NULL) {
+ char *addrp = strchr(linebuf, '=');
+
+ *(addrp++) = '\0';
+ if(strcmp(linebuf, "SMBIOS") == 0) {
+ *address = strtoul(addrp, NULL, 0);
+ printf("# SMBIOS entry point at 0x%08lx\n", (unsigned long)*address);
+ ret = 0;
+ break;
+ }
+ }
+ if(fclose(efi_systab) != 0)
+ perror(filename);
+
+ if(ret == EFI_NO_SMBIOS)
+ fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
+
+ return ret;
+}
+
diff --git a/src/efi.h b/src/efi.h
new file mode 100644
index 0000000..240fb01
--- /dev/null
+++ b/src/efi.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009 David Sommerseth <davids@redhat.com>
+ * Copyright 2002-2008 Jean Delvare <khali@linux-fr.org>
+ * Copyright 2000-2002 Alan Cox <alan@redhat.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+#ifndef _EFI_H
+#define _EFI_H
+#define EFI_NOT_FOUND (-1)
+#define EFI_NO_SMBIOS (-2)
+
+int address_from_efi(size_t * address);
+
+#endif
diff --git a/src/libxml_wrap.h b/src/libxml_wrap.h
new file mode 100644
index 0000000..e4f56dd
--- /dev/null
+++ b/src/libxml_wrap.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is fur-
+ * nished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+ * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+ * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Daniel Veillard shall not
+ * be used in advertising or otherwise to promote the sale, use or other deal-
+ * ings in this Software without prior written authorization from him.
+ *
+ *
+ * This include file is taken from the libxml2 source tree, to provide the needed
+ * declarations to implement usage of libxml2xml.so
+ * (David Sommerseth <davids@redhat.com>, 2009)
+ *
+ */
+
+#include <Python.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/catalog.h>
+#include <libxml/threads.h>
+#include <libxml/nanoftp.h>
+#include <libxml/nanohttp.h>
+#include <libxml/uri.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xinclude.h>
+#include <libxml/xpointer.h>
+#include <libxml/xmlunicode.h>
+#include <libxml/xmlregexp.h>
+#include <libxml/xmlautomata.h>
+#include <libxml/xmlreader.h>
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#endif
+
+/**
+ * ATTRIBUTE_UNUSED:
+ *
+ * Macro used to signal to GCC unused function parameters
+ * Repeated here since the definition is not available when
+ * compiled outside the libxml2 build tree.
+ */
+#ifdef __GNUC__
+#ifdef ATTRIBUTE_UNUSED
+#undef ATTRIBUTE_UNUSED
+#endif
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+#define PyxmlNode_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlNode_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlNodePtr obj;
+} PyxmlNode_Object;
+
+#define PyxmlXPathContext_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlXPathContext_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlXPathContextPtr obj;
+} PyxmlXPathContext_Object;
+
+#define PyxmlXPathParserContext_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlXPathParserContext_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlXPathParserContextPtr obj;
+} PyxmlXPathParserContext_Object;
+
+#define PyparserCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyparserCtxt_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlParserCtxtPtr obj;
+} PyparserCtxt_Object;
+
+#define PyValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyValidCtxt_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlValidCtxtPtr obj;
+} PyValidCtxt_Object;
+
+#define Pycatalog_Get(v) (((v) == Py_None) ? NULL : \
+ (((Pycatalog_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlCatalogPtr obj;
+} Pycatalog_Object;
+
+#ifdef LIBXML_REGEXP_ENABLED
+#define PyxmlReg_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlReg_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlRegexpPtr obj;
+} PyxmlReg_Object;
+#endif /* LIBXML_REGEXP_ENABLED */
+
+#ifdef LIBXML_READER_ENABLED
+#define PyxmlTextReader_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlTextReader_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlTextReaderPtr obj;
+} PyxmlTextReader_Object;
+
+#define PyxmlTextReaderLocator_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlTextReaderLocator_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlTextReaderLocatorPtr obj;
+} PyxmlTextReaderLocator_Object;
+#endif
+
+#define PyURI_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyURI_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlErrorPtr obj;
+} PyError_Object;
+
+#define PyError_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyError_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlOutputBufferPtr obj;
+} PyoutputBuffer_Object;
+
+#define PyoutputBuffer_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyoutputBuffer_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlParserInputBufferPtr obj;
+} PyinputBuffer_Object;
+
+#define PyinputBuffer_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyinputBuffer_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlURIPtr obj;
+} PyURI_Object;
+
+/* FILE * have their own internal representation */
+#define PyFile_Get(v) (((v) == Py_None) ? NULL : \
+ (PyFile_Check(v) ? (PyFile_AsFile(v)) : stdout))
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+typedef struct {
+ PyObject_HEAD
+ xmlRelaxNGPtr obj;
+} PyrelaxNgSchema_Object;
+
+#define PyrelaxNgSchema_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyrelaxNgSchema_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlRelaxNGParserCtxtPtr obj;
+} PyrelaxNgParserCtxt_Object;
+
+#define PyrelaxNgParserCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyrelaxNgParserCtxt_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlRelaxNGValidCtxtPtr obj;
+} PyrelaxNgValidCtxt_Object;
+
+#define PyrelaxNgValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyrelaxNgValidCtxt_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlSchemaPtr obj;
+} PySchema_Object;
+
+#define PySchema_Get(v) (((v) == Py_None) ? NULL : \
+ (((PySchema_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlSchemaParserCtxtPtr obj;
+} PySchemaParserCtxt_Object;
+
+#define PySchemaParserCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PySchemaParserCtxt_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlSchemaValidCtxtPtr obj;
+} PySchemaValidCtxt_Object;
+
+#define PySchemaValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PySchemaValidCtxt_Object *)(v))->obj))
+
+#endif /* LIBXML_SCHEMAS_ENABLED */
+
+PyObject * libxml_intWrap(int val);
+PyObject * libxml_longWrap(long val);
+PyObject * libxml_xmlCharPtrWrap(xmlChar *str);
+PyObject * libxml_constxmlCharPtrWrap(const xmlChar *str);
+PyObject * libxml_charPtrWrap(char *str);
+PyObject * libxml_constcharPtrWrap(const char *str);
+PyObject * libxml_charPtrConstWrap(const char *str);
+PyObject * libxml_xmlCharPtrConstWrap(const xmlChar *str);
+PyObject * libxml_xmlDocPtrWrap(xmlDocPtr doc);
+PyObject * libxml_xmlNodePtrWrap(xmlNodePtr node);
+PyObject * libxml_xmlAttrPtrWrap(xmlAttrPtr attr);
+PyObject * libxml_xmlNsPtrWrap(xmlNsPtr ns);
+PyObject * libxml_xmlAttributePtrWrap(xmlAttributePtr ns);
+PyObject * libxml_xmlElementPtrWrap(xmlElementPtr ns);
+PyObject * libxml_doubleWrap(double val);
+PyObject * libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt);
+PyObject * libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt);
+PyObject * libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt);
+PyObject * libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj);
+PyObject * libxml_xmlValidCtxtPtrWrap(xmlValidCtxtPtr valid);
+PyObject * libxml_xmlCatalogPtrWrap(xmlCatalogPtr obj);
+PyObject * libxml_xmlURIPtrWrap(xmlURIPtr uri);
+PyObject * libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer);
+PyObject * libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer);
+#ifdef LIBXML_REGEXP_ENABLED
+PyObject * libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp);
+#endif /* LIBXML_REGEXP_ENABLED */
+#ifdef LIBXML_READER_ENABLED
+PyObject * libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader);
+PyObject * libxml_xmlTextReaderLocatorPtrWrap(xmlTextReaderLocatorPtr locator);
+#endif
+
+xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
+#ifdef LIBXML_SCHEMAS_ENABLED
+PyObject * libxml_xmlRelaxNGPtrWrap(xmlRelaxNGPtr ctxt);
+PyObject * libxml_xmlRelaxNGParserCtxtPtrWrap(xmlRelaxNGParserCtxtPtr ctxt);
+PyObject * libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid);
+PyObject * libxml_xmlSchemaPtrWrap(xmlSchemaPtr ctxt);
+PyObject * libxml_xmlSchemaParserCtxtPtrWrap(xmlSchemaParserCtxtPtr ctxt);
+PyObject * libxml_xmlSchemaValidCtxtPtrWrap(xmlSchemaValidCtxtPtr valid);
+#endif /* LIBXML_SCHEMAS_ENABLED */
+PyObject * libxml_xmlErrorPtrWrap(xmlErrorPtr error);
+PyObject * libxml_xmlSchemaSetValidErrors(PyObject * self, PyObject * args);
diff --git a/src/pymap.xml b/src/pymap.xml
new file mode 100644
index 0000000..a07512c
--- /dev/null
+++ b/src/pymap.xml
@@ -0,0 +1,864 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ # 2007-2009 (C) Nima Talebi <nima@autonomy.net.au>
+ # 2009 (C) David Sommerseth <davids@redhat.com>
+ #
+ # This file is part of Python DMI-Decode.
+ #
+ # Python DMI-Decode is free software: you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation, either version 2 of the License, or
+ # (at your option) any later version.
+ #
+ # Python DMI-Decode is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ # EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #
+ # ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ # AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ #
+-->
+
+<dmidecode_mapping version="1">
+
+<!--
+ TODO: To discuss the following with dazo...
+ TODO: Naming convention - sit on this or can we do better? For example some
+ TODO: root-paths have an appended `Info', and some don't (going from doc/README.types).
+-->
+
+ <TypeMapping>
+ <!-- Type 00 : BIOS -->
+ <TypeMap id="0x00">
+ <Map rootpath="/dmidecode/BIOSinfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Vendor" valuetype="string" value="Vendor"/>
+ <Map keytype="constant" key="Characteristics" valuetype="dict">
+ <Map keytype="string" key="Characteristics/flags/flag[../../@level = '0']"
+ valuetype="boolean" value="Characteristics/flags/flag/@enabled"/>
+ </Map>
+ <Map keytype="constant" key="Characteristic x1" valuetype="dict">
+ <Map keytype="string" key="Characteristics/characteristic[../@level = 'x1']"
+ valuetype="boolean" value="Characteristics/characteristic/@enabled"/>
+ </Map>
+ <Map keytype="constant" key="Characteristic x2" valuetype="dict">
+ <Map keytype="string" key="Characteristics/characteristic[../@level = 'x2']"
+ valuetype="boolean" value="Characteristics/characteristic/@enabled"/>
+ </Map>
+ <Map keytype="constant" key="Runtime Size" valuetype="string"
+ value="concat(RuntimeSize,' ',RuntimeSize/@unit)"/>
+ <Map keytype="constant" key="BIOS Revision"
+ valuetype="string" value="BIOSrevision"/>
+ <Map keytype="constant" key="Version" valuetype="string" value="Version"/>
+ <Map keytype="constant" key="ROM Size" valuetype="string"
+ value="concat(ROMsize,' ',ROMsize/@unit)"/>
+ <Map keytype="constant" key="Address" valuetype="string" value="Address"/>
+ <Map keytype="constant" key="Relase Date" valuetype="string" value="ReleaseDate"/>
+ </Map>
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 01 : System -->
+ <TypeMap id="0x01">
+ <Map rootpath="/dmidecode/SystemInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="SKU Number" valuetype="string" value="SKUnumber"/>
+ <Map keytype="constant" key="UUID" valuetype="string" value="SystemUUID"/>
+ <Map keytype="constant" key="Family" valuetype="string" value="Family"/>
+ <Map keytype="constant" key="Serial Number" valuetype="string" value="SerialNumber"/>
+ <Map keytype="constant" key="Version" valuetype="string" value="Version"/>
+ <Map keytype="constant" key="Product Name" valuetype="string" value="ProductName"/>
+ <Map keytype="constant" key="Wake-Up Type" valuetype="string" value="SystemWakeUpType"/>
+ <Map keytype="constant" key="Manufacturer" valuetype="string" value="Manufacturer"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 02 : Base Board -->
+ <TypeMap id="0x02">
+ <Map rootpath="/dmidecode/BaseBoardInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Serial Number" valuetype="string" value="SerialNumber"/>
+ <Map keytype="constant" key="Version" valuetype="string" value="Version"/>
+ <Map keytype="constant" key="Product Name" valuetype="string" value="ProductName"/>
+ <Map keytype="constant" key="Manufacturer" valuetype="string" value="Manufacturer"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 03 : Chassis -->
+ <TypeMap id="0x03">
+ <Map rootpath="/dmidecode/ChassisInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Boot-Up State" valuetype="string" value="ChassisStates/BootUp"/>
+ <Map keytype="constant" key="Power Supply State" valuetype="string" value="ChassisStates/PowerSupply"/>
+ <Map keytype="constant" key="Thermal State" valuetype="string" value="ChassisStates/Thermal"/>
+ <Map keytype="constant" key="Lock" valuetype="string" value="ChassisLock"/>
+ <Map keytype="constant" key="Serial Number" valuetype="string" value="SerialNumber"/>
+ <Map keytype="constant" key="Version" valuetype="string" value="Version"/>
+ <Map keytype="constant" key="Asset Tag" valuetype="string" value="AssetTag"/>
+ <Map keytype="constant" key="Security Status" valuetype="string" value="SecurityStatus"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="ChassisType"/>
+ <Map keytype="constant" key="Manufacturer" valuetype="string" value="Manufacturer"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 04 : Processor -->
+ <TypeMap id="0x04">
+ <Map rootpath="/dmidecode/ProcessorInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Status" valuetype="string" value="concat('Populated:', Populated)"/>
+ <Map keytype="constant" key="Part Number" valuetype="string" value="PartNumber"/>
+ <Map keytype="constant" key="Upgrade" valuetype="string" value="Upgrade"/>
+ <Map keytype="constant" key="Socket Designation" valuetype="string" value="SocketDesignation"/>
+ <Map keytype="constant" key="Family" valuetype="string" value="Family"/>
+ <Map keytype="constant" key="Characteristics" valuetype="list:string" value="Cores/Characteristics/Flag"/>
+ <Map keytype="constant" key="Current Speed" valuetype="integer" value="Frequencies/CurrentSpeed"/>
+ <Map keytype="constant" key="Thread Count" valuetype="integer" value="Cores/ThreadCount"/>
+ <Map keytype="constant" key="External Clock" valuetype="integer" value="Frequencies/ExternalClock"/>
+ <Map keytype="constant" key="Serial Number" valuetype="string" value="SerialNumber"/>
+ <Map keytype="constant" key="Version" valuetype="string" value="Manufacturer/Version"/>
+ <Map keytype="constant" key="Voltage" valuetype="string" value="concat(Voltages/Voltage, ' ', Voltages/Voltage/@unit)"/>
+ <Map keytype="constant" key="Max Speed" valuetype="integer" value="Frequencies/MaxSpeed"/>
+ <Map keytype="constant" key="Asset Tag" valuetype="string" value="AssetTag"/>
+ <Map keytype="constant" key="Core Enabled" valuetype="integer" value="Cores/CoresEnabled"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="Type"/>
+ <Map keytype="constant" key="Core Count" valuetype="integer" value="Cores/CoreCount"/>
+ <Map keytype="constant" key="Manufacturer" valuetype="dict">
+ <Map keytype="constant" key="Vendor" valuetype="string" value="Manufacturer/Vendor"/>
+ <Map keytype="constant" key="Flags" valuetype="dict">
+ <Map keytype="string" key="CPUCore/cpu_flags/flag"
+ valuetype="boolean" value="CPUCore/cpu_flags/flag/@available"/>
+ </Map>
+ <Map keytype="constant" key="ID" valuetype="string" value="CPUCore/ID"/>
+ <Map keytype="constant" key="Signature" valuetype="string" value="CPUCore/Signature"/>
+ </Map>
+ <Map keytype="constant" key="L1 Cache Handle"
+ valuetype="string" value="Cache/Level[@level = '1']/@handle"/>
+ <Map keytype="constant" key="L2 Cache Handle"
+ valuetype="string" value="Cache/Level[@level = '2']/@handle"/>
+ <Map keytype="constant" key="L3 Cache Handle"
+ valuetype="string" value="Cache/Level[@level = '3']/@handle"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 05 : Memory Controller -->
+ <TypeMap id="0x05">
+ <Map rootpath="/dmidecode/MemoryCtrlInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Associated Memory Slots"
+ valuetype="list:string" value="AssociatedMemorySlots/Slot"/>
+ <Map keytype="constant" key="Current Interleave" valuetype="string" value="CurrentInterleave"/>
+ <Map keytype="constant" key="Enabled Error Correcting Capabilities"
+ valuetype="list:string" value="EnabledErrorCorrection/Capability"
+ fixedsize="6" index_attr="index"/>
+ <Map keytype="constant" key="Error Correcting Capabilities"
+ valuetype="list:string" value="ErrorCorrection/Capabilities/Capability"
+ fixedsize="6" index_attr="index"/>
+ <Map keytype="constant" key="Error Detecting Method"
+ valuetype="string" value="ErrorCorrection/CorrectionMethod"/>
+ <Map keytype="constant" key="Maximum Memory Module Size"
+ valuetype="string" value="concat(MaxMemoryModuleSize,' ',MaxMemoryModuleSize/@unit)"/>
+ <Map keytype="constant" key="Maximum Total Memory Size"
+ valuetype="string" value="concat(MaxTotalMemorySize,' ',MaxTotalMemorySize/@unit)"/>
+ <Map rootpath="Voltages" keytype="constant" key="Memory Module Voltage" valuetype="dict">
+ <Map keytype="string" key="Voltage/@key_compound" valuetype="boolean" value="Voltage/@available"/>
+ </Map>
+ <Map keytype="constant" key="Supported Interleave" valuetype="string" value="SupportedInterleave"/>
+ <Map keytype="constant" key="Supported Memory Types"
+ valuetype="list:string" value="SupportedTypes/ModuleType" fixedsize="11" index_attr="index"/>
+ <Map keytype="constant" key="Supported Speeds"
+ valuetype="list:string" value="SupportedSpeeds/Speed" emptyIsNone="1"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 06 : Memory Module -->
+ <TypeMap id="0x06">
+ <Map rootpath="/dmidecode/MemoryModuleInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Bank Connections"
+ valuetype="list:integer" value="BankConnections/Connection"/>
+ <Map keytype="constant" key="Current Speed"
+ valuetype="string" value="concat(ModuleSpeed,' ',ModuleSpeed/@unit)" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Enabled Size" valuetype="dict">
+ <Map keytype="constant" key="Connection" valuetype="string" value="EnabledSize/@Connection"/>
+ <Map keytype="constant" key="Size"
+ valuetype="string" value="concat(EnabledSize,' ',EnabledSize/@unit)"/>
+ </Map>
+ <Map keytype="constant" key="Error Status" valuetype="boolean" value="ModuleErrorStatus/@Error"/>
+ <Map keytype="constant" key="Installed Size" valuetype="dict">
+ <Map keytype="constant" key="Connection" valuetype="string" value="InstalledSize/@Connection"/>
+ <Map keytype="constant" key="Size"
+ valuetype="string" value="concat(InstalledSize,' ',InstalledSize/@unit)"/>
+ </Map>
+ <Map keytype="constant" key="Socket Designation" valuetype="string" value="SocketDesignation"/>
+ <Map keytype="constant" key="Type"
+ valuetype="list:string" value="Type/ModuleType" fixedsize="11" index_attr="index"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 07 : Cache -->
+ <TypeMap id="0x07">
+ <Map rootpath="/dmidecode/CacheInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="System Type" valuetype="string" value="SystemType"/>
+ <Map keytype="constant" key="Socket Designation" valuetype="string" value="SocketDesignation"/>
+ <Map keytype="constant" key="Installed SRAM Type"
+ valuetype="list:string" value="InstalledSRAMtypes/CacheType" fixedsize="7" index_attr="index"/>
+ <Map keytype="constant" key="Supported SRAM Type"
+ valuetype="list:string" value="SupportedSRAMtypes/CacheType" fixedsize="7" index_attr="index"/>
+ <Map keytype="constant" key="Associativity" valuetype="string" value="Associativity"/>
+ <Map keytype="constant" key="Maximum Size" valuetype="string"
+ value="concat(MaximumSize,' ',MaximumSize/@unit)"/>
+ <Map keytype="constant" key="Installed Size" valuetype="string"
+ value="concat(InstalledSize,' ',InstalledSize/@unit)"/>
+ <Map keytype="constant" key="Location" valuetype="string" value="CacheLocation"/>
+ <Map keytype="constant" key="Error Correction Type" valuetype="string" value="ErrorCorrectionType"/>
+ <Map keytype="constant" key="Speed" valuetype="string" value="Speed" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Operational Mode" valuetype="string" value="OperationalMode"/>
+ <Map keytype="constant" key="Configuration" valuetype="dict">
+ <Map keytype="constant" key="Socketed" valuetype="boolean" value="@Socketed"/>
+ <Map keytype="constant" key="Enabled" valuetype="boolean" value="@Enabled"/>
+ <Map keytype="constant" key="Level" valuetype="integer" value="@Level"/>
+ </Map>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 08 : Port Connector -->
+ <TypeMap id="0x08">
+ <Map rootpath="/dmidecode/PortConnectorInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="External Reference Designator"
+ valuetype="string" value="DesignatorRef[@type='external']"/>
+ <Map keytype="constant" key="Port Type" valuetype="string" value="PortType"/>
+ <Map keytype="constant" key="External Connector Type"
+ valuetype="string" value="Connector[@type='external']"/>
+ <Map keytype="constant" key="Internal Reference Designator"
+ valuetype="string" value="DesignatorRef[@type='internal']"/>
+ <Map keytype="constant" key="Internal Connector Type"
+ valuetype="string" value="Connector[@type='internal']"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 09 : System Slots -->
+ <TypeMap id="0x09">
+ <Map rootpath="/dmidecode/SystemSlots" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Designation" valuetype="string" value="Designation"/>
+ <Map keytype="constant" key="Current Usage" valuetype="string" value="CurrentUsage"/>
+ <Map keytype="constant" key="Characteristics"
+ valuetype="list:string" value="SlotCharacteristics/Characteristic"
+ fixedsize="10" index_attr="index"/>
+ <Map keytype="constant" key="SlotLength" valuetype="string" value="SlotLength"/>
+ <Map keytype="constant" key="SlotId" valuetype="string" value="SlotID/@id"/>
+ <Map keytype="constant" key="Type:SlotBusWidth" valuetype="string" value="SlotWidth"/>
+ <Map keytype="constant" key="Type:SlotType" valuetype="string" value="SlotType"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 10 : On-Board Devices -->
+ <TypeMap id="0x0A">
+ <Map rootpath="/dmidecode/OnBoardDevicesInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="dmi_on_board_devices" valuetype="list:dict" value="dmi_on_board_devices">
+ <Map keytype="constant" key="Enabled" valuetype="boolean" value="Device/@Enabled"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="Device/Type"/>
+ <Map keytype="constant" key="Description" valuetype="string" value="Device/Description"/>
+ </Map>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 11 : OEM Strings -->
+ <TypeMap id="0x0B">
+ <Map rootpath="/dmidecode/OEMstrings" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Strings" valuetype="dict">
+ <Map keytype="integer" key="Record/@index" valuetype="string" value="Record"/>
+ </Map>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 12 : System Configuration Options -->
+ <TypeMap id="0x0C">
+ <Map rootpath="/dmidecode/SysConfigOptions" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map rootpath="Options" keytype="constant" key="Options" valuetype="dict">
+ <Map keytype="integer" key="Option/@index" valuetype="string" value="Option"/>
+ </Map>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 13 : BIOS Language -->
+ <TypeMap id="0x0D">
+ <Map rootpath="/dmidecode/BIOSlanguage" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Currently Installed Language"
+ valuetype="list:string" value="Installed/Language"/>
+ <Map keytype="constant" key="Installed Languages"
+ valuetype="integer" value="@installable_languages"/>
+ </Map>
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ </Map>
+ </TypeMap>
+
+ <!-- FIXME : Type 14 : Group Associations -->
+ <TypeMap id="0x0E">
+ </TypeMap>
+
+ <!-- Type 15 : System Event Log -->
+ <TypeMap id="0x0F">
+ <Map rootpath="/dmidecode/SysEventLog" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Status"
+ valuetype="string" value="concat(Status/@Valid, ', ', Status/@Full)"/>
+ <Map keytype="constant" key="Access Method" valuetype="string" value="Access/AccessMethod"/>
+ <Map keytype="constant" key="Header Format" valuetype="string" value="Access/Header/Format"/>
+ <Map keytype="constant" key="Supported Log Type Descriptors" valuetype="string" value="LogTypes/@count"/>
+ <Map keytype="constant" key="Header Start Offset" valuetype="string" value="Access/Header/OffsetStart"/>
+ <Map keytype="constant" key="Change Token" valuetype="string" value="Access/Header/ChangeToken"/>
+ <Map keytype="constant" key="Header Length" valuetype="string" value="Access/Header/Length"/>
+ <Map keytype="constant" key="Access Address" valuetype="string" value="Access/Address/@Data"/>
+ <Map keytype="constant" key="Area Length" valuetype="string" value="Access/@AreaLength"/>
+ <Map keytype="constant" key="Data Start Offset" valuetype="string" value="Access/Header/DataOffset"/>
+ <Map keytype="constant" key="DMI Event Log Descriptors" valuetype="list:dict" value="LogTypes/LogType">
+ <Map keytype="constant" key="Descriptor" valuetype="string" value="Descriptor"/>
+ <Map keytype="constant" key="Data Format" valuetype="string" value="Format"/>
+ </Map>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 16 : Physical Memory Array -->
+ <TypeMap id="0x10">
+ <Map rootpath="/dmidecode/PhysicalMemoryArray" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Maximum Capacity"
+ valuetype="string" value="concat(MaxCapacity, ' ', MaxCapacity/@unit)"/>
+ <Map keytype="constant" key="Number Of Devices" valuetype="integer" value="@NumDevices"/>
+ <Map keytype="constant" key="Use" valuetype="string" value="Use"/>
+ <Map keytype="constant" key="Error Information Handle"
+ valuetype="string" value="ErrorInfoHandle" emptyValue="Not Provided"/>
+ <Map keytype="constant" key="Error Correction Type" valuetype="string" value="ErrorCorrectionType"/>
+ <Map keytype="constant" key="Location" valuetype="string" value="Location"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 17 : Memory Device -->
+ <TypeMap id="0x11">
+ <Map rootpath="/dmidecode/MemoryDevice" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Manufacturer" valuetype="string" value="Manufacturer"/>
+ <Map keytype="constant" key="Set" valuetype="integer" value="Set" emptyIsNone="1"/>
+ <Map keytype="constant" key="Data Width"
+ valuetype="string" value="concat(DataWidth, ' ', DataWidth/@unit)"/>
+ <Map keytype="constant" key="Part Number" valuetype="string" value="PartNumber"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="Type"/>
+ <Map keytype="constant" key="Bank Locator" valuetype="string" value="BankLocator"/>
+ <Map keytype="constant" key="Speed"
+ valuetype="string" value="concat(Speed, ' ', Speed/@unit, ' (',Speed/@speed_ns,'ns)')"/>
+ <Map keytype="constant" key="Error Information Handle"
+ valuetype="string" value="ErrorInfoHandle" emptyValue="No Error"/>
+ <Map keytype="constant" key="Locator" valuetype="string" value="Locator"/>
+ <Map keytype="constant" key="Serial Number" valuetype="string" value="SerialNumber"/>
+ <Map keytype="constant" key="Total Width"
+ valuetype="string" value="concat(TotalWidth, ' ', TotalWidth/@unit)"/>
+ <Map keytype="constant" key="AssetTag" valuetype="string" value="AssetTag"/>
+ <Map keytype="constant" key="Type Detail" valuetype="list:string" value="TypeDetails/flag"
+ fixedsize="12" index_attr="index"/>
+ <Map keytype="constant" key="Array Handle" valuetype="string" value="@ArrayHandle"/>
+ <Map keytype="constant" key="Form Factor" valuetype="string" value="FormFactor"/>
+ <Map keytype="constant" key="Size"
+ valuetype="string" value="concat(Size, ' ', Size/@unit)" emptyIsNone="1"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 18 : 32-bit Memory Error -->
+ <TypeMap id="0x12">
+ <Map rootpath="/dmidecode/MemoryErrorInfo[@bits='32']" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Device Address"
+ valuetype="string" value="DeviceAddr" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Granularity" valuetype="string" value="Granularity"/>
+ <Map keytype="constant" key="Memory Array Address"
+ valuetype="string" value="MemArrayAddr" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Operation" valuetype="string" value="Operation"/>
+ <Map keytype="constant" key="Resolution" valuetype="string" value="Resolution" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="Type"/>
+ <Map keytype="constant" key="Vendor Syndrome"
+ valuetype="string" value="VendorSyndrome" emptyValue="Unknown"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 19 : Memory Array Mapped Address -->
+ <TypeMap id="0x13">
+ <Map rootpath="/dmidecode/MemoryArrayMappedAddress" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Ending Address" valuetype="string" value="EndAddress"/>
+ <Map keytype="constant" key="Partition Width" valuetype="string" value="PartitionWidth"/>
+ <Map keytype="constant" key="Physical Array Handle" valuetype="string" value="PhysicalArrayHandle"/>
+ <Map keytype="constant" key="Range Size"
+ valuetype="string" value="concat(RangeSize, ' ', RangeSize/@unit)"/>
+ <Map keytype="constant" key="Starting Address" valuetype="string" value="StartAddress"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 20 : Memory Device Mapped Address -->
+ <TypeMap id="0x14">
+ <Map rootpath="/dmidecode/MemoryDeviceMappedAddress" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Interleave Data Depth"
+ valuetype="integer" value="InterleaveDataDepth"/>
+ <Map keytype="constant" key="Ending Address" valuetype="string" value="EndAddress"/>
+ <Map keytype="constant" key="Memory Array Mapped Address Handle"
+ valuetype="string" value="MemArrayMappedAddrHandle"/>
+ <Map keytype="constant" key="Partition Row Position" valuetype="integer" value="PartitionRowPosition"/>
+ <Map keytype="constant" key="Physical Device Handle" valuetype="string" value="PhysicalDeviceHandle"/>
+ <Map keytype="constant" key="Range Size"
+ valuetype="string" value="concat(RangeSize,' ',RangeSize/@unit)"/>
+ <Map keytype="constant" key="Starting Address" valuetype="string" value="StartAddress"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 21 : Built-in Pointing Device -->
+ <TypeMap id="0x15">
+ <Map rootpath="/dmidecode/BuiltIntPointingDevice" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Buttons" valuetype="string" value="Buttons"/>
+ <Map keytype="constant" key="Interface" valuetype="string" value="DeviceInterface"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="DeviceType"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 22 : Portable Battery -->
+ <TypeMap id="0x16">
+ <Map rootpath="/dmidecode/PortableBattery" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Design Capacity"
+ valuetype="string" value="concat(DesignCapacity,' ',DesignCapacity/@unit)"/>
+ <Map keytype="constant" key="Design Voltage"
+ valuetype="string" value="concat(DesignVoltage,' ',DesignVoltage/@unit)"/>
+ <Map keytype="constant" key="Location" valuetype="string" value="Location"/>
+ <Map keytype="constant" key="Manufacturer" valuetype="string" value="Manufacturer"/>
+ <Map keytype="constant" key="Maximum Error"
+ valuetype="string" value="MaximumError" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Name" valuetype="string" value="Name"/>
+ <Map keytype="constant" key="OEM-specific Information" valuetype="string" value="OEMinformation"/>
+ <Map keytype="constant" key="SBDS Chemistry" valuetype="string" value="SBDSchemistry"/>
+ <Map keytype="constant" key="SBDS Manufacture Date" valuetype="string" value="SBDSmanufactureDate"/>
+ <Map keytype="constant" key="SBDS Serial Number" valuetype="string" value="SBDSserialNumber"/>
+ <Map keytype="constant" key="SBDS Version" valuetype="string" value="SBDSversion"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 23 : System Reset -->
+ <TypeMap id="0x17">
+ <Map rootpath="/dmidecode/SystemReset" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Boot Option" valuetype="string" value="BootOption"/>
+ <Map keytype="constant" key="Boot Option On Limit" valuetype="string" value="BootOptionOnLimit"/>
+ <Map keytype="constant" key="Reset Count" valuetype="string" value="ResetCount" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Reset Limit" valuetype="string" value="ResetLimit" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Status" valuetype="string" value="Status"/>
+ <Map keytype="constant" key="Timeout" valuetype="string" value="Timeout" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Timer Interval"
+ valuetype="string" value="TimerInterval" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Watchdog Timer" valuetype="string" value="WatchdogTimer"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 24 : Hardware Security -->
+ <TypeMap id="0x18">
+ <Map rootpath="/dmidecode/HardwareSecurity" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Administrator Password Status"
+ valuetype="string" value="AdministratorPassword"/>
+ <Map keytype="constant" key="Front Panel Reset Status"
+ valuetype="string" value="FronPanelReset"/>
+ <Map keytype="constant" key="Keyboard Password Status"
+ valuetype="string" value="KeyboardPassword"/>
+ <Map keytype="constant" key="Power-On Password Status"
+ valuetype="string" value="PowerOnPassword"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 25 : System Power Controls -->
+ <TypeMap id="0x19">
+ <Map rootpath="/dmidecode/SystemPowerCtrls" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Next Scheduled Power-on" valuetype="string" value="NextSchedPowerOn"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 26 : Voltage Probe -->
+ <TypeMap id="0x1A">
+ <Map rootpath="/dmidecode/Probe[@probetype='Voltage']" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Accuracy"
+ valuetype="string" value="concat(Accuracy,' ',Accuracy/@unit)"/>
+ <Map keytype="constant" key="Description"
+ valuetype="string" value="Description"/>
+ <Map keytype="constant" key="Location"
+ valuetype="string" value="Location"/>
+ <Map keytype="constant" key="Maximum Value"
+ valuetype="string" value="concat(MaxValue,' ',MaxValue/@unit)"/>
+ <Map keytype="constant" key="Minimum Value"
+ valuetype="string" value="concat(MinValue,' ',MinValue/@unit)"/>
+ <Map keytype="constant" key="OEM-specific Information"
+ valuetype="string" value="OEMinformation"/>
+ <Map keytype="constant" key="Resolution"
+ valuetype="string" value="concat(Resolution,' ',Resolution/@unit)"/>
+ <Map keytype="constant" key="Status" valuetype="string" value="Status"/>
+ <Map keytype="constant" key="Tolerance" valuetype="string" value="Tolerance" emptyValue="Unknown"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 27 : Cooling Device -->
+ <TypeMap id="0x1B">
+ <Map rootpath="/dmidecode/CoolingDevice" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="OEM-specific Information" valuetype="string" value="OEMinformation"/>
+ <Map keytype="constant" key="Status" valuetype="string" value="Status"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="Type"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 28 : Temperature Probe -->
+ <TypeMap id="0x1C">
+ <Map rootpath="/dmidecode/Probe[@probetype='Temperature']" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Accuracy"
+ valuetype="string" value="concat(Accuracy,' ',Accuracy/@unit)" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Description"
+ valuetype="string" value="Description"/>
+ <Map keytype="constant" key="Location"
+ valuetype="string" value="Location"/>
+ <Map keytype="constant" key="Maximum Value"
+ valuetype="string" value="concat(MaxValue,' deg ',MaxValue/@unit)"/>
+ <Map keytype="constant" key="Minimum Value"
+ valuetype="string" value="concat(MinValue,' deg ',MinValue/@unit)"/>
+ <Map keytype="constant" key="OEM-specific Information"
+ valuetype="string" value="OEMinformation"/>
+ <Map keytype="constant" key="Resolution"
+ valuetype="string" value="concat(Resolution,' deg ',Resolution/@unit)"/>
+ <Map keytype="constant" key="Status" valuetype="string" value="Status"/>
+ <Map keytype="constant" key="Tolerance" valuetype="string" value="Tolerance" emptyValue="Unknown"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- FIXME : Type 29 : Electrical Current Probe -->
+ <TypeMap id="0x1D">
+ </TypeMap>
+
+ <!-- Type 30 : Out-of-band Remote Access -->
+ <TypeMap id="0x1E">
+ <Map rootpath="/dmidecode/RemoteAccess" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Inbound Connection Enabled"
+ valuetype="boolean" value="@InboundConnectionEnabled"/>
+ <Map keytype="constant" key="Manufacturer Name" valuetype="string" value="ManufacturerName"/>
+ <Map keytype="constant" key="Outbound Connection Enabled"
+ valuetype="boolean" value="@OutboundConnectionEnabled"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- FIXME : Type 31 : Boot Integrity Services -->
+ <TypeMap id="0x1F">
+ </TypeMap>
+
+ <!-- Type 32 : System Boot -->
+ <TypeMap id="0x20">
+ <Map rootpath="/dmidecode/SystemBootInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Status" valuetype="string" value="Status"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- Type 33 : 64-bit Memory Error -->
+ <TypeMap id="0x21">
+ <Map rootpath="/dmidecode/MemoryErrorInfo[@bits='64']" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Device Address" valuetype="string" value="DeviceAddr"/>
+ <Map keytype="constant" key="Granularity" valuetype="string" value="Granularity"/>
+ <Map keytype="constant" key="Memory Array Address" valuetype="string" value="MemArrayAddr"/>
+ <Map keytype="constant" key="Operation" valuetype="string" value="Operation"/>
+ <Map keytype="constant" key="Resolution"
+ valuetype="string" value="Resolution" emptyValue="Unknown"/>
+ <Map keytype="constant" key="Type" valuetype="string" value="Type"/>
+ <Map keytype="constant" key="Vendor Syndrome"
+ valuetype="string" value="VendorSyndrome" emptyValue="Unknown"/>
+ </Map>
+ </Map>
+ </TypeMap>
+
+ <!-- FIXME : Type 34 : Management Device -->
+ <TypeMap id="0x22">
+ </TypeMap>
+
+ <!-- FIXME : Type 35 : Management Device Component -->
+ <TypeMap id="0x23">
+ </TypeMap>
+
+ <!-- FIXME : Type 36 : Management Device Threshold Data -->
+ <TypeMap id="0x24">
+ </TypeMap>
+
+ <!-- FIXME : Type 37 : Memory Channel -->
+ <TypeMap id="0x25">
+ </TypeMap>
+
+ <!-- Type 38 : IPMI Device -->
+ <TypeMap id="0x26">
+ <Map rootpath="/dmidecode/IPMIdeviceInfo" keytype="string" key="@handle" valuetype="dict">
+ <Map keytype="constant" key="dmi_type" valuetype="integer" value="@type"/>
+ <Map keytype="constant" key="dmi_handle" valuetype="string" value="@handle"/>
+ <Map keytype="constant" key="dmi_size" valuetype="integer" value="@size"/>
+ <Map keytype="constant" key="data" valuetype="dict">
+ <Map keytype="constant" key="Base Address"
+ valuetype="string" value="concat(BaseAddress, ' (',BaseAddress/@interface,')')"/>
+ <Map keytype="constant" key="I2C Slave Address" valuetype="string" value="@I2CslaveAddr"/>
+ <Map keytype="constant" key="Interface Type" valuetype="string" value="InterfaceType"/>
+ <Map keytype="constant" key="NV Storage Device: Not Present"
+ valuetype="string" value="NVstorageDevice[@NotPresent='1']" emptyIsNone="1"/>
+ <Map keytype="constant" key="Register Spacing" valuetype="string" value="RegisterSpacing"/>
+ <Map keytype="constant" key="Specification Version" valuetype="string" value="@spec_version"/>
+ </Map>
+ </Map>
+
+ </TypeMap>
+
+ <!-- FIXME : Type 39 : Power Supply -->
+ <TypeMap id="0x27">
+ </TypeMap>
+ </TypeMapping>
+
+ <GroupMapping>
+ <!-- Mapping setup for BIOS DMI data -->
+ <Mapping name="bios">
+ <TypeMap id="0x00" />
+ <TypeMap id="0x0D" />
+ </Mapping>
+
+ <!-- Mapping setup for processor info -->
+ <Mapping name="processor">
+ <TypeMap id="0x04" />
+ </Mapping>
+
+ <!-- Mapping setup for chassis info -->
+ <Mapping name="chassis">
+ <TypeMap id="0x03" />
+ </Mapping>
+
+ <!-- Mapping setup for memory info -->
+ <Mapping name="memory">
+ <TypeMap id="0x10" />
+ <TypeMap id="0x11" />
+ </Mapping>
+
+ <!-- Mapping setup for cache info -->
+ <Mapping name="cache">
+ <TypeMap id="0x07" />
+ </Mapping>
+
+ <!-- Mapping setup for system info -->
+ <Mapping name="system">
+ <TypeMap id="0x01" />
+ <TypeMap id="0x0C" />
+ <TypeMap id="0x20" />
+ </Mapping>
+
+ <!-- Mapping setup for baseboard info -->
+ <Mapping name="baseboard">
+ <TypeMap id="0x02" />
+ <TypeMap id="0x0A" />
+ </Mapping>
+
+ <!-- Mapping setup for slot info -->
+ <Mapping name="slot">
+ <TypeMap id="0x09" />
+ </Mapping>
+
+ <!-- Mapping setup for connector info -->
+ <Mapping name="connector">
+ <TypeMap id="0x08" />
+ </Mapping>
+
+ <!-- Mapping setup for retrieving all info at once -->
+ <Mapping name="all">
+ <TypeMap id="0x00"/>
+ <TypeMap id="0x01"/>
+ <TypeMap id="0x02"/>
+ <TypeMap id="0x03"/>
+ <TypeMap id="0x04"/>
+ <TypeMap id="0x05"/>
+ <TypeMap id="0x06"/>
+ <TypeMap id="0x07"/>
+ <TypeMap id="0x08"/>
+ <TypeMap id="0x09"/>
+ <TypeMap id="0x0A"/>
+ <TypeMap id="0x0B"/>
+ <TypeMap id="0x0C"/>
+ <TypeMap id="0x0D"/>
+ <TypeMap id="0x0E"/>
+ <TypeMap id="0x0F"/>
+ <TypeMap id="0x10"/>
+ <TypeMap id="0x11"/>
+ <TypeMap id="0x12"/>
+ <TypeMap id="0x13"/>
+ <TypeMap id="0x14"/>
+ <TypeMap id="0x15"/>
+ <TypeMap id="0x16"/>
+ <TypeMap id="0x17"/>
+ <TypeMap id="0x18"/>
+ <TypeMap id="0x19"/>
+ <TypeMap id="0x1A"/>
+ <TypeMap id="0x1B"/>
+ <TypeMap id="0x1C"/>
+ <TypeMap id="0x1D"/>
+ <TypeMap id="0x1E"/>
+ <TypeMap id="0x1F"/>
+ <TypeMap id="0x20"/>
+ <TypeMap id="0x21"/>
+ <TypeMap id="0x22"/>
+ <TypeMap id="0x23"/>
+ <TypeMap id="0x24"/>
+ <TypeMap id="0x25"/>
+ <TypeMap id="0x26"/>
+ <TypeMap id="0x27"/>
+ <TypeMap id="0x28"/>
+ <TypeMap id="0x29"/>
+ </Mapping>
+ </GroupMapping>
+
+</dmidecode_mapping>
diff --git a/src/setup-dbg.py b/src/setup-dbg.py
index e4b3b37..9602abc 100644
--- a/src/setup-dbg.py
+++ b/src/setup-dbg.py
@@ -1,25 +1,80 @@
+#
+# setup-dbg.py
+# Python distutil package setup, with debug features enabled
+#
+# Copyright 2009 David Sommerseth <davids@redhat.com>
+# Copyright 2007-2009 Nima Talebi <nima@autonomy.net.au>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# For the avoidance of doubt the "preferred form" of this code is one which
+# is in an open unpatent encumbered format. Where cryptographic key signing
+# forms part of the process of creating an executable the information
+# including keys needed to generate an equivalently functional executable
+# are deemed to be part of the source code.
+#
+
from distutils.core import setup, Extension
+from setup_common import *
+
+#
+# Some default values
+#
+incdir = []
+libdir = []
+libs = []
+
+# Get libxml2 info
+libxml2_include(incdir)
+libxml2_lib(libdir, libs)
+
+# misc info
+dmidec_version = get_version()
+
+#
+# Python setup
+#
setup(
name = "python-dmidecode-dbg",
- version = "2.10.6",
+ version = dmidec_version,
+ license='GPL-2',
description = "Python extension module for dmidecode",
- author = "Nima Talebi",
- author_email = "nima@autonomy.net.au",
- url = "http://projects.autonomy.net.au/dmidecode/",
+ author = "Nima Talebi & David Sommerseth",
+ author_email = "nima@it.net.au, davids@redhat.com",
+ url = "http://projects.autonomy.net.au/python-dmidecode/",
+ data_files = [ ('share/python-dmidecode-dbg', ['src/pymap.xml']) ],
ext_modules = [
Extension(
- "dmidecode",
+ "dmidecodemod",
sources = [
"src/dmidecodemodule.c",
- "src/dmihelper.c",
"src/util.c",
"src/dmioem.c",
- "src/dmidecode.c"
+ "src/dmidecode.c",
+ "src/dmixml.c",
+ "src/dmierror.c",
+ "src/xmlpythonizer.c",
+ "src/efi.c",
+ "src/dmidump.c"
],
- library_dirs = [ "/home/nima/dev-room/projects/dmidecode" ],
- libraries = [ "util" ],
- #libraries = [ "util", "efence" ],
+ include_dirs = incdir,
+ library_dirs = libdir,
+ libraries = libs,
+ undef_macros = [ "NDEBUG" ]
)
- ]
+ ],
+ py_modules = [ "dmidecode" ]
)
diff --git a/src/setup.py b/src/setup.py
index 69b1d80..d33db64 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -1,25 +1,80 @@
+#
+# setup.py
+# Python distutil package setup
+#
+# Copyright 2009 David Sommerseth <davids@redhat.com>
+# Copyright 2007-2009 Nima Talebi <nima@autonomy.net.au>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# For the avoidance of doubt the "preferred form" of this code is one which
+# is in an open unpatent encumbered format. Where cryptographic key signing
+# forms part of the process of creating an executable the information
+# including keys needed to generate an equivalently functional executable
+# are deemed to be part of the source code.
+#
+
from distutils.core import setup, Extension
+from setup_common import *
+
+#
+# Some default values
+#
+incdir = []
+libdir = []
+libs = []
+
+# Get libxml2 info
+libxml2_include(incdir)
+libxml2_lib(libdir, libs)
+
+# misc info
+dmidec_version = get_version()
+
+#
+# Python setup
+#
setup(
name = "python-dmidecode",
- version = "2.10.6",
+ version = dmidec_version,
+ license='GPL-2',
description = "Python extension module for dmidecode",
- author = "Nima Talebi",
- author_email = "nima@autonomy.net.au",
- url = "http://projects.autonomy.net.au/dmidecode/",
+ author = "Nima Talebi & David Sommerseth",
+ author_email = "nima@it.net.au, davids@redhat.com",
+ url = "http://projects.autonomy.net.au/python-dmidecode/",
+ data_files = [ ('share/python-dmidecode', ['src/pymap.xml']) ],
ext_modules = [
Extension(
- "dmidecode",
+ "dmidecodemod",
sources = [
"src/dmidecodemodule.c",
- "src/dmihelper.c",
"src/util.c",
"src/dmioem.c",
- "src/dmidecode.c"
+ "src/dmidecode.c",
+ "src/dmixml.c",
+ "src/dmierror.c",
+ "src/xmlpythonizer.c",
+ "src/efi.c",
+ "src/dmidump.c"
],
- library_dirs = [ "/home/nima/dev-room/projects/dmidecode" ],
- libraries = [ "util" ],
- #libraries = [ "util", "efence" ],
+ include_dirs = incdir,
+ library_dirs = libdir,
+ libraries = libs,
+ undef_macros = [ "NDEBUG" ]
)
- ]
+ ],
+ py_modules = [ "dmidecode" ]
)
diff --git a/src/setup_common.py b/src/setup_common.py
new file mode 100644
index 0000000..fdf5c8c
--- /dev/null
+++ b/src/setup_common.py
@@ -0,0 +1,93 @@
+#
+# setup-common.py
+# Helper functions for retrieving libxml2 arguments needed for compilation
+# and other functions which is used in both setup.py and setup-dbg.py
+#
+# Copyright 2009 David Sommerseth <davids@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# For the avoidance of doubt the "preferred form" of this code is one which
+# is in an open unpatent encumbered format. Where cryptographic key signing
+# forms part of the process of creating an executable the information
+# including keys needed to generate an equivalently functional executable
+# are deemed to be part of the source code.
+#
+
+import commands, sys
+from os import path as os_path
+from distutils.sysconfig import get_python_lib
+
+# libxml2 - C flags
+def libxml2_include(incdir):
+ (res, libxml2_cflags) = commands.getstatusoutput("xml2-config --cflags")
+ if res != 0:
+ print "Could not build python-dmidecode."
+ print "Could not run xml2-config, is libxml2 installed?"
+ print "Also the development libraries?"
+ sys.exit(1)
+
+ # Parse the xml2-config --cflags response
+ for l in libxml2_cflags.split(" "):
+ if l.find('-I') == 0:
+ incdir.append(l.replace("-I", "", 1))
+
+
+
+# libxml2 - library flags
+def libxml2_lib(libdir, libs):
+ libdir.append(get_python_lib(1))
+ if os_path.exists("/etc/debian_version"): #. XXX: Debian Workaround...
+ libdir.append("/usr/lib/pymodules/python%d.%d"%sys.version_info[0:2])
+
+ (res, libxml2_libs) = commands.getstatusoutput("xml2-config --libs")
+ if res != 0:
+ print "Could not build python-dmidecode."
+ print "Could not run xml2-config, is libxml2 installed?"
+ print "Also the development libraries?"
+ sys.exit(1)
+
+ # Parse the xml2-config --libs response
+ for l in libxml2_libs.split(" "):
+ if l.find('-L') == 0:
+ libdir.append(l.replace("-L", "", 1))
+ elif l.find('-l') == 0:
+ libs.append(l.replace("-l", "", 1))
+
+ # this library is not reported and we need it anyway
+ libs.append('xml2mod')
+
+
+
+# Get version from src/version.h
+def get_version():
+ version = "0.0.0"
+ try:
+ f = open("src/version.h")
+ except:
+ f = open("version.h")
+
+ try:
+ for line in f:
+ part = line.split(" ")
+ if part[0] == "#define":
+ if part[1] == "VERSION":
+ version = part[2].strip().strip('"')
+ break
+ finally:
+ f.close()
+
+ return version
+
diff --git a/src/types.h b/src/types.h
index b124ecf..5f3dcd4 100644
--- a/src/types.h
+++ b/src/types.h
@@ -1,3 +1,29 @@
+/*
+ * This file is part of the dmidecode project.
+ *
+ * Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
#ifndef TYPES_H
#define TYPES_H
@@ -21,25 +47,25 @@ typedef unsigned int u32;
#ifdef BIGENDIAN
typedef struct {
- u32 h;
- u32 l;
+ u32 h;
+ u32 l;
} u64;
#else
typedef struct {
- u32 l;
- u32 h;
+ u32 l;
+ u32 h;
} u64;
#endif
#ifdef ALIGNMENT_WORKAROUND
static inline u64 U64(u32 low, u32 high)
{
- u64 self;
-
- self.l=low;
- self.h=high;
-
- return self;
+ u64 self;
+
+ self.l = low;
+ self.h = high;
+
+ return self;
}
#endif
diff --git a/src/util.c b/src/util.c
index 15d24a7..014b75d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,3 +1,4 @@
+
/*
* Common "util" functions
* This file is part of the dmidecode project.
@@ -48,46 +49,41 @@
#include "util.h"
#ifndef USE_MMAP
-static int myread(int fd, u8 *buf, size_t count, const char *prefix)
+static int myread(int fd, u8 * buf, size_t count, const char *prefix)
{
- ssize_t r = 1;
- size_t r2 = 0;
-
- while (r2 != count && r != 0)
- {
- r = read(fd, buf + r2, count - r2);
- if (r == -1)
- {
- if (errno != EINTR)
- {
- close(fd);
- perror(prefix);
- return -1;
- }
- }
- else
- r2 += r;
- }
-
- if (r2 != count)
- {
- close(fd);
- fprintf(stderr, "%s: Unexpected end of file\n", prefix);
- return -1;
- }
-
- return 0;
+ ssize_t r = 1;
+ size_t r2 = 0;
+
+ while(r2 != count && r != 0) {
+ r = read(fd, buf + r2, count - r2);
+ if(r == -1) {
+ if(errno != EINTR) {
+ close(fd);
+ perror(prefix);
+ return -1;
+ }
+ } else
+ r2 += r;
+ }
+
+ if(r2 != count) {
+ close(fd);
+ fprintf(stderr, "%s: Unexpected end of file\n", prefix);
+ return -1;
+ }
+
+ return 0;
}
#endif
-int checksum(const u8 *buf, size_t len)
+int checksum(const u8 * buf, size_t len)
{
- u8 sum = 0;
- size_t a;
+ u8 sum = 0;
+ size_t a;
- for (a = 0; a < len; a++)
- sum += buf[a];
- return (sum == 0);
+ for(a = 0; a < len; a++)
+ sum += buf[a];
+ return (sum == 0);
}
/*
@@ -96,110 +92,101 @@ int checksum(const u8 *buf, size_t len)
*/
void *mem_chunk(size_t base, size_t len, const char *devmem)
{
- void *p;
- int fd;
+ void *p;
+ int fd;
+
#ifdef USE_MMAP
- size_t mmoffset;
- void *mmp;
+ size_t mmoffset;
+ void *mmp;
#endif
- if ((fd = open(devmem, O_RDONLY)) == -1)
- {
- perror(devmem);
- return NULL;
- }
-
- if ((p = malloc(len)) == NULL)
- {
- perror("malloc");
- return NULL;
- }
+ if((fd = open(devmem, O_RDONLY)) == -1) {
+ perror(devmem);
+ return NULL;
+ }
+ if((p = malloc(len)) == NULL) {
+ perror("malloc");
+ return NULL;
+ }
#ifdef USE_MMAP
#ifdef _SC_PAGESIZE
- mmoffset = base % sysconf(_SC_PAGESIZE);
+ mmoffset = base % sysconf(_SC_PAGESIZE);
#else
- mmoffset = base % getpagesize();
+ mmoffset = base % getpagesize();
#endif /* _SC_PAGESIZE */
- /*
- * Please note that we don't use mmap() for performance reasons here,
- * but to workaround problems many people encountered when trying
- * to read from /dev/mem using regular read() calls.
- */
- mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
- if (mmp == MAP_FAILED)
- {
- fprintf(stderr, "%s: ", devmem);
- perror("mmap");
- free(p);
- return NULL;
- }
-
- memcpy(p, (u8 *)mmp + mmoffset, len);
-
- if (munmap(mmp, mmoffset + len) == -1)
- {
- fprintf(stderr, "%s: ", devmem);
- perror("munmap");
- }
+ /*
+ * Please note that we don't use mmap() for performance reasons here,
+ * but to workaround problems many people encountered when trying
+ * to read from /dev/mem using regular read() calls.
+ */
+ mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
+ if(mmp == MAP_FAILED) {
+ fprintf(stderr, "%s: ", devmem);
+ perror("mmap");
+ free(p);
+ return NULL;
+ }
+
+ memcpy(p, (u8 *) mmp + mmoffset, len);
+
+ if(munmap(mmp, mmoffset + len) == -1) {
+ fprintf(stderr, "%s: ", devmem);
+ perror("munmap");
+ }
#else /* USE_MMAP */
- if (lseek(fd, base, SEEK_SET) == -1)
- {
- fprintf(stderr, "%s: ", devmem);
- perror("lseek");
- free(p);
- return NULL;
- }
-
- if (myread(fd, p, len, devmem) == -1)
- {
- free(p);
- return NULL;
- }
+ if(lseek(fd, base, SEEK_SET) == -1) {
+ fprintf(stderr, "%s: ", devmem);
+ perror("lseek");
+ free(p);
+ return NULL;
+ }
+
+ if(myread(fd, p, len, devmem) == -1) {
+ free(p);
+ return NULL;
+ }
#endif /* USE_MMAP */
- if (close(fd) == -1)
- perror(devmem);
+ if(close(fd) == -1)
+ perror(devmem);
- return p;
+ return p;
}
int write_dump(size_t base, size_t len, const void *data, const char *dumpfile, int add)
{
- FILE *f;
-
- f = fopen(dumpfile, add ? "r+b" : "wb");
- if (!f)
- {
- fprintf(stderr, "%s: ", dumpfile);
- perror("fopen");
- return -1;
- }
-
- if (fseek(f, base, SEEK_SET) != 0)
- {
- fprintf(stderr, "%s: ", dumpfile);
- perror("fseek");
- goto err_close;
- }
-
- if (fwrite(data, len, 1, f) != 1)
- {
- fprintf(stderr, "%s: ", dumpfile);
- perror("fwrite");
- goto err_close;
- }
-
- if (fclose(f))
- {
- fprintf(stderr, "%s: ", dumpfile);
- perror("fclose");
- return -1;
- }
-
- return 0;
-
-err_close:
- fclose(f);
- return -1;
+ FILE *f;
+
+ f = fopen(dumpfile, add ? "r+b" : "wb");
+ if(!f) {
+ fprintf(stderr, "%s: ", dumpfile);
+ perror("fopen");
+ return -1;
+ }
+
+ if(fseek(f, base, SEEK_SET) != 0) {
+ fprintf(stderr, "%s: ", dumpfile);
+ perror("fseek");
+ goto err_close;
+ }
+
+ if(fwrite(data, len, 1, f) != 1) {
+ fprintf(stderr, "%s: ", dumpfile);
+ perror("fwrite");
+ goto err_close;
+ }
+
+ if(fclose(f)) {
+ fprintf(stderr, "%s: ", dumpfile);
+ perror("fclose");
+ return -1;
+ }
+
+ return 0;
+
+ err_close:
+ fclose(f);
+ return -1;
}
+
diff --git a/src/util.h b/src/util.h
index 894bd2f..3effd0c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,3 +1,4 @@
+
/*
* This file is part of the dmidecode project.
*
@@ -24,6 +25,6 @@
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
-int checksum(const u8 *buf, size_t len);
+int checksum(const u8 * buf, size_t len);
void *mem_chunk(size_t base, size_t len, const char *devmem);
int write_dump(size_t base, size_t len, const void *data, const char *dumpfile, int add);
diff --git a/src/version.h b/src/version.h
index 050cf7a..70ea80d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define VERSION "2.9"
+#define VERSION "3.10.6"
diff --git a/src/xmlpythonizer.c b/src/xmlpythonizer.c
new file mode 100644
index 0000000..ba018eb
--- /dev/null
+++ b/src/xmlpythonizer.c
@@ -0,0 +1,1183 @@
+/*. ******* coding:utf-8 AUTOHEADER START v1.1 *******
+ *. vim: fileencoding=utf-8 syntax=c sw=8 ts=8 et
+ *.
+ *. © 2009 David Sommerseth <davids@redhat.com>
+ *. © 2007-2009 Nima Talebi <nima@autonomy.net.au>
+ *.
+ *. This file is part of Python DMI-Decode.
+ *.
+ *. Python DMI-Decode is free software: you can redistribute it and/or modify
+ *. it under the terms of the GNU General Public License as published by
+ *. the Free Software Foundation, either version 2 of the License, or
+ *. (at your option) any later version.
+ *.
+ *. Python DMI-Decode is distributed in the hope that it will be useful,
+ *. but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *. GNU General Public License for more details.
+ *.
+ *. You should have received a copy of the GNU General Public License
+ *. along with Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ *.
+ *. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ *. EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ *. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *.
+ *. ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ *. AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ *.
+ *. $AutoHeaderSerial::20090522 $
+ *. ******* AUTOHEADER END v1.1 ******* */
+
+/* Converts XML docs and nodes to Python dicts and lists by
+ * using an XML file which describes the Python dict layout
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+/**
+ * @file xmlpythonizer.c
+ * @brief Generic parser for converting XML documents or XML nodes
+ * into Python Dictionaries
+ * @author David Sommerseth <davids@redhat.com>
+ * @author Nima Talebi <nima@autonomy.net.au>
+ */
+
+
+#include <Python.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#include "util.h"
+#include "dmixml.h"
+#include "dmierror.h"
+#include "xmlpythonizer.h"
+#include "version.h"
+
+
+/**
+ * This functions appends a new ptzMAP structure to an already existing chain
+ * @author David Sommerseth <davids@redhat.com>
+ * @param ptzMAP* Pointer to the chain the new ptzMAP is to be appended
+ * @param ptzMAP* Pointer to the new ptzMAP to be appended to the already existing ptzMAP
+ * @return ptzMAP* Pointer to the ptzMAP which includes the newly added ptzMAP
+ */
+ptzMAP *ptzmap_AppendMap(const ptzMAP *chain, ptzMAP *newmap)
+{
+ if( chain != NULL ) {
+ newmap->next = (ptzMAP *) chain;
+ }
+ return newmap;
+}
+
+
+/**
+ * This function creates a new ptzMAP mapping record. This defines the key/value relationship in
+ * the resulting Python Dictionaries.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param ptzMAP* Pointer to the chain the new mapping will be appended
+ * @param char* XPath root of the given key and value XPath expressions.
+ * If NULL, the key and value XPath expressions must be absolute.
+ * @param ptzTYPES Type of the 'key' value
+ * @param const char* XPath expression or constant string for the 'key' value
+ * @param ptzTYPES Type of the 'value' value
+ * @param const char* XPath expression or constant string for the 'value' value
+ * @param ptzMAP* Used if the value type is of one of the ptzDICT types, contains a new
+ * mapping level for the children
+ * @return ptzMAP* Pointer to the ptzMAP which includes the newly added ptzMAP
+ */
+ptzMAP *ptzmap_Add(const ptzMAP *chain, char *rootp,
+ ptzTYPES ktyp, const char *key,
+ ptzTYPES vtyp, const char *value,
+ ptzMAP *child)
+{
+ ptzMAP *ret = NULL;
+
+ assert( (ktyp == ptzCONST) || (ktyp == ptzSTR) || (ktyp == ptzINT) || (ktyp == ptzFLOAT) );
+ assert( key != NULL );
+
+ ret = (ptzMAP *) malloc(sizeof(ptzMAP)+2);
+ assert( ret != NULL );
+ memset(ret, 0, sizeof(ptzMAP)+2);
+
+ if( rootp != NULL ) {
+ ret->rootpath = strdup(rootp);
+ }
+
+ ret->type_key = ktyp;
+ ret->key = strdup(key);
+
+ ret->type_value = vtyp;
+ if( value != NULL ) {
+ ret->value = strdup(value);
+ }
+
+ if( child != NULL ) {
+ ret->child = child;
+ }
+
+ return ptzmap_AppendMap(chain, ret);
+};
+
+
+/**
+ * This functions sets an ptzLIST typed map entry as a fixed list
+ * @author David Sommerseth <davids@redhat.com>
+ * @param ptzMAP* Pointer to the ptzMAP elemnt to be updated
+ * @param const char* Attribute name of the XML node of the 'key' to use as the list index
+ * @param int Defines the size of the list
+ */
+void ptzmap_SetFixedList(ptzMAP *map_p, const char *index, int size)
+{
+ assert( map_p != NULL );
+
+ switch( map_p->type_value ) {
+ case ptzLIST_STR:
+ case ptzLIST_INT:
+ case ptzLIST_FLOAT:
+ case ptzLIST_BOOL:
+ map_p->list_index = strdup(index);
+ map_p->fixed_list_size = size;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/**
+ * This functions frees up a complete pointer chain. This is normally called via #define ptzmap_Free()
+ * @author David Sommerseth <davids@redhat.com>
+ * @param ptzMAP* Pointer to the ptzMAP to free
+ */
+void ptzmap_Free_func(ptzMAP *ptr)
+{
+ if( ptr == NULL ) {
+ return;
+ }
+
+ if( ptr->rootpath != NULL ) {
+ free(ptr->rootpath);
+ ptr->rootpath = NULL;
+ }
+
+ if( ptr->list_index != NULL ) {
+ free(ptr->list_index);
+ ptr->list_index = NULL;
+ }
+
+ if( ptr->emptyValue != NULL ) {
+ free(ptr->emptyValue);
+ ptr->emptyValue = NULL;
+ }
+
+ free(ptr->key);
+ ptr->key = NULL;
+
+ if( ptr->value != NULL ) {
+ free(ptr->value);
+ ptr->value = NULL;
+ }
+
+ if( ptr->child != NULL ) {
+ ptzmap_Free(ptr->child);
+ }
+ if( ptr->next != NULL ) {
+ ptzmap_Free(ptr->next);
+ }
+ free(ptr);
+}
+
+
+#if 0
+// DEBUG FUNCTIONS
+static const char *ptzTYPESstr[] = { "ptzCONST", "ptzSTR", "ptzINT", "ptzFLOAT", "ptzBOOL",
+ "ptzLIST_STR", "ptzLIST_INT", "ptzLIST_FLOAT", "ptzLIST_BOOL",
+ "ptzDICT", "ptzLIST_DICT", NULL };
+
+void indent(int lvl)
+{
+ int i = 0;
+ if( lvl == 0 ) {
+ return;
+ }
+
+ for( i = 0; i < (lvl * 3); i++ ) {
+ printf(" ");
+ }
+}
+
+
+#define ptzmap_Dump(ptr) { ptzmap_Dump_func(ptr, 0); }
+void ptzmap_Dump_func(const ptzMAP *ptr, int level)
+{
+ if( ptr == NULL ) {
+ return;
+ }
+
+ if( ptr->rootpath != NULL ) {
+ indent(level); printf("root path: %s\n", ptr->rootpath);
+ }
+ indent(level); printf("key type: (%i) %-13.13s - key: %s\n",
+ ptr->type_key, ptzTYPESstr[ptr->type_key], ptr->key);
+ indent(level); printf("value type: (%i) %-13.13s - value: %s %s\n",
+ ptr->type_value, ptzTYPESstr[ptr->type_value], ptr->value,
+ (ptr->emptyIsNone ? "(EmptyIsNone)": ""));
+ if( ptr->list_index != NULL ) {
+ indent(level);
+ printf("List index: %s - Fixed size: %i\n",
+ ptr->list_index, ptr->fixed_list_size);
+ }
+ if( ptr->child != NULL ) {
+ indent(level); printf(" ** CHILD\n");
+ ptzmap_Dump_func(ptr->child, level + 1);
+ indent(level); printf(" ** ---------\n");
+ }
+ if( ptr->next != NULL ) {
+ printf("\n");
+ ptzmap_Dump_func(ptr->next, level);
+ }
+}
+#endif // END OF DEBUG FUNCTIONS
+
+
+/**
+ * This functions converts a string to valid ptzTYPES values. This is used when parsing the XML mapping nodes
+ * @author David Sommerseth <davids@redhat.com>
+ * @param const char* String value containing the key/value type
+ * @return ptzTYPES The type value
+ */
+inline ptzTYPES _convert_maptype(const char *str) {
+ if( strcmp(str, "string") == 0 ) {
+ return ptzSTR;
+ } else if( strcmp(str, "constant") == 0 ) {
+ return ptzCONST;
+ } else if( strcmp(str, "integer") == 0 ) {
+ return ptzINT;
+ } else if( strcmp(str, "float") == 0 ) {
+ return ptzFLOAT;
+ } else if( strcmp(str, "boolean") == 0 ) {
+ return ptzBOOL;
+ } else if( strcmp(str, "list:string") == 0 ) {
+ return ptzLIST_STR;
+ } else if( strcmp(str, "list:integer") == 0 ) {
+ return ptzLIST_INT;
+ } else if( strcmp(str, "list:float") == 0 ) {
+ return ptzLIST_FLOAT;
+ } else if( strcmp(str, "list:boolean") == 0 ) {
+ return ptzLIST_BOOL;
+ } else if( strcmp(str, "dict") == 0 ) {
+ return ptzDICT;
+ } else if( strcmp(str, "list:dict") == 0 ) {
+ return ptzLIST_DICT;
+ } else {
+ fprintf(stderr, "Unknown field type: %s - defaulting to 'constant'\n", str);
+ return ptzCONST;
+ }
+}
+
+
+/**
+ * This functions is the internal parser - SubMapper (Individual Types of a Group)
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* Node of the starting point for the parsing
+ * @return ptzMAP* The ptzMAP version of the XML definition
+ */
+ptzMAP *_do_dmimap_parsing_typeid(xmlNode *node) {
+ ptzMAP *retmap = NULL;
+ xmlNode *ptr_n = NULL, *map_n = NULL;;
+
+ // Go to the next XML_ELEMENT_NODE
+ foreach_xmlnode(node, map_n) {
+ if( map_n->type == XML_ELEMENT_NODE ) {
+ break;
+ }
+ }
+ if( map_n == NULL ) {
+ PyReturnError(PyExc_NameError, "No mapping nodes were found");
+ }
+
+ // Go to the first <Map> node
+ if( xmlStrcmp(node->name, (xmlChar *) "Map") != 0 ) {
+ map_n = dmixml_FindNode(node, "Map");
+ if( map_n == NULL ) {
+ // If we don't find a <Map> node, we just exit now.
+ // Other checks will raise an exception if needed.
+ return NULL;
+ }
+ }
+
+ // Loop through it's children
+ foreach_xmlnode(map_n, ptr_n) {
+ ptzTYPES type_key, type_value;
+ char *key = NULL, *value = NULL;
+ char *rootpath = NULL;
+ char *listidx = NULL;
+ int fixedsize = 0;
+ if( ptr_n->type != XML_ELEMENT_NODE ) {
+ continue;
+ }
+
+ // Get the attributes defining key, keytype, value and valuetype
+ key = dmixml_GetAttrValue(ptr_n, "key");
+ type_key = _convert_maptype(dmixml_GetAttrValue(ptr_n, "keytype"));
+
+ value = dmixml_GetAttrValue(ptr_n, "value");
+ type_value = _convert_maptype(dmixml_GetAttrValue(ptr_n, "valuetype"));
+
+ rootpath = dmixml_GetAttrValue(ptr_n, "rootpath");
+
+ listidx = dmixml_GetAttrValue(ptr_n, "index_attr");
+ if( listidx != NULL ) {
+ char *fsz = dmixml_GetAttrValue(ptr_n, "fixedsize");
+ fixedsize = (fsz != NULL ? atoi(fsz) : 0);
+ }
+
+ if( (type_value == ptzDICT) || (type_value == ptzLIST_DICT) ) {
+ // When value type is ptzDICT, traverse the children nodes
+ // - should contain another Map set instead of a value attribute
+ if( ptr_n->children == NULL ) {
+ continue;
+ }
+ // Recursion
+ retmap = ptzmap_Add(retmap, rootpath, type_key, key, type_value,
+ (type_value == ptzLIST_DICT ? value : NULL),
+ _do_dmimap_parsing_typeid(ptr_n->children->next));
+ } else {
+ char *tmpstr = NULL;
+
+ // Append the value as a normal value when the
+ // value type is not a Python Dict
+ retmap = ptzmap_Add(retmap, rootpath, type_key, key, type_value, value, NULL);
+
+ // Set emptyIsNone flag
+ if( (tmpstr = dmixml_GetAttrValue(ptr_n, "emptyIsNone")) != NULL ) {
+ switch( retmap->type_value ) {
+ case ptzSTR:
+ case ptzINT:
+ case ptzFLOAT:
+ case ptzBOOL:
+ case ptzLIST_STR:
+ case ptzLIST_INT:
+ case ptzLIST_FLOAT:
+ case ptzLIST_BOOL:
+ retmap->emptyIsNone = (tmpstr[0] == '1' ? 1 : 0);
+ break;
+ default:
+ break;
+ }
+ }
+ if( (tmpstr = dmixml_GetAttrValue(ptr_n, "emptyValue")) != NULL ) {
+ retmap->emptyValue = strdup(tmpstr);
+ }
+ }
+
+ if( (retmap != NULL) && (listidx != NULL) && (fixedsize > 0) ) {
+ ptzmap_SetFixedList(retmap, listidx, fixedsize);
+ }
+
+ value = NULL;
+ key = NULL;
+ }
+
+ return retmap;
+}
+
+/**
+ * This functions validates and retrieves the root node of the dmidecode_mapping XML node from an XML document
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlDoc* XML mapping document pointer
+ * @return xmlNode* The root xmlNode of a valid XML mapping document. On invalid document NULL is returned.
+ */
+xmlNode *dmiMAP_GetRootElement(xmlDoc *mapdoc) {
+ xmlNode *rootnode = NULL;
+
+ // Find the root tag and locate our mapping
+ rootnode = xmlDocGetRootElement(mapdoc);
+ assert( rootnode != NULL );
+
+ // Verify that the root node got the right name
+ if( (rootnode == NULL)
+ || (xmlStrcmp(rootnode->name, (xmlChar *) "dmidecode_mapping") != 0 )) {
+ PyReturnError(PyExc_IOError, "Invalid XML-Python mapping file. "
+ "Root node is not 'dmidecode_mapping'");
+ }
+
+ // Verify that it's of a version we support
+ if( strcmp(dmixml_GetAttrValue(rootnode, "version"), "1") != 0 ) {
+ PyReturnError(PyExc_RuntimeError, "Unsupported XML-Python mapping file format. "
+ "Only version 1 is supported");
+ }
+ return rootnode;
+}
+
+
+/**
+ * Internal function which looks up the given Type ID among TypeMap nodes and and parses
+ * the found XML nodes into a ptzMAP
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* The node where the TypeMapping tags are found
+ * @param const char* The typeid to parse to a ptzMAP
+ * @return ptzMAP* The parsed result of the XML nodes
+ */
+ptzMAP *_dmimap_parse_mapping_node_typeid(xmlNode *mapnode, const char *typeid) {
+ xmlNode *node = NULL;
+
+ assert( mapnode != NULL);
+
+ // Find the <TypeMap> tag with our type ID
+ node = dmixml_FindNodeByAttr_NoCase(mapnode, "TypeMap", "id", typeid);
+ if( node == NULL ) {
+ // No exception handling possible here, as we don't return PyObject
+ fprintf(stderr,"** WARNING: Could not find any XML->Python "
+ "mapping for type ID '%s'", typeid);
+ return NULL;
+ }
+ // Create an internal map structure and return this structure
+ return _do_dmimap_parsing_typeid(node);
+}
+
+
+/**
+ * Exported function for parsing a XML mapping document for a given Type ID to a ptzMAP
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlDoc* Pointer to the XML mapping document
+ * @param const char* The Type ID to create the map for
+ * @return ptzMAP* The parsed XML containing as a ptzMAP
+ */
+ptzMAP *dmiMAP_ParseMappingXML_TypeID(xmlDoc *xmlmap, int typeid) {
+ xmlNode *node = NULL;
+ char typeid_s[16];
+
+ node = dmiMAP_GetRootElement(xmlmap);
+ if( node == NULL ) {
+ PyReturnError(PyExc_RuntimeError, "Could not locate root XML node for mapping file");
+ }
+
+ memset(&typeid_s, 0, 16);
+ snprintf(typeid_s, 14, "0x%02X", typeid);
+
+ // Find the <TypeMapping> section
+ node = dmixml_FindNode(node, "TypeMapping");
+ assert( node != NULL );
+ return _dmimap_parse_mapping_node_typeid(node, typeid_s);
+}
+
+
+/**
+ * Internal parser for GroupMapping (group of types). Converts a given GroupMapping to a ptzMAP
+ * from a XML node set
+ * @author Nima Talebi <nima@autonomy.net.au>
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlNode* The source XML nodes of what to parse to a ptzMAP
+ * @param xmlDoc* A pointer to the source map, used for further parsing of each type defined in the GroupMapping
+ * @return ptzMAP* The resulting ptzMAP of the parsed xmlNode group mapping
+ */
+ptzMAP *_do_dmimap_parsing_group(xmlNode *node, xmlDoc *xmlmap) {
+ ptzMAP *retmap = NULL;
+ xmlNode *ptr_n = NULL, *map_n = NULL, *typemap = NULL;
+ char *type_id;
+
+ // Go to the next XML_ELEMENT_NODE
+ foreach_xmlnode(node, map_n) {
+ if( map_n->type == XML_ELEMENT_NODE ) {
+ break;
+ }
+ }
+ if( map_n == NULL ) {
+ PyReturnError(PyExc_RuntimeError, "Could not find any valid XML nodes");
+ }
+
+ // Check that our "root" node is as expected
+ if( xmlStrcmp(node->name, (xmlChar *) "Mapping") != 0 ) {
+ PyReturnError(PyExc_NameError, "Expected to find <Mapping> node");
+ }
+
+ // Go to the first <TypeMap> node
+ map_n = dmixml_FindNode(node, "TypeMap");
+ if( map_n == NULL ) {
+ PyReturnError(PyExc_NameError, "Could not locate any <TypeMap> nodes");
+ }
+
+ // Get the root element of the <TypeMapping> tag, needed for further parsing
+ typemap = dmixml_FindNode(xmlDocGetRootElement(xmlmap), "TypeMapping");
+ if( typemap == NULL ) {
+ PyReturnError(PyExc_NameError, "Could not locate the <TypeMapping> node");
+ }
+
+ // Loop through it's children
+ foreach_xmlnode(map_n, ptr_n) {
+ // Validate if we have the right node name
+ if( xmlStrcmp(ptr_n->name, (xmlChar *) "TypeMap") != 0 ) {
+ continue; // Skip unexpected tag names
+ }
+
+ // Make sure that we have an id attribute before trying to locate that in th
+ if( (type_id = dmixml_GetAttrValue(ptr_n, "id")) != NULL) {
+ ptzMAP *map = NULL;
+
+ map = _dmimap_parse_mapping_node_typeid(typemap, type_id);
+ if( map ) {
+ retmap = ptzmap_AppendMap(retmap, map);
+ }
+ }
+ }
+ return retmap;
+}
+
+
+/**
+ * Exported function which parses a given GroupMapping (consisting of
+ * one or more TypeMaps) into a ptzMAP
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlDoc* Pointer to the XML document holding the mapping
+ * @param const char* Defines which group mapping to parse to a ptzMAP
+ * @return ptzMAP* The parsed XML mapping in a ptzMAP
+ */
+ptzMAP *dmiMAP_ParseMappingXML_GroupName(xmlDoc *xmlmap, const char *mapname) {
+ xmlNode *node = NULL;
+
+ // Validate the XML mapping document and get the root element
+ node = dmiMAP_GetRootElement(xmlmap);
+ if( node == NULL ) {
+ PyReturnError(PyExc_RuntimeError, "No valid mapping XML recieved");
+ }
+
+ // Find the <GroupMapping> section
+ node = dmixml_FindNode(node, "GroupMapping");
+ if( node == NULL ) {
+ PyReturnError(PyExc_NameError, "Could not find the <GroupMapping> node");
+ }
+
+ // Find the <Mapping> section matching our request (mapname)
+ node = dmixml_FindNodeByAttr(node, "Mapping", "name", mapname);
+ if( node == NULL ) {
+ PyReturnError(PyExc_NameError, "No group mapping for '%s' was found "
+ "in the XML-Python mapping file", mapname);
+ }
+
+ // Create an internal map structure and return this structure
+ return _do_dmimap_parsing_group(node, xmlmap);
+}
+
+
+/**
+ * Internal function for converting a given mapped value to the appropriate Python data type
+ * @author David Sommerseth <davids@redhat.com>
+ * @param ptzMAP* Pointer to the current mapping entry being parsed
+ * @param const char * String which contains the value to be converted to a Python value
+ * @return PyObject * The converted value as a Python object
+ */
+inline PyObject *StringToPyObj(ptzMAP *val_m, const char *instr) {
+ PyObject *value;
+ const char *workstr = NULL;
+
+ if( instr == NULL ) {
+ return Py_None;
+ }
+
+ if( (val_m->emptyIsNone == 1) || (val_m->emptyValue != NULL) ) {
+ char *cp = strdup(instr);
+ char *cp_p = NULL;
+ assert( cp != NULL );
+
+ // Trim the string for trailing spaces
+ cp_p = cp + strlen(cp) - 1;
+ while( (cp_p >= cp) && (*cp_p == ' ') ) {
+ *cp_p = 0;
+ cp_p--;
+ }
+
+ // If our copy pointer is the same
+ // or less than the starting point,
+ // there is no data here
+ if( cp_p <= cp ) {
+ free(cp);
+ if( val_m->emptyIsNone == 1 ) {
+ return Py_None;
+ }
+ if( val_m->emptyValue != NULL ) {
+ workstr = (const char *)val_m->emptyValue;
+ }
+ } else {
+ free(cp);
+ }
+ }
+
+ if( workstr == NULL ) {
+ workstr = instr;
+ }
+
+
+ switch( val_m->type_value ) {
+ case ptzINT:
+ case ptzLIST_INT:
+ value = PyInt_FromLong(atoi(workstr));
+ break;
+
+ case ptzFLOAT:
+ case ptzLIST_FLOAT:
+ value = PyFloat_FromDouble(atof(workstr));
+ break;
+
+ case ptzBOOL:
+ case ptzLIST_BOOL:
+ value = PyBool_FromLong((atoi(workstr) == 1 ? 1:0));
+ break;
+
+ case ptzSTR:
+ case ptzLIST_STR:
+ value = PyString_FromString(workstr);
+ break;
+
+ default:
+ fprintf(stderr, "Invalid type '%i' for value '%s'\n", val_m->type_value, instr);
+ value = Py_None;
+ }
+ return value;
+}
+
+
+/**
+ * Retrieves a value from the data XML doc (via XPath Context) based on a XPath query
+ * @author David Sommerseth <davids@redhat.com>
+ * @param xmlXPathContext* Pointer to the XPath context holding the source data
+ * @param const char* The XPath expression where to find the data
+ * @return xmlXPathObject* If data is found, it is returned in an XPath object for further processing
+ */
+
+xmlXPathObject *_get_xpath_values(xmlXPathContext *xpctx, const char *xpath) {
+ xmlChar *xp_xpr = NULL;
+ xmlXPathObject *xp_obj = NULL;
+
+ if( xpath == NULL ) {
+ return NULL;
+ }
+
+ xp_xpr = xmlCharStrdup(xpath);
+ xp_obj = xmlXPathEvalExpression(xp_xpr, xpctx);
+ assert( xp_obj != NULL );
+ free(xp_xpr);
+
+ return xp_obj;
+}
+
+
+/**
+ * Retrieves the value which is to be used as the key value in a Python dictionary.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param char* Pointer to the return buffer for the value
+ * @param size_t Size of the return buffer
+ * @param ptzMAP* Pointer to the current mapping entry which is being parsed
+ * @param xmlXPathContext* Pointer to the XPath context containing the source data
+ * @param int Defines which of the XPath results to use, if more is found
+ * @returns char* Returns a pointer to the return buffer (parameter 1) if key value
+ * is found, or NULL if not found
+ */
+char *_get_key_value(char *key, size_t buflen, ptzMAP *map_p, xmlXPathContext *xpctx, int idx) {
+ xmlXPathObject *xpobj = NULL;
+
+ memset(key, 0, buflen);
+
+ switch( map_p->type_key ) {
+ case ptzCONST:
+ strncpy(key, map_p->key, buflen-1);
+ break;
+
+ case ptzSTR:
+ case ptzINT:
+ case ptzFLOAT:
+ xpobj = _get_xpath_values(xpctx, map_p->key);
+ if( xpobj == NULL ) {
+ return NULL;
+ }
+ if( dmixml_GetXPathContent(key, buflen, xpobj, idx) == NULL ) {
+ xmlXPathFreeObject(xpobj);
+ return NULL;
+ }
+ xmlXPathFreeObject(xpobj);
+ break;
+
+ default:
+ fprintf(stderr, "Unknown key type: %i\n", map_p->type_key);
+ return NULL;
+ }
+ // We consider to have a key, if the first byte is a readable
+ // character (usually starting at 0x20/32d)
+ return ((key != NULL) && (strlen(key) > 0) ? key : NULL) ;
+}
+
+
+/**
+ * Simple define to properly add a key/value pair to a Python dictionary
+ * @author David Sommerseth <davids@redhat.com>
+ * @param PyObject* Pointer to the Python dictionary to be updated
+ * @param const char* String containing the key value
+ * @param PyObject* Pointer to the Python value
+ */
+
+#define PyADD_DICT_VALUE(p, k, v) { \
+ PyDict_SetItemString(p, k, v); \
+ if( v != Py_None ) { \
+ Py_DECREF(v); \
+ } \
+ }
+
+
+/**
+ * Internal function for adding a XPath result to the resulting Python dictionary
+ * @author David Sommerseth <davids@redhat.com>
+ * @param PyObject* Pointer to the resulting Python dictionary
+ * @param xmlXPathContext* Pointer to the XPath context containing the source data
+ * (used for retrieving the key value)
+ * @param ptzMAP* Pointer to the current mapping entry being parsed
+ * @param xmlXPathObject* Pointer to XPath object containing the data value(s) for the dictionary
+ */
+inline void _add_xpath_result(PyObject *pydat, xmlXPathContext *xpctx, ptzMAP *map_p, xmlXPathObject *value) {
+ int i = 0;
+ char *key = NULL;
+ char *val = NULL;
+
+ assert( pydat != NULL && value != NULL );
+
+ key = (char *) malloc(258);
+ assert( key != NULL );
+
+ val = (char *) malloc(4098);
+ assert( val != NULL );
+
+ switch( value->type ) {
+ case XPATH_NODESET:
+ if( value->nodesetval == NULL ) {
+ break;
+ }
+ if( value->nodesetval->nodeNr == 0 ) {
+ if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ PyADD_DICT_VALUE(pydat, key, Py_None);
+ }
+ } else {
+ for( i = 0; i < value->nodesetval->nodeNr; i++ ) {
+ if( _get_key_value(key, 256, map_p, xpctx, i) != NULL ) {
+ dmixml_GetXPathContent(val, 4097, value, i);
+ PyADD_DICT_VALUE(pydat, key, StringToPyObj(map_p, val));
+ }
+ }
+ }
+ break;
+ default:
+ if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ dmixml_GetXPathContent(val, 4097, value, 0);
+ PyADD_DICT_VALUE(pydat, key, StringToPyObj(map_p, val));
+ }
+ break;
+ }
+ free(key);
+ free(val);
+}
+
+
+/**
+ * Internal XML parser routine, which traverses the given mapping table,
+ * returning a Python structure accordingly to the map. Data for the Python dictionary is
+ * take from the input XML node.
+ * @author David Sommerseth <davids@redhat.com>
+ * @param PyObject* Pointer to the Python dictionary of the result
+ * @param ptzMAP* Pointer to the starting point for the further parsing
+ * @param xmlNode* Pointer to the XML node containing the source data
+ * @param int For debug purpose only, to keep track of which element being parsed
+ * @return PyObject* Pointer to the input Python dictionary
+ */
+PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int elmtid) {
+ char *key = NULL;
+ xmlXPathContext *xpctx = NULL;
+ xmlDoc *xpdoc = NULL;
+ xmlXPathObject *xpo = NULL;
+ PyObject *value = NULL;
+ int i;
+
+ xpdoc = xmlNewDoc((xmlChar *) "1.0");
+ assert( xpdoc != NULL );
+ xmlDocSetRootElement(xpdoc, xmlCopyNode(data_n, 1));
+
+ xpctx = xmlXPathNewContext(xpdoc);
+ assert( xpctx != NULL );
+ xpctx->node = data_n;
+
+ key = (char *) malloc(258);
+ assert( key != NULL );
+
+ // Extract value
+ switch( map_p->type_value ) {
+ case ptzCONST:
+ if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ value = PyString_FromString(map_p->value);
+ PyADD_DICT_VALUE(retdata, key, value);
+ } else {
+ PyReturnError(PyExc_ValueError, "Could not get key value: %s [%i] (Defining key: %s)",
+ map_p->rootpath, elmtid, map_p->key);
+ }
+ break;
+
+ case ptzSTR:
+ case ptzINT:
+ case ptzFLOAT:
+ case ptzBOOL:
+ xpo = _get_xpath_values(xpctx, map_p->value);
+ if( xpo != NULL ) {
+ _add_xpath_result(retdata, xpctx, map_p, xpo);
+ xmlXPathFreeObject(xpo);
+ }
+ break;
+
+ case ptzLIST_STR:
+ case ptzLIST_INT:
+ case ptzLIST_FLOAT:
+ case ptzLIST_BOOL:
+ xpo = _get_xpath_values(xpctx, map_p->value);
+ if( xpo != NULL ) {
+ if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ if( (xpo->nodesetval != NULL) && (xpo->nodesetval->nodeNr > 0) ) {
+ value = PyList_New(0);
+
+ // If we're working on a fixed list, create one which contains
+ // only Py_None objects. Otherwise the list will be filled with
+ // <nil> elements.
+ if( map_p->fixed_list_size > 0 ) {
+ for( i = 0; i < map_p->fixed_list_size; i++ ) {
+ PyList_Append(value, Py_None);
+ }
+ }
+
+ for( i = 0; i < xpo->nodesetval->nodeNr; i++ ) {
+ char *valstr = NULL;
+ valstr = (char *) malloc(4098);
+ dmixml_GetXPathContent(valstr, 4097, xpo, i);
+
+ // If we have a fixed list and we have a index value for the list
+ if( (map_p->fixed_list_size > 0) && (map_p->list_index != NULL) ) {
+ char *idx = NULL;
+
+ idx = dmixml_GetAttrValue(xpo->nodesetval->nodeTab[i],
+ map_p->list_index);
+ if( idx != NULL ) {
+ PyList_SetItem(value, atoi(idx)-1,
+ StringToPyObj(map_p, valstr)
+ );
+ }
+ } else {
+ // No list index - append the value
+ PyList_Append(value, StringToPyObj(map_p, valstr));
+ }
+ free(valstr);
+ }
+ } else {
+ value = Py_None;
+ }
+ PyADD_DICT_VALUE(retdata, key, value);
+ xmlXPathFreeObject(xpo);
+ } else {
+ PyReturnError(PyExc_ValueError, "Could not get key value: "
+ "%s [%i] (Defining key: %s)",
+ map_p->rootpath, elmtid, map_p->key);
+ }
+ }
+ break;
+
+ case ptzDICT:
+ // Traverse children nodes
+ if( map_p->child == NULL ) {
+ break;
+ }
+ if( _get_key_value(key, 256, map_p, xpctx, 0) == NULL ) {
+ PyReturnError(PyExc_ValueError,
+ "Could not get key value: %s [%i] (Defining key: %s)",
+ map_p->rootpath, elmtid, map_p->key);
+ }
+ // Use recursion when procession child elements
+ value = pythonizeXMLnode(map_p->child, data_n);
+ PyADD_DICT_VALUE(retdata, key, (value != NULL ? value : Py_None));
+ break;
+
+ case ptzLIST_DICT: // List of dict arrays
+ if( map_p->child == NULL ) {
+ break;
+ }
+ if( _get_key_value(key, 256, map_p, xpctx, 0) == NULL ) {
+ PyReturnError(PyExc_ValueError,
+ "Could not get key value: %s [%i] (Defining key: %s)",
+ map_p->rootpath, elmtid, map_p->key);
+ }
+
+ // Iterate all nodes which is found in the 'value' XPath
+ xpo = _get_xpath_values(xpctx, map_p->value);
+ if( (xpo == NULL) || (xpo->nodesetval == NULL) || (xpo->nodesetval->nodeNr == 0) ) {
+ if( xpo != NULL ) {
+ xmlXPathFreeObject(xpo);
+ }
+ PyReturnError(PyExc_ValueError,
+ "Could not get key value: %s [%i] (Defining key: %s)",
+ map_p->rootpath, elmtid, map_p->key);
+ }
+
+ // Prepare a data list
+ value = PyList_New(0);
+
+ // If we're working on a fixed list, create one which contains
+ // only Py_None objects. Otherwise the list will be filled with
+ // <nil> elements.
+ if( map_p->fixed_list_size > 0 ) {
+ for( i = 0; i < map_p->fixed_list_size; i++ ) {
+ PyList_Append(value, Py_None);
+ }
+ }
+
+ for( i = 0; i < xpo->nodesetval->nodeNr; i++ ) {
+ PyObject *dataset = NULL;
+
+ dataset = pythonizeXMLnode(map_p->child, xpo->nodesetval->nodeTab[i]);
+ if( dataset != NULL ) {
+ // If we have a fixed list and we have a index value for the list
+ if( (map_p->fixed_list_size > 0) && (map_p->list_index != NULL) ) {
+ char *idx = NULL;
+ idx = dmixml_GetAttrValue(xpo->nodesetval->nodeTab[i],
+ map_p->list_index);
+ if( idx != NULL ) {
+ PyList_SetItem(value, atoi(idx)-1, dataset);
+ }
+ } else {
+ // No list index - append the value
+ PyList_Append(value, dataset);
+ }
+ } else {
+ // If NULL, something is wrong - exception is already set.
+ return NULL;
+ }
+ }
+ PyADD_DICT_VALUE(retdata, key, value);
+ xmlXPathFreeObject(xpo);
+ break;
+
+ default:
+ fprintf(stderr, "Unknown value type: %i\n", map_p->type_value);
+ break;
+ }
+
+ free(key);
+ xmlXPathFreeContext(xpctx);
+ xmlFreeDoc(xpdoc);
+ return retdata;
+}
+
+
+/**
+ * Exported function, for parsing a XML node to a Python dictionary based on the given ptzMAP
+ * @author David Sommerseth <davids@redhat.com>
+ * @param ptzMAP* The map descriping the resulting Python dictionary
+ * @param xmlNode* XML node pointer to the source data to be used for populating the Python dictionary
+ */
+PyObject *pythonizeXMLnode(ptzMAP *in_map, xmlNode *data_n) {
+ xmlXPathContext *xpctx = NULL;
+ xmlDoc *xpdoc = NULL;
+ PyObject *retdata = NULL;
+ ptzMAP *map_p = NULL;
+ char *key = NULL;
+
+ if( (in_map == NULL) || (data_n == NULL) ) {
+ PyReturnError(PyExc_RuntimeError, "pythonXMLnode() - xmlNode or ptzMAP is NULL");
+ }
+
+ key = (char *) malloc(258);
+ if( key == NULL ) {
+ PyReturnError(PyExc_MemoryError, "Could not allocate temporary buffer");
+ }
+
+ // Loop through all configured elements
+ retdata = PyDict_New();
+ foreach_xmlnode(in_map, map_p) {
+ if( (map_p->type_value == ptzDICT) && (map_p->rootpath != NULL) ) {
+ xmlXPathObject *xpo = NULL;
+ int i;
+
+ // Set the root node in the XPath context
+ xpdoc = xmlNewDoc((xmlChar *) "1.0");
+ assert( xpdoc != NULL );
+ xmlDocSetRootElement(xpdoc, xmlCopyNode(data_n, 1));
+
+ xpctx = xmlXPathNewContext(xpdoc);
+ if( xpctx == NULL ) {
+ PyReturnError(PyExc_MemoryError, "Could not setup new XPath context");
+ }
+ xpctx->node = data_n;
+
+ xpo = _get_xpath_values(xpctx, map_p->rootpath);
+ if( (xpo != NULL) && (xpo->nodesetval != NULL) && (xpo->nodesetval->nodeNr > 0) ) {
+ for( i = 0; i < xpo->nodesetval->nodeNr; i++ ) {
+ xpctx->node = xpo->nodesetval->nodeTab[i];
+
+ if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ PyObject *res = _deep_pythonize(retdata, map_p,
+ xpo->nodesetval->nodeTab[i], i);
+ if( res == NULL ) {
+ // Exit if we get NULL - something is wrong
+ //and exception is set
+ return NULL;
+ }
+ }
+ }
+ xmlXPathFreeContext(xpctx);
+ xmlFreeDoc(xpdoc);
+ }
+#ifdef DEBUG
+ else {
+ fprintf(stderr, "** pythonizeXMLnode :: Could not locate node for key value: "
+ "root path '%s', key '%s'\n", map_p->rootpath, map_p->key);
+ }
+#endif
+ if( xpo != NULL ) {
+ xmlXPathFreeObject(xpo); xpo = NULL;
+ }
+ } else {
+ PyObject *res = _deep_pythonize(retdata, map_p, data_n, 0);
+ if( res == NULL ) {
+ // Exit if we get NULL - something is wrong
+ //and exception is set
+ return NULL;
+ }
+ }
+ }
+ free(key);
+ return retdata;
+}
+
+
+/**
+ * Exported function, for parsing a XML document to a Python dictionary based on the given ptzMAP
+ * @author David Sommerseth <davids@redhat.com>
+ * @param ptzMAP* The map descriping the resulting Python dictionary
+ * @param xmlDoc* XML document pointer to the source data to be used for populating the Python dictionary
+ */
+PyObject *pythonizeXMLdoc(ptzMAP *map, xmlDoc *doc)
+{
+ xmlNode *node = NULL;
+
+ node = xmlDocGetRootElement(doc);
+ return pythonizeXMLnode(map, node);
+}
+
+
+#if 0
+// Simple independent main function - only for debugging
+int main(int argc, char **argv) {
+ xmlDoc *doc = NULL, *data = NULL;
+ ptzMAP *map = NULL;
+ PyObject *pydat = NULL;
+
+ Py_Initialize();
+
+ doc = xmlReadFile("pymap.xml", NULL, 0);
+ assert( doc != NULL );
+
+ map = dmiMAP_ParseMappingXML_GroupName(doc, argv[1]);
+ // map = dmiMAP_ParseMappingXML_TypeID(doc, atoi(rgv[1]));
+ ptzmap_Dump(map);
+ printf("----------------------\n");
+ assert(map != NULL);
+
+ data = xmlReadFile(argv[2], NULL, 0);
+ assert( data != NULL );
+
+ pydat = pythonizeXMLdoc(map, data);
+ assert( pydat != NULL );
+
+ Py_INCREF(pydat);
+ printf("\n\n");
+ PyObject_Print(pydat, stdout, 0);
+ Py_DECREF(pydat);
+ printf("\n\n");
+ ptzmap_Free(map);
+ xmlFreeDoc(data);
+ xmlFreeDoc(doc);
+
+ return 0;
+}
+#endif
+
+#if 0
+// Simple test module for Python - only for debugging
+PyObject* demo_xmlpy()
+{
+ xmlDoc *doc = NULL, *mapping_xml = NULL;
+ ptzMAP *mapping = NULL;
+ PyObject *ret = NULL;
+
+ // Read the XML-Python mapping setup
+ mapping_xml = xmlReadFile("pythonmap.xml", NULL, 0);
+ assert( mapping_xml != NULL );
+
+ mapping = dmiMAP_ParseMappingXML(mapping_xml, "bios");
+ assert( mapping != NULL );
+
+ // Read XML data from file
+ doc = xmlReadFile("cpu.xml", NULL, 0);
+ assert( doc != NULL );
+
+ // Create a PyObject out of the XML indata
+ ret = pythonizeXMLdoc(mapping, doc);
+
+ // Clean up and return the data
+ ptzmap_Free(mapping);
+ xmlFreeDoc(doc);
+ xmlFreeDoc(mapping_xml);
+
+ return ret;
+}
+
+static PyMethodDef DemoMethods[] = {
+ {"xmlpy", demo_xmlpy, METH_NOARGS, ""},
+ {NULL, NULL, 0, NULL}
+};
+
+PyMODINIT_FUNC initxmlpythonizer(void) {
+ PyObject *module =
+ Py_InitModule3((char *)"xmlpythonizer", DemoMethods,
+ "XML to Python Proof-of-Concept Python Module");
+
+ PyObject *version = PyString_FromString(VERSION);
+ Py_INCREF(version);
+ PyModule_AddObject(module, "version", version);
+}
+#endif // Python test module
+
+
diff --git a/src/xmlpythonizer.h b/src/xmlpythonizer.h
new file mode 100644
index 0000000..df60140
--- /dev/null
+++ b/src/xmlpythonizer.h
@@ -0,0 +1,60 @@
+/* Converts XML docs and nodes to Python dicts and lists by
+ * using an XML file which describes the Python dict layout
+ *
+ * Copyright 2009 David Sommerseth <davids@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+#ifndef _XMLPYTHONIZER_H
+#define _XMLPYTHONIZER_H
+
+typedef enum ptzTYPES_e { ptzCONST, ptzSTR, ptzINT, ptzFLOAT, ptzBOOL,
+ ptzLIST_STR, ptzLIST_INT, ptzLIST_FLOAT, ptzLIST_BOOL,
+ ptzDICT, ptzLIST_DICT } ptzTYPES;
+
+typedef struct ptzMAP_s {
+ char *rootpath; // XML root path for the data - if NULL, XML document is the root document.
+
+ ptzTYPES type_key; // Valid types: ptzCONST, ptzSTR, ptzINT, ptzFLOAT
+ char *key; // for ptzCONST key contains a static string, other types an XPath to XML data
+ ptzTYPES type_value;
+ char *value; // for ptzCONST key contains a static string,
+ // the rest of types, an XPath to XML data
+ int fixed_list_size; // Only to be used on lists
+ char *list_index ; // Only to be used on fixed lists
+ int emptyIsNone; // If set to 1, empty input (right trimmed) strings sets the result to Py_None
+ char *emptyValue; // If set, this value will be used when input is empty
+ struct ptzMAP_s *child; // Only used for type_value == (ptzDICT || ptzLIST_DICT)
+ struct ptzMAP_s *next; // Pointer chain
+
+} ptzMAP;
+
+xmlNode *dmiMAP_GetRootElement(xmlDoc *mapdoc);
+ptzMAP *dmiMAP_ParseMappingXML_TypeID(xmlDoc *xmlmap, int typeid);
+ptzMAP *dmiMAP_ParseMappingXML_GroupName(xmlDoc *xmlmap, const char *mapname);
+#define ptzmap_Free(ptr) { ptzmap_Free_func(ptr); ptr = NULL; }
+void ptzmap_Free_func(ptzMAP *ptr);
+
+PyObject *pythonizeXMLdoc(ptzMAP *map, xmlDoc *xmldoc);
+PyObject *pythonizeXMLnode(ptzMAP *map, xmlNode *nodes);
+
+#endif // _XMLPYTHONIZER_H