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(a)student.tuwien.ac.at>
---
Makefile | 2 +-
ich_descriptors.c | 415 ++++++++++++++++++++++
ich_descriptors.h | 406 +++++++++++++++++++++
ichspi.c | 12 +-
util/ich_descriptors_tool/Makefile | 42 +++
util/ich_descriptors_tool/TODO | 5 +
util/ich_descriptors_tool/ich_descriptors_tool.c | 226 ++++++++++++
7 files changed, 1105 insertions(+), 3 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..9ae153b
--- /dev/null
+++ b/ich_descriptors.c
@@ -0,0 +1,415 @@
+/* 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;
+struct flash_component fcba;
+struct flash_region frba;
+struct flash_master fmba;
+
+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;
+}
+
+#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)
+{
+ 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 */
+ };
+ 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 density is not used (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)
+{
+ 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..96dd724
--- /dev/null
+++ b/ich_descriptors.h
@@ -0,0 +1,406 @@
+/* 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);
+
+#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 df44373..23ceeff 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -6,6 +6,7 @@
* Copyright (C) 2008 Dominik Geyer <dominik.geyer(a)kontron.com>
* Copyright (C) 2008 coresystems GmbH <info(a)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 */
@@ -1194,6 +1196,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:
@@ -1265,6 +1268,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);
@@ -1313,8 +1318,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("0xB0: 0x%08x (FDOC)\n",
- mmio_readl(ich_spibar + ICH9_REG_FDOC));
+ 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)/$((a)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