/* * DMI decode rev 1.5 * * (C) 2000-2002 Alan Cox * * 2-July-2001 Matt Domsch * Additional structures displayed per SMBIOS 2.3.1 spec * * 13-December-2001 Arjan van de Ven * Fix memory bank type (DMI case 6) * * 3-August-2002 Mark D. Studebaker * Better indent in dump_raw_data * Fix return value in dmi_bus_name * Additional sensor fields decoded * Fix compilation warnings * * 6-August-2002 Jean Delvare * Reposition file pointer after DMI table display * Disable first RSD PTR checksum (was not correct anyway) * Show actual DMI struct count and occupied size * Check for NULL after malloc * Use SEEK_* constants instead of numeric values * Code optimization (and warning fix) in DMI cases 10 and 14 * Add else's to avoid unneeded cascaded if's in main loop * Code optimization in DMI information display * Fix all compilation warnings * * 9-August-2002 Jean Delvare * Better DMI struct count/size error display * More careful memory access in dmi_table * DMI case 13 (Language) decoded * C++ style comments removed * Commented out code removed * DMI 0.0 case handled * Fix return value in dmi_port_type and dmi_port_connector_type * * 23-August-2002 Alan Cox * Make the code pass -Wall -pedantic by fixing a few harmless * sign of pointer mismatches. * Correct main() prototype * Check for compiles with wrong type sizes * * Licensed under the GNU Public license. If you want to use it in with * another license just ask. * * 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 */ #include #include #include #include #include typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; static void dump_raw_data(void *data, unsigned int length) { char buffer1[80], buffer2[80], *b1, *b2, c; unsigned char *p = data; unsigned long column=0; unsigned int length_printed = 0; const unsigned char maxcolumn = 16; while (length_printed < length) { printf("\t"); b1 = buffer1; b2 = buffer2; for (column = 0; column < maxcolumn && length_printed < length; column ++) { b1 += sprintf(b1, "%02x ",(unsigned int) *p); if (*p < 32 || *p > 126) c = '.'; else c = *p; b2 += sprintf(b2, "%c", c); p++; length_printed++; } /* pad out the line */ for (; column < maxcolumn; column++) { b1 += sprintf(b1, " "); b2 += sprintf(b2, " "); } printf("%s\t%s\n", buffer1, buffer2); } } struct dmi_header { u8 type; u8 length; u16 handle; }; static char *dmi_string(struct dmi_header *dm, u8 s) { char *bp=(char *)dm; if (!s) return NULL; bp+=dm->length; while(s>1) { bp+=strlen(bp); bp++; s--; } return bp; } static void dmi_decode_ram(u8 data) { if(data&(1<<0)) printf("OTHER "); if(data&(1<<1)) printf("UNKNOWN "); if(data&(1<<2)) printf("STANDARD "); if(data&(1<<3)) printf("FPM "); if(data&(1<<4)) printf("EDO "); if(data&(1<<5)) printf("PARITY "); if(data&(1<<6)) printf("ECC "); if(data&(1<<7)) printf("SIMM "); if(data&(1<<8)) printf("DIMM "); if(data&(1<<9)) printf("Burst EDO "); if(data&(1<<10)) printf("SDRAM "); } static void dmi_cache_size(u16 n) { if(n&(1<<15)) printf("%dK\n", (n&0x7FFF)*64); else printf("%dK\n", n&0x7FFF); } static void dmi_decode_cache(u16 c) { if(c&(1<<0)) printf("Other "); if(c&(1<<1)) printf("Unknown "); if(c&(1<<2)) printf("Non-burst "); if(c&(1<<3)) printf("Burst "); if(c&(1<<4)) printf("Pipeline burst "); if(c&(1<<5)) printf("Synchronous "); if(c&(1<<6)) printf("Asynchronous "); } const char *dmi_bus_name(u8 num) { static const char *bus[]={ "", "", "", "ISA ", "MCA ", "EISA ", "PCI ", "PCMCIA " "VLB ", "Proprietary ", "CPU Slot ", "Proprietary RAM ", "I/O Riser ", "NUBUS ", "PCI-66 ", "AGP ", "AGP 2x ", "AGP 4x " }; static const char *jpbus[]={ "PC98/C20", "PC98/C24", "PC98/E", "PC98/LocalBus", "PC98/Card" }; if(num<=0x12) return bus[num]; if(num>=0xA0 && num<0xA5) return jpbus[num - 0xA0]; return ""; } const char *dmi_bus_width(u8 code) { static const char *width[]={ "", "", "", "8bit ", "16bit ", "32bit ", "64bit ", "128bit " }; if(code>7) return ""; return width[code]; } const char *dmi_card_size(u8 v) { if(v==2) return("Short "); if(v==3) return("Long "); return ""; } static void dmi_card_props(u8 v) { printf("\t\tSlot Features: "); if(v&(1<<1)) printf("5v "); if(v&(1<<2)) printf("3.3v "); if(v&(1<<3)) printf("Shared "); if(v&(1<<4)) printf("PCCard16 "); if(v&(1<<5)) printf("CardBus "); if(v&(1<<6)) printf("Zoom-Video "); if(v&(1<<7)) printf("ModemRingResume "); printf("\n"); } const char *dmi_chassis_type(u8 code) { static const char *chassis_type[]={ "", "Other", "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", "Expansion Chassis", "SubChassis", "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis", "Rack Mount Chassis", "Sealed-case PC", }; code &= ~0x80; if(code>0x18) return ""; return chassis_type[code]; } const char *dmi_port_connector_type(u8 code) { static const char *connector_type[]={ "None", "Centronics", "Mini Centronics", "Proprietary", "DB-25 pin male", "DB-25 pin female", "DB-15 pin male", "DB-15 pin female", "DB-9 pin male", "DB-9 pin 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", "1394", "PC-98", "PC-98Hireso", "PC-H98", "PC-98Note", "PC98Full", }; if(code == 0xFF) return "Other"; if(code <= 0x21) return connector_type[code]; if((code >= 0xA0) && (code <= 0xA4)) return connector_type[code-0xA0+0x22]; return ""; } const char *dmi_port_type(u8 code) { static const char *port_type[]={ "None", "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 16650 Compatible", "Serial Port 16650A Compatible", "SCSI Port", "MIDI Port", "Joy Stick 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", "8251 Compatible", "8251 FIFO Compatible", }; if(code == 0xFF) return "Other"; if (code <= 0x1F) return port_type[code]; if ((code >= 0xA0) && (code <= 0xA1)) return port_type[code-0xA0+0x20]; return ""; } const char *dmi_processor_type(u8 code) { static const char *processor_type[]={ "", "Other", "Unknown", "Central Processor", "Math Processor", "DSP Processor", "Video Processor" }; if(code == 0xFF) return "Other"; if (code > 0xA1) return ""; return processor_type[code]; } const char *dmi_processor_family(u8 code) { static const char *processor_family[]={ "", "Other", "Unknown", "8086", "80286", "Intel386 processor", "Intel486 processor", "8087", "80287", "80387", "80487", "Pentium processor Family", "Pentium Pro processor", "Pentium II processor", "Pentium processor with MMX technology", "Celeron processor", "Pentium II Xeon processor", "Pentium III processor", "M1 Family", "M1","M1","M1","M1","M1","M1", /* 13h - 18h */ "K5 Family", "K5","K5","K5","K5","K5","K5", /* 1Ah - 1Fh */ "Power PC Family", "Power PC 601", "Power PC 603", "Power PC 603+", "Power PC 604", }; if(code == 0xFF) return "Other"; if (code > 0x24) return ""; return processor_family[code]; } const char *dmi_onboard_type(u8 code) { static const char *onboard_type[]={ "", "Other", "Unknown", "Video", "SCSI Controller", "Ethernet", "Token Ring", "Sound", }; code &= 0x80; if (code > 7) return ""; return onboard_type[code]; } const char *dmi_mgmt_dev_type(u8 code) { static const char *type[]={ "", "Other", "Unknown", "LM75", "LM78", "LM79", "LM80", "LM81", "ADM9240", "DS1780", "MAX1617", "GL518SM", "W83781D", "HT82H791", }; code &= 0x80; if (code > 0x0d) return ""; return type[code]; } const char *dmi_mgmt_addr_type(u8 code) { static const char *type[]={ "", "Other", "Unknown", "I/O", "Memory", "SMBus", }; code &= 0x80; if (code > 5) return ""; return type[code]; } const char *dmi_fan_type(u8 code) { static const char *type[]={ "", "Other", "Unknown", "Fan", "Centrifugal Blower", "Chip Fan", "Cabinet Fan", "Power Supply Fan", "Heat Pipe", "Integrated Refrigeration", "", "", "", "", "", "", "Active Cooling", "Passive Cooling", }; code &= 0x80; if (code > 0x11) return ""; return type[code]; } const char *dmi_volt_loc(u8 code) { static const char *type[]={ "", "Other", "Unknown", "Processor", "Disk", "Peripheral Bay", "System Management Module", "Motherboard", "Memory Module", "Processor Module", "Power Unit", "Add-in Card", }; code &= 0x80; if (code > 0x0b) return ""; return type[code]; } const char *dmi_temp_loc(u8 code) { static const char *type[]={ "Front Panel Board", "Back Panel Board", "Power System Board", "Drive Back Plane", }; code &= 0x80; if (code <= 0x0b) return dmi_volt_loc(code); return type[code - 0x0c]; } const char *dmi_status(u8 code) { static const char *type[]={ "", "Other", "Unknown", "OK", "Non-critical", "Critical", "Non-recoverable", }; code &= 0x80; if (code > 6) return ""; return type[code]; } /* 3 dec. places */ const char *dmi_millivolt(u8 *data, int indx) { static char buffer[20]; short int d; if (data[indx+1] == 0x80 && data[indx] == 0) return "Unknown"; d = data[indx+1] << 8 | data[indx]; sprintf(buffer, "%0.3f", d / 1000.0); return buffer; } /* 2 dec. places */ const char *dmi_accuracy(u8 *data, int indx) { static char buffer[20]; short int d; if (data[indx+1] == 0x80 && data[indx] == 0) return "Unknown"; d = data[indx+1] << 8 | data[indx]; sprintf(buffer, "%0.2f", d / 100.0); return buffer; } /* 1 dec. place */ const char *dmi_temp(u8 *data, int indx) { static char buffer[20]; short int d; if (data[indx+1] == 0x80 && data[indx] == 0) return "Unknown"; d = data[indx+1] << 8 | data[indx]; sprintf(buffer, "%0.1f", d / 10.0); return buffer; } /* 0 dec. place */ const char *dmi_speed(u8 *data, int indx) { static char buffer[20]; short int d; if (data[indx+1] == 0x80 && data[indx] == 0) return "Unknown"; d = data[indx+1] << 8 | data[indx]; sprintf(buffer, "%d", d); return buffer; } static void dmi_table(int fd, u32 base, int len, int num) { unsigned char *buf=malloc(len); struct dmi_header *dm; u8 *data; int i=0; if(buf==NULL) { perror("dmi: malloc"); return; } if(lseek(fd, (long)base, SEEK_SET)==-1) { perror("dmi: lseek"); return; } if(read(fd, buf, len)!=len) { perror("dmi: read"); return; } data = buf; while(data+sizeof(struct dmi_header)<=(u8*)buf+len) { u32 u, u2; dm=(struct dmi_header *)data; printf("Handle 0x%04X\n\tDMI type %d, %d bytes.\n", dm->handle, dm->type, dm->length); /* we won't read beyond allocated memory */ if(data+dm->length>(u8*)buf+len) { printf("\tIncomplete structure, abort decoding.\n"); break; } switch(dm->type) { case 0: printf("\tBIOS Information Block\n"); printf("\t\tVendor: %s\n", dmi_string(dm, data[4])); printf("\t\tVersion: %s\n", dmi_string(dm, data[5])); printf("\t\tRelease: %s\n", dmi_string(dm, data[8])); printf("\t\tBIOS base: 0x%04X0\n", data[7]<<8|data[6]); printf("\t\tROM size: %dK\n", 64*data[9]); printf("\t\tCapabilities:\n"); u=data[13]<<24|data[12]<<16|data[11]<<8|data[10]; u2=data[17]<<24|data[16]<<16|data[15]<<8|data[14]; printf("\t\t\tFlags: 0x%08X%08X\n", u2,u); break; case 1: printf("\tSystem Information Block\n"); printf("\t\tVendor: %s\n", dmi_string(dm, data[4])); printf("\t\tProduct: %s\n", dmi_string(dm, data[5])); printf("\t\tVersion: %s\n", dmi_string(dm, data[6])); printf("\t\tSerial Number: %s\n", dmi_string(dm, data[7])); break; case 2: printf("\tBoard Information Block\n"); printf("\t\tVendor: %s\n", dmi_string(dm, data[4])); printf("\t\tProduct: %s\n", dmi_string(dm, data[5])); printf("\t\tVersion: %s\n", dmi_string(dm, data[6])); printf("\t\tSerial Number: %s\n", dmi_string(dm, data[7])); break; case 3: printf("\tChassis Information Block\n"); printf("\t\tVendor: %s\n", dmi_string(dm, data[4])); printf("\t\tChassis Type: %s\n", dmi_chassis_type(data[5])); if (data[5] & 0x80) printf("\t\t\tLock present\n"); printf("\t\tVersion: %s\n", dmi_string(dm, data[6])); printf("\t\tSerial Number: %s\n", dmi_string(dm, data[7])); printf("\t\tAsset Tag: %s\n", dmi_string(dm, data[8])); break; case 4: printf("\tProcessor\n"); printf("\t\tSocket Designation: %s\n", dmi_string(dm, data[4])); printf("\t\tProcessor Type: %s\n", dmi_processor_type(data[5])); printf("\t\tProcessor Family: %s\n", dmi_processor_family(data[6])); printf("\t\tProcessor Manufacturer: %s\n", dmi_string(dm, data[7])); printf("\t\tProcessor Version: %s\n", dmi_string(dm, data[0x10])); if (dm->length <= 0x20) break; printf("\t\tSerial Number: %s\n", dmi_string(dm, data[0x20])); printf("\t\tAsset Tag: %s\n", dmi_string(dm, data[0x21])); printf("\t\tVendor Part Number: %s\n", dmi_string(dm, data[0x22])); break; case 5: printf("\tMemory Controller\n"); break; case 6: printf("\tMemory Bank\n"); printf("\t\tSocket: %s\n", dmi_string(dm, data[4])); if(data[5]!=0xFF) { printf("\t\tBanks: "); if((data[5]&0xF0)!=0xF0) printf("%d ", data[5]>>4); if((data[5]&0x0F)!=0x0F) printf("%d", data[5]&0x0F); printf("\n"); } if(data[6]) printf("\t\tSpeed: %dnS\n", data[6]); printf("\t\tType: "); dmi_decode_ram(data[8]<<8|data[7]); printf("\n"); printf("\t\tInstalled Size: "); switch(data[9]&0x7F) { case 0x7D: printf("Unknown");break; case 0x7E: printf("Disabled");break; case 0x7F: printf("Not Installed");break; default: printf("%dMbyte", (1<<(data[9]&0x7F))); } if(data[9]&0x80) printf(" (Double sided)"); printf("\n"); printf("\t\tEnabled Size: "); switch(data[10]&0x7F) { case 0x7D: printf("Unknown");break; case 0x7E: printf("Disabled");break; case 0x7F: printf("Not Installed");break; default: printf("%dMbyte", (1<<(data[10]&0x7F))); } if(data[10]&0x80) printf(" (Double sided)"); printf("\n"); if((data[11]&4)==0) { if(data[11]&(1<<0)) printf("\t\t*** BANK HAS UNCORRECTABLE ERRORS (BIOS DISABLED)\n"); if(data[11]&(1<<1)) printf("\t\t*** BANK LOGGED CORRECTABLE ERRORS AT BOOT\n"); } break; case 7: { static const char *types[4]={ "Internal ", "External ", "", ""}; static const char *modes[4]={ "write-through", "write-back", "",""}; printf("\tCache\n"); printf("\t\tSocket: %s\n", dmi_string(dm, data[4])); u=data[6]<<8|data[5]; printf("\t\tL%d %s%sCache: ", 1+(u&7), (u&(1<<3))?"socketed ":"", types[(u>>5)&3]); if(u&(1<<7)) printf("%s\n", modes[(u>>8)&3]); else printf("disabled\n"); printf("\t\tL%d Cache Size: ", 1+(u&7)); dmi_cache_size(data[7]|data[8]<<8); printf("\t\tL%d Cache Maximum: ", 1+(u&7)); dmi_cache_size(data[9]|data[10]<<8); printf("\t\tL%d Cache Type: ", 1+(u&7)); dmi_decode_cache(data[13]); printf("\n"); } break; case 8: printf("\tPort Connector\n"); printf("\t\tInternal Designator: %s\n", dmi_string(dm, data[4])); printf("\t\tInternal Connector Type: %s\n", dmi_port_connector_type(data[5])); printf("\t\tExternal Designator: %s\n", dmi_string(dm, data[6])); printf("\t\tExternal Connector Type: %s\n", dmi_port_connector_type(data[7])); printf("\t\tPort Type: %s\n", dmi_port_type(data[8])); break; case 9: printf("\tCard Slot\n"); printf("\t\tSlot: %s\n", dmi_string(dm, data[4])); printf("\t\tType: %s%s%s\n", dmi_bus_width(data[6]), dmi_card_size(data[8]), dmi_bus_name(data[5])); if(data[7]==3) printf("\t\tStatus: Available.\n"); if(data[7]==4) printf("\t\tStatus: In use.\n"); if(data[11]&0xFE) dmi_card_props(data[11]); break; case 10: printf("\tOn Board Devices Information\n"); for (u=2; u*2+1length; u++) { printf("\t\tDescription: %s : %s\n", dmi_string(dm, data[1+2*u]), (data[2*u]) & 0x80 ? "Enabled" : "Disabled"); printf("\t\tType: %s\n", dmi_onboard_type(data[2*u])); } break; case 11: printf("\tOEM Data\n"); for(u=1;u<=data[4];u++) printf("\t\t%s\n", dmi_string(dm,u)); break; case 12: printf("\tConfiguration Information\n"); for(u=1;u<=data[4];u++) printf("\t\t%s\n", dmi_string(dm,u)); break; case 13: printf("\tBIOS Language Information\n"); printf("\t\tInstallable Languages: %u\n", data[4]); for (u=1; u<=data[4]; u++) { printf("\t\t\t%s\n", dmi_string(dm,u)); } printf("\t\tCurrently Installed Language: %s\n", dmi_string(dm, data[21])); break; case 14: printf("\tGroup Associations\n"); for (u=0; 3*u+7length; u++) { printf("\t\tGroup Name: %s\n", dmi_string(dm,data[4])); printf("\t\t\tType: 0x%02x\n", *(data+5+(u*3))); printf("\t\t\tHandle: 0x%04x\n", *(u16*)(data+6+(u*3))); } break; case 15: printf("\tEvent Log\n"); printf("\t\tLog Area: %d bytes.\n", data[5]<<8|data[4]); printf("\t\tLog Header At: %d.\n", data[7]<<8|data[6]); printf("\t\tLog Data At: %d.\n", data[9]<<8|data[8]); printf("\t\tLog Type: %d.\n", data[10]); if(data[11]&(1<<0)) printf("\t\tLog Valid: Yes.\n"); if(data[11]&(1<<1)) printf("\t\t**Log Is Full**.\n"); break; case 16: printf("\tPhysical Memory Array\n"); break; case 17: printf("\tMemory Device\n"); break; case 18: printf("\t32-bit Memory Error Information\n"); break; case 19: printf("\tMemory Array Mapped Address\n"); break; case 20: printf("\tMemory Device Mapped Address\n"); break; case 21: printf("\tBuilt-In Pointing Device\n"); break; case 22: printf("\tPortable Battery\n"); printf("\t\tLocation: %s\n", dmi_string(dm, data[4])); printf("\t\tManufacturer: %s\n", dmi_string(dm, data[5])); printf("\t\tManufacture Date: %s\n", dmi_string(dm, data[6])); printf("\t\tSerial Number: %s\n", dmi_string(dm, data[7])); printf("\t\tName: %s\n", dmi_string(dm, data[8])); break; case 23: printf("\tSystem Reset\n"); break; case 24: printf("\tHardware Security\n"); break; case 25: printf("\tSystem Power Controls\n"); break; case 26: printf("\tVoltage Sensor\n"); printf("\t\tDescription: %s\n", dmi_string(dm, data[4])); printf("\t\tDevice Location: %s\n", dmi_volt_loc(data[5] & 0x1f)); printf("\t\tDevice Status: %s\n", dmi_status(data[5] >> 5)); printf("\t\tMaximum Value: %s\n", dmi_millivolt(data, 6)); printf("\t\tMinimum Value: %s\n", dmi_millivolt(data, 8)); printf("\t\tResolution: %s\n", dmi_millivolt(data, 10)); printf("\t\tTolerance: %s\n", dmi_millivolt(data, 12)); printf("\t\tAccuracy: %s\n", dmi_accuracy(data, 14)); if(dm->length > 0x14) printf("\t\tNominal Value: %s\n", dmi_millivolt(data, 0x14)); break; case 27: printf("\tCooling Device\n"); printf("\t\tDevice Type: %s\n", dmi_fan_type(data[5] & 0x1f)); printf("\t\tDevice Status: %s\n", dmi_status(data[5] >> 5)); if(dm->length > 0x0c) printf("\t\tNominal Speed: %s\n", dmi_speed(data, 0x0c)); break; case 28: printf("\tTemperature Sensor\n"); printf("\t\tDescription: %s\n", dmi_string(dm, data[4])); printf("\t\tDevice Location: %s\n", dmi_temp_loc(data[5] & 0x1f)); printf("\t\tDevice Status: %s\n", dmi_status(data[5] >> 5)); printf("\t\tMaximum Value: %s\n", dmi_temp(data, 6)); printf("\t\tMinimum Value: %s\n", dmi_temp(data, 8)); printf("\t\tResolution: %s\n", dmi_temp(data, 10)); printf("\t\tTolerance: %s\n", dmi_temp(data, 12)); printf("\t\tAccuracy: %s\n", dmi_accuracy(data, 14)); if(dm->length > 0x14) printf("\t\tNominal Value: %s\n", dmi_temp(data, 0x14)); break; case 29: printf("\tCurrent Sensor\n"); printf("\t\tDescription: %s\n", dmi_string(dm, data[4])); printf("\t\tDevice Location: %s\n", dmi_volt_loc(data[5] & 0x1f)); printf("\t\tDevice Status: %s\n", dmi_status(data[5] >> 5)); printf("\t\tMaximum Value: %s\n", dmi_millivolt(data, 6)); printf("\t\tMinimum Value: %s\n", dmi_millivolt(data, 8)); printf("\t\tResolution: %s\n", dmi_millivolt(data, 10)); printf("\t\tTolerance: %s\n", dmi_millivolt(data, 12)); printf("\t\tAccuracy: %s\n", dmi_accuracy(data, 14)); if(dm->length > 0x14) printf("\t\tNominal Value: %s\n", dmi_millivolt(data, 0x14)); break; case 30: printf("\tOut-of-Band Remote Access\n"); break; case 31: printf("\tBoot Integrity Services Entry Point\n"); break; case 32: printf("\tSystem Boot Information\n"); break; case 33: printf("\t64-bit Memory Error Information\n"); break; case 34: printf("\tManagement Device\n"); printf("\t\tDescription: %s\n", dmi_string(dm, data[4])); printf("\t\tDevice Type: %s\n", dmi_mgmt_dev_type(data[5])); printf("\t\tAddress Type: %s\n", dmi_mgmt_addr_type(data[6])); break; case 35: printf("\tManagement Device Component\n"); printf("\t\tDescription: %s\n", dmi_string(dm, data[4])); printf("\t\tDevice Handle : 0x%02x%02x\n", data[6], data[5]); printf("\t\tComponent Handle: 0x%02x%02x\n", data[8], data[7]); printf("\t\tThreshold Handle: 0x%02x%02x\n", data[10], data[9]); break; case 36: printf("\tManagement Device Threshold Data\n"); if (dm->length > 4) dump_raw_data(data+4, dm->length-4); break; case 37: printf("\tMemory Channeln"); break; case 38: printf("\tIPMI Device\n"); if (dm->length > 4) dump_raw_data(data+4, dm->length-4); break; case 39: printf("\tPower Supply\n"); if (dm->length > 4) dump_raw_data(data+4, dm->length-4); break; case 126: printf("\tInactive\n"); break; case 127: printf("\tEnd-of-Table\n"); break; default: if (dm->length > 4) dump_raw_data(data+4, dm->length-4); break; } data+=dm->length; while(*data || data[1]) data++; data+=2; i++; } if(i!=num) { printf("Wrong DMI structures count: %d announced, %d decoded.\n", num, i); } if(data-(u8*)buf!=len) { printf("Wrong DMI structures length: %d bytes announced, %d bytes decoded.\n", len, data-(u8*)buf); } free(buf); } int main(int argc, const char *argv[]) { unsigned char buf[20]; int fd=open("/dev/mem", O_RDONLY); long fp=0xE0000L; u8 smmajver=0, smminver=0; if( sizeof(u8) != 1 || sizeof(u16) != 2 || sizeof(u32) != 4) { fprintf(stderr,"%s: compiler incompatibility.\n", argv[0]); exit(255); } if(fd==-1) { perror("/dev/mem"); exit(1); } if(lseek(fd, fp, SEEK_SET)==-1) { perror("lseek"); exit(1); } fp -= 16; while( fp < 0xFFFFF) { fp+=16; if(read(fd, buf, 16)!=16) perror("read"); else if(memcmp(buf, "_SM_", 4)==0) printf("SMBIOS %d.%d present.\n", smmajver=buf[6], smminver=buf[7]); else if(memcmp(buf, "_SYSID_", 7)==0) printf("SYSID present.\n"); else if(memcmp(buf, "_DMI_", 5)==0) { u16 num=buf[13]<<8|buf[12]; u16 len=buf[7]<<8|buf[6]; u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; printf("DMI %d.%d present.\n", buf[14]?buf[14]>>4:smmajver, buf[14]?buf[14]&0x0F:smminver); printf("%d structures occupying %d bytes.\n", num, len); printf("DMI table at 0x%08X.\n", base); dmi_table(fd, base, len, num); /* dmi_table moved us far away */ lseek(fd, fp+16, SEEK_SET); } else if(memcmp(buf, "$PnP", 4)==0) printf("PNP BIOS present.\n"); else if(memcmp(buf, "RSD PTR ", 8)==0) { int a; unsigned char sum=0; printf("RSD PTR found at 0x%lX.\n", fp); if(buf[15]!=0) { printf("Reserved check failed.\n"); } printf("OEM "); fwrite(buf+9, 6, 1, stdout); printf("\n"); read(fd,buf+16,4); lseek(fd, -4, SEEK_CUR); for(a=0;a<20;a++) sum+=buf[a]; if(sum!=0) printf("Bad checksum.\n"); } } close(fd); return 0; }