📄 dmidecode.c
字号:
/*
* DMI Decode
*
* Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
* Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For the avoidance of doubt the "preferred form" of this code is one which
* is in an open unpatent encumbered format. Where cryptographic key signing
* forms part of the process of creating an executable the information
* including keys needed to generate an equivalently functional executable
* are deemed to be part of the source code.
*
* Unless specified otherwise, all references are aimed at the "System
* Management BIOS Reference Specification, Version 2.6" document,
* available from http://www.dmtf.org/standards/smbios/.
*
* Note to contributors:
* Please reference every value you add or modify, especially if the
* information does not come from the above mentioned specification.
*
* Additional references:
* - Intel AP-485 revision 32
* "Intel Processor Identification and the CPUID Instruction"
* http://developer.intel.com/design/xeon/applnots/241618.htm
* - DMTF Common Information Model
* CIM Schema version 2.19.1
* http://www.dmtf.org/standards/cim/
* - IPMI 2.0 revision 1.0
* "Intelligent Platform Management Interface Specification"
* http://developer.intel.com/design/servers/ipmi/spec.htm
* - AMD publication #25481 revision 2.28
* "CPUID Specification"
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
* - BIOS Integrity Services Application Programming Interface version 1.0
* http://www.intel.com/design/archives/wfm/downloads/bisspec.htm
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include "version.h"
#include "config.h"
#include "types.h"
#include "util.h"
#include "dmidecode.h"
#include "dmiopt.h"
#include "dmioem.h"
#define out_of_spec "<OUT OF SPEC>"
static const char *bad_index = "<BAD INDEX>";
/*
* Type-independant Stuff
*/
const char *dmi_string(const struct dmi_header *dm, u8 s)
{
char *bp = (char *)dm->data;
size_t i, len;
if (s == 0)
return "Not Specified";
bp += dm->length;
while (s > 1 && *bp)
{
bp += strlen(bp);
bp++;
s--;
}
if (!*bp)
return bad_index;
if (!(opt.flags & FLAG_DUMP))
{
/* ASCII filtering */
len = strlen(bp);
for (i = 0; i < len; i++)
if (bp[i] < 32 || bp[i] == 127)
bp[i] = '.';
}
return bp;
}
static const char *dmi_smbios_structure_type(u8 code)
{
static const char *type[] = {
"BIOS", /* 0 */
"System",
"Base Board",
"Chassis",
"Processor",
"Memory Controller",
"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",
"Additional Information",
"Onboard Device", /* 41 */
};
if (code <= 41)
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(const 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 ? " " : "",
(h->data)[(row << 4) + i]);
printf("\n");
}
if ((h->data)[h->length] || (h->data)[h->length + 1])
{
printf("%sStrings:\n", prefix);
i = 1;
while ((s = dmi_string(h, i++)) != bad_index)
{
if (opt.flags & FLAG_DUMP)
{
int j, l = strlen(s) + 1;
for (row = 0; row < ((l - 1) >> 4) + 1; row++)
{
printf("%s\t", prefix);
for (j = 0; j < 16 && j < l - (row << 4); j++)
printf("%s%02X", j ? " " : "",
s[(row << 4) + j]);
printf("\n");
}
/* String isn't filtered yet so do it now */
printf("%s\t\"", prefix);
while (*s)
{
if (*s < 32 || *s == 127)
fputc('.', stdout);
else
fputc(*s, stdout);
s++;
}
printf("\"\n");
}
else
printf("%s\t%s\n", prefix, s);
}
}
}
/*
* 3.3.1 BIOS Information (Type 0)
*/
static void dmi_bios_runtime_size(u32 code)
{
if (code & 0x000003FF)
printf(" %u bytes", code);
else
printf(" %u kB", code >> 10);
}
static void dmi_bios_characteristics(u64 code, const char *prefix)
{
/* 3.3.1.1 */
static const char *characteristics[] = {
"BIOS characteristics not supported", /* 3 */
"ISA is supported",
"MCA is supported",
"EISA is supported",
"PCI is supported",
"PC Card (PCMCIA) is supported",
"PNP is supported",
"APM is supported",
"BIOS is upgradeable",
"BIOS shadowing is allowed",
"VLB is supported",
"ESCD support is available",
"Boot from CD is supported",
"Selectable boot is supported",
"BIOS ROM is socketed",
"Boot from PC Card (PCMCIA) is supported",
"EDD is supported",
"Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)",
"Japanese floppy for Toshiba 1.2 MB is supported (int 13h)",
"5.25\"/360 kB floppy services are supported (int 13h)",
"5.25\"/1.2 MB floppy services are supported (int 13h)",
"3.5\"/720 kB floppy services are supported (int 13h)",
"3.5\"/2.88 MB floppy services are supported (int 13h)",
"Print screen service is supported (int 5h)",
"8042 keyboard services are supported (int 9h)",
"Serial services are supported (int 14h)",
"Printer services are supported (int 17h)",
"CGA/mono video services are supported (int 10h)",
"NEC PC-98" /* 31 */
};
int i;
/*
* This isn't very clear what this bit is supposed to mean
*/
if (code.l & (1 << 3))
{
printf("%s%s\n",
prefix, characteristics[0]);
return;
}
for (i = 4; i <= 31; i++)
if (code.l & (1 << i))
printf("%s%s\n",
prefix, characteristics[i - 3]);
}
static void dmi_bios_characteristics_x1(u8 code, const char *prefix)
{
/* 3.3.1.2.1 */
static const char *characteristics[] = {
"ACPI is supported", /* 0 */
"USB legacy is supported",
"AGP is supported",
"I2O boot is supported",
"LS-120 boot is supported",
"ATAPI Zip drive boot is supported",
"IEEE 1394 boot is supported",
"Smart battery is supported" /* 7 */
};
int i;
for (i = 0; i <= 7; i++)
if (code & (1 << i))
printf("%s%s\n",
prefix, characteristics[i]);
}
static void dmi_bios_characteristics_x2(u8 code, const char *prefix)
{
/* 3.3.1.2.2 */
static const char *characteristics[] = {
"BIOS boot specification is supported", /* 0 */
"Function key-initiated network boot is supported",
"Targeted content distribution is supported" /* 2 */
};
int i;
for (i = 0; i <= 2; i++)
if (code & (1 << i))
printf("%s%s\n",
prefix, characteristics[i]);
}
/*
* 3.3.2 System Information (Type 1)
*/
static void dmi_system_uuid(const u8 *p, u16 ver)
{
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;
}
/*
* As off version 2.6 of the SMBIOS specification, the first 3
* fields of the UUID are supposed to be encoded on little-endian.
* The specification says that this is the defacto standard,
* however I've seen systems following RFC 4122 instead and use
* network byte order, so I am reluctant to apply the byte-swapping
* for older versions.
*/
if (ver >= 0x0206)
printf("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
else
printf("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
}
static const char *dmi_system_wake_up_type(u8 code)
{
/* 3.3.2.1 */
static const char *type[] = {
"Reserved", /* 0x00 */
"Other",
"Unknown",
"APM Timer",
"Modem Ring",
"LAN Remote",
"Power Switch",
"PCI PME#",
"AC Power Restored" /* 0x08 */
};
if (code <= 0x08)
return type[code];
return out_of_spec;
}
/*
* 3.3.3 Base Board Information (Type 2)
*/
static void dmi_base_board_features(u8 code, const char *prefix)
{
/* 3.3.3.1 */
static const char *features[] = {
"Board is a hosting board", /* 0 */
"Board requires at least one daughter board",
"Board is removable",
"Board is replaceable",
"Board is hot swappable" /* 4 */
};
if ((code & 0x1F) == 0)
printf(" None\n");
else
{
int i;
printf("\n");
for (i = 0; i <= 4; i++)
if (code & (1 << i))
printf("%s%s\n",
prefix, features[i]);
}
}
static const char *dmi_base_board_type(u8 code)
{
/* 3.3.3.2 */
static const char *type[] = {
"Unknown", /* 0x01 */
"Other",
"Server Blade",
"Connectivity Switch",
"System Management Module",
"Processor Module",
"I/O Module",
"Memory Module",
"Daughter Board",
"Motherboard",
"Processor+Memory Module",
"Processor+I/O Module",
"Interconnect Board" /* 0x0D */
};
if (code >= 0x01 && code <= 0x0D)
return type[code - 0x01];
return out_of_spec;
}
static void dmi_base_board_handles(u8 count, const u8 *p, const char *prefix)
{
int i;
printf("%sContained Object Handles: %u\n",
prefix, count);
for (i = 0; i < count; i++)
printf("%s\t0x%04X\n",
prefix, WORD(p + sizeof(u16) * i));
}
/*
* 3.3.4 Chassis Information (Type 3)
*/
static const char *dmi_chassis_type(u8 code)
{
/* 3.3.4.1 */
static const char *type[] = {
"Other", /* 0x01 */
"Unknown",
"Desktop",
"Low Profile Desktop",
"Pizza Box",
"Mini Tower",
"Tower",
"Portable",
"Laptop",
"Notebook",
"Hand Held",
"Docking Station",
"All In One",
"Sub Notebook",
"Space-saving",
"Lunch Box",
"Main Server Chassis", /* CIM_Chassis.ChassisPackageType says "Main System Chassis" */
"Expansion Chassis",
"Sub Chassis",
"Bus Expansion Chassis",
"Peripheral Chassis",
"RAID Chassis",
"Rack Mount Chassis",
"Sealed-case PC",
"Multi-system",
"CompactPCI",
"AdvancedTCA",
"Blade",
"Blade Enclosing" /* 0x1D */
};
if (code >= 0x01 && code <= 0x1D)
return type[code - 0x01];
return out_of_spec;
}
static const char *dmi_chassis_lock(u8 code)
{
static const char *lock[] = {
"Not Present", /* 0x00 */
"Present" /* 0x01 */
};
return lock[code];
}
static const char *dmi_chassis_state(u8 code)
{
/* 3.3.4.2 */
static const char *state[] = {
"Other", /* 0x01 */
"Unknown",
"Safe",
"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, const 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(const struct dmi_header *h)
{
const u8 *data = h->data;
unsigned int i, low, high;
u16 code;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -