nanxiongchao / rpms / dmidecode

Forked from rpms/dmidecode 4 years ago
Clone

Blame SOURCES/Add-libdmifs-from-Linaro.patch

4f8197
From a909f4e024bdb5b0a8ea11f9fde62a9c74438983 Mon Sep 17 00:00:00 2001
4f8197
From: Mark Salter <msalter@redhat.com>
4f8197
Date: Mon, 26 Jan 2015 12:42:42 -0500
4f8197
Subject: [PATCH] Add libdmifs from Linaro
4f8197
4f8197
This library module comes from:
4f8197
4f8197
  git://git.linaro.org/people/ivan.khoronzhuk/libdmifs.git
4f8197
4f8197
For now, it is being built in rather than as a shared lib.
4f8197
4f8197
Signed-off-by: Mark Salter <msalter@redhat.com>
4f8197
---
4f8197
 Makefile    |   7 +-
4f8197
 dmidecode.c |   2 +-
4f8197
 libdmifs.c  | 644 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4f8197
 libdmifs.h  |  56 ++++++
4f8197
 4 files changed, 706 insertions(+), 3 deletions(-)
4f8197
 create mode 100644 libdmifs.c
4f8197
 create mode 100644 libdmifs.h
4f8197
4f8197
diff --git a/Makefile b/Makefile
4f8197
index d8457da..805d08e 100644
4f8197
--- a/Makefile
4f8197
+++ b/Makefile
4f8197
@@ -57,8 +57,8 @@ all : $(PROGRAMS)
4f8197
 # Programs
4f8197
 #
4f8197
 
4f8197
-dmidecode : dmidecode.o dmiopt.o dmioem.o util.o
4f8197
-	$(CC) $(LDFLAGS) dmidecode.o dmiopt.o dmioem.o util.o -ldmifs -o $@
4f8197
+dmidecode : dmidecode.o dmiopt.o dmioem.o util.o libdmifs.o
4f8197
+	$(CC) $(LDFLAGS) dmidecode.o dmiopt.o dmioem.o util.o libdmifs.o -o $@
4f8197
 
4f8197
 biosdecode : biosdecode.o util.o
4f8197
 	$(CC) $(LDFLAGS) biosdecode.o util.o -o $@
4f8197
@@ -98,6 +98,9 @@ vpdopt.o : vpdopt.c config.h util.h vpdopt.h
4f8197
 util.o : util.c types.h util.h config.h
4f8197
 	$(CC) $(CFLAGS) -c $< -o $@
4f8197
 
4f8197
+libdmifs.o: libdmifs.c libdmifs.h
4f8197
+	$(CC) $(CFLAGS) -c $< -o $@
4f8197
+
4f8197
 #
4f8197
 # Commands
4f8197
 #
4f8197
diff --git a/dmidecode.c b/dmidecode.c
4f8197
index 4663cc6..fee3af1 100644
4f8197
--- a/dmidecode.c
4f8197
+++ b/dmidecode.c
4f8197
@@ -57,7 +57,7 @@
4f8197
 #include <strings.h>
4f8197
 #include <stdlib.h>
4f8197
 #include <unistd.h>
4f8197
-#include <libdmifs.h>
4f8197
+#include "libdmifs.h"
4f8197
 
4f8197
 #include "version.h"
4f8197
 #include "config.h"
