[flashrom] [PATCH 07/12] add ICH/PCH flash descriptor decoding

Stefan Tauner stefan.tauner at student.tuwien.ac.at
Wed Jun 8 04:55:34 CEST 2011


based on the work of Matthias 'mazzoo' Wenzel this patch adds...
 - pretty printing of those ICH/PCH flash descriptors that are cached/mapped by the chipset
   (and which are therefore reachable via FDOC/FDOD registers) and
 - a new tool to the util directory that is able to decode all flash descriptors stored in a flash
   dump file.

Signed-off-by: Stefan Tauner <stefan.tauner at student.tuwien.ac.at>
---
 Makefile                                         |    2 +-
 ich_descriptors.c                                |  453 ++++++++++++++++++++++
 ich_descriptors.h                                |  408 +++++++++++++++++++
 ichspi.c                                         |   10 +
 util/ich_descriptors_tool/Makefile               |   42 ++
 util/ich_descriptors_tool/TODO                   |    5 +
 util/ich_descriptors_tool/ich_descriptors_tool.c |  226 +++++++++++
 7 files changed, 1145 insertions(+), 1 deletions(-)
 create mode 100644 ich_descriptors.c
 create mode 100644 ich_descriptors.h
 create mode 100644 util/ich_descriptors_tool/Makefile
 create mode 100644 util/ich_descriptors_tool/TODO
 create mode 100644 util/ich_descriptors_tool/ich_descriptors_tool.c

diff --git a/Makefile b/Makefile
index 6e6e2de..b61031f 100644
--- a/Makefile
+++ b/Makefile
@@ -223,7 +223,7 @@ ifeq ($(CONFIG_INTERNAL), yes)
 FEATURE_CFLAGS += -D'CONFIG_INTERNAL=1'
 PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o dmi.o internal.o
 # FIXME: The PROGRAMMER_OBJS below should only be included on x86.
-PROGRAMMER_OBJS += it87spi.o it85spi.o ichspi.o sb600spi.o wbsio_spi.o mcp6x_spi.o
+PROGRAMMER_OBJS += it87spi.o it85spi.o ichspi.o ich_descriptors.o sb600spi.o wbsio_spi.o mcp6x_spi.o
 NEED_PCI := yes
 endif
 
diff --git a/ich_descriptors.c b/ich_descriptors.c
new file mode 100644
index 0000000..0b03624
--- /dev/null
+++ b/ich_descriptors.c
@@ -0,0 +1,453 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * authors:
+ * (c) 2010  Matthias Wenzel <bios at mazzoo dot de>
+ * (c) 2011  Stefan Tauner
+ */
+
+#include "ich_descriptors.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+
+#define DESCRIPTOR_MODE_MAGIC 0x0ff0a55a
+#define msg_pdbg printf
+#include <stdio.h>
+
+struct flash_strap fisba;
+struct flash_upper_map flumap;
+
+#else
+
+#include "flash.h" /* for msg_* */
+
+#endif // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+
+struct flash_descriptor fdbar = { 0 };
+struct flash_component fcba = { {0} };
+struct flash_region frba = { {0} };
+struct flash_master fmba = { {0} };
+
+uint32_t getFCBA()
+{
+	return (fdbar.FLMAP0 <<  4) & 0x00000ff0;
+}
+
+uint32_t getFRBA()
+{
+	return (fdbar.FLMAP0 >> 12) & 0x00000ff0;
+}
+
+uint32_t getFMBA()
+{
+	return (fdbar.FLMAP1 <<  4) & 0x00000ff0;
+}
+
+uint32_t getFMSBA()
+{
+	return (fdbar.FLMAP2 <<  4) & 0x00000ff0;
+}
+
+uint32_t getFLREG_limit(uint32_t flreg)
+{
+	return (flreg >>  4) & 0x01fff000;
+}
+
+uint32_t getFLREG_base(uint32_t flreg)
+{
+	return (flreg << 12) & 0x01fff000;
+}
+
+uint32_t getFISBA()
+{
+	return (fdbar.FLMAP1 >> 12) & 0x00000ff0;
+}
+
+/** Returns the integer representation of the component density with index
+comp in bytes or 0 if a correct size can not be determined. */
+int getFCBA_component_density(uint8_t comp)
+{
+	uint8_t size_enc;
+	const int dec_mem[6] = {
+		      512 * 1024,
+		 1 * 1024 * 1024,
+		 2 * 1024 * 1024,
+		 4 * 1024 * 1024,
+		 8 * 1024 * 1024,
+		16 * 1024 * 1024,
+	};
+
+	switch(comp) {
+	case 0:
+		size_enc = fcba.comp1_density;
+		break;
+	case 1:
+		if (fdbar.NC == 0)
+			return 0;
+		size_enc = fcba.comp2_density;
+		break;
+	default:
+		msg_perr("Only component index 0 or 1 are supported yet.\n");
+		return 0;
+	}
+	if (size_enc > 5) {
+		msg_perr("Density of component with index %d illegal or "
+			 "unsupported. Encoded density is 0x%x.\n",
+			 comp,
+			 size_enc);
+		return 0;
+	}
+	return dec_mem[size_enc];
+}
+
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+uint32_t getVTBA()
+{
+	return (flumap.FLUMAP1 << 4) & 0x0ff0;
+}
+#endif
+
+const struct flash_descriptor_addresses desc_addr = {
+	.FCBA = getFCBA,
+	.FRBA = getFRBA,
+	.FMBA = getFMBA,
+	.FMSBA = getFMSBA,
+	.FISBA = getFISBA,
+	.FLREG_limit = getFLREG_limit,
+	.FLREG_base = getFLREG_base,
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+	.VTBA = getVTBA,
+#endif
+};
+
+void pretty_print_ich_descriptors()
+{
+	pretty_print_ich_descriptor_map();
+	pretty_print_ich_descriptor_component();
+	pretty_print_ich_descriptor_region();
+	pretty_print_ich_descriptor_master();
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+	pretty_print_ich_descriptor_upper_map();
+	/* FIXME: detect chipset correctly */
+	pretty_print_ich_descriptor_straps(CHIPSET_SERIES_5_IBEX_PEAK);
+#endif // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+	msg_pdbg("\n");
+}
+
+void pretty_print_ich_descriptor_map(void)
+{
+	msg_pdbg("=== FDBAR ===\n");
+	msg_pdbg("FLVALSIG 0x%8.8x\n", fdbar.FLVALSIG);
+	msg_pdbg("FLMAP0   0x%8.8x\n", fdbar.FLMAP0  );
+	msg_pdbg("FLMAP1   0x%8.8x\n", fdbar.FLMAP1  );
+	msg_pdbg("FLMAP2   0x%8.8x\n", fdbar.FLMAP2  );
+	msg_pdbg("\n");
+	msg_pdbg("--- FDBAR details ---\n");
+	msg_pdbg("0x%2.2x        NR    Number of Regions\n", fdbar.NR   );
+	msg_pdbg("0x%8.8x  FRBA  Flash Region Base Address\n", desc_addr.FRBA() );
+	msg_pdbg("0x%2.2x        NC    Number of Components\n", fdbar.NC   );
+	msg_pdbg("0x%8.8x  FCBA  Flash Component Base Address\n", desc_addr.FCBA() );
+	msg_pdbg("\n");
+	msg_pdbg("0x%2.2x        ISL   ICH Strap Length\n", fdbar.ISL  );
+	msg_pdbg("0x%8.8x  FISBA Flash ICH Strap Base Address\n", desc_addr.FISBA());
+	msg_pdbg("0x%2.2x        NM    Number of Masters\n", fdbar.NM   );
+	msg_pdbg("0x%8.8x  FMBA  Flash Master Base Address\n", desc_addr.FMBA() );
+	msg_pdbg("\n");
+	msg_pdbg("0x%2.2x        MSL   MCH Strap Length\n", fdbar.MSL  );
+	msg_pdbg("0x%8.8x  FMSBA Flash MCH Strap Base Address\n", desc_addr.FMSBA());
+}
+
+void pretty_print_ich_descriptor_component(void)
+{
+	const char * str_freq[8] = {
+		"20 MHz",		/* 000 */
+		"33 MHz",		/* 001 */
+		"reserved/illegal",	/* 010 */
+		"reserved/illegal",	/* 011 */
+		"50 MHz",		/* 100 */
+		"reserved/illegal",	/* 101 */
+		"reserved/illegal",	/* 110 */
+		"reserved/illegal"	/* 111 */
+	};
+	const char * str_mem[8] = {
+		"512kB",
+		"1 MB",
+		"2 MB",
+		"4 MB",
+		"8 MB",
+		"16 MB",
+		"undocumented/illegal",
+		"reserved/illegal"
+	};
+
+	msg_pdbg("\n");
+	msg_pdbg("=== FCBA ===\n");
+	msg_pdbg("FLCOMP   0x%8.8x\n", fcba.FLCOMP);
+	msg_pdbg("FLILL    0x%8.8x\n", fcba.FLILL );
+	msg_pdbg("\n");
+	msg_pdbg("--- FCBA details ---\n");
+	msg_pdbg("0x%2.2x    freq_read_id   %s\n",
+		fcba.freq_read_id , str_freq[fcba.freq_read_id ]);
+	msg_pdbg("0x%2.2x    freq_write     %s\n",
+		fcba.freq_write   , str_freq[fcba.freq_write   ]);
+	msg_pdbg("0x%2.2x    freq_fastread  %s\n",
+		fcba.freq_fastread, str_freq[fcba.freq_fastread]);
+	msg_pdbg("0x%2.2x    fastread       %ssupported\n",
+		fcba.fastread, fcba.fastread ? "" : "not ");
+	msg_pdbg("0x%2.2x    freq_read      %s\n",
+		fcba.freq_read, str_freq[fcba.freq_read    ]);
+	msg_pdbg("0x%2.2x    comp 1 density %s\n",
+		fcba.comp1_density, str_mem[fcba.comp1_density]);
+	if (fdbar.NC)
+		msg_pdbg("0x%2.2x    comp 2 density %s\n",
+			fcba.comp2_density, str_mem[fcba.comp2_density]);
+	else
+		msg_pdbg("0x%2.2x    comp 2 is not used (FLMAP0.NC=0)\n",
+			fcba.comp2_density);
+	msg_pdbg("\n");
+	msg_pdbg("0x%2.2x    invalid instr 0\n", fcba.invalid_instr0);
+	msg_pdbg("0x%2.2x    invalid instr 1\n", fcba.invalid_instr1);
+	msg_pdbg("0x%2.2x    invalid instr 2\n", fcba.invalid_instr2);
+	msg_pdbg("0x%2.2x    invalid instr 3\n", fcba.invalid_instr3);
+}
+
+void pretty_print_ich_descriptor_region(void)
+{
+	msg_pdbg("\n");
+	msg_pdbg("=== FRBA ===\n");
+	msg_pdbg("FLREG0   0x%8.8x\n", frba.FLREG0);
+	msg_pdbg("FLREG1   0x%8.8x\n", frba.FLREG1);
+	msg_pdbg("FLREG2   0x%8.8x\n", frba.FLREG2);
+	msg_pdbg("FLREG3   0x%8.8x\n", frba.FLREG3);
+	msg_pdbg("\n");
+	msg_pdbg("--- FRBA details ---\n");
+	msg_pdbg("0x%8.8x  region 0 limit (descr)\n", desc_addr.FLREG_limit(frba.FLREG0));
+	msg_pdbg("0x%8.8x  region 0 base  (descr)\n", desc_addr.FLREG_base(frba.FLREG0));
+	msg_pdbg("0x%8.8x  region 1 limit ( BIOS)\n", desc_addr.FLREG_limit(frba.FLREG1));
+	msg_pdbg("0x%8.8x  region 1 base  ( BIOS)\n", desc_addr.FLREG_base(frba.FLREG1));
+	msg_pdbg("0x%8.8x  region 2 limit ( ME  )\n", desc_addr.FLREG_limit(frba.FLREG2));
+	msg_pdbg("0x%8.8x  region 2 base  ( ME  )\n", desc_addr.FLREG_base(frba.FLREG2));
+	msg_pdbg("0x%8.8x  region 3 limit ( GbE )\n", desc_addr.FLREG_limit(frba.FLREG3));
+	msg_pdbg("0x%8.8x  region 3 base  ( GbE )\n", desc_addr.FLREG_base(frba.FLREG3));
+}
+
+void pretty_print_ich_descriptor_master(void)
+{
+	msg_pdbg("\n");
+	msg_pdbg("=== FMBA ===\n");
+	msg_pdbg("FLMSTR1  0x%8.8x\n", fmba.FLMSTR1);
+	msg_pdbg("FLMSTR2  0x%8.8x\n", fmba.FLMSTR2);
+	msg_pdbg("FLMSTR3  0x%8.8x\n", fmba.FLMSTR3);
+
+	msg_pdbg("\n");
+	msg_pdbg("--- FMBA details ---\n");
+	msg_pdbg("BIOS can %s write GbE\n",   fmba.BIOS_GbE_write   ? "   " : "NOT");
+	msg_pdbg("BIOS can %s write ME\n",    fmba.BIOS_ME_write    ? "   " : "NOT");
+	msg_pdbg("BIOS can %s write BIOS\n",  fmba.BIOS_BIOS_write  ? "   " : "NOT");
+	msg_pdbg("BIOS can %s write descr\n", fmba.BIOS_descr_write ? "   " : "NOT");
+	msg_pdbg("BIOS can %s read  GbE\n",   fmba.BIOS_GbE_read    ? "   " : "NOT");
+	msg_pdbg("BIOS can %s read  ME\n",    fmba.BIOS_ME_read     ? "   " : "NOT");
+	msg_pdbg("BIOS can %s read  BIOS\n",  fmba.BIOS_BIOS_read   ? "   " : "NOT");
+	msg_pdbg("BIOS can %s read  descr\n", fmba.BIOS_descr_read  ? "   " : "NOT");
+	msg_pdbg("ME   can %s write GbE\n",   fmba.ME_GbE_write     ? "   " : "NOT");
+	msg_pdbg("ME   can %s write ME\n",    fmba.ME_ME_write      ? "   " : "NOT");
+	msg_pdbg("ME   can %s write BIOS\n",  fmba.ME_BIOS_write    ? "   " : "NOT");
+	msg_pdbg("ME   can %s write descr\n", fmba.ME_descr_write   ? "   " : "NOT");
+	msg_pdbg("ME   can %s read  GbE\n",   fmba.ME_GbE_read      ? "   " : "NOT");
+	msg_pdbg("ME   can %s read  ME\n",    fmba.ME_ME_read       ? "   " : "NOT");
+	msg_pdbg("ME   can %s read  BIOS\n",  fmba.ME_BIOS_read     ? "   " : "NOT");
+	msg_pdbg("ME   can %s read  descr\n", fmba.ME_descr_read    ? "   " : "NOT");
+	msg_pdbg("GbE  can %s write GbE\n",   fmba.GbE_GbE_write    ? "   " : "NOT");
+	msg_pdbg("GbE  can %s write ME\n",    fmba.GbE_ME_write     ? "   " : "NOT");
+	msg_pdbg("GbE  can %s write BIOS\n",  fmba.GbE_BIOS_write   ? "   " : "NOT");
+	msg_pdbg("GbE  can %s write descr\n", fmba.GbE_descr_write  ? "   " : "NOT");
+	msg_pdbg("GbE  can %s read  GbE\n",   fmba.GbE_GbE_read     ? "   " : "NOT");
+	msg_pdbg("GbE  can %s read  ME\n",    fmba.GbE_ME_read      ? "   " : "NOT");
+	msg_pdbg("GbE  can %s read  BIOS\n",  fmba.GbE_BIOS_read    ? "   " : "NOT");
+	msg_pdbg("GbE  can %s read  descr\n", fmba.GbE_descr_read   ? "   " : "NOT");
+}
+
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+void pretty_print_ich_descriptor_straps_ich8(void)
+{
+	const char * str_GPIO12[4] = {
+		"GPIO12",
+		"LAN PHY Power Control Function (Native Output)",
+		" GLAN_DOCK# (Native Input)",
+		"invalid configuration",
+	};
+
+	msg_pdbg("\n");
+	msg_pdbg("=== FISBA ===\n");
+	msg_pdbg("STRP0    0x%8.8x\n", fisba.ich8.STRP0);
+
+	msg_pdbg("\n");
+	msg_pdbg("--- FISBA details ---\n");
+	msg_pdbg("ME SMBus addr2 0x%2.2x\n", fisba.ich8.ASD2);
+	msg_pdbg("ME SMBus addr1 0x%2.2x\n", fisba.ich8.ASD);
+	msg_pdbg("ME SMBus Controller is connected to %s\n", fisba.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
+	msg_pdbg("SPI CS1 is used for %s\n", fisba.ich8.SPICS1_LANPHYPC_SEL ? "LAN PHY Power Control Function" : "SPI Chip Select");
+	msg_pdbg("GPIO12_SEL is used as %s\n", str_GPIO12[fisba.ich8.GPIO12_SEL]);
+	msg_pdbg("PCIe Port 6 is used for %s\n", fisba.ich8.GLAN_PCIE_SEL ? "integrated GLAN" : "PCI Express");
+	msg_pdbg("Intel AMT SMBus Controller 1 is connected to %s\n",   fisba.ich8.BMCMODE ? "SMLink" : "SMBus");
+	msg_pdbg("TCO slave is on %s. Intel AMT SMBus Controller 1 is %sabled\n",
+		fisba.ich8.TCOMODE ? "SMBus" : "SMLink", fisba.ich8.TCOMODE ? "en" : "dis");
+	msg_pdbg("ME A is %sabled\n", fisba.ich8.ME_DISABLE ? "dis" : "en");
+
+	msg_pdbg("\n");
+	msg_pdbg("=== FMSBA ===\n");
+	msg_pdbg("STRP1    0x%8.8x\n", fisba.ich8.STRP1);
+
+	msg_pdbg("\n");
+	msg_pdbg("--- FMSBA details ---\n");
+	msg_pdbg("ME B is %sabled\n", fisba.ich8.ME_disable_B ? "dis" : "en");
+}
+
+void pretty_print_ich_descriptor_straps_ibex(void)
+{
+	int i;
+	msg_pdbg("\n");
+	msg_pdbg("=== FPSBA ===\n");
+	for(i = 0; i <= 15; i++)
+		msg_pdbg("STRP%-2d = 0x%8.8x\n", i, fisba.ibex.STRPs[i]);
+}
+
+void pretty_print_ich_descriptor_straps(enum chipset cs)
+{
+	switch (cs) {
+	case CHIPSET_ICH8:
+		pretty_print_ich_descriptor_straps_ich8();
+		break;
+	case CHIPSET_SERIES_5_IBEX_PEAK:
+		pretty_print_ich_descriptor_straps_ibex();
+		break;
+	default:
+		break;
+	}
+}
+
+void pretty_print_ich_descriptor_upper_map(void)
+{
+	int i;
+	msg_pdbg("\n");
+	msg_pdbg("=== FLUMAP ===\n");
+	msg_pdbg("FLUMAP1  0x%8.8x\n", flumap.FLUMAP1);
+
+	msg_pdbg("\n");
+	msg_pdbg("--- FLUMAP details ---\n");
+	msg_pdbg("VTL   0x%8.8x\n", flumap.VTL);
+	msg_pdbg("VTBA  0x%8.8x\n", desc_addr.VTBA());
+	msg_pdbg("\n");
+
+	for (i=0; i < flumap.VTL/2; i++)
+	{
+		msg_pdbg("  JID%d  = 0x%8.8x\n", i, flumap.vscc_table[i].JID );
+		msg_pdbg("  VSCC%d = 0x%8.8x\n", i, flumap.vscc_table[i].VSCC);
+	}
+}
+
+int read_ich_descriptors_from_dump(uint32_t *dump)
+{
+	int i;
+	uint8_t pch_bug_offset = 0;
+	if (dump[0] != DESCRIPTOR_MODE_MAGIC) {
+		if (dump[4] == DESCRIPTOR_MODE_MAGIC)
+			pch_bug_offset = 4;
+		else
+			return -1;
+	}
+
+	/* map */
+	fdbar.FLVALSIG = dump[0 + pch_bug_offset];
+	fdbar.FLMAP0   = dump[1 + pch_bug_offset];
+	fdbar.FLMAP1   = dump[2 + pch_bug_offset];
+	fdbar.FLMAP2   = dump[3 + pch_bug_offset];
+
+	/* component */
+	fcba.FLCOMP = dump[(desc_addr.FCBA() >> 2) + 0];
+	fcba.FLILL  = dump[(desc_addr.FCBA() >> 2) + 1];
+	fcba.FLPB  = dump[(desc_addr.FCBA() >> 2) + 2];
+
+	/* region */
+	frba.FLREG0 = dump[(desc_addr.FRBA() >> 2) + 0];
+	frba.FLREG1 = dump[(desc_addr.FRBA() >> 2) + 1];
+	frba.FLREG2 = dump[(desc_addr.FRBA() >> 2) + 2];
+	frba.FLREG3 = dump[(desc_addr.FRBA() >> 2) + 3];
+
+	/* master */
+	fmba.FLMSTR1 = dump[(desc_addr.FMBA() >> 2) + 0];
+	fmba.FLMSTR2 = dump[(desc_addr.FMBA() >> 2) + 1];
+	fmba.FLMSTR3 = dump[(desc_addr.FMBA() >> 2) + 2];
+
+	/* upper map */
+	flumap.FLUMAP1 = dump[(0x0efc >> 2) + 0];
+
+	for (i=0; i < flumap.VTL; i++)
+	{
+		flumap.vscc_table[i].JID  = dump[(desc_addr.VTBA() >> 2) + i * 2 + 0];
+		flumap.vscc_table[i].VSCC = dump[(desc_addr.VTBA() >> 2) + i * 2 + 1];
+	}
+	/* straps */
+	/* FIXME: detect chipset correctly */
+	switch (CHIPSET_SERIES_5_IBEX_PEAK) {
+		case CHIPSET_ICH8:
+			fisba.ich8.STRP0 = dump[(desc_addr.FISBA() >> 2) + 0];
+			fisba.ich8.STRP1 = dump[(desc_addr.FMSBA() >> 2) + 0];
+			break;
+		case CHIPSET_SERIES_5_IBEX_PEAK:
+			for(i = 0; i <= 15; i++)
+				fisba.ibex.STRPs[i] = dump[(desc_addr.FISBA() >> 2) + i];
+			break;
+		default:
+			break;
+	}
+
+	return 0;
+}
+#else // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+
+static uint32_t read_descriptor_reg(uint8_t section, uint16_t offset, void *spibar)
+{
+	uint32_t control = 0;
+	control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
+	control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
+	*(volatile uint32_t *) (spibar + ICH9_REG_FDOC) = control;
+	return *(volatile uint32_t *)(spibar + ICH9_REG_FDOD);
+}
+
+void read_ich_descriptors_from_fdo(void *spibar)
+{
+	msg_pdbg("Reading flash descriptors "
+		 "mapped by the chipset via FDOC/FDOD...");
+	/* descriptor map section */
+	fdbar.FLVALSIG = read_descriptor_reg(0, 0, spibar);
+	fdbar.FLMAP0   = read_descriptor_reg(0, 1, spibar);
+	fdbar.FLMAP1   = read_descriptor_reg(0, 2, spibar);
+	fdbar.FLMAP2   = read_descriptor_reg(0, 3, spibar);
+
+	/* component section */
+	fcba.FLCOMP = read_descriptor_reg(1, 0, spibar);
+	fcba.FLILL  = read_descriptor_reg(1, 1, spibar);
+	fcba.FLPB  = read_descriptor_reg(1, 2, spibar);
+
+	/* region section */
+	frba.FLREG0 = read_descriptor_reg(2, 0, spibar);
+	frba.FLREG1 = read_descriptor_reg(2, 1, spibar);
+	frba.FLREG2 = read_descriptor_reg(2, 2, spibar);
+	frba.FLREG3 = read_descriptor_reg(2, 3, spibar);
+
+	/* master section */
+	fmba.FLMSTR1 = read_descriptor_reg(3, 0, spibar);
+	fmba.FLMSTR2 = read_descriptor_reg(3, 1, spibar);
+	fmba.FLMSTR3 = read_descriptor_reg(3, 2, spibar);
+
+	/* strap section and upper map */
+	/* impossible via FDOC/FDOD(?) */
+	msg_pdbg(" done\n");
+}
+
+#endif // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+#endif // defined(__i386__) || defined(__x86_64__)
diff --git a/ich_descriptors.h b/ich_descriptors.h
new file mode 100644
index 0000000..af9d0ba
--- /dev/null
+++ b/ich_descriptors.h
@@ -0,0 +1,408 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * authors:
+ * (c) 2010  Matthias Wenzel <bios at mazzoo dot de>
+ * (c) 2011  Stefan Tauner
+ */
+
+#include <stdint.h>
+
+#if defined(__i386__) || defined(__x86_64__)
+#ifndef __ICH_DESCRIPTORS_H__
+#define __ICH_DESCRIPTORS_H__ 1
+
+/* should probably be in ichspi.h */
+#define ICH9_REG_FDOC		0xB0	/* 32 Bits Flash Descriptor Observability Control */
+#define FDOC_FDSI_OFF		2	/* 2-11: Flash Descriptor Section Select */
+#define FDOC_FDSI		(0x3f << FDOC_FDSI_OFF)
+#define FDOC_FDSS_OFF		12	/* 12-14: Flash Descriptor Section Select */
+#define FDOC_FDSS		(0x3 << FDOC_FDSS_OFF)
+#define ICH9_REG_FDOD		0xB4	/* 32 Bits Flash Descriptor Observability Data */
+
+enum chipset {
+	CHIPSET_ICH8,
+	CHIPSET_ICH9,
+	CHIPSET_ICH10,
+	CHIPSET_SERIES_5_IBEX_PEAK,
+	CHIPSET_SERIES_6_COUGAR_POINT,
+	CHIPSET_SERIES_7_PANTHER_POINT
+};
+
+struct flash_descriptor_addresses {
+	uint32_t (*FCBA)(void);
+	uint32_t (*FRBA)(void);
+	uint32_t (*FMBA)(void);
+	uint32_t (*FMSBA)(void);
+	uint32_t (*FLREG_limit)(uint32_t flreg);
+	uint32_t (*FLREG_base)(uint32_t flreg);
+	uint32_t (*FISBA)(void);
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+	uint32_t (*VTBA)(void);
+#endif // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+};
+	
+struct flash_descriptor {
+	uint32_t FLVALSIG;	/* 0x00 */
+	union {			/* 0x04 */
+		uint32_t FLMAP0;
+		struct {
+			uint8_t FCBA	:8;
+			uint8_t NC	:2;
+			unsigned	:6;
+			uint8_t FRBA	:8;
+			uint8_t NR	:3;
+			unsigned	:5;
+		};
+	};
+	union {			/* 0x08 */
+		uint32_t FLMAP1;
+		struct {
+			uint8_t FMBA	:8;
+			uint8_t NM	:3;
+			unsigned	:5;
+			union {
+				uint8_t FISBA	:8;
+				uint8_t FPSBA	:8;
+			};
+			uint8_t ISL	:8;
+		};
+	};
+	union {			/* 0x0c */
+		uint32_t FLMAP2;
+		struct {
+			uint8_t  FMSBA	:8;
+			uint8_t  MSL	:8;
+			unsigned	:16;
+		};
+	};
+};
+
+struct flash_component {
+	union {			/* 0x00 */
+		uint32_t FLCOMP;
+		struct {
+			uint8_t  comp1_density	:3;
+			uint8_t  comp2_density	:3;
+			unsigned		:11;
+			uint8_t  freq_read	:3;
+			uint8_t  fastread	:1;
+			uint8_t  freq_fastread	:3;
+			uint8_t  freq_write	:3;
+			uint8_t  freq_read_id	:3;
+			unsigned		:2;
+		};
+	};
+	union {			/* 0x04 */
+		uint32_t FLILL;
+		struct {
+			uint8_t invalid_instr0;
+			uint8_t invalid_instr1;
+			uint8_t invalid_instr2;
+			uint8_t invalid_instr3;
+		};
+	};
+	union {			/* 0x08 */
+		uint32_t FLPB;
+		struct {
+			uint16_t FPBA	:13;
+			unsigned	:19;
+		};
+	};
+};
+
+struct flash_region {
+	
+	union {
+		uint32_t FLREG0; /* Flash Descriptor */
+		struct {
+			uint16_t reg0_base	:13;
+			unsigned		:3;
+			uint16_t reg0_limit	:13;
+			unsigned		:3;
+		};
+	};
+	union {
+		uint32_t FLREG1; /* BIOS */
+		struct {
+			uint16_t reg1_base	:13;
+			unsigned		:3;
+			uint16_t reg1_limit	:13;
+			unsigned		:3;
+		};
+	};
+	union {
+		uint32_t FLREG2; /* ME */
+		struct {
+			uint16_t reg2_base	:13;
+			unsigned		:3;
+			uint16_t reg2_limit	:13;
+			unsigned		:3;
+		};
+	};
+	union {
+		uint32_t FLREG3; /* GbE */
+		struct {
+			uint16_t reg3_base	:13;
+			unsigned		:3;
+			uint16_t reg3_limit	:13;
+			unsigned		:3;
+		};
+	};
+} frba;
+
+struct flash_master {
+	union {
+		uint32_t FLMSTR1;
+		struct {
+			uint16_t BIOS_req_ID		:16;
+			uint8_t  BIOS_descr_read	:1;
+			uint8_t  BIOS_BIOS_read		:1;
+			uint8_t  BIOS_ME_read		:1;
+			uint8_t  BIOS_GbE_read		:1;
+			uint8_t  BIOS_plat_read		:1;
+			unsigned			:3;
+			uint8_t  BIOS_descr_write	:1;
+			uint8_t  BIOS_BIOS_write	:1;
+			uint8_t  BIOS_ME_write		:1;
+			uint8_t  BIOS_GbE_write		:1;
+			uint8_t  BIOS_plat_write	:1;
+			unsigned			:3;
+		};
+	};
+	union {
+		uint32_t FLMSTR2;
+		struct {
+			uint16_t ME_req_ID		:16;
+			uint8_t  ME_descr_read	:1;
+			uint8_t  ME_BIOS_read		:1;
+			uint8_t  ME_ME_read		:1;
+			uint8_t  ME_GbE_read		:1;
+			uint8_t  ME_plat_read		:1;
+			unsigned			:3;
+			uint8_t  ME_descr_write		:1;
+			uint8_t  ME_BIOS_write		:1;
+			uint8_t  ME_ME_write		:1;
+			uint8_t  ME_GbE_write		:1;
+			uint8_t  ME_plat_write		:1;
+			unsigned			:3;
+		};
+	};
+	union {
+		uint32_t FLMSTR3;
+		struct {
+			uint16_t GbE_req_ID		:16;
+			uint8_t  GbE_descr_read		:1;
+			uint8_t  GbE_BIOS_read		:1;
+			uint8_t  GbE_ME_read		:1;
+			uint8_t  GbE_GbE_read		:1;
+			uint8_t  GbE_plat_read		:1;
+			unsigned			:3;
+			uint8_t  GbE_descr_write	:1;
+			uint8_t  GbE_BIOS_write		:1;
+			uint8_t  GbE_ME_write		:1;
+			uint8_t  GbE_GbE_write		:1;
+			uint8_t  GbE_plat_write		:1;
+			unsigned			:3;
+		};
+	};
+};
+
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+struct flash_strap {
+	union {
+		struct {
+			union {
+				uint32_t STRP0;
+				struct {
+					uint8_t  ME_DISABLE		:1;
+					unsigned			:6;
+					uint8_t  TCOMODE		:1;
+					uint8_t  ASD			:7;
+					uint8_t  BMCMODE		:1;
+					unsigned			:3;
+					uint8_t  GLAN_PCIE_SEL		:1;
+					uint8_t  GPIO12_SEL		:2;
+					uint8_t  SPICS1_LANPHYPC_SEL	:1;
+					uint8_t  MESM2SEL		:1;
+					unsigned			:1;
+					uint8_t  ASD2			:7;
+				};
+			};
+			union {
+				uint32_t STRP1;
+				struct {
+					uint8_t  ME_disable_B		:1;
+					unsigned			:31;
+				};
+			};
+		}ich8;
+		union {
+			uint32_t STRPs[15];
+			struct {
+				union {
+					uint32_t STRP0;
+					struct {
+						unsigned			:1;
+						uint8_t  cs_ss2			:1;
+						unsigned			:5;
+						uint8_t  SMB_EN			:1;
+						uint8_t  SML0_EN		:1;
+						uint8_t  SML1_EN		:1;
+						uint8_t  SML1FRQ		:2;
+						uint8_t  SMB0FRQ		:2;
+						uint8_t  SML0FRQ		:2;
+						unsigned			:4;
+						uint8_t  LANPHYPC_GP12_SEL	:1;
+						uint8_t  cs_ss1			:1;
+						unsigned			:2;
+						uint8_t  DMI_REQID_DIS		:1;
+						unsigned			:4;
+						uint8_t  BBBS			:2;
+						unsigned			:1;
+					};
+				};
+				union {
+					uint32_t STRP1;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP2;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP3;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP4;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP5;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP6;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP7;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP8;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP9;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP10;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP11;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP12;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP13;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP14;
+					struct {
+					};
+				};
+				union {
+					uint32_t STRP15;
+					struct {
+					};
+				};
+			};
+		}ibex;
+	};
+};
+
+struct flash_upper_map {
+	union {
+		uint32_t FLUMAP1;
+		struct {
+			uint8_t  VTBA	:8;
+			uint8_t  VTL	:8;
+			unsigned	:16;
+		};
+	};
+	struct {
+		union {
+			uint32_t JID;
+			struct {
+				uint8_t vid	:8;
+				uint8_t cid0	:8;
+				uint8_t cid1	:8;
+				unsigned	:8;
+			};
+		};
+		union {
+			uint32_t VSCC;
+			struct {
+				uint8_t  ubes	:2;
+				uint8_t  uwg	:1;
+				uint8_t  uwsr	:1;
+				uint8_t  uwews	:1;
+				unsigned	:3;
+				uint8_t  ueo	:8;
+				uint8_t  lbes	:2;
+				uint8_t  lwg	:1;
+				uint8_t  lwsr	:1;
+				uint8_t  lwews	:1;
+				unsigned	:3;
+				uint16_t leo	:16;
+			};
+		};
+	}vscc_table[128];
+};
+#endif // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+
+void pretty_print_ich_descriptors(void);
+
+void pretty_print_ich_descriptor_map(void);
+void pretty_print_ich_descriptor_component(void);
+void pretty_print_ich_descriptor_region(void);
+void pretty_print_ich_descriptor_master(void);
+
+int getFCBA_component_density(uint8_t comp);
+
+#ifdef ICH_DESCRIPTORS_FROM_MMAP_DUMP
+
+void pretty_print_ich_descriptor_upper_map(void);
+void pretty_print_ich_descriptor_straps(enum chipset cs);
+int read_ich_descriptors_from_dump(uint32_t *dump);
+
+#else // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+
+void read_ich_descriptors_from_fdo(void *spibar);
+
+#endif // ICH_DESCRIPTORS_FROM_MMAP_DUMP
+
+#endif // __ICH_DESCRIPTORS_H__
+#endif // defined(__i386__) || defined(__x86_64__)
diff --git a/ichspi.c b/ichspi.c
index 584cab4..d8df898 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2008 Dominik Geyer <dominik.geyer at kontron.com>
  * Copyright (C) 2008 coresystems GmbH <info at coresystems.de>
  * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
+ * 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
@@ -41,6 +42,7 @@
 #include "chipdrivers.h"
 #include "programmer.h"
 #include "spi.h"
+#include "ich_descriptors.h"
 
 /* ICH9 controller register definition */
 #define ICH9_REG_HSFS		0x04	/* 16 Bits Hardware Sequencing Flash Status */
@@ -1197,6 +1199,7 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
 	uint8_t old, new;
 	uint16_t spibar_offset, tmp2;
 	uint32_t tmp;
+	int ichspi_desc = 0;
 
 	switch (ich_generation) {
 	case 7:
@@ -1268,6 +1271,8 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
 			msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");
 			ichspi_lock = 1;
 		}
+		if (tmp2 & HSFS_FDV)
+			ichspi_desc = 1;
 
 		tmp2 = mmio_readw(ich_spibar + ICH9_REG_HSFC);
 		msg_pdbg("0x06: 0x%04x (HSFC)\n", tmp2);
@@ -1316,6 +1321,11 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
 		ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR);
 		msg_pdbg("0xA0: 0x%08x (BBAR)\n",
 			     ichspi_bbar);
+		msg_pdbg("\n");
+		if (ichspi_desc) {
+			read_ich_descriptors_from_fdo(ich_spibar);
+			pretty_print_ich_descriptors();
+		}
 		ich_init_opcodes();
 		break;
 	default:
diff --git a/util/ich_descriptors_tool/Makefile b/util/ich_descriptors_tool/Makefile
new file mode 100644
index 0000000..9b1d096
--- /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 dump arrays
+CFLAGS += -D ICH_DESCRIPTORS_FROM_MMAP_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 NOT share object files with flashrom,
+# which would lead to unexpected results otherwise (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
\ No newline at end of file
diff --git a/util/ich_descriptors_tool/TODO b/util/ich_descriptors_tool/TODO
new file mode 100644
index 0000000..e3933ee
--- /dev/null
+++ b/util/ich_descriptors_tool/TODO
@@ -0,0 +1,5 @@
+- reverse the path, as in 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
+- handle descriptors of various chipsets correctly
\ No newline at end of file
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..8ce7677
--- /dev/null
+++ b/util/ich_descriptors_tool/ich_descriptors_tool.c
@@ -0,0 +1,226 @@
+/*
+ * dump information and binaries from BIOS images that are in descriptor mode/soft-strap
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * authors:
+ * (c) 2010  Matthias Wenzel <bios at mazzoo dot de>
+ * (c) 2011  Stefan Tauner
+ *
+ * */
+#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 "flash.h"
+#include "ich_descriptors.h"
+
+extern struct flash_descriptor fdbar;
+extern struct flash_component fcba;
+extern struct flash_region frba;
+extern struct flash_master fmba;
+extern struct flash_strap fisba;
+extern struct flash_upper_map flumap;
+extern struct flash_descriptor_addresses desc_addr;
+
+static int f;         /* file descriptor to flash file */
+static int fs;        /* file size */
+static uint32_t *fm; /* mmap'd file */
+
+void dump_file_descriptor(char * fn)
+{
+	char * n = malloc(strlen(fn) + 11);
+	snprintf(n, strlen(fn) + 11, "%s.descr.bin", fn);
+	printf("\n");
+	printf("+++ dumping %s ... ", n);
+	int fh = open(n, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+	free(n);
+	if (fh < 0)
+	{
+		printf("ERROR: couldn't open(%s): %s\n", n, strerror(errno));
+		exit(1);
+	}
+
+	int ret;
+	ret = write(fh, &fm[frba.reg0_base >> 2], frba.reg0_limit);
+	if (ret != frba.reg0_limit)
+	{
+		printf("FAILED.\n");
+		exit(1);
+	}
+
+	printf("done.\n");
+
+	close(fh);
+}
+
+void dump_file_BIOS(char * fn)
+{
+	char * n = malloc(strlen(fn) + 10);
+	snprintf(n, strlen(fn) + 10, "%s.BIOS.bin", fn);
+	printf("\n");
+	printf("+++ dumping %s ... ", n);
+	int fh = open(n, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+	free(n);
+	if (fh < 0)
+	{
+		printf("ERROR: couldn't open(%s): %s\n", n, strerror(errno));
+		exit(1);
+	}
+
+	int ret;
+	ret = write(fh, &fm[frba.reg1_base >> 2], frba.reg1_limit);
+	if (ret != frba.reg1_limit)
+	{
+		printf("FAILED.\n");
+		exit(1);
+	}
+
+	printf("done.\n");
+
+	close(fh);
+}
+
+void dump_file_ME(char * fn)
+{
+	char * n = malloc(strlen(fn) + 8);
+	snprintf(n, strlen(fn) + 8, "%s.ME.bin", fn);
+	printf("\n");
+	printf("+++ dumping %s ... ", n);
+	int fh = open(n, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+	free(n);
+	if (fh < 0)
+	{
+		printf("ERROR: couldn't open(%s): %s\n", n, strerror(errno));
+		exit(1);
+	}
+
+	int ret;
+	ret = write(fh, &fm[frba.reg2_base >> 2], frba.reg2_limit);
+	if (ret != frba.reg2_limit)
+	{
+		printf("FAILED.\n");
+		exit(1);
+	}
+
+	printf("done.\n");
+
+	close(fh);
+}
+
+void dump_file_GbE(char * fn)
+{
+	char * n = malloc(strlen(fn) + 9);
+	snprintf(n, strlen(fn) + 9, "%s.GbE.bin", fn);
+	printf("\n");
+	printf("+++ dumping %s ... ", n);
+	int fh = open(n, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+	free(n);
+	if (fh < 0)
+	{
+		printf("ERROR: couldn't open(%s): %s\n", n, strerror(errno));
+		exit(1);
+	}
+
+	int ret;
+	ret = write(fh, &fm[frba.reg3_base >> 2], frba.reg3_limit);
+	if (ret != frba.reg3_limit)
+	{
+		printf("FAILED.\n");
+		exit(1);
+	}
+
+	printf("done.\n");
+	uint8_t * pMAC = (uint8_t *) &fm[frba.reg3_base >> 2];
+	printf("the MAC-address might be: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
+		pMAC[0],
+		pMAC[1],
+		pMAC[2],
+		pMAC[3],
+		pMAC[4],
+		pMAC[5]
+		);
+
+	close(fh);
+}
+
+void dump_files(char * n)
+{
+	printf("=== dumping section files ===\n");
+	if (frba.reg0_limit)
+		dump_file_descriptor(n);
+	if (frba.reg1_limit)
+		dump_file_BIOS(n);
+	if (frba.reg2_limit)
+		dump_file_ME(n);
+	if (frba.reg3_limit)
+		dump_file_GbE(n);
+}
+
+void usage(char ** argv, char* error)
+{
+	printf("%s\n", error);
+	printf("\n");
+	printf("usage: '%s <bios image file> [-d]'\n", argv[0]);
+	printf("\n");
+	printf("\twhere <bios image file> isn't actually a BIOS image, but the SPI flash\n");
+	printf("\tcontents of the SPI connected to your intel chipset.\n");
+	printf("\tIn case that image is really in descriptor mode (a.k.a soft-strap)\n");
+	printf("\t%s will pretty print all relevant information.\n", argv[0]);
+	printf("\tIf '-d' is specified as the second parameter some sections such as\n");
+	printf("\tthe real BIOS image as seen by the CPU or a GbE blob that is\n");
+	printf("\trequired to initialize your ICH GbE are also dumped to files.\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	if (argc < 2)
+		usage(argv, "Need at least one parameter");
+	f = open(argv[1], O_RDONLY);
+	if (f < 0)
+		usage(argv, "No such file");
+	if (argc >= 3 && (strcmp("-d", argv[2]) == 0))
+		usage(argv, "Bogus second argument");
+
+	fs = lseek(f, 0, SEEK_END);
+	if (fs < 0)
+		usage(argv, "Seeking to the end of the file failed");
+
+	fm = mmap(NULL, fs, PROT_READ, MAP_PRIVATE, f, 0);
+	if (fm == (void *) -1)
+	{
+		/* fallback for stupid OSes like cygwin */
+		int ret;
+		fm = malloc(fs);
+		if (!fm)
+			usage(argv, "Could not allocate memory");
+		lseek(f, 0, SEEK_SET);
+		ret = read(f, fm, fs);
+		if (ret != fs)
+			usage(argv, "Seeking to the end of the file failed");
+	}
+	printf("flash image is %d [0x%x] bytes\n", fs, fs);
+	close(f);
+
+	if(read_ich_descriptors_from_dump(fm)){
+		printf("not in descriptor mode\n");
+		exit(1);
+	}
+
+	pretty_print_ich_descriptors();
+
+	if (argc >= 3)
+		dump_files(argv[1]);
+
+	return 0;
+}
+
-- 
1.7.1





More information about the flashrom mailing list