[flashrom] Ideas for implementing support for 2nd status register

Hatim Kanchwala hatim at hatimak.me
Sat Jun 18 03:32:48 CEST 2016


Regarding block protection scheme, I am very glad to say I have had a 
breakthrough observation. After having sifted through around 90 
datasheets, I was able to spot a pattern that majority of chips follow. 
GigaDevice and Winbond , along with some AMIC, Eon, Fudan and Macronix 
chips follow this pattern - around 50 in number. With this pattern, we 
can now dynamically generate the entire block protection ranges 
on-the-go. We don't need to hard-code the tables for these chips anymore 
and presence (or absence) of SEC, TB, or CMP bits is also handles 
generically! The exact algorithm is slightly convoluted, but I'll try my 
best to explain it. Feel free to skip past #5, you will have nothing 
much to lose. For all practical purposes, the BP4 and BP3 bits are 
identical to SEC and TB bits respectively. We'll call tuple of (BP3, 
BP2, BP1) as BP, and X is don't care.
1. For BP=(0,0,0):
     No protection, SEC=X, TB=X

2. For BP=(1,1,1):
     All protection, SEC=X, TB=X

3. For (SEC,TB)=(0,0):
     We introduce a parameter f, such that f = chip_size(in kB) / 64 for 
chips_size < 4096 kB; and f = 64 for chips_size >= 4096 kB.
3.1 For chip_size >= 4096 kB, we have the following correspondence of 
fraction of chip_size with BP:
     (0,0,1) - 1/64
     (0,1,0) - 1/32
     (0,1,1) - 1/16
     (1,1,0) - 1/2
3.2 For chip_size = 2048 kB, we have the following correspondence of 
fraction of chip_size with BP:
     (0,0,1) - 1/32
     (0,1,0) - 1/16
     (0,1,1) - 1/8
     (1,1,0) - 1
3.3 For chip_size = 1024 kB, we have the following correspondence of 
fraction of chip_size with BP:
     (0,0,1) - 1/16
     (0,1,0) - 1/8
     (0,1,1) - 1/4
     (1,1,0) - 1
3.4 For chip_size = 512 kB, we have the following correspondence of 
fraction of chip_size with BP:
     (0,0,1) - 1/8
     (0,1,0) - 1/4
     (1,1,0) - 1
3.5 For chip_size = 256 kB, we have the following correspondence of 
fraction of chip_size with BP:
     (0,0,1) - 1/4
     (0,1,0) - 1/2
     (0,1,1) - 1
     (1,0,0) - 0
     (1,0,1) - 1/4
     (1,1,0) - 1/2
3.6 For chip_size = 128 kB, we have the following correspondence of 
fraction of chip_size with BP:
     (0,0,1) - 1/2
     (0,1,0) - 1
     (0,1,1) - 1
     (1,0,0) - 0
     (1,0,1) - 1/2
     (1,1,0) - 1
(SEC,TB)=(0,0) represents the upper portion of the chip (which means 
range addresses always end at top boundary).
E.g. For a 4096 kB chip, (0,1,0) 1/32 means upper 256 kB - 0x3fff00-0x3fffff

4. For (SEC,TB)=(0,1):
     This represents the lower portion of the chip (which means range 
addresses always start at lower boundary). The same mapping defined 
earlier for fraction of chip_size holds.
E.g. For a 512 kB chip, (0,1,0) means lower 128 kB - 0x000000-0x01ffff

5. For (SEC,TB)=(1,X):
     (0,0,1) - 4 kB
     (0,1,0) - 8 kB
     (0,1,1) - 16 kB
     (1,0,0) - 32 kB
     (1,0,1) - 32 kB
    *(1,1,0) - 32 kB
We have upper for TB=0, lower for TB=1
E.g. For a 1024 kB chip TB=1, (1,0,0) means lower 32 kB - 0x000000-0x007fff
*Some chips have 64 kB block instead of 32 kB.

(You will not lose much if you skip up to here)

6. For chips with CMP bit:
     For all chips that I have seen (and that is well over a 100 SPI 
chips), the block protection range either starts at lower boundary of 
chip or ends at upper boundary of chip. So, given the range and size of 
the chip, we can compute the complement range.

Please find attached pattern.c. It is an excerpt from the unmerged code 
I am working on and contains the implementation of the discussed model 
(cf. sec_block_pattern_range_generic). There are other functions and 
structs to show the models impact on the infrastructure. IMO, this is an 
immense improvement from what we have in ChromiumOS fork and what we 
have been discussing. Here are the key takeaway points -
- Having the status register layout member in struct flashchip is 
immensely beneficial. A lot of chips can be supported with the generic 
code, perhaps with only slight adaptation.
- Based on David's suggestion, shifting to function pointers was a good 
choice - it allows flexibility.
- Presence (or absence) of CMP, TB (BP3), SEC (BP4) bit is automatically 
taken of, and the corresponding range is also dynamically generated.
- For chips whose ranges cannot be dynamically generated, we have the 
option of specifying range manually. I think it is best to stick to 
range for such representation, instead of range of sectors/blocks or 
portions of chip (as suggested by David in the previous mail). Sticking 
with range is safe because range is independent of sector/block and will 
yield the proper result.
- Based on Stefan's suggestion some time ago, having pointers to struct 
status_register and struct wp will allow greater re-use (which is 
happening a lot!)

Please have a look at the source file. The output of the source is here 

Further work -
- In the current implementation, for chips whose range is dynamically 
generated we have a pointer to the range and an ID variable to associate 
the range with the chip (this is so that range is computed once and 
reused for subsequent calls). If we have another chip then the ID and 
pointer gets overwritten (like is happening in main() in the source). So 
when we want to return to the previous chip, we have to again spend the 
computing cost. This can be enhanced if we use list data structures and 
append newly computed range tables. That way, we can always revisit a 
previously computed table at a nominal computing cost.
- The computation of BP bitfield from a given range can be enhanced if 
we factor in CMP bit (if present) - there could be a scenario where 
CMP=0 and the given range is not possible, but if CMP=1 the range could 
be possible.
- Another way we could enhance it is through suggesting nearest 
neighbours to the range. (I find this idea theoretically interesting, 
but practically I cannot come up with use cases)

I hope you enjoyed going through the source. It took me a while to sift 
through so many datasheets and try out varying models, but I was elated 
with joy when the above algorithm was ready. I am looking forward to 
your feedback and comments on this.

Thanks for your time and patience.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: pattern.c
Type: text/x-csrc
Size: 15933 bytes
Desc: not available
URL: <http://www.flashrom.org/pipermail/flashrom/attachments/20160618/4a7c48a0/attachment.c>

More information about the flashrom mailing list