[flashrom] [PATCH 2/4] add ICH/PCH flash descriptor decoding via FDOC/FDOD

Stefan Tauner stefan.tauner at student.tuwien.ac.at
Fri Jul 15 02:39:33 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).

this includes the following:
- content descriptor:
    describes the image and some generic properties (number of regions,
    offset of regions, PCH/ICH and MCH/PROC strap offsets and lengths)
- component descriptor:
    identify the different SPI Flash Components and their capabilities.
- region descriptor
    similarly to a partition table this describes the different regions
- master descriptor
    defines access rights of the individual regions

this is only a part of the data included in the descriptor. other
information can be retreived from a complete binary dump of the
descriptor image only.

this patch also adds macros and pretty printing for "Vendor Specific
Component Capabilities" registers:
there are two of them: lower and upper. they describe the properties
of the address space divided by FPBA (which allows to use multiple
flash chips or partitions with different properties). the properties
of flash chips supported by the ME are stored in the same format in
a descriptor table. a later patch will uses them outside of ichspi.c
which is also the reason why the prettyprinting function and the
register bit macros are not defined in ichspi.c but ich_descriptors.h.

TODO:
- is endianess important? and other questions related to the
  struct/union pattern used.
- file naming and partitioning was not discussed. we may want a ichspi.h.
  and/or rename ichspi.c to ich_spi.c or similar...
- checking derived offsets for OOB errors

Signed-off-by: Stefan Tauner <stefan.tauner at student.tuwien.ac.at>
---
 Makefile          |    3 +-
 ich_descriptors.c |  250 +++++++++++++++++++++++++++++++++++++++++++++++++++
 ich_descriptors.h |  258 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 ichspi.c          |   31 ++++++-
 4 files changed, 539 insertions(+), 3 deletions(-)
 create mode 100644 ich_descriptors.c
 create mode 100644 ich_descriptors.h

diff --git a/Makefile b/Makefile
index a35df06..7f73452 100644
--- a/Makefile
+++ b/Makefile
@@ -308,7 +308,8 @@ 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
 ifeq ($(ARCH),"x86")
-PROGRAMMER_OBJS += it87spi.o it85spi.o ichspi.o sb600spi.o wbsio_spi.o mcp6x_spi.o
+PROGRAMMER_OBJS += it87spi.o it85spi.o sb600spi.o wbsio_spi.o mcp6x_spi.o
+PROGRAMMER_OBJS += ichspi.o ich_descriptors.o
 else
 endif
 NEED_PCI := yes
