From 3ea65822f64fbc1693c7044344db6a34bc23cadc Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 19 2015 15:38:06 +0000 Subject: import dmidecode-2.12-9.el7 --- diff --git a/SOURCES/Add-libdmifs-from-Linaro.patch b/SOURCES/Add-libdmifs-from-Linaro.patch new file mode 100644 index 0000000..04a3394 --- /dev/null +++ b/SOURCES/Add-libdmifs-from-Linaro.patch @@ -0,0 +1,773 @@ +From a909f4e024bdb5b0a8ea11f9fde62a9c74438983 Mon Sep 17 00:00:00 2001 +From: Mark Salter +Date: Mon, 26 Jan 2015 12:42:42 -0500 +Subject: [PATCH] Add libdmifs from Linaro + +This library module comes from: + + git://git.linaro.org/people/ivan.khoronzhuk/libdmifs.git + +For now, it is being built in rather than as a shared lib. + +Signed-off-by: Mark Salter +--- + Makefile | 7 +- + dmidecode.c | 2 +- + libdmifs.c | 644 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + libdmifs.h | 56 ++++++ + 4 files changed, 706 insertions(+), 3 deletions(-) + create mode 100644 libdmifs.c + create mode 100644 libdmifs.h + +diff --git a/Makefile b/Makefile +index d8457da..805d08e 100644 +--- a/Makefile ++++ b/Makefile +@@ -57,8 +57,8 @@ all : $(PROGRAMS) + # Programs + # + +-dmidecode : dmidecode.o dmiopt.o dmioem.o util.o +- $(CC) $(LDFLAGS) dmidecode.o dmiopt.o dmioem.o util.o -ldmifs -o $@ ++dmidecode : dmidecode.o dmiopt.o dmioem.o util.o libdmifs.o ++ $(CC) $(LDFLAGS) dmidecode.o dmiopt.o dmioem.o util.o libdmifs.o -o $@ + + biosdecode : biosdecode.o util.o + $(CC) $(LDFLAGS) biosdecode.o util.o -o $@ +@@ -98,6 +98,9 @@ vpdopt.o : vpdopt.c config.h util.h vpdopt.h + util.o : util.c types.h util.h config.h + $(CC) $(CFLAGS) -c $< -o $@ + ++libdmifs.o: libdmifs.c libdmifs.h ++ $(CC) $(CFLAGS) -c $< -o $@ ++ + # + # Commands + # +diff --git a/dmidecode.c b/dmidecode.c +index 4663cc6..fee3af1 100644 +--- a/dmidecode.c ++++ b/dmidecode.c +@@ -57,7 +57,7 @@ + #include + #include + #include +-#include ++#include "libdmifs.h" + + #include "version.h" + #include "config.h" +diff --git a/libdmifs.c b/libdmifs.c +new file mode 100644 +index 0000000..9ad2414 +--- /dev/null ++++ b/libdmifs.c +@@ -0,0 +1,644 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "libdmifs.h" ++ ++/* ++ * maximum number of entries can be calculated based on maximum table ++ * size and minimum size of structure (4 + 2 NULL symbols). ++ */ ++#define MIN_HEADER_SIZE 4 ++#define MIN_DMI_STRUCT_SIZE (MIN_HEADER_SIZE + 2) ++#define MAX_ENTRIES_COUNT (~0U/MIN_DMI_STRUCT_SIZE) ++#define POSITION_ERR (MAX_ENTRIES_COUNT + 1) ++ ++/* list of dmi entries */ ++ ++/** ++ * dmilist_insert - inserts new dmi entry to ordered dmi_list, ++ * sorting according to the position in dmi table ++ * @dmi_list: pointer on pointer to the first dmi entry in the list ++ * @new: new entry to be inserted in the ordered dmi_list. ++ * ++ * Returns 0 on success and -1 when error. ++ */ ++static int dmilist_insert(struct dmi_entry **dmi_list, struct dmi_entry *new) ++{ ++ struct dmi_entry *old; ++ struct dmi_entry *cur = *dmi_list; ++ ++ if (!cur) { ++ new->next = NULL; ++ *dmi_list = new; ++ return 0; ++ } ++ ++ old = NULL; ++ while (cur) { ++ if (cur->position < new->position) { ++ old = cur; ++ cur = cur->next; ++ continue; ++ } else if (cur->position > new->position) { ++ if (old) { ++ old->next = new; ++ new->next = cur; ++ return 0; ++ } ++ new->next = cur; ++ *dmi_list = new; ++ return 0; ++ } ++ ++ fprintf(stderr, "dmitable is broken"); ++ return -1; ++ } ++ ++ old->next = new; ++ new->next = NULL; ++ ++ return 0; ++} ++ ++static void dmilist_free_entry(struct dmi_entry *entry) ++{ ++ free(entry->d_name); ++ free(entry); ++} ++ ++static void dmilist_free(struct dmi_entry **dmi_list) ++{ ++ struct dmi_entry *old; ++ struct dmi_entry *cur = *dmi_list; ++ ++ if (!cur) ++ return; ++ ++ while (cur) { ++ old = cur; ++ cur = cur->next; ++ dmilist_free_entry(old); ++ } ++ ++ *dmi_list = NULL; ++} ++ ++/* dmi sysfs attribute reading */ ++ ++/** ++ * dmi_get_smbios - get smbios data ++ * @smbios: pointer on array to read raw smbios table in ++ * ++ * Returns read data size in bytes on success and 0 when error. ++ */ ++static int dmi_get_smbios(unsigned char *smbios) ++{ ++ FILE *file; ++ int count = 0; ++ enum {SMBIOS_SIZE = 32}; ++ ++ file = fopen("/sys/firmware/dmi/smbios_raw_header", "rb"); ++ if (!file) { ++ fprintf(stderr, "no \"smbios\" sysfs entry\n"); ++ return count; ++ } ++ ++ count = fread(smbios, sizeof(char), SMBIOS_SIZE, file); ++ if (!feof(file)) { ++ fprintf(stderr, "Error while reading a file\n"); ++ goto err; ++ } ++ ++err: ++ fclose(file); ++ return count; ++} ++ ++/** ++ * read_position - reads position of dmi entry as it's inside dmi table ++ * @dir: appropriate directory of dmi entry position ++ * ++ * returns dmi entry position in dmi table on success and POSITION_ERR when ++ * error occurred. ++ */ ++static unsigned int read_position(char *dir) ++{ ++ FILE *file; ++ char pos[10]; ++ unsigned int position; ++ ++ file = fopen("position", "r"); ++ if (!file) { ++ fprintf(stderr, "no \"position\" in \"%s\"\n", dir); ++ return POSITION_ERR; ++ } ++ ++ if (!fgets(pos, 10, file) && ferror(file)) { ++ fclose(file); ++ fprintf(stderr, "Error while working with \"position\" in %s\n", ++ dir); ++ return POSITION_ERR; ++ } ++ ++ fclose(file); ++ ++ position = strtoul(pos, NULL, 0); ++ /* position can't be more than number of entries */ ++ if (position > MAX_ENTRIES_COUNT) { ++ fprintf(stderr, "position is incorrect %d\n", position); ++ return POSITION_ERR; ++ } ++ ++ return position; ++} ++ ++/** ++ * read_raw - reads raw data of dmi entry ++ * @dir: appropriate directory of dmi entry position ++ * @data: pointer to the array where raw data will be read ++ * @max_size: maximum data size possible to read ++ * ++ * Returns read data size in bytes on success and 0 when error. ++ * In the same time return value < 6 is also error as at least header is ++ * 4 bytes in size + 2 NULLs. ++ */ ++static unsigned int read_raw(char *dir, ++ unsigned char *buf, unsigned int max_size) ++{ ++ FILE *file; ++ unsigned int count; ++ unsigned int size = 0; ++ ++ file = fopen("raw", "rb"); ++ if (!file) { ++ fprintf(stderr, "no \"raw\" in \"%s\"\n", dir); ++ return 0; ++ } ++ ++ count = fread(buf, sizeof(char), max_size, file); ++ if (!feof(file)) { ++ fprintf(stderr, "Error while reading \"raw\" file\n"); ++ goto err; ++ } ++ ++ if (count < MIN_DMI_STRUCT_SIZE) { ++ fprintf(stderr, "DMI header cannot be less than 4 bytes"); ++ goto err; ++ } ++ ++ /* check if structure is correct */ ++ if (buf[count - 1] || buf[count - 2]) { ++ fprintf(stderr, "Bad raw file of \"%s\"\n", dir); ++ goto err; ++ } ++ ++ size = count; ++err: ++ fclose(file); ++ return size; ++} ++ ++/** ++ * add_entry_to_dmilist - generates empty dmi entry and places it to dmi list ++ * @dmi_list: dmi list where allocated dmi entry will be put ++ * @dir: the directory name appropriate to dmi entry ++ * ++ * Returns 0 on success and -1 on error ++ */ ++static int add_entry_to_dmilist(struct dmi_entry **dmi_list, char *dir) ++{ ++ char *dir_name; ++ unsigned int position; ++ struct dmi_entry *entry; ++ ++ position = read_position(dir); ++ if (position == POSITION_ERR) { ++ fprintf(stderr, ++ "Cannot read smbios position for \"%s\"\n", dir); ++ return -1; ++ } ++ ++ dir_name = malloc(strlen(dir) + 1); ++ if (!dir_name) { ++ fprintf(stderr, "Cannot allocate memory for dir\n"); ++ return -1; ++ } ++ strcpy(dir_name, dir); ++ ++ entry = malloc(sizeof(struct dmi_entry)); ++ if (!entry) { ++ fprintf(stderr, "Cannot allocate memory for dmi struct\n"); ++ free(dir_name); ++ return -1; ++ } ++ ++ entry->d_name = dir_name; ++ entry->position = position; ++ ++ if (dmilist_insert(dmi_list, entry)) { ++ fprintf(stderr, "Cannot insert new dmientry in the list"); ++ dmilist_free_entry(entry); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * gather_entry_data - reads data from given dmi directory raw attribute end ++ * binds it with given dmi entry. ++ * @entry: dmi entry for what data will be read ++ * @rdata: pointer to array where data will be read in ++ * @max_size: maximum data size possible to read for now ++ * ++ * Returns read raw data size including two NULLs at the end ++ * On error returns 0 ++ */ ++static unsigned int gather_entry_data(struct dmi_entry *entry, ++ unsigned char *rdata, ++ unsigned int max_size) ++{ ++ unsigned int dsize; ++ ++ dsize = read_raw(entry->d_name, rdata, max_size); ++ if (dsize < MIN_DMI_STRUCT_SIZE) { ++ fprintf(stderr, ++ "Cannot read DMI raw for \"%s\"\n", entry->d_name); ++ return 0; ++ } ++ ++ entry->h.data = rdata; ++ entry->h.type = rdata[0]; ++ entry->h.length = rdata[1]; ++ entry->h.handle = le16toh(rdata[2] | (rdata[3] << 8)); ++ ++ return dsize; ++} ++ ++/** ++ * populate_dmilist - populate dmi entries in dmi list by raw data ++ * @dmi_list: dmi list with dmi entries to be populated ++ * @max_size: supposed size of whole dmi table. Can be taken from ++ * table SMBIOS entry. ++ * ++ * Returns dmi raw table size on success, otherwise 0. ++ */ ++static unsigned int populate_dmilist(struct dmi_entry *dmi_list, ++ unsigned int max_size) ++{ ++ unsigned int dsize; ++ struct dmi_entry *entry; ++ unsigned char *raw_table, *tp; ++ ++ /* allocate memory for whole dmi table */ ++ raw_table = malloc(max_size); ++ if (!raw_table) { ++ fprintf(stderr, "Cannot allocate memory for DMI table\n"); ++ return 0; ++ } ++ ++ tp = raw_table; ++ for (entry = dmi_list; entry; entry = entry->next) { ++ if (max_size < MIN_DMI_STRUCT_SIZE) { ++ fprintf(stderr, "Max size of DMI table is reached\n"); ++ goto err; ++ } ++ ++ if (chdir(entry->d_name)) { ++ fprintf(stderr, "Cannot change dir to %s\n", ++ entry->d_name); ++ goto err; ++ } ++ ++ dsize = gather_entry_data(entry, tp, max_size); ++ if (dsize < MIN_DMI_STRUCT_SIZE) { ++ if (chdir("../")) ++ fprintf(stderr, "Cannot change dir to ../\n"); ++ goto err; ++ } ++ ++ if (chdir("../")) { ++ fprintf(stderr, "Cannot change dir to ../\n"); ++ goto err; ++ } ++ ++ tp += dsize; ++ max_size -= dsize; ++ } ++ ++ return tp - raw_table; ++ ++err: ++ fprintf(stderr, "Cannot gather data for dir %s\n", entry->d_name); ++ free(raw_table); ++ return 0; ++} ++ ++/** ++ * create_dmilist - creates ordered linked dmi list with empty entries. ++ * The empty entry is entry with empty dmi header data ++ * @entry_count: pointer to dmi entry count to be updated while creating. ++ * ++ * On success returns dmi_entry pointer on first entry in the list ++ * Otherwise returns NULL. Updates entry_count. ++ */ ++static struct dmi_entry *create_dmilist(unsigned int *entry_count) ++{ ++ DIR *dmi; ++ char *cwd; ++ void *ret = NULL; ++ struct dirent *dir_entry; ++ struct dmi_entry *dmi_list = NULL; ++ ++ dmi = opendir("."); ++ if (!dmi) { ++ fprintf(stderr, "Cannot open cwd\n"); ++ return ret; ++ } ++ ++ *entry_count = 0; ++ readdir(dmi); /* miss "." */ ++ readdir(dmi); /* miss ".." */ ++ while ((dir_entry = readdir(dmi))) { ++ if (chdir(dir_entry->d_name)) { ++ fprintf(stderr, "Cannot change dir to %s\n", ++ dir_entry->d_name); ++ goto err; ++ } ++ ++ if (add_entry_to_dmilist(&dmi_list, dir_entry->d_name)) { ++ fprintf(stderr, "Cannot add \"%s\" to dmi_list\n", ++ dir_entry->d_name); ++ if (chdir("../")) ++ fprintf(stderr, "Cannot change dir to ../\n"); ++ goto err; ++ } ++ ++ if (chdir("../")) { ++ fprintf(stderr, "Cannot change dir to ../\n"); ++ goto err; ++ } ++ ++ (*entry_count)++; ++ } ++ /* now dmilist is complete */ ++ ret = dmi_list; ++err: ++ if (closedir(dmi)) { ++ cwd = getcwd(NULL, 1024); ++ fprintf(stderr, "Cannot close %s", cwd); ++ free(cwd); ++ ret = NULL; ++ } ++ ++ if (ret == dmi_list) ++ return dmi_list; ++ ++ dmilist_free(&dmi_list); ++ return ret; ++} ++ ++/** ++ * dmi_put_dmilist - frees dmi list alloted by dmi_get_dmilist() ++ * @dmi_list: dmi list to be free ++ * ++ * Returns 0 on success, -1 otherwise. ++ */ ++static int dmi_put_dmilist(struct dmi_entry *dmi_list) ++{ ++ unsigned char *raw_table; ++ ++ if (!dmi_list) { ++ fprintf(stderr, "Cannot free dmi_list NULL pointer\n"); ++ return -1; ++ } ++ ++ raw_table = dmi_list->h.data; ++ if (!raw_table) { ++ fprintf(stderr, "Cannot free raw_table NULL pointer\n"); ++ return -1; ++ } ++ ++ free(raw_table); ++ dmilist_free(&dmi_list); ++ ++ return 0; ++} ++ ++/** ++ * dmi_get_dmilist - creates ordered dmi list with all dmi entries present ++ * on dmi sysfs. All raw entries data are situated contiguously in the RAM. ++ * @entry_count: read count of dmi list entries, that's dmi structs in dmi table ++ * @dmi_size: read whole size in bytes of dmi table. ++ * @max_size: supposed size of whole dmi table. Can be taken from SMBIOS ++ * entry point table. ++ * ++ * Returns a pointer to first dmi entry in the list. When list is no longer ++ * needed it has to be freed with dmi_put_dmilist(). ++ * In case of error returns NULL. ++ */ ++static struct dmi_entry *dmi_get_dmilist(unsigned int *entry_count, ++ unsigned int *dmi_size, ++ unsigned int max_size) ++{ ++ char *cwd; ++ struct dmi_entry *dmi_list = NULL; ++ char root[] = "/sys/firmware/dmi/entries/"; ++ ++ cwd = getcwd(NULL, 1024); ++ if (!cwd) { ++ fprintf(stderr, "Cannot get current directory\n"); ++ return NULL; ++ } ++ ++ if (chdir(root)) { ++ fprintf(stderr, "Cannot change dir to %s\n", root); ++ goto err; ++ } ++ ++ /* ++ * Create dmi_list then fill it in. Do this in two steps to ++ * have contiguous raw data for whole table ++ */ ++ dmi_list = create_dmilist(entry_count); ++ if (!dmi_list) { ++ fprintf(stderr, "Cannot create dmi_list\n"); ++ goto err; ++ } ++ ++ *dmi_size = populate_dmilist(dmi_list, max_size); ++ if (*dmi_size == 0) { ++ dmilist_free(&dmi_list); ++ fprintf(stderr, "Cannot fill in dmi_list by data from raw\n"); ++ goto err; ++ } ++ ++err: ++ if (chdir(cwd)) { ++ fprintf(stderr, "Cannot change root dir to %s\n", cwd); ++ dmi_put_dmilist(dmi_list); ++ dmi_list = NULL; ++ } ++ ++ free(cwd); ++ return dmi_list; ++} ++ ++static int dmi_checksum(unsigned char *buf, unsigned char len) ++{ ++ int i; ++ unsigned char sum = 0; ++ ++ for (i = 0; i < len; i++) ++ sum += buf[i]; ++ ++ return sum == 0; ++} ++ ++/** ++ * dmi_get_expected_size - read dmi table size from SMBIOS entry point table. ++ * Verify SMBIOS entry point table checksum. ++ * ++ * Returns dmi table size read from SMBIOS entry point table. Return 0 on error. ++ */ ++static unsigned int dmi_get_expected_size(unsigned char *smbios) ++{ ++ if (!memcmp(smbios, "_SM3_", 5) && ++ dmi_checksum(smbios, smbios[0x06])) ++ return le32toh(smbios[0x0C] | (smbios[0x0D] << 8) | ++ (smbios[0x0E] << 16) | (smbios[0x0F] << 24)); ++ else if (!memcmp(smbios, "_SM_", 4) && ++ dmi_checksum(smbios, smbios[0x05]) && ++ dmi_checksum(smbios + 0x10, 0x0F)) ++ return le16toh(smbios[0x16] | (smbios[0x17] << 8)); ++ else if (!memcmp(smbios, "_DMI_", 5) && ++ dmi_checksum(smbios, 0x0F)) ++ return le16toh(smbios[0x06] | (smbios[0x07] << 8)); ++ ++ return 0; ++} ++ ++/* API */ ++ ++/** ++ * dmi_get_table - allocate dmi table ++ * ++ * Returns pointer on allocated dmi_table struct on success, ++ * otherwise returns NULL. When table is not needed it has to be ++ * put by dmi_put_table. ++ */ ++struct dmi_table *dmi_get_table(void) ++{ ++ struct dmi_table *dt; ++ unsigned int max_dmisize; ++ ++ dt = malloc(sizeof(struct dmi_table)); ++ ++ if (!dmi_get_smbios(dt->smbios)) ++ goto err; ++ ++ max_dmisize = dmi_get_expected_size(dt->smbios); ++ if (max_dmisize < MIN_DMI_STRUCT_SIZE) { ++ fprintf(stderr, "SMBIOS entry point is incorrect\n"); ++ goto err; ++ } ++ ++ dt->dmi_list = dmi_get_dmilist(&dt->dmi_count, ++ &dt->dmi_size, max_dmisize + 1); ++ if (!dt->dmi_list) ++ goto err; ++ ++ return dt; ++ ++err: ++ free(dt); ++ return NULL; ++} ++ ++/** ++ * dmi_put_table - used in pair with dmi_get_dmitable ++ * @dt: dmi table pointer taken by dmi_get_table ++ */ ++int dmi_put_table(struct dmi_table *dt) ++{ ++ int ret = -1; ++ ++ if (!dt) { ++ fprintf(stderr, "pointer for DMI table is incorrect\n"); ++ return ret; ++ } ++ ++ ret = dmi_put_dmilist(dt->dmi_list); ++ free(dt); ++ ++ return ret; ++} ++ ++/** ++ * dmi_get_raw_data - give a pointer to raw dmi table, all raw dmi entries are ++ * contiguously situated within this memory in original right order. ++ * @dmi_list: dmi list only taken by dmi_get_dmilist ++ */ ++void *dmi_get_raw_data(struct dmi_entry *dmi_list) ++{ ++ return dmi_list->h.data; ++} ++ ++/** ++ * dmi_get_entry_by_handle - searches an entry in dmi list by given handle ++ * @dmi_list: dmi list to search for ++ * @handle: handle to find entry with ++ * ++ * Returns entry with given handle on success and NULL otherwise ++ */ ++struct dmi_entry *dmi_get_entry_by_handle(struct dmi_entry *dmi_list, ++ int handle) ++{ ++ struct dmi_entry *entry; ++ ++ for (entry = dmi_list; entry; entry = entry->next) ++ if (handle == entry->h.handle) ++ return entry; ++ ++ return NULL; ++} ++ ++/** ++ * dmi_get_next_entry_by_type - searches a next entry in dmi list by type ++ * @dmi_entry: the dmi_entry in dmi list to search beginnig with ++ * @type: type of dmi entry to find ++ */ ++struct dmi_entry *dmi_get_next_entry_by_type(struct dmi_entry *dmi_entry, ++ unsigned char type) ++{ ++ struct dmi_entry *entry; ++ ++ for (entry = dmi_entry->next; entry; entry = entry->next) ++ if (type == entry->h.type) ++ return entry; ++ ++ return NULL; ++} ++ ++/** ++ * dmifs_is_exist - checks if dmi sysfs exists ++ * ++ * Returns 1 on success and 0 if no ++ */ ++int dmifs_is_exist(void) ++{ ++ int ret; ++ char dmi_cat[] = "/sys/firmware/dmi/entries/"; ++ DIR *dmi_dir = opendir(dmi_cat); ++ ++ ret = dmi_dir ? 1 : 0; ++ ++ if (closedir(dmi_dir)) ++ fprintf(stderr, "Cannot close %s", dmi_cat); ++ ++ return ret; ++} +diff --git a/libdmifs.h b/libdmifs.h +new file mode 100644 +index 0000000..218d07f +--- /dev/null ++++ b/libdmifs.h +@@ -0,0 +1,56 @@ ++#ifndef LIBDMIFS_H ++#define LIBDMIFS_H ++ ++/** ++ * dmi_hdata - information of dmi entry header ++ * type: type of dmi entry ++ * length: length of formated area of dmi entry ++ * data: pointer to whole raw dmi entry data ++ */ ++struct dmi_hdata { ++ unsigned char type; ++ unsigned char length; ++ unsigned short handle; ++ unsigned char *data; ++}; ++ ++/** ++ * dmi_entry - holds information about dmi entry ++ * next: internal in list pointer ++ * h: dmi header data, including raw data ++ * position: position within the dmi table ++ * d_name: dirctory entry name in sysfs ++ */ ++struct dmi_entry { ++ struct dmi_entry *next; ++ struct dmi_hdata h; ++ unsigned int position; ++ char *d_name; ++}; ++ ++/** ++ * dmi_table - contains whole information about smbios/dmi tables ++ * @smbios: pointer to raw data of smbios table ++ * @dmi_count: number of dmi entries in dmi table ++ * @dmi_size: length of dmi table in bytes ++ * @dmi_list: single list of dmi table entries, raw data of which contiguously ++ * situated in memnory. The list can be used to take a pointer to raw data ++ * of whole dmi table. ++ */ ++struct dmi_table { ++ unsigned char smbios[32]; ++ unsigned int dmi_count; ++ unsigned int dmi_size; ++ struct dmi_entry *dmi_list; ++}; ++ ++int dmifs_is_exist(void); ++struct dmi_table *dmi_get_table(void); ++int dmi_put_table(struct dmi_table *dt); ++void *dmi_get_raw_data(struct dmi_entry *dmi_list); ++struct dmi_entry *dmi_get_entry_by_handle(struct dmi_entry *dmi_list, ++ int handle); ++struct dmi_entry *dmi_get_next_entry_by_type(struct dmi_entry *dmi_entry, ++ unsigned char type); ++ ++#endif +-- +1.9.3 diff --git a/SOURCES/Support-SMBIOS-3.0-64-bit-header.patch b/SOURCES/Support-SMBIOS-3.0-64-bit-header.patch new file mode 100644 index 0000000..7615830 --- /dev/null +++ b/SOURCES/Support-SMBIOS-3.0-64-bit-header.patch @@ -0,0 +1,268 @@ +From 59820aacf5f9bcfde98753fde79ca2c779d755aa Mon Sep 17 00:00:00 2001 +From: Mark Salter +Date: Tue, 24 Feb 2015 23:42:05 -0500 +Subject: [PATCH] Support SMBIOS 3.0 64-bit header + +The SMBIOS 64-bit header adds suport for a 64-bit base address for the +SMBIOS tables. This patch adds code to parse deal with older 32-bit +headers and well as the 64-bit header. It also fixes 32-bit address +assumptions in a number of places. + +Signed-off-by: Mark Salter +--- + dmidecode.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 112 insertions(+), 31 deletions(-) + +diff --git a/dmidecode.c b/dmidecode.c +index fee3af1..6865cd7 100644 +--- a/dmidecode.c ++++ b/dmidecode.c +@@ -4277,7 +4277,10 @@ static u16 get_smbios_version(unsigned char *smbios) + { + u16 ver; + +- ver = (smbios[0x06] << 8) + smbios[0x07]; ++ if (!memcmp(smbios, "_SM3_", 5)) ++ ver = (smbios[0x07] << 8) + smbios[0x08]; ++ else ++ ver = (smbios[0x06] << 8) + smbios[0x07]; + + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (ver) { +@@ -4348,7 +4351,33 @@ static void dmi_table_dump(u8 *buf, u16 len) + write_dump(32, len, buf, opt.dumpfile, 0); + } + +-static void dmi_table(u32 base, u8 *buf, u16 len, u16 num, u16 ver) ++static u16 dmi_table_count(u8 *buf, u16 len) ++{ ++ u8 *data; ++ u16 i = 0; ++ ++ data = buf; ++ while (data+4 <= buf + len) /* 4 is the length of an SMBIOS structure header */ ++ { ++ struct dmi_header h; ++ ++ ++i; ++ ++ to_dmi_header(&h, data); ++ ++ if (h.length < 4) ++ break; ++ ++ /* look for the next handle */ ++ data += h.length; ++ while (data - buf + 1 < len && (data[0] != 0 || data[1] != 0)) ++ data++; ++ data += 2; ++ } ++ return i; ++} ++ ++static void dmi_table(u64 base, u8 *buf, u16 len, u16 num, u16 ver) + { + u8 *data; + int i = 0; +@@ -4372,8 +4401,13 @@ static void dmi_table(u32 base, u8 *buf, u16 len, u16 num, u16 ver) + { + printf("%u structures occupying %u bytes.\n", + num, len); +- if (!(opt.flags & FLAG_FROM_DUMP)) +- printf("Table at 0x%08X.\n", base); ++ if (!(opt.flags & FLAG_FROM_DUMP)) { ++ if (base.h) ++ printf("Table at 0x%08X%08X.\n", ++ base.h, base.l); ++ else ++ printf("Table at 0x%08X.\n", base.l); ++ } + } + printf("\n"); + } +@@ -4460,15 +4494,19 @@ static void dmi_table(u32 base, u8 *buf, u16 len, u16 num, u16 ver) + /* + * 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 +- * DMI checksum appropriately. The SMBIOS checksum needs no adjustment. ++ * checksum appropriately. + */ +-static void overwrite_dmi_address(u8 *buf) ++static void overwrite_address(u8 *cksum, u8 *addr, int addr_len) + { +- buf[0x05] += buf[0x08] + buf[0x09] + buf[0x0A] + buf[0x0B] - 32; +- buf[0x08] = 32; +- buf[0x09] = 0; +- buf[0x0A] = 0; +- buf[0x0B] = 0; ++ int i; ++ ++ *cksum += addr[0] - 32; ++ addr[0] = 32; ++ ++ for (i = 1; i < addr_len; ++i) { ++ *cksum += addr[i]; ++ addr[i] = 0; ++ } + } + + /** +@@ -4478,36 +4516,51 @@ static void overwrite_dmi_address(u8 *buf) + static void smbios_in_dumpfile(unsigned char *smbios) + { + u8 crafted[32]; ++ u8 len; + + memcpy(crafted, smbios, 32); +- overwrite_dmi_address(crafted + 0x10); ++ if (!memcmp(smbios, "_SM3_", 5)) { ++ overwrite_address(crafted + 0x05, crafted + 0x10, 8); ++ len = crafted[0x06]; ++ } else { ++ overwrite_address(crafted + 0x15, crafted + 0x18, 4); ++ len = crafted[0x05]; ++ } + + 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); ++ write_dump(0, len, crafted, opt.dumpfile, 1); + } + + static int smbios_decode(u8 *buf, const char *devmem) + { + u16 ver; +- u16 len; +- u32 base; ++ u16 len, num; ++ u64 base; + u8 *dmibuf; + +- if (!checksum(buf, buf[0x05]) +- || memcmp(buf + 0x10, "_DMI_", 5) != 0 +- || !checksum(buf + 0x10, 0x0F)) +- return 0; ++ if (!memcmp(buf, "_SM3_", 5)) { ++ if (!checksum(buf, buf[0x06])) ++ return 0; ++ base = QWORD(buf + 0x10); ++ len = WORD(buf + 0x0C); ++ } else { ++ if (!checksum(buf, buf[0x05]) ++ || memcmp(buf + 0x10, "_DMI_", 5) != 0 ++ || !checksum(buf + 0x10, 0x0F)) ++ return 0; ++ base.h = 0; ++ base.l = DWORD(buf + 0x18); ++ len = WORD(buf + 0x16); ++ } + + ver = get_smbios_version(buf); +- +- base = DWORD(buf + 0x18); +- len = WORD(buf + 0x16); +- dmibuf = mem_chunk(base, len, devmem); ++ dmibuf = mem_chunk(base.l, len, devmem); + if (!dmibuf) { + fprintf(stderr, "Table is unreachable, sorry." ++ + #ifndef USE_MMAP + " Try compiling dmidecode with -DUSE_MMAP." + #endif +@@ -4515,7 +4568,13 @@ static int smbios_decode(u8 *buf, const char *devmem) + return 0; + } + +- dmi_table(base, dmibuf, len, WORD(buf + 0x1C), ver); ++ /* version 3 64-bit header doesn't have number of tables */ ++ if (!memcmp(buf, "_SM3_", 5)) ++ num = dmi_table_count(dmibuf, len); ++ else ++ num = WORD(buf + 0x1C); ++ ++ dmi_table(base, dmibuf, len, num, ver); + + free(dmibuf); + +@@ -4529,6 +4588,7 @@ static void dmifs_smbios_decode(void) + { + u16 ver; + u8 *smbios; ++ u64 base; + struct dmi_table *dt; + + dt = dmi_get_table(); +@@ -4538,8 +4598,28 @@ static void dmifs_smbios_decode(void) + 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 (!memcmp(smbios, "_SM3_", 5)) { ++ base = QWORD(smbios + 0x10); ++ dmi_table(base, dmi_get_raw_data(dt->dmi_list), ++ dt->dmi_size, dt->dmi_count, ver); ++ if (opt.flags & FLAG_DUMP_BIN) { ++ /* ++ * Table length in SMBIOS 3.0 header is a maximum size. ++ * Make it exact to avoid warnings/errors when decoding ++ * from file we are dumping. ++ */ ++ dt->smbios[0x05] += dt->smbios[0x0c] + dt->smbios[0x0d]; ++ dt->smbios[0x0c] = dt->dmi_size; ++ dt->smbios[0x0d] = dt->dmi_size >> 8; ++ dt->smbios[0x05] -= dt->smbios[0x0c] + dt->smbios[0x0d]; ++ } ++ } else { ++ base.h = 0; ++ base.l = DWORD(smbios + 0x18); ++ dmi_table(base, 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); +@@ -4550,7 +4630,7 @@ static void dmifs_smbios_decode(void) + static int legacy_decode(u8 *buf, const char *devmem) + { + u16 len; +- u32 base; ++ u64 base; + u8 *dmibuf; + + if (!checksum(buf, 0x0F)) +@@ -4561,8 +4641,9 @@ static int legacy_decode(u8 *buf, const char *devmem) + buf[0x0E] >> 4, buf[0x0E] & 0x0F); + + len = WORD(buf + 0x06); +- base = DWORD(buf + 0x08); +- dmibuf = mem_chunk(base, len, devmem); ++ base.h = 0; ++ base.l = DWORD(buf + 0x08); ++ dmibuf = mem_chunk(base.l, len, devmem); + if (!dmibuf) { + fprintf(stderr, "Table is unreachable, sorry." + #ifndef USE_MMAP +@@ -4582,7 +4663,7 @@ static int legacy_decode(u8 *buf, const char *devmem) + u8 crafted[16]; + + memcpy(crafted, buf, 16); +- overwrite_dmi_address(crafted); ++ overwrite_address(crafted + 0x05, crafted + 0x08, 4); + + printf("# Writing %d bytes to %s.\n", 0x0F, opt.dumpfile); + write_dump(0, 0x0F, crafted, opt.dumpfile, 1); +@@ -4689,7 +4770,7 @@ int main(int argc, char * const argv[]) + goto exit_free; + } + +- if (memcmp(buf, "_SM_", 4) == 0) ++ if (memcmp(buf, "_SM_", 4) == 0 || memcmp(buf, "_SM3_", 5) == 0) + { + if (smbios_decode(buf, opt.dumpfile)) + found++; +-- +1.8.3.1 diff --git a/SOURCES/Support-upstream-filename-for-smbios-64-bit-header.patch b/SOURCES/Support-upstream-filename-for-smbios-64-bit-header.patch new file mode 100644 index 0000000..de812b8 --- /dev/null +++ b/SOURCES/Support-upstream-filename-for-smbios-64-bit-header.patch @@ -0,0 +1,32 @@ +From 5b47f83914e68f40c57feeaa6582c183556f51c2 Mon Sep 17 00:00:00 2001 +From: Mark Salter +Date: Thu, 25 Jun 2015 12:27:03 -0400 +Subject: [PATCH] Support upstream sysfs filename for smbios entry point + +The existing (preliminary) SMBIOS 64-bit support relies on the +SMBIOS entry point to be exposed via sysfs. Since this support +was added, the upstream kernel patches have evolved and now use +a different filename. This patch checks for the new filename as +well as the older name for backwards compatibility. + +Signed-off-by: Mark Salter +--- + libdmifs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libdmifs.c b/libdmifs.c +index ef4e1c1..05c8ea0 100644 +--- a/libdmifs.c ++++ b/libdmifs.c +@@ -102,6 +102,8 @@ static int dmi_get_smbios(unsigned char *smbios) + enum {SMBIOS_SIZE = 32}; + + file = fopen("/sys/firmware/dmi/smbios_raw_header", "rb"); ++ if (!file) ++ file = fopen("/sys/firmware/dmi/tables/smbios_entry_point", "rb"); + if (!file) { + fprintf(stderr, "no \"smbios\" sysfs entry\n"); + return count; +-- +2.4.3 + diff --git a/SOURCES/dmidecode-add-dmi-sysfs-support.patch b/SOURCES/dmidecode-add-dmi-sysfs-support.patch new file mode 100644 index 0000000..2459227 --- /dev/null +++ b/SOURCES/dmidecode-add-dmi-sysfs-support.patch @@ -0,0 +1,99 @@ +From 1bd45ec19f7a2d4cdc293b7a5e705c6ee793953e Mon Sep 17 00:00:00 2001 +From: Ivan Khoronzhuk +Date: Thu, 15 Jan 2015 03:01:37 +0200 +Subject: [PATCH 4/4] dmidecode: add dmi sysfs support + +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 +Signed-off-by: Ivan Khoronzhuk +--- + 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 + #include + #include ++#include + + #include "version.h" + #include "config.h" +@@ -4524,6 +4525,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; +@@ -4679,7 +4702,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" +-- +1.9.3 diff --git a/SOURCES/dmidecode-move-memory-map-function-from-dmi_decode.patch b/SOURCES/dmidecode-move-memory-map-function-from-dmi_decode.patch new file mode 100644 index 0000000..b219592 --- /dev/null +++ b/SOURCES/dmidecode-move-memory-map-function-from-dmi_decode.patch @@ -0,0 +1,154 @@ +From 9967415630f6e58da27ebd33a32d1f1bb1f6ba78 Mon Sep 17 00:00:00 2001 +From: Ivan Khoronzhuk +Date: Thu, 15 Jan 2015 22:39:26 +0200 +Subject: [PATCH 3/4] dmidecode: move memory map function from dmi_decode + +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 +--- + 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 +@@ -4340,25 +4340,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; + +@@ -4371,7 +4361,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; + } + +@@ -4387,16 +4377,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 */ + { +@@ -4474,8 +4454,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); + } + + /* +@@ -4513,6 +4491,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 +@@ -4521,8 +4502,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); +@@ -4532,6 +4526,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; + +@@ -4539,8 +4537,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) + { +-- +1.9.3 diff --git a/SOURCES/dmidecode-only-use-SMBIOS3-on-aarch64-systems.patch b/SOURCES/dmidecode-only-use-SMBIOS3-on-aarch64-systems.patch new file mode 100644 index 0000000..b6ca1e0 --- /dev/null +++ b/SOURCES/dmidecode-only-use-SMBIOS3-on-aarch64-systems.patch @@ -0,0 +1,30 @@ +From 0966726a8ecd982797ef1181d95fd2f172dc38af Mon Sep 17 00:00:00 2001 +From: Jeffrey Bastian +Date: Tue, 14 Jul 2015 07:48:34 -0500 +Subject: [PATCH] only use SMBIOS3 on aarch64 systems + +--- + dmidecode.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dmidecode.c b/dmidecode.c +index 163730b6e298..5e9e8a29b977 100644 +--- a/dmidecode.c ++++ b/dmidecode.c +@@ -4784,11 +4784,13 @@ int main(int argc, char * const argv[]) + goto done; + } + ++#ifdef __aarch64__ + /* First try dmi sysfs */ + if (dmifs_is_exist()) { + dmifs_smbios_decode(); + goto exit_free; + } ++#endif + + /* Second try EFI (ia64, Intel-based Mac) */ + efi = address_from_efi(&fp); +-- +1.9.4 + diff --git a/SOURCES/dmidecode-support-for-ddr4-mem.patch b/SOURCES/dmidecode-support-for-ddr4-mem.patch new file mode 100644 index 0000000..9486b17 --- /dev/null +++ b/SOURCES/dmidecode-support-for-ddr4-mem.patch @@ -0,0 +1,18 @@ +diff --git a/dmidecode.c b/dmidecode.c +index 83e66e6..a5304a7 100644 +--- a/dmidecode.c ++++ b/dmidecode.c +@@ -2302,10 +2302,11 @@ static const char *dmi_memory_device_type(u8 code) + "Reserved", + "Reserved", + "DDR3", +- "FBD2", /* 0x19 */ ++ "FBD2", ++ "DDR4" /* 0x1A */ + }; + +- if (code >= 0x01 && code <= 0x19) ++ if (code >= 0x01 && code <= 0x1A) + return type[code - 0x01]; + return out_of_spec; + } diff --git a/SOURCES/dmidecode-update-oem-decode.patch b/SOURCES/dmidecode-update-oem-decode.patch new file mode 100644 index 0000000..fbb3ea7 --- /dev/null +++ b/SOURCES/dmidecode-update-oem-decode.patch @@ -0,0 +1,263 @@ +--- a/dmioem.c 2012-03-12 08:49:07.000000000 +0100 ++++ b/dmioem.c 2015-09-21 09:57:41.255989615 +0200 +@@ -30,31 +30,80 @@ + * 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; + +-/* +- * Remember the system vendor for later use. We only actually store the +- * value if we know how to decode at least one specific entry type for +- * that vendor. +- */ + 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; ++} ++ ++static 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; + } + + /* + * 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 +129,19 @@ static int dmi_decode_hp(const struct dm + * + * 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 +150,128 @@ static int dmi_decode_hp(const struct dm + 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 +288,8 @@ int dmi_decode_oem(const struct dmi_head + { + case VENDOR_HP: + return dmi_decode_hp(h); ++ case VENDOR_ACER: ++ return dmi_decode_acer(h); + default: + return 0; + } diff --git a/SOURCES/dmidecode-use-common-function-to-get-SMBIOS-version.patch b/SOURCES/dmidecode-use-common-function-to-get-SMBIOS-version.patch new file mode 100644 index 0000000..4ce75a6 --- /dev/null +++ b/SOURCES/dmidecode-use-common-function-to-get-SMBIOS-version.patch @@ -0,0 +1,100 @@ +From db2e8e195c15ed0e56e6652c1b59fdd487d4fbb9 Mon Sep 17 00:00:00 2001 +From: Ivan Khoronzhuk +Date: Thu, 15 Jan 2015 01:14:43 +0200 +Subject: [PATCH 1/4] dmidecode: use common function to get SMBIOS version + +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 +--- + 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 +@@ -4266,6 +4266,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]; +@@ -4442,7 +4478,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 +@@ -4466,27 +4501,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); +-- +1.9.3 diff --git a/SOURCES/dmidecode-use-common-function-to-put-SMBIOS-in-dumpf.patch b/SOURCES/dmidecode-use-common-function-to-put-SMBIOS-in-dumpf.patch new file mode 100644 index 0000000..a756482 --- /dev/null +++ b/SOURCES/dmidecode-use-common-function-to-put-SMBIOS-in-dumpf.patch @@ -0,0 +1,63 @@ +From d4a148740afb211dc519945a8fc8b5eaa0adf280 Mon Sep 17 00:00:00 2001 +From: Ivan Khoronzhuk +Date: Thu, 15 Jan 2015 02:28:22 +0200 +Subject: [PATCH 2/4] dmidecode: use common function to put SMBIOS in dumpfile + +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 +--- + 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 +@@ -4492,6 +4492,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; +@@ -4507,17 +4525,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; + } +-- +1.9.3 diff --git a/SPECS/dmidecode.spec b/SPECS/dmidecode.spec index 6f76f41..d9fe093 100644 --- a/SPECS/dmidecode.spec +++ b/SPECS/dmidecode.spec @@ -1,13 +1,23 @@ Summary: Tool to analyse BIOS DMI data Name: dmidecode Version: 2.12 -Release: 5%{?dist} +Release: 9%{?dist} Epoch: 1 Group: System Environment/Base License: GPLv2+ Source0: %{name}-%{version}.tar.bz2 URL: http://www.nongnu.org/dmidecode/ Patch0: dmidecode-2.12-smbios_fix.patch +Patch1: dmidecode-use-common-function-to-get-SMBIOS-version.patch +Patch2: dmidecode-use-common-function-to-put-SMBIOS-in-dumpf.patch +Patch3: dmidecode-move-memory-map-function-from-dmi_decode.patch +Patch4: dmidecode-add-dmi-sysfs-support.patch +Patch5: Add-libdmifs-from-Linaro.patch +Patch6: Support-SMBIOS-3.0-64-bit-header.patch +Patch7: dmidecode-support-for-ddr4-mem.patch +Patch8: dmidecode-only-use-SMBIOS3-on-aarch64-systems.patch +Patch9: Support-upstream-filename-for-smbios-64-bit-header.patch +Patch10: dmidecode-update-oem-decode.patch Buildroot: %{_tmppath}/%{name}-%{version}-root BuildRequires: automake autoconf ExclusiveArch: %{ix86} x86_64 ia64 aarch64 @@ -26,7 +36,16 @@ I/O ports (e.g. serial, parallel, USB). %prep %setup -q %patch0 -p1 -b .smbios_fix - +%patch1 -p1 -b .smbios_ver +%patch2 -p1 -b .smbios_dump +%patch3 -p1 -b .smbios_memmap +%patch4 -p1 -b .dmi_sysfs +%patch5 -p1 -b .libdmifs +%patch6 -p1 -b .smbios3 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 %build make %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" @@ -49,6 +68,24 @@ rm -rf ${buildroot} %{_mandir}/man8/* %changelog +* Mon Sep 21 2015 Petr Oros - 1:2.12-9 +- dmioem: Decode Acer-specific DMI type 170 +- dmioem: Decode HP-specific DMI types 212 and 219 +- dmioem: Decode HP-specific DMI type 233, and refactored 209 and 221 to use a common function +- Resolves: #1232501 + +* Thu Jul 23 2015 Petr Oros - 1:2.12-8 +- Support upstream sysfs filename for smbios entry point (Mark Salter) +- Resolves: #1232153 + +* Thu Jul 16 2015 Petr Oros - 1:2.12-7 +- only use SMBIOS3 on aarch64 systems (Jeffrey Bastian) +- Resolves: #1242409 + +* Wed May 13 2015 Petr Oros - 1:2.12-6 +- Add preliminary support for SMBIOS 64-bit entry point (Mark Salter) +- Add support for DDR4 memmory + * Fri Feb 21 2014 Anton Arapov - 2.12-5 - Spec file fixes for the Aarch64. (John Feeney )