Merge to new upstream release 3.0

This commit is contained in:
Jörg Frings-Fürst 2015-09-28 12:32:24 +02:00
commit c86ea762ab
No known key found for this signature in database
GPG Key ID: 09F89F3C8CA1D25D
21 changed files with 964 additions and 342 deletions

7
.gitignore vendored
View File

@ -1,3 +1,8 @@
.bzr
.bzrignore
.pc
.pc
biosdecode
dmidecode
ownership
vpddecode
*.o

View File

@ -1,9 +1,9 @@
DEVELOPER AND MAINTAINER
Anton Arapov <anton@redhat.com>
Jean Delvare <jdelvare@suse.de>
ORIGINAL AUTHORS
Alan Cox <alan@redhat.com>
Jean Delvare <khali@linux-fr.org>
Jean Delvare <jdelvare@suse.de>
CODE CONTRIBUTORS (IN CHRONOLOGICAL ORDER)
Matt Domsch <Matt_Domsch@dell.com>
@ -16,6 +16,9 @@ Roberto Nibali <ratz@tac.ch>
John Cagle <jcagle@kernel.org>
Jens Elkner <elkner@linofee.org>
Jarod Wilson <jarod@redhat.com>
Anton Arapov <anton@redhat.com>
Roy Franz <roy.franz@linaro.org>
Tyler Bell <tyler.bell@hp.com>
MANY THANKS TO (IN CHRONOLOGICAL ORDER)
Werner Heuser
@ -84,3 +87,4 @@ Thomas Mingarelli
Andrey Matveyev
Stefan Tauner
Naga Chumbalkar
Jens Rosenboom

461
CHANGELOG

File diff suppressed because it is too large Load Diff

39
LICENSE
View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
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
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -4,7 +4,7 @@
# VPD Decode
#
# Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
# Copyright (C) 2002-2007 Jean Delvare <khali@linux-fr.org>
# Copyright (C) 2002-2015 Jean Delvare <jdelvare@suse.de>
#
# 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
@ -15,6 +15,10 @@
CC = gcc
CFLAGS = -W -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual \
-Wcast-align -Wwrite-strings -Wmissing-prototypes -Winline -Wundef
# Let lseek and mmap support 64-bit wide offsets
CFLAGS += -D_FILE_OFFSET_BITS=64
#CFLAGS += -DBIGENDIAN
#CFLAGS += -DALIGNMENT_WORKAROUND

View File

