📄 dmidecode.c
字号:
/* * DMI Decode * * (C) 2000-2002 Alan Cox <alan@redhat.com> * (C) 2002-2003 Jean Delvare <khali@linux-fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For the avoidance of doubt the "preferred form" of this code is one which * is in an open unpatent encumbered format. Where cryptographic key signing * forms part of the process of creating an executable the information * including keys needed to generate an equivalently functional executable * are deemed to be part of the source code. * * Unless specified otherwise, all references are aimed at the "System * Management BIOS Reference Specification, Version 2.3.4" document, * available from http://www.dmtf.org/standards/bios.php. * * Note to contributors: * Please reference every value you add or modify, especially if the * information does not come from the above mentioned specification. * * Additional references: * - Intel AP-485 revision 23 * "Intel Processor Identification and the CPUID Instruction" * http://developer.intel.com/design/xeon/applnots/241618.htm * - DMTF Master MIF version 021205 * "DMTF approved standard groups" * http://www.dmtf.org/standards/standard_dmi.php * - IPMI 1.5 revision 1.1 * "Intelligent Platform Management Interface Specification" * http://developer.intel.com/design/servers/ipmi/spec.htm */#include <sys/types.h>#include <sys/stat.h>#ifdef USE_MMAP#include <sys/mman.h>#endif /* USE MMAP */#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <stdlib.h>#include "version.h"#include "types.h"#include "util.h"static const char *out_of_spec = "<OUT OF SPEC>";static const char *bad_index = "<BAD INDEX>";/* * The specification isn't very clear on endianness problems, so we better * have macros for these. It also helps us solve problems on systems that * don't support non-aligned memory access. This isn't a big issue IMHO, * since SMBIOS/DMI is intended mainly for Intel and compatible systems, * which are little-endian and support non-aligned memory access. Anyway, * you may use the following defines to control the way it works: * - Define BIGENDIAN on big-endian systems. * - Define ALIGNMENT_WORKAROUND if your system doesn't support * non-aligned memory access. In this case, we use a slower, but safer, * memory access method. * - If it happens that the table is supposed to be always little-endian * ordered regardless of the architecture, define TABLE_LITTLEENDIAN. * You most probably will have to define none or the three of them. */#ifndef TABLE_LITTLEENDIAN# ifdef BIGENDIAN typedef struct { u32 h; u32 l; } u64;# else /* BIGENDIAN */ typedef struct { u32 l; u32 h; } u64;# endif /* BIGENDIAN */# ifdef ALIGNMENT_WORKAROUND# ifdef BIGENDIAN# define WORD(x) (u16)((x)[1]+((x)[0]<<8))# define DWORD(x) (u32)((x)[3]+((x)[2]<<8)+((x)[1]<<16)+((x)[0]<<24))# define QWORD(x) (U64(DWORD(x+4), DWORD(x)))# else /* BIGENDIAN */# define WORD(x) (u16)((x)[0]+((x)[1]<<8))# define DWORD(x) (u32)((x)[0]+((x)[1]<<8)+((x)[2]<<16)+((x)[3]<<24))# define QWORD(x) (U64(DWORD(x), DWORD(x+4)))# endif /* BIGENDIAN */# else /* ALIGNMENT_WORKAROUND */# define WORD(x) (u16)(*(u16 *)(x))# define DWORD(x) (u32)(*(u32 *)(x))# define QWORD(x) (*(u64 *)(x))# endif /* ALIGNMENT_WORKAROUND */#else /* TABLE_LITTLEENDIAN */typedef struct { u32 l; u32 h;} u64;#define WORD(x) (u16)((x)[0]+((x)[1]<<8))#define DWORD(x) (u32)((x)[0]+((x)[1]<<8)+((x)[2]<<16)+((x)[3]<<24))#define QWORD(x) (U64(DWORD(x), DWORD(x+4)))#endif /* TABLE_LITTLEENDIAN */#if defined ALIGNMENT_WORKAROUND || defined TABLE_LITTLEENDIANstatic u64 U64(u32 low, u32 high){ u64 self; self.l=low; self.h=high; return self;}#endifstruct dmi_header{ u8 type; u8 length; u16 handle;};#if ((defined BIGENDIAN && defined TABLE_LITTLEENDIAN) || defined ALIGNMENT_WORKAROUND)#define HANDLE(x) WORD((u8 *)&(x->handle))#else#define HANDLE(x) x->handle#endif/* * Type-independant Stuff */static const char *dmi_string(struct dmi_header *dm, u8 s){ char *bp=(char *)dm; size_t i; if(s==0) return "Not Specified"; bp+=dm->length; while(s>1 && *bp) { bp+=strlen(bp); bp++; s--; } if(!*bp) return bad_index; /* ASCII filtering */ for(i=0; i<strlen(bp); i++) if(bp[i]<32 || bp[i]==127) bp[i]='.'; return bp;}static const char *dmi_smbios_structure_type(u8 code){ static const char *type[]={ "BIOS", /* 0 */ "System", "Base Board", "Chassis", "Processor", "Memory Controler", "Memory Module", "Cache", "Port Connector", "System Slots", "On Board Devices", "OEM Strings", "System Configuration Options", "BIOS Language", "Group Associations", "System Event Log", "Physical Memory Array", "Memory Device", "32-bit Memory Error", "Memory Array Mapped Address", "Memory Device Mapped Address", "Built-in Pointing Device", "Portable Battery", "System Reset", "Hardware Security", "System Power Controls", "Voltage Probe", "Cooling Device", "Temperature Probe", "Electrical Current Probe", "Out-of-band Remote Access", "Boot Integrity Services", "System Boot", "64-bit Memory Error", "Management Device", "Management Device Component", "Management Device Threshold Data", "Memory Channel", "IPMI Device", "Power Supply" /* 39 */ }; if(code<=39) return(type[code]); return out_of_spec;}static int dmi_bcd_range(u8 value, u8 low, u8 high){ if(value>0x99 || (value&0x0F)>0x09) return 0; if(value<low || value>high) return 0; return 1;}static void dmi_dump(struct dmi_header *h, const char *prefix){ int row, i; const char *s; printf("%sHeader And Data:\n", prefix); for(row=0; row<((h->length-1)>>4)+1; row++) { printf("%s\t", prefix); for(i=0; i<16 && i<h->length-(row<<4); i++) printf("%s%02X", i?" ":"", ((u8 *)h)[(row<<4)+i]); printf("\n"); } if(((u8 *)h)[h->length] || ((u8 *)h)[h->length+1]) { printf("%sStrings:\n", prefix); i=1; while((s=dmi_string(h, i++))!=bad_index) printf("%s\t%s\n", prefix, s); }}/* * 3.3.1 BIOS Information (Type 0) */static void dmi_bios_runtime_size(u32 code){ if(code&0x000003FF) printf(" %u bytes", code); else printf(" %u kB", code>>10);}static void dmi_bios_characteristics(u64 code, const char *prefix){ /* 3.3.1.1 */ static const char *characteristics[]={ "BIOS characteristics not supported", /* 3 */ "ISA is supported", "MCA is supported", "EISA is supported", "PCI is supported", "PC Card (PCMCIA) is supported", "PNP is supported", "APM is supported", "BIOS is upgradeable", "BIOS shadowing is allowed", "VLB is supported", "ESCD support is available", "Boot from CD is supported", "Selectable boot is supported", "BIOS ROM is socketed", "Boot from PC Card (PCMCIA) is supported", "EDD is supported", "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)", "Japanese floppy for Toshiba 1.2 MB is supported (int 13h)", "5.25\"/360 KB floppy services are supported (int 13h)", "5.25\"/1.2 MB floppy services are supported (int 13h)", "3.5\"/720 KB floppy services are supported (int 13h)", "3.5\"/2.88 MB floppy services are supported (int 13h)", "Print screen service is supported (int 5h)", "8042 keyboard services are supported (int 9h)", "Serial services are supported (int 14h)", "Printer services are supported (int 17h)", "CGA/mono video services are supported (int 10h)", "NEC PC-98" /* 31 */ }; int i; /* * This isn't very clear what this bit is supposed to mean */ if(code.l&(1<<3)) { printf("%s%s\n", prefix, characteristics[0]); return; } for(i=4; i<=31; i++) if(code.l&(1<<i)) printf("%s%s\n", prefix, characteristics[i-3]);}static void dmi_bios_characteristics_x1(u8 code, const char *prefix){ /* 3.3.1.2.1 */ static const char *characteristics[]={ "ACPI is supported", /* 0 */ "USB legacy is supported", "AGP is supported", "I2O boot is supported", "LS-120 boot is supported", "ATAPI Zip drive boot is supported", "IEEE 1394 boot is supported", "Smart battery is supported" /* 7 */ }; int i; for(i=0; i<=7; i++) if(code&(1<<i)) printf("%s%s\n", prefix, characteristics[i]);}static void dmi_bios_characteristics_x2(u8 code, const char *prefix){ /* 3.3.1.2.2 */ static const char *characteristics[]={ "BIOS boot specification is supported", /* 0 */ "Function key-initiated network boot is supported" /* 1 */ }; int i; for(i=0; i<=1; i++) if(code&(1<<i)) printf("%s%s\n", prefix, characteristics[i]);}/* * 3.3.2 System Information (Type 1) */static void dmi_system_uuid(u8 *p){ 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) { printf(" Not Present"); return; } if(only0x00) { printf(" Not Settable"); return; } printf(" %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]);}static const char *dmi_system_wake_up_type(u8 code){ /* 3.3.2.1 */ static const char *type[]={ "Reserved", /* 0x00 */ "Other", "Unknown", "APM Timer", "Modem Ring", "LAN Remote", "Power Switch", "PCI PME#", "AC Power Restored" /* 0x08 */ }; if(code<=0x08) return type[code]; return out_of_spec;}/* * 3.3.3 Base Board Information (Type 2) */static void dmi_base_board_features(u8 code, const char *prefix){ /* 3.3.3.1 */ static const char *features[]={ "Board is a hosting board", /* 0 */ "Board requires at least one daughter board", "Board is removable", "Board is replaceable", "Board is hot swappable" /* 4 */ }; if((code&0x1F)==0) printf(" None\n"); else { int i; printf("\n"); for(i=0; i<=4; i++) if(code&(1<<i)) printf("%s%s\n", prefix, features[i]); }}static const char *dmi_base_board_type(u8 code){ /* 3.3.3.2 */ static const char *type[]={ "Unknown", /* 0x01 */ "Other", "Server Blade", "Connectivity Switch", "System Management Module", "Processor Module", "I/O Module", "Memory Module", "Daughter Board", "Motherboard", "Processor+Memory Module", "Processor+I/O Module", "Interconnect Board" /* 0x0D */ }; if(code>=0x01 && code<=0x0D) return type[code-0x01]; return out_of_spec;}static void dmi_base_board_handlers(u8 count, u8 *p, const char *prefix){ int i; printf("%sContained Object Handlers: %u\n", prefix, count); for(i=0; i<count; i++) printf("%s\t0x%04X\n", prefix, WORD(p+sizeof(u16)*i));}/* * 3.3.4 Chassis Information (Type 3) */static const char *dmi_chassis_type(u8 code){ /* 3.3.4.1 */ static const char *type[]={ "Other", /* 0x01 */ "Unknown", "Desktop", "Low Profile Desktop", "Pizza Box", "Mini Tower", "Tower", "Portable", "Laptop", "Notebook", "Hand Held", "Docking Station", "All In One", "Sub Notebook", "Space-saving", "Lunch Box", "Main Server Chassis", /* master.mif says System */ "Expansion Chassis", "Sub Chassis", "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis", "Rack Mount Chassis", "Sealed-case PC", "Multi-system" /* 0x19 */ }; if(code>=0x01 && code<=0x19) return type[code-0x01]; return out_of_spec;}static const char *dmi_chassis_lock(u8 code){ static const char *lock[]={ "Not Present", /* 0x00 */ "Present" /* 0x01 */ }; return lock[code];}static const char *dmi_chassis_state(u8 code){ /* 3.3.4.2 */ static const char *state[]={ "Other", /* 0x01 */ "Unknown", "Safe", /* master.mif says OK */ "Warning", "Critical", "Non-recoverable" /* 0x06 */ }; if(code>=0x01 && code<=0x06) return(state[code-0x01]); return out_of_spec;}static const char *dmi_chassis_security_status(u8 code){ /* 3.3.4.3 */ static const char *status[]={ "Other", /* 0x01 */ "Unknown", "None", "External Interface Locked Out", "External Interface Enabled" /* 0x05 */ }; if(code>=0x01 && code<=0x05) return(status[code-0x01]); return out_of_spec;}static void dmi_chassis_height(u8 code){ if(code==0x00) printf(" Unspecified"); else printf(" %u U", code);}static void dmi_chassis_power_cords(u8 code){ if(code==0x00) printf(" Unspecified"); else printf(" %u", code);}static void dmi_chassis_elements(u8 count, u8 len, u8 *p, const char *prefix){ int i; printf("%sContained Elements: %u\n", prefix, count); for(i=0; i<count; i++) { if(len>=0x03) { printf("%s\t%s (", prefix, p[i*len]&0x80? dmi_smbios_structure_type(p[i*len]&0x7F): dmi_base_board_type(p[i*len]&0x7F)); if(p[1+i*len]==p[2+i*len]) printf("%u", p[1+i*len]); else printf("%u-%u", p[1+i*len], p[2+i*len]); printf(")\n"); } }}/* * 3.3.5 Processor Information (Type 4) */static const char *dmi_processor_type(u8 code){ /* 3.3.5.1 */ static const char *type[]={ "Other", /* 0x01 */ "Unknown", "Central Processor", "Math Processor", "DSP Processor", "Video Processor" /* 0x06 */ }; if(code>=0x01 && code<=0x06) return type[code-0x01]; return out_of_spec;}static const char *dmi_processor_family(u8 code){ /* 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",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -