diff options
author | nima <nima@abc39116-655e-4be6-ad55-d661dc543056> | 2008-12-20 15:32:30 +0000 |
---|---|---|
committer | nima <nima@abc39116-655e-4be6-ad55-d661dc543056> | 2008-12-20 15:32:30 +0000 |
commit | 0e2598266442b8f1015c75833034ac0f26857820 (patch) | |
tree | f4fb3cb9a3ad6e0fb9f61cd437a0933623ac820b | |
parent | 6d5ebf5d39e419e2f83960223bf840275426dc87 (diff) | |
download | python-dmidecode-0e2598266442b8f1015c75833034ac0f26857820.tar.gz python-dmidecode-0e2598266442b8f1015c75833034ac0f26857820.tar.xz python-dmidecode-0e2598266442b8f1015c75833034ac0f26857820.zip |
Version information now set once during init().
Bettered test cases.
Case 127 magically fixed.
git-svn-id: svn://svn.autonomy.net.au/python-dmidecode@135 abc39116-655e-4be6-ad55-d661dc543056
-rw-r--r-- | src/dmidecode.c | 213 | ||||
-rw-r--r-- | src/dmidecode.h | 6 | ||||
-rw-r--r-- | src/dmidecodemodule.c | 105 | ||||
-rw-r--r-- | src/dmidecodemodule.h | 6 | ||||
-rwxr-xr-x | test.py | 126 |
5 files changed, 224 insertions, 232 deletions
diff --git a/src/dmidecode.c b/src/dmidecode.c index 564cd28..874720d 100644 --- a/src/dmidecode.c +++ b/src/dmidecode.c @@ -4658,33 +4658,78 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, P } -int smbios_decode(u8 *buf, const char *devmem, PyObject* pydata, PyObject* pydata_ver) { - if(pydata == NULL) return -1; //. TODO: Raise Exception - - 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) { fprintf(stderr, "SMBIOS version fixup (2.31 -> 2.3).\n"); ver = 0x0203; } - if(pydata_ver) { Py_DECREF(pydata_ver); } - pydata_ver = PyString_FromFormat("SMBIOS %i.%i present.", ver>>8, ver&0xFF); - Py_INCREF(pydata_ver); - dmi_table(DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C), ver, devmem, pydata); - return 1; + + +int _smbios_decode_check(u8 *buf, const char *devmem, PyObject** pydata) { + int check; + if(!checksum(buf, buf[0x05]) || !memcmp(buf+0x10, "_DMI_", 5)==0 || !checksum(buf+0x10, 0x0F)) check = 0; //. Bad + else check = 1; //. Good + return check; +} +int smbios_decode_set_version(u8 *buf, const char *devmem, PyObject** pydata) { + int check = _smbios_decode_check(buf, devmem, pydata); + char vbuf[64]; bzero(vbuf, 64); + if(check == 1) { + 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) { + sprintf(vbuf, "SMBIOS 2.3 present. (Version fixup 2.31 -> 2.3)."); + ver = 0x0203; + } else { + sprintf(vbuf, "SMBIOS %i.%i present.", ver>>8, ver&0xFF); + } + } else if(check == 0) { + sprintf(vbuf, "No SMBIOS nor DMI entry point found, sorry G."); + } + 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, devmem, &pydata); + if(check == 1) { + u16 ver = (buf[0x06] << 8) + buf[0x07]; + dmi_table(DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C), ver, devmem, pydata); + } + return check; } -int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata, PyObject* pydata_ver) { - if(pydata == NULL) return -1; //. TODO: Raise Exception - if(!checksum(buf, 0x0F)) return 0; - if(pydata_ver) { Py_DECREF(pydata_ver); } - pydata_ver = PyString_FromFormat("Legacy DMI %i.%i present.", buf[0x0E]>>4, buf[0x0E]&0x0F); - Py_INCREF(pydata_ver); - dmi_table(DWORD(buf+0x08), WORD(buf+0x06), WORD(buf+0x0C), ((buf[0x0E]&0xF0)<<4)+(buf[0x0E]&0x0F), devmem, pydata); - return 1; +int _legacy_decode_check(u8 *buf, const char *devmem, PyObject** pydata) { + 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, devmem, pydata); + 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, sorry G."); + } + 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, devmem, &pydata); + 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; +} + + + /******************************************************************************* ** Probe for EFI interface @@ -4725,129 +4770,3 @@ int address_from_efi(size_t *address) { return ret; } - -/* -int submain(int argc, char * const argv[]) -{ - int ret=0; / * Returned value * / - int found=0; - size_t fp; - int efi; - u8 *buf; - - char _[2048]; bzero(_, 2048); - - if(sizeof(u8)!=1 || sizeof(u16)!=2 || sizeof(u32)!=4 || '\0'!=0) - { - fprintf(stderr, "%s: compiler incompatibility\n", argv[0]); - exit(255); - } - - / * Set default option values * / - //. opt.devmem=DEFAULT_MEM_DEV; - //. opt.flags=0; - - if(parse_command_line(argc, argv)<0) - { - ret=2; - goto exit_free; - } - - if(opt.flags & FLAG_HELP) - { - print_help(); - goto exit_free; - } - - if(opt.flags & FLAG_VERSION) - { - sprintf(_, "%s\n", VERSION); - goto exit_free; - } - - 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) - { - case EFI_NOT_FOUND: - goto memory_scan; - case EFI_NO_SMBIOS: - ret=1; - goto exit_free; - } - - if((buf=mem_chunk(fp, 0x20, opt.devmem))==NULL) - { - ret=1; - goto exit_free; - } - - if(smbios_decode(buf, opt.devmem, NULL)) - found++; - goto done; - -memory_scan: - / * Fallback to memory scan (x86, x86_64) * / - if((buf=mem_chunk(0xF0000, 0x10000, opt.devmem))==NULL) - { - ret=1; - goto exit_free; - } - - for(fp=0; fp<=0xFFF0; fp+=16) - { - if(memcmp(buf+fp, "_SM_", 4)==0 && fp<=0xFFE0) - { - if(smbios_decode(buf+fp, opt.devmem, NULL)) - found++; - fp+=16; - } - else if(memcmp(buf+fp, "_DMI_", 5)==0) - { - if (legacy_decode(buf+fp, opt.devmem, NULL)) - found++; - } - } - -done: - free(buf); - - if(!found && !(opt.flags & FLAG_QUIET)) - fprintf(stderr, "# No SMBIOS nor DMI entry point found, sorry.\n"); - -exit_free: - //. free(opt.type); - - return ret; -} -*/ diff --git a/src/dmidecode.h b/src/dmidecode.h index 1673394..7e99faa 100644 --- a/src/dmidecode.h +++ b/src/dmidecode.h @@ -30,8 +30,10 @@ 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(u8 *buf, const char *devmem, PyObject* pydata, PyObject* pydata_ver); -int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata, PyObject* pydata_ver); +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); const char *dmi_string(const struct dmi_header *dm, u8 s); const char *dmi_system_uuid(u8 *p); diff --git a/src/dmidecodemodule.c b/src/dmidecodemodule.c index 06e5cf0..03001a8 100644 --- a/src/dmidecodemodule.c +++ b/src/dmidecodemodule.c @@ -62,19 +62,66 @@ u8 *parse_opt_type(u8 *p, const char *arg) { } +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; +} + + static PyObject* dmidecode_get(PyObject *self, const char* section) { //mtrace(); - /* This is `embedding API', not applicable to this dmidecode module which is `Extending' - Py_SetProgramName("dmidecode"); - int argc = 3; - char *argv[4]; - argv[0] = "dmidecode"; - argv[1] = "--type"; - argv[2] = section; - argv[3] = NULL; - */ - int ret=0; int found=0; size_t fp; @@ -83,13 +130,12 @@ static PyObject* dmidecode_get(PyObject *self, const char* section) { /* Set default option values */ opt.devmem = DEFAULT_MEM_DEV; - opt.flags=0; + opt.flags = 0; opt.type = NULL; - opt.type=parse_opt_type(opt.type, section); + opt.type = parse_opt_type(opt.type, section); if(opt.type==NULL) return NULL; PyObject* pydata = PyDict_New(); - PyObject* pydata_ver; /***********************************/ /* Read from dump if so instructed */ @@ -98,9 +144,9 @@ static PyObject* dmidecode_get(PyObject *self, const char* section) { //. 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, pydata_ver)) found++; + if(smbios_decode(buf, dumpfile, pydata)) found++; } else if (memcmp(buf, "_DMI_", 5)==0) { - if(legacy_decode(buf, dumpfile, pydata, pydata_ver)) found++; + if(legacy_decode(buf, dumpfile, pydata)) found++; } } else ret = 1; } else { /* Read from /dev/mem */ @@ -111,10 +157,10 @@ static PyObject* dmidecode_get(PyObject *self, const char* section) { 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, pydata_ver)) found++; + 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, pydata_ver)) found++; + if(legacy_decode(buf+fp, opt.devmem, pydata)) found++; } } } else ret = 1; @@ -122,20 +168,12 @@ static PyObject* dmidecode_get(PyObject *self, const char* section) { ret = 1; } else { if((buf=mem_chunk(fp, 0x20, opt.devmem))==NULL) ret = 1; - else if(smbios_decode(buf, opt.devmem, pydata, pydata_ver)) found++; + else if(smbios_decode(buf, opt.devmem, pydata)) found++; //. TODO: dmiSetItem(pydata, "efi_address", efiAddress); } } - if(ret==0) { - free(buf); - if(!found) { - if(!pydata_ver) { - pydata_ver = PyString_FromString("No SMBIOS nor DMI entry point found, sorry G."); - Py_INCREF(pydata_ver); - } - } - } + if(ret==0) free(buf); free(opt.type); //muntrace(); @@ -207,7 +245,7 @@ static PyObject* dmidecode_set_dev(PyObject *self, PyObject *arg) { //PyErr_Occurred(); } -/* TODO +/* typedef struct { PyObject_HEAD char *version; } ivars; @@ -240,5 +278,14 @@ static PyMethodDef DMIDataMethods[] = { PyMODINIT_FUNC initdmidecode(void) { init(); - (void)Py_InitModule((char *)"dmidecode", DMIDataMethods); + + PyObject *module = Py_InitModule3((char *)"dmidecode", DMIDataMethods, "Testing"); + + PyObject *version = PyString_FromString("2.10"); + Py_INCREF(version); + PyModule_AddObject(module, "version", version); + + PyObject *dmi_version = NULL; + dmidecode_set_version(&dmi_version); + PyModule_AddObject(module, "dmi", dmi_version); } diff --git a/src/dmidecodemodule.h b/src/dmidecodemodule.h index 00532bd..cf1e5f4 100644 --- a/src/dmidecodemodule.h +++ b/src/dmidecodemodule.h @@ -27,8 +27,10 @@ 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, PyObject* pydata_ver); -extern int legacy_decode(u8 *buf, const char *devmem, PyObject* pydata, PyObject* pydata_ver); +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); extern u8 *parse_opt_type(u8 *p, const char *arg); @@ -1,66 +1,88 @@ #!/usr/bin/env python -#.awk '$0 ~ /case [0-9]+: .. 3/ { print $2 }' src/dmidecode.c|tr ':\n' ', ' +#.awk '$0 ~ /case [0-9]+: .. 3/ { sys.stdout.write($2 }' src/dmidecode.c|tr ':\n' ', ' from pprint import pprint -import os, sys, random +import os, sys, random, tempfile, time -print "Importing module...", -import dmidecode -print "Done" +FH, DUMP = tempfile.mkstemp() +os.unlink(DUMP) +os.close(FH) -print "Testing check for write permission on dump...", -print not dmidecode.dump() and "Good" or "Bad" +total = 0 +success = 0 -print "Testing that default device is /dev/mem", -print dmidecode.get_dev() == "/dev/mem" and "Good" or "Bad" +def test(r): + global total + global success -print "Testing ability to change device to /tmp/foo...", -print dmidecode.set_dev("/tmp/foo") and "Good" or "Bad" + total += 1 + if r: + sys.stdout.write("Good\n") + success += 1 + else: + sys.stdout.write("Bad\n") -print "Testing that device has changed to /tmp/foo...", -print dmidecode.get_dev() == "/tmp/foo" and "Good" or "Bad" +total += 1 +sys.stdout.write("Importing module...") +try: + import dmidecode + sys.stdout.write("Done\n") + success += 1 + sys.stdout.write(" * Version: %s\n"%dmidecode.version) + sys.stdout.write(" * DMI Version String: %s\n"%dmidecode.dmi) -print "Testing that write on new file is ok...", -print dmidecode.dump() and "Good" or "Bad" + sys.stdout.write("Testing that default device is /dev/mem...") + test(dmidecode.get_dev() == "/dev/mem") -print "Testing that file was actually written...", -if os.path.exists("/tmp/foo"): - sys.stdout.write("Good\n") - os.unlink("/tmp/foo") -else: - sys.stdout.write("FAILED\n") + sys.stdout.write("Testing that write-lock will not break on dump()...") + test(not dmidecode.dump()) -types = range(0, 42)+range(126, 128) -types = range(0, 42)+[126, 127] -sections = ["bios", "system", "baseboard", "chassis", "processor", "memory", "cache", "connector", "slot"] -devices = [os.path.join("private", _) for _ in os.listdir("private")] -devices.remove('private/.svn') -devices.append("/dev/mem") -random.shuffle(types) -random.shuffle(devices) -random.shuffle(sections) + sys.stdout.write("Testing ability to change device to %s..."%DUMP) + test(dmidecode.set_dev(DUMP)) -total = 0 -success = 0 -for dev in devices: - sys.stdout.write(" * Testing %s..."%dev); sys.stdout.flush() - total += 1 - if dmidecode.set_dev(dev) and dmidecode.get_dev() == dev: - success += 1 - sys.stdout.write("...\n") - for i in types: - sys.stdout.write(" * Testing type %i..."%i); sys.stdout.flush() - output = dmidecode.type(i).keys() - total += 1 - sys.stdout.write("Done (%s)\n"%output) - success += 1 - for section in sections: - total += 1 - sys.stdout.write(" * Testing %s..."%section); sys.stdout.flush() - output = getattr(dmidecode, section)().keys() - sys.stdout.write("Done (%s)\n"%output) + sys.stdout.write("Testing that device has changed to %s..."%DUMP) + test(dmidecode.get_dev() == DUMP) + + sys.stdout.write("Testing that write on new file is ok...") + test(dmidecode.dump()) + + sys.stdout.write("Testing that file was actually written...") + time.sleep(0.1) + test(os.path.exists(DUMP)) + os.unlink(DUMP) + + types = range(0, 42)+range(126, 128) + types = range(0, 42)+[126, 127] + sections = ["bios", "system", "baseboard", "chassis", "processor", "memory", "cache", "connector", "slot"] + devices = [os.path.join("private", _) for _ in os.listdir("private")] + devices.remove('private/.svn') + devices.append("/dev/mem") + random.shuffle(types) + random.shuffle(devices) + random.shuffle(sections) + + for dev in devices: + sys.stdout.write(" * Testing %s..."%dev); sys.stdout.flush() + total += 1 + if dmidecode.set_dev(dev) and dmidecode.get_dev() == dev: success += 1 - else: - sys.stdout.write("FAILED\n") + sys.stdout.write("...\n") + for i in types: + total += 1 + sys.stdout.write(" * Testing type %i..."%i); sys.stdout.flush() + output = dmidecode.type(i).keys() + sys.stdout.write("Done (%s)\n"%output) + success += 1 + for section in sections: + total += 1 + sys.stdout.write(" * Testing %s..."%section); sys.stdout.flush() + output = getattr(dmidecode, section)().keys() + sys.stdout.write("Done (%s)\n"%output) + success += 1 + else: + sys.stdout.write("FAILED\n") + +except ImportError: + sys.stdout.write("FAILED\n") -print "Score: %d/%d"%(success, total) +sys.stdout.write("Score: %d/%d\n"%(success, total)) |