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

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

```Hi,

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
(http://paste.flashrom.org/view.php?id=2940)

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

Thanks for your time and patience.

Bye,
Hatim

-------------- 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>
```