Skip to content

Commit 8b90e66

Browse files
committed
Documentation/bootblock-protection.md: add
Change-Id: Iaad1014fad5a60e78bef55c5f3aceaed782b66d6 Signed-off-by: Sergii Dmytruk <[email protected]>
1 parent cf23702 commit 8b90e66

File tree

1 file changed

+202
-0
lines changed

1 file changed

+202
-0
lines changed

Documentation/bootblock-protection.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
This document provides demonstration of how one can protect part of a flash
2+
chip from writing using `flashrom` and its support for manipulating SPI write
3+
protection (WP). This kind of protection requires changing connection of WP
4+
pin of a chip to prevent any attempt of disabling the protection by software
5+
alone.
6+
7+
**Not to be confused** with protection by flash controller of your
8+
motherboard (PCH protection).
9+
10+
## `flashrom` version
11+
12+
At the time of writing (5 August 2022) there hasn't been a `flashrom` release
13+
that includes WP manipulation facilities. You might have to build one from
14+
scratch (assuming you've already installed build dependencies):
15+
16+
```
17+
git clone --depth 1 https://github.com/flashrom/flashrom
18+
cd flashrom
19+
make
20+
# flashrom executable will appear in current directory
21+
```
22+
23+
## Chip support by `flashrom`
24+
25+
There is a great variety of chips with some not supporting write protection at
26+
all and others doing it in their own peculiar way of which `flashrom` has no
27+
idea. So the first thing to do is to make sure that `flashrom` knows how WP
28+
works in your particular chip. Run a command like (adjust this and similar
29+
commands below if you're not using internal programmer or need other options):
30+
31+
```
32+
flashrom --programmer internal --wp-status
33+
```
34+
35+
Seeing this output line would mean that `flashrom` doesn't know how to use WP
36+
feature of the chip you have:
37+
38+
```
39+
Failed to get WP status: WP operations are not implemented for this chip
40+
```
41+
42+
Otherwise the output might contain something similar to this:
43+
44+
```
45+
Protection range: start=0x00000000 length=0x00000000 (none)
46+
Protection mode: disabled
47+
```
48+
49+
If so, you can continue with the rest of the instructions.
50+
51+
## Collecting information about the range
52+
53+
You need to know where the area you want to protect starts and ends. The example
54+
below will assume you're trying to protect bootblock stored in CBFS at the end
55+
of some coreboot firmware. In other cases it might be a separate file which is
56+
put at the beginning of a chip. You need to have an idea of what you're doing
57+
here or have some reliable instructions to follow.
58+
59+
In this case `cbfstool` can be used to list information about bootblock like
60+
this:
61+
62+
```
63+
$ cbfstool rom print | sed -n '2p; /bootblock/p'
64+
Name Offset Type Size Comp
65+
bootblock 0x3ef100 bootblock 36544 none
66+
```
67+
68+
However, the offset is relative to the start of CBFS region, so we also need to
69+
find out offset of CBFS:
70+
71+
```
72+
$ cbfstool rom layout | grep CBFS
73+
'COREBOOT' (CBFS, size 4161536, offset 12615680)
74+
```
75+
76+
Now we can calculate:
77+
78+
* start offset (CBFS offset + 64 + bootblock offset): \
79+
`12615680 + 64 + 0x3ef100 = 0xff7140` \
80+
(`printf "%#x\n" $(( 12615680 + 64 + 0x3ef100 ))`)
81+
* end offset (start offset + bootblock size - 1): \
82+
`0xff7140 + 36544 - 1 = 0xffffff` \
83+
(`printf "%#x\n" $(( 0xff7140 + 36544 - 1 ))`)
84+
85+
Thus we need to write-protect the smallest area that covers the range from
86+
`0xff7140` to `0xffffff` (both bounds are inclusive).
87+
88+
"64" in the computation of start offset is offset of booblock data.
89+
Unfortunately, current tooling doesn't provide a reliable way of determining
90+
actual offset, but 64 is the typical "extra offset" one needs to add to account
91+
for file metadata of CBFS (otherwise it can be its multiple 128 or bigger).
92+
Bootblock should normally end at the last byte of ROM on x86 systems, giving you
93+
a way to test the result.
94+
95+
## Finding a matching range
96+
97+
In most chips, the list of supported ranges is fixed and you can't specify an
98+
arbitrary one. Some others allow more fine-grained control, but that feature is
99+
not supported by `flashrom` as of now.
100+
101+
Obtain list of supported ranges from which we'll pick the best match:
102+
103+
```
104+
$ flashrom --programmer internal --wp-list
105+
...
106+
Available protection ranges:
107+
start=0x00000000 length=0x00000000 (none)
108+
start=0x00000000 length=0x00001000 (lower 1/4096)
109+
start=0x00fff000 length=0x00001000 (upper 1/4096)
110+
start=0x00000000 length=0x00002000 (lower 1/2048)
111+
start=0x00ffe000 length=0x00002000 (upper 1/2048)
112+
start=0x00000000 length=0x00004000 (lower 1/1024)
113+
start=0x00ffc000 length=0x00004000 (upper 1/1024)
114+
start=0x00000000 length=0x00008000 (lower 1/512)
115+
start=0x00ff8000 length=0x00008000 (upper 1/512)
116+
start=0x00000000 length=0x00040000 (lower 1/64)
117+
start=0x00fc0000 length=0x00040000 (upper 1/64)
118+
start=0x00000000 length=0x00080000 (lower 1/32)
119+
start=0x00f80000 length=0x00080000 (upper 1/32)
120+
start=0x00000000 length=0x00100000 (lower 1/16)
121+
start=0x00f00000 length=0x00100000 (upper 1/16)
122+
start=0x00000000 length=0x00200000 (lower 1/8)
123+
start=0x00e00000 length=0x00200000 (upper 1/8)
124+
start=0x00000000 length=0x00400000 (lower 1/4)
125+
start=0x00c00000 length=0x00400000 (upper 1/4)
126+
start=0x00000000 length=0x00800000 (lower 1/2)
127+
start=0x00800000 length=0x00800000 (upper 1/2)
128+
start=0x00000000 length=0x00c00000 (lower 3/4)
129+
start=0x00400000 length=0x00c00000 (upper 3/4)
130+
start=0x00000000 length=0x00e00000 (lower 7/8)
131+
start=0x00200000 length=0x00e00000 (upper 7/8)
132+
start=0x00000000 length=0x00f00000 (lower 15/16)
133+
start=0x00100000 length=0x00f00000 (upper 15/16)
134+
start=0x00000000 length=0x00f80000 (lower 31/32)
135+
start=0x00080000 length=0x00f80000 (upper 31/32)
136+
start=0x00000000 length=0x00fc0000 (lower 63/64)
137+
start=0x00040000 length=0x00fc0000 (upper 63/64)
138+
start=0x00000000 length=0x00ff8000 (lower 511/512)
139+
start=0x00008000 length=0x00ff8000 (upper 511/512)
140+
start=0x00000000 length=0x00ffc000 (lower 1023/1024)
141+
start=0x00004000 length=0x00ffc000 (upper 1023/1024)
142+
start=0x00000000 length=0x00ffe000 (lower 2047/2048)
143+
start=0x00002000 length=0x00ffe000 (upper 2047/2048)
144+
start=0x00000000 length=0x00fff000 (lower 4095/4096)
145+
start=0x00001000 length=0x00fff000 (upper 4095/4096)
146+
start=0x00000000 length=0x01000000 (all)
147+
```
148+
149+
Pick a range by scanning the list in the top down order (because the smaller
150+
ranges come first):
151+
152+
- if bootblock is at the start of a chip, look for the first lower range whose
153+
length is greater than the end offset
154+
- if bootblock is at the end of a chip, look for the first upper range which
155+
starts before the start offset
156+
- mind that you're unlikely to find an ideal match and will probably protect
157+
more than you need; this is fine if that's just an empty space, but can
158+
cause troubles with future updates if that's some data or metadata which
159+
changes with every release
160+
161+
This is the first upper range starting before `0xff7140`:
162+
163+
```
164+
start=0x00fc0000 length=0x00040000 (upper 1/64)
165+
```
166+
167+
It covers `0x00fc0000 -- 0x00ffffff` which includes our bootblock. This area
168+
takes up 256 KiB, about 7 times bigger than our bootblock, but there is no better
169+
choice in this case and output of `cbfstool rom layout` shows that we
170+
additionally include a part of 876 KiB empty space which will hopefully remain
171+
there in future firmware versions (it's a good idea to check before a firmware
172+
update).
173+
174+
## Protection setup
175+
176+
The following command sets the range and enables WP at the same time, the values
177+
are taken from the chosen range above:
178+
179+
```
180+
flashrom --programmer internal --wp-range=0x00fc0000,0x00040000 --wp-enable
181+
```
182+
183+
You can set the range and change WP status independently as well if needed
184+
(just specify one `--wp-*` option at a time). No need to disable protection for
185+
changing the range (via `--wp-disable`), just make sure that hardware
186+
protection is off (state of `W#`/`W/` pin of the chip).
187+
188+
On success, the output of the above command will include such lines:
189+
190+
```
191+
Enabled hardware protection
192+
Activated protection range: start=0x00fc0000 length=0x00040000 (upper 1/64)
193+
```
194+
195+
**Caveat**: `flashrom` automatically tries to disable WP before any operation
196+
on a chip (read, write, erase, verify), so double-check status of WP before
197+
changing state of WP pin on your chip!
198+
199+
## Verifying hardware protection
200+
201+
Once you've happy with the configuration and changed state of WP pin, you can
202+
try disabling WP using `flashrom` to make sure that it the operation now fails.

0 commit comments

Comments
 (0)