4f8197
diff --git a/libdmifs.c b/libdmifs.c
4f8197
new file mode 100644
4f8197
index 0000000..9ad2414
4f8197
--- /dev/null
4f8197
+++ b/libdmifs.c
4f8197
@@ -0,0 +1,644 @@
4f8197
+#include <stdio.h>
4f8197
+#include <stdlib.h>
4f8197
+#include <string.h>
4f8197
+#include <dirent.h>
4f8197
+#include <unistd.h>
4f8197
+#include <errno.h>
4f8197
+#include <endian.h>
4f8197
+#include "libdmifs.h"
4f8197
+
4f8197
+/*
4f8197
+ * maximum number of entries can be calculated based on maximum table
4f8197
+ * size and minimum size of structure (4 + 2 NULL symbols).
4f8197
+ */
4f8197
+#define MIN_HEADER_SIZE			4
4f8197
+#define MIN_DMI_STRUCT_SIZE		(MIN_HEADER_SIZE + 2)
4f8197
+#define MAX_ENTRIES_COUNT		(~0U/MIN_DMI_STRUCT_SIZE)
4f8197
+#define POSITION_ERR			(MAX_ENTRIES_COUNT + 1)
4f8197
+
4f8197
+/* list of dmi entries */
4f8197
+
4f8197
+/**
4f8197
+ * dmilist_insert - inserts new dmi entry to ordered dmi_list,
4f8197
+ * sorting according to the position in dmi table
4f8197
+ * @dmi_list: pointer on pointer to the first dmi entry in the list
4f8197
+ * @new: new entry to be inserted in the ordered dmi_list.
4f8197
+ *
4f8197
+ * Returns 0 on success and -1 when error.
4f8197
+ */
4f8197
+static int dmilist_insert(struct dmi_entry **dmi_list, struct dmi_entry *new)
4f8197
+{
4f8197
+	struct dmi_entry *old;
4f8197
+	struct dmi_entry *cur = *dmi_list;
4f8197
+
4f8197
+	if (!cur) {
4f8197
+		new->next = NULL;
4f8197
+		*dmi_list = new;
4f8197
+		return 0;
4f8197
+	}
4f8197
+
4f8197
+	old = NULL;
4f8197
+	while (cur) {
4f8197
+		if (cur->position < new->position) {
4f8197
+			old = cur;
4f8197
+			cur = cur->next;
4f8197
+			continue;
4f8197
+		} else if (cur->position > new->position) {
4f8197
+			if (old) {
4f8197
+				old->next = new;
4f8197
+				new->next = cur;
4f8197
+				return 0;
4f8197
+			}
4f8197
+			new->next = cur;
4f8197
+			*dmi_list = new;
4f8197
+			return 0;
4f8197
+		}
4f8197
+
4f8197
+		fprintf(stderr, "dmitable is broken");
4f8197
+		return -1;
4f8197
+	}
4f8197
+
4f8197
+	old->next = new;
4f8197
+	new->next = NULL;
4f8197
+
4f8197
+	return 0;
4f8197
+}
4f8197
+
4f8197
+static void dmilist_free_entry(struct dmi_entry *entry)
4f8197
+{
4f8197
+	free(entry->d_name);
4f8197
+	free(entry);
4f8197
+}
4f8197
+
4f8197
+static void dmilist_free(struct dmi_entry **dmi_list)
4f8197
+{
4f8197
+	struct dmi_entry *old;
4f8197
+	struct dmi_entry *cur = *dmi_list;
4f8197
+
4f8197
+	if (!cur)
4f8197
+		return;
4f8197
+
4f8197
+	while (cur) {
4f8197
+		old = cur;
4f8197
+		cur = cur->next;
4f8197
+		dmilist_free_entry(old);
4f8197
+	}
4f8197
+
4f8197
+	*dmi_list = NULL;
4f8197
+}
4f8197
+
4f8197
+/* dmi sysfs attribute reading */
4f8197
+
4f8197
+/**
4f8197
+ * dmi_get_smbios - get smbios data
4f8197
+ * @smbios: pointer on array to read raw smbios table in
4f8197
+ *
4f8197
+ * Returns read data size in bytes on success and 0 when error.
4f8197
+ */
4f8197
+static int dmi_get_smbios(unsigned char *smbios)
4f8197
+{
4f8197
+	FILE *file;
4f8197
+	int count = 0;
4f8197
+	enum {SMBIOS_SIZE = 32};
4f8197
+
4f8197
+	file = fopen("/sys/firmware/dmi/smbios_raw_header", "rb");
4f8197
+	if (!file) {
4f8197
+		fprintf(stderr, "no \"smbios\" sysfs entry\n");
4f8197
+		return count;
4f8197
+	}
4f8197
+
4f8197
+	count = fread(smbios, sizeof(char), SMBIOS_SIZE, file);
4f8197
+	if (!feof(file)) {
4f8197
+		fprintf(stderr, "Error while reading a file\n");
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+err:
4f8197
+	fclose(file);
4f8197
+	return count;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * read_position - reads position of dmi entry as it's inside dmi table
4f8197
+ * @dir: appropriate directory of dmi entry position
4f8197
+ *
4f8197
+ * returns dmi entry position in dmi table on success and POSITION_ERR when
4f8197
+ * error occurred.
4f8197
+ */
4f8197
+static unsigned int read_position(char *dir)
4f8197
+{
4f8197
+	FILE *file;
4f8197
+	char pos[10];
4f8197
+	unsigned int position;
4f8197
+
4f8197
+	file = fopen("position", "r");
4f8197
+	if (!file) {
4f8197
+		fprintf(stderr, "no \"position\" in \"%s\"\n", dir);
4f8197
+		return POSITION_ERR;
4f8197
+	}
4f8197
+
4f8197
+	if (!fgets(pos, 10, file) && ferror(file)) {
4f8197
+		fclose(file);
4f8197
+		fprintf(stderr, "Error while working with \"position\" in %s\n",
4f8197
+			dir);
4f8197
+		return POSITION_ERR;
4f8197
+	}
4f8197
+
4f8197
+	fclose(file);
4f8197
+
4f8197
+	position = strtoul(pos, NULL, 0);
4f8197
+	/* position can't be more than number of entries */
4f8197
+	if (position > MAX_ENTRIES_COUNT) {
4f8197
+		fprintf(stderr, "position is incorrect %d\n", position);
4f8197
+		return POSITION_ERR;
4f8197
+	}
4f8197
+
4f8197
+	return position;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * read_raw - reads raw data of dmi entry
4f8197
+ * @dir: appropriate directory of dmi entry position
4f8197
+ * @data: pointer to the array where raw data will be read
4f8197
+ * @max_size: maximum data size possible to read
4f8197
+ *
4f8197
+ * Returns read data size in bytes on success and 0 when error.
4f8197
+ * In the same time return value < 6 is also error as at least header is
4f8197
+ * 4 bytes in size + 2 NULLs.
4f8197
+ */
4f8197
+static unsigned int read_raw(char *dir,
4f8197
+			     unsigned char *buf, unsigned int max_size)
4f8197
+{
4f8197
+	FILE *file;
4f8197
+	unsigned int count;
4f8197
+	unsigned int size = 0;
4f8197
+
4f8197
+	file = fopen("raw", "rb");
4f8197
+	if (!file) {
4f8197
+		fprintf(stderr, "no \"raw\" in \"%s\"\n", dir);
4f8197
+		return 0;
4f8197
+	}
4f8197
+
4f8197
+	count = fread(buf, sizeof(char), max_size, file);
4f8197
+	if (!feof(file)) {
4f8197
+		fprintf(stderr, "Error while reading \"raw\" file\n");
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+	if (count < MIN_DMI_STRUCT_SIZE) {
4f8197
+		fprintf(stderr, "DMI header cannot be less than 4 bytes");
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+	/* check if structure is correct */
4f8197
+	if (buf[count - 1] || buf[count - 2]) {
4f8197
+		fprintf(stderr, "Bad raw file of \"%s\"\n", dir);
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+	size = count;
4f8197
+err:
4f8197
+	fclose(file);
4f8197
+	return size;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * add_entry_to_dmilist - generates empty dmi entry and places it to dmi list
4f8197
+ * @dmi_list: dmi list where allocated dmi entry will be put
4f8197
+ * @dir: the directory name appropriate to dmi entry
4f8197
+ *
4f8197
+ * Returns 0 on success and -1 on error
4f8197
+ */
4f8197
+static int add_entry_to_dmilist(struct dmi_entry **dmi_list, char *dir)
4f8197
+{
4f8197
+	char *dir_name;
4f8197
+	unsigned int position;
4f8197
+	struct dmi_entry *entry;
4f8197
+
4f8197
+	position = read_position(dir);
4f8197
+	if (position == POSITION_ERR) {
4f8197
+		fprintf(stderr,
4f8197
+			"Cannot read smbios position for \"%s\"\n", dir);
4f8197
+		return -1;
4f8197
+	}
4f8197
+
4f8197
+	dir_name = malloc(strlen(dir) + 1);
4f8197
+	if (!dir_name) {
4f8197
+		fprintf(stderr, "Cannot allocate memory for dir\n");
4f8197
+		return -1;
4f8197
+	}
4f8197
+	strcpy(dir_name, dir);
4f8197
+
4f8197
+	entry = malloc(sizeof(struct dmi_entry));
4f8197
+	if (!entry) {
4f8197
+		fprintf(stderr, "Cannot allocate memory for dmi struct\n");
4f8197
+		free(dir_name);
4f8197
+		return -1;
4f8197
+	}
4f8197
+
4f8197
+	entry->d_name = dir_name;
4f8197
+	entry->position = position;
4f8197
+
4f8197
+	if (dmilist_insert(dmi_list, entry)) {
4f8197
+		fprintf(stderr, "Cannot insert new dmientry in the list");
4f8197
+		dmilist_free_entry(entry);
4f8197
+		return -1;
4f8197
+	}
4f8197
+
4f8197
+	return 0;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * gather_entry_data - reads data from given dmi directory raw attribute end
4f8197
+ * binds it with given dmi entry.
4f8197
+ * @entry: dmi entry for what data will be read
4f8197
+ * @rdata: pointer to array where data will be read in
4f8197
+ * @max_size: maximum data size possible to read for now
4f8197
+ *
4f8197
+ * Returns read raw data size including two NULLs at the end
4f8197
+ * On error returns 0
4f8197
+ */
4f8197
+static unsigned int gather_entry_data(struct dmi_entry *entry,
4f8197
+				      unsigned char *rdata,
4f8197
+				      unsigned int max_size)
4f8197
+{
4f8197
+	unsigned int dsize;
4f8197
+
4f8197
+	dsize = read_raw(entry->d_name, rdata, max_size);
4f8197
+	if (dsize < MIN_DMI_STRUCT_SIZE) {
4f8197
+		fprintf(stderr,
4f8197
+			"Cannot read DMI raw for \"%s\"\n", entry->d_name);
4f8197
+		return 0;
4f8197
+	}
4f8197
+
4f8197
+	entry->h.data = rdata;
4f8197
+	entry->h.type = rdata[0];
4f8197
+	entry->h.length = rdata[1];
4f8197
+	entry->h.handle = le16toh(rdata[2] | (rdata[3] << 8));
4f8197
+
4f8197
+	return dsize;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * populate_dmilist - populate dmi entries in dmi list by raw data
4f8197
+ * @dmi_list: dmi list with dmi entries to be populated
4f8197
+ * @max_size: supposed size of whole dmi table. Can be taken from
4f8197
+ *	table SMBIOS entry.
4f8197
+ *
4f8197
+ * Returns dmi raw table size on success, otherwise 0.
4f8197
+ */
4f8197
+static unsigned int populate_dmilist(struct dmi_entry *dmi_list,
4f8197
+				     unsigned int max_size)
4f8197
+{
4f8197
+	unsigned int dsize;
4f8197
+	struct dmi_entry *entry;
4f8197
+	unsigned char *raw_table, *tp;
4f8197
+
4f8197
+	/* allocate memory for whole dmi table */
4f8197
+	raw_table = malloc(max_size);
4f8197
+	if (!raw_table) {
4f8197
+		fprintf(stderr, "Cannot allocate memory for DMI table\n");
4f8197
+		return 0;
4f8197
+	}
4f8197
+
4f8197
+	tp = raw_table;
4f8197
+	for (entry = dmi_list; entry; entry = entry->next) {
4f8197
+		if (max_size < MIN_DMI_STRUCT_SIZE) {
4f8197
+			fprintf(stderr, "Max size of DMI table is reached\n");
4f8197
+			goto err;
4f8197
+		}
4f8197
+
4f8197
+		if (chdir(entry->d_name)) {
4f8197
+			fprintf(stderr, "Cannot change dir to %s\n",
4f8197
+				entry->d_name);
4f8197
+			goto err;
4f8197
+		}
4f8197
+
4f8197
+		dsize = gather_entry_data(entry, tp, max_size);
4f8197
+		if (dsize < MIN_DMI_STRUCT_SIZE) {
4f8197
+			if (chdir("../"))
4f8197
+				fprintf(stderr, "Cannot change dir to ../\n");
4f8197
+			goto err;
4f8197
+		}
4f8197
+
4f8197
+		if (chdir("../")) {
4f8197
+			fprintf(stderr, "Cannot change dir to ../\n");
4f8197
+			goto err;
4f8197
+		}
4f8197
+
4f8197
+		tp += dsize;
4f8197
+		max_size -= dsize;
4f8197
+	}
4f8197
+
4f8197
+	return tp - raw_table;
4f8197
+
4f8197
+err:
4f8197
+	fprintf(stderr, "Cannot gather data for dir %s\n", entry->d_name);
4f8197
+	free(raw_table);
4f8197
+	return 0;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * create_dmilist - creates ordered linked dmi list with empty entries.
4f8197
+ * The empty entry is entry with empty dmi header data
4f8197
+ * @entry_count: pointer to dmi entry count to be updated while creating.
4f8197
+ *
4f8197
+ * On success returns dmi_entry pointer on first entry in the list
4f8197
+ * Otherwise returns NULL. Updates entry_count.
4f8197
+ */
4f8197
+static struct dmi_entry *create_dmilist(unsigned int *entry_count)
4f8197
+{
4f8197
+	DIR *dmi;
4f8197
+	char *cwd;
4f8197
+	void *ret = NULL;
4f8197
+	struct dirent *dir_entry;
4f8197
+	struct dmi_entry *dmi_list = NULL;
4f8197
+
4f8197
+	dmi = opendir(".");
4f8197
+	if (!dmi) {
4f8197
+		fprintf(stderr, "Cannot open cwd\n");
4f8197
+		return ret;
4f8197
+	}
4f8197
+
4f8197
+	*entry_count = 0;
4f8197
+	readdir(dmi); /* miss "." */
4f8197
+	readdir(dmi); /* miss ".." */
4f8197
+	while ((dir_entry = readdir(dmi))) {
4f8197
+		if (chdir(dir_entry->d_name)) {
4f8197
+			fprintf(stderr, "Cannot change dir to %s\n",
4f8197
+				dir_entry->d_name);
4f8197
+			goto err;
4f8197
+		}
4f8197
+
4f8197
+		if (add_entry_to_dmilist(&dmi_list, dir_entry->d_name)) {
4f8197
+			fprintf(stderr, "Cannot add \"%s\" to dmi_list\n",
4f8197
+				dir_entry->d_name);
4f8197
+			if (chdir("../"))
4f8197
+				fprintf(stderr, "Cannot change dir to ../\n");
4f8197
+			goto err;
4f8197
+		}
4f8197
+
4f8197
+		if (chdir("../")) {
4f8197
+			fprintf(stderr, "Cannot change dir to ../\n");
4f8197
+			goto err;
4f8197
+		}
4f8197
+
4f8197
+		(*entry_count)++;
4f8197
+	}
4f8197
+	/* now dmilist is complete */
4f8197
+	ret = dmi_list;
4f8197
+err:
4f8197
+	if (closedir(dmi)) {
4f8197
+		cwd = getcwd(NULL, 1024);
4f8197
+		fprintf(stderr, "Cannot close %s", cwd);
4f8197
+		free(cwd);
4f8197
+		ret = NULL;
4f8197
+	}
4f8197
+
4f8197
+	if (ret == dmi_list)
4f8197
+		return dmi_list;
4f8197
+
4f8197
+	dmilist_free(&dmi_list);
4f8197
+	return ret;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmi_put_dmilist - frees dmi list alloted by dmi_get_dmilist()
4f8197
+ * @dmi_list: dmi list to be free
4f8197
+ *
4f8197
+ * Returns 0 on success, -1 otherwise.
4f8197
+ */
4f8197
+static int dmi_put_dmilist(struct dmi_entry *dmi_list)
4f8197
+{
4f8197
+	unsigned char *raw_table;
4f8197
+
4f8197
+	if (!dmi_list) {
4f8197
+		fprintf(stderr, "Cannot free dmi_list NULL pointer\n");
4f8197
+		return -1;
4f8197
+	}
4f8197
+
4f8197
+	raw_table = dmi_list->h.data;
4f8197
+	if (!raw_table) {
4f8197
+		fprintf(stderr, "Cannot free raw_table NULL pointer\n");
4f8197
+		return -1;
4f8197
+	}
4f8197
+
4f8197
+	free(raw_table);
4f8197
+	dmilist_free(&dmi_list);
4f8197
+
4f8197
+	return 0;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmi_get_dmilist - creates ordered dmi list with all dmi entries present
4f8197
+ * on dmi sysfs. All raw entries data are situated contiguously in the RAM.
4f8197
+ * @entry_count: read count of dmi list entries, that's dmi structs in dmi table
4f8197
+ * @dmi_size: read whole size in bytes of dmi table.
4f8197
+ * @max_size: supposed size of whole dmi table. Can be taken from SMBIOS
4f8197
+ *	entry point table.
4f8197
+ *
4f8197
+ * Returns a pointer to first dmi entry in the list. When list is no longer
4f8197
+ * needed it has to be freed with dmi_put_dmilist().
4f8197
+ * In case of error returns NULL.
4f8197
+ */
4f8197
+static struct dmi_entry *dmi_get_dmilist(unsigned int *entry_count,
4f8197
+					 unsigned int *dmi_size,
4f8197
+					 unsigned int max_size)
4f8197
+{
4f8197
+	char *cwd;
4f8197
+	struct dmi_entry *dmi_list = NULL;
4f8197
+	char root[] = "/sys/firmware/dmi/entries/";
4f8197
+
4f8197
+	cwd = getcwd(NULL, 1024);
4f8197
+	if (!cwd) {
4f8197
+		fprintf(stderr, "Cannot get current directory\n");
4f8197
+		return NULL;
4f8197
+	}
4f8197
+
4f8197
+	if (chdir(root)) {
4f8197
+		fprintf(stderr, "Cannot change dir to %s\n", root);
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+	/*
4f8197
+	 * Create dmi_list then fill it in. Do this in two steps to
4f8197
+	 * have contiguous raw data for whole table
4f8197
+	 */
4f8197
+	dmi_list = create_dmilist(entry_count);
4f8197
+	if (!dmi_list) {
4f8197
+		fprintf(stderr, "Cannot create dmi_list\n");
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+	*dmi_size = populate_dmilist(dmi_list, max_size);
4f8197
+	if (*dmi_size == 0) {
4f8197
+		dmilist_free(&dmi_list);
4f8197
+		fprintf(stderr, "Cannot fill in dmi_list by data from raw\n");
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+err:
4f8197
+	if (chdir(cwd)) {
4f8197
+		fprintf(stderr, "Cannot change root dir to %s\n", cwd);
4f8197
+		dmi_put_dmilist(dmi_list);
4f8197
+		dmi_list = NULL;
4f8197
+	}
4f8197
+
4f8197
+	free(cwd);
4f8197
+	return dmi_list;
4f8197
+}
4f8197
+
4f8197
+static int dmi_checksum(unsigned char *buf, unsigned char len)
4f8197
+{
4f8197
+	int i;
4f8197
+	unsigned char sum = 0;
4f8197
+
4f8197
+	for (i = 0; i < len; i++)
4f8197
+		sum += buf[i];
4f8197
+
4f8197
+	return sum == 0;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmi_get_expected_size - read dmi table size from SMBIOS entry point table.
4f8197
+ * Verify SMBIOS entry point table checksum.
4f8197
+ *
4f8197
+ * Returns dmi table size read from SMBIOS entry point table. Return 0 on error.
4f8197
+ */
4f8197
+static unsigned int dmi_get_expected_size(unsigned char *smbios)
4f8197
+{
4f8197
+	if (!memcmp(smbios, "_SM3_", 5) &&
4f8197
+	    dmi_checksum(smbios, smbios[0x06]))
4f8197
+		return le32toh(smbios[0x0C] | (smbios[0x0D] << 8) |
4f8197
+			       (smbios[0x0E] << 16) | (smbios[0x0F] << 24));
4f8197
+	else if (!memcmp(smbios, "_SM_", 4) &&
4f8197
+		 dmi_checksum(smbios, smbios[0x05]) &&
4f8197
+		 dmi_checksum(smbios + 0x10, 0x0F))
4f8197
+		return le16toh(smbios[0x16] | (smbios[0x17] << 8));
4f8197
+	else if (!memcmp(smbios, "_DMI_", 5) &&
4f8197
+		 dmi_checksum(smbios, 0x0F))
4f8197
+		return le16toh(smbios[0x06] | (smbios[0x07] << 8));
4f8197
+
4f8197
+	return 0;
4f8197
+}
4f8197
+
4f8197
+/* API */
4f8197
+
4f8197
+/**
4f8197
+ * dmi_get_table - allocate dmi table
4f8197
+ *
4f8197
+ * Returns pointer on allocated dmi_table struct on success,
4f8197
+ * otherwise returns NULL. When table is not needed it has to be
4f8197
+ * put by dmi_put_table.
4f8197
+ */
4f8197
+struct dmi_table *dmi_get_table(void)
4f8197
+{
4f8197
+	struct dmi_table *dt;
4f8197
+	unsigned int max_dmisize;
4f8197
+
4f8197
+	dt = malloc(sizeof(struct dmi_table));
4f8197
+
4f8197
+	if (!dmi_get_smbios(dt->smbios))
4f8197
+		goto err;
4f8197
+
4f8197
+	max_dmisize = dmi_get_expected_size(dt->smbios);
4f8197
+	if (max_dmisize < MIN_DMI_STRUCT_SIZE) {
4f8197
+		fprintf(stderr, "SMBIOS entry point is incorrect\n");
4f8197
+		goto err;
4f8197
+	}
4f8197
+
4f8197
+	dt->dmi_list = dmi_get_dmilist(&dt->dmi_count,
4f8197
+				       &dt->dmi_size, max_dmisize + 1);
4f8197
+	if (!dt->dmi_list)
4f8197
+		goto err;
4f8197
+
4f8197
+	return dt;
4f8197
+
4f8197
+err:
4f8197
+	free(dt);
4f8197
+	return NULL;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmi_put_table - used in pair with dmi_get_dmitable
4f8197
+ * @dt: dmi table pointer taken by dmi_get_table
4f8197
+ */
4f8197
+int dmi_put_table(struct dmi_table *dt)
4f8197
+{
4f8197
+	int ret = -1;
4f8197
+
4f8197
+	if (!dt) {
4f8197
+		fprintf(stderr, "pointer for DMI table is incorrect\n");
4f8197
+		return ret;
4f8197
+	}
4f8197
+
4f8197
+	ret = dmi_put_dmilist(dt->dmi_list);
4f8197
+	free(dt);
4f8197
+
4f8197
+	return ret;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmi_get_raw_data - give a pointer to raw dmi table, all raw dmi entries are
4f8197
+ * contiguously situated within this memory in original right order.
4f8197
+ * @dmi_list: dmi list only taken by dmi_get_dmilist
4f8197
+ */
4f8197
+void *dmi_get_raw_data(struct dmi_entry *dmi_list)
4f8197
+{
4f8197
+	return dmi_list->h.data;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmi_get_entry_by_handle - searches an entry in dmi list by given handle
4f8197
+ * @dmi_list: dmi list to search for
4f8197
+ * @handle: handle to find entry with
4f8197
+ *
4f8197
+ * Returns entry with given handle on success and NULL otherwise
4f8197
+ */
4f8197
+struct dmi_entry *dmi_get_entry_by_handle(struct dmi_entry *dmi_list,
4f8197
+					  int handle)
4f8197
+{
4f8197
+	struct dmi_entry *entry;
4f8197
+
4f8197
+	for (entry = dmi_list; entry; entry = entry->next)
4f8197
+		if (handle == entry->h.handle)
4f8197
+			return entry;
4f8197
+
4f8197
+	return NULL;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmi_get_next_entry_by_type - searches a next entry in dmi list by type
4f8197
+ * @dmi_entry: the dmi_entry in dmi list to search beginnig with
4f8197
+ * @type: type of dmi entry to find
4f8197
+ */
4f8197
+struct dmi_entry *dmi_get_next_entry_by_type(struct dmi_entry *dmi_entry,
4f8197
+					     unsigned char type)
4f8197
+{
4f8197
+	struct dmi_entry *entry;
4f8197
+
4f8197
+	for (entry = dmi_entry->next; entry; entry = entry->next)
4f8197
+		if (type == entry->h.type)
4f8197
+			return entry;
4f8197
+
4f8197
+	return NULL;
4f8197
+}
4f8197
+
4f8197
+/**
4f8197
+ * dmifs_is_exist - checks if dmi sysfs exists
4f8197
+ *
4f8197
+ * Returns 1 on success and 0 if no
4f8197
+ */
4f8197
+int dmifs_is_exist(void)
4f8197
+{
4f8197
+	int ret;
4f8197
+	char dmi_cat[] = "/sys/firmware/dmi/entries/";
4f8197
+	DIR *dmi_dir = opendir(dmi_cat);
4f8197
+
4f8197
+	ret = dmi_dir ? 1 : 0;
4f8197
+
4f8197
+	if (closedir(dmi_dir))
4f8197
+		fprintf(stderr, "Cannot close %s", dmi_cat);
4f8197
+
4f8197
+	return ret;
4f8197
+}
4f8197
diff --git a/libdmifs.h b/libdmifs.h
4f8197
new file mode 100644
4f8197
index 0000000..218d07f
4f8197
--- /dev/null
4f8197
+++ b/libdmifs.h
4f8197
@@ -0,0 +1,56 @@
4f8197
+#ifndef LIBDMIFS_H
4f8197
+#define LIBDMIFS_H
4f8197
+
4f8197
+/**
4f8197
+ * dmi_hdata - information of dmi entry header
4f8197
+ * type: type of dmi entry
4f8197
+ * length: length of formated area of dmi entry
4f8197
+ * data: pointer to whole raw dmi entry data
4f8197
+ */
4f8197
+struct dmi_hdata {
4f8197
+	unsigned char type;
4f8197
+	unsigned char length;
4f8197
+	unsigned short handle;
4f8197
+	unsigned char *data;
4f8197
+};
4f8197
+
4f8197
+/**
4f8197
+ * dmi_entry - holds information about dmi entry
4f8197
+ * next: internal in list pointer
4f8197
+ * h: dmi header data, including raw data
4f8197
+ * position: position within the dmi table
4f8197
+ * d_name: dirctory entry name in sysfs
4f8197
+ */
4f8197
+struct dmi_entry {
4f8197
+	struct dmi_entry *next;
4f8197
+	struct dmi_hdata h;
4f8197
+	unsigned int position;
4f8197
+	char *d_name;
4f8197
+};
4f8197
+
4f8197
+/**
4f8197
+ * dmi_table - contains whole information about smbios/dmi tables
4f8197
+ * @smbios: pointer to raw data of smbios table
4f8197
+ * @dmi_count: number of dmi entries in dmi table
4f8197
+ * @dmi_size: length of dmi table in bytes
4f8197
+ * @dmi_list: single list of dmi table entries, raw data of which contiguously
4f8197
+ *	situated in memnory. The list can be used to take a pointer to raw data
4f8197
+ *	of whole dmi table.
4f8197
+ */
4f8197
+struct dmi_table {
4f8197
+	unsigned char smbios[32];
4f8197
+	unsigned int dmi_count;
4f8197
+	unsigned int dmi_size;
4f8197
+	struct dmi_entry *dmi_list;
4f8197
+};
4f8197
+
4f8197
+int dmifs_is_exist(void);
4f8197
+struct dmi_table *dmi_get_table(void);
4f8197
+int dmi_put_table(struct dmi_table *dt);
4f8197
+void *dmi_get_raw_data(struct dmi_entry *dmi_list);
4f8197
+struct dmi_entry *dmi_get_entry_by_handle(struct dmi_entry *dmi_list,
4f8197
+					  int handle);
4f8197
+struct dmi_entry *dmi_get_next_entry_by_type(struct dmi_entry *dmi_entry,
4f8197
+					     unsigned char type);
4f8197
+
4f8197
+#endif
4f8197
-- 
4f8197
1.9.3
4f8197