@ -2,7 +2,7 @@
* BIOS Decode
*
* Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
* Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2002-2015 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -25,10 +25,10 @@
* are deemed to be part of the source code.
*
* References:
* - DMTF "System Management BIOS Reference Specification"
* Version 2.3.4
* - DMTF "System Management BIOS (SMBIOS) Reference Specification"
* Version 3.0.0
* http://www.dmtf.org/standards/smbios
* - Intel "Preboot Execution Environment (PXE) Specification"
* - 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"
@ -90,6 +90,26 @@ struct bios_entry {
* SMBIOS
*/
static size_t smbios3_length(const u8 *p)
{
return p[0x06];
}
static int smbios3_decode(const u8 *p, size_t len)
{
if (len < 0x18 || !checksum(p, p[0x06]))
return 0;
printf("SMBIOS %u.%u.%u present.\n",
p[0x07], p[0x08], p[0x09]);
printf("\tStructure Table Maximum Length: %u bytes\n",
DWORD(p + 0x0C));
printf("\tStructure Table 64-bit Address: 0x%08X%08X\n",
QWORD(p + 0x10).h, QWORD(p + 0x10).l);
return 1;
}
static size_t smbios_length(const u8 *p)
{
return p[0x05] == 0x1E ? 0x1F : p[0x05];
@ -105,7 +125,7 @@ static int smbios_decode(const u8 *p, size_t len)
printf("SMBIOS %u.%u present.\n",
p[0x06], p[0x07]);
printf("\tStructure Table Length: %u bytes\n",
WORD(p+0x16));
WORD(p + 0x16));
printf("\tStructure Table Address: 0x%08X\n",
DWORD(p + 0x18));
printf("\tNumber Of Structures: %u\n",
@ -516,7 +536,7 @@ static int fjkeyinf_decode(const u8 *p, size_t len)
return 1;
printf("\tDevice %d: type %u, chip %u", i + 1,
*(p + 8 + i * 4), *(p + 8 + i * 4 + 2));
if (*(p+8+i*4+1)) /* Access method */
if (*(p + 8 + i * 4 + 1)) /* Access method */
printf(", SMBus address 0x%x",
*(p + 8 + i * 4 + 3) >> 1);
printf("\n");
@ -530,6 +550,7 @@ static int fjkeyinf_decode(const u8 *p, size_t len)
*/
static struct bios_entry bios_entries[] = {
{ "_SM3_", 0, 0xF0000, 0xFFFFF, smbios3_length, smbios3_decode },
{ "_SM_", 0, 0xF0000, 0xFFFFF, smbios_length, smbios_decode },
{ "_DMI_", 0, 0xF0000, 0xFFFFF, dmi_length, dmi_decode },
{ "_SYSID_", 0, 0xE0000, 0xFFFFF, sysid_length, sysid_decode },
@ -565,7 +586,7 @@ static int parse_command_line(int argc, char * const argv[])
{ "dev-mem", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ 0, 0, 0, 0 }
{ NULL, 0, NULL, 0 }
};
while ((option = getopt_long(argc, argv, optstring, longopts, NULL)) != -1)

View File

@ -2,7 +2,7 @@
* DMI Decode
*
* Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
* Copyright (C) 2002-2010 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2002-2015 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -25,7 +25,7 @@
* 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.8.0" document,
* Management BIOS Reference Specification, Version 3.0.0" document,
* available from http://www.dmtf.org/standards/smbios.
*
* Note to contributors:
@ -69,12 +69,30 @@
#define out_of_spec "<OUT OF SPEC>"
static const char *bad_index = "<BAD INDEX>";
#define SUPPORTED_SMBIOS_VER 0x0207
#define SUPPORTED_SMBIOS_VER 0x0300
#define FLAG_NO_FILE_OFFSET (1 << 0)
#define FLAG_STOP_AT_EOT (1 << 1)
#define SYS_ENTRY_FILE "/sys/firmware/dmi/tables/smbios_entry_point"
#define SYS_TABLE_FILE "/sys/firmware/dmi/tables/DMI"
/*
* Type-independant Stuff
*/
/* Returns 1 if the buffer contains only printable ASCII characters */
int is_printable(const u8 *data, int len)
{
int i;
for (i = 0; i < len; i++)
if (data[i] < 32 || data[i] >= 127)
return 0;
return 1;
}
const char *dmi_string(const struct dmi_header *dm, u8 s)
{
char *bp = (char *)dm->data;
@ -529,12 +547,15 @@ static const char *dmi_chassis_type(u8 code)
"CompactPCI",
"AdvancedTCA",
"Blade",
"Blade Enclosing" /* 0x1D */
"Blade Enclosing",
"Tablet",
"Convertible",
"Detachable" /* 0x20 */
};
code &= 0x7F; /* bits 6:0 are chassis type, 7th bit is the lock bit */
if (code >= 0x01 && code <= 0x1D)
if (code >= 0x01 && code <= 0x20)
return type[code - 0x01];
return out_of_spec;
}
@ -695,6 +716,7 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x29, "Core Duo Mobile" },
{ 0x2A, "Core Solo Mobile" },
{ 0x2B, "Atom" },
{ 0x2C, "Core M" },
{ 0x30, "Alpha" },
{ 0x31, "Alpha 21064" },
@ -712,7 +734,6 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x3D, "Opteron 6200" },
{ 0x3E, "Opteron 4200" },
{ 0x3F, "FX" },
{ 0x40, "MIPS" },
{ 0x41, "MIPS R4000" },
{ 0x42, "MIPS R4200" },
@ -729,7 +750,6 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x4D, "Opteron 6300" },
{ 0x4E, "Opteron 3300" },
{ 0x4F, "FirePro" },
{ 0x50, "SPARC" },
{ 0x51, "SuperSPARC" },
{ 0x52, "MicroSPARC II" },
@ -746,6 +766,9 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x63, "68010" },
{ 0x64, "68020" },
{ 0x65, "68030" },
{ 0x66, "Athlon X4" },
{ 0x67, "Opteron X1000" },
{ 0x68, "Opteron X2000" },
{ 0x70, "Hobbit" },
@ -821,7 +844,7 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0xC9, "G4" },
{ 0xCA, "G5" },
{ 0xCB, "ESA/390 G6" },
{ 0xCC, "z/Architectur" },
{ 0xCC, "z/Architecture" },
{ 0xCD, "Core i5" },
{ 0xCE, "Core i3" },
@ -1014,11 +1037,11 @@ static void dmi_processor_id(u8 type, const u8 *p, const char *version, const ch
sig = 1;
else if ((type >= 0x18 && type <= 0x1D) /* AMD */
|| type == 0x1F /* AMD */
|| (type >= 0x38 && type <= 0x3E) /* AMD */
|| (type >= 0x46 && type <= 0x49) /* AMD */
|| (type >= 0x38 && type <= 0x3F) /* AMD */
|| (type >= 0x46 && type <= 0x4F) /* AMD */
|| (type >= 0x83 && type <= 0x8F) /* AMD */
|| (type >= 0xB6 && type <= 0xB7) /* AMD */
|| (type >= 0xE6 && type <= 0xEF)) /* AMD */
|| (type >= 0xE4 && type <= 0xEF)) /* AMD */
sig = 2;
else if (type == 0x01 || type == 0x02)
{
@ -1173,10 +1196,14 @@ static const char *dmi_processor_upgrade(u8 code)
"Socket FM1",
"Socket FM2",
"Socket LGA2011-3",
"Socket LGA1356-3" /* 0x2C */
"Socket LGA1356-3",
"Socket LGA1150",
"Socket BGA1168",
"Socket BGA1234",
"Socket BGA1364" /* 0x30 */
};
if (code >= 0x01 && code <= 0x2A)
if (code >= 0x01 && code <= 0x30)
return upgrade[code - 0x01];
return out_of_spec;
}
@ -1672,7 +1699,20 @@ static const char *dmi_slot_type(u8 code)
"AGP 2x",
"AGP 4x",
"PCI-X",
"AGP 8x" /* 0x13 */
"AGP 8x",
"M.2 Socket 1-DP",
"M.2 Socket 1-SD",
"M.2 Socket 2",
"M.2 Socket 3",
"MXM Type I",
"MXM Type II",
"MXM Type III",
"MXM Type III-HE",
"MXM Type IV",
"MXM 3.0 Type A",
"MXM 3.0 Type B",
"PCI Express 2 SFF-8639",
"PCI Express 3 SFF-8639" /* 0x20 */
};
static const char *type_0xA0[] = {
"PC-98/C20", /* 0xA0 */
@ -1699,8 +1739,12 @@ static const char *dmi_slot_type(u8 code)
"PCI Express 3 x8",
"PCI Express 3 x16" /* 0xB6 */
};
/*
* Note to developers: when adding entries to these lists, check if
* function dmi_slot_id below needs updating too.
*/
if (code >= 0x01 && code <= 0x13)
if (code >= 0x01 && code <= 0x20)
return type[code - 0x01];
if (code >= 0xA0 && code <= 0xB6)
return type_0xA0[code - 0xA0];
@ -1780,6 +1824,8 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type, const char *prefix)
case 0x11: /* AGP */
case 0x12: /* PCI-X */
case 0x13: /* AGP */
case 0x1F: /* PCI Express 2 */
case 0x20: /* PCI Express 3 */
case 0xA5: /* PCI Express */
case 0xA6: /* PCI Express */
case 0xA7: /* PCI Express */
@ -1792,6 +1838,12 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type, const char *prefix)
case 0xAE: /* PCI Express 2 */
case 0xAF: /* PCI Express 2 */
case 0xB0: /* PCI Express 2 */
case 0xB1: /* PCI Express 3 */
case 0xB2: /* PCI Express 3 */
case 0xB3: /* PCI Express 3 */
case 0xB4: /* PCI Express 3 */
case 0xB5: /* PCI Express 3 */
case 0xB6: /* PCI Express 3 */
printf("%sID: %u\n", prefix, code1);
break;
case 0x07: /* PCMCIA */
@ -2236,7 +2288,7 @@ static void dmi_memory_voltage_value(u16 code)
if (code == 0)
printf(" Unknown");
else
printf(" %.3f V", (float)(i16)code / 1000);
printf(code % 100 ? " %g V" : " %.1f V", (float)code / 1000);
}
static const char *dmi_memory_device_form_factor(u8 code)
@ -2303,10 +2355,15 @@ static const char *dmi_memory_device_type(u8 code)
"Reserved",
"Reserved",
"DDR3",
"FBD2", /* 0x19 */
"FBD2",
"DDR4",
"LPDDR",
"LPDDR2",
"LPDDR3",
"LPDDR4" /* 0x1E */
};
if (code >= 0x01 && code <= 0x19)
if (code >= 0x01 && code <= 0x1E)
return type[code - 0x01];
return out_of_spec;
}
@ -2338,7 +2395,7 @@ static void dmi_memory_device_type_detail(u16 code)
{
int i;
for (i = 1; i <= 14; i++)
for (i = 1; i <= 15; i++)
if (code & (1 << i))
printf(" %s", detail[i - 1]);
}
@ -2883,6 +2940,25 @@ static void dmi_64bit_memory_error_address(u64 code)
* 7.35 Management Device (Type 34)
*/
/*
* Several boards have a bug where some type 34 structures have their
* length incorrectly set to 0x10 instead of 0x0B. This causes the
* first 5 characters of the device name to be trimmed. It's easy to
* check and fix, so do it, but warn.
*/
static void dmi_fixup_type_34(struct dmi_header *h)
{
u8 *p = h->data;
/* Make sure the hidden data is ASCII only */
if (h->length == 0x10
&& is_printable(p + 0x0B, 0x10 - 0x0B))
{
printf("Invalid entry length (%u). Fixed up to %u.\n", 0x10, 0x0B);
h->length = 0x0B;
}
}
static const char *dmi_management_device_type(u8 code)
{
/* 7.35.1 */
@ -3155,7 +3231,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
const u8 *data = h->data;
/*
* Note: DMI types 37, 39 and 40 are untested
* Note: DMI types 37 and 42 are untested
*/
switch (h->type)
{
@ -3350,11 +3426,17 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_string(h, data[0x22]));
if (h->length < 0x28) break;
if (data[0x23] != 0)
printf("\tCore Count: %u\n", data[0x23]);
printf("\tCore Count: %u\n",
h->length >= 0x2C && data[0x23] == 0xFF ?
WORD(data + 0x2A) : data[0x23]);
if (data[0x24] != 0)
printf("\tCore Enabled: %u\n", data[0x24]);
printf("\tCore Enabled: %u\n",
h->length >= 0x2E && data[0x24] == 0xFF ?
WORD(data + 0x2C) : data[0x24]);
if (data[0x25] != 0)
printf("\tThread Count: %u\n", data[0x25]);
printf("\tThread Count: %u\n",
h->length >= 0x30 && data[0x25] == 0xFF ?
WORD(data + 0x2E) : data[0x25]);
printf("\tCharacteristics:");
dmi_processor_characteristics(WORD(data + 0x26), "\t\t");
break;
@ -3657,13 +3739,13 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_memory_device_speed(WORD(data + 0x20));
printf("\n");
if (h->length < 0x28) break;
printf("\tMinimum voltage: ");
printf("\tMinimum Voltage:");
dmi_memory_voltage_value(WORD(data + 0x22));
printf("\n");
printf("\tMaximum voltage: ");
printf("\tMaximum Voltage:");
dmi_memory_voltage_value(WORD(data + 0x24));
printf("\n");
printf("\tConfigured voltage: ");
printf("\tConfigured Voltage:");
dmi_memory_voltage_value(WORD(data + 0x26));
printf("\n");
break;
@ -4212,8 +4294,9 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
case 40: /* 7.41 Additional Information */
if (h->length < 0x0B) break;
if (!(opt.flags & FLAG_QUIET))
dmi_additional_info(h, "");
if (opt.flags & FLAG_QUIET)
return;
dmi_additional_info(h, "");
break;
case 41: /* 7.42 Onboard Device Extended Information */
@ -4306,65 +4389,21 @@ static void dmi_table_string(const struct dmi_header *h, const u8 *data, u16 ver
}
}
static void dmi_table_dump(u32 base, u16 len, const char *devmem)
static void dmi_table_dump(const u8 *buf, u32 len)
{
u8 *buf;
if ((buf = mem_chunk(base, len, devmem)) == NULL)
{
fprintf(stderr, "Failed to read table, sorry.\n");
return;
}
if (!(opt.flags & FLAG_QUIET))
printf("# Writing %d bytes to %s.\n", len, opt.dumpfile);
write_dump(32, len, buf, opt.dumpfile, 0);
free(buf);
}
static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem)
static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags)
{
u8 *buf;
u8 *data;
int i = 0;
if (ver > SUPPORTED_SMBIOS_VER)
{
printf("# SMBIOS implementations newer than version %u.%u are not\n"
"# fully supported by this version of dmidecode.\n",
SUPPORTED_SMBIOS_VER >> 8, SUPPORTED_SMBIOS_VER & 0xFF);
}
if (opt.flags & FLAG_DUMP_BIN)
{
dmi_table_dump(base, len, devmem);
return;
}
if (!(opt.flags & FLAG_QUIET))
{
if (opt.type == NULL)
{
printf("%u structures occupying %u bytes.\n",
num, len);
if (!(opt.flags & FLAG_FROM_DUMP))
printf("Table at 0x%08X.\n", base);
}
printf("\n");
}
if ((buf = mem_chunk(base, len, devmem)) == NULL)
{
fprintf(stderr, "Table is unreachable, sorry."
#ifndef USE_MMAP
" Try compiling dmidecode with -DUSE_MMAP."
#endif
"\n");
return;
}
data = buf;
while (i < num && data+4 <= buf + len) /* 4 is the length of an SMBIOS structure header */
while ((i < num || !num)
&& data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */
{
u8 *next;
struct dmi_header h;
@ -4372,7 +4411,7 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem)
to_dmi_header(&h, data);
display = ((opt.type == NULL || opt.type[h.type])
&& !((opt.flags & FLAG_QUIET) && (h.type > 39 && h.type <= 127))
&& !((opt.flags & FLAG_QUIET) && (h.type == 126 || h.type == 127))
&& !opt.string);
/*
@ -4399,17 +4438,22 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem)
h.handle, h.type, h.length);
/* assign vendor for vendor-specific decodes later */
if (h.type == 0 && h.length >= 5)
if (h.type == 1 && h.length >= 5)
dmi_set_vendor(dmi_string(&h, data[0x04]));
/* Fixup a common mistake */
if (h.type == 34)
dmi_fixup_type_34(&h);
/* look for the next handle */
next = data + h.length;
while (next - buf + 1 < len && (next[0] != 0 || next[1] != 0))
while ((unsigned long)(next - buf + 1) < len
&& (next[0] != 0 || next[1] != 0))
next++;
next += 2;
if (display)
{
if (next - buf <= len)
if ((unsigned long)(next - buf) <= len)
{
if (opt.flags & FLAG_DUMP)
{
@ -4428,19 +4472,79 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem)
data = next;
i++;
/* SMBIOS v3 requires stopping at this marker */
if (h.type == 127 && (flags & FLAG_STOP_AT_EOT))
break;
}
/*
* SMBIOS v3 64-bit entry points do not announce a structures count,
* and only indicate a maximum size for the table.
*/
if (!(opt.flags & FLAG_QUIET))
{
if (num && i != num)
printf("Wrong DMI structures count: %d announced, "
"only %d decoded.\n", num, i);
if ((unsigned long)(data - buf) > len
|| (num && (unsigned long)(data - buf) < len))
printf("Wrong DMI structures length: %u bytes "
"announced, structures occupy %lu bytes.\n",
len, (unsigned long)(data - buf));
}
}
static void dmi_table(off_t base, u32 len, u16 num, u16 ver, const char *devmem,
u32 flags)
{
u8 *buf;
if (ver > SUPPORTED_SMBIOS_VER && !(opt.flags & FLAG_QUIET))
{
printf("# SMBIOS implementations newer than version %u.%u are not\n"
"# fully supported by this version of dmidecode.\n",
SUPPORTED_SMBIOS_VER >> 8, SUPPORTED_SMBIOS_VER & 0xFF);
}
if (!(opt.flags & FLAG_QUIET))
{
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, structures occupy %d bytes.\n",
len, (unsigned int)(data - buf));
if (opt.type == NULL)
{
if (num)
printf("%u structures occupying %u bytes.\n",
num, len);
if (!(opt.flags & FLAG_FROM_DUMP))
printf("Table at 0x%08llX.\n",
(unsigned long long)base);
}
printf("\n");
}
/*
* When we are reading the DMI table from sysfs, we want to print
* the address of the table (done above), but the offset of the
* data in the file is 0. When reading from /dev/mem, the offset
* in the file is the address.
*/
if (flags & FLAG_NO_FILE_OFFSET)
base = 0;
if ((buf = mem_chunk(base, len, devmem)) == NULL)
{
fprintf(stderr, "Table is unreachable, sorry."
#ifndef USE_MMAP
" Try compiling dmidecode with -DUSE_MMAP."
#endif
"\n");
return;
}
if (opt.flags & FLAG_DUMP_BIN)
dmi_table_dump(buf, len);
else
dmi_table_decode(buf, len, num, ver, flags);
free(buf);
}
@ -4459,7 +4563,61 @@ static void overwrite_dmi_address(u8 *buf)
buf[0x0B] = 0;
}
static int smbios_decode(u8 *buf, const char *devmem)
/* Same thing for SMBIOS3 entry points */
static void overwrite_smbios3_address(u8 *buf)
{
buf[0x05] += buf[0x10] + buf[0x11] + buf[0x12] + buf[0x13]
+ buf[0x14] + buf[0x15] + buf[0x16] + buf[0x17] - 32;
buf[0x10] = 32;
buf[0x11] = 0;
buf[0x12] = 0;
buf[0x13] = 0;
buf[0x14] = 0;
buf[0x15] = 0;
buf[0x16] = 0;
buf[0x17] = 0;
}
static int smbios3_decode(u8 *buf, const char *devmem, u32 flags)
{
u16 ver;
u64 offset;
if (!checksum(buf, buf[0x06]))
return 0;
ver = (buf[0x07] << 8) + buf[0x08];
if (!(opt.flags & FLAG_QUIET))
printf("SMBIOS %u.%u.%u present.\n",
buf[0x07], buf[0x08], buf[0x09]);
offset = QWORD(buf + 0x10);
if (!(flags & FLAG_NO_FILE_OFFSET) && offset.h && sizeof(off_t) < 8)
{
fprintf(stderr, "64-bit addresses not supported, sorry.\n");
return 0;
}
dmi_table(((off_t)offset.h << 32) | offset.l,
WORD(buf + 0x0C), 0, ver, devmem, flags | FLAG_STOP_AT_EOT);
if (opt.flags & FLAG_DUMP_BIN)
{
u8 crafted[32];
memcpy(crafted, buf, 32);
overwrite_smbios3_address(crafted);
if (!(opt.flags & FLAG_QUIET))
printf("# Writing %d bytes to %s.\n", crafted[0x06],
opt.dumpfile);
write_dump(0, crafted[0x06], crafted, opt.dumpfile, 1);
}
return 1;
}
static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
{
u16 ver;
@ -4491,7 +4649,7 @@ static int smbios_decode(u8 *buf, const char *devmem)
ver >> 8, ver & 0xFF);
dmi_table(DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C),
ver, devmem);
ver, devmem, flags);
if (opt.flags & FLAG_DUMP_BIN)
{
@ -4509,7 +4667,7 @@ static int smbios_decode(u8 *buf, const char *devmem)
return 1;
}
static int legacy_decode(u8 *buf, const char *devmem)
static int legacy_decode(u8 *buf, const char *devmem, u32 flags)
{
if (!checksum(buf, 0x0F))
return 0;
@ -4519,7 +4677,7 @@ static int legacy_decode(u8 *buf, const char *devmem)
buf[0x0E] >> 4, buf[0x0E] & 0x0F);
dmi_table(DWORD(buf + 0x08), WORD(buf + 0x06), WORD(buf + 0x0C),
((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F), devmem);
((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F), devmem, flags);
if (opt.flags & FLAG_DUMP_BIN)
{
@ -4528,7 +4686,9 @@ static int legacy_decode(u8 *buf, const char *devmem)
memcpy(crafted, buf, 16);
overwrite_dmi_address(crafted);
printf("# Writing %d bytes to %s.\n", 0x0F, opt.dumpfile);
if (!(opt.flags & FLAG_QUIET))
printf("# Writing %d bytes to %s.\n", 0x0F,
opt.dumpfile);
write_dump(0, 0x0F, crafted, opt.dumpfile, 1);
}
@ -4540,7 +4700,7 @@ static int legacy_decode(u8 *buf, const char *devmem)
*/
#define EFI_NOT_FOUND (-1)
#define EFI_NO_SMBIOS (-2)
static int address_from_efi(size_t *address)
static int address_from_efi(off_t *address)
{
FILE *efi_systab;
const char *filename;
@ -4564,12 +4724,13 @@ static int address_from_efi(size_t *address)
{
char *addrp = strchr(linebuf, '=');
*(addrp++) = '\0';
if (strcmp(linebuf, "SMBIOS") == 0)
if (strcmp(linebuf, "SMBIOS3") == 0
|| strcmp(linebuf, "SMBIOS") == 0)
{
*address = strtoul(addrp, NULL, 0);
*address = strtoull(addrp, NULL, 0);
if (!(opt.flags & FLAG_QUIET))
printf("# SMBIOS entry point at 0x%08lx\n",
(unsigned long)*address);
printf("# %s entry point at 0x%08llx\n",
linebuf, (unsigned long long)*address);
ret = 0;
break;
}
@ -4586,7 +4747,7 @@ int main(int argc, char * const argv[])
{
int ret = 0; /* Returned value */
int found = 0;
size_t fp;
off_t fp;
int efi;
u8 *buf;
@ -4633,20 +4794,57 @@ int main(int argc, char * const argv[])
goto exit_free;
}
if (memcmp(buf, "_SM_", 4) == 0)
if (memcmp(buf, "_SM3_", 5) == 0)
{
if (smbios_decode(buf, opt.dumpfile))
if (smbios3_decode(buf, opt.dumpfile, 0))
found++;
}
else if (memcmp(buf, "_SM_", 4) == 0)
{
if (smbios_decode(buf, opt.dumpfile, 0))
found++;
}
else if (memcmp(buf, "_DMI_", 5) == 0)
{
if (legacy_decode(buf, opt.dumpfile))
if (legacy_decode(buf, opt.dumpfile, 0))
found++;
}
goto done;
}
/* First try EFI (ia64, Intel-based Mac) */
/*
* First try reading from sysfs tables. The entry point file could
* contain one of several types of entry points, so read enough for
* the largest one, then determine what type it contains.
*/
if (!(opt.flags & FLAG_NO_SYSFS)
&& (buf = read_file(0x20, SYS_ENTRY_FILE)) != NULL)
{
if (!(opt.flags & FLAG_QUIET))
printf("Getting SMBIOS data from sysfs.\n");
if (memcmp(buf, "_SM3_", 5) == 0)
{
if (smbios3_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
found++;
}
else if (memcmp(buf, "_SM_", 4) == 0)
{
if (smbios_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
found++;
}
else if (memcmp(buf, "_DMI_", 5) == 0)
{
if (legacy_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
found++;
}
if (found)
goto done;
if (!(opt.flags & FLAG_QUIET))
printf("Failed to get SMBIOS data from sysfs.\n");
}
/* Next try EFI (ia64, Intel-based Mac) */
efi = address_from_efi(&fp);
switch (efi)
{
@ -4657,17 +4855,22 @@ int main(int argc, char * const argv[])
goto exit_free;
}
if (!(opt.flags & FLAG_QUIET))
printf("Found SMBIOS entry point in EFI, reading table from %s.\n",
opt.devmem);
if ((buf = mem_chunk(fp, 0x20, opt.devmem)) == NULL)
{
ret = 1;
goto exit_free;
}
if (smbios_decode(buf, opt.devmem))
if (smbios_decode(buf, opt.devmem, 0))
found++;
goto done;
memory_scan:
if (!(opt.flags & FLAG_QUIET))
printf("Scanning %s for entry point.\n", opt.devmem);
/* Fallback to memory scan (x86, x86_64) */
if ((buf = mem_chunk(0xF0000, 0x10000, opt.devmem)) == NULL)
{
@ -4677,9 +4880,17 @@ memory_scan:
for (fp = 0; fp <= 0xFFF0; fp += 16)
{
if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0)
if (memcmp(buf + fp, "_SM3_", 5) == 0 && fp <= 0xFFE0)
{
if (smbios_decode(buf+fp, opt.devmem))
if (smbios3_decode(buf + fp, opt.devmem, 0))
{
found++;
fp += 16;
}
}
else if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0)
{
if (smbios_decode(buf + fp, opt.devmem, 0))
{
found++;
fp += 16;
@ -4687,7 +4898,7 @@ memory_scan:
}
else if (memcmp(buf + fp, "_DMI_", 5) == 0)
{
if (legacy_decode(buf + fp, opt.devmem))
if (legacy_decode(buf + fp, opt.devmem, 0))
found++;
}
}

View File

@ -1,7 +1,7 @@
/*
* This file is part of the dmidecode project.
*
* Copyright (C) 2005-2008 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2005-2008 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "types.h"
struct dmi_header
{
u8 type;
@ -26,4 +28,5 @@ struct dmi_header
u8 *data;
};
int is_printable(const u8 *data, int len);
const char *dmi_string(const struct dmi_header *dm, u8 s);

197
dmioem.c
View File

@ -2,7 +2,7 @@
* Decoding of OEM-specific entries
* This file is part of the dmidecode project.
*
* Copyright (C) 2007-2008 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2007-2008 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -30,7 +30,12 @@
* Globals for vendor-specific decodes
*/
enum DMI_VENDORS { VENDOR_UNKNOWN, VENDOR_HP };
enum DMI_VENDORS
{
VENDOR_UNKNOWN,
VENDOR_HP,
VENDOR_ACER,
};
static enum DMI_VENDORS dmi_vendor = VENDOR_UNKNOWN;
@ -41,20 +46,58 @@ static enum DMI_VENDORS dmi_vendor = VENDOR_UNKNOWN;
*/
void dmi_set_vendor(const char *s)
{
if (strcmp(s, "HP") == 0 || strcmp(s, "Hewlett-Packard") == 0)
int len;
/*
* Often DMI strings have trailing spaces. Ignore these
* when checking for known vendor names.
*/
len = strlen(s);
while (len && s[len - 1] == ' ')
len--;
if (strncmp(s, "HP", len) == 0 || strncmp(s, "Hewlett-Packard", len) == 0)
dmi_vendor = VENDOR_HP;
else if (strncmp(s, "Acer", len) == 0)
dmi_vendor = VENDOR_ACER;
}
/*
* HP-specific data structures are decoded here.
*
* Code contributed by John Cagle.
* Code contributed by John Cagle and Tyler Bell.
*/
static void dmi_print_hp_net_iface_rec(u8 id, u8 bus, u8 dev, const u8 *mac)
{
/* Some systems do not provide an id. nic_ctr provides an artificial
* id, and assumes the records will be provided "in order". Also,
* using 0xFF marker is not future proof. 256 NICs is a lot, but
* 640K ought to be enough for anybody(said no one, ever).
* */
static u8 nic_ctr;
if (id == 0xFF)
id = ++nic_ctr;
if (dev == 0x00 && bus == 0x00)
printf("\tNIC %d: Disabled\n", id);
else if (dev == 0xFF && bus == 0xFF)
printf("\tNIC %d: Not Installed\n", id);
else
{
printf("\tNIC %d: PCI device %02x:%02x.%x, "
"MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
id, bus, dev >> 3, dev & 7,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
}
static int dmi_decode_hp(const struct dmi_header *h)
{
u8 *data = h->data;
int nic, ptr;
u32 feat;
switch (h->type)
{
@ -80,6 +123,19 @@ static int dmi_decode_hp(const struct dmi_header *h)
*
* This prints the BIOS NIC number,
* PCI bus/device/function, and MAC address
*
* Type 209:
* Offset | Name | Width | Description
* -------------------------------------
* 0x00 | Type | BYTE | 0xD1, MAC Info
* 0x01 | Length | BYTE | Length of structure
* 0x02 | Handle | WORD | Unique handle
* 0x04 | Dev No | BYTE | PCI Device/Function No
* 0x05 | Bus No | BYTE | PCI Bus
* 0x06 | MAC | 6B | MAC addr
* 0x0C | NIC #2 | 8B | Repeat 0x04-0x0B
*
* Type 221: is deprecated in the latest docs
*/
printf(h->type == 221 ?
"HP BIOS iSCSI NIC PCI and MAC Information\n" :
@ -88,25 +144,128 @@ static int dmi_decode_hp(const struct dmi_header *h)
ptr = 4;
while (h->length >= ptr + 8)
{
if (data[ptr] == 0x00 && data[ptr + 1] == 0x00)
printf("\tNIC %d: Disabled\n", nic);
else if (data[ptr] == 0xFF && data[ptr + 1] == 0xFF)
printf("\tNIC %d: Not Installed\n", nic);
else
{
printf("\tNIC %d: PCI device %02x:%02x.%x, "
"MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
nic, data[ptr + 1],
data[ptr] >> 3, data[ptr] & 7,
data[ptr + 2], data[ptr + 3],
data[ptr + 4], data[ptr + 5],
data[ptr + 6], data[ptr + 7]);
}
dmi_print_hp_net_iface_rec(nic,
data[ptr + 0x01],
data[ptr],
&data[ptr + 0x02]);
nic++;
ptr += 8;
}
break;
case 233:
/*
* Vendor Specific: HP ProLiant NIC MAC Information
*
* This prints the BIOS NIC number,
* PCI bus/device/function, and MAC address
*
* Offset | Name | Width | Description
* -------------------------------------
* 0x00 | Type | BYTE | 0xE9, NIC structure
* 0x01 | Length | BYTE | Length of structure
* 0x02 | Handle | WORD | Unique handle
* 0x04 | Grp No | WORD | 0 for single segment
* 0x06 | Bus No | BYTE | PCI Bus
* 0x07 | Dev No | BYTE | PCI Device/Function No
* 0x08 | MAC | 32B | MAC addr padded w/ 0s
* 0x28 | Port No| BYTE | Each NIC maps to a Port
*/
printf("HP BIOS PXE NIC PCI and MAC Information\n");
if (h->length < 0x0E) break;
/* If the record isn't long enough, we don't have an ID
* use 0xFF to use the internal counter.
* */
nic = h->length > 0x28 ? data[0x28] : 0xFF;
dmi_print_hp_net_iface_rec(nic, data[0x06], data[0x07],
&data[0x08]);
break;
case 212:
/*
* Vendor Specific: HP 64-bit CRU Information
*
* Source: hpwdt kernel driver
*/
printf("HP 64-bit CRU Information\n");
if (h->length < 0x18) break;
printf("\tSignature: 0x%08x", DWORD(data + 0x04));
if (is_printable(data + 0x04, 4))
printf(" (%c%c%c%c)", data[0x04], data[0x05],
data[0x06], data[0x07]);
printf("\n");
if (DWORD(data + 0x04) == 0x55524324)
{
u64 paddr = QWORD(data + 0x08);
paddr.l += DWORD(data + 0x14);
if (paddr.l < DWORD(data + 0x14))
paddr.h++;
printf("\tPhysical Address: 0x%08x%08x\n",
paddr.h, paddr.l);
printf("\tLength: 0x%08x\n", DWORD(data + 0x10));
}
break;
case 219:
/*
* Vendor Specific: HP ProLiant Information
*
* Source: hpwdt kernel driver
*/
printf("HP ProLiant Information\n");
if (h->length < 0x08) break;
printf("\tPower Features: 0x%08x\n", DWORD(data + 0x04));
if (h->length < 0x0C) break;
printf("\tOmega Features: 0x%08x\n", DWORD(data + 0x08));
if (h->length < 0x14) break;
feat = DWORD(data + 0x10);
printf("\tMisc. Features: 0x%08x\n", feat);
printf("\t\tiCRU: %s\n", feat & 0x0001 ? "Yes" : "No");
printf("\t\tUEFI: %s\n", feat & 0x0408 ? "Yes" : "No");
break;
default:
return 0;
}
return 1;
}
/*
* Acer-specific data structures are decoded here.
*/
static int dmi_decode_acer(const struct dmi_header *h)
{
u8 *data = h->data;
u16 cap;
switch (h->type)
{
case 170:
/*
* Vendor Specific: Acer Hotkey Function
*
* Source: acer-wmi kernel driver
*
* Probably applies to some laptop models of other
* brands, including Fujitsu-Siemens, Medion, Lenovo,
* and eMachines.
*/
printf("Acer Hotkey Function\n");
if (h->length < 0x0F) break;
cap = WORD(data + 0x04);
printf("\tFunction bitmap for Communication Button: 0x%04hx\n", cap);
printf("\t\tWiFi: %s\n", cap & 0x0001 ? "Yes" : "No");
printf("\t\t3G: %s\n", cap & 0x0040 ? "Yes" : "No");
printf("\t\tWiMAX: %s\n", cap & 0x0080 ? "Yes" : "No");
printf("\t\tBluetooth: %s\n", cap & 0x0800 ? "Yes" : "No");
printf("\tFunction bitmap for Application Button: 0x%04hx\n", WORD(data + 0x06));
printf("\tFunction bitmap for Media Button: 0x%04hx\n", WORD(data + 0x08));
printf("\tFunction bitmap for Display Button: 0x%04hx\n", WORD(data + 0x0A));
printf("\tFunction bitmap for Others Button: 0x%04hx\n", WORD(data + 0x0C));
printf("\tCommunication Function Key Number: %d\n", data[0x0E]);
break;
default:
return 0;
}
@ -123,6 +282,8 @@ int dmi_decode_oem(const struct dmi_header *h)
{
case VENDOR_HP:
return dmi_decode_hp(h);
case VENDOR_ACER:
return dmi_decode_acer(h);
default:
return 0;
}

View File

@ -2,7 +2,7 @@
* Decoding of OEM-specific entries
* This file is part of the dmidecode project.
*
* Copyright (C) 2007-2008 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2007-2008 Jean Delvare <jdelvare@suse.de>
*
* 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

View File

@ -2,7 +2,7 @@
* Command line handling of dmidecode
* This file is part of the dmidecode project.
*
* Copyright (C) 2005-2008 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2005-2008 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -225,8 +225,9 @@ int parse_command_line(int argc, char * const argv[])
{ "dump", no_argument, NULL, 'u' },
{ "dump-bin", required_argument, NULL, 'B' },
{ "from-dump", required_argument, NULL, 'F' },
{ "no-sysfs", no_argument, NULL, 'S' },
{ "version", no_argument, NULL, 'V' },
{ 0, 0, 0, 0 }
{ NULL, 0, NULL, 0 }
};
while ((option = getopt_long(argc, argv, optstring, longopts, NULL)) != -1)
@ -262,6 +263,9 @@ int parse_command_line(int argc, char * const argv[])
case 'u':
opt.flags |= FLAG_DUMP;
break;
case 'S':
opt.flags |= FLAG_NO_SYSFS;
break;
case 'V':
opt.flags |= FLAG_VERSION;
break;

View File

@ -2,7 +2,7 @@
* Command line handling of dmidecode
* This file is part of the dmidecode project.
*
* Copyright (C) 2005-2008 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2005-2008 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "types.h"
struct string_keyword
{
const char *keyword;
@ -42,6 +44,7 @@ extern struct opt opt;
#define FLAG_QUIET (1 << 3)
#define FLAG_DUMP_BIN (1 << 4)
#define FLAG_FROM_DUMP (1 << 5)
#define FLAG_NO_SYSFS (1 << 6)
int parse_command_line(int argc, char * const argv[]);
void print_help(void);

View File

@ -52,7 +52,7 @@ for a more detailed output.
.B biosdecode
started its life as a part of
.B dmidecode
but as more entry point types were added, if was moved to a different
but as more entry point types were added, it was moved to a different
program.
.SH OPTIONS

View File

@ -25,8 +25,12 @@ and developed by the \s-1DMTF\s0 (Desktop Management Task Force).
As you run it,
.B dmidecode
will try to locate the \s-1DMI\s0 table. If it succeeds, it will then parse
this table and display a list of records like this one:
will try to locate the \s-1DMI\s0 table. It will first try to read the DMI table
from sysfs, and next try reading directly from memory if sysfs access failed.
If
.B dmidecode
succeeds in locating a valid DMI table, it will then parse this table
and display a list of records like this one:
Handle 0x0002, DMI type 2, 8 bytes.
Base Board Information
@ -89,6 +93,13 @@ keywords is printed and
.B dmidecode
exits with an error.
This option cannot be used more than once.
Note: on Linux, most of these strings can alternatively be read directly
from
.BR sysfs ,
typically from files under
.IR /sys/devices/virtual/dmi/id .
Most of these files are even readable by regular users.
.TP
.BR "-t" ", " "--type TYPE"
Only display the entries of type \fBTYPE\fR. \fBTYPE\fR can be either a
@ -119,6 +130,10 @@ later.
Read the DMI data from a binary file previously generated using
\fB--dump-bin\fR.
.TP
.BR " " " " "--no-sysfs"
Do not attempt to read DMI data from sysfs files. This is mainly useful for
debugging.
.TP
.BR "-h" ", " "--help"
Display usage information and exit
.TP
@ -234,6 +249,8 @@ The DMI table is located at offset 0x20.
.SH FILES
.I /dev/mem
.I /sys/firmware/dmi/tables/smbios_entry_point (Linux only)
.I /sys/firmware/dmi/tables/DMI (Linux only)
.SH BUGS
More often than not, information contained in the \s-1DMI\s0 tables is inaccurate,
incomplete or simply wrong.

View File

@ -1,7 +1,7 @@
/*
* Compaq Ownership Tag
*
* Copyright (C) 2003-2005 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2003-2005 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -119,7 +119,7 @@ static int parse_command_line(int argc, char * const argv[])
{ "dev-mem", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ 0, 0, 0, 0 }
{ NULL, 0, NULL, 0 }
};
while ((option = getopt_long(argc, argv, optstring, longopts, NULL)) != -1)

68
util.c
View File

@ -2,7 +2,7 @@
* Common "util" functions
* This file is part of the dmidecode project.
*
* Copyright (C) 2002-2010 Jean Delvare <khali@linux-fr>
* Copyright (C) 2002-2015 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -88,16 +88,71 @@ int checksum(const u8 *buf, size_t len)
return (sum == 0);
}
/*
* Reads all of file, up to max_len bytes.
* A buffer of max_len bytes is allocated by this function, and
* needs to be freed by the caller.
* This provides a similar usage model to mem_chunk()
*
* Returns pointer to buffer of max_len bytes, or NULL on error
*
*/
void *read_file(size_t max_len, const char *filename)
{
int fd;
size_t r2 = 0;
ssize_t r;
u8 *p;
/*
* Don't print error message on missing file, as we will try to read
* files that may or may not be present.
*/
if ((fd = open(filename, O_RDONLY)) == -1)
{
if (errno != ENOENT)
perror(filename);
return(NULL);
}
if ((p = malloc(max_len)) == NULL)
{
perror("malloc");
return NULL;
}
do
{
r = read(fd, p + r2, max_len - r2);
if (r == -1)
{
if (errno != EINTR)
{
close(fd);
perror(filename);
free(p);
return NULL;
}
}
else
r2 += r;
}
while (r != 0);
close(fd);
return p;
}
/*
* Copy a physical memory chunk into a memory buffer.
* This function allocates memory.
*/
void *mem_chunk(size_t base, size_t len, const char *devmem)
void *mem_chunk(off_t base, size_t len, const char *devmem)
{
void *p;
int fd;
#ifdef USE_MMAP
size_t mmoffset;
off_t mmoffset;
void *mmp;
#endif
@ -124,7 +179,7 @@ void *mem_chunk(size_t base, size_t len, const char *devmem)
* but to workaround problems many people encountered when trying
* to read from /dev/mem using regular read() calls.
*/
mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
mmp = mmap(NULL, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
if (mmp == MAP_FAILED)
goto try_read;
@ -138,9 +193,8 @@ void *mem_chunk(size_t base, size_t len, const char *devmem)
goto out;
#endif /* USE_MMAP */
try_read:
#endif /* USE_MMAP */
if (lseek(fd, base, SEEK_SET) == -1)
{
fprintf(stderr, "%s: ", devmem);
@ -155,7 +209,9 @@ try_read:
return NULL;
}
#ifdef USE_MMAP
out:
#endif
if (close(fd) == -1)
perror(devmem);

5
util.h
View File

@ -1,7 +1,7 @@
/*
* This file is part of the dmidecode project.
*
* Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2003-2015 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -25,6 +25,7 @@
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
int checksum(const u8 *buf, size_t len);
void *mem_chunk(size_t base, size_t len, const char *devmem);
void *read_file(size_t len, const char *filename);
void *mem_chunk(off_t base, size_t len, const char *devmem);
int write_dump(size_t base, size_t len, const void *data, const char *dumpfile, int add);
u64 u64_range(u64 start, u64 end);

View File

@ -1 +1 @@
#define VERSION "2.12"
#define VERSION "3.0"

View File

@ -1,7 +1,7 @@
/*
* IBM Vital Product Data decoder
*
* Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2003-2007 Jean Delvare <jdelvare@suse.de>
*
* 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

View File

@ -2,7 +2,7 @@
* Command line handling of vpddecode
* This file is part of the dmidecode project.
*
* Copyright (C) 2005-2007 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2005-2007 Jean Delvare <jdelvare@suse.de>
*
* 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
@ -99,7 +99,7 @@ int parse_command_line(int argc, char * const argv[])
{ "string", required_argument, NULL, 's' },
{ "dump", no_argument, NULL, 'u' },
{ "version", no_argument, NULL, 'V' },
{ 0, 0, 0, 0 }
{ NULL, 0, NULL, 0 }
};
while ((option = getopt_long(argc, argv, optstring, longopts, NULL)) != -1)

View File

@ -2,7 +2,7 @@
* Command line handling of vpddecode
* This file is part of the dmidecode project.
*
* Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2005-2006 Jean Delvare <jdelvare@suse.de>
*
* 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