This series adds dmi sysfs support for dmidecode util. It's needed when access to /dev/mem is forbidden. In this case to get needed information the dmi sysfs can be used.
The GIT mirror of CVS dmidecode; https://git.linaro.org/people/ivan.khoronzhuk/dmidecode.git based on master
Ivan Khoronzhuk (4): dmidecode: use common function to get SMBIOS version dmidecode: use common function to put SMBIOS in dumpfile dmidecode: move memory map function from dmi_decode dmidecode: add dmi sysfs support
Makefile | 2 +- dmidecode.c | 186 ++++++++++++++++++++++++++++++++++++++++-------------------- version.h | 2 +- 3 files changed, 127 insertions(+), 63 deletions(-)
Move SMBIOS version code in separate function as it's more readable and can be used by others when it's required. In paticular, it can be used when dmi sysfs support is added.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org --- dmidecode.c | 59 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 22 deletions(-)
diff --git a/dmidecode.c b/dmidecode.c index a5304a7..c4b4fd1 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -4277,6 +4277,42 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) printf("\n"); }
+/** + * get_smbios_version - get SMBIOS version + * @smbios: pointer on SMBIOS entry point table + * + * Returns SMBIOS version + */ +static u16 get_smbios_version(unsigned char *smbios) +{ + u16 ver; + + ver = (smbios[0x06] << 8) + smbios[0x07]; + + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (ver) { + case 0x021F: + case 0x0221: + if (!(opt.flags & FLAG_QUIET)) + printf("SMBIOS version fixup (2.%d -> 2.%d).\n", + ver & 0xFF, 3); + ver = 0x0203; + break; + case 0x0233: + if (!(opt.flags & FLAG_QUIET)) + printf("SMBIOS version fixup (2.%d -> 2.%d).\n", + 51, 6); + ver = 0x0206; + break; + } + + if (!(opt.flags & FLAG_QUIET)) + printf("SMBIOS %u.%u present.\n", + ver >> 8, ver & 0xFF); + + return ver; +} + static void to_dmi_header(struct dmi_header *h, u8 *data) { h->type = data[0]; @@ -4453,7 +4489,6 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem) free(buf); }
- /* * Build a crafted entry point with table address hard-coded to 32, * as this is where we will put it in the output file. We adjust the @@ -4477,27 +4512,7 @@ static int smbios_decode(u8 *buf, const char *devmem) || !checksum(buf + 0x10, 0x0F)) return 0;
- ver = (buf[0x06] << 8) + buf[0x07]; - /* Some BIOS report weird SMBIOS version, fix that up */ - switch (ver) - { - case 0x021F: - case 0x0221: - if (!(opt.flags & FLAG_QUIET)) - printf("SMBIOS version fixup (2.%d -> 2.%d).\n", - ver & 0xFF, 3); - ver = 0x0203; - break; - case 0x0233: - if (!(opt.flags & FLAG_QUIET)) - printf("SMBIOS version fixup (2.%d -> 2.%d).\n", - 51, 6); - ver = 0x0206; - break; - } - if (!(opt.flags & FLAG_QUIET)) - printf("SMBIOS %u.%u present.\n", - ver >> 8, ver & 0xFF); + ver = get_smbios_version(buf);
dmi_table(DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C), ver, devmem);
It's needed in order to generalize code before adding dmi sysfs support. It' more convenient to hold common code in separate function.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org --- dmidecode.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/dmidecode.c b/dmidecode.c index c4b4fd1..4e4a82f 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -4503,6 +4503,24 @@ static void overwrite_dmi_address(u8 *buf) buf[0x0B] = 0; }
+/** + * smbios_in_dumpfile - put SMBIOS entry table in dump file + * @smbios: pointer on SMBIOS entry table + */ +static void smbios_in_dumpfile(unsigned char *smbios) +{ + u8 crafted[32]; + + memcpy(crafted, smbios, 32); + overwrite_dmi_address(crafted + 0x10); + + if (!(opt.flags & FLAG_QUIET)) + printf("# Writing %d bytes to %s.\n", crafted[0x05], + opt.dumpfile); + + write_dump(0, crafted[0x05], crafted, opt.dumpfile, 1); +} + static int smbios_decode(u8 *buf, const char *devmem) { u16 ver; @@ -4518,17 +4536,7 @@ static int smbios_decode(u8 *buf, const char *devmem) ver, devmem);
if (opt.flags & FLAG_DUMP_BIN) - { - u8 crafted[32]; - - memcpy(crafted, buf, 32); - overwrite_dmi_address(crafted + 0x10); - - if (!(opt.flags & FLAG_QUIET)) - printf("# Writing %d bytes to %s.\n", crafted[0x05], - opt.dumpfile); - write_dump(0, crafted[0x05], crafted, opt.dumpfile, 1); - } + smbios_in_dumpfile(buf);
return 1; }
There is no reason to allocate/copy/free memory for dmi_table inside function. It's more convenient to do it outside. In this case we can use dmi_decode function with already allocated memory like in case with dmifs library. The same is for dmi_table_dump().
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org --- dmidecode.c | 70 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 29 deletions(-)
diff --git a/dmidecode.c b/dmidecode.c index 4e4a82f..2fedddc 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -4351,25 +4351,15 @@ 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(u8 *buf, u16 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(u32 base, u8 *buf, u16 len, u16 num, u16 ver) { - u8 *buf; u8 *data; int i = 0;
@@ -4382,7 +4372,7 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem)
if (opt.flags & FLAG_DUMP_BIN) { - dmi_table_dump(base, len, devmem); + dmi_table_dump(buf, len); return; }
@@ -4398,16 +4388,6 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem) 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 */ { @@ -4485,8 +4465,6 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem) "announced, structures occupy %d bytes.\n", len, (unsigned int)(data - buf)); } - - free(buf); }
/* @@ -4524,6 +4502,9 @@ static void smbios_in_dumpfile(unsigned char *smbios) static int smbios_decode(u8 *buf, const char *devmem) { u16 ver; + u16 len; + u32 base; + u8 *dmibuf;
if (!checksum(buf, buf[0x05]) || memcmp(buf + 0x10, "_DMI_", 5) != 0 @@ -4532,8 +4513,21 @@ static int smbios_decode(u8 *buf, const char *devmem)
ver = get_smbios_version(buf);
- dmi_table(DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C), - ver, devmem); + base = DWORD(buf + 0x18); + len = WORD(buf + 0x16); + dmibuf = mem_chunk(base, len, devmem); + if (!dmibuf) { + fprintf(stderr, "Table is unreachable, sorry." +#ifndef USE_MMAP + " Try compiling dmidecode with -DUSE_MMAP." +#endif + "\n"); + return 0; + } + + dmi_table(base, dmibuf, len, WORD(buf + 0x1C), ver); + + free(dmibuf);
if (opt.flags & FLAG_DUMP_BIN) smbios_in_dumpfile(buf); @@ -4543,6 +4537,10 @@ static int smbios_decode(u8 *buf, const char *devmem)
static int legacy_decode(u8 *buf, const char *devmem) { + u16 len; + u32 base; + u8 *dmibuf; + if (!checksum(buf, 0x0F)) return 0;
@@ -4550,8 +4548,22 @@ static int legacy_decode(u8 *buf, const char *devmem) printf("Legacy DMI %u.%u present.\n", 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); + len = WORD(buf + 0x06); + base = DWORD(buf + 0x08); + dmibuf = mem_chunk(base, len, devmem); + if (!dmibuf) { + fprintf(stderr, "Table is unreachable, sorry." +#ifndef USE_MMAP + " Try compiling dmidecode with -DUSE_MMAP." +#endif + "\n"); + return 0; + } + + dmi_table(base, dmibuf, len, WORD(buf + 0x0C), + ((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F)); + + free(dmibuf);
if (opt.flags & FLAG_DUMP_BIN) {
For working with newly introduced dmi sysfs the dmifs library was used. It's needed by the systems that cannot use /dev/mem to access hardware addresses and as result cannot read dmi table. So another, more correct approach, can be used, it's to read information from dmi sysfs.
Currently we can use libdmifs library for that.
Reported-by: Leif Lindholm leif.lindholm@linaro.org Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org --- Makefile | 2 +- dmidecode.c | 31 ++++++++++++++++++++++++++++++- version.h | 2 +- 3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile index 66c24d5..e3f5c49 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ all : $(PROGRAMS) #
dmidecode : dmidecode.o dmiopt.o dmioem.o util.o - $(CC) $(LDFLAGS) dmidecode.o dmiopt.o dmioem.o util.o -o $@ + $(CC) $(LDFLAGS) dmidecode.o dmiopt.o dmioem.o util.o -ldmifs -o $@
biosdecode : biosdecode.o util.o $(CC) $(LDFLAGS) biosdecode.o util.o -o $@ diff --git a/dmidecode.c b/dmidecode.c index 2fedddc..7d3c133 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -57,6 +57,7 @@ #include <strings.h> #include <stdlib.h> #include <unistd.h> +#include <libdmifs.h>
#include "version.h" #include "config.h" @@ -4535,6 +4536,28 @@ static int smbios_decode(u8 *buf, const char *devmem) return 1; }
+static void dmifs_smbios_decode(void) +{ + u16 ver; + u8 *smbios; + struct dmi_table *dt; + + dt = dmi_get_table(); + if (!dt) + return; + + smbios = dt->smbios; + + ver = get_smbios_version(dt->smbios); + dmi_table(DWORD(smbios + 0x18), dmi_get_raw_data(dt->dmi_list), + WORD(smbios + 0x16), WORD(smbios + 0x1C), ver); + + if (opt.flags & FLAG_DUMP_BIN) + smbios_in_dumpfile(dt->smbios); + + dmi_put_table(dt); +} + static int legacy_decode(u8 *buf, const char *devmem) { u16 len; @@ -4692,7 +4715,13 @@ int main(int argc, char * const argv[]) goto done; }
- /* First try EFI (ia64, Intel-based Mac) */ + /* First try dmi sysfs */ + if (dmifs_is_exist()) { + dmifs_smbios_decode(); + goto exit_free; + } + + /* Second try EFI (ia64, Intel-based Mac) */ efi = address_from_efi(&fp); switch (efi) { diff --git a/version.h b/version.h index 140d334..ce7ffaf 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define VERSION "2.12" +#define VERSION "2.12-dmifs"