From d6c691f310b4a5f16b7e2a550ef8b0b006352c10 Mon Sep 17 00:00:00 2001 From: khali Date: Mon, 27 Apr 2015 08:12:59 +0000 Subject: dmidecode: Preliminary support for 64-bit entry point Add preliminary support for the new _SM3_ 64-bit entry point defined in the SMBIOS specification version 3.0.0. 64-bit addresses are not actually supported yet, nor tables with size over 16-bit. --- CHANGELOG | 5 ++++ dmidecode.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 282a89e..5e207e7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +2015-04-27 Jean Delvare + + * dmidecode.c: Add preliminary support for the new _SM3_ 64-bit + entry point defined in the SMBIOS specification version 3.0.0. + 2015-04-21 Roy Franz * util.c, util.h: Add utility function read_file, which reads an diff --git a/dmidecode.c b/dmidecode.c index 6321b84..39f8ec7 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -2,7 +2,7 @@ * DMI Decode * * Copyright (C) 2000-2002 Alan Cox - * Copyright (C) 2002-2014 Jean Delvare + * Copyright (C) 2002-2015 Jean Delvare * * 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 @@ -4360,8 +4360,9 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, { if (opt.type == NULL) { - printf("%u structures occupying %u bytes.\n", - num, len); + if (num) + printf("%u structures occupying %u bytes.\n", + num, len); if (!(opt.flags & FLAG_FROM_DUMP)) printf("Table at 0x%08X.\n", base); } @@ -4388,7 +4389,8 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, } 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; @@ -4454,12 +4456,17 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, i++; } + /* + * 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 (i != num) + if (num && i != num) printf("Wrong DMI structures count: %d announced, " "only %d decoded.\n", num, i); - if (data - buf != len) + if (data - buf > len + || (num && data - buf < len)) printf("Wrong DMI structures length: %d bytes " "announced, structures occupy %d bytes.\n", len, (unsigned int)(data - buf)); @@ -4483,6 +4490,59 @@ static void overwrite_dmi_address(u8 *buf) buf[0x0B] = 0; } +/* 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) + { + fprintf(stderr, "64-bit addresses not supported, sorry.\n"); + return 0; + } + + dmi_table(offset.l, WORD(buf + 0x0C), 0, ver, devmem, flags); + + 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; @@ -4659,7 +4719,12 @@ int main(int argc, char * const argv[]) goto exit_free; } - if (memcmp(buf, "_SM_", 4) == 0) + if (memcmp(buf, "_SM3_", 5) == 0) + { + if (smbios3_decode(buf, opt.dumpfile, 0)) + found++; + } + else if (memcmp(buf, "_SM_", 4) == 0) { if (smbios_decode(buf, opt.dumpfile, 0)) found++; @@ -4684,8 +4749,8 @@ int main(int argc, char * const argv[]) printf("Getting SMBIOS data from sysfs.\n"); if (memcmp(buf, "_SM3_", 5) == 0) { - if (!(opt.flags & FLAG_QUIET)) - printf("SMBIOS v3 64-bit entry point found, but not supported.\n"); + if (smbios3_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET)) + found++; } else if (memcmp(buf, "_SM_", 4) == 0) { @@ -4740,7 +4805,15 @@ 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 (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)) { -- cgit v1.2.1