From 912c8ba257f0c0b05b3d5916da203bc8566c83af Mon Sep 17 00:00:00 2001 From: nima Date: Wed, 29 Oct 2008 07:10:24 +0000 Subject: Recoded the new work from upstream into these (main) files. The options to dump the memory image onto file, and read back from it has not yet been worked in, but the underlying work has been completed. git-svn-id: svn://svn.autonomy.net.au/python-dmidecode@83 abc39116-655e-4be6-ad55-d661dc543056 --- dmidecode.c | 757 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 383 insertions(+), 374 deletions(-) (limited to 'dmidecode.c') 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 = ""; ** 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; ilength-1)>>4)+1; row++) { - catsprintf(_, "{"); + fprintf(stderr, "{"); for(i=0; i<16 && ilength-(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= 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=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=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, ""); - } else if(opt.string!=NULL - && opt.string->type==h.type - && opt.string->offsettype==h.type) + dmi_table_string_py(&h, data, hDict, ver); + /* && opt.string->offsetlookup!=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); -- cgit