[flashrom] [PATCH 2/4] add ICH/PCH flash descriptor decoding via FDOC/FDOD
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Mon Aug 8 03:41:28 CEST 2011
Am 21.07.2011 01:24 schrieb Stefan Tauner:
> 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,
offset of which regions, or something else? How does this relate to
region descriptor(s)?
> PCH/ICH and MCH/PROC strap offsets and lengths)
> - component descriptor:
> identify the different SPI Flash Components and their capabilities.
>
components==chips? If yes, please say so in the changelog (and maybe
code comments).
> - region descriptor
> similarly to a partition table this describes the different regions
>
One common descriptor for all regions or one descriptor per region?
> - 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
retrieved
> from a complete binary dump of the descriptor image only.
>
What's a descriptor image?
> 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
We really need some place (maybe as comment in ich_decriptor.h?) where
all Intel acronyms are expanded and explained.
> (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 descriptor table" implies there is more than one. Which one is it?
> 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:
> - file naming and partitioning was not discussed. we may want a ichspi.h.
> and/or rename ichspi.c to ich_spi.c or similar...
>
I'd say naming of the files is the least of our worries. We'll
reorganize all flashrom code in a directory structure anyway, and that's
when we can rename files if needed.
> - straps of ich8 (only)
Why not ICH7 (no descriptors?) or ICH9 and later (no datasheets?)
> could be printed at runtime via FDOC/FDOD.
> worth it? no, imo.
Agreed.
> but reading out the descriptor region manually and
> parsing it with the following patch may be useful?
>
following patch == 3/4?
Once we support true partial reads with the help of layout files, this
should be possible.
> Signed-off-by: Stefan Tauner <stefan.tauner at student.tuwien.ac.at>
>
Please note that I didn't check the code for correctness against the
datasheets nor did I check the code flow. The comments below are what I
noticed from reading the patch alone.
The message levels of most messages really need to be discussed... a
flood of msg_dbg is not necessarily a good idea, downgrading a lot of
them to dbg2 may improve said flood. That said, msg_[cpg]dbg2 is now in
the tree, so the dbg1 hack can go away. Looking again at your
messagelevels, maybe dbg1->dbg2 and dbg2->spew would be in order.
All ich specific structs should have an ich_ prefix in the struct name
to avoid polluting the global namespace.
> ---
> Makefile | 3 +-
> ich_descriptors.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++
> ich_descriptors.h | 264 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> ichspi.c | 39 ++++++--
> 4 files changed, 544 insertions(+), 9 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..cf77601
> --- /dev/null
> +++ b/ich_descriptors.c
> @@ -0,0 +1,247 @@
> +/*
> + * 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_* */
> +
> +#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
> +#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
> +#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
> +#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
> +#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
> +
> +void prettyprint_ich_descriptors(enum chipset cs, const struct flash_descriptors *desc)
>
(enum ich_chipset cs, const struct ich_flash_descriptors *desc)
> +{
>
Please try to handle cs at least somewhat. Check if it has the expected
value, and skip descriptor decoding (with a dbg/dbg2 message telling the
user about it) if the result would be wrong (i.e. for the wrong ICH family).
> + 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)
>
ich_flash_content
Does this work on all chipsets?
> +{
> + msg_pdbg1("=== Content Section ===\n");
> + msg_pdbg1("FLVALSIG 0x%08x\n", cont->FLVALSIG);
> + msg_pdbg1("FLMAP0 0x%08x\n", cont->FLMAP0);
> + msg_pdbg1("FLMAP1 0x%08x\n", cont->FLMAP1);
> + msg_pdbg1("FLMAP2 0x%08x\n", cont->FLMAP2);
> + msg_pdbg1("\n");
>
dbg1->dbg, or maybe ->dbg2 to reduce output. The message level
discussion should not hold back this patch.
> +
> + msg_pdbg2("--- Details ---\n");
> + msg_pdbg2("NR (Number of Regions): %5d\n",
> + cont->NR + 1);
> + msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n",
> + getFRBA(cont));
> + msg_pdbg2("NC (Number of Components): %5d\n",
> + cont->NC + 1);
> + msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n",
> + getFCBA(cont));
> + msg_pdbg2("ISL (ICH/PCH Strap Length): %5d\n",
> + cont->ISL);
> + msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x%03x\n",
> + getFISBA(cont));
> + msg_pdbg2("NM (Number of Masters): %5d\n",
> + cont->NM + 1);
> + msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n",
> + getFMBA(cont));
> + msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n",
> + cont->MSL);
> + msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n",
> + getFMSBA(cont));
> + msg_pdbg2("\n");
> +}
> +
> +void prettyprint_ich_descriptor_component(const struct flash_descriptors *desc)
>
ich_flash_descriptors
Which chipset is handled by this function?
> +{
> + const char * const str_freq[8] = {
>
static? Or is that useless here?
> + "20 MHz", /* 000 */
> + "33 MHz", /* 001 */
> + "reserved", /* 010 */
> + "reserved", /* 011 */
> + "50 MHz", /* 100 */
>
Mh. Is 50 MHz available on all descriptor capable chipsets?
> + "reserved", /* 101 */
> + "reserved", /* 110 */
> + "reserved" /* 111 */
> + };
> + const char * const str_mem[8] = {
>
static?
> + "512 kB", /* 000 */
> + " 1 MB", /* 001 */
> + " 2 MB", /* 010 */
> + " 4 MB", /* 011 */
> + " 8 MB", /* 100 */
> + " 16 MB", /* 101 */
> + "reserved", /* 110 */
> + "reserved", /* 111 */
> + };
> +
> + msg_pdbg1("=== Component Section ===\n");
> + msg_pdbg1("FLCOMP 0x%08x\n", desc->component.FLCOMP);
> + msg_pdbg1("FLILL 0x%08x\n", desc->component.FLILL );
> + msg_pdbg1("\n");
> +
> + msg_pdbg2("--- Details ---\n");
> + msg_pdbg2("Component 1 density: %s\n",
> + str_mem[desc->component.comp1_density]);
> + if (desc->content.NC)
> + msg_pdbg2("Component 2 density: %s\n",
> + str_mem[desc->component.comp2_density]);
> + else
> + msg_pdbg2("Component 2 is not used.\n");
> + msg_pdbg2("Read Clock Frequency: %s\n",
> + str_freq[desc->component.freq_read]);
> + msg_pdbg2("Read ID and Status Clock Freq.: %s\n",
> + str_freq[desc->component.freq_read_id]);
> + msg_pdbg2("Write and Erase Clock Freq.: %s\n",
> + str_freq[desc->component.freq_write]);
> + msg_pdbg2("Fast Read is %ssupported.\n",
> + desc->component.fastread ? "" : "not ");
> + if (desc->component.fastread)
> + msg_pdbg2("Fast Read Clock Frequency: %s\n",
> + str_freq[desc->component.freq_fastread]);
> + if (desc->component.FLILL == 0)
> + msg_pdbg2("No forbidden opcodes.\n");
> + else {
> + msg_pdbg2("Invalid instruction 0: 0x%02x\n",
> + desc->component.invalid_instr0);
> + msg_pdbg2("Invalid instruction 1: 0x%02x\n",
> + desc->component.invalid_instr1);
> + msg_pdbg2("Invalid instruction 2: 0x%02x\n",
> + desc->component.invalid_instr2);
> + msg_pdbg2("Invalid instruction 3: 0x%02x\n",
> + desc->component.invalid_instr3);
> + }
> + msg_pdbg2("\n");
> +}
> +
> +static void pprint_freg(const struct flash_region *reg, uint32_t i)
>
ich_flash_region
Which chipset? Or is the code generic?
> +{
> + const char *const region_names[5] = {
> + "Descr.", "BIOS", "ME", "GbE", "Platf."
> + };
> + uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
> + uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
> + msg_pdbg2("Region %d (%-6s) ", i, region_names[i]);
> + if (base > limit)
> + msg_pdbg2("is unused.\n");
> + else
> + msg_pdbg2("0x%08x - 0x%08x\n", base, limit | 0x0fff);
> +}
> +
> +void prettyprint_ich_descriptor_region(const struct flash_region *reg)
>
ich_flash_region
Chipset specific or generic?
> +{
> + uint8_t i;
> + msg_pdbg1("=== Region Section ===\n");
> + for (i = 0; i < 5; i++)
> + msg_pdbg1("FLREG%d 0x%08x\n", i, reg->FLREGs[i]);
> + msg_pdbg1("\n");
> +
> + msg_pdbg2("--- Details ---\n");
> + for (i = 0; i < 5; i++)
> + pprint_freg(reg, i);
> + msg_pdbg2("\n");
> +}
> +
> +void prettyprint_ich_descriptor_master(const struct flash_master *mstr)
>
ich_flash_master
> +{
> + msg_pdbg1("=== Master Section ===\n");
> + msg_pdbg1("FLMSTR1 0x%08x\n", mstr->FLMSTR1);
> + msg_pdbg1("FLMSTR2 0x%08x\n", mstr->FLMSTR2);
> + msg_pdbg1("FLMSTR3 0x%08x\n", mstr->FLMSTR3);
> + msg_pdbg1("\n");
> +
> + msg_pdbg2("--- Details ---\n");
> + msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
> + msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
> + (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
> + (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
> + (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
> + (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
> + (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
> + msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
> + (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
> + (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
> + (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
> + (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
> + (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
> + msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
> + (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
> + (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
> + (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
> + (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
> + (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
> + 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;
>
volatile is absolutely no-go outside hwaccess.c. Use mmio_write[bwl] or
the littleendian variant of mmio_write[bwl] instead.
> + return *(volatile uint32_t *)(spibar + ICH9_REG_FDOD);
>
Same here. Use mmio_read[bwl] instead.
> +}
> +
> +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.FLREGs[0] = read_descriptor_reg(2, 0, spibar);
> + desc->region.FLREGs[1] = read_descriptor_reg(2, 1, spibar);
> + desc->region.FLREGs[2] = read_descriptor_reg(2, 2, spibar);
> + desc->region.FLREGs[3] = read_descriptor_reg(2, 3, spibar);
> + desc->region.FLREGs[4] = read_descriptor_reg(2, 4, 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 the strap section via FDOC/D is only possible on ICH8 and
> + * reading the upper map is impossible on all chipsets, so don't bother.
> + */
> +
> + msg_pdbg1(" done\n");
>
This seems to be a true flood of output. dbg2 for all callees maybe?
> +}
> +#endif // defined(__i386__) || defined(__x86_64__)
> diff --git a/ich_descriptors.h b/ich_descriptors.h
> new file mode 100644
> index 0000000..f248394
> --- /dev/null
> +++ b/ich_descriptors.h
> @@ -0,0 +1,264 @@
> +/*
> + * 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)
>
Whitespace damage or is this caused by the leading + in the patch?
> +#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 */
>
Whitespace damage?
> +#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)
>
Please add () around val at the right hand side.
> +void prettyprint_ich9_reg_vscc(uint32_t reg_val);
> +
> +#define ICH_FREG_BASE(flreg) ((flreg << 12) & 0x01fff000)
> +#define ICH_FREG_LIMIT(flreg) ((flreg >> 4) & 0x01fff000)
>
Please add () around flreg at the right hand side.
> +
> +/* Used to select the right descriptor printing function.
> + * Currently only ICH8 and Ibex Peak are supported.
> + */
> +enum chipset {
>
ich_chipset
> + CHIPSET_UNKNOWN,
>
CHIPSET_ICH_UNKNOWN
We may need a CHIPSET_UNKNOWN elsewhere...
> + CHIPSET_ICH7 = 7,
> + CHIPSET_ICH8,
> + CHIPSET_ICH9,
> + CHIPSET_ICH10,
> + CHIPSET_5_SERIES_IBEX_PEAK,
> + CHIPSET_6_SERIES_COUGAR_POINT,
> + CHIPSET_7_SERIES_PANTHER_POINT
> +};
> +
>
All structs below probably need __attribute__((packed)).
> +struct flash_content {
>
ich_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;
> + uint32_t FISBA :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 {
>
ich_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;
>
Really uint32_t? If FLILL is 32 bits, but all invalid_instr are 32 bits
as well, the union members have inconsistent sizes.
uint8_t invalid_instr0 maybe?
> + uint32_t invalid_instr1;
> + uint32_t invalid_instr2;
> + uint32_t invalid_instr3;
>
Dito for the other invalid_instr above.
> + };
> + };
> + union { /* 0x08 */
> + uint32_t FLPB;
> + struct {
> + uint32_t FPBA :13;
> + uint32_t :19;
> + };
> + };
>
All code accessing FLPB/FPBA was broken due to the wrong FLILL union
size, so if it worked anyway, you have another bug hidden somewhere.
> +};
> +
> +struct flash_region {
>
ich_flash_region
> + union {
> + uint32_t FLREGs[5];
> + struct {
> + /* FLREG0 Flash Descriptor */
> + struct {
> + uint32_t reg0_base :13;
>
Are uint32_t bitfields allowed? I thought bitfields were either signed
int or unsigned int, but never uint32_t.
> + uint32_t :3;
>
Are anonymous bitfields allowed?
> + uint32_t reg0_limit :13;
> + uint32_t :3;
> + };
> + /* FLREG1 BIOS */
> + struct {
> + uint32_t reg1_base :13;
> + uint32_t :3;
> + uint32_t reg1_limit :13;
> + uint32_t :3;
> + };
> + /* FLREG2 ME */
> + struct {
> + uint32_t reg2_base :13;
> + uint32_t :3;
> + uint32_t reg2_limit :13;
> + uint32_t :3;
> + };
> + /* FLREG3 GbE */
> + struct {
> + uint32_t reg3_base :13;
> + uint32_t :3;
> + uint32_t reg3_limit :13;
> + uint32_t :3;
> + };
> + /* FLREG4 Platform */
> + struct {
> + uint32_t reg4_base :13;
> + uint32_t :3;
> + uint32_t reg4_limit :13;
> + uint32_t :3;
> + };
> + };
> + };
> +};
> +
> +struct flash_master {
>
ich_flash_master
> + union {
> + uint32_t FLMSTR1;
> + struct {
> + uint32_t BIOS_req_ID :16;
> + uint32_t BIOS_descr_r :1;
> + uint32_t BIOS_BIOS_r :1;
> + uint32_t BIOS_ME_r :1;
> + uint32_t BIOS_GbE_r :1;
> + uint32_t BIOS_plat_r :1;
> + uint32_t :3;
> + uint32_t BIOS_descr_w :1;
> + uint32_t BIOS_BIOS_w :1;
> + uint32_t BIOS_ME_w :1;
> + uint32_t BIOS_GbE_w :1;
> + uint32_t BIOS_plat_w :1;
> + uint32_t :3;
> + };
> + };
> + union {
> + uint32_t FLMSTR2;
> + struct {
> + uint32_t ME_req_ID :16;
> + uint32_t ME_descr_r :1;
> + uint32_t ME_BIOS_r :1;
> + uint32_t ME_ME_r :1;
> + uint32_t ME_GbE_r :1;
> + uint32_t ME_plat_r :1;
> + uint32_t :3;
> + uint32_t ME_descr_w :1;
> + uint32_t ME_BIOS_w :1;
> + uint32_t ME_ME_w :1;
> + uint32_t ME_GbE_w :1;
> + uint32_t ME_plat_w :1;
> + uint32_t :3;
> + };
> + };
> + union {
> + uint32_t FLMSTR3;
> + struct {
> + uint32_t GbE_req_ID :16;
> + uint32_t GbE_descr_r :1;
> + uint32_t GbE_BIOS_r :1;
> + uint32_t GbE_ME_r :1;
> + uint32_t GbE_GbE_r :1;
> + uint32_t GbE_plat_r :1;
> + uint32_t :3;
> + uint32_t GbE_descr_w :1;
> + uint32_t GbE_BIOS_w :1;
> + uint32_t GbE_ME_w :1;
> + uint32_t GbE_GbE_w :1;
> + uint32_t GbE_plat_w :1;
> + uint32_t :3;
> + };
> + };
> +};
> +
> +struct flash_descriptors {
>
ich_flash_descriptors
> + struct flash_content content;
>
ich_flash_content
> + struct flash_component component;
>
ich_flash_component
> + struct flash_region region;
>
ich_flash_region
> + struct flash_master master;
>
ich_flash_master
> +};
> +
> +void prettyprint_ich_descriptors(enum chipset, const struct flash_descriptors *desc);
>
Missing parameter name for first parameter, and of course
ich_chipset ... ich_flash_descriptors.
> +
> +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);
>
ich_ for all struct names (not for the variable names)
> +
> +void read_ich_descriptors_via_fdo(void *spibar, struct flash_descriptors *desc);
>
ich_flash_descriptors
> +
> +#endif // __ICH_DESCRIPTORS_H__
> +#endif // defined(__i386__) || defined(__x86_64__)
> diff --git a/ichspi.c b/ichspi.c
> index 2480fa5..b5ee23a 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. */
>
This comment is a bit unclear to me.
> +
> #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: ");
> @@ -1130,9 +1137,6 @@ static int ich_spi_send_multicommand(struct spi_command *cmds)
> #define ICH_BRWA(x) ((x >> 8) & 0xff)
> #define ICH_BRRA(x) ((x >> 0) & 0xff)
>
> -#define ICH_FREG_BASE(x) ((x >> 0) & 0x1fff)
> -#define ICH_FREG_LIMIT(x) ((x >> 16) & 0x1fff)
> -
> static void do_ich9_spi_frap(uint32_t frap, int i)
> {
> static const char *const access_names[4] = {
> @@ -1159,9 +1163,8 @@ static void do_ich9_spi_frap(uint32_t frap, int i)
> return;
> }
>
> - msg_pdbg("0x%08x-0x%08x is %s\n",
> - (base << 12), (limit << 12) | 0x0fff,
> - access_names[rwperms]);
> + msg_pdbg("0x%08x-0x%08x is %s\n", base, (limit | 0x0fff),
> + access_names[rwperms]);
> }
>
> static const struct spi_programmer spi_programmer_ich7 = {
> @@ -1191,6 +1194,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 +1266,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 +1318,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);
>
Does the block above work correctly for all ICH8 and later chipsets?
> +
> + tmp = mmio_readl(ich_spibar + ICH9_REG_UVSCC);
> + msg_pdbg("0xC8: 0x%08x (UVSCC)\n", tmp);
> + msg_pdbg("UVSCC: ");
> + prettyprint_ich9_reg_vscc(tmp);
>
Ditto.
> +
> 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);
>
Odd code structure, but I see what you're trying to do. Makes sense.
> + prettyprint_ich_descriptors(CHIPSET_UNKNOWN, &desc);
>
Hmmm... I really would like to see this fixed, but it's OK if you want
to do that in a followup patch.
> + }
> ich_init_opcodes();
> break;
> default:
>
Regards,
Carl-Daniel
--
http://www.hailfinger.org/
More information about the flashrom
mailing list