additionally to what is available via FDOC/FDOD this allows to access:
 - the softstraps which are used to configure the chipset by flash content 
without the need
   for BIOS routines. on ICH8 it is possible to read those with FDOC/FDOC too, 
but this was
   removed in later chipsets.
 - the ME VSCC (Vendor Specific Component Capabilities) table.
   simply put, this is an SPI chip database used to figure out the flash's 
capabilities

Signed-off-by: Stefan Tauner <stefan.tau...@student.tuwien.ac.at>
---
 ich_descriptors.c                                |  399 ++++++++++++++++++++++
 ich_descriptors.h                                |  206 +++++++++++-
 util/ich_descriptors_tool/Makefile               |   63 ++++
 util/ich_descriptors_tool/TODO                   |    6 +
 util/ich_descriptors_tool/ich_descriptors_tool.c |  225 ++++++++++++
 5 files changed, 898 insertions(+), 1 deletions(-)
 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/ich_descriptors.c b/ich_descriptors.c
index 8076b09..57c1d51 100644
--- a/ich_descriptors.c
+++ b/ich_descriptors.c
@@ -22,9 +22,33 @@
 #if defined(__i386__) || defined(__x86_64__)
 
 #include "ich_descriptors.h"
+
+#ifdef ICH_DESCRIPTORS_FROM_DUMP
+
+#include <stdio.h>
+#define msg_perr printf
+#define msg_pdbg printf
+#define msg_pdbg2 printf
+#define msg_pspew printf
+#define print(t, ...) printf(__VA_ARGS__)
+#define DESCRIPTOR_MODE_SIGNATURE 0x0ff0a55a
+/* The upper map is located in the word before the 256B-long OEM section at the
+ * end of the 4kB-long flash descriptor.
+ */
+#define UPPER_MAP_OFFSET (4096 - 256 - 4)
+#define getVTBA(flumap)        (((flumap)->FLUMAP1 << 4) & 0x00000ff0)
+
+#else /* ICH_DESCRIPTORS_FROM_DUMP */
+
 #include "flash.h" /* for msg_* */
 #include "programmer.h"
 
+#endif /* ICH_DESCRIPTORS_FROM_DUMP */
+
+#ifndef min
+#define min(a, b) (a < b) ? a : b
+#endif
+
 void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity)
 {
        print(verbosity, "BES=0x%x, ",  (reg_val & VSCC_BES)  >> VSCC_BES_OFF);
@@ -48,6 +72,12 @@ void prettyprint_ich_descriptors(enum ich_chipset cs, const 
struct ich_descripto
        prettyprint_ich_descriptor_component(desc);
        prettyprint_ich_descriptor_region(desc);
        prettyprint_ich_descriptor_master(&desc->master);
+#ifdef ICH_DESCRIPTORS_FROM_DUMP
+       if (cs >= CHIPSET_ICH8) {
+               prettyprint_ich_descriptor_upper_map(&desc->upper);
+               prettyprint_ich_descriptor_straps(cs, desc);
+       }
+#endif /* ICH_DESCRIPTORS_FROM_DUMP */
 }
 
 void prettyprint_ich_descriptor_content(const struct ich_desc_content *cont)
@@ -214,6 +244,374 @@ void prettyprint_ich_descriptor_master(const struct 
ich_desc_master *mstr)
        msg_pdbg2("\n");
 }
 
+#ifdef ICH_DESCRIPTORS_FROM_DUMP
+
+void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
+{
+       static const char * const str_GPIO12[4] = {
+               "GPIO12",
+               "LAN PHY Power Control Function (Native Output)",
+               "GLAN_DOCK# (Native Input)",
+               "invalid configuration",
+       };
+
+
+       msg_pdbg2("--- MCH details ---\n");
+       msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
+       msg_pdbg2("\n");
+
+       msg_pdbg2("--- ICH details ---\n");
+       msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
+       msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
+       msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
+                 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
+       msg_pdbg2("SPI CS1 is used for %s.\n",
+                 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
+                 "LAN PHY Power Control Function" :
+                 "SPI Chip Select");
+       msg_pdbg2("GPIO12 Select is used as %s.\n",
+                 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
+       msg_pdbg2("PCIe Port 6 is used for %s.\n",
+            desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
+       msg_pdbg2("%sn BMC Mode: "
+                 "Intel AMT SMBus Controller 1 is connected to %s.\n",
+                 desc->south.ich8.BMCMODE ? "I" : "Not i",
+                 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
+       msg_pdbg2("TCO is in %s Mode.\n",
+              desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
+       msg_pdbg2("ME A is %sabled.\n",
+                 desc->south.ich8.ME_DISABLE ? "dis" : "en");
+       msg_pdbg2("\n");
+}
+
+static void prettyprint_ich_descriptor_straps_ibex_pciecs(uint8_t conf, 
uint8_t off)
+{
+       msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
+
+       off *= 4;
+       switch(conf){
+       case 0:
+               msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
+               break;
+       case 1:
+               msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
+                         "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
+               break;
+       case 2:
+               msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
+                         "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
+               break;
+       case 3:
+               msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
+                         1+off, 2+off, 4+off);
+               break;
+       }
+       msg_pdbg2("\n");
+}
+
+void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap 
*s)
+{
+       static const uint8_t const dec_t209min[4] = {
+               100,
+               50,
+               5,
+               1
+       };
+
+       msg_pdbg2("--- PCH ---\n");
+
+       /* PCHSTRP1 */
+       msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
+       msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
+                 s->ibex.SMB_EN ? "en" : "dis");
+       msg_pdbg2("SMLink0 segment is %sabled.\n",
+                 s->ibex.SML0_EN ? "en" : "dis");
+       msg_pdbg2("SMLink1 segment is %sabled.\n",
+                 s->ibex.SML1_EN ? "en" : "dis");
+       msg_pdbg2("SMLink1 Frequency: %s\n",
+                 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
+       msg_pdbg2("Intel ME SMBus Frequency: %s\n",
+                 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
+       msg_pdbg2("SMLink0 Frequency: %s\n",
+                 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
+       msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
+                 "LAN_PHY_PWR_CTRL" : "general purpose output");
+
+       /* PCHSTRP2 */
+       msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
+
+       /* PCHSTRP3 */
+       msg_pdbg2("ME SMBus ASD address is %sabled.\n",
+                 s->ibex.MESMASDEN ? "en" : "dis");
+       msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
+                 s->ibex.MESMASDA);
+       msg_pdbg2("ME SMBus I2C address is %sabled.\n",
+                 s->ibex.MESMI2CEN ? "en" : "dis");
+       msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
+                 s->ibex.MESMI2CA);
+
+       /* PCHSTRP4 */
+       /* PCHSTRP5 */
+       msg_pdbg2("Intel PHY is %s.\n",
+                 (s->ibex.PHYCON == 2) ? "connected" :
+                         (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
+       msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
+                 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
+       msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
+                 s->ibex.GBEMAC_SMBUS_ADDR);
+       msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
+                 s->ibex.GBEPHY_SMBUS_ADDR);
+
+       /* PCHSTRP6 */
+       /* PCHSTRP7 */
+       msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
+                 s->ibex.MESMA2UDID_VENDOR);
+       msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
+                 s->ibex.MESMA2UDID_VENDOR);
+
+       /* PCHSTRP8 */
+       /* PCHSTRP9 */
+       prettyprint_ich_descriptor_straps_ibex_pciecs(s->ibex.PCIEPCS1, 0);
+       prettyprint_ich_descriptor_straps_ibex_pciecs(s->ibex.PCIEPCS1, 1);
+       msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
+                 s->ibex.PCIELR1 ? "" : "not ");
+       msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
+                 s->ibex.PCIELR2 ? "" : "not ");
+       msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
+                 s->ibex.DMILR ? "" : "not ");
+       msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
+       msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
+                 s->ibex.PHY_PCIE_EN ? "en" : "dis");
+
+       /* PCHSTRP10 */
+       msg_pdbg2("Management Engine will boot from %sflash.\n",
+                 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
+       msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
+       msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
+                 s->ibex.VE_EN ? "en" : "dis");
+       msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
+                 s->ibex.MMDDE ? "en" : "dis");
+       msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
+                 s->ibex.MMADDR);
+       msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
+       msg_pdbg2("Integrated Clocking Configuration is %d.\n",
+                 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
+       msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
+                 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
+
+       /* PCHSTRP11 */
+       msg_pdbg2("SMLink1 GP Address is %sabled.\n",
+                 s->ibex.SML1GPAEN ? "en" : "dis");
+       msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
+                 s->ibex.SML1GPA);
+       msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
+                 s->ibex.SML1I2CAEN ? "en" : "dis");
+       msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
+                 s->ibex.SML1I2CA);
+
+       /* PCHSTRP12 */
+       /* PCHSTRP13 */
+       /* PCHSTRP14 */
+       msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
+                 s->ibex.VE_EN2 ? "en" : "dis");
+       msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
+                 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
+       msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
+                 s->ibex.BW_SSD ? "en" : "dis");
+       msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
+                 s->ibex.NVMHCI_EN ? "en" : "dis");
+
+       /* PCHSTRP15 */
+       msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
+       msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
+                 s->ibex.IWL_EN ? "en" : "dis");
+       msg_pdbg2("t209 min Timing: %d ms\n",
+                 dec_t209min[s->ibex.t209min]);
+       msg_pdbg2("\n");
+}
+
+void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct 
ich_descriptors *desc)
+{
+       unsigned int i, max;
+       msg_pdbg2("=== Softstraps ===\n");
+
+       if (sizeof(desc->north.STRPs) / 4 + 1 < desc->content.MSL) {
+               max = sizeof(desc->north.STRPs) / 4 + 1;
+               msg_pdbg2("MSL (%u) is greater than the current maximum of %u "
+                         "entries.\n", desc->content.MSL, max + 1);
+               msg_pdbg2("Only the first %u entries will be printed.\n", max);
+       } else
+               max = desc->content.MSL;
+
+       msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max);
+       for(i = 0; i < max; i++)
+               msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
+       msg_pdbg2("\n");
+
+       if (sizeof(desc->south.STRPs) / 4 < desc->content.ISL) {
+               max = sizeof(desc->south.STRPs) / 4;
+               msg_pdbg2("ISL (%u) is greater than the current maximum of %u "
+                         "entries.\n", desc->content.ISL, max);
+               msg_pdbg2("Only the first %u entries will be printed.\n", max);
+       } else
+               max = desc->content.ISL;
+
+       msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max);
+       for(i = 0; i < max; i++)
+               msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
+       msg_pdbg2("\n");
+
+       switch (cs) {
+       case CHIPSET_ICH8:
+               if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
+                       msg_pdbg2("Detailed North/MCH/PROC information is "
+                                 "probably not reliable, printing anyway.\n");
+               if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
+                       msg_pdbg2("Detailed South/ICH/PCH information is "
+                                 "probably not reliable, printing anyway.\n");
+               prettyprint_ich_descriptor_straps_ich8(desc);
+               break;
+       case CHIPSET_5_SERIES_IBEX_PEAK:
+               /* PCH straps only. PROCSTRPs are unknown. */
+               if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
+                       msg_pdbg2("Detailed South/ICH/PCH information is "
+                                 "probably not reliable, printing anyway.\n");
+               prettyprint_ich_descriptor_straps_ibex(&desc->south);
+               break;
+       case CHIPSET_ICH_UNKNOWN:
+               break;
+       default:
+               msg_pdbg2("The meaning of the descriptor straps are unknown "
+                         "yet.\n\n");
+               break;
+       }
+}
+
+void prettyprint_rdid(uint32_t reg_val)
+{
+       uint8_t mid = reg_val & 0xFF;
+       uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
+       msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
+}
+
+void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map 
*umap)
+{
+       int i;
+       msg_pdbg2("=== Upper Map Section ===\n");
+       msg_pdbg2("FLUMAP1  0x%08x\n", umap->FLUMAP1);
+       msg_pdbg2("\n");
+
+       msg_pdbg2("--- Details ---\n");
+       msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
+       msg_pdbg2("VTBA (base address)    = 0x%6.6x\n", getVTBA(umap));
+       msg_pdbg2("\n");
+
+       msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
+       for (i = 0; i < umap->VTL/2; i++)
+       {
+               uint32_t jid = umap->vscc_table[i].JID;
+               uint32_t vscc = umap->vscc_table[i].VSCC;
+               msg_pdbg2("  JID%d  = 0x%08x\n", i, jid);
+               msg_pdbg2("  VSCC%d = 0x%08x\n", i, vscc);
+               msg_pdbg2("    "); /* indention */
+               prettyprint_rdid(jid);
+               msg_pdbg2("    "); /* indention */
+               prettyprint_ich_reg_vscc(vscc, 0);
+       }
+       msg_pdbg2("\n");
+}
+
+/* len is the length of dump in bytes */
+int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, 
enum ich_chipset cs, struct ich_descriptors *desc)
+{
+       unsigned int i, max;
+       uint8_t pch_bug_offset = 0;
+
+       if (dump == NULL || desc == NULL)
+               return RET_PARAM;
+
+       if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
+               if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
+                       pch_bug_offset = 4;
+               else
+                       return RET_ERR;
+       }
+
+       /* map */
+       if (len < (4 + pch_bug_offset) * 4 - 1)
+               return RET_OOB;
+       desc->content.FLVALSIG  = dump[0 + pch_bug_offset];
+       desc->content.FLMAP0    = dump[1 + pch_bug_offset];
+       desc->content.FLMAP1    = dump[2 + pch_bug_offset];
+       desc->content.FLMAP2    = dump[3 + pch_bug_offset];
+
+       /* component */
+       if (len < (getFCBA(&desc->content) + 3 * 4 - 1))
+               return RET_OOB;
+       desc->component.FLCOMP  = dump[(getFCBA(&desc->content) >> 2) + 0];
+       desc->component.FLILL   = dump[(getFCBA(&desc->content) >> 2) + 1];
+       desc->component.FLPB    = dump[(getFCBA(&desc->content) >> 2) + 2];
+
+       /* region */
+       if (len < (getFRBA(&desc->content) + 5 * 4 - 1))
+               return RET_OOB;
+       desc->region.FLREGs[0] = dump[(getFRBA(&desc->content) >> 2) + 0];
+       desc->region.FLREGs[1] = dump[(getFRBA(&desc->content) >> 2) + 1];
+       desc->region.FLREGs[2] = dump[(getFRBA(&desc->content) >> 2) + 2];
+       desc->region.FLREGs[3] = dump[(getFRBA(&desc->content) >> 2) + 3];
+       desc->region.FLREGs[4] = dump[(getFRBA(&desc->content) >> 2) + 4];
+
+       /* master */
+       if (len < (getFMBA(&desc->content) + 3 * 4 - 1))
+               return RET_OOB;
+       desc->master.FLMSTR1 = dump[(getFMBA(&desc->content) >> 2) + 0];
+       desc->master.FLMSTR2 = dump[(getFMBA(&desc->content) >> 2) + 1];
+       desc->master.FLMSTR3 = dump[(getFMBA(&desc->content) >> 2) + 2];
+
+       /* upper map */
+       desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
+
+       /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
+        * "Identifies the 1s based number of DWORDS contained in the VSCC
+        * Table. Each SPI component entry in the table is 2 DWORDS long." So
+        * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
+        * check ensures that the maximum offset actually accessed is available.
+        */
+       if (len < (getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8) - 1))
+               return RET_OOB;
+
+       for (i = 0; i < desc->upper.VTL/2; i++) {
+               desc->upper.vscc_table[i].JID  =
+                                dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
+               desc->upper.vscc_table[i].VSCC =
+                                dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
+       }
+
+       /* MCH/PROC (aka. North) straps */
+       if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
+               return RET_OOB;
+
+       /* limit the range to be written */
+       max = min(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
+       for (i = 0; i < max; i++)
+                       desc->north.STRPs[i] =
+                                     dump[(getFMSBA(&desc->content) >> 2) + i];
+
+       /* ICH/PCH (aka. South) straps */
+       if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
+               return RET_OOB;
+
+       /* limit the range to be written */
+       max = min(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
+       for (i = 0; i < max; i++)
+                       desc->south.STRPs[i] =
+                                     dump[(getFISBA(&desc->content) >> 2) + i];
+
+       return RET_OK;
+}
+
+#else /* ICH_DESCRIPTORS_FROM_DUMP */
+
 /** Returns the integer representation of the component density with index
 idx in bytes or 0 if a correct size can not be determined. */
 int getFCBA_component_density(uint8_t idx, const struct ich_descriptors *desc)
@@ -319,5 +717,6 @@ int read_ich_descriptors_via_fdo(void *spibar, struct 
ich_descriptors *desc)
        msg_pdbg2(" done.\n");
        return RET_OK;
 }
+#endif /* ICH_DESCRIPTORS_FROM_DUMP */
 #endif /* BITFIELDS == 1 */
 #endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/ich_descriptors.h b/ich_descriptors.h
index 8ab798f..56d1b3e 100644
--- a/ich_descriptors.h
+++ b/ich_descriptors.h
@@ -240,11 +240,206 @@ struct ich_desc_master {
        };
 };
 
+#ifdef ICH_DESCRIPTORS_FROM_DUMP
+struct ich_desc_north_strap {
+       union {
+               uint32_t STRPs[1]; /* current maximum: ich8 */
+               struct { /* ich8 */
+                       struct { /* STRP2 (in the datasheet) */
+                               uint32_t MDB                    :1,
+                                                               :31;
+                       };
+               } ich8;
+       };
+};
+
+struct ich_desc_south_strap {
+       union {
+               uint32_t STRPs[16]; /* current maximum: ibex peak */
+               struct { /* ich8 */
+                       struct { /* STRP1 */
+                               uint32_t ME_DISABLE             :1,
+                                                               :6,
+                                        TCOMODE                :1,
+                                        ASD                    :7,
+                                        BMCMODE                :1,
+                                                               :3,
+                                        GLAN_PCIE_SEL          :1,
+                                        GPIO12_SEL             :2,
+                                        SPICS1_LANPHYPC_SEL    :1,
+                                        MESM2SEL               :1,
+                                                               :1,
+                                        ASD2                   :7;
+                       };
+               } ich8;
+               struct { /* ibex peak */
+                       struct { /* STRP0 */
+                               uint32_t                        :1,
+                                        cs_ss2                 :1,
+                                                               :5,
+                                        SMB_EN                 :1,
+                                        SML0_EN                :1,
+                                        SML1_EN                :1,
+                                        SML1FRQ                :2,
+                                        SMB0FRQ                :2,
+                                        SML0FRQ                :2,
+                                                               :4,
+                                        LANPHYPC_GP12_SEL      :1,
+                                        cs_ss1                 :1,
+                                                               :2,
+                                        DMI_REQID_DIS          :1,
+                                                               :4,
+                                        BBBS                   :2,
+                                                               :1;
+                       };
+                       struct { /* STRP1 */
+                               uint32_t cs_ss3                 :4,
+                                                               :28;
+                       };
+                       struct { /* STRP2 */
+                               uint32_t                        :8,
+                                        MESMASDEN              :1,
+                                        MESMASDA               :7,
+                                                               :8,
+                                        MESMI2CEN              :1,
+                                        MESMI2CA               :7;
+                       };
+                       struct { /* STRP3 */
+                               uint32_t                        :32;
+                       };
+                       struct { /* STRP4 */
+                               uint32_t PHYCON                 :2,
+                                                               :6,
+                                        GBEMAC_SMBUS_ADDR_EN   :1,
+                                        GBEMAC_SMBUS_ADDR      :7,
+                                                               :1,
+                                        GBEPHY_SMBUS_ADDR      :7,
+                                                               :8;
+                       };
+                       struct { /* STRP5 */
+                               uint32_t                        :32;
+                       };
+                       struct { /* STRP6 */
+                               uint32_t                        :32;
+                       };
+                       struct { /* STRP7 */
+                               uint32_t MESMA2UDID_VENDOR      :16,
+                                        MESMA2UDID_DEVICE      :16;
+                       };
+                       struct { /* STRP8 */
+                               uint32_t                        :32;
+                       };
+                       struct { /* STRP9 */
+                               uint32_t PCIEPCS1               :2,
+                                        PCIEPCS2               :2,
+                                        PCIELR1                :1,
+                                        PCIELR2                :1,
+                                        DMILR                  :1,
+                                                               :1,
+                                        PHY_PCIEPORTSEL        :3,
+                                        PHY_PCIE_EN            :1,
+                                                               :20;
+                       };
+                       struct { /* STRP10 */
+                               uint32_t                        :1,
+                                        ME_BOOT_FLASH          :1,
+                                        cs_ss5                 :1,
+                                        VE_EN                  :1,
+                                                               :4,
+                                        MMDDE                  :1,
+                                        MMADDR                 :7,
+                                        cs_ss7                 :1,
+                                                               :1,
+                                        ICC_SEL                :3,
+                                        MER_CL1                :1,
+                                                               :10;
+                       };
+                       struct { /* STRP11 */
+                               uint32_t SML1GPAEN              :1,
+                                        SML1GPA                :7,
+                                                               :16,
+                                        SML1I2CAEN             :1,
+                                        SML1I2CA               :7;
+                       };
+                       struct { /* STRP12 */
+                               uint32_t                        :32;
+                       };
+                       struct { /* STRP13 */
+                               uint32_t                        :32;
+                       };
+                       struct { /* STRP14 */
+                               uint32_t                        :8,
+                                        VE_EN2                 :1,
+                                                               :5,
+                                        VE_BOOT_FLASH          :1,
+                                                               :1,
+                                        BW_SSD                 :1,
+                                        NVMHCI_EN              :1,
+                                                               :14;
+                       };
+                       struct { /* STRP15 */
+                               uint32_t                        :3,
+                                        cs_ss6                 :2,
+                                                               :1,
+                                        IWL_EN                 :1,
+                                                               :1,
+                                        t209min                :2,
+                                                               :22;
+                       };
+               }ibex;
+       };
+};
+
+struct ich_desc_upper_map {
+       union {
+               uint32_t FLUMAP1;               /* Flash Upper Map 1 */
+               struct {
+                       uint32_t VTBA   :8,     /* ME VSCC Table Base Address */
+                                VTL    :8,     /* ME VSCC Table Length */
+                                       :16;
+               };
+       };
+       struct {
+               union {         /* JEDEC-ID Register */
+                       uint32_t JID;
+                       struct {
+                               uint32_t vid    :8, /* Vendor ID */
+                                        cid0   :8, /* Component ID 0 */
+                                        cid1   :8, /* Component ID 1 */
+                                               :8;
+                       };
+               };
+               union {         /* Vendor Specific Component Capabilities */
+                       uint32_t VSCC;
+                       struct {
+                               uint32_t ubes   :2, /* Upper Block/Sector Erase 
Size */
+                                        uwg    :1, /* Upper Write Granularity 
*/
+                                        uwsr   :1, /* Upper Write Status 
Required */
+                                        uwews  :1, /* Upper Write Enable on 
Write Status */
+                                               :3,
+                                        ueo    :8, /* Upper Erase Opcode */
+                                        lbes   :2, /* Lower Block/Sector Erase 
Size */
+                                        lwg    :1, /* Lower Write Granularity 
*/
+                                        lwsr   :1, /* Lower Write Status 
Required */
+                                        lwews  :1, /* Lower Write Enable on 
Write Status */
+                                               :3,
+                                        leo    :16; /* Lower Erase Opcode */
+                       };
+               };
+       } vscc_table[128];
+};
+#endif /* ICH_DESCRIPTORS_FROM_DUMP */
+
 struct ich_descriptors {
        struct ich_desc_content content;
        struct ich_desc_component component;
        struct ich_desc_region region;
        struct ich_desc_master master;
+#ifdef ICH_DESCRIPTORS_FROM_DUMP
+       struct ich_desc_north_strap north;
+       struct ich_desc_south_strap south;
+       struct ich_desc_upper_map upper;
+#endif /* ICH_DESCRIPTORS_FROM_DUMP */
 };
 
 void prettyprint_ich_descriptors(enum ich_chipset, const struct 
ich_descriptors *desc);
@@ -254,9 +449,18 @@ void prettyprint_ich_descriptor_component(const struct 
ich_descriptors *desc);
 void prettyprint_ich_descriptor_region(const struct ich_descriptors *desc);
 void prettyprint_ich_descriptor_master(const struct ich_desc_master *master);
 
+#ifdef ICH_DESCRIPTORS_FROM_DUMP
+
+void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map 
*umap);
+void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct 
ich_descriptors *desc);
+int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, 
enum ich_chipset cs, struct ich_descriptors *desc);
+
+#else /* ICH_DESCRIPTORS_FROM_DUMP */
+
 int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc);
 int getFCBA_component_density(uint8_t idx, const struct ich_descriptors *desc);
- 
+
+#endif /* ICH_DESCRIPTORS_FROM_DUMP */
 #endif /* BITFIELDS == 1 */
 #endif /* __ICH_DESCRIPTORS_H__ */
 #endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/util/ich_descriptors_tool/Makefile 
b/util/ich_descriptors_tool/Makefile
new file mode 100644
index 0000000..3afd480
--- /dev/null
+++ b/util/ich_descriptors_tool/Makefile
@@ -0,0 +1,63 @@
+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 += -D BITFIELDS
+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): bitfields $(OBJ) $(SHAREDOBJ)
+       $(CC) -o $(PROGRAM) $(OBJ) $(SHAREDOBJ)
+
+clean:
+       rm -f $(PROGRAM)
+       rm -rf $(DEPPATH) $(OBJATH)
+
+define BITFIELDS_TEST
+#include "ich_descriptors.h"
+int main(int argc, char **argv)
+{
+       struct ich_descriptors desc;
+       (void) argc;
+       (void) argv;
+       desc.region.FLREGs[4] = 0x5aa5a55a;
+       return desc.region.reg4_base;
+}
+endef
+export BITFIELDS_TEST
+
+bitfields:
+       @printf "Checking if bit-fields support is sufficient... "
+       @echo "$$BITFIELDS_TEST" > .test.c
+       @$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -D BITFIELDS .test.c -o .test$ 
>/dev/null 2>&1 && \
+               ( echo "yes." ; rm -f .test.c .test ) || \
+               ( echo "no."; rm -f .test.c .test; exit 1)
+
+# Include the dependency files.
+-include $(shell mkdir -p $(DEPPATH) $(OBJATH) 2>/dev/null) $(wildcard 
$(DEPPATH)/*)
+
+.PHONY: all clean bitfields
diff --git a/util/ich_descriptors_tool/TODO b/util/ich_descriptors_tool/TODO
new file mode 100644
index 0000000..03701bf
--- /dev/null
+++ b/util/ich_descriptors_tool/TODO
@@ -0,0 +1,6 @@
+- 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
+- little endian only
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..3721eb4
--- /dev/null
+++ b/util/ich_descriptors_tool/ich_descriptors_tool.c
@@ -0,0 +1,225 @@
+/*
+ * 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 that 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 */
+
+       int opt;
+       int 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, cs, &desc);
+       switch (ret) {
+       case RET_OK:
+               break;
+       case RET_ERR:
+               printf("Image not in descriptor mode.\n");
+               exit(1);
+       case 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);
+
+       //uint8_t *pMAC = (uint8_t *) &buf[r->reg3_base >> 2];
+       //printf("The MAC-address might be: %02x:%02x:%02x:%02x:%02x:%02x\n",
+              //pMAC[0], pMAC[1], pMAC[2], pMAC[3], pMAC[4], pMAC[5]);
+
+       if (dump == 1)
+               dump_files(fn, buf, len, &desc.region);
+
+       return 0;
+}
+
-- 
1.7.1


_______________________________________________
flashrom mailing list
flashrom@flashrom.org
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to