Hello list!
i am researching hardware sequencing at the moment and i am thinking about how it should be implemented and integrated.
== INTRODUCTION == newer intel chipsets allow two modes of operation when talking to spi flashes: software and hw sequencing. in sw sequencing the software needs to provide the spi opcodes (or use the predefined ones if applicable) in a table that it can later invoke. to do so the id of the opcode, data lengths and data content is written to some ich registers and a bit is flipped to trigger the execution. the opcodes can be reprogrammed by the software at any time (which allows pretty much everything - as long as there is no locking/protection activated, but that's another story). sw sequencing is already fully supported by flashrom.
in hw sequencing the list of opcodes is fixed (with the exception of the erase command). this does of course only work if the flash chip adheres to strict specifications which are documented in the datasheets (erase sector size, write enable procedures/status register semantics etc). if ME or GbE firmware should be supported then the restrictions are even more severe (and HW seq is required for those features).
another requirement for hw seq is that the flash must contain a valid descriptor section. in that data structure the layout of the flash contents it described among other things. this way the ME and the GbE processors can find their firmware at startup (my guess). the descriptors also define the locking of the flash regions we had so much trouble in the past. it is also possible to use more than one flash chip to store bios and firmware information with descriptors. this is transparent to the software when using hw seq (and sw seq is not able to speak to the second chip/toggle the second CS at all afaics).
== DETAILS == requirements for hw seq (besides the reqs for sw seq like unlocked regions and the properties mentioned in "SPI Based BIOS Requirements" in the data sheets etc.): - a compatible flash device as defined in "Hardware Sequencing Requirements" in intel's ICH/PCH datasheets. that is not easy to check right now, but we probably do not care anyway (or is anyone interested in using ICHs as general purpose flashing devices? actually this would be possible with the second chip select and hardware sequencing... :). - HSFS.FDV=1 i.e. a valid flash descriptor signature is found at the bottom of the flash (some steppings seem to have an offset of 0x10, but that's not our problem when we are using HSFS.FDV).
limitations of hw seq: - only read, write and erase operations can be committed. this has lots of implications for an integration into flashrom; see IMPLEMENTATION.
other interesting bits: - there is support for shadowing two flash chips into one contiguous address space. the use of multiple flash chips can be checked in flash descriptor bit FLMAP0.NC. there is limited support for chips with different attributes: different sizes are no problem (defined in fd FCBA). other attributes can be assigned to two parts of the SPI address space by the lower and upper VSCC (Host Lower/Upper Vendor Specific Component Capabilities Register). the border between them is defined by register FPB.FPBA. this can be used for flash chips that differ for example in the erase opcode. NB: this also allows the use of a single flash chip with different erase granularities in different address spaces. the two attribute registers (LVSCC and UVSCC) can be locked independently from each other and from the FLOCKDN bit. - there is a table of jedec ids and the (erase/write (enable)) abilities of associated flash chips in the flash descriptor (unreachable via ICH/PCH registers). the ability words have the same semantic as the VSCC mentioned above. quoting the (confidential) ibex peak SPI programming guide AN: "The Intel® ME VSCC Table defines how the Intel® ME will communicate with the installed SPI flash. This table is defined in the descriptor and is the responsibility of who puts together the NVM image. LVSCC and/or UVSCC registers are defined in memory space and must be set by BIOS. This table must define every flash part that is intended to be used."
== IMPLEMENTATION == the very simple access model of hw seq is too simple for flashrom, or put in another way: flashrom is too sophisticated to integrate hw seq easily. in hw seq the target device is not a single flashchip from the flashchips table, but a contiguous address space which we can access by just setting an address, filling in the data (like in sw seq) and then committing the command by setting the read/write or erase mode and the go-flag in HSFC. i have identified the following problems and am asking for possible solutions:
- "dynamic" target device. we dont have one single flash chip, but only certain attributes available (total size, erase block sizes for currently up to two address spaces). there are many combinations of flash chips that could be wired up on boards. theoretically we could define them all and use a customized probe function to "detect" them, but that's of course(?) not the way to go. the main problem here is the constant flashrom array. an alternative may be a const array of pointers to (mostly const) flashchips, where one of them is a non-const generic ich hw seq device with a custom probe function that sets the important fields of that chip. dunno if that would work (i.e. compile to mostly text section data). maybe we could probably live with a const generic device anyway, because we can read the flash size anytime via the ich registers. but there are problems with the generic flashrom methods: e.g. they check for matching file and flash sizes.
- different programmer function semantics. there are no opcodes to deal with, so the existing spi functions in ichspi.c are not really useful. i think the best way would be to add a new programmer for this. since we only allow one spi programmer atm(?), the registering of the programmer in ich_init_spi would have to be changed. how would we want to specify if hw seq should be used? there is no way to get command line arguments in there (yet). another way would be to deduce that just from the register contents: - if the opcodes are locked and dont contain enough opcodes to succeed, use hw seq. this is probably not so easy to check, so it would be easier to just do the following: - if the opcodes are locked down, use hw seq - also if there are (>=) 2 flash components, we have to use hw seq. - another way may be to use sw seq and retry with sw seq when we fail, but that's also complicated and i would love to avoid that at least for the near future.
i may have missed a thing or a dozen, but please dont shoot me my brain is already wounded from digging through all that information ;)
On Thu, 26 May 2011 03:15:02 +0200 Stefan Tauner stefan.tauner@student.tuwien.ac.at wrote:
== IMPLEMENTATION == the very simple access model of hw seq is too simple for flashrom, or put in another way: flashrom is too sophisticated to integrate hw seq easily. in hw seq the target device is not a single flashchip from the flashchips table, but a contiguous address space which we can access by just setting an address, filling in the data (like in sw seq) and then committing the command by setting the read/write or erase mode and the go-flag in HSFC.
i successfully read out the 4kB descriptor region with hardware sequencing today. of course i had to cheat a bit, but as proof of concept i am quite pleased with this quick success :)
my first approach was to add a new spi programmer to ichspi and register it in ich_init_spi: extern struct flash_descriptor fdbar; if (ichspi_lock || fdbar.NC != 0) register_spi_programmer(&spi_programmer_ich_hwseq); else { register_spi_programmer(&spi_programmer_ich9); ich_init_opcodes(); }
i then added a special device to flashchips.c which points to new probe, read, write functions in ichspi.c (without solving the const problem).
the probing just checks if the special spi programmer is the current/registered one.
reading is currently done by a simple 4byte-reading loop which certainly could be improved (and maybe refactored together with the existing run_opcode methods (which should be refactored anyway imho)).
writing is not implemented yet... and i certainly wont test it on my hardware. if someone with an ICH (>=9)/PCH and a good way to recover wants to test it later please step forward. best would be if there is already a descriptor available for that board. else we would have a nice opportunity to enhance the ich_descriptor_tool... not on my schedule though.
i discovered another minor problem: the programmer has to have the generic spi programmer functions implemented, that is: int (*command)(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); int (*multicommand)(struct spi_command *cmds);
this is (at least) needed to get correct probing output else you will get something like: Probing for Winbond W25Q80, 1024 kB: spi_send_command called, but SPI is unsupported on this hardware. Please report a bug at flashrom@flashrom.org
i tried to circumvent this problem by adding a new chip bus type, but it is not trivial (register_spi_programmer sets the bus to SPI explicitly etc) and imho not worth it.
to sum up: i think the second problem can be considered solved, but the first one namely the constant flashchip array needs a solution. i will probably come up with a hack later when i try to add erase and write functions.. and probably with new problems too (erase sizes etc...). will keep you updated ofc.