diff options
author | David Sommerseth <davids@redhat.com> | 2009-08-11 11:34:21 +0200 |
---|---|---|
committer | David Sommerseth <davids@redhat.com> | 2009-08-11 11:34:21 +0200 |
commit | eb08fd406370a81172d7fdd0663233a5f140b784 (patch) | |
tree | c50e19f2b873441672b20a7e339c176d9a4a7cbf /src | |
parent | 39cbdfb56e80cabbd67754d8d77f781e14eaa3da (diff) | |
parent | 3165a97a06f891622b913714bc4f8ca54565f9cc (diff) | |
download | python-dmidecode-eb08fd406370a81172d7fdd0663233a5f140b784.tar.gz python-dmidecode-eb08fd406370a81172d7fdd0663233a5f140b784.tar.xz python-dmidecode-eb08fd406370a81172d7fdd0663233a5f140b784.zip |
Merge commit 'nima/xml'
Conflicts:
debian/changelog
Had the same changelog entry in both xml and master
branch, with a minor wording difference. Removed the
duplicate and merged in the changelog entries from the
XML branch
src/dmidecode.c
Merge process got confused by some functions which was not
changed. Removed the code coming from the master branch and
let the XML be the base.
src/setup-dbg.py
src/setup.py
In the XML branch, the version of the python-dmidecode is
now a function which retrieves the version number from
src/version.h. Merged in this feature to master as well.
Diffstat (limited to 'src')
-rw-r--r-- | src/config.h | 39 | ||||
-rw-r--r-- | src/dmidecode.c | 8809 | ||||
-rw-r--r-- | src/dmidecode.h | 39 | ||||
-rw-r--r-- | src/dmidecodemodule.c | 964 | ||||
-rw-r--r-- | src/dmidecodemodule.h | 87 | ||||
-rw-r--r-- | src/dmidump.c | 168 | ||||
-rw-r--r-- | src/dmidump.h | 37 | ||||
-rw-r--r-- | src/dmierror.c | 79 | ||||
-rw-r--r-- | src/dmierror.h | 54 | ||||
-rw-r--r-- | src/dmihelper.c | 115 | ||||
-rw-r--r-- | src/dmihelper.h | 189 | ||||
-rw-r--r-- | src/dmioem.c | 125 | ||||
-rw-r--r-- | src/dmioem.h | 1 | ||||
-rw-r--r-- | src/dmixml.c | 360 | ||||
-rw-r--r-- | src/dmixml.h | 79 | ||||
-rw-r--r-- | src/efi.c | 83 | ||||
-rw-r--r-- | src/efi.h | 35 | ||||
-rw-r--r-- | src/libxml_wrap.h | 280 | ||||
-rw-r--r-- | src/pymap.xml | 864 | ||||
-rw-r--r-- | src/setup-dbg.py | 77 | ||||
-rw-r--r-- | src/setup.py | 77 | ||||
-rw-r--r-- | src/setup_common.py | 93 | ||||
-rw-r--r-- | src/types.h | 46 | ||||
-rw-r--r-- | src/util.c | 235 | ||||
-rw-r--r-- | src/util.h | 3 | ||||
-rw-r--r-- | src/version.h | 2 | ||||
-rw-r--r-- | src/xmlpythonizer.c | 1183 | ||||
-rw-r--r-- | src/xmlpythonizer.h | 60 |
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, §_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 @@ -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; } + @@ -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 |