summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Delvare <jdelvare@suse.de>2003-03-01 15:44:33 +0000
committerJean Delvare <jdelvare@suse.de>2003-03-01 15:44:33 +0000
commit47fe8c800a087fdeae3b1c566d9cedace0a64767 (patch)
tree81fed57f3a474aebe686f7930eb03a83d4601e8c
parentd8fc38b86308edf335f02186ddf0eff6b1a97fe3 (diff)
downloaddmidecode-git-47fe8c800a087fdeae3b1c566d9cedace0a64767.tar.gz
Almost complete code rewrite. Fully support SMBIOS 2.3.3. Splited DMI anddmidecode-2-0
non-DMI code.
-rw-r--r--biosdecode.c539
-rw-r--r--dmidecode.c4793
2 files changed, 4064 insertions, 1268 deletions
diff --git a/biosdecode.c b/biosdecode.c
new file mode 100644
index 0000000..e68163c
--- /dev/null
+++ b/biosdecode.c
@@ -0,0 +1,539 @@
+/*
+ * BIOS decode rev 2.0
+ *
+ * (C) 2000-2002 Alan Cox <alan@redhat.com>
+ * (C) 2002 Jean Delvare <khali@linux-fr>
+ *
+ * 2002-10-24 Jean Delvare <khali@linux-fr.org>
+ * Initial release
+ * Original code from dmidecode
+ *
+ * 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
+ *
+ * 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.
+ *
+ * References:
+ * - DMTF "System Management BIOS Reference Specification"
+ * Version 2.3.3
+ * http://www.dmtf.org/standards/bios.php.
+ * - Intel "Preboot Execution Environment (PXE) Specification"
+ * Version 2.1
+ * http://www.intel.com/labs/manage/wfm/wfmspecs.htm
+ * - ACPI "Advanced Configuration and Power Interface Specification"
+ * Revision 2.0
+ * http://www.acpi.info/spec20.htm
+ * - Phoenix "BIOS32 Service Directory"
+ * Revision 0.4
+ * http://www.phoenix.com/en/support/white+papers-specs/
+ * - Microsoft "Plug and Play BIOS Specification"
+ * Version 1.0A
+ * http://www.microsoft.com/hwdev/tech/PnP/
+ * - Microsoft "PCI IRQ Routing Table Specification"
+ * Version 1.0
+ * http://www.microsoft.com/hwdev/archive/BUSBIOS/pciirq.asp
+ *
+ * Thanks to:
+ * Werner Heuser
+ * Alexandre Duret-Lutz
+ * Xavier Roche
+ * Pam Huntley
+ * Gael Stephan
+ * Sebastian Henschel
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+
+#define VERSION "2.0"
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#ifdef BIGENDIAN
+typedef struct {
+ u32 h;
+ u32 l;
+} u64;
+#else /* BIGENDIAN */
+typedef struct {
+ u32 l;
+ u32 h;
+} u64;
+#endif /* BIGENDIAN */
+
+#define WORD(x) (*(const u16 *)(x))
+#define DWORD(x) (*(const u32 *)(x))
+#define QWORD(x) (*(const u64 *)(x))
+
+struct bios_entry {
+ const char *anchor;
+ off_t low_address;
+ off_t high_address;
+ size_t (*length)(const u8 *);
+ int (*decode)(const u8*, size_t);
+};
+
+/*
+ * Tools
+ */
+
+static int myread(int fd, u8 *buf, size_t count, const char *prefix)
+{
+ ssize_t r=1;
+ size_t r2=0;
+
+ while(r2!=count && r!=0)
+ {
+ r=read(fd, buf+r2, count-r2);
+ if(r==-1)
+ {
+ if(errno!=EINTR)
+ {
+ close(fd);
+ perror(prefix);
+ return -1;
+ }
+ }
+ else
+ r2+=r;
+ }
+
+ if(r2!=count)
+ {
+ close(fd);
+ fprintf(stderr, "%s: Unexpected end of file\n", prefix);
+ return -1;
+ }
+
+ return 0;
+}
+
+static __inline__ int checksum(const u8 *buf, size_t len)
+{
+ u8 sum=0;
+ size_t a;
+
+ for(a=0; a<len; a++)
+ sum+=buf[a];
+ return (sum==0);
+}
+
+/*
+ * SMBIOS
+ */
+
+static size_t smbios_length(const u8 *p)
+{
+ return(p[0x05]==0x1E?0x1F:p[0x05]);
+}
+
+static int smbios_decode(const u8 *p, size_t len)
+{
+ if(len<0x1F || !checksum(p, p[0x05])
+ || memcmp("_DMI_", p+0x10, 5)!=0
+ || !checksum(p+0x10, 0x0F))
+ return 0;
+
+ printf("SMBIOS %u.%u present.\n",
+ p[0x06], p[0x07]);
+ printf("\tStructure Table Length: %u bytes\n",
+ WORD(p+0x16));
+ printf("\tStructure Table Address: 0x%08X\n",
+ DWORD(p+0x18));
+ printf("\tNumber Of Structures: %u\n",
+ WORD(p+0x1C));
+ printf("\tMaximum Structure Size: %u bytes\n",
+ WORD(p+0x08));
+
+ return 1;
+}
+
+static size_t dmi_length(__attribute__ ((unused)) const u8 *p)
+{
+ return(0x0F);
+}
+
+static int dmi_decode(const u8 *p, size_t len)
+{
+ if(len<0x0F || !checksum(p, len))
+ return 0;
+
+ printf("Legacy DMI %u.%u present.\n",
+ p[0x0E]>>4, p[0x0E]&0x0F);
+ printf("\tStructure Table Length: %u bytes\n",
+ WORD(p+0x06));
+ printf("\tStructure Table Address: 0x%08X\n",
+ DWORD(p+0x08));
+ printf("\tNumber Of Structures: %u\n",
+ WORD(p+0x0C));
+
+ return 1;
+}
+
+/*
+ * SYSID
+ */
+
+static size_t sysid_length(const u8 *p)
+{
+ return WORD(p+0x08);
+}
+
+static int sysid_decode(const u8 *p, size_t len)
+{
+ if(len<0x11 || !checksum(p, WORD(p+0x08)))
+ return 0;
+
+ printf("SYSID present.\n");
+ printf("\tRevision: %u\n",
+ p[0x10]);
+ printf("\tStructure Table Address: 0x%08X\n",
+ DWORD(p+0x0A));
+ printf("\tNumber Of Structures: %u\n",
+ WORD(p+0x0E));
+
+ return 1;
+}
+
+/*
+ * PnP
+ */
+
+static size_t pnp_length(const u8 *p)
+{
+ return(p[0x05]);
+}
+
+static const char *pnp_event_notification(u8 code)
+{
+ static const char *notification[]={
+ "Not Supported", /* 0x0 */
+ "Polling",
+ "Asynchronous",
+ "Unknown" /* 0x3 */
+ };
+
+ return notification[code];
+}
+
+static int pnp_decode(const u8 *p, size_t len)
+{
+ if(len<0x21 || !checksum(p, p[0x05]))
+ return 0;
+
+ printf("PNP BIOS %u.%u present.\n",
+ p[0x04]>>4, p[0x04]&0x0F);
+ printf("\tEvent Notification: %s\n",
+ pnp_event_notification(WORD(p+0x06)&0x03));
+ if((WORD(p+0x06)&0x03)==0x01)
+ printf("\tEvent Notification Flag Address: 0x%08X\n",
+ DWORD(p+0x09));
+ printf("\tReal Mode 16-bit Code Address: %04X:%04X\n",
+ WORD(p+0x0F), WORD(p+0x0D));
+ printf("\tReal Mode 16-bit Data Address: %04X:0000\n",
+ WORD(p+0x1B));
+ printf("\t16-bit Protected Mode Code Address: 0x%08X\n",
+ DWORD(p+0x13)+WORD(p+0x11));
+ printf("\t16-bit Protected Mode Data Address: 0x%08X\n",
+ DWORD(p+0x1D));
+ if(DWORD(p+0x17)!=0)
+ printf("\tOEM Device Identifier: %c%c%c%02X%02X\n",
+ 0x40+((p[0x17]>>2)&0x1F),
+ 0x40+((p[0x17]&0x03)<<3)+((p[0x18]>>5)&0x07),
+ 0x40+(p[0x18]&0x1F), p[0x19], p[0x20]);
+
+ return 1;
+}
+
+/*
+ * ACPI
+ */
+
+static size_t acpi_length(const u8 *p)
+{
+ return(p[15]==2?36:20);
+}
+
+static const char *acpi_revision(u8 code)
+{
+ switch(code)
+ {
+ case 0:
+ return " 1.0";
+ case 2:
+ return " 2.0";
+ default:
+ return "";
+ }
+}
+
+static int acpi_decode(const u8 *p, size_t len)
+{
+ if(len<20 || !checksum(p, 20))
+ return 0;
+
+ printf("ACPI%s present.\n",
+ acpi_revision(p[15]));
+ printf("\tOEM Identifier: ");
+ fwrite(p+9, 6, 1, stdout);
+ printf("\n");
+ printf("\tRSD Table 32-bit Address: 0x%08X\n",
+ DWORD(p+16));
+
+ if(DWORD(p+20)>len || !checksum(p, DWORD(p+20)))
+ return 0;
+
+ if(DWORD(p+20)<32) return 1;
+
+ printf("\tXSD Table 64-bit Address: 0x%08X%08X\n",
+ QWORD(p+24).h, QWORD(p+24).l);
+
+ return 1;
+}
+
+/*
+ * Sony
+ */
+
+static size_t sony_length(const u8 *p)
+{
+ return(p[0x05]);
+}
+
+static int sony_decode(const u8 *p, __attribute__ ((unused)) size_t len)
+{
+ if(!checksum(p, p[0x05]))
+ return 0;
+
+ printf("Sony system detected.\n");
+
+ return 1;
+}
+
+/*
+ * BIOS32
+ */
+
+static size_t bios32_length(const u8 *p)
+{
+ return p[0x09]<<4;
+}
+
+static int bios32_decode(const u8 *p, size_t len)
+{
+ if(len<0x0A || !checksum(p, p[0x09]<<4))
+ return 0;
+
+ printf("BIOS32 Service Directory present.\n");
+ printf("\tRevision: %u\n",
+ p[0x08]);
+ printf("\tCalling Interface Address: 0x%08X\n",
+ DWORD(p+0x04));
+
+ return 1;
+}
+
+/*
+ * PIR
+ */
+
+static void pir_irqs(u16 code)
+{
+ if(code==0)
+ printf(" None");
+ else
+ {
+ u8 i;
+
+ for(i=0; i<16; i++)
+ if(code&(1<<i))
+ printf(" %u", i);
+ }
+}
+
+static void pir_slot_number(u8 code)
+{
+ if(code==0)
+ printf(" on-board");
+ else
+ printf(" slot number %u", code);
+}
+
+static size_t pir_length(const u8 *p)
+{
+ return WORD(p+6);
+}
+
+static int pir_decode(const u8 *p, size_t len)
+{
+ int i;
+
+ if(len<32 || !checksum(p, WORD(p+6)))
+ return 0;
+
+ printf("PCI Interrupt Routing %u.%u present.\n",
+ p[5], p[4]);
+ printf("\tRouter ID: %02x:%02x.%1x\n",
+ p[8], p[9]>>3, p[9]&0x07);
+ printf("\tExclusive IRQs:");
+ pir_irqs(WORD(p+10));
+ printf("\n");
+ if(DWORD(p+12)!=0)
+ printf("\tCompatible Router: %04x:%04x\n",
+ WORD(p+12), WORD(p+14));
+ if(DWORD(p+16)!=0)
+ printf("\tMiniport Data: 0x%08X\n",
+ DWORD(p+16));
+
+ for(i=1; i<=(WORD(p+6)-32)/16; i++)
+ {
+ printf("\tSlot Entry %u: ID %02x:%02x,",
+ i, p[(i+1)*16], p[(i+1)*16+1]>>3);
+ pir_slot_number(p[(i+1)*16+14]);
+ printf("\n");
+/* printf("\tSlot Entry %u\n", i);
+ printf("\t\tID: %02x:%02x\n",
+ p[(i+1)*16], p[(i+1)*16+1]>>3);
+ printf("\t\tLink Value for INTA#: %u\n",
+ p[(i+1)*16+2]);
+ printf("\t\tIRQ Bitmap for INTA#:");
+ pir_irqs(WORD(p+(i+1)*16+3));
+ printf("\n");
+ printf("\t\tLink Value for INTB#: %u\n",
+ p[(i+1)*16+5]);
+ printf("\t\tIRQ Bitmap for INTB#:");
+ pir_irqs(WORD(p+(i+1)*16+6));
+ printf("\n");
+ printf("\t\tLink Value for INTC#: %u\n",
+ p[(i+1)*16+8]);
+ printf("\t\tIRQ Bitmap for INTC#:");
+ pir_irqs(WORD(p+(i+1)*16+9));
+ printf("\n");
+ printf("\t\tLink Value for INTD#: %u\n",
+ p[(i+1)*16+11]);
+ printf("\t\tIRQ Bitmap for INTD#:");
+ pir_irqs(WORD(p+(i+1)*16+12));
+ printf("\n");
+ printf("\t\tSlot Number:");
+ pir_slot_number(p[(i+1)*16+14]);
+ printf("\n");*/
+ }
+
+ return 1;
+}
+
+/*
+ * Main
+ */
+
+static struct bios_entry bios_entries[]={
+ { "_SM_", 0xF0000, 0xFFFFF, smbios_length, smbios_decode },
+ { "_DMI_", 0xF0000, 0xFFFFF, dmi_length, dmi_decode },
+ { "_SYSID_", 0xE0000, 0xFFFFF, sysid_length, sysid_decode },
+ { "$PnP", 0xF0000, 0xFFFFF, pnp_length, pnp_decode },
+ { "RSD PTR ", 0xE0000, 0xFFFFF, acpi_length, acpi_decode },
+ { "$SNY", 0xE0000, 0xFFFFF, sony_length, sony_decode },
+ { "_32_", 0xE0000, 0xFFFFF, bios32_length, bios32_decode },
+ { "$PIR", 0xF0000, 0xFFFFF, pir_length, pir_decode },
+ { NULL, 0, 0, NULL, NULL }
+};
+
+int main(__attribute__ ((unused)) int argc, const char *argv[])
+{
+ u8 buf[16];
+ int fd;
+ off_t fp=0xE0000;
+ const char *devmem="/dev/mem";
+
+ if(sizeof(u8)!=1 || sizeof(u16)!=2 || sizeof(u32)!=4)
+ {
+ fprintf(stderr,"%s: compiler incompatibility\n", argv[0]);
+ exit(255);
+ }
+
+ if((fd=open(devmem, O_RDONLY))==-1 || lseek(fd, fp, SEEK_SET)==-1)
+ {
+ perror(devmem);
+ exit(1);
+ }
+
+ printf("# biosdecode %s\n", VERSION);
+ while(fp<0xFFFFF)
+ {
+ int i;
+
+ if(myread(fd, buf, 16, devmem)==-1)
+ exit(1);
+
+ for(i=0; bios_entries[i].anchor!=NULL; i++)
+ {
+ if(strncmp((char *)buf, bios_entries[i].anchor, strlen(bios_entries[i].anchor))==0
+ && fp>=bios_entries[i].low_address
+ && fp<bios_entries[i].high_address)
+ {
+ off_t len=bios_entries[i].length(buf);
+ u8 *p;
+
+ if(fp+len-1<=bios_entries[i].high_address)
+ {
+ if((p=malloc(len))==NULL)
+ {
+ perror("malloc");
+ exit(1);
+ }
+
+ memcpy(p, buf, 16);
+ if(len>16)
+ {
+ /* buffer completion */
+ if(myread(fd, p+16, len-16, devmem)==-1)
+ {
+ free(p);
+ exit(1);
+ }
+ }
+ if(bios_entries[i].decode(p, len))
+ fp+=(((len-1)>>4)<<4);
+ lseek(fd, fp+16, SEEK_SET);
+ free(p);
+ }
+ }
+ }
+ fp+=16;
+ }
+
+ if(close(fd)==-1)
+ {
+ perror(devmem);
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/dmidecode.c b/dmidecode.c
index ff4440d..1f5643f 100644
--- a/dmidecode.c
+++ b/dmidecode.c
@@ -1,21 +1,22 @@
/*
- * DMI decode rev 1.8
+ * DMI decode rev 2.0
*
- * (C) 2000-2002 Alan Cox <alan@redhat.com>
+ * (C) 2000-2002 Alan Cox <alan@redhat.com>
+ * (C) 2002 Jean Delvare <khali@linux-fr>
*
- * 2-July-2001 Matt Domsch <Matt_Domsch@dell.com>
+ * 2001-07-02 Matt Domsch <Matt_Domsch@dell.com>
* Additional structures displayed per SMBIOS 2.3.1 spec
*
* 13-December-2001 Arjan van de Ven <arjanv@redhat.com>
* Fix memory bank type (DMI case 6)
*
- * 3-August-2002 Mark D. Studebaker <mds@paradyne.com>
+ * 2002-08-03 Mark D. Studebaker <mds@paradyne.com>
* Better indent in dump_raw_data
- * Fix return value in dmi_bus_name
+ * Fix return value of dmi_bus_name
* Additional sensor fields decoded
* Fix compilation warnings
*
- * 6-August-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-08-06 Jean Delvare <khali@linux-fr.org>
* Reposition file pointer after DMI table display
* Disable first RSD PTR checksum (was not correct anyway)
* Show actual DMI struct count and occupied size
@@ -26,7 +27,7 @@
* Code optimization in DMI information display
* Fix all compilation warnings
*
- * 9-August-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-08-09 Jean Delvare <khali@linux-fr.org>
* Better DMI struct count/size error display
* More careful memory access in dmi_table
* DMI case 13 (Language) decoded
@@ -35,22 +36,22 @@
* DMI 0.0 case handled
* Fix return value of dmi_port_type and dmi_port_connector_type
*
- * 23-August-2002 Alan Cox <alan@redhat.com>
+ * 2002-08-23 Alan Cox <alan@redhat.com>
* Make the code pass -Wall -pedantic by fixing a few harmless sign of
* pointer mismatches
- * Correct main prototype
+ * Correct main() prototype
* Check for compilers with wrong type sizes
*
- * 17-Sep-2002 Larry Lile <llile@dreamworks.com>
+ * 2002-09-17 Larry Lile <llile@dreamworks.com>
* Type 16 & 17 structures displayed per SMBIOS 2.3.1 spec
*
- * 20-September-2002 Dave Johnson <ddj@cascv.brown.edu>
+ * 2002-09-20 Dave Johnson <ddj@cascv.brown.edu>
* Fix comparisons in dmi_bus_name
* Fix comparison in dmi_processor_type
* Fix bitmasking in dmi_onboard_type
* Fix return value of dmi_temp_loc
*
- * 28-September-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-09-28 Jean Delvare <khali@linux-fr.org>
* Fix missing coma in dmi_bus_name
* Remove unwanted bitmaskings in dmi_mgmt_dev_type, dmi_mgmt_addr_type,
* dmi_fan_type, dmi_volt_loc, dmi_temp_loc and dmi_status
@@ -58,7 +59,7 @@
* Make the code pass -W again
* Fix return value of dmi_card_size
*
- * 05-October-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-10-05 Jean Delvare <khali@linux-fr.org>
* More ACPI decoded
* More PNP decoded
* More SYSID decoded
@@ -73,110 +74,230 @@
* Fix an off-by-one error that caused the last address being
* scanned to be 0x100000, not 0xFFFF0 as it should
*
- * 10-October-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-10-10 Jean Delvare <khali@linux-fr.org>
* Remove extra semicolon at the end of dmi_memory_array_use
* Fix compilation warnings
* Add missing backslash in DMI case 37
* Fix BIOS ROM size (DMI case 0)
*
- * 12-October-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-10-12 Jean Delvare <khali@linux-fr.org>
* Fix maximum cache size and installed size being inverted
* Fix typos in port types
*
- * 14-October-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-10-14 Jean Delvare <khali@linux-fr.org>
* Fix typo in dmi_memory_array_location
* Replace Kbyte by kB in DMI case 16
* Add DDR entry in dmi_memory_device_type
* Fix extra s in SYSIS
*
- * 15-October-2002 Jean Delvare <khali@linux-fr.org>
+ * 2002-10-15 Jean Delvare <khali@linux-fr.org>
* Fix bad index in DMI case 27 (cooling device)
*
+ * 2002-10-18 Jean Delvare <khali@linux-fr.org>
+ * Complete rewrite
+ * Now complies with SMBIOS specification 2.3.3
+ * Removed all non-DMI stuff
+ *
+ * 2002-10-21 Jean Delvare <khali@linux-fr.org>
+ * Changed supported log type descriptors display
+ * Code optimization in event log status
+ * Remove extra newline in voltage probe accuracy
+ * Display "OEM-specific" if type is 128 or more
+ * Do not display Strings on dump if there are no strings
+ * Add ASCII-filtering to dmi_string
+ * Convert all dates to ISO 8601
+ *
* 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 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.
*
- * 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.
+ * Unless specified otherwise, all references are aimed at the "System
+ * Management BIOS Reference Specification, Version 2.3.3" document,
+ * available from http://www.dmtf.org/standards/bios.php.
*
- * 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
+ * Note to contributors:
+ * Please reference every value you add or modify, especially if the
+ * information does not come from the above mentioned specification.
*
- * 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.
- * [In the light of TCPA and Palladium the author urges
- * other open source authors to add such a clarification]
+ * Additional references:
+ * - Intel AP-485 revision 21
+ * "Intel Processor Identification and the CPUID Instruction"
+ * http://developer.intel.com/design/xeon/applnots/241618.htm
+ * - DMTF Master MIF version 020507
+ * "DMTF approved standard groups"
+ * http://www.dmtf.org/standards/standard_dmi.php
+ *
+ * Thanks to:
+ * Werner Heuser
+ * Alexandre Duret-Lutz
+ * Xavier Roche
+ * Pam Huntley
+ * Gael Stephan
+ * Sebastian Henschel
*/
+#include <sys/types.h>
+#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
+
+#define VERSION "2.0"
-#define VERSION "1.8"
+static const char *out_of_spec = "<OUT OF SPEC>";
+static const char *bad_index = "<BAD INDEX>";
typedef unsigned char u8;
typedef unsigned short u16;
+typedef signed short i16;
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);
- }
-}
+/*
+ * 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_LITTLEENDIAN
+static u64 U64(u32 low, u32 high)
+{
+ u64 self;
+
+ self.l=low;
+ self.h=high;
+
+ return self;
+}
+#endif
struct dmi_header
{
- u8 type;
- u8 length;
- u16 handle;
+ 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
+
+/*
+ * Tools
+ */
+
+static int myread(int fd, u8 *buf, size_t count, const char *prefix)
+{
+ ssize_t r=1;
+ size_t r2=0;
+
+ while(r2!=count && r!=0)
+ {
+ r=read(fd, buf+r2, count-r2);
+ if(r==-1)
+ {
+ if(errno!=EINTR)
+ {
+ close(fd);
+ perror(prefix);
+ return -1;
+ }
+ }
+ else
+ r2+=r;
+ }
+
+ if(r2!=count)
+ {
+ close(fd);
+ fprintf(stderr, "%s: Unexpected end of file\n", prefix);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * 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 "";
+ return "Not Specified";
bp+=dm->length;
while(s>1 && *bp)
@@ -185,151 +306,324 @@ static const char *dmi_string(struct dmi_header *dm, u8 s)
bp++;
s--;
}
+
if(!*bp)
- return "<bad index>";
+ return bad_index;
+
+ /* ASCII filtering */
+ for(i=0; i<strlen(bp); i++)
+ if(bp[i]<32 || bp[i]==127)
+ bp[i]='.';
+
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);
+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("%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<=0x11)
- return bus[num];
- if(num>=0xA0 && num<=0xA4)
- return jpbus[num - 0xA0];
- return "";
-}
-
-const char *dmi_bus_width(u8 code)
+ printf(" %u kB", code>>10);
+}
+
+static void dmi_bios_characteristics(u64 code, const char *prefix)
{
- 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==3)
- return("Short ");
- if(v==4)
- 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");
-}
+ /* 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;
-const char *dmi_chassis_type(u8 code)
+ 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)
{
- static const char *chassis_type[]={
- "",
+ /* 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",
@@ -341,45 +635,922 @@ const char *dmi_chassis_type(u8 code)
"Notebook",
"Hand Held",
"Docking Station",
- "All in One",
+ "All In One",
"Sub Notebook",
"Space-saving",
"Lunch Box",
- "Main Server Chassis",
+ "Main Server Chassis", /* master.mif says System */
"Expansion Chassis",
- "SubChassis",
+ "Sub Chassis",
"Bus Expansion Chassis",
"Peripheral Chassis",
"RAID Chassis",
"Rack Mount Chassis",
"Sealed-case PC",
+ "Multi-system" /* 0x19 */
};
- code &= ~0x80;
- if(code>0x18)
- return "";
- return chassis_type[code];
+ 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];
}
-const char *dmi_port_connector_type(u8 code)
+static const char *dmi_chassis_state(u8 code)
{
- static const char *connector_type[]={
+ /* 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",
+ 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",
+ NULL, /* 0x7A */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 0x7F */
+ "Weitek",
+ NULL, /* 0x81 */
+ "Itanium",
+ NULL, /* 0x83 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 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",
+ NULL, /* 0xB8 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 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 */
+ };
+
+ if(family[code]!=NULL)
+ return family[code];
+ return out_of_spec;
+}
+
+static void dmi_processor_id(u8 type, u8 *p, const char *version, const char *prefix)
+{
+ /* Intel AP-485 revision 21 */
+ static const char *flags[32]={
+ "FPU (Floating-point unit on-chip)", /* 0 */
+ "VME (Virtual mode extension)",
+ "DE (Debugging extension)",
+ "PSE (Page size extension)",
+ "TSC (Time stamp counter)",
+ "MSR (Model specific registers)",
+ "PAE (Physical address extension)",
+ "MCE (Machine check exception)",
+ "CX8 (CMPXCHG8 instruction supported)",
+ "APIC (On-chip APIC hardware supported)",
+ NULL, /* 10 */
+ "SEP (Fast system call)",
+ "MTRR (Memory type range registers)",
+ "PGE (Page global enable)",
+ "MCA (Machine check architecture)",
+ "CMOV (Conditional move instruction supported)",
+ "PAT (Page attribute table)",
+ "PSE-36 (36-bit page size extension)",
+ "PSN (Processor serial number present and enabled)",
+ "CLFSH (CLFLUSH instruction supported)",
+ NULL, /* 20 */
+ "DS (Debug store)",
+ "ACPI (ACPI supported)",
+ "MMX (MMX technology supported)",
+ "FXSR (Fast floating-point save and restore)",
+ "SSE (Streaming SIMD extensions)",
+ "SSE2 (Streaming SIMD extensions 2)",
+ "SS (Self-snoop)",
+ "HTT (Hyper-threading technology)",
+ "TM (Thermal monitor supported)",
+ NULL, /* 30 */
+ NULL /* 31 */
+ };
+ u32 eax;
+ int cpuid=0;
+
+ /*
+ * This might help learn about new processors supporting the
+ * CPUID instruction or another form of identification.
+ */
+ printf("%sID: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ prefix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+
+ if(type==0x05) /* 80386 */
+ {
+ u16 dx=WORD(p);
+ /*
+ * 80386 have a different signature.
+ */
+ printf("%sSignature: Type %u, Family %u, Major Stepping %u, Minor Stepping %u\n",
+ prefix, dx>>12, (dx>>8)&0xF, (dx>>4)&0xF, dx&0xF);
+ return;
+ }
+ if(type==0x06) /* 80486 */
+ {
+ u16 dx=WORD(p);
+ /*
+ * Not all 80486 CPU support the CPUID instruction, we have to find
+ * wether the one we have here does or not. Note that this trick
+ * works only because we know that 80486 must be little-endian.
+ */
+ if((dx&0x0F00)==0x0400 && ((dx&0x00F0)==0x0040 || (dx&0x00F0)>=0x0070))
+ cpuid=1;
+ }
+ else if((type>=0x0B && type<=0x13) /* Intel, Cyrix */
+ || (type>=0x18 && type<=0x1D) || type==0x1F /* AMD */
+ || (type>=0xB0 && type<=0xB3) /* Intel */
+ || (type>=0xB5 && type<=0xB7)) /* Intel, AMD */
+ cpuid=1;
+ else if(type==0x01)
+ {
+ /*
+ * Some X86-class CPU have family "Other". In this case, we use
+ * the version string to determine if they are known to support the
+ * CPUID instruction.
+ */
+ if(strcmp(version, "AMD Athlon(TM) Processor")==0)
+ cpuid=1;
+ else
+ return;
+ }
+ else /* not X86-class */
+ return;
+
+ eax=DWORD(p);
+ printf("%sSignature: Type %u, Family %u, Model %u, Stepping %u\n",
+ prefix, (eax>>12)&0x3, ((eax>>16)&0xFF0)+((eax>>8)&0x00F),
+ ((eax>>12)&0xF0)+((eax>>4)&0x0F), eax&0xF);
+ if(cpuid)
+ {
+ u32 edx=DWORD(p+4);
+
+ printf("%sFlags:", prefix);
+ if((edx&0x3FF7FDFF)==0)
+ printf(" None\n");
+ else
+ {
+ int i;
+
+ printf("\n");
+ for(i=0; i<=31; i++)
+ if(flags[i]!=NULL && edx&(1<<i))
+ printf("%s\t%s\n", prefix, flags[i]);
+ }
+ }
+}
+
+static void dmi_processor_voltage(u8 code)
+{
+ /* 3.3.5.4 */
+ static const char *voltage[]={
+ "5.0 V", /* 0 */
+ "3.3 V",
+ "2.9 V" /* 2 */
+ };
+ int i;
+
+ if(code&0x80)
+ printf(" %.1f V", (float)(code&0x7f)/10);
+ else
+ for(i=0; i<=2; i++)
+ if(code&(1<<i))
+ printf(" %s", voltage[i]);
+}
+
+static void dmi_processor_frequency(u16 code)
+{
+ if(code)
+ printf(" %u MHz", code);
+ else
+ printf(" Unknown");
+}
+
+static const char *dmi_processor_status(u8 code)
+{
+ static const char *status[]={
+ "Unknown", /* 0x00 */
+ "Enabled",
+ "Disabled By User",
+ "Disabled By BIOS",
+ "Idle", /* 0x04 */
+ "Other" /* 0x07 */
+ };
+
+ if(code<=0x04)
+ return status[code];
+ if(code==0x07)
+ return status[0x05];
+ return out_of_spec;
+}
+
+static const char *dmi_processor_upgrade(u8 code)
+{
+ /* 3.3.5.5 */
+ static const char *upgrade[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Daughter Board",
+ "ZIF Socket",
+ "Replaceable Piggy Back",
+ "None",
+ "LIF Socket",
+ "Slot 1",
+ "Slot 2",
+ "370-pin Socket",
+ "Slot A",
+ "Slot M",
+ "Socket 423",
+ "Socket A (Socket 462)",
+ "Socket 478" /* 0x0F */
+ };
+
+ if(code>=0x01 && code<=0x0F)
+ return upgrade[code-0x01];
+ return out_of_spec;
+}
+
+static void dmi_processor_cache(u16 code, const char *level, u16 ver)
+{
+ if(code==0xFFFF)
+ {
+ if(ver>=0x0203)
+ printf(" Not Provided");
+ else
+ printf(" No %s Cache", level);
+ }
+ else
+ printf(" 0x%04X", code);
+}
+
+/*
+ * 3.3.6 Memory Controller Information (Type 5)
+ */
+
+static const char *dmi_memory_controller_ed_method(u8 code)
+{
+ /* 3.3.6.1 */
+ static const char *method[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "None",
+ "8-bit Parity",
+ "32-bit ECC",
+ "64-bit ECC",
+ "128-bit ECC",
+ "CRC" /* 0x08 */
+ };
+
+ if(code>=0x01 && code<=0x08)
+ return(method[code-0x01]);
+ return out_of_spec;
+}
+
+static void dmi_memory_controller_ec_capabilities(u8 code, const char *prefix)
+{
+ /* 3.3.6.2 */
+ static const char *capabilities[]={
+ "Other", /* 0 */
+ "Unknown",
"None",
+ "Single-bit Error Correcting",
+ "Double-bit Error Correcting",
+ "Error Scrubbing" /* 5 */
+ };
+
+ if((code&0x3F)==0)
+ printf(" None\n");
+ else
+ {
+ int i;
+
+ printf("\n");
+ for(i=0; i<=5; i++)
+ if(code&(1<<i))
+ printf("%s%s\n", prefix, capabilities[i]);
+ }
+}
+
+static const char* dmi_memory_controller_interleave(u8 code)
+{
+ /* 3.3.6.3 */
+ static const char *interleave[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "One-way Interleave",
+ "Two-way Interleave",
+ "Four-way Interleave",
+ "Eight-way Interleave",
+ "Sixteen-way Interleave" /* 0x07 */
+ };
+
+ if(code>=0x01 && code<=0x07)
+ return(interleave[code-0x01]);
+ return(out_of_spec);
+}
+
+static void dmi_memory_controller_speeds(u16 code, const char *prefix)
+{
+ /* 3.3.6.4 */
+ const char *speeds[]={
+ "Other", /* 0 */
+ "Unknown",
+ "70 ns",
+ "60 ns",
+ "50 ns" /* 4 */
+ };
+
+ if((code&0x001F)==0)
+ printf(" None\n");
+ else
+ {
+ int i;
+
+ printf("\n");
+ for(i=0; i<=4; i++)
+ if(code&(1<<i))
+ printf("%s%s\n", prefix, speeds[i]);
+ }
+}
+
+static void dmi_memory_controller_slots(u8 count, u8 *p, const char *prefix)
+{
+ int i;
+
+ printf("%sAssociated Memory Slots: %u\n",
+ prefix, count);
+ for(i=0; i<count; i++)
+ printf("%s\t0x%04X\n",
+ prefix, WORD(p+sizeof(u16)*i));
+}
+
+/*
+ * 3.3.7 Memory Module Information (Type 6)
+ */
+
+static void dmi_memory_module_types(u16 code, const char *sep)
+{
+ /* 3.3.7.1 */
+ static const char *types[]={
+ "Other", /* 0 */
+ "Unknown",
+ "Standard",
+ "FPM",
+ "EDO",
+ "Parity",
+ "EDD",
+ "SIMM",
+ "DIMM",
+ "Burst EDO",
+ "SDRAM" /* 10 */
+ };
+
+ if((code&0x03FF)==0)
+ printf(" None");
+ else
+ {
+ int i;
+
+ for(i=0; i<=10; i++)
+ if(code&(1<<i))
+ printf("%s%s", sep, types[i]);
+ }
+}
+
+static void dmi_memory_module_connections(u8 code)
+{
+ if(code==0xFF)
+ printf(" None");
+ else
+ {
+ if((code&0xF0)!=0xF0)
+ printf(" %u", code>>4);
+ if((code&0x0F)!=0x0F)
+ printf(" %u", code&0x0F);
+ }
+}
+
+static void dmi_memory_module_speed(u8 code)
+{
+ if(code==0)
+ printf(" Unknown");
+ else
+ printf(" %u ns", code);
+}
+
+static void dmi_memory_module_size(u8 code)
+{
+ /* 3.3.7.2 */
+ switch(code&0x7F)
+ {
+ case 0x7D:
+ printf(" Not Determinable");
+ break;
+ case 0x7E:
+ printf(" Disabled");
+ break;
+ case 0x7F:
+ printf(" Not Installed");
+ break;
+ default:
+ printf(" %u MB", 1<<(code&0x7F));
+ }
+
+ if(code&0x80)
+ printf(" (Double-bank Connection)");
+ else
+ printf(" (Single-bank Connection)");
+}
+
+static void dmi_memory_module_error(u8 code, const char *prefix)
+{
+ if(code&(1<<2))
+ printf(" See Event Log\n");
+ else
+ { if((code&0x03)==0)
+ printf(" OK\n");
+ if(code&(1<<0))
+ printf("%sUncorrectable Errors\n", prefix);
+ if(code&(1<<1))
+ printf("%sCorrectable Errors\n", prefix);
+ }
+}
+
+/*
+ * 3.3.8 Cache Information (Type 7)
+ */
+
+static const char *dmi_cache_mode(u8 code)
+{
+ static const char *mode[]={
+ "Write Through", /* 0x00 */
+ "Write Back",
+ "Varies With Memory Address",
+ "Unknown" /* 0x03 */
+ };
+
+ return mode[code];
+}
+
+static const char *dmi_cache_location(u8 code)
+{
+ static const char *location[4]={
+ "Internal", /* 0x00 */
+ "External",
+ NULL, /* 0x02 */
+ "Unknown" /* 0x03 */
+ };
+
+ if(location[code]!=NULL)
+ return location[code];
+ return out_of_spec;
+}
+
+static void dmi_cache_size(u16 code)
+{
+ if(code&0x8000)
+ printf(" %u KB", (code&0x7FFF)<<6);
+ else
+ printf(" %u KB", code);
+}
+
+static void dmi_cache_types(u16 code, const char *sep)
+{
+ /* 3.3.8.1 */
+ static const char *types[]={
+ "Other", /* 0 */
+ "Unknown",
+ "Non-burst",
+ "Burst",
+ "Pipeline Burst",
+ "Synchronous",
+ "Asynchronous" /* 6 */
+ };
+
+ if((code&0x007F)==0)
+ printf(" None");
+ else
+ {
+ int i;
+
+ for(i=0; i<=6; i++)
+ if(code&(1<<i))
+ printf("%s%s", sep, types[i]);
+ }
+}
+
+static const char *dmi_cache_ec_type(u8 code)
+{
+ /* 3.3.8.2 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "None",
+ "Parity",
+ "Single-bit ECC",
+ "Multi-bit ECC" /* 0x06 */
+ };
+
+ if(code>=0x01 && code<=0x06)
+ return type[code-0x01];
+ return out_of_spec;
+}
+
+static const char *dmi_cache_type(u8 code)
+{
+ /* 3.3.8.3 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Instruction",
+ "Data",
+ "Unified" /* 0x05 */
+ };
+
+ if(code>=0x01 && code<=0x05)
+ return type[code-0x01];
+ return out_of_spec;
+}
+
+static const char *dmi_cache_associativity(u8 code)
+{
+ /* 3.3.8.4 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Direct Mapped",
+ "2-way Set-associative",
+ "4-way Set-associative",
+ "Fully Associative",
+ "8-way Set-associative",
+ "16-way Set-associative" /* 0x08 */
+ };
+
+ if(code>=0x01 && code<=0x08)
+ return type[code-0x01];
+ return out_of_spec;
+}
+
+/*
+ * 3.3.9 Port Connector Information (Type 8)
+ */
+
+static const char *dmi_port_connector_type(u8 code)
+{
+ /* 3.3.9.2 */
+ static const char *type[]={
+ "None", /* 0x00 */
"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",
+ "DB-25 male",
+ "DB-25 female",
+ "DB-15 male",
+ "DB-15 female",
+ "DB-9 male",
+ "DB-9 female",
"RJ-11",
"RJ-45",
"50 Pin MiniSCSI",
- "Mini-DIN",
- "Micro-DIN",
+ "Mini DIN",
+ "Micro DIN",
"PS/2",
"Infrared",
"HP-HIL",
@@ -393,98 +1564,612 @@ const char *dmi_port_connector_type(u8 code)
"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)",
+ "On Board Sound Input From CD-ROM",
+ "Mini Centronics Type-14",
+ "Mini Centronics Type-26",
+ "Mini Jack (headphones)",
"BNC",
- "1394",
+ "IEEE 1394" /* 0x21 */
+ };
+ static const char *type_0xA0[]={
+ "PC-98", /* 0xA0 */
+ "PC-98 Hireso",
+ "PC-H98",
+ "PC-98 Note",
+ "PC-98 Full" /* 0xA4 */
+ };
+
+ if(code<=0x21)
+ return type[code];
+ if(code>=0xA0 && code<=0xA4)
+ return type_0xA0[code-0xA0];
+ if(code==0xFF)
+ return "Other";
+ return out_of_spec;
+}
+
+static const char *dmi_port_type(u8 code)
+{
+ /* 3.3.9.3 */
+ static const char *type[]={
+ "None", /* 0x00 */
+ "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 16550 Compatible",
+ "Serial Port 16550A Compatible",
+ "SCSI Port",
+ "MIDI Port",
+ "Joystick 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-98Hireso",
+ "PC-98 Hireso",
"PC-H98",
- "PC-98Note",
- "PC98Full",
+ "Video Port",
+ "Audio Port",
+ "Modem Port",
+ "Network Port" /* 0x1F */
+ };
+ static const char *type_0xA0[]={
+ "8251 Compatible", /* 0xA0 */
+ "8251 FIFO Compatible" /* 0xA1 */
};
- if(code == 0xFF)
+ if(code<=0x1F)
+ return type[code];
+ if(code>=0xA0 && code<=0xA1)
+ return type_0xA0[code-0xA0];
+ if(code==0xFF)
return "Other";
+ return out_of_spec;
+}
+
+/*
+ * 3.3.10 System Slots (Type 9)
+ */
+
+static const char *dmi_slot_type(u8 code)
+{
+ /* 3.3.10.1 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "ISA",
+ "MCA",
+ "EISA",
+ "PCI",
+ "PC Card (PCMCIA)",
+ "VLB",
+ "Proprietary",
+ "Processor Card",
+ "Proprietary Memory Card",
+ "I/O Riser Card",
+ "NuBus",
+ "PCI-66",
+ "AGP",
+ "AGP 2x",
+ "AGP 4x",
+ "PCI-X" /* 0x12 */
+ };
+ static const char *type_0xA0[]={
+ "PC-98/C20", /* 0xA0 */
+ "PC-98/C24",
+ "PC-98/E",
+ "PC-98/Local Bus",
+ "PC-98/Card" /* 0xA4 */
+ };
+
+ if(code>=0x01 && code<=0x12)
+ return type[code-0x01];
+ if(code>=0xA0 && code<=0xA4)
+ return type_0xA0[code-0xA0];
+ return out_of_spec;
+}
+
+static const char *dmi_slot_bus_width(u8 code)
+{
+ /* 3.3.10.2 */
+ static const char *width[]={
+ "", /* 0x01, "Other" */
+ "", /* "Unknown" */
+ "8-bit ",
+ "16-bit ",
+ "32-bit ",
+ "64-bit ",
+ "128-bit " /* 0x07 */
+ };
+
+ if(code>=0x01 && code<=0x07)
+ return width[code-0x01];
+ return out_of_spec;
+}
+
+static const char *dmi_slot_current_usage(u8 code)
+{
+ /* 3.3.10.3 */
+ static const char *usage[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Available",
+ "In Use" /* 0x04 */
+ };
- if(code <= 0x21)
- return connector_type[code];
+ if(code>=0x01 && code<=0x04)
+ return usage[code-0x01];
+ return out_of_spec;
+}
+
+static const char *dmi_slot_length(u8 code)
+{
+ /* 3.3.1O.4 */
+ static const char *length[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Short",
+ "Long" /* 0x04 */
+ };
- if((code >= 0xA0) && (code <= 0xA4))
- return connector_type[code-0xA0+0x22];
+ if(code>=0x01 && code<=0x04)
+ return length[code-0x01];
+ return out_of_spec;
+}
+
+static void dmi_slot_id(u8 code1, u8 code2, u8 type, const char *prefix)
+{
+ /* 3.3.10.5 */
+ switch(type)
+ {
+ case 0x04: /* MCA */
+ printf("%sID: %u\n", prefix, code1);
+ break;
+ case 0x05: /* EISA */
+ printf("%sID: %u\n", prefix, code1);
+ break;
+ case 0x06: /* PCI */
+ case 0x0E: /* PCI */
+ case 0x0F: /* AGP */
+ case 0x10: /* AGP */
+ case 0x11: /* AGP */
+ case 0x12: /* PCI */
+ printf("%sID: %u\n", prefix, code1);
+ break;
+ case 0x07: /* PCMCIA */
+ printf("%sID: Adapter %u, Socket %u\n", prefix, code1, code2);
+ break;
+ }
+}
+
+static void dmi_slot_characteristics(u8 code1, u8 code2, const char *prefix)
+{
+ /* 3.3.10.6 */
+ static const char *characteristics1[]={
+ "5.0 V is provided", /* 1 */
+ "3.3 V is provided",
+ "Opening is shared",
+ "PC Card-16 is supported",
+ "Cardbus is supported",
+ "Zoom Video is supported",
+ "Modem ring resume is supported" /* 7 */
+ };
+ /* 3.3.10.7 */
+ static const char *characteristics2[]={
+ "PME signal is supported", /* 0 */
+ "Hot-plug devices are supported",
+ "SMBus signal is supported" /* 2 */
+ };
- return "";
+ if(code1&(1<<0))
+ printf(" Unknown\n");
+ else if((code1&0x7F)==0 && (code2&0x07)==0)
+ printf(" None\n");
+ else
+ {
+ int i;
+
+ printf("\n");
+ for(i=1; i<=7; i++)
+ if(code1&(1<<i))
+ printf("%s%s\n", prefix, characteristics1[i-1]);
+ for(i=0; i<=2; i++)
+ if(code2&(1<<i))
+ printf("%s%s\n", prefix, characteristics2[i]);
+ }
}
-static const char *dmi_memory_array_location(u8 num)
+/*
+ * 3.3.11 On Board Devices Information (Type 10)
+ */
+
+static const char *dmi_on_board_devices_type(u8 code)
{
- static const char *memory_array_location[]={
- "",
- "Other",
+ /* 3.3.11.1 */
+ static const char *type[]={
+ "Other", /* 0x01 */
"Unknown",
- "System board or motherboard",
- "ISA add-on card",
- "EISA add-on card",
- "PCI add-on card",
- "MCA add-on card",
- "PCMCIA add-on card",
- "Proprietary add-on card",
- "NuBus",
+ "Video",
+ "SCSI Controller",
+ "Ethernet",
+ "Token Ring",
+ "Sound" /* 0x07 */
+ };
+
+ if(code>=0x01 && code <=0x07)
+ return type[code-0x01];
+ return out_of_spec;
+}
+
+static void dmi_on_board_devices(struct dmi_header *h, const char *prefix)
+{
+ u8 *p=(u8 *)h+4;
+ u8 count=(h->length-0x04)/2;
+ int i;
+
+ for(i=0; i<count; i++)
+ {
+ printf("%sOn Board Device Information\n",
+ prefix);
+ printf("%s\tType: %s\n",
+ prefix, dmi_on_board_devices_type(p[2*i]&0x7F));
+ printf("%s\tStatus: %s\n",
+ prefix, p[2*i]&0x80?"Enabled":"Disabled");
+ printf("%s\tDescription: %s\n",
+ prefix, dmi_string(h, p[2*i+1]));
+ }
+}
+
+/*
+ * 3.3.12 OEM Strings (Type 11)
+ */
+
+static void dmi_oem_strings(struct dmi_header *h, const char *prefix)
+{
+ u8 *p=(u8 *)h+4;
+ u8 count=p[0x00];
+ int i;
+
+ for(i=1; i<=count; i++)
+ printf("%sString %d: %s\n",
+ prefix, i, dmi_string(h, i));
+}
+
+/*
+ * 3.3.13 System Configuration Options (Type 12)
+ */
+
+static void dmi_system_configuration_options(struct dmi_header *h, const char *prefix)
+{
+ u8 *p=(u8 *)h+4;
+ u8 count=p[0x00];
+ int i;
+
+ for(i=1; i<=count; i++)
+ printf("%sOption %d: %s\n",
+ prefix, i, dmi_string(h, i));
+}
+
+/*
+ * 3.3.14 BIOS Language Information (Type 13)
+ */
+
+static void dmi_bios_languages(struct dmi_header *h, const char *prefix)
+{
+ u8 *p=(u8 *)h+4;
+ u8 count=p[0x00];
+ int i;
+
+ for(i=1; i<=count; i++)
+ printf("%s%s\n",
+ prefix, dmi_string(h, i));
+}
+
+/*
+ * 3.3.15 Group Associations (Type 14)
+ */
+
+static void dmi_group_associations_items(u8 count, u8 *p, const char *prefix)
+{
+ int i;
+
+ for(i=0; i<count; i++)
+ {
+ printf("%s0x%04X (%s)\n",
+ prefix, WORD(p+3*i+1),
+ dmi_smbios_structure_type(p[3*i]));
+ }
+}
+
+/*
+ * 3.3.16 System Event Log (Type 15)
+ */
+
+static const char *dmi_event_log_method(u8 code)
+{
+ static const char *method[]={
+ "Indexed I/O, one 8-bit index port, one 8-bit data port", /* 0x00 */
+ "Indexed I/O, two 8-bit index ports, one 8-bit data port",
+ "Indexed I/O, one 16-bit index port, one 8-bit data port",
+ "Memory-mapped physical 32-bit address",
+ "General-pupose non-volatile data functions" /* 0x04 */
+ };
+
+ if(code<=0x04)
+ return method[code];
+ if(code>=0x80)
+ return "OEM-specific";
+ return out_of_spec;
+}
+
+static void dmi_event_log_status(u8 code)
+{
+ static const char *valid[]={
+ "Invalid", /* 0 */
+ "Valid" /* 1 */
};
- static const char *jp_memory_array_location[]={
- "PC-98/C20 add-on card",
- "PC-98/C24 add-on card",
- "PC-98/E add-on card",
- "PC-98/Local bus add-on card",
+ static const char *full[]={
+ "Not Full", /* 0 */
+ "Full" /* 1 */
};
- if(num<=0x0A)
- return memory_array_location[num];
- if(num>=0xA0 && num<0xA3)
- return jp_memory_array_location[num];
- return "";
+
+ printf(" %s, %s",
+ valid[code&(1<<0)], full[code&(1<<1)]);
}
-static const char *dmi_memory_array_use(u8 num)
+static void dmi_event_log_address(u8 method, u8 *p)
{
- static const char *memory_array_use[]={
- "",
- "Other",
+ /* 3.3.16.3 */
+ switch(method)
+ {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ printf(" Index 0x%04X, Data 0x%04X", WORD(p), WORD(p+2));
+ break;
+ case 0x03:
+ printf(" 0x%08X", DWORD(p));
+ break;
+ case 0x04:
+ printf(" 0x%04X", WORD(p));
+ break;
+ default:
+ printf(" Unknown");
+ }
+}
+
+static const char *dmi_event_log_header_type(u8 code)
+{
+ static const char *type[]={
+ "No Header", /* 0x00 */
+ "Type 1" /* 0x01 */
+ };
+
+ if(code<=0x01)
+ return type[code];
+ if(code>=0x80)
+ return "OEM-specific";
+ return out_of_spec;
+}
+
+static const char *dmi_event_log_descriptor_type(u8 code)
+{
+ /* 3.3.16.6.1 */
+ static const char *type[]={
+ NULL, /* 0x00 */
+ "Single-bit ECC memory error",
+ "Multi-bit ECC memory error",
+ "Parity memory error",
+ "Bus timeout",
+ "I/O channel block",
+ "Software NMI",
+ "POST memory resize",
+ "POST error",
+ "PCI parity error",
+ "PCI system error",
+ "CPU failure",
+ "EISA failsafe timer timeout",
+ "Correctable memory log disabled",
+ "Logging disabled",
+ NULL, /* 0x0F */
+ "System limit exceeded",
+ "Asynchronous hardware timer expired",
+ "System configuration information",
+ "Hard disk information",
+ "System reconfigured",
+ "Uncorrectable CPU-complex error",
+ "Log area reset/cleared",
+ "System boot" /* 0x17 */
+ };
+
+ if(code<=0x17 && type[code]!=NULL)
+ return type[code];
+ if(code>=0x80 && code<=0xFE)
+ return "OEM-specific";
+ if(code==0xFF)
+ return "End of log";
+ return out_of_spec;
+}
+
+static const char *dmi_event_log_descriptor_format(u8 code)
+{
+ /* 3.3.16.6.2 */
+ static const char *format[]={
+ "None", /* 0x00 */
+ "Handle",
+ "Multiple-event",
+ "Multiple-event handle",
+ "POST results bitmap",
+ "System management",
+ "Multiple-event system management" /* 0x06 */
+ };
+
+ if(code<=0x06)
+ return format[code];
+ if(code>=0x80)
+ return "OEM-specific";
+ return out_of_spec;
+}
+
+static void dmi_event_log_descriptors(u8 count, u8 len, u8 *p, const char *prefix)
+{
+ /* 3.3.16.1, , 3.3.16.6.2 */
+ int i;
+
+ for(i=0; i<count; i++)
+ {
+ if(len>=0x02)
+ {
+ printf("%sDescriptor %u: %s\n",
+ prefix, i+1, dmi_event_log_descriptor_type(p[i*len]));
+ printf("%sData Format %u: %s\n",
+ prefix, i+1, dmi_event_log_descriptor_format(p[i*len+1]));
+ }
+ }
+}
+
+/*
+ * 3.3.17 Physical Memory Array (Type 16)
+ */
+
+static const char *dmi_memory_array_location(u8 code)
+{
+ /* 3.3.17.1 */
+ static const char *location[]={
+ "Other", /* 0x01 */
"Unknown",
- "System memory",
- "Video memory",
- "Flash memory",
+ "System Board Or Motherboard",
+ "ISA Add-on Card",
+ "EISA Add-on Card",
+ "PCI Add-on Card",
+ "MCA Add-on Card",
+ "PCMCIA Add-on Card",
+ "Proprietary Add-on Card",
+ "NuBus" /* 0x0A, master.mif says 16 */
+ };
+ static const char *location_0xA0[]={
+ "PC-98/C20 Add-on Card", /* 0xA0 */
+ "PC-98/C24 Add-on Card",
+ "PC-98/E Add-on Card",
+ "PC-98/Local Bus Add-on Card",
+ "PC-98/Card Slot Add-on Card" /* 0xA4, from master.mif */
+ };
+
+ if(code>=0x01 && code<=0x0A)
+ return location[code-0x01];
+ if(code>=0xA0 && code<=0xA4)
+ return location_0xA0[code-0xA0];
+ return out_of_spec;
+}
+
+static const char *dmi_memory_array_use(u8 code)
+{
+ /* 3.3.17.2 */
+ static const char *use[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "System Memory",
+ "Video Memory",
+ "Flash Memory",
"Non-volatile RAM",
- "Cache memory",
+ "Cache Memory" /* 0x07 */
};
- if (num > 0x07)
- return "";
- return memory_array_use[num];
+
+ if(code>=0x01 && code<=0x07)
+ return use[code-0x01];
+ return out_of_spec;
}
-static const char *dmi_memory_array_error_correction_type(u8 num)
+static const char *dmi_memory_array_ec_type(u8 code)
{
- static const char *memory_array_error_correction_type[]={
- "",
- "Other",
+ /* 3.3.17.3 */
+ static const char *type[]={
+ "Other", /* 0x01 */
"Unknown",
"None",
"Parity",
"Single-bit ECC",
"Multi-bit ECC",
- "CRC",
+ "CRC" /* 0x07 */
};
- if (num > 0x07)
- return "";
- return memory_array_error_correction_type[num];
+
+ if(code>=0x01 && code<=0x07)
+ return type[code-0x01];
+ return out_of_spec;
}
-static const char *dmi_memory_device_form_factor(u8 num)
+static void dmi_memory_array_capacity(u32 code)
{
- static const char *memory_device_form_factor[]={
- "",
- "Other",
+ if(code==0x8000000)
+ printf(" Unknown");
+ else
+ {
+ if((code&0x000FFFFF)==0)
+ printf(" %u GB", code>>20);
+ else if((code&0x000003FF)==0)
+ printf(" %u MB", code>>10);
+ else
+ printf(" %u kB", code);
+ }
+}
+
+static void dmi_memory_array_error_handle(u16 code)
+{
+ if(code==0xFFFE)
+ printf(" Not Provided");
+ else if(code==0xFFFF)
+ printf(" No Error");
+ else
+ printf(" 0x%04X", code);
+}
+
+/*
+ * 3.3.18 Memory Device (Type 17)
+ */
+
+static void dmi_memory_device_width(u16 code)
+{
+ /*
+ * If no memory module is present, width may be 0
+ */
+ if(code==0xFFFF || code==0)
+ printf(" Unknown");
+ else
+ printf(" %u bits", code);
+}
+
+static void dmi_memory_device_size(u16 code)
+{
+ if(code==0)
+ printf(" No Module Installed");
+ else if(code==0xFFFF)
+ printf(" Unknown");
+ else
+ {
+ if(code&0x8000)
+ printf(" %u kB", code&0x7FFF);
+ else
+ printf(" %u MB", code);
+ }
+}
+
+static const char *dmi_memory_device_form_factor(u8 code)
+{
+ /* 3.3.18.1 */
+ static const char *form_factor[]={
+ "Other", /* 0x01 */
"Unknown",
"SIMM",
"SIP",
@@ -494,21 +2179,32 @@ static const char *dmi_memory_device_form_factor(u8 num)
"Proprietary Card",
"DIMM",
"TSOP",
- "Row of chips",
+ "Row Of Chips",
"RIMM",
"SODIMM",
- "SRIMM",
+ "SRIMM" /* 0x0E */
};
- if (num > 0x0E)
- return "";
- return memory_device_form_factor[num];
+
+ if(code>=0x01 && code<=0x0E)
+ return form_factor[code-0x01];
+ return out_of_spec;
}
-static const char *dmi_memory_device_type(u8 num)
+static void dmi_memory_device_set(u8 code)
{
- static const char *memory_device_type[]={
- "",
- "Other",
+ if(code==0)
+ printf(" None");
+ else if(code==0xFF)
+ printf(" Unknown");
+ else
+ printf(" %u", code);
+}
+
+static const char *dmi_memory_device_type(u8 code)
+{
+ /* 3.3.18.2 */
+ static const char *type[]={
+ "Other", /* 0x01 */
"Unknown",
"DRAM",
"EDRAM",
@@ -516,7 +2212,7 @@ static const char *dmi_memory_device_type(u8 num)
"SRAM",
"RAM",
"ROM",
- "FLASH",
+ "Flash",
"EEPROM",
"FEPROM",
"EPROM",
@@ -525,217 +2221,435 @@ static const char *dmi_memory_device_type(u8 num)
"SDRAM",
"SGRAM",
"RDRAM",
- "DDR"
- };
- if (num > 0x12)
- return "";
- return memory_device_type[num];
-}
-
-static void dmi_memory_device_detail(u8 v)
-{
- printf("\t\tType Detail: ");
- if (v&(1<<1))
- printf("Other ");
- if (v&(1<<2))
- printf("Unknown ");
- if (v&(1<<3))
- printf("Fast-paged ");
- if (v&(1<<4))
- printf("Static column ");
- if (v&(1<<5))
- printf("Pseudo-static ");
- if (v&(1<<6))
- printf("RAMBUS ");
- if (v&(1<<7))
- printf("Synchronous ");
- if (v&(1<<8))
- printf("CMOS ");
- if (v&(1<<9))
- printf("EDO ");
- if (v&(1<<10))
- printf("Window DRAM ");
- if (v&(1<<11))
- printf("Cache DRAM ");
- if (v&(1<<12))
- printf("Non-volatile ");
- printf("\n");
-}
-
-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 16550 Compatible",
- "Serial Port 16550A 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",
+ "DDR" /* 0x12 */
};
- if(code == 0xFF)
- return "Other";
-
- if (code <= 0x1F)
- return port_type[code];
+ if(code>=0x01 && code<=0x12)
+ return type[code-0x01];
+ return out_of_spec;
+}
+
+static void dmi_memory_device_type_detail(u16 code)
+{
+ /* 3.3.18.3 */
+ static const char *detail[]={
+ "Other", /* 1 */
+ "Unknown",
+ "Fast-paged",
+ "Static Column",
+ "Pseudo-static",
+ "RAMBus",
+ "Synchronous",
+ "CMOS",
+ "EDO",
+ "Window DRAM",
+ "Cache DRAM",
+ "Non-Volatile" /* 12 */
+ };
- if ((code >= 0xA0) && (code <= 0xA1))
- return port_type[code-0xA0+0x20];
+ if((code&0x1FFE)==0)
+ printf(" None");
+ else
+ {
+ int i;
+
+ for(i=1; i<=12; i++)
+ if(code&(1<<i))
+ printf(" %s", detail[i-1]);
+ }
+}
+
+static void dmi_memory_device_speed(u16 code)
+{
+ if(code==0)
+ printf(" Unknown");
+ else
+ printf(" %u MHz (%.1f ns)", code, (float)1000/code);
+}
+
+/*
+ * 3.3.19 32-bit Memory Error Information (Type 18)
+ */
+
+static const char *dmi_memory_error_type(u8 code)
+{
+ /* 3.3.19.1 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "OK"
+ "Bad Read",
+ "Parity Error",
+ "Single-bit Error",
+ "Double-bit Error",
+ "Multi-bit Error",
+ "Nibble Error",
+ "Checksum Error",
+ "CRC Error",
+ "Corrected Single-bit Error",
+ "Corrected Error",
+ "Uncorrectable Error" /* 0x0E */
+ };
- return "";
+ if(code>=0x01 && code<=0x0E)
+ return type[code-0x01];
+ return out_of_spec;
}
-const char *dmi_processor_type(u8 code)
+static const char *dmi_memory_error_granularity(u8 code)
{
- static const char *processor_type[]={
- "",
- "Other",
+ /* 3.3.19.2 */
+ static const char *granularity[]={
+ "Other", /* 0x01 */
"Unknown",
- "Central Processor",
- "Math Processor",
- "DSP Processor",
- "Video Processor"
+ "Device Level",
+ "Memory Partition Level" /* 0x04 */
};
- if(code == 0xFF)
- return "Other";
+ if(code>=0x01 && code<=0x04)
+ return granularity[code-0x01];
+ return out_of_spec;
+}
+
+static const char *dmi_memory_error_operation(u8 code)
+{
+ /* 3.3.19.3 */
+ static const char *operation[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Read",
+ "Write",
+ "Partial Write" /* 0x05 */
+ };
- if (code > 6)
- return "";
- return processor_type[code];
+ if(code>=0x01 && code<=0x05)
+ return operation[code-0x01];
+ return out_of_spec;
}
-const char *dmi_processor_family(u8 code)
+static void dmi_memory_error_syndrome(u32 code)
{
- static const char *processor_family[]={
- "",
- "Other",
+ if(code==0x00000000)
+ printf(" Unknown");
+ else
+ printf(" 0x%08X", code);
+}
+
+static void dmi_32bit_memory_error_address(u32 code)
+{
+ if(code==0x80000000)
+ printf(" Unknown");
+ else
+ printf(" 0x%08X", code);
+}
+
+/*
+ * 3.3.20 Memory Array Mapped Address (Type 19)
+ */
+
+static void dmi_mapped_address_size(u32 code)
+{
+ if(code==0)
+ printf(" Invalid");
+ else if((code&0x000FFFFF)==0)
+ printf(" %u GB", code>>20);
+ else if((code&0x000003FF)==0)
+ printf(" %u MB", code>>10);
+ else
+ printf(" %u kB", code);
+}
+
+/*
+ * 3.3.21 Memory Device Mapped Address (Type 20)
+ */
+
+static void dmi_mapped_address_row_position(u8 code)
+{
+ if(code==0)
+ printf(" %s", out_of_spec);
+ else if(code==0xFF)
+ printf(" Unknown");
+ else
+ printf(" %u", code);
+}
+
+static void dmi_mapped_address_interleave_position(u8 code, const char *prefix)
+{
+ if(code!=0)
+ {
+ printf("%sInterleave Position:", prefix);
+ if(code==0xFF)
+ printf(" Unknown");
+ else
+ printf(" %u", code);
+ printf("\n");
+ }
+}
+
+static void dmi_mapped_address_interleaved_data_depth(u8 code, const char *prefix)
+{
+ if(code!=0)
+ {
+ printf("%sInterleaved Data Depth:", prefix);
+ if(code==0xFF)
+ printf(" Unknown");
+ else
+ printf(" %u", code);
+ printf("\n");
+ }
+}
+
+/*
+ * 3.3.22 Built-in Pointing Device (Type 21)
+ */
+
+static const char *dmi_pointing_device_type(u8 code)
+{
+ /* 3.3.22.1 */
+ static const char *type[]={
+ "Other", /* 0x01 */
"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",
+ "Mouse",
+ "Track Ball",
+ "Track Point",
+ "Glide Point",
+ "Touch Pad",
+ "Touch Screen",
+ "Optical Sensor" /* 0x09 */
};
- if(code == 0xFF)
- return "Other";
+ if(code>=0x01 && code<=0x09)
+ return type[code-0x01];
+ return out_of_spec;
+}
+
+static const char *dmi_pointing_device_interface(u8 code)
+{
+ /* 3.3.22.2 */
+ static const char *interface[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Serial",
+ "PS/2",
+ "Infrared",
+ "HIP-HIL",
+ "Bus Mouse",
+ "ADB (Apple Desktop Bus)" /* 0x08 */
+ };
+ static const char *interface_0xA0[]={
+ "Bus Mouse DB-9", /* 0xA0 */
+ "Bus Mouse Micro DIN",
+ "USB" /* 0xA2 */
+ };
- if (code > 0x24)
- return "";
- return processor_family[code];
+ if(code>=0x01 && code<=0x08)
+ return interface[code-0x01];
+ if(code>=0xA0 && code<=0xA2)
+ return interface_0xA0[code-0xA0];
+ return out_of_spec;
}
-const char *dmi_onboard_type(u8 code)
+/*
+ * 3.3.23 Portable Battery (Type 22)
+ */
+
+static const char *dmi_battery_chemistry(u8 code)
{
- static const char *onboard_type[]={
- "",
- "Other",
+ /* 3.3.23.1 */
+ static const char *chemistry[]={
+ "Other", /* 0x01 */
"Unknown",
- "Video",
- "SCSI Controller",
- "Ethernet",
- "Token Ring",
- "Sound",
+ "Lead Acid",
+ "Nickel Cadmium",
+ "Nickel Metal Hydride",
+ "Lithium Ion",
+ "Zinc Air",
+ "Lithium Polymer" /* 0x08 */
};
- code &= ~0x80;
- if (code > 7)
- return "";
- return onboard_type[code];
+
+ if(code>=0x01 && code<=0x08)
+ return chemistry[code-0x01];
+ return out_of_spec;
}
-const char *dmi_mgmt_dev_type(u8 code)
+static void dmi_battery_capacity(u16 code, u8 multiplier)
{
- static const char *type[]={
- "",
- "Other",
+ if(code==0)
+ printf(" Unknown");
+ else
+ printf(" %u mWh", code*multiplier);
+}
+
+static void dmi_battery_voltage(u16 code)
+{
+ if(code==0)
+ printf(" Unknown");
+ else
+ printf(" %u mV", code);
+}
+
+static void dmi_battery_maximum_error(u8 code)
+{
+ if(code==0xFF)
+ printf(" Unknown");
+ else
+ printf(" %u%%", code);
+}
+
+/*
+ * 3.3.24 System Reset (Type 23)
+ */
+
+static const char *dmi_system_reset_boot_option(u8 code)
+{
+ static const char *option[]={
+ "Operating System", /* 0x1 */
+ "System Utilities",
+ "Do Not Reboot" /* 0x3 */
+ };
+
+ if(code>=0x1)
+ return option[code-0x1];
+ return out_of_spec;
+}
+
+static void dmi_system_reset_count(u16 code)
+{
+ if(code==0xFFFF)
+ printf(" Unknown");
+ else
+ printf(" %u", code);
+}
+
+static void dmi_system_reset_timer(u16 code)
+{
+ if(code==0xFFFF)
+ printf(" Unknown");
+ else
+ printf(" %u min", code);
+}
+
+/*
+ * 3.3.25 Hardware Security (Type 24)
+ */
+
+static const char *dmi_hardware_security_status(u8 code)
+{
+ static const char *status[]={
+ "Disabled", /* 0x00 */
+ "Enabled",
+ "Not Implemented",
+ "Unknown" /* 0x03 */
+ };
+
+ return status[code];
+}
+
+/*
+ * 3.3.26 System Power Controls (Type 25)
+ */
+
+static void dmi_power_controls_power_on(u8 *p)
+{
+ /* 3.3.26.1 */
+ if(dmi_bcd_range(p[0], 0x01, 0x12))
+ printf(" %02X", p[0]);
+ else
+ printf(" *");
+ if(dmi_bcd_range(p[1], 0x01, 0x31))
+ printf("-%02X", p[1]);
+ else
+ printf("-*");
+ if(dmi_bcd_range(p[2], 0x00, 0x23))
+ printf(" %02X", p[2]);
+ else
+ printf(" *");
+ if(dmi_bcd_range(p[3], 0x00, 0x59))
+ printf(":%02X", p[3]);
+ else
+ printf(":*");
+ if(dmi_bcd_range(p[4], 0x00, 0x59))
+ printf(":%02X", p[4]);
+ else
+ printf(":*");
+}
+
+/*
+ * 3.3.27 Voltage Probe (Type 26)
+ */
+
+static const char *dmi_voltage_probe_location(u8 code)
+{
+ /* 3.3.27.1 */
+ static const char *location[]={
+ "Other", /* 0x01 */
"Unknown",
- "LM75",
- "LM78",
- "LM79",
- "LM80",
- "LM81",
- "ADM9240",
- "DS1780",
- "MAX1617",
- "GL518SM",
- "W83781D",
- "HT82H791",
+ "Processor",
+ "Disk",
+ "Peripheral Bay",
+ "System Management Module",
+ "Motherboard",
+ "Memory Module",
+ "Processor Module",
+ "Power Unit",
+ "Add-in Card" /* 0x0B */
};
- if (code > 0x0d)
- return "";
- return type[code];
+ if(code>=0x01 && code<=0x0B)
+ return location[code-0x01];
+ return out_of_spec;
}
-const char *dmi_mgmt_addr_type(u8 code)
+static const char *dmi_probe_status(u8 code)
{
- static const char *type[]={
- "",
- "Other",
+ /* 3.3.27.1 */
+ static const char *status[]={
+ "Other", /* 0x01 */
"Unknown",
- "I/O",
- "Memory",
- "SMBus",
+ "OK",
+ "Non-critical",
+ "Critical",
+ "Non-recoverable" /* 0x06 */
};
- if (code > 5)
- return "";
- return type[code];
+ if(code>=0x01 && code<=0x06)
+ return status[code-0x01];
+ return out_of_spec;
+}
+
+static void dmi_voltage_probe_value(u16 code)
+{
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.3f V", (float)(i16)code/1000);
+}
+
+static void dmi_voltage_probe_resolution(u16 code)
+{
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.1f mV", (float)code/10);
+}
+
+static void dmi_probe_accuracy(u16 code)
+{
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.2f%%", (float)code/100);
}
-const char *dmi_fan_type(u8 code)
+/*
+ * 3.3.28 Cooling Device (Type 27)
+ */
+
+static const char *dmi_cooling_device_type(u8 code)
{
+ /* 3.3.28.1 */
static const char *type[]={
- "",
- "Other",
+ "Other", /* 0x01 */
"Unknown",
"Fan",
"Centrifugal Blower",
@@ -743,983 +2657,1326 @@ const char *dmi_fan_type(u8 code)
"Cabinet Fan",
"Power Supply Fan",
"Heat Pipe",
- "Integrated Refrigeration",
- "",
- "",
- "",
- "",
- "",
- "",
- "Active Cooling",
- "Passive Cooling",
+ "Integrated Refrigeration" /* 0x09 */
+ };
+ static const char *type_0x10[]={
+ "Active Cooling", /* 0x10, master.mif says 32 */
+ "Passive Cooling" /* 0x11, master.mif says 33 */
};
- if (code > 0x11)
- return "";
- return type[code];
+ if(code>=0x01 && code<=0x09)
+ return type[code-0x01];
+ if(code>=0x10 && code<=0x11)
+ return type_0x10[code-0x10];
+ return out_of_spec;
}
-const char *dmi_volt_loc(u8 code)
+static void dmi_cooling_device_speed(u16 code)
{
- static const char *type[]={
- "",
- "Other",
+ if(code==0x8000)
+ printf(" Unknown Or Non-rotating");
+ else
+ printf(" %u rpm", code);
+}
+
+/*
+ * 3.3.29 Temperature Probe (Type 28)
+ */
+
+static const char *dmi_temperature_probe_location(u8 code)
+{
+ /* 3.3.29.1 */
+ static const char *location[]={
+ "Other", /* 0x01 */
"Unknown",
"Processor",
"Disk",
"Peripheral Bay",
- "System Management Module",
+ "System Management Module", /* master.mif says SMB MAster */
"Motherboard",
"Memory Module",
"Processor Module",
"Power Unit",
"Add-in Card",
+ "Front Panel Board",
+ "Back Panel Board",
+ "Power System Board",
+ "Drive Back Plane" /* 0x0F */
};
- if (code > 0x0b)
- return "";
- return type[code];
+ if(code>=0x01 && code<=0x0F)
+ return location[code-0x01];
+ return out_of_spec;
}
-const char *dmi_temp_loc(u8 code)
+static void dmi_temperature_probe_value(u16 code)
{
- static const char *type[]={
- "Front Panel Board",
- "Back Panel Board",
- "Power System Board",
- "Drive Back Plane",
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.1f deg C", (float)(i16)code/10);
+}
+
+static void dmi_temperature_probe_resolution(u16 code)
+{
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.3f deg C", (float)code/1000);
+}
+
+/*
+ * 3.3.30 Electrical Current Probe (Type 29)
+ */
+
+static void dmi_current_probe_value(u16 code)
+{
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.3f A", (float)(i16)code/1000);
+}
+
+static void dmi_current_probe_resolution(u16 code)
+{
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.1f mA", (float)code/10);
+}
+
+/*
+ * 3.3.33 System Boot Information (Type 32)
+ */
+
+static const char *dmi_system_boot_status(u8 code)
+{
+ static const char *status[]={
+ "No errors detected", /* 0 */
+ "No bootable media",
+ "Operating system failed to load",
+ "Firmware-detected hardware failure",
+ "Operating system-detected hardware failure",
+ "User-requested boot",
+ "System security violation",
+ "Previously-requested image",
+ "System watchdog timer expired" /* 8 */
};
- if (code <= 0x0b)
- return dmi_volt_loc(code);
- if (code <= 0x0f)
- return type[code - 0x0c];
- return "";
+ if(code<=8)
+ return status[code];
+ if(code>=128 && code<=191)
+ return "OEM-specific";
+ if(code>=192 && code<=255)
+ return "Product-specific";
+ return out_of_spec;
+}
+
+/*
+ * 3.3.34 64-bit Memory Error Information (Type 33)
+ */
+
+static void dmi_64bit_memory_error_address(u64 code)
+{
+ if(code.h==0x80000000 && code.l==0x00000000)
+ printf(" Unknown");
+ else
+ printf(" 0x%08X%08X", code.h, code.l);
}
-const char *dmi_status(u8 code)
+/*
+ * 3.3.35 Management Device (Type 34)
+ */
+
+static const char *dmi_management_device_type(u8 code)
{
+ /* 3.3.35.1 */
static const char *type[]={
- "",
- "Other",
+ "Other", /* 0x01 */
"Unknown",
- "OK",
- "Non-critical",
- "Critical",
- "Non-recoverable",
+ "LM75",
+ "LM78",
+ "LM79",
+ "LM80",
+ "LM81",
+ "ADM9240",
+ "DS1780",
+ "MAX1617",
+ "GL518SM",
+ "W83781D",
+ "HT82H791" /* 0x0D */
};
- if (code > 6)
- return "";
- return type[code];
+ if(code>=0x01 && code<=0x0D)
+ return type[code-0x01];
+ return out_of_spec;
}
-/* 3 dec. places */
-const char *dmi_millivolt(u8 *data, int indx)
+static const char *dmi_management_device_address_type(u8 code)
{
- static char buffer[20];
- short int d;
+ /* 3.3.35.2 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "I/O Port",
+ "Memory",
+ "SMBus" /* 0x05 */
+ };
+
+ if(code>=0x01 && code<=0x05)
+ return type[code-0x01];
+ return out_of_spec;
+}
- 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;
+/*
+ * 3.3.38 Memory Channel (Type 37)
+ */
+
+static const char *dmi_memory_channel_type(u8 code)
+{
+ /* 3.3.38.1 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "RAMBus",
+ "Synclink" /* 0x04 */
+ };
+
+ if(code>=0x01 && code<=0x04)
+ return type[code-0x01];
+ return out_of_spec;
}
-/* 2 dec. places */
-const char *dmi_accuracy(u8 *data, int indx)
+static void dmi_memory_channel_devices(u8 count, u8 *p, const char *prefix)
{
- static char buffer[20];
- short int d;
+ int i;
+
+ for(i=1; i<=count; i++)
+ {
+ printf("%sDevice %u Load: %u\n",
+ prefix, i, p[3*i]);
+ printf("%sDevice %u Handle: 0x%04X\n",
+ prefix, i, WORD(p+3*i+1));
+ }
+}
+
+/*
+ * 3.3.39 IPMI Device Information (Type 38)
+ */
- 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;
+static const char *dmi_ipmi_interface_type(u8 code)
+{
+ /* 3.3.39.1 */
+ static const char *type[]={
+ "Unknown", /* 0x00 */
+ "KCS (Keyboard Control Style)",
+ "SMIC (Server Management Interface Chip)",
+ "BT (Block Transfer)" /* 0x03 */
+ };
+
+ if(code<=0x03)
+ return type[code-0x01];
+ return out_of_spec;
}
-/* 1 dec. place */
-const char *dmi_temp(u8 *data, int indx)
+/*
+ * 3.3.40 System Power Supply (Type 39)
+ */
+
+static void dmi_power_supply_power(u16 code)
{
- static char buffer[20];
- short int d;
+ if(code==0x8000)
+ printf(" Unknown");
+ else
+ printf(" %.3f W", (float)code/1000);
+}
- 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;
+static const char *dmi_power_supply_type(u8 code)
+{
+ /* 3.3.40.1 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Linear",
+ "Switching",
+ "Battery",
+ "UPS",
+ "Converter",
+ "Regulator" /* 0x08 */
+ };
+
+ if(code>=0x01 && code<=0x08)
+ return type[code-0x01];
+ return out_of_spec;
}
-/* 0 dec. place */
-const char *dmi_speed(u8 *data, int indx)
+static const char *dmi_power_supply_status(u8 code)
{
- static char buffer[20];
- short int d;
+ /* 3.3.40.1 */
+ static const char *status[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "OK",
+ "Non-critical"
+ "Critical" /* 0x05 */
+ };
+
+ if(code>=0x01 && code<=0x05)
+ return status[code-0x01];
+ return out_of_spec;
+}
- if (data[indx+1] == 0x80 && data[indx] == 0)
- return "Unknown";
- d = data[indx+1] << 8 | data[indx];
- sprintf(buffer, "%d", d);
- return buffer;
+static const char *dmi_power_supply_range_switching(u8 code)
+{
+ /* 3.3.40.1 */
+ static const char *switching[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "Manual",
+ "Auto-switch",
+ "Wide Range",
+ "N/A" /* 0x06 */
+ };
+
+ if(code>=0x01 && code<=0x06)
+ return switching[code-0x01];
+ return out_of_spec;
}
-
-static void dmi_table(int fd, u32 base, int len, int num)
+/*
+ * Main
+ */
+
+static void dmi_decode(u8 *data, u16 ver)
{
- unsigned char *buf=malloc(len);
- struct dmi_header *dm;
- u8 *data, *next;
- int i=0;
- int r=0, r2=0;
-
- if(len==0)
- {
- fputs("dmi: no data\n", stderr);
- return;
- }
+ struct dmi_header *h=(struct dmi_header *)data;
- if(buf==NULL)
- {
- perror("dmi: malloc");
- return;
- }
- if(lseek(fd, (long)base, SEEK_SET)==-1)
- {
- perror("dmi: lseek");
- return;
- }
- while(r2!=len && (r=read(fd, buf+r2, len-r2))!=0 && r!=-1)
- r2+=r;
- if(r==-1)
- {
- perror("dmi: read");
- return;
- }
- if(r==0)
- {
- fputs("dmi: read: Unexpected end of file\n", stderr);
- return;
- }
- data = buf;
- while(i<num && data+sizeof(struct dmi_header)<=(u8*)buf+len)
+ /*
+ * Note: DMI types 31, 37, 38 and 39 are untested
+ */
+ switch(h->type)
{
- 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 */
- next=data+dm->length;
- while(next-buf+1<len && (next[0]!=0 || next[1]!=0))
- next++;
- next+=2;
- if(next-buf>len)
- {
- printf("\tIncomplete structure, abort decoding.\n");
- break;
- }
-
- switch(dm->type)
- {
- case 0:
- printf("\tBIOS Information Block\n");
+ case 0: /* 3.3.1 BIOS Information */
+ printf("\tBIOS Information\n");
+ if(h->length<0x12) break;
printf("\t\tVendor: %s\n",
- dmi_string(dm, data[4]));
+ dmi_string(h, data[0x04]));
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]+1));
- 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]));
+ dmi_string(h, data[0x05]));
+ printf("\t\tRelease Date: %s\n",
+ dmi_string(h, data[0x08]));
+ printf("\t\tAddress: 0x%04X0\n",
+ WORD(data+0x06));
+ printf("\t\tRuntime Size:");
+ dmi_bios_runtime_size((0x10000-WORD(data+0x06))<<4);
+ printf("\n");
+ printf("\t\tROM Size: %u kB\n",
+ (data[0x09]+1)<<6);
+ printf("\t\tCharacteristics:\n");
+ dmi_bios_characteristics(QWORD(data+0x0A), "\t\t\t");
+ if(h->length<0x13) break;
+ dmi_bios_characteristics_x1(data[0x12], "\t\t\t");
+ if(h->length<0x14) break;
+ dmi_bios_characteristics_x2(data[0x13], "\t\t\t");
+ break;
+
+ case 1: /* 3.3.2 System Information */
+ printf("\tSystem Information\n");
+ if(h->length<0x08) break;
+ printf("\t\tManufacturer: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tProduct Name: %s\n",
+ dmi_string(h, data[0x05]));
printf("\t\tVersion: %s\n",
- dmi_string(dm, data[6]));
+ dmi_string(h, data[0x06]));
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]));
+ dmi_string(h, data[0x07]));
+ if(h->length<0x19) break;
+ printf("\t\tUUID:");
+ dmi_system_uuid(data+0x08);
+ printf("\n");
+ printf("\t\tWake-up Type: %s\n",
+ dmi_system_wake_up_type(data[0x18]));
+ break;
+
+ case 2: /* 3.3.3 Base Board Information */
+ printf("\tBase Board Information\n");
+ if(h->length<0x08) break;
+ printf("\t\tManufacturer: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tProduct Name: %s\n",
+ dmi_string(h, data[0x05]));
printf("\t\tVersion: %s\n",
- dmi_string(dm, data[6]));
+ dmi_string(h, data[0x06]));
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");
+ dmi_string(h, data[0x07]));
+ if(h->length<0x0F) break;
+ printf("\t\tAsset Tag: %s\n",
+ dmi_string(h, data[0x08]));
+ printf("\t\tFeatures:");
+ dmi_base_board_features(data[0x09], "\t\t");
+ printf("\t\tLocation In Chassis: %s\n",
+ dmi_string(h, data[0x0A]));
+ printf("\t\tChassis Handle: 0x%04X\n",
+ WORD(data+0x0B));
+ printf("\t\tType: %s\n",
+ dmi_base_board_type(data[0x0D]));
+ if(h->length<0x0F+data[0x0E]*sizeof(u16)) break;
+ dmi_base_board_handlers(data[0x0E], data+0x0F, "\t\t");
+ break;
+
+ case 3: /* 3.3.4 Chassis Information */
+ printf("\tChassis Information\n");
+ if(h->length<0x09) break;
+ printf("\t\tManufacturer: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tType: %s\n",
+ dmi_chassis_type(data[0x05]&0x7F));
+ printf("\t\tLock: %s\n",
+ dmi_chassis_lock(data[0x05]>>7));
printf("\t\tVersion: %s\n",
- dmi_string(dm, data[6]));
+ dmi_string(h, data[0x06]));
printf("\t\tSerial Number: %s\n",
- dmi_string(dm, data[7]));
+ dmi_string(h, data[0x07]));
printf("\t\tAsset Tag: %s\n",
- dmi_string(dm, data[8]));
- break;
-
- case 4:
- printf("\tProcessor\n");
+ dmi_string(h, data[0x08]));
+ if(h->length<0x0D) break;
+ printf("\t\tBoot-up State: %s\n",
+ dmi_chassis_state(data[0x09]));
+ printf("\t\tPower Supply State: %s\n",
+ dmi_chassis_state(data[0x0A]));
+ printf("\t\tThermal State: %s\n",
+ dmi_chassis_state(data[0x0B]));
+ printf("\t\tSecurity Status: %s\n",
+ dmi_chassis_security_status(data[0x0C]));
+ if(h->length<0x11) break;
+ printf("\t\tOEM Information: 0x%08X\n",
+ DWORD(data+0x0D));
+ if(h->length<0x15) break;
+ printf("Heigth:");
+ dmi_chassis_height(data[0x11]);
+ printf("\n");
+ printf("Number Of Power Cords:");
+ dmi_chassis_power_cords(data[0x12]);
+ printf("\n");
+ if(h->length<0x15+data[0x13]*data[0x14]) break;
+ dmi_chassis_elements(data[0x13], data[0x14], data+0x15, "\t\t");
+ break;
+
+ case 4: /* 3.3.5 Processor Information */
+ printf("\tProcessor Information\n");
+ if(h->length<0x1A) break;
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;
+ dmi_string(h, data[0x04]));
+ printf("\t\tType: %s\n",
+ dmi_processor_type(data[0x05]));
+ printf("\t\tFamily: %s\n",
+ dmi_processor_family(data[0x06]));
+ printf("\t\tManufacturer: %s\n",
+ dmi_string(h, data[0x07]));
+ dmi_processor_id(data[0x06], data+8, dmi_string(h, data[0x10]), "\t\t");
+ printf("\t\tVersion: %s\n",
+ dmi_string(h, data[0x10]));
+ printf("\t\tVoltage:");
+ dmi_processor_voltage(data[0x11]);
+ printf("\n");
+ printf("\t\tExternal Clock:");
+ dmi_processor_frequency(WORD(data+0x12));
+ printf("\n");
+ printf("\t\tMax Speed:");
+ dmi_processor_frequency(WORD(data+0x14));
+ printf("\n");
+ printf("\t\tCurrent Speed:");
+ dmi_processor_frequency(WORD(data+0x16));
+ printf("\n");
+ if(data[0x18]&(1<<6))
+ printf("\t\tStatus: Populated, %s\n",
+ dmi_processor_status(data[0x18]&0x07));
+ else
+ printf("\t\tStatus: Unpopulated\n");
+ printf("\t\tUpgrade: %s\n",
+ dmi_processor_upgrade(data[0x19]));
+ if(h->length<0x20) break;
+ printf("\t\tL1 Cache Handle:");
+ dmi_processor_cache(WORD(data+0x1A), "L1", ver);
+ printf("\n");
+ printf("\t\tL2 Cache Handle:");
+ dmi_processor_cache(WORD(data+0x1C), "L2", ver);
+ printf("\n");
+ printf("\t\tL3 Cache Handle:");
+ dmi_processor_cache(WORD(data+0x1E), "L3", ver);
+ printf("\n");
+ if(h->length<0x23) break;
printf("\t\tSerial Number: %s\n",
- dmi_string(dm, data[0x20]));
+ dmi_string(h, 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]));
+ dmi_string(h, data[0x21]));
+ printf("\t\tPart Number: %s\n",
+ dmi_string(h, data[0x22]));
break;
-
- case 5:
- printf("\tMemory Controller\n");
+
+ case 5: /* 3.3.6 Memory Controller Information */
+ printf("\tMemory Controller Information\n");
+ if(h->length<0x0F) break;
+ printf("\t\tError Detecting Method: %s\n",
+ dmi_memory_controller_ed_method(data[0x04]));
+ printf("\t\tError Correcting Capabilities:");
+ dmi_memory_controller_ec_capabilities(data[0x05], "\t\t\t");
+ printf("\t\tSupported Interleave: %s\n",
+ dmi_memory_controller_interleave(data[0x06]));
+ printf("\t\tCurrent Interleave: %s\n",
+ dmi_memory_controller_interleave(data[0x07]));
+ printf("\t\tMaximum Memory Module Size: %u MB\n",
+ 1<<data[0x08]);
+ printf("\t\tMaximum Total Memory Size: %u MB\n",
+ data[0x0E]*(1<<data[0x08]));
+ printf("\t\tSupported Speeds:");
+ dmi_memory_controller_speeds(WORD(data+0x09), "\t\t\t");
+ printf("\t\tSupported Memory Types:");
+ dmi_memory_module_types(WORD(data+0x0B), "\n\t\t\t");
+ printf("\n");
+ printf("\t\tMemory Module Voltage:");
+ dmi_processor_voltage(data[0x0D]);
+ printf("\n");
+ if(h->length<0x0F+data[0x0E]*sizeof(u16)) break;
+ dmi_memory_controller_slots(data[0x0E], data+0x0F, "\t\t");
+ if(h->length<0x10+data[0x0E]*sizeof(u16)) break;
+ printf("\t\tEnabled Error Correcting Capabilities:");
+ dmi_memory_controller_ec_capabilities(data[0x0F+data[0x0E]*sizeof(u16)], "\t\t\t");
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[9]|data[10]<<8);
- printf("\t\tL%d Cache Maximum: ", 1+(u&7));
- dmi_cache_size(data[7]|data[8]<<8);
- printf("\t\tL%d Cache Type: ", 1+(u&7));
- dmi_decode_cache(data[13]);
- printf("\n");
- }
+
+ case 6: /* 3.3.7 Memory Module Information */
+ printf("\tMemory Module Information\n");
+ if(h->length<0x0C) break;
+ printf("\t\tSocket Designation: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tBank Connections:");
+ dmi_memory_module_connections(data[0x05]);
+ printf("\n");
+ printf("\t\tCurrent Speed:");
+ dmi_memory_module_speed(data[0x06]);
+ printf("\n");
+ printf("\t\tType:");
+ dmi_memory_module_types(WORD(data+0x07), " ");
+ printf("\n");
+ printf("\t\tInstalled Size:");
+ dmi_memory_module_size(data[0x09]);
+ printf("\n");
+ printf("\t\tEnabled Size:");
+ dmi_memory_module_size(data[0x0A]);
+ printf("\n");
+ printf("\t\tError Status:");
+ dmi_memory_module_error(data[0x0B], "\t\t\t");
break;
-
- case 8:
- printf("\tPort Connector\n");
- printf("\t\tInternal Designator: %s\n",
- dmi_string(dm, data[4]));
+
+ case 7: /* 3.3.8 Cache Information */
+ printf("\tCache Information\n");
+ if(h->length<0x0F) break;
+ printf("\t\tSocket Designation: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tConfiguration: %s, %s, Level %u\n",
+ WORD(data+0x05)&0x0080?"Enabled":"Disabled",
+ WORD(data+0x05)&0x0008?"Socketed":"Not Socketed",
+ (WORD(data+0x05)&0x0007)+1);
+ printf("\t\tOperational Mode: %s\n",
+ dmi_cache_mode((WORD(data+0x05)>>8)&0x0003));
+ printf("\t\tLocation: %s\n",
+ dmi_cache_location((WORD(data+0x05)>>5)&0x0003));
+ printf("\t\tInstalled Size:");
+ dmi_cache_size(WORD(data+0x09));
+ printf("\n");
+ printf("\t\tMaximum Size:");
+ dmi_cache_size(WORD(data+0x07));
+ printf("\n");
+ printf("\t\tSupported SRAM Types:");
+ dmi_cache_types(WORD(data+0x0B), "\n\t\t\t");
+ printf("\n");
+ printf("\t\tInstalled SRAM Type:");
+ dmi_cache_types(WORD(data+0x0D), " ");
+ printf("\n");
+ if(h->length<0x13) break;
+ printf("\t\tSpeed:");
+ dmi_memory_module_speed(data[0x0F]);
+ printf("\n");
+ printf("\t\tError Correction Type: %s\n",
+ dmi_cache_ec_type(data[0x10]));
+ printf("\t\tSystem Type: %s\n",
+ dmi_cache_type(data[0x11]));
+ printf("\t\tAssociativity: %s\n",
+ dmi_cache_associativity(data[0x12]));
+ break;
+
+ case 8: /* 3.3.9 Port Connector Information */
+ printf("\tPort Connector Information\n");
+ if(h->length<0x09) break;
+ printf("\t\tInternal Reference Designator: %s\n",
+ dmi_string(h, data[0x04]));
printf("\t\tInternal Connector Type: %s\n",
- dmi_port_connector_type(data[5]));
- printf("\t\tExternal Designator: %s\n",
- dmi_string(dm, data[6]));
+ dmi_port_connector_type(data[0x05]));
+ printf("\t\tExternal Reference Designator: %s\n",
+ dmi_string(h, data[0x06]));
printf("\t\tExternal Connector Type: %s\n",
- dmi_port_connector_type(data[7]));
+ dmi_port_connector_type(data[0x07]));
printf("\t\tPort Type: %s\n",
- dmi_port_type(data[8]));
+ dmi_port_type(data[0x08]));
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]);
+
+ case 9: /* 3.3.10 System Slots */
+ printf("\tSystem Slot Information\n");
+ if(h->length<0x0C) break;
+ printf("\t\tDesignation: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tType: %s%s\n",
+ dmi_slot_bus_width(data[0x06]),
+ dmi_slot_type(data[0x05]));
+ printf("\t\tCurrent Usage: %s\n",
+ dmi_slot_current_usage(data[0x07]));
+ printf("\t\tLength: %s\n",
+ dmi_slot_length(data[0x08]));
+ dmi_slot_id(data[0x09], data[0x0A], data[0x05], "\t\t");
+ printf("\t\tCharacteristics:");
+ if(h->length<0x0D)
+ dmi_slot_characteristics(data[0x0B], 0x00, "\t\t\t");
+ else
+ dmi_slot_characteristics(data[0x0B], data[0x0C], "\t\t\t");
break;
-
- case 10:
- printf("\tOn Board Devices Information\n");
- for (u=2; u*2+1<dm->length; 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]));
-
- }
-
+
+ case 10: /* 3.3.11 On Board Devices Information */
+ dmi_on_board_devices(h, "\t");
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:
+
+ case 11: /* 3.3.12 OEM Strings */
+ printf("\tOEM Strings\n");
+ if(h->length<0x05) break;
+ dmi_oem_strings(h, "\t\t");
+ break;
+
+ case 12: /* 3.3.13 System Configuration Options */
+ printf("\tSystem Configuration Options\n");
+ if(h->length<0x05) break;
+ dmi_system_configuration_options(h, "\t\t");
+ break;
+
+ case 13: /* 3.3.14 BIOS Language Information */
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]));
+ if(h->length<0x16) break;
+ printf("\t\tInstallable Languages: %u\n", data[0x04]);
+ dmi_bios_languages(h, "\t\t\t");
+ printf("\t\tCurrently Installed Language: %s\n", dmi_string(h, data[0x15]));
break;
-
- case 14:
+
+ case 14: /* 3.3.15 Group Associations */
printf("\tGroup Associations\n");
- for (u=0; 3*u+7<dm->length; 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)));
- }
+ if(h->length<0x05) break;
+ printf("\t\tName: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tItems: %u\n",
+ (h->length-0x05)/3);
+ dmi_group_associations_items((h->length-0x05)/3, data+0x05, "\t\t\t");
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:
+
+ case 15: /* 3.3.16 System Event Log */
+ printf("\tSystem Event Log\n");
+ if(h->length<0x14) break;
+ printf("\t\tArea Length: %u bytes\n",
+ WORD(data+0x04));
+ printf("\t\tHeader Start Offset: 0x%04X\n",
+ WORD(data+0x06));
+ if(WORD(data+0x08)-WORD(data+0x06))
+ printf("\t\tHeader Length: %u byte%s\n",
+ WORD(data+0x08)-WORD(data+0x06),
+ WORD(data+0x08)-WORD(data+0x06)>1?"s":"");
+ printf("\t\tData Start Offset: 0x%04X\n",
+ WORD(data+0x08));
+ printf("\t\tAccess Method: %s\n",
+ dmi_event_log_method(data[0x0A]));
+ printf("\t\tAccess Address:");
+ dmi_event_log_address(data[0x0A], data+0x10);
+ printf("\n");
+ printf("\t\tStatus:");
+ dmi_event_log_status(data[0x0B]);
+ printf("\n");
+ printf("\t\tChange Token: 0x%08X\n",
+ DWORD(data+0x0C));
+ if(h->length<0x17) break;
+ printf("\t\tHeader Format: %s\n",
+ dmi_event_log_header_type(data[0x14]));
+ printf("\t\tSupported Log Type Descriptors: %u\n",
+ data[0x15]);
+ if(h->length<0x17+data[0x15]*data[0x16]) break;
+ dmi_event_log_descriptors(data[0x15], data[0x16], data+0x17, "\t\t");
+ break;
+
+ case 16: /* 3.3.17 Physical Memory Array */
printf("\tPhysical Memory Array\n");
+ if(h->length<0x0F) break;
printf("\t\tLocation: %s\n",
- dmi_memory_array_location(data[4]));
+ dmi_memory_array_location(data[0x04]));
printf("\t\tUse: %s\n",
- dmi_memory_array_use(data[5]));
+ dmi_memory_array_use(data[0x05]));
printf("\t\tError Correction Type: %s\n",
- dmi_memory_array_error_correction_type(data[6]));
- u2 = data[10]<<24|data[9]<<16|data[8]<<8|data[7];
- printf("\t\tMaximum Capacity: ");
- if (u2 == 0x80000000)
- printf("Unknown\n");
- else
- printf("%u kB\n", u2);
- printf("\t\tError Information Handle: ");
- u = data[12]<<8|data[11];
- if (u == 0xffff) {
- printf("None\n");
- } else if (u == 0xfffe) {
- printf("Not Provided\n");
- } else {
- printf("0x%04X\n", u);
- }
- printf("\t\tNumber of Devices: %u\n", data[14]<<8|data[13]);
+ dmi_memory_array_ec_type(data[0x06]));
+ printf("\t\tMaximum Capacity:");
+ dmi_memory_array_capacity(DWORD(data+0x07));
+ printf("\n");
+ printf("\t\tError Information Handle:");
+ dmi_memory_array_error_handle(WORD(data+0x0B));
+ printf("\n");
+ printf("\t\tNumber Of Devices: %u\n",
+ WORD(data+0x0D));
break;
- case 17:
+
+ case 17: /* 3.3.18 Memory Device */
printf("\tMemory Device\n");
- printf("\t\tArray Handle: 0x%04X\n", data[5]<<8|data[4]);
- printf("\t\tError Information Handle: ");
- u = data[7]<<8|data[6];
- if (u == 0xffff) {
- printf("None\n");
- } else if (u == 0xfffe) {
- printf("Not Provided\n");
- } else {
- printf("0x%04X\n", u);
- }
- u = data[9]<<8|data[8];
- printf("\t\tTotal Width: ");
- if (u == 0xffff)
- printf("Unknown\n");
- else
- printf("%u bits\n", u);
- u = data[11]<<8|data[10];
- printf("\t\tData Width: ");
- if (u == 0xffff)
- printf("Unknown\n");
- else
- printf("%u bits\n", u);
- u = data[13]<<8|data[12];
- printf("\t\tSize: ");
- if (u == 0xffff)
- printf("Unknown\n");
- else
- printf("%u %sbyte\n", (u&0x7fff), (u&0x8000) ? "K" : "M");
+ if(h->length<0x15) break;
+ printf("\t\tArray Handle: 0x%04X\n",
+ WORD(data+0x04));
+ printf("\t\tError Information Handle:");
+ dmi_memory_array_error_handle(WORD(data+0x06));
+ printf("\n");
+ printf("\t\tTotal Width:");
+ dmi_memory_device_width(WORD(data+0x08));
+ printf("\n");
+ printf("\t\tData Width:");
+ dmi_memory_device_width(WORD(data+0x0A));
+ printf("\n");
+ printf("\t\tSize:");
+ dmi_memory_device_size(WORD(data+0x0C));
+ printf("\n");
printf("\t\tForm Factor: %s\n",
- dmi_memory_device_form_factor(data[14]));
- if (data[15] != 0) {
- printf("\t\tSet: ");
- if (data[15] == 0xff)
- printf("Unknown\n");
- else
- printf("0x%02X\n", data[15]);
- }
+ dmi_memory_device_form_factor(data[0x0E]));
+ printf("\t\tSet:");
+ dmi_memory_device_set(data[0x0F]);
+ printf("\n");
printf("\t\tLocator: %s\n",
- dmi_string(dm, data[16]));
+ dmi_string(h, data[0x10]));
printf("\t\tBank Locator: %s\n",
- dmi_string(dm, data[17]));
+ dmi_string(h, data[0x11]));
printf("\t\tType: %s\n",
- dmi_memory_device_type(data[18]));
- u = data[20]<<8|data[19];
- if (u&0x1ffe)
- dmi_memory_device_detail(u);
- if (dm->length > 21) {
- u = data[22]<<8|data[21];
- printf("\t\tSpeed: ");
- if (u == 0)
- printf("Unknown\n");
- else
- printf("%u MHz (%.1f ns)\n", u, (1000.0/u));
- }
- if (dm->length > 23)
- printf("\t\tManufacturer: %s\n",
- dmi_string(dm, data[23]));
- if (dm->length > 24)
- printf("\t\tSerial Number: %s\n",
- dmi_string(dm, data[24]));
- if (dm->length > 25)
- printf("\t\tAsset Tag: %s\n",
- dmi_string(dm, data[25]));
- if (dm->length > 26)
- printf("\t\tPart Number: %s\n",
- dmi_string(dm, data[26]));
+ dmi_memory_device_type(data[0x12]));
+ printf("\t\tType Detail:");
+ dmi_memory_device_type_detail(WORD(data+0x13));
+ printf("\n");
+ if(h->length<0x17) break;
+ printf("\t\tSpeed:");
+ dmi_memory_device_speed(WORD(data+0x15));
+ printf("\n");
+ if(h->length<0x1B) break;
+ printf("\t\tManufacturer: %s\n",
+ dmi_string(h, data[0x17]));
+ printf("\t\tSerial Number: %s\n",
+ dmi_string(h, data[0x18]));
+ printf("\t\tAsset Tag: %s\n",
+ dmi_string(h, data[0x19]));
+ printf("\t\tPart Number: %s\n",
+ dmi_string(h, data[0x1A]));
break;
- case 18:
+
+ case 18: /* 3.3.19 32-bit Memory Error Information */
printf("\t32-bit Memory Error Information\n");
+ if(h->length<0x17) break;
+ printf("\t\tType: %s\n",
+ dmi_memory_error_type(data[0x04]));
+ printf("\t\tGranularity: %s\n",
+ dmi_memory_error_granularity(data[0x05]));
+ printf("\t\tOperation: %s\n",
+ dmi_memory_error_operation(data[0x06]));
+ printf("\t\tVendor Syndrome:");
+ dmi_memory_error_syndrome(DWORD(data+0x07));
+ printf("\n");
+ printf("\t\tMemory Array Address:");
+ dmi_32bit_memory_error_address(DWORD(data+0x0B));
+ printf("\n");
+ printf("\t\tDevice Address:");
+ dmi_32bit_memory_error_address(DWORD(data+0x0F));
+ printf("\n");
+ printf("\t\tResolution:");
+ dmi_32bit_memory_error_address(DWORD(data+0x13));
+ printf("\n");
break;
- case 19:
+
+ case 19: /* 3.3.20 Memory Array Mapped Address */
printf("\tMemory Array Mapped Address\n");
+ if(h->length<0x0F) break;
+ printf("\t\tStarting Address: 0x%08X%03X\n",
+ DWORD(data+0x04)>>2, (DWORD(data+0x04)&0x3)<<10);
+ printf("\t\tEnding Address: 0x%08X%03X\n",
+ DWORD(data+0x08)>>2, ((DWORD(data+0x08)&0x3)<<10)+0x3FF);
+ printf("\t\tRange Size:");
+ dmi_mapped_address_size(DWORD(data+0x08)-DWORD(data+0x04)+1);
+ printf("\n");
+ printf("\t\tPhysical Array Handle: 0x%04X\n",
+ WORD(data+0x0C));
+ printf("\t\tPartition Width: %u\n",
+ data[0x0F]);
break;
- case 20:
+
+ case 20: /* 3.3.21 Memory Device Mapped Address */
printf("\tMemory Device Mapped Address\n");
+ if(h->length<0x13) break;
+ printf("\t\tStarting Address: 0x%08X%03X\n",
+ DWORD(data+0x04)>>2, (DWORD(data+0x04)&0x3)<<10);
+ printf("\t\tEnding Address: 0x%08X%03X\n",
+ DWORD(data+0x08)>>2, ((DWORD(data+0x08)&0x3)<<10)+0x3FF);
+ printf("\t\tRange Size:");
+ dmi_mapped_address_size(DWORD(data+0x08)-DWORD(data+0x04)+1);
+ printf("\n");
+ printf("\t\tPhysical Device Handle: 0x%04X\n",
+ WORD(data+0x0C));
+ printf("\t\tMemory Array Mapped Address Handle: 0x%04X\n",
+ WORD(data+0x0E));
+ printf("\t\tPartition Row Position:");
+ dmi_mapped_address_row_position(data[0x10]);
+ printf("\n");
+ dmi_mapped_address_interleave_position(data[0x11], "\t\t");
+ dmi_mapped_address_interleaved_data_depth(data[0x12], "\t\t");
break;
- case 21:
- printf("\tBuilt-In Pointing Device\n");
+
+ case 21: /* 3.3.22 Built-in Pointing Device */
+ printf("\tBuilt-in Pointing Device\n");
+ if(h->length<0x07) break;
+ printf("\t\tType: %s\n",
+ dmi_pointing_device_type(data[0x04]));
+ printf("\t\tInterface: %s\n",
+ dmi_pointing_device_interface(data[0x05]));
+ printf("\t\tButtons: %u\n",
+ data[0x06]);
break;
- case 22:
+
+ case 22: /* 3.3.23 Portable Battery */
printf("\tPortable Battery\n");
+ if(h->length<0x10) break;
printf("\t\tLocation: %s\n",
- dmi_string(dm, data[4]));
+ dmi_string(h, data[0x04]));
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]));
+ dmi_string(h, data[0x05]));
+ if(data[0x06] || h->length<0x1A)
+ printf("\t\tManufacture Date: %s\n",
+ dmi_string(h, data[0x06]));
+ if(data[0x07] || h->length<0x1A)
+ printf("\t\tSerial Number: %s\n",
+ dmi_string(h, data[0x07]));
printf("\t\tName: %s\n",
- dmi_string(dm, data[8]));
- break;
-
- case 23:
+ dmi_string(h, data[0x08]));
+ if(data[0x09]!=0x02 || h->length<0x1A)
+ printf("\t\tChemistry: %s\n",
+ dmi_battery_chemistry(data[0x09]));
+ printf("\t\tDesign Capacity:");
+ if(h->length<0x1A)
+ dmi_battery_capacity(WORD(data+0x0A), 1);
+ else
+ dmi_battery_capacity(WORD(data+0x0A), data[0x15]);
+ printf("\n");
+ printf("\t\tDesign Voltage:");
+ dmi_battery_voltage(WORD(data+0x0C));
+ printf("\n");
+ printf("\t\tSBDS Version: %s\n",
+ dmi_string(h, data[0x0E]));
+ printf("\t\tMaximum Error:");
+ dmi_battery_maximum_error(data[0x0E]);
+ printf("\n");
+ if(h->length<0x1A) break;
+ if(data[0x07]==0)
+ printf("\t\tSBDS Serial Number: %04X\n",
+ WORD(data+0x10));
+ if(data[0x06]==0)
+ printf("\t\tSBDS Manufacture Date: %u-%02u-%02u\n",
+ 1980+(WORD(data+0x12)>>9), (WORD(data+0x12)>>5)&0x0F,
+ WORD(data+0x12)&0x1F);
+ if(data[0x09]==0x02)
+ printf("\t\tSBDS Chemistry: %s\n",
+ dmi_string(h, data[0x14]));
+ printf("\t\tOEM-specific Information: 0x%08X\n",
+ DWORD(data+0x16));
+ break;
+
+ case 23: /* 3.3.24 System Reset */
printf("\tSystem Reset\n");
+ if(h->length<0x0D) break;
+ printf("\t\tStatus: %s\n",
+ data[4]&(1<<0)?"Enabled":"Disabled");
+ printf("\t\tWatchdog Timer: %s\n",
+ data[4]&(1<<5)?"Present":"No");
+ printf("\t\tBoot Option: %s\n",
+ dmi_system_reset_boot_option((data[0x04]>>1)&0x3));
+ printf("\t\tBoot Option On Limit: %s\n",
+ dmi_system_reset_boot_option((data[0x04]>>3)&0x3));
+ printf("\t\tReset Count:");
+ dmi_system_reset_count(WORD(data+0x05));
+ printf("\n");
+ printf("\t\tReset Limit:");
+ dmi_system_reset_count(WORD(data+0x07));
+ printf("\n");
+ printf("\t\tTimer Interval:");
+ dmi_system_reset_timer(WORD(data+0x09));
+ printf("\n");
+ printf("\t\tTimeout:");
+ dmi_system_reset_timer(WORD(data+0x0B));
+ printf("\n");
break;
- case 24:
+
+ case 24: /* 3.3.25 Hardware Security */
printf("\tHardware Security\n");
+ if(h->length<0x05) break;
+ printf("\t\tPower-On Password Status: %s\n",
+ dmi_hardware_security_status(data[0x04]>>6));
+ printf("\t\tKeyboard Password Status: %s\n",
+ dmi_hardware_security_status((data[0x04]>>4)&0x3));
+ printf("\t\tAdministrator Password Status: %s\n",
+ dmi_hardware_security_status((data[0x04]>>2)&0x3));
+ printf("\t\tFront Panel Reset Status: %s\n",
+ dmi_hardware_security_status(data[0x04]&0x3));
break;
- case 25:
+
+ case 25: /* 3.3.26 System Power Controls */
printf("\tSystem Power Controls\n");
+ if(h->length<0x09) break;
+ printf("\t\tNext Scheduled Power-on:");
+ dmi_power_controls_power_on(data+0x04);
+ printf("\n");
break;
- case 26:
- printf("\tVoltage Sensor\n");
+
+ case 26: /* 3.3.27 Voltage Probe */
+ printf("\tVoltage Probe\n");
+ if(h->length<0x14) break;
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));
+ dmi_string(h, data[0x04]));
+ printf("\t\tLocation: %s\n",
+ dmi_voltage_probe_location(data[0x05]&0x1f));
+ printf("\t\tStatus: %s\n",
+ dmi_probe_status(data[0x05]>>5));
+ printf("\t\tMaximum Value:");
+ dmi_voltage_probe_value(WORD(data+0x06));
+ printf("\n");
+ printf("\t\tMinimum Value:");
+ dmi_voltage_probe_value(WORD(data+0x08));
+ printf("\n");
+ printf("\t\tResolution:");
+ dmi_voltage_probe_resolution(WORD(data+0x0A));
+ printf("\n");
+ printf("\t\tTolerance:");
+ dmi_voltage_probe_value(WORD(data+0x0C));
+ printf("\n");
+ printf("\t\tAccuracy:");
+ dmi_probe_accuracy(WORD(data+0x0E));
+ printf("\n");
+ printf("\t\tOEM-specific Information: 0x%08X\n",
+ DWORD(data+0x10));
+ if(h->length<0x16) break;
+ printf("\t\tNominal Value:");
+ dmi_voltage_probe_value(WORD(data+0x14));
+ printf("\n");
break;
- case 27:
+
+ case 27: /* 3.3.28 Cooling Device */
printf("\tCooling Device\n");
- printf("\t\tDevice Type: %s\n",
- dmi_fan_type(data[6] & 0x1f));
- printf("\t\tDevice Status: %s\n",
- dmi_status(data[6] >> 5));
- if(dm->length > 0x0c)
- printf("\t\tNominal Speed: %s\n",
- dmi_speed(data, 0x0c));
+ if(h->length<0x0C) break;
+ if(WORD(data+0x04)!=0xFFFF)
+ printf("\t\tTemperature Probe Handle: 0x%04X\n",
+ WORD(data+0x04));
+ printf("\t\tType: %s\n",
+ dmi_cooling_device_type(data[0x06]&0x1f));
+ printf("\t\tStatus: %s\n",
+ dmi_probe_status(data[0x06]>>5));
+ if(data[0x07]!=0x00)
+ printf("\t\tCooling Unit Group: %u\n",
+ data[0x07]);
+ printf("\t\tOEM-specific Information: 0x%08X\n",
+ DWORD(data+0x08));
+ if(h->length<0x0E) break;
+ printf("\t\tNominal Speed:");
+ dmi_cooling_device_speed(WORD(data+0x0C));
+ printf("\n");
break;
- case 28:
- printf("\tTemperature Sensor\n");
+
+ case 28: /* 3.3.29 Temperature Probe */
+ printf("\tTemperature Probe\n");
+ if(h->length<0x14) break;
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));
+ dmi_string(h, data[0x04]));
+ printf("\t\tLocation: %s\n",
+ dmi_temperature_probe_location(data[0x05]&0x1F));
+ printf("\t\tStatus: %s\n",
+ dmi_probe_status(data[0x05]>>5));
+ printf("\t\tMaximum Value:");
+ dmi_temperature_probe_value(WORD(data+0x06));
+ printf("\n");
+ printf("\t\tMinimum Value");
+ dmi_temperature_probe_value(WORD(data+0x08));
+ printf("\n");
+ printf("\t\tResolution:");
+ dmi_temperature_probe_resolution(WORD(data+0x0A));
+ printf("\n");
+ printf("\t\tTolerance:");
+ dmi_temperature_probe_value(WORD(data+0x0C));
+ printf("\n");
+ printf("\t\tAccuracy:");
+ dmi_probe_accuracy(WORD(data+0x0E));
+ printf("\n");
+ printf("\t\tOEM-specific Information: 0x%08X\n",
+ DWORD(data+0x10));
+ if(h->length<0x16) break;
+ printf("\t\tNominal Value:");
+ dmi_temperature_probe_value(WORD(data+0x14));
+ printf("\n");
break;
- case 29:
- printf("\tCurrent Sensor\n");
+
+ case 29: /* 3.3.30 Electrical Current Probe */
+ printf("\tElectrical Current Probe\n");
+ if(h->length<0x14) break;
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));
+ dmi_string(h, data[0x04]));
+ printf("\t\tLocation: %s\n",
+ dmi_voltage_probe_location(data[5]&0x1F));
+ printf("\t\tStatus: %s\n",
+ dmi_probe_status(data[0x05]>>5));
+ printf("\t\tMaximum Value:");
+ dmi_current_probe_value(WORD(data+0x06));
+ printf("\n");
+ printf("\t\tMinimum Value:");
+ dmi_current_probe_value(WORD(data+0x08));
+ printf("\n");
+ printf("\t\tResolution:");
+ dmi_current_probe_resolution(WORD(data+0x0A));
+ printf("\n");
+ printf("\t\tTolerance:");
+ dmi_current_probe_value(WORD(data+0x0C));
+ printf("\n");
+ printf("\t\tAccuracy:");
+ dmi_probe_accuracy(WORD(data+0x0E));
+ printf("\n");
+ printf("\t\tOEM-specific Information: 0x%08X\n",
+ DWORD(data+0x10));
+ if(h->length<0x16) break;
+ printf("\t\tNominal Value:");
+ dmi_current_probe_value(WORD(data+0x14));
+ printf("\n");
break;
- case 30:
- printf("\tOut-of-Band Remote Access\n");
+
+ case 30: /* 3.3.31 Out-of-band Remote Access */
+ printf("\tOut-of-band Remote Access\n");
+ if(h->length<0x06) break;
+ printf("\t\tManufacturer Name: %s\n",
+ dmi_string(h, data[0x04]));
+ printf("\t\tInbound Connection: %s\n",
+ data[0x05]&(1<<0)?"Enabled":"Disabled");
+ printf("\t\tOutbound Connection: %s\n",
+ data[0x05]&(1<<1)?"Enabled":"Disabled");
break;
- case 31:
+
+ case 31: /* 3.3.32 Boot Integrity Services Entry Point */
printf("\tBoot Integrity Services Entry Point\n");
break;
- case 32:
+
+ case 32: /* 3.3.33 System Boot Information */
printf("\tSystem Boot Information\n");
+ if(h->length<0x0B) break;
+ printf("\t\tStatus: %s\n",
+ dmi_system_boot_status(data[0x0A]));
break;
- case 33:
+
+ case 33: /* 3.3.34 64-bit Memory Error Information */
+ if(h->length<0x1F) break;
printf("\t64-bit Memory Error Information\n");
+ printf("\t\tType: %s\n",
+ dmi_memory_error_type(data[0x04]));
+ printf("\t\tGranularity: %s\n",
+ dmi_memory_error_granularity(data[0x05]));
+ printf("\t\tOperation: %s\n",
+ dmi_memory_error_operation(data[0x06]));
+ printf("\t\tVendor Syndrome:");
+ dmi_memory_error_syndrome(DWORD(data+0x07));
+ printf("\n");
+ printf("\t\tMemory Array Address:");
+ dmi_64bit_memory_error_address(QWORD(data+0x0B));
+ printf("\n");
+ printf("\t\tDevice Address:");
+ dmi_64bit_memory_error_address(QWORD(data+0x13));
+ printf("\n");
+ printf("\t\tResolution:");
+ dmi_32bit_memory_error_address(DWORD(data+0x1B));
+ printf("\n");
break;
- case 34:
+
+ case 34: /* 3.3.35 Management Device */
printf("\tManagement Device\n");
+ if(h->length<0x0B) break;
printf("\t\tDescription: %s\n",
- dmi_string(dm, data[4]));
- printf("\t\tDevice Type: %s\n",
- dmi_mgmt_dev_type(data[5]));
+ dmi_string(h, data[0x04]));
+ printf("\t\tType: %s\n",
+ dmi_management_device_type(data[0x05]));
+ printf("\t\tAddress: 0x%08X\n",
+ DWORD(data+0x06));
printf("\t\tAddress Type: %s\n",
- dmi_mgmt_addr_type(data[6]));
+ dmi_management_device_address_type(data[0x0A]));
break;
- case 35:
+
+ case 35: /* 3.3.36 Management Device Component */
printf("\tManagement Device Component\n");
+ if(h->length<0x0B) break;
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]);
+ dmi_string(h, data[0x04]));
+ printf("\t\tManagement Device Handle: 0x%04X\n",
+ WORD(data+0x05));
+ printf("\t\tComponent Handle: 0x%04X\n",
+ WORD(data+0x07));
+ if(WORD(data+0x09)!=0xFFFF)
+ printf("\t\tThreshold Handle: 0x%04X\n",
+ WORD(data+0x09));
break;
- case 36:
+
+ case 36: /* 3.3.37 Management Device Threshold Data */
printf("\tManagement Device Threshold Data\n");
- if (dm->length > 4)
- dump_raw_data(data+4, dm->length-4);
+ if(h->length<0x10) break;
+ if(WORD(data+0x04)!=0x8000)
+ printf("\t\tLower Non-critical Threshold: %d\n",
+ (i16)WORD(data+0x04));
+ if(WORD(data+0x06)!=0x8000)
+ printf("\t\tUpper Non-critical Threshold: %d\n",
+ (i16)WORD(data+0x06));
+ if(WORD(data+0x08)!=0x8000)
+ printf("\t\tLower Critical Threshold: %d\n",
+ (i16)WORD(data+0x08));
+ if(WORD(data+0x0A)!=0x8000)
+ printf("\t\tUpper Critical Threshold: %d\n",
+ (i16)WORD(data+0x0A));
+ if(WORD(data+0x0C)!=0x8000)
+ printf("\t\tLower Non-recoverable Threshold: %d\n",
+ (i16)WORD(data+0x0C));
+ if(WORD(data+0x0E)!=0x8000)
+ printf("\t\tUpper Non-recoverable Threshold: %d\n",
+ (i16)WORD(data+0x0E));
break;
- case 37:
+
+ case 37: /* 3.3.38 Memory Channel */
printf("\tMemory Channel\n");
+ if(h->length<0x07) break;
+ printf("\t\tType: %s\n",
+ dmi_memory_channel_type(data[0x04]));
+ printf("\t\tMaximal Load: %u\n",
+ data[0x05]);
+ printf("\t\tDevices: %u\n",
+ data[0x06]);
+ if(h->length<0x07+3*data[0x06]) break;
+ dmi_memory_channel_devices(data[0x06], data+0x07, "\t\t\t");
break;
- case 38:
- printf("\tIPMI Device\n");
- if (dm->length > 4)
- dump_raw_data(data+4, dm->length-4);
+
+ case 38: /* 3.3.39 IPMI Device Information */
+ printf("\tIPMI Device Information\n");
+ if(h->length<0x10) break;
+ printf("\t\tInterface Type: %s\n",
+ dmi_ipmi_interface_type(data[0x04]));
+ printf("\t\tSpecification Revision: %u.%u\n",
+ data[0x05]>>4, data[0x05]&0x0F);
+ printf("\t\tI2C Slave Address: %u\n",
+ data[0x06]);
+ if(data[0x07]==0xFF)
+ printf("\t\tNV Storage Device Address: %u\n",
+ data[0x07]);
+ printf("\t\tBase Address: 0x%08X (%s)\n",
+ DWORD(data+0x08), DWORD(data+0x08)&1?"I/O":"memory-mapped");
break;
- case 39:
- printf("\tPower Supply\n");
- if (dm->length > 4)
- dump_raw_data(data+4, dm->length-4);
+
+ case 39: /* 3.3.40 System Power Supply */
+ printf("\tSystem Power Supply\n");
+ if(h->length<0x10) break;
+ if(data[0x04]!=0x00)
+ printf("\t\tPower Unit Group: %u\n",
+ data[0x04]);
+ printf("\t\tLocation: %s\n",
+ dmi_string(h, data[0x05]));
+ printf("\t\tName: %s\n",
+ dmi_string(h, data[0x06]));
+ printf("\t\tManufacturer: %s\n",
+ dmi_string(h, data[0x07]));
+ printf("\t\tSerial Number: %s\n",
+ dmi_string(h, data[0x08]));
+ printf("\t\tAsset Tag: %s\n",
+ dmi_string(h, data[0x09]));
+ printf("\t\tModel Part Number: %s\n",
+ dmi_string(h, data[0x0A]));
+ printf("\t\tRevision: %s\n",
+ dmi_string(h, data[0x0B]));
+ printf("\t\tMax Power Capacity:");
+ dmi_power_supply_power(WORD(data+0x0C));
+ printf("\n");
+ printf("\t\tStatus:");
+ if(WORD(data+0x0E)&(1<<1))
+ printf(" Present, %s",
+ dmi_power_supply_status((WORD(data+0x0E)>>7)&0x07));
+ else
+ printf(" Not Present");
+ printf("\n");
+ printf("\t\tType: %s\n",
+ dmi_power_supply_type((WORD(data+0x0E)>>10)&0x0F));
+ printf("\t\tInput Voltage Range Switching: %s\n",
+ dmi_power_supply_range_switching((WORD(data+0x0E)>>3)&0x0F));
+ printf("\t\tPlugged: %s\n",
+ WORD(data+0x0E)&(1<<2)?"No":"Yes");
+ printf("\t\tHot Replaceable: %s\n",
+ WORD(data+0x0E)&(1<<0)?"Yes":"No");
+ if(h->length<0x16) break;
+ if(WORD(data+0x10)!=0xFFFF)
+ printf("\t\tInput Voltage Probe Handle: 0x%04X\n",
+ WORD(data+0x10));
+ if(WORD(data+0x12)!=0xFFFF)
+ printf("\t\tCooling Device Handle: 0x%04X\n",
+ WORD(data+0x12));
+ if(WORD(data+0x14)!=0xFFFF)
+ printf("\t\tInput Current Probe Handle: 0x%04X\n",
+ WORD(data+0x14));
break;
- case 126:
+
+ case 126: /* 3.3.41 Inactive */
printf("\tInactive\n");
break;
-
- case 127:
- printf("\tEnd-of-Table\n");
+
+ case 127: /* 3.3.42 End Of Table */
+ printf("\tEnd Of Table\n");
break;
-
+
default:
- if (dm->length > 4)
- dump_raw_data(data+4, dm->length-4);
- break;
-
-
-
- }
- data=next;
- i++;
+ printf("\t%s Type\n",
+ h->type>=128?"OEM-specific":"Unknown");
+ dmi_dump(h, "\t\t");
}
- if(i!=num)
+}
+
+static void dmi_table(int fd, u32 base, u16 len, u16 num, u16 ver, const char *pname, const char *devmem)
+{
+ u8 *buf;
+ u8 *data;
+ int i=0;
+
+ printf("%u structures occupying %u bytes.\n",
+ num, len);
+ printf("Table at 0x%08X.\n",
+ base);
+
+ if(base>0xFFFFF) return;
+
+ if((buf=malloc(len))==NULL)
{
- printf("Wrong DMI structures count: %d announced, only %d decoded.\n",
- num, i);
+ perror(pname);
+ return;
}
- if(data-(u8*)buf!=len)
+ if(lseek(fd, (off_t)base, SEEK_SET)==-1)
{
- printf("Wrong DMI structures length: %d bytes announced, %d bytes decoded.\n",
- len, data-(u8*)buf);
+ perror(devmem);
+ return;
+ }
+ if(myread(fd, buf, len, devmem)==-1)
+ {
+ free(buf);
+ exit(1);
}
- free(buf);
-}
-
-
-static const char *acpi_version(u8 code)
-{
- static const char *version[]={
- " 1.0",
- "",
- " 2.0"
- };
-
- if(code<=2)
- return version[code];
- return "";
-}
-
-
-static const char *pnp_event_notification(u8 code)
-{
- static const char *notification[]={
- "Not Supported",
- "Polling",
- "Asynchronous"
- };
- if(code<=2)
- return notification[code];
- return "";
-}
-
-
-static void pir_exclusive_irqs(u16 code)
-{
- if(code==0)
- printf(" None");
- else
+ data=buf;
+ while(i<num && data+sizeof(struct dmi_header)<=buf+len)
{
- u8 a;
- for(a=0; a<16; a++)
- if(code&(1<<a))
- printf(" %u", a);
+ u8 *next;
+ struct dmi_header *h=(struct dmi_header *)data;
+
+ printf("Handle 0x%04X\n\tDMI type %d, %d bytes.\n",
+ HANDLE(h), h->type, h->length);
+
+ /* look for the next handle */
+ next=data+h->length;
+ while(next-buf+1<len && (next[0]!=0 || next[1]!=0))
+ next++;
+ next+=2;
+ if(next-buf<=len)
+ dmi_decode(data, ver);
+
+ data=next;
+ i++;
}
+
+ if(i!=num)
+ printf("Wrong DMI structures count: %d announced, only %d decoded.\n",
+ num, i);
+ if(data-buf!=len)
+ printf("Wrong DMI structures length: %d bytes announced, %d bytes decoded.\n",
+ len, data-buf);
+
+ free(buf);
}
-static __inline__ int checksum(u8 *buf, int len)
+static int checksum(u8 *buf, u8 len)
{
- u8 sum=0;
- int a;
+ u8 sum=0, a;
for(a=0; a<len; a++)
sum+=buf[a];
return (sum==0);
}
-int main(__attribute__ ((unused)) int argc, const char *argv[])
+int main(int argc, const char *argv[])
{
- u8 buf[48];
- int fd=open("/dev/mem", O_RDONLY);
- long fp=0xE0000L;
- u8 smmajver=0, smminver=0;
+ u8 buf[0x20];
+ int fd;
+ off_t fp=0xF0000;
+ const char *devmem="/dev/mem";
if(sizeof(u8)!=1 || sizeof(u16)!=2 || sizeof(u32)!=4 || '\0'!=0)
{
- fprintf(stderr,"%s: compiler incompatibility.\n", argv[0]);
+ fprintf(stderr,"%s: compiler incompatibility\n", argv[0]);
exit(255);
}
- printf("# dmidecode %s\n", VERSION);
- if(fd==-1)
- {
- perror("/dev/mem");
- exit(1);
- }
- if(lseek(fd, fp, SEEK_SET)==-1)
+
+ if(argc>=2)
+ devmem=argv[1];
+ if((fd=open(devmem, O_RDONLY))==-1 || lseek(fd, fp, SEEK_SET)==-1)
{
- perror("lseek");
+ perror(devmem);
exit(1);
}
-
- while( fp < 0xFFFFF)
+
+ printf("# dmidecode %s\n", VERSION);
+ while(fp<0xFFFFF)
{
- ssize_t r=0, r2=0;
-
- while(r2!=16 && (r=read(fd, buf+r2, 16-r2))!=0 && r!=-1)
- r2+=r;
- if(r==-1)
- {
- perror("read");
+ if(myread(fd, buf, 0x10, devmem)==-1)
exit(1);
- }
- if(r==0)
- {
- fputs("read: Unexpected end of file\n", stderr);
- exit(1);
- }
+ fp+=16;
- 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)
+ if(memcmp(buf, "_SM_", 4)==0 && fp<0xFFFFF)
{
- /* complete buffer, compute checksum */
- read(fd, buf+16, 16); /* arbitrary, at least 1 */
- if(*(u16 *)(buf+8)<=32 && checksum(buf, *(u16 *)(buf+8)))
+ if(myread(fd, buf+0x10, 0x10, devmem)==-1)
+ exit(1);
+ fp+=16;
+
+ if(checksum(buf, buf[0x05])
+ && memcmp(buf+0x10, "_DMI_", 5)==0
+ && checksum(buf+0x10, 0x0F))
{
- fp+=16;
- printf("SYSID present.\n");
- printf("\tRevision: %u\n",
- buf[16]);
- printf("%d structure%s.\n",
- *(u16 *)(buf+14), *(u16 *)(buf+14)>1?"s":"");
- printf("SYSID table at 0x%08X.\n",
- *(u32 *)(buf+10));
+ printf("SMBIOS %u.%u present.\n",
+ buf[0x06], buf[0x07]);
+ dmi_table(fd, DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C),
+ (buf[0x06]<<8)+buf[0x07], argv[0], devmem);
+
+ /* dmi_table moved us far away */
+ lseek(fd, fp, SEEK_SET);
}
- else
- lseek(fd, -16, SEEK_CUR);
}
- else if(memcmp(buf, "_DMI_", 5)==0 && checksum(buf, 15))
+ else if(memcmp(buf, "_DMI_", 5)==0
+ && checksum(buf, 0x0F))
{
- 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];
-
- /* if version is 0.0, the real version is taken from _SM_ above */
- 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);
-
+ printf("Legacy DMI %u.%u present.\n",
+ buf[0x0E]>>4, buf[0x0E]&0x0F);
+ dmi_table(fd, DWORD(buf+0x08), WORD(buf+0x06), WORD(buf+0x0C),
+ ((buf[0x0E]&0xF0)<<4)+(buf[0x0E]&0x0F), argv[0], devmem);
+
/* dmi_table moved us far away */
- lseek(fd, fp+16, SEEK_SET);
- }
- else if(memcmp(buf, "$PnP", 4)==0)
- {
- /* complete buffer, compute checksum */
- read(fd, buf+16, 32); /* arbitrary, at least 1 */
- if(buf[5]<=48 && checksum(buf, buf[5]))
- {
- fp+=32;
- printf("PNP %u.%u present.\n",
- buf[4]>>4, buf[4]&0x0F);
- printf("\tEvent Notification: %s\n",
- pnp_event_notification((*(u16 *)(buf+6))&0x03));
- if(((*(u16 *)(buf+6))&0x03)==1)
- printf("\tEvent Notification Flag Address: 0x%08X\n",
- *(u32 *)(buf+9));
- printf("\tReal Mode Code Address: %04X:%04X\n",
- *(u16 *)(buf+0x0F), *(u16 *)(buf+0x0D));
- printf("\tReal Mode Data Address: %04X:0000\n",
- *(u16 *)(buf+0x1B));
- printf("\tProtected Mode Code Address: 0x%08X\n",
- *(u32 *)(buf+0x13)+*(u16 *)(buf+0x11));
- printf("\tProtected Mode Data Address: 0x%08X\n",
- *(u32 *)(buf+0x1D));
- if(*(u32 *)(buf+0x17)!=0)
- printf("\tOEM Device Identifier: 0x%08X\n",
- *(u32 *)(buf+0x17));
- }
- else
- lseek(fd, -32, SEEK_CUR);
- }
- else if(memcmp(buf, "RSD PTR ", 8)==0)
- {
- /* complete buffer, compute checksum */
- read(fd, buf+16, 4);
- if(checksum(buf, 20))
- {
- lseek(fd, 12, SEEK_CUR);
- fp+=16;
- printf("ACPI%s present.\n",
- acpi_version(buf[15]));
- printf("\tOEM ID: ");
- fwrite(buf+9, 6, 1, stdout);
- printf("\n");
- printf("RSD table at 0x%08X.\n",
- *(u32 *)(buf+16));
- }
- else
- lseek(fd, -4, SEEK_CUR);
- }
- else if(memcmp(buf, "$SNY", 4)==0)
- {
- /* complete buffer, compute checksum */
- read(fd, buf+16, 16);
- if(buf[5]<=32 && checksum(buf, buf[5]))
- {
- fp+=16;
- printf("Sony system detected (?).\n");
- }
- else
- lseek(fd, -16, SEEK_CUR);
- }
- else if(memcmp(buf, "_32_", 4)==0)
- {
- /* complete buffer, reposition file, compute checksum */
- read(fd, buf+16, 32);
- lseek(fd, -32, SEEK_CUR);
- if(buf[9]>=1 && buf[9]<=3 && checksum(buf, buf[9]<<4))
- {
- printf("BIOS32 Service Directory present.\n");
- printf("\tCalling Interface Address: 0x%08X\n",
- *(u32 *)(buf+4));
- lseek(fd, (buf[9]-1)<<4, SEEK_CUR);
- fp+=(buf[9]-1)<<4;
- }
+ lseek(fd, fp, SEEK_SET);
}
- else if(memcmp(buf, "$PIR", 4)==0)
- {
- /* complete buffer, reposition file */
- read(fd, buf+16, 16);
- lseek(fd, -16, SEEK_CUR);
- if(buf[5]!=0 && buf[30]==0)
- {
- printf("PCI Interrupt Routing %u.%u present.\n",
- buf[5], buf[4]);
- printf("\tTable Size: %u bytes\n",
- *(u16 *)(buf+6));
- printf("\tRouter ID: %02x:%02x.%1x\n",
- buf[8], buf[9]>>3, buf[9]&0x07);
- printf("\tExclusive IRQs:");
- pir_exclusive_irqs(*(u16 *)(buf+10));
- printf("\n");
- if(*(u32 *)(buf+12)!=0)
- printf("\tCompatible Router: %04x:%04x\n",
- *(u16 *)(buf+12), *(u16 *)(buf+14));
- if(*(u32 *)(buf+16)!=0)
- printf("\tMiniport Data: 0x%08X\n",
- *(u32 *)(buf+16));
- }
- }
- fp+=16;
}
-
+
if(close(fd)==-1)
{
- perror("/dev/mem");
+ perror(devmem);
exit(1);
}
-
+
return 0;
}