diff options
-rw-r--r-- | dmidecode.c | 757 | ||||
-rw-r--r-- | dmidecode.h | 8 | ||||
-rw-r--r-- | dmidecodemodule.c | 6 | ||||
-rw-r--r-- | dmidecodemodule.h | 3 |
4 files changed, 390 insertions, 384 deletions
diff --git a/dmidecode.c b/dmidecode.c index 102225c..3aef036 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -67,8 +67,7 @@ #include "dmiopt.h" #include "dmioem.h" -#include "global.h" -#include "catsprintf.h" +#include "dmihelper.h" /* */ @@ -81,7 +80,7 @@ static const char *bad_index = "<BAD INDEX>"; ** Type-independant Stuff */ -static PyObject *dmi_string_py(struct dmi_header *dm, u8 s) { +static PyObject *dmi_string_py(const struct dmi_header *dm, u8 s) { char *bp=(char *)dm->data; size_t i, len; @@ -105,11 +104,11 @@ static PyObject *dmi_string_py(struct dmi_header *dm, u8 s) { return data; } -const char *dmi_string(struct dmi_header *dm, u8 s) { - char *bp=(char *)dm->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"; + if(s == 0) return "Not Specified"; bp += dm->length; while(s>1 && *bp) { @@ -121,7 +120,7 @@ const char *dmi_string(struct dmi_header *dm, u8 s) { if(!*bp) return bad_index; /* ASCII filtering */ - len=strlen(bp); + len = strlen(bp); for(i=0; i<len; i++) if(bp[i]<32 || bp[i]==127) bp[i]='.'; @@ -133,7 +132,7 @@ const char *dmi_string(struct dmi_header *dm, u8 s) { static const char *dmi_smbios_structure_type(u8 code) { - static const char *type[]={ + static const char *type[] = { "BIOS", /* 0 */ "System", "Base Board", @@ -192,27 +191,27 @@ const char *dmi_dump(struct dmi_header *h, char *_) { sprintf(_, "Header and Data"); for(row=0; row<((h->length-1)>>4)+1; row++) { - catsprintf(_, "{"); + fprintf(stderr, "{"); for(i=0; i<16 && i<h->length-(row<<4); i++) - catsprintf(_, "%s%02x", i?" ":"", (h->data)[(row<<4)+i]); - catsprintf(_, "}"); + fprintf(stderr, "%s%02x", i?" ":"", (h->data)[(row<<4)+i]); + fprintf(stderr, "}"); } if((h->data)[h->length] || (h->data)[h->length+1]) { - catsprintf(_, "Strings:"); + fprintf(stderr, "Strings:"); i=1; while((s=dmi_string(h, i++))!=bad_index) { if(opt.flags & FLAG_DUMP) { int j, l = strlen(s)+1; for(row=0; row<((l-1)>>4)+1; row++) { - catsprintf(_, "{"); + fprintf(stderr, "{"); for(j=0; j<16 && j<l-(row<<4); j++) - catsprintf(_, "%s%02x", j?" ":"", s[(row<<4)+j]); - catsprintf(_, "}"); + fprintf(stderr, "%s%02x", j?" ":"", s[(row<<4)+j]); + fprintf(stderr, "}"); } - catsprintf(_, "\"%s\"|", s); + fprintf(stderr, "\"%s\"|", s); } - else catsprintf(_, "%s|", s); + else fprintf(stderr, "%s|", s); } } return _; @@ -313,7 +312,7 @@ static PyObject* dmi_bios_characteristics_x2(u8 code) { ** 3.3.2 System Information (Type 1) */ -PyObject *dmi_system_uuid_py(u8 *p) { +PyObject *dmi_system_uuid_py(const u8 *p, u16 ver) { int only0xFF=1, only0x00=1; int i; @@ -328,41 +327,26 @@ PyObject *dmi_system_uuid_py(u8 *p) { if(only0x00) return PyString_FromString("Not Settable"); - 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] - ); -} - -const char *dmi_system_uuid(u8 *p, char *_) { //. FIXME: KILLME (Replace all calls to this by above function) - 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) { - sprintf(_, "Not Present"); - return _; - } - - if(only0x00) { - sprintf(_, "Not Settable"); - return _; - } - - sprintf( - _, "%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] - ); - - 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) + 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] + ); } - /* 3.3.2.1 */ static PyObject *dmi_system_wake_up_type(u8 code) { static const char *type[]={ @@ -431,7 +415,7 @@ static PyObject *dmi_base_board_type(u8 code) { return OUT_OF_SPEC; } -static PyObject *dmi_base_board_handles(u8 count, u8 *p) { +static PyObject *dmi_base_board_handles(u8 count, const u8 *p) { int i; PyObject *dict = PyDict_New(); @@ -479,7 +463,9 @@ const char *dmi_chassis_type(u8 code) { "Sealed-case PC", "Multi-system", "CompactPCI", - "AdvancedTCA" /* 0x1B */ + "AdvancedTCA", /* 0x1B */ + "Blade", + "Blade Enclosing" /* 0x1D */ }; if(code>=0x01 && code<=0x1B) @@ -541,24 +527,33 @@ static PyObject *dmi_chassis_power_cords(u8 code) { else return PyString_FromFormat("%i", code); } -static const char *dmi_chassis_elements(u8 count, u8 len, u8 *p, char *_) { +static PyObject *dmi_chassis_elements(u8 count, u8 len, const u8 *p) { int i; - sprintf(_, "Contained Elements:%i", count); + PyObject *data = PyDict_New(); + PyDict_SetItemString(data, "Contained Elements", PyInt_FromLong(count)); + + PyObject *_key, *_val; for(i=0; i<count; i++) { if(len>=0x03) { - catsprintf(_, "%s (", + + _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))); - if(p[1+i*len]==p[2+i*len]) - catsprintf(_, "%i", p[1+i*len]); - else - catsprintf(_, "%i-%i", p[1+i*len], p[2+i*len]); - catsprintf(_, ")"); + PyString_AS_STRING(dmi_base_board_type(p[i*len]&0x7F)) + ); + + 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]); + + PyDict_SetItem(data, _key, _val); + + Py_DECREF(_key); + Py_DECREF(_val); } } - return _; + + return data; } /******************************************************************************* @@ -580,276 +575,165 @@ static PyObject *dmi_processor_type(u8 code) { return OUT_OF_SPEC; } -const char *dmi_processor_family(u8 code) { +static const char *dmi_processor_family(u16 code) { + unsigned int i; + /* 3.3.5.2 */ - static const char *family[256] = { - NULL, /* 0x00 */ - "Other", - "Unknown", - "8086", - "80286", - "80386", - "80486", - "8087", - "80287", - "80387", - "80487", - "Pentium", - "Pentium Pro", - "Pentium II", - "Pentium MMX", - "Celeron", - "Pentium II Xeon", - "Pentium III", - "M1", - "M2", - NULL, /* 0x14 */ - NULL, - NULL, - NULL, /* 0x17 */ - "Duron", - "K5", - "K6", - "K6-2", - "K6-3", - "Athlon", - "AMD2900", - "K6-2+", - "Power PC", - "Power PC 601", - "Power PC 603", - "Power PC 603+", - "Power PC 604", - "Power PC 620", - "Power PC x704", - "Power PC 750", - NULL, /* 0x28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL,/* 0x2F */ - "Alpha", - "Alpha 21064", - "Alpha 21066", - "Alpha 21164", - "Alpha 21164PC", - "Alpha 21164a", - "Alpha 21264", - "Alpha 21364", - NULL, /* 0x38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x3F */ - "MIPS", - "MIPS R4000", - "MIPS R4200", - "MIPS R4400", - "MIPS R4600", - "MIPS R10000", - NULL, /* 0x46 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x4F */ - "SPARC", - "SuperSPARC", - "MicroSPARC II", - "MicroSPARC IIep", - "UltraSPARC", - "UltraSPARC II", - "UltraSPARC IIi", - "UltraSPARC III", - "UltraSPARC IIIi", - NULL, /* 0x59 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x5F */ - "68040", - "68xxx", - "68000", - "68010", - "68020", - "68030", - NULL, /* 0x66 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x6F */ - "Hobbit", - NULL, /* 0x71 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x77 */ - "Crusoe TM5000", - "Crusoe TM3000", - "Efficeon TM8000", - NULL, /* 0x7B */ - NULL, - NULL, - NULL, - NULL, /* 0x7F */ - "Weitek", - NULL, /* 0x81 */ - "Itanium", - "Athlon 64", - "Opteron", - "Sempron", - "Turion 64", - "Dual-Core Opteron", - "Athlon 64 X2", - NULL, /* 0x89 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x8F */ - "PA-RISC", - "PA-RISC 8500", - "PA-RISC 8000", - "PA-RISC 7300LC", - "PA-RISC 7200", - "PA-RISC 7100LC", - "PA-RISC 7100", - NULL, /* 0x97 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x9F */ - "V30", - NULL, /* 0xA1 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0xAF */ - "Pentium III Xeon", - "Pentium III Speedstep", - "Pentium 4", - "Xeon", - "AS400", - "Xeon MP", - "Athlon XP", - "Athlon MP", - "Itanium 2", - "Pentium M", - "Celeron D", - "Pentium D", - "Pentium EE", - NULL, /* 0xBD */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0xC7 */ - "IBM390", - "G4", - "G5", - NULL, /* 0xCB */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0xF9 */ - "i860", - "i960", - NULL, /* 0xFC */ - NULL, - NULL, - NULL /* 0xFF */ - /* master.mif has values beyond that, but they can't be used for DMI */ + 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" }, + + { 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" }, + + { 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" }, + + { 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" }, + + { 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" }, + + { 0xBF, "Core 2 Duo" }, + + { 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" }, }; - if(family[code]!=NULL) return family[code]; + for(i=0; i<ARRAY_SIZE(family2); i++) + if (family2[i].value == code) + return family2[i].name; + return out_of_spec; } -static PyObject *dmi_processor_family_py(u8 code) { +static PyObject *dmi_processor_family_py(u16 code) { return PyString_FromString(dmi_processor_family(code)); } -static PyObject *dmi_processor_id(u8 type, u8 *p, const char *version) { +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 */ @@ -1021,13 +905,13 @@ static PyObject *dmi_processor_voltage(u8 code) { return data; } -int dmi_processor_frequency(u8 *p) { +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(u8 *p) { +static PyObject *dmi_processor_frequency_py(const u8 *p) { return PyInt_FromLong(dmi_processor_frequency(p)); } @@ -1067,9 +951,12 @@ static PyObject *dmi_processor_upgrade(u8 code) { "Socket 754", "Socket 940", "Socket 939", - "Socket mPGA604", + "Socket mPGA604", "Socket LGA771", - "Socket LGA775" /* 0x15 */ + "Socket LGA775", /* 0x15 */ + "Socket S1", + "Socket AM2", + "Socket F (1207)" /* 0x18 */ }; if(code>=0x01 && code<=0x15) return PyString_FromString(upgrade[code-0x01]); @@ -1192,7 +1079,7 @@ static PyObject *dmi_memory_controller_speeds(u16 code) { return data; } -static PyObject *dmi_memory_controller_slots(u8 count, u8 *p) { +static PyObject *dmi_memory_controller_slots(u8 count, const u8 *p) { int i; PyObject *data = PyList_New(count); @@ -1784,7 +1671,7 @@ static PyObject *dmi_bios_languages(struct dmi_header *h) { ** 3.3.15 Group Associations (Type 14) */ -static PyObject *dmi_group_associations_items(u8 count, u8 *p) { +static PyObject *dmi_group_associations_items(u8 count, const u8 *p) { int i; PyObject *data = PyList_New(count); @@ -1817,7 +1704,7 @@ static const char *dmi_event_log_method(u8 code) { return out_of_spec; } -static const char *dmi_event_log_status(u8 code, char *_) { +static PyObject *dmi_event_log_status_py(u8 code) { static const char *valid[]={ "Invalid", /* 0 */ "Valid" /* 1 */ @@ -1827,28 +1714,26 @@ static const char *dmi_event_log_status(u8 code, char *_) { "Full" /* 1 */ }; - sprintf(_, " %s, %s", valid[(code>>0)&1], full[(code>>1)&1]); - return _; + return PyString_FromFormat("%s, %s", valid[(code>>0)&1], full[(code>>1)&1]); } -static const char *dmi_event_log_address(u8 method, u8 *p, char *_) { +static PyObject *dmi_event_log_address_py(u8 method, const u8 *p) { /* 3.3.16.3 */ switch(method) { case 0x00: case 0x01: case 0x02: - catsprintf(_, " Index 0x%04x, Data 0x%04x", WORD(p), WORD(p+2)); + return PyString_FromFormat("Index 0x%04x, Data 0x%04x", WORD(p), WORD(p+2)); break; case 0x03: - catsprintf(_, " 0x%08x", DWORD(p)); + return PyString_FromFormat("0x%08x", DWORD(p)); break; case 0x04: - catsprintf(_, " 0x%04x", WORD(p)); + return PyString_FromFormat("0x%04x", WORD(p)); break; default: - catsprintf(_, " Unknown"); + return PyString_FromString("Unknown"); } - return _; } static const char *dmi_event_log_header_type(u8 code) { @@ -1918,7 +1803,7 @@ static PyObject *dmi_event_log_descriptor_format(u8 code) { return PyString_FromString(data); } -static PyObject *dmi_event_log_descriptors(u8 count, const u8 len, u8 *p) { +static PyObject *dmi_event_log_descriptors(u8 count, const u8 len, const u8 *p) { /* 3.3.16.1 */ int i; @@ -2404,7 +2289,7 @@ static PyObject *dmi_hardware_security_status(u8 code) { ** 3.3.26 System Power Controls (Type 25) */ -static PyObject *dmi_power_controls_power_on(u8 *p) { +static PyObject *dmi_power_controls_power_on(const u8 *p) { /* 3.3.26.1 */ PyObject *data = PyList_New(5); @@ -2678,7 +2563,7 @@ static PyObject *dmi_memory_channel_type(u8 code) { return data; } -static PyObject *dmi_memory_channel_devices(u8 count, u8 *p) { +static PyObject *dmi_memory_channel_devices(u8 count, const u8 *p) { PyObject *data = PyDict_New(); PyObject *subdata, *val; int i; @@ -2721,7 +2606,7 @@ static PyObject *dmi_ipmi_interface_type(u8 code) { return data; } -static PyObject *dmi_ipmi_base_address(u8 type, u8 *p, u8 lsb) { +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); @@ -2814,7 +2699,7 @@ static PyObject *dmi_power_supply_range_switching(u8 code) { PyObject* dmi_decode(struct dmi_header *h, u16 ver) { - u8 *data = h->data; + const u8 *data = h->data; //. 0xF1 --> 0xF100 //int minor = h->type<<8; @@ -2919,7 +2804,7 @@ PyObject* dmi_decode(struct dmi_header *h, u16 ver) { Py_DECREF(_val); if(h->length<0x19) break; - _val = dmi_system_uuid_py(data+0x08); + _val = dmi_system_uuid_py(data+0x08, ver); PyDict_SetItemString(caseData, "UUID", _val); Py_DECREF(_val); @@ -3047,11 +2932,8 @@ PyObject* dmi_decode(struct dmi_header *h, u16 ver) { PyDict_SetItemString(caseData, "Number Of Power Cords", _val); Py_DECREF(_val); - //. FIXME: Clean this block - Elements is not quite right, also - //. FIXME: dmi_chassis_elements should return PyObject when we know - //. FIXME: what the hell it is doing. if(h->length<0x15+data[0x13]*data[0x14]) break; - _val = PyString_FromString(dmi_chassis_elements(data[0x13], data[0x14], data+0x15, _)); + _val = dmi_chassis_elements(data[0x13], data[0x14], data+0x15); PyDict_SetItemString(caseData, "Elements", _val); Py_DECREF(_val); @@ -3071,7 +2953,9 @@ PyObject* dmi_decode(struct dmi_header *h, u16 ver) { PyDict_SetItemString(caseData, "Type", _val); Py_DECREF(_val); - _val = dmi_processor_family_py(data[0x06]); + _val = (data[0x06] == 0xFE && h->length >= 0x2A) + ? dmi_processor_family_py(WORD(data+0x28)) + : dmi_processor_family_py(data[0x06]); PyDict_SetItemString(caseData, "Family", _val); Py_DECREF(_val); @@ -3453,11 +3337,11 @@ PyObject* dmi_decode(struct dmi_header *h, u16 ver) { PyDict_SetItemString(caseData, "Access Method", _val); Py_DECREF(_val); - _val = PyString_FromFormat("%s", dmi_event_log_address(data[0x0A], data+0x10, _)); + _val = dmi_event_log_address_py(data[0x0A], data+0x10); PyDict_SetItemString(caseData, "Access Address", _val); Py_DECREF(_val); - _val = PyString_FromFormat("%s", dmi_event_log_status(data[0x0B], _)); + _val = dmi_event_log_status_py(data[0x0B]); PyDict_SetItemString(caseData, "Status", _val); Py_DECREF(_val); @@ -4389,22 +4273,82 @@ void to_dmi_header(struct dmi_header *h, u8 *data) { 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_FromFormat("%s", + data[0x06] == 0xFE && h->length >= 0x2A ? + dmi_processor_family(WORD(data + 0x28)) : + dmi_processor_family(data[offset]) + ); + 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); +} + +static void dmi_table_dump(u32 base, u16 len, const char *devmem) +{ + u8 *buf; + + if ((buf = mem_chunk(base, len, devmem)) == NULL) + { + fprintf(stderr, "Failed to read table, sorry.\n"); + return; + } + + printf("# Writing %d bytes to %s.\n", len, opt.dumpfile); + write_dump(32, len, buf, opt.dumpfile, 0); + free(buf); +} + + 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.flags & FLAG_DUMP_BIN) { + dmi_table_dump(base, len, devmem); + return; + } + if(!(opt.flags & FLAG_QUIET)) { if(opt.type==NULL) { dmiSetItem(pydata, "dmi_table_size", "%i structures occupying %i bytes", num, len); - dmiSetItem(pydata, "dmi_table_base", "Table at 0x%08x", base); + if (!(opt.flags & FLAG_FROM_DUMP)) + 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 - fprintf(stderr, "Table is unreachable, sorry. Try compiling dmidecode with -DUSE_MMAP."); + "Try compiling dmidecode with -DUSE_MMAP."; #endif + "\n"); return; } @@ -4442,7 +4386,7 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, P dmiSetItem(hDict, "dmi_handle", "0x%04x", h.handle); dmiSetItem(hDict, "dmi_type", "%d", h.type); dmiSetItem(hDict, "dmi_size", "%d", h.length); - //catsprintf(_, "Handle 0x%04x, DMI type %d, %d bytes", h.handle, h.type, h.length); + //fprintf(stderr, "Handle 0x%04x, DMI type %d, %d bytes", h.handle, h.type, h.length); //} /* assign vendor for vendor-specific decodes later */ @@ -4471,9 +4415,9 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, P } } else if(!(opt.flags & FLAG_QUIET)) fprintf(stderr, "<TRUNCATED>"); - } else if(opt.string!=NULL - && opt.string->type==h.type - && opt.string->offset<h.length) { + } else if(opt.string!=NULL && opt.string->type==h.type) + dmi_table_string_py(&h, data, hDict, ver); + /* && opt.string->offset<h.length) { if(opt.string->lookup!=NULL) { char _[512]; strcpy(_, opt.string->lookup(data[opt.string->offset])); @@ -4484,9 +4428,10 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, P dmiSetItem(hDict, "print", _); } else { dmiSetItem(hDict, "lookup", dmi_string(&h, data[opt.string->offset])); - //catsprintf(_, "%s\n", dmi_string(&h, data[opt.string->offset])); + //fprintf(stderr, "%s\n", dmi_string(&h, data[opt.string->offset])); } } + */ data=next; i++; @@ -4503,29 +4448,66 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, P free(buf); } +/* + * 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 smbios_decode(u8 *buf, const char *devmem, PyObject* pydata) { - if(checksum(buf, buf[0x05]) && memcmp(buf+0x10, "_DMI_", 5)==0 && checksum(buf+0x10, 0x0F)) { - if(pydata == NULL) return 1; + if(pydata == NULL) return 1; + if(!checksum(buf, buf[0x05]) || !memcmp(buf+0x10, "_DMI_", 5)==0 || !checksum(buf+0x10, 0x0F)) return 0; + u16 ver = (buf[0x06] << 8) + buf[0x07]; + /* Some BIOS attempt to encode version 2.3.1 as 2.31, fix it up */ + if(ver == 0x021F) { if(!(opt.flags & FLAG_QUIET)) - dmiSetItem(pydata, "detected", "SMBIOS %i.%i present.", buf[0x06], buf[0x07]); - dmi_table(DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C), (buf[0x06]<<8)+buf[0x07], devmem, pydata); - //. XXX dmiSetItem(pydata, "table", dmi_string(&h, data[opt.string->offset])); - return 1; + printf("SMBIOS version fixup (2.31 -> 2.3).\n"); + ver = 0x0203; } + if(!(opt.flags & FLAG_QUIET)) + dmiSetItem(pydata, "detected", "SMBIOS %i.%i present.", ver>>8, ver&0xFF); + dmi_table(DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C), ver, devmem, pydata); + //. XXX dmiSetItem(pydata, "table", dmi_string(&h, data[opt.string->offset])); - return 0; + if (opt.flags & FLAG_DUMP_BIN) { + u8 crafted[32]; + + memcpy(crafted, buf, 32); + overwrite_dmi_address(crafted + 0x10); + + printf("# Writing %d bytes to %s.\n", crafted[0x05], opt.dumpfile); + write_dump(0, crafted[0x05], crafted, opt.dumpfile, 1); + } + + return 1; } int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata) { - if(checksum(buf, 0x0F)) { - if(pydata == NULL) return 1; - if(!(opt.flags & FLAG_QUIET)) - dmiSetItem(pydata, "detected", "Legacy DMI %i.%i present.", buf[0x0E]>>4, buf[0x0E]&0x0F); + if(pydata == NULL) return 1; + if(!checksum(buf, 0x0F)) return 0; + if(!(opt.flags & FLAG_QUIET)) { + printf("Legacy DMI %u.%u present.\n", buf[0x0E]>>4, buf[0x0E]&0x0F); + dmiSetItem(pydata, "detected", "Legacy DMI %i.%i present.", buf[0x0E]>>4, buf[0x0E]&0x0F); dmi_table(DWORD(buf+0x08), WORD(buf+0x06), WORD(buf+0x0C), ((buf[0x0E]&0xF0)<<4)+(buf[0x0E]&0x0F), devmem, pydata); - return 1; } - return 0; + if(!(opt.flags & FLAG_QUIET)) { + u8 crafted[16]; + memcpy(crafted, buf, 16); + overwrite_dmi_address(crafted); + printf("# Writing %d bytes to %s.\n", 0x0F, opt.dumpfile); + write_dump(0, 0x0F, crafted, opt.dumpfile, 1); + } + + return 1; } /******************************************************************************* @@ -4617,6 +4599,33 @@ int submain(int argc, char * const argv[]) if(!(opt.flags & FLAG_QUIET)) sprintf(_, "# dmidecode %s\n", VERSION); + + /* Read from dump if so instructed */ + if (opt.flags & FLAG_FROM_DUMP) + { + if (!(opt.flags & FLAG_QUIET)) + printf("Reading SMBIOS/DMI data from file %s.\n", + opt.dumpfile); + if ((buf = mem_chunk(0, 0x20, opt.dumpfile)) == NULL) + { + ret = 1; + goto exit_free; + } + + if (memcmp(buf, "_SM_", 4)==0) + { + if (smbios_decode(buf, opt.dumpfile, NULL)) + found++; + } + else if (memcmp(buf, "_DMI_", 5)==0) + { + if (legacy_decode(buf, opt.dumpfile, NULL)) + found++; + } + goto done; + } + + /* First try EFI (ia64, Intel-based Mac) */ efi=address_from_efi(&fp, _); switch(efi) @@ -4665,7 +4674,7 @@ done: free(buf); if(!found && !(opt.flags & FLAG_QUIET)) - catsprintf(buffer, "# No SMBIOS nor DMI entry point found, sorry.\n"); + fprintf(stderr, "# No SMBIOS nor DMI entry point found, sorry.\n"); exit_free: //. free(opt.type); diff --git a/dmidecode.h b/dmidecode.h index 5a0a768..130f0c5 100644 --- a/dmidecode.h +++ b/dmidecode.h @@ -34,12 +34,10 @@ void to_dmi_header(struct dmi_header *h, u8 *data); int smbios_decode(u8 *buf, const char *devmem, PyObject* pydata); int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata); -const char *dmi_string(struct dmi_header *dm, u8 s); - +const char *dmi_string(const struct dmi_header *dm, u8 s); const char *dmi_system_uuid(u8 *p, char *_); -PyObject *dmi_system_uuid_py(u8 *p); +PyObject *dmi_system_uuid_py(const u8 *p, u16 ver); const char *dmi_chassis_type(u8 code); -const char *dmi_processor_family(u8 code); -int dmi_processor_frequency(u8 *p); +int dmi_processor_frequency(const u8 *p); int submain(int argc, char * const argv[]); diff --git a/dmidecodemodule.c b/dmidecodemodule.c index 57b499a..62d36c6 100644 --- a/dmidecodemodule.c +++ b/dmidecodemodule.c @@ -1,7 +1,7 @@ #include "dmidecodemodule.h" #include <mcheck.h> -static PyObject* dmidecode_get(PyObject *self, char* section) { +static PyObject* dmidecode_get(PyObject *self, const char* section) { //mtrace(); @@ -122,9 +122,9 @@ static PyObject* dmidecode_get_connector(PyObject *self, PyObject *args) { retur static PyObject* dmidecode_get_slot(PyObject *self, PyObject *args) { return dmidecode_get(self, "slot"); } static PyObject* dmidecode_get_type(PyObject *self, PyObject *args) { const char *s; - if(PyArg_ParseTuple(args, "s", &s)) { + if(PyArg_ParseTuple(args, "s", &s)) return dmidecode_get(self, s); - } + return Py_None; } PyMethodDef DMIDataMethods[] = { diff --git a/dmidecodemodule.h b/dmidecodemodule.h index 6143379..0be61b3 100644 --- a/dmidecodemodule.h +++ b/dmidecodemodule.h @@ -16,8 +16,7 @@ #define EFI_NOT_FOUND (-1) #define EFI_NO_SMBIOS (-2) -#include "global.h" -#include "catsprintf.h" +#include "dmihelper.h" extern const char *dmi_dump(struct dmi_header *h, char *_); //extern void dmi_decode(struct dmi_header *h, u16 ver, PyObject* pydata); |