diff --git a/ich_descriptors.c b/ich_descriptors.c
new file mode 100644
index 0000000..43b2c52
--- /dev/null
+++ b/ich_descriptors.c
@@ -0,0 +1,250 @@
+/*
+ * 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
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "ich_descriptors.h"
+#include "flash.h" /* for msg_* */
+
+uint32_t getFCBA(const struct flash_content *cont)
+{
+	return (cont->FLMAP0 <<  4) & 0x00000ff0;
+}
+
+uint32_t getFRBA(const struct flash_content *cont)
+{
+	return (cont->FLMAP0 >> 12) & 0x00000ff0;
+}
+
+uint32_t getFMBA(const struct flash_content *cont)
+{
+	return (cont->FLMAP1 <<  4) & 0x00000ff0;
+}
+
+uint32_t getFMSBA(const struct flash_content *cont)
+{
+	return (cont->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(const struct flash_content *cont)
+{
+	return (cont->FLMAP1 >> 12) & 0x00000ff0;
+}
+
+void prettyprint_ich_descriptors(enum chipset cs, const struct flash_descriptors *desc)
+{
+	prettyprint_ich_descriptor_content(&desc->content);
+	prettyprint_ich_descriptor_component(desc);
+	prettyprint_ich_descriptor_region(&desc->region);
+	prettyprint_ich_descriptor_master(&desc->master);
+}
+
+void prettyprint_ich_descriptor_content(const struct flash_content *cont)
+{
+	msg_pdbg1("=== Content Section ===\n");
+	msg_pdbg1("FLVALSIG 0x%8.8x\n", cont->FLVALSIG);
+	msg_pdbg1("FLMAP0   0x%8.8x\n", cont->FLMAP0  );
+	msg_pdbg1("FLMAP1   0x%8.8x\n", cont->FLMAP1  );
+	msg_pdbg1("FLMAP2   0x%8.8x\n", cont->FLMAP2  );
+	msg_pdbg1("\n");
+
+	msg_pdbg2("--- Details ---\n");
+	msg_pdbg2("0x%02x      NR    Number of Regions (%d)\n", cont->NR, cont->NR + 1);
+	msg_pdbg2("0x%06x  FRBA  Flash Region Base Address\n", getFRBA(cont));
+	msg_pdbg2("0x%02x      NC    Number of Components (%d)\n", cont->NC, cont->NC + 1);
+	msg_pdbg2("0x%06x  FCBA  Flash Component Base Address\n", getFCBA(cont));
+	msg_pdbg2("\n");
+	msg_pdbg2("0x%02x      ISL   ICH Strap Length (%d)\n", cont->ISL, cont->ISL);
+	msg_pdbg2("0x%06x  FISBA Flash ICH Strap Base Address\n", getFISBA(cont));
+	msg_pdbg2("0x%02x      NM    Number of Masters (%d)\n", cont->NM, cont->NM + 1);
+	msg_pdbg2("0x%06x  FMBA  Flash Master Base Address\n", getFMBA(cont));
+	msg_pdbg2("\n");
+	msg_pdbg2("0x%02x      MSL   MCH Strap Length (%d)\n", cont->MSL, cont->MSL);
+	msg_pdbg2("0x%06x  FMSBA Flash MCH Strap Base Address\n", getFMSBA(cont));
+	msg_pdbg2("\n");
+}
+
+void prettyprint_ich_descriptor_component(const struct flash_descriptors *desc)
+{
+	const char * const str_freq[8] = {
+		"20 MHz",	/* 000 */
+		"33 MHz",	/* 001 */
+		"reserved",	/* 010 */
+		"reserved",	/* 011 */
+		"50 MHz",	/* 100 */
+		"reserved",	/* 101 */
+		"reserved",	/* 110 */
+		"reserved"	/* 111 */
+	};
+	const char * const str_mem[8] = {
+		"512kB",
+		"1 MB",
+		"2 MB",
+		"4 MB",
+		"8 MB",
+		"16 MB",
+		"reserved",
+		"reserved"
+	};
+
+	msg_pdbg1("=== Component Section ===\n");
+	msg_pdbg1("FLCOMP   0x%8.8x\n", desc->component.FLCOMP);
+	msg_pdbg1("FLILL    0x%8.8x\n", desc->component.FLILL );
+	msg_pdbg1("\n");
+
+	msg_pdbg2("--- Details ---\n");
+	msg_pdbg2("0x%2.2x    freq_read_id   %s\n",
+		desc->component.freq_read_id , str_freq[desc->component.freq_read_id ]);
+	msg_pdbg2("0x%2.2x    freq_write     %s\n",
+		desc->component.freq_write   , str_freq[desc->component.freq_write   ]);
+	msg_pdbg2("0x%2.2x    freq_fastread  %s\n",
+		desc->component.freq_fastread, str_freq[desc->component.freq_fastread]);
+	msg_pdbg2("0x%2.2x    fastread       %ssupported\n",
+		desc->component.fastread, desc->component.fastread ? "" : "not ");
+	msg_pdbg2("0x%2.2x    freq_read      %s\n",
+		desc->component.freq_read, str_freq[desc->component.freq_read    ]);
+	msg_pdbg2("0x%2.2x    comp 1 density %s\n",
+		desc->component.comp1_density, str_mem[desc->component.comp1_density]);
+	if (desc->content.NC)
+		msg_pdbg2("0x%2.2x    comp 2 density %s\n",
+			desc->component.comp2_density, str_mem[desc->component.comp2_density]);
+	else
+		msg_pdbg2("0x%2.2x    comp 2 is not used (FLMAP0.NC=0)\n",
+			desc->component.comp2_density);
+	msg_pdbg2("\n");
+	msg_pdbg2("0x%2.2x    invalid instr 0\n", desc->component.invalid_instr0);
+	msg_pdbg2("0x%2.2x    invalid instr 1\n", desc->component.invalid_instr1);
+	msg_pdbg2("0x%2.2x    invalid instr 2\n", desc->component.invalid_instr2);
+	msg_pdbg2("0x%2.2x    invalid instr 3\n", desc->component.invalid_instr3);
+	msg_pdbg2("\n");
+}
+
+void prettyprint_ich_descriptor_region(const struct flash_region *reg)
+{
+	msg_pdbg1("=== Region Section ===\n");
+	msg_pdbg1("FLREG0   0x%8.8x\n", reg->FLREG0);
+	msg_pdbg1("FLREG1   0x%8.8x\n", reg->FLREG1);
+	msg_pdbg1("FLREG2   0x%8.8x\n", reg->FLREG2);
+	msg_pdbg1("FLREG3   0x%8.8x\n", reg->FLREG3);
+	msg_pdbg1("\n");
+
+	msg_pdbg2("--- Details ---\n");
+	msg_pdbg2("0x%8.8x  region 0 limit (descr)\n", getFLREG_limit(reg->FLREG0));
+	msg_pdbg2("0x%8.8x  region 0 base  (descr)\n", getFLREG_base(reg->FLREG0));
+	msg_pdbg2("0x%8.8x  region 1 limit ( BIOS)\n", getFLREG_limit(reg->FLREG1));
+	msg_pdbg2("0x%8.8x  region 1 base  ( BIOS)\n", getFLREG_base(reg->FLREG1));
+	msg_pdbg2("0x%8.8x  region 2 limit ( ME  )\n", getFLREG_limit(reg->FLREG2));
+	msg_pdbg2("0x%8.8x  region 2 base  ( ME  )\n", getFLREG_base(reg->FLREG2));
+	msg_pdbg2("0x%8.8x  region 3 limit ( GbE )\n", getFLREG_limit(reg->FLREG3));
+	msg_pdbg2("0x%8.8x  region 3 base  ( GbE )\n", getFLREG_base(reg->FLREG3));
+	msg_pdbg2("\n");
+}
+
+void prettyprint_ich_descriptor_master(const struct flash_master *mstr)
+{
+	msg_pdbg1("=== Master Section ===\n");
+	msg_pdbg1("FLMSTR1  0x%8.8x\n", mstr->FLMSTR1);
+	msg_pdbg1("FLMSTR2  0x%8.8x\n", mstr->FLMSTR2);
+	msg_pdbg1("FLMSTR3  0x%8.8x\n", mstr->FLMSTR3);
+	msg_pdbg1("\n");
+
+	#define R(r) (r)?'r':' '
+	#define W(w) (w)?'w':' '
+	msg_pdbg2("--- Details ---\n");
+	msg_pdbg2("      Descr. BIOS ME GbE\n");
+	msg_pdbg2("BIOS    %c%c    %c%c  %c%c  %c%c\n",
+	R(mstr->BIOS_descr_read),	W(mstr->BIOS_descr_write),
+	R(mstr->BIOS_BIOS_read),	W(mstr->BIOS_BIOS_write),
+	R(mstr->BIOS_ME_read),		W(mstr->BIOS_ME_write),
+	R(mstr->BIOS_GbE_read),		W(mstr->BIOS_GbE_write));
+	msg_pdbg2("ME      %c%c    %c%c  %c%c  %c%c\n",
+	R(mstr->ME_descr_read),		W(mstr->ME_descr_write),
+	R(mstr->ME_BIOS_read),		W(mstr->ME_BIOS_write),
+	R(mstr->ME_ME_read),		W(mstr->ME_ME_write),
+	R(mstr->ME_GbE_read),		W(mstr->ME_GbE_write));
+	msg_pdbg2("GbE     %c%c    %c%c  %c%c  %c%c\n",
+	R(mstr->GbE_descr_read),	W(mstr->GbE_descr_write),
+	R(mstr->GbE_BIOS_read),		W(mstr->GbE_BIOS_write),
+	R(mstr->GbE_ME_read),		W(mstr->GbE_ME_write),
+	R(mstr->GbE_GbE_read),		W(mstr->GbE_GbE_write));
+	msg_pdbg2("\n");
+}
+
+void prettyprint_ich9_reg_vscc(uint32_t reg_val)
+{
+	pprint_reg_hex(VSCC, BES, reg_val, ", ");
+	pprint_reg(VSCC, WG, reg_val, ", ");
+	pprint_reg(VSCC, WSR, reg_val, ", ");
+	pprint_reg(VSCC, WEWS, reg_val, ", ");
+	pprint_reg_hex(VSCC, EO, reg_val, ", ");
+	pprint_reg(VSCC, VCL, reg_val, "\n");
+}
+
+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_via_fdo(void *spibar, struct flash_descriptors *desc)
+{
+	msg_pdbg1("Reading flash descriptors "
+		 "mapped by the chipset via FDOC/FDOD...");
+	/* content section */
+	desc->content.FLVALSIG	= read_descriptor_reg(0, 0, spibar);
+	desc->content.FLMAP0	= read_descriptor_reg(0, 1, spibar);
+	desc->content.FLMAP1	= read_descriptor_reg(0, 2, spibar);
+	desc->content.FLMAP2	= read_descriptor_reg(0, 3, spibar);
+
+	/* component section */
+	desc->component.FLCOMP	= read_descriptor_reg(1, 0, spibar);
+	desc->component.FLILL	= read_descriptor_reg(1, 1, spibar);
+	desc->component.FLPB	= read_descriptor_reg(1, 2, spibar);
+
+	/* region section */
+	desc->region.FLREG0 = read_descriptor_reg(2, 0, spibar);
+	desc->region.FLREG1 = read_descriptor_reg(2, 1, spibar);
+	desc->region.FLREG2 = read_descriptor_reg(2, 2, spibar);
+	desc->region.FLREG3 = read_descriptor_reg(2, 3, spibar);
+
+	/* master section */
+	desc->master.FLMSTR1 = read_descriptor_reg(3, 0, spibar);
+	desc->master.FLMSTR2 = read_descriptor_reg(3, 1, spibar);
+	desc->master.FLMSTR3 = read_descriptor_reg(3, 2, spibar);
+
+	/* accessing strap section and upper map is impossible via FDOC/D(?) */
+	msg_pdbg1(" done\n");
+}
+
+#endif // defined(__i386__) || defined(__x86_64__)
diff --git a/ich_descriptors.h b/ich_descriptors.h
new file mode 100644
index 0000000..9954149
--- /dev/null
+++ b/ich_descriptors.h
@@ -0,0 +1,258 @@
+/*
+ * 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
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+#ifndef __ICH_DESCRIPTORS_H__
+#define __ICH_DESCRIPTORS_H__ 1
+
+#include <stdint.h>
+
+/* most of the following should probably be in a new file named ichspi.h */
+#define msg_pdbg1 msg_pdbg
+#define msg_pdbg2 msg_pspew
+
+#define ICH9_REG_FDOC		0xB0	/* 32 Bits Flash Descriptor Observability Control */
+					/* 0-1: reserved */
+#define FDOC_FDSI_OFF		2	/* 2-11: Flash Descriptor Section Index */
+#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)
+					/* 15-31: reserved */
+
+#define ICH9_REG_FDOD		0xB4	/* 32 Bits Flash Descriptor Observability Data */
+
+/* Field locations and semantics for LVSCC, UVSCC and related words in the flash
+ * descriptor are equal therefore they all share the same macros below. */
+#define VSCC_BES_OFF		0	/* 0-1: Block/Sector Erase Size */
+#define VSCC_BES			(0x3 << VSCC_BES_OFF)
+#define VSCC_WG_OFF		2	/* 2: Write Granularity */
+#define VSCC_WG				(0x1 << VSCC_WG_OFF)
+#define VSCC_WSR_OFF		3	/* 3: Write Status Required */
+#define VSCC_WSR			(0x1 << VSCC_WSR_OFF)
+#define VSCC_WEWS_OFF		4	/* 4: Write Enable on Write Status */
+#define VSCC_WEWS			(0x1 << VSCC_WEWS_OFF)
+					/* 5-7: reserved */
+#define VSCC_EO_OFF		8	/* 8-15: Erase Opcode */
+#define VSCC_EO				(0xff << VSCC_EO_OFF)
+					/* 16-22: reserved */
+#define VSCC_VCL_OFF		23	/* 23: Vendor Component Lock */
+#define VSCC_VCL			(0x1 << VSCC_VCL_OFF)
+					/* 24-31: reserved */
+
+#define pprint_reg(reg, bit, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & reg##_##bit)>>reg##_##bit##_OFF)
+#define pprint_reg_hex(reg, bit, val, sep) msg_pdbg("%s=0x%x" sep, #bit, (val & reg##_##bit)>>reg##_##bit##_OFF)
+void prettyprint_ich9_reg_vscc(uint32_t reg_val);
+
+enum chipset {
+	CHIPSET_UNKNOWN,
+	CHIPSET_ICH7 = 7,
+	CHIPSET_ICH8,
+	CHIPSET_ICH9,
+	CHIPSET_ICH10,
+	CHIPSET_SERIES_5_IBEX_PEAK,
+	CHIPSET_SERIES_6_COUGAR_POINT,
+	CHIPSET_SERIES_7_PANTHER_POINT
+};
+
+struct flash_content {
+	uint32_t FLVALSIG;	/* 0x00 */
+	union {			/* 0x04 */
+		uint32_t FLMAP0;
+		struct {
+			uint32_t FCBA	:8;
+			uint32_t NC	:2;
+			uint32_t	:6;
+			uint32_t FRBA	:8;
+			uint32_t NR	:3;
+			uint32_t	:5;
+		};
+	};
+	union {			/* 0x08 */
+		uint32_t FLMAP1;
+		struct {
+			uint32_t FMBA	:8;
+			uint32_t NM	:3;
+			uint32_t	:5;
+			union {
+				uint32_t FISBA :8;
+				uint32_t FPSBA :8;
+			};
+			uint32_t ISL	:8;
+		};
+	};
+	union {			/* 0x0c */
+		uint32_t FLMAP2;
+		struct {
+			uint32_t  FMSBA	:8;
+			uint32_t  MSL	:8;
+			uint32_t	:16;
+		};
+	};
+};
+
+struct flash_component {
+	union {			/* 0x00 */
+		uint32_t FLCOMP;
+		struct {
+			uint32_t  comp1_density	:3;
+			uint32_t  comp2_density	:3;
+			uint32_t		:11;
+			uint32_t  freq_read	:3;
+			uint32_t  fastread	:1;
+			uint32_t  freq_fastread	:3;
+			uint32_t  freq_write	:3;
+			uint32_t  freq_read_id	:3;
+			uint32_t		:2;
+		};
+	};
+	union {			/* 0x04 */
+		uint32_t FLILL;
+		struct {
+			uint32_t invalid_instr0;
+			uint32_t invalid_instr1;
+			uint32_t invalid_instr2;
+			uint32_t invalid_instr3;
+		};
+	};
+	union {			/* 0x08 */
+		uint32_t FLPB;
+		struct {
+			uint32_t FPBA	:13;
+			uint32_t	:19;
+		};
+	};
+};
+
+struct flash_region {
+	
+	union {
+		uint32_t FLREG0; /* Flash Descriptor */
+		struct {
+			uint32_t reg0_base	:13;
+			uint32_t		:3;
+			uint32_t reg0_limit	:13;
+			uint32_t		:3;
+		};
+	};
+	union {
+		uint32_t FLREG1; /* BIOS */
+		struct {
+			uint32_t reg1_base	:13;
+			uint32_t		:3;
+			uint32_t reg1_limit	:13;
+			uint32_t		:3;
+		};
+	};
+	union {
+		uint32_t FLREG2; /* ME */
+		struct {
+			uint32_t reg2_base	:13;
+			uint32_t		:3;
+			uint32_t reg2_limit	:13;
+			uint32_t		:3;
+		};
+	};
+	union {
+		uint32_t FLREG3; /* GbE */
+		struct {
+			uint32_t reg3_base	:13;
+			uint32_t		:3;
+			uint32_t reg3_limit	:13;
+			uint32_t		:3;
+		};
+	};
+};
+
+struct flash_master {
+	union {
+		uint32_t FLMSTR1;
+		struct {
+			uint32_t BIOS_req_ID		:16;
+			uint32_t BIOS_descr_read	:1;
+			uint32_t BIOS_BIOS_read		:1;
+			uint32_t BIOS_ME_read		:1;
+			uint32_t BIOS_GbE_read		:1;
+			uint32_t BIOS_plat_read		:1;
+			uint32_t			:3;
+			uint32_t BIOS_descr_write	:1;
+			uint32_t BIOS_BIOS_write	:1;
+			uint32_t BIOS_ME_write		:1;
+			uint32_t BIOS_GbE_write		:1;
+			uint32_t BIOS_plat_write	:1;
+			uint32_t			:3;
+		};
+	};
+	union {
+		uint32_t FLMSTR2;
+		struct {
+			uint32_t ME_req_ID		:16;
+			uint32_t ME_descr_read		:1;
+			uint32_t ME_BIOS_read		:1;
+			uint32_t ME_ME_read		:1;
+			uint32_t ME_GbE_read		:1;
+			uint32_t ME_plat_read		:1;
+			uint32_t			:3;
+			uint32_t ME_descr_write		:1;
+			uint32_t ME_BIOS_write		:1;
+			uint32_t ME_ME_write		:1;
+			uint32_t ME_GbE_write		:1;
+			uint32_t ME_plat_write		:1;
+			uint32_t			:3;
+		};
+	};
+	union {
+		uint32_t FLMSTR3;
+		struct {
+			uint32_t GbE_req_ID		:16;
+			uint32_t GbE_descr_read		:1;
+			uint32_t GbE_BIOS_read		:1;
+			uint32_t GbE_ME_read		:1;
+			uint32_t GbE_GbE_read		:1;
+			uint32_t GbE_plat_read		:1;
+			uint32_t			:3;
+			uint32_t GbE_descr_write	:1;
+			uint32_t GbE_BIOS_write		:1;
+			uint32_t GbE_ME_write		:1;
+			uint32_t GbE_GbE_write		:1;
+			uint32_t GbE_plat_write		:1;
+			uint32_t			:3;
+		};
+	};
+};
+
+struct flash_descriptors {
+	struct flash_content content;
+	struct flash_component component;
+	struct flash_region region;
+	struct flash_master master;
+};
+
+void prettyprint_ich_descriptors(enum chipset, const struct flash_descriptors *desc);
+
+void prettyprint_ich_descriptor_content(const struct flash_content *content);
+void prettyprint_ich_descriptor_component(const struct flash_descriptors *desc);
+void prettyprint_ich_descriptor_region(const struct flash_region *region);
+void prettyprint_ich_descriptor_master(const struct flash_master *master);
+
+void read_ich_descriptors_via_fdo(void *spibar, struct flash_descriptors *desc);
+
+#endif // __ICH_DESCRIPTORS_H__
+#endif // defined(__i386__) || defined(__x86_64__)
diff --git a/ichspi.c b/ichspi.c
index 2480fa5..edca654 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -30,6 +30,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 */
@@ -120,6 +121,14 @@
 #define ICH9_REG_BBAR		0xA0	/* 32 Bits BIOS Base Address Configuration */
 #define BBAR_MASK	0x00ffff00		/* 8-23: Bottom of System Flash */
 
+#define ICH9_REG_LVSCC		0xC4	/* 32 Bits Host Lower Vendor Specific Component Capabilities */
+#define ICH9_REG_UVSCC		0xC8	/* 32 Bits Host Upper Vendor Specific Component Capabilities */
+/* The individual fields of the VSCC registers are defined in the file
+ * ich_descriptors.h. The reason is that the same fields are also used in the
+ * flash descriptors to define the properties of the different flash chips
+ * supported by the BIOS image. These descriptors are also the source for the
+ * registers above. */
+
 #define ICH9_REG_FPB		0xD0	/* 32 Bits Flash Partition Boundary */
 #define FPB_FPBA_OFF		0	/* 0-12: Block/Sector Erase Size */
 #define FPB_FPBA			(0x1FFF << FPB_FPBA_OFF)
@@ -302,8 +311,6 @@ static void prettyprint_opcodes(OPCODES *ops)
 	}
 }
 
-#define pprint_reg(reg, bit, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & reg##_##bit)>>reg##_##bit##_OFF)
-
 static void prettyprint_ich9_reg_hsfs(uint16_t reg_val)
 {
 	msg_pdbg("HSFS: ");
@@ -1191,6 +1198,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:
@@ -1262,6 +1270,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);
@@ -1312,9 +1322,26 @@ 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);
+
+		tmp = mmio_readl(ich_spibar + ICH9_REG_LVSCC);
+		msg_pdbg("0xC4: 0x%08x (LVSCC)\n", tmp);
+		msg_pdbg("LVSCC: ");
+		prettyprint_ich9_reg_vscc(tmp);
+
+		tmp = mmio_readl(ich_spibar + ICH9_REG_UVSCC);
+		msg_pdbg("0xC8: 0x%08x (UVSCC)\n", tmp);
+		msg_pdbg("UVSCC: ");
+		prettyprint_ich9_reg_vscc(tmp);
+
 		tmp = mmio_readl(ich_spibar + ICH9_REG_FPB);
 		msg_pdbg("0xD0: 0x%08x (FPB)\n", tmp);
 
+		msg_pdbg("\n");
+		if (ichspi_desc) {
+			struct flash_descriptors desc = {{ 0 }};
+			read_ich_descriptors_via_fdo(ich_spibar, &desc);
+			prettyprint_ich_descriptors(CHIPSET_UNKNOWN, &desc);
+		}
 		ich_init_opcodes();
 		break;
 	default:
-- 
1.7.1





More information about the flashrom mailing list