summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/ich_descriptors_tool/Makefile42
-rw-r--r--util/ich_descriptors_tool/TODO10
-rw-r--r--util/ich_descriptors_tool/ich_descriptors_tool.c227
3 files changed, 279 insertions, 0 deletions
diff --git a/util/ich_descriptors_tool/Makefile b/util/ich_descriptors_tool/Makefile
new file mode 100644
index 0000000..1af90ce
--- /dev/null
+++ b/util/ich_descriptors_tool/Makefile
@@ -0,0 +1,42 @@
+CC ?= gcc
+
+PROGRAM=ich_descriptors_tool
+EXTRAINCDIRS = ../../ .
+DEPPATH = .dep
+OBJATH = .obj
+SHAREDSRC = ich_descriptors.c
+SHAREDSRCDIR = ../..
+
+SRC = $(wildcard *.c)
+
+CFLAGS += -Wall
+CFLAGS += -MMD -MP -MF $(DEPPATH)/$(@F).d
+# enables functions that populate the descriptor structs from plain binary dumps
+CFLAGS += -D ICH_DESCRIPTORS_FROM_DUMP
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+
+OBJ = $(OBJATH)/$(SRC:%.c=%.o)
+
+SHAREDOBJ = $(OBJATH)/$(notdir $(SHAREDSRC:%.c=%.o))
+
+all:$(PROGRAM)
+
+$(OBJ): $(OBJATH)/%.o : %.c
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+# this enables us to share source files without simultaneously sharing .o files
+# with flashrom, which would lead to unexpected results (w/o running make clean)
+$(SHAREDOBJ): $(OBJATH)/%.o : $(SHAREDSRCDIR)/%.c
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+$(PROGRAM): $(OBJ) $(SHAREDOBJ)
+ $(CC) -o $(PROGRAM) $(OBJ) $(SHAREDOBJ)
+
+clean:
+ rm -f $(PROGRAM)
+ rm -rf $(DEPPATH) $(OBJATH)
+
+# Include the dependency files.
+-include $(shell mkdir -p $(DEPPATH) $(OBJATH) 2>/dev/null) $(wildcard $(DEPPATH)/*)
+
+.PHONY: all clean
diff --git a/util/ich_descriptors_tool/TODO b/util/ich_descriptors_tool/TODO
new file mode 100644
index 0000000..e1bb843
--- /dev/null
+++ b/util/ich_descriptors_tool/TODO
@@ -0,0 +1,10 @@
+- reverse the path: assemble a descriptormode image from various
+ blobs (BIOS, GbE, ME, OEM) and a description (xml? custom config?
+ sane defaults and cmd-line switches?)
+- dump 256 OEM bytes
+- deal with the various possible locations of mac address(es?)
+ /* mazzoo said: from what I've seen, the MAC address is the 1st or
+ * 2nd 6 bytes in the GbE region. It seems the PXE-OpROM and/or the
+ * intel EEUPDATE-tool copies the MAC address to the 2nd part.
+ */
+- add descriptions for the missing chipsets
diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c
new file mode 100644
index 0000000..a1bce1b
--- /dev/null
+++ b/util/ich_descriptors_tool/ich_descriptors_tool.c
@@ -0,0 +1,227 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Matthias Wenzel <bios at mazzoo dot de>
+ * Copyright (C) 2011 Stefan Tauner
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * dump information and binaries from BIOS images that are in descriptor mode
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "ich_descriptors.h"
+
+static void dump_file(const char *basename, const uint32_t *dump, unsigned int len, struct ich_desc_region *reg, unsigned int i)
+{
+ int ret;
+ char *fn;
+ const char *reg_name;
+ uint32_t file_len;
+ const char *const region_names[5] = {
+ "Descriptor", "BIOS", "ME", "GbE", "Platform"
+ };
+ uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
+ uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
+
+ reg_name = region_names[i];
+ if (base > limit) {
+ printf("The %s region is unused and thus not dumped.\n",
+ reg_name);
+ return;
+ }
+
+ limit = limit | 0x0fff;
+ file_len = limit + 1 - base;
+ if (base + file_len > len) {
+ printf("The %s region is spanning 0x%08x-0x%08x, but it is "
+ "not (fully) included in the image (0-0x%08x), thus not "
+ "dumped.\n", reg_name, base, limit, len - 1);
+ return;
+ }
+
+ fn = malloc(strlen(basename) + strlen(reg_name) + strlen(".bin") + 2);
+ if (!fn) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(1);
+ }
+ snprintf(fn, strlen(basename) + strlen(reg_name) + strlen(".bin") + 2,
+ "%s.%s.bin", basename, reg_name);
+ printf("Dumping %u bytes of the %s region from 0x%08x-0x%08x to %s... ",
+ file_len, region_names[i], base, limit, fn);
+ int fh = open(fn, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ free(fn);
+ if (fh < 0) {
+ fprintf(stderr,
+ "ERROR: couldn't open(%s): %s\n", fn, strerror(errno));
+ exit(1);
+ }
+
+ ret = write(fh, &dump[base >> 2], file_len);
+ if (ret != file_len) {
+ fprintf(stderr, "FAILED.\n");
+ exit(1);
+ }
+
+ printf("done.\n");
+ close(fh);
+}
+
+void dump_files(const char *n, const uint32_t *buf, unsigned int len, struct ich_desc_region *reg)
+{
+ unsigned int i;
+ printf("=== Dumping region files ===\n");
+ for (i = 0; i < 5; i++)
+ dump_file(n, buf, len, reg, i);
+ printf("\n");
+}
+
+static void usage(char *argv[], char *error)
+{
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ printf("usage: '%s -f <image file name> [-c <chipset name>] [-d]'\n\n"
+"where <image file name> points to an image of the contents of the SPI flash.\n"
+"In case the image is really in descriptor mode %s\n"
+"will pretty print some of the contained information.\n"
+"To also print the data stored in the descriptor strap you have to indicate\n"
+"the chipset series with the '-c' parameter and one of the possible arguments:\n"
+"\t- \"ich8\",\n"
+"\t- \"ich9\",\n"
+"\t- \"ich10\",\n"
+"\t- \"5\" or \"ibex\" for Intel's 5 series chipsets,\n"
+"\t- \"6\" or \"cougar\" for Intel's 6 series chipsets,\n"
+"\t- \"7\" or \"panther\" for Intel's 7 series chipsets.\n"
+"If '-d' is specified some regions such as the BIOS image as seen by the CPU or\n"
+"the GbE blob that is required to initialize the GbE are also dumped to files.\n",
+ argv[0], argv[0]);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ int fd; /* file descriptor to flash file */
+ int len; /* file/buffer size in bytes */
+ uint32_t *buf; /* mmap'd file */
+ uint8_t *pMAC;
+ int opt, ret;
+
+ int dump = 0;
+ const char *fn = NULL;
+ const char *csn = NULL;
+ enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
+ struct ich_descriptors desc = {{ 0 }};
+
+ while ((opt = getopt(argc, argv, "df:c:")) != -1) {
+ switch (opt) {
+ case 'd':
+ dump = 1;
+ break;
+ case 'f':
+ fn = optarg;
+ break;
+ case 'c':
+ csn = optarg;
+ break;
+ default: /* '?' */
+ usage(argv, NULL);
+ }
+ }
+ if (fn == NULL)
+ usage(argv,
+ "Need a file name of a descriptor image to read from.");
+
+ fd = open(fn, O_RDONLY);
+ if (fd < 0)
+ usage(argv, "No such file");
+ len = lseek(fd, 0, SEEK_END);
+ if (len < 0)
+ usage(argv, "Seeking to the end of the file failed");
+
+ buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (buf == (void *) -1) {
+ /* fallback for stupid OSes like cygwin */
+ int ret;
+ buf = malloc(len);
+ if (!buf)
+ usage(argv, "Could not allocate memory");
+ lseek(fd, 0, SEEK_SET);
+ ret = read(fd, buf, len);
+ if (ret != len)
+ usage(argv, "Seeking to the end of the file failed");
+ }
+ printf("The flash image has a size of %d [0x%x] bytes.\n", len, len);
+ close(fd);
+
+ if (csn != NULL) {
+ if (strcmp(csn, "ich8") == 0)
+ cs = CHIPSET_ICH8;
+ else if (strcmp(csn, "ich9") == 0)
+ cs = CHIPSET_ICH9;
+ else if (strcmp(csn, "ich10") == 0)
+ cs = CHIPSET_ICH10;
+ else if ((strcmp(csn, "5") == 0) ||
+ (strcmp(csn, "ibex") == 0))
+ cs = CHIPSET_5_SERIES_IBEX_PEAK;
+ else if ((strcmp(csn, "6") == 0) ||
+ (strcmp(csn, "cougar") == 0))
+ cs = CHIPSET_6_SERIES_COUGAR_POINT;
+ else if ((strcmp(csn, "7") == 0) ||
+ (strcmp(csn, "panther") == 0))
+ cs = CHIPSET_7_SERIES_PANTHER_POINT;
+ }
+
+ ret = read_ich_descriptors_from_dump(buf, len, &desc);
+ switch (ret) {
+ case ICH_RET_OK:
+ break;
+ case ICH_RET_ERR:
+ printf("Image not in descriptor mode.\n");
+ exit(1);
+ case ICH_RET_OOB:
+ printf("Tried to access a location out of bounds of the image. "
+ "- Corrupt image?\n");
+ exit(1);
+ default:
+ printf("Unhandled return value at %s:%u, please report this.\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ prettyprint_ich_descriptors(cs, &desc);
+
+ pMAC = (uint8_t *) &buf[ICH_FREG_BASE(desc.region.reg3_base) >> 2];
+ if (len >= ICH_FREG_BASE(desc.region.reg3_base) + 5 && pMAC[0] != 0xff)
+ printf("The MAC address might be at offset 0x%x: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ICH_FREG_BASE(desc.region.reg3_base),
+ pMAC[0], pMAC[1], pMAC[2], pMAC[3], pMAC[4], pMAC[5]);
+
+ if (dump == 1)
+ dump_files(fn, buf, len, &desc.region);
+
+ return 0;
+}
OpenPOWER on IntegriCloud