xref: /aosp_15_r20/external/gsc-utils/docs/write_protection.md (revision 4f2df630800bdcf1d4f0decf95d8a1cb87344f5f)
1*4f2df630SAndroid Build Coastguard Worker# Firmware Write Protection
2*4f2df630SAndroid Build Coastguard Worker
3*4f2df630SAndroid Build Coastguard Worker[TOC]
4*4f2df630SAndroid Build Coastguard Worker
5*4f2df630SAndroid Build Coastguard WorkerThis is a somewhat tricky topic since write protection implementations can
6*4f2df630SAndroid Build Coastguard Workerdiffer between chips and the hardware write protection has changed over time,
7*4f2df630SAndroid Build Coastguard Workerso please edit or open a bug if something is not clear.
8*4f2df630SAndroid Build Coastguard Worker
9*4f2df630SAndroid Build Coastguard Worker## Terminology
10*4f2df630SAndroid Build Coastguard Worker
11*4f2df630SAndroid Build Coastguard Worker## RO and RW
12*4f2df630SAndroid Build Coastguard Worker
13*4f2df630SAndroid Build Coastguard WorkerMCUs running the EC code have read-only (RO) and read-write (RW) firmware.
14*4f2df630SAndroid Build Coastguard WorkerComing out of reset, the MCU boots into its RO firmware.
15*4f2df630SAndroid Build Coastguard Worker
16*4f2df630SAndroid Build Coastguard WorkerIn the case of the EC, the RO firmware boots the host and asks it verify a hash
17*4f2df630SAndroid Build Coastguard Workerof the RW firmware (software sync). If the RW firmware is invalid, it is
18*4f2df630SAndroid Build Coastguard Workerupdated from a copy in the host's RW firmware.
19*4f2df630SAndroid Build Coastguard Worker
20*4f2df630SAndroid Build Coastguard WorkerIn the case of the FPMCU, the RO firmware uses the public key embedded in it to
21*4f2df630SAndroid Build Coastguard Workervalidate the signature of the RW firmware. If the RW firmware is invalid it
22*4f2df630SAndroid Build Coastguard Workerdoes not jump to the RW firmware.
23*4f2df630SAndroid Build Coastguard Worker
24*4f2df630SAndroid Build Coastguard WorkerOnce the RW firmware is validated, the MCU jumps to it (without rebooting). The
25*4f2df630SAndroid Build Coastguard WorkerRO firmware is locked in the factory and is never changed. The RW firmware can
26*4f2df630SAndroid Build Coastguard Workerbe updated later by pushing a new system firmware containing an updated RW
27*4f2df630SAndroid Build Coastguard Workerregion.
28*4f2df630SAndroid Build Coastguard Worker
29*4f2df630SAndroid Build Coastguard WorkerNote that both the RO and RW firmware regions are normally protected once write
30*4f2df630SAndroid Build Coastguard Workerprotect has been turned on.
31*4f2df630SAndroid Build Coastguard Worker
32*4f2df630SAndroid Build Coastguard WorkerIn the case of the EC, the RW region is unprotected at MCU boot until it has
33*4f2df630SAndroid Build Coastguard Workerbeen verified by the host. The RW region is protected before the Linux kernel
34*4f2df630SAndroid Build Coastguard Workeris loaded.
35*4f2df630SAndroid Build Coastguard Worker
36*4f2df630SAndroid Build Coastguard WorkerIn the case of the FPMCU, the RW region is protected before jumping the RO
37*4f2df630SAndroid Build Coastguard Workerfirmware jumps to it.
38*4f2df630SAndroid Build Coastguard Worker
39*4f2df630SAndroid Build Coastguard Worker## Hardware Write Protect {#hw_wp}
40*4f2df630SAndroid Build Coastguard Worker
41*4f2df630SAndroid Build Coastguard WorkerOn modern Chrome OS devices, the Cr50 (aka GSC / TPM) provides a "hardware
42*4f2df630SAndroid Build Coastguard Workerwrite protect" GPIO that is connected to the AP SPI flash, EC SPI flash,
43*4f2df630SAndroid Build Coastguard WorkerEEPROM, and FPMCU via a [GPIO][write_protect_gpio].  This "hardware write
44*4f2df630SAndroid Build Coastguard Workerprotect" can only be disabled with servo or suzyq (["CCD open"]) and
45*4f2df630SAndroid Build Coastguard Workercorresponds to [`OverrideWP`] in ccd. Disabling this write protect disables it
46*4f2df630SAndroid Build Coastguard Workerfor everything connected to this signal.
47*4f2df630SAndroid Build Coastguard Worker
48*4f2df630SAndroid Build Coastguard WorkerIn the case of the FPMCU, the hardware write protect GPIO is tied to the STM32
49*4f2df630SAndroid Build Coastguard Worker`BOOT0` pin, which is what tells the MCU to enter the STM32 bootloader mode.
50*4f2df630SAndroid Build Coastguard Worker
51*4f2df630SAndroid Build Coastguard WorkerYou may see various references to a [write protect screw in
52*4f2df630SAndroid Build Coastguard Workerdocumentation][wp_screw]. Older Chrome OS devices had a write protect screw
53*4f2df630SAndroid Build Coastguard Workerthat had to be physically removed. More details on this history can be found
54*4f2df630SAndroid Build Coastguard Workerhere: http://go/cros-wp-status.
55*4f2df630SAndroid Build Coastguard Worker
56*4f2df630SAndroid Build Coastguard WorkerAnother way of disabling hardware write protection is to remove the battery;
57*4f2df630SAndroid Build Coastguard Workerthis method is mainly used during bringup.
58*4f2df630SAndroid Build Coastguard Worker
59*4f2df630SAndroid Build Coastguard WorkerAdditional reference:
60*4f2df630SAndroid Build Coastguard Workerhttps://www.google.com/chromeos/partner/fe/docs/cpfe/firmwaretestmanual.html#hardware-write-protect
61*4f2df630SAndroid Build Coastguard Worker
62*4f2df630SAndroid Build Coastguard Worker## Changing Hardware Write Protection
63*4f2df630SAndroid Build Coastguard Worker
64*4f2df630SAndroid Build Coastguard WorkerModifying the state of hardware write protection (via Cr50 GPIO) can be done
65*4f2df630SAndroid Build Coastguard Workerif the ["CCD open"] process has been completed.
66*4f2df630SAndroid Build Coastguard Worker
67*4f2df630SAndroid Build Coastguard Worker*** note
68*4f2df630SAndroid Build Coastguard Worker`servod` *must* be running for `dut-control` to work. See the [Servo] page for
69*4f2df630SAndroid Build Coastguard Workerdetails.
70*4f2df630SAndroid Build Coastguard Worker***
71*4f2df630SAndroid Build Coastguard Worker
72*4f2df630SAndroid Build Coastguard Worker### Enable Hardware Write Protection
73*4f2df630SAndroid Build Coastguard Worker
74*4f2df630SAndroid Build Coastguard Worker```bash
75*4f2df630SAndroid Build Coastguard Worker(chroot)$ dut-control fw_wp_state:force_on
76*4f2df630SAndroid Build Coastguard Worker```
77*4f2df630SAndroid Build Coastguard Worker
78*4f2df630SAndroid Build Coastguard Worker### Disable Hardware Write Protection
79*4f2df630SAndroid Build Coastguard Worker
80*4f2df630SAndroid Build Coastguard Worker```bash
81*4f2df630SAndroid Build Coastguard Worker(chroot)$ dut-control fw_wp_state:force_off
82*4f2df630SAndroid Build Coastguard Worker```
83*4f2df630SAndroid Build Coastguard Worker
84*4f2df630SAndroid Build Coastguard Worker### Enable/Disable Hardware Write Protection via Cr50 Console
85*4f2df630SAndroid Build Coastguard Worker
86*4f2df630SAndroid Build Coastguard WorkerYou can use the following commands from the [Cr50 console]:
87*4f2df630SAndroid Build Coastguard Worker
88*4f2df630SAndroid Build Coastguard Worker```bash
89*4f2df630SAndroid Build Coastguard Workerwp disable
90*4f2df630SAndroid Build Coastguard Worker```
91*4f2df630SAndroid Build Coastguard Worker
92*4f2df630SAndroid Build Coastguard Worker```bash
93*4f2df630SAndroid Build Coastguard Workerwp enable
94*4f2df630SAndroid Build Coastguard Worker```
95*4f2df630SAndroid Build Coastguard Worker
96*4f2df630SAndroid Build Coastguard Worker```bash
97*4f2df630SAndroid Build Coastguard Workerwp follow_batt_pres
98*4f2df630SAndroid Build Coastguard Worker```
99*4f2df630SAndroid Build Coastguard Worker
100*4f2df630SAndroid Build Coastguard Worker## Software Write Protect
101*4f2df630SAndroid Build Coastguard Worker
102*4f2df630SAndroid Build Coastguard WorkerSoftware-based write protect state stored in non-volatile memory. If hardware
103*4f2df630SAndroid Build Coastguard Workerwrite protect is enabled, software write protect can be enabled but can’t be
104*4f2df630SAndroid Build Coastguard Workerdisabled. If hardware write protect is disabled, software write protect can be
105*4f2df630SAndroid Build Coastguard Workerenabled or disabled (note that some implementations require an EC reset to
106*4f2df630SAndroid Build Coastguard Workerdisable software write protect).
107*4f2df630SAndroid Build Coastguard Worker
108*4f2df630SAndroid Build Coastguard WorkerThe underlying mechanism implementing software write protect may differ between
109*4f2df630SAndroid Build Coastguard WorkerEC chips. However the common requirements are that software write protect can
110*4f2df630SAndroid Build Coastguard Workeronly be disabled when hardware write protect is off and that the RO firmware
111*4f2df630SAndroid Build Coastguard Workermust be protected before jumping to RW firmware if protection is enabled.
112*4f2df630SAndroid Build Coastguard Worker
113*4f2df630SAndroid Build Coastguard Worker*** note
114*4f2df630SAndroid Build Coastguard Worker*WARNING*: If you disable HW write protect *and* then reboot the FPMCU, it will do
115*4f2df630SAndroid Build Coastguard Workera mass erase of the chip, due to [RDP1](#rdp1).
116*4f2df630SAndroid Build Coastguard Worker***
117*4f2df630SAndroid Build Coastguard Worker
118*4f2df630SAndroid Build Coastguard WorkerAdditional reference:
119*4f2df630SAndroid Build Coastguard Workerhttps://www.google.com/chromeos/partner/fe/docs/cpfe/firmwaretestmanual.html#software-write-protect
120*4f2df630SAndroid Build Coastguard Worker
121*4f2df630SAndroid Build Coastguard Worker## Changing Software Write Protection
122*4f2df630SAndroid Build Coastguard Worker
123*4f2df630SAndroid Build Coastguard Worker*** note
124*4f2df630SAndroid Build Coastguard Worker*NOTE*: You cannot disable software write protect if hardware write protect is
125*4f2df630SAndroid Build Coastguard Workerenabled.
126*4f2df630SAndroid Build Coastguard Worker***
127*4f2df630SAndroid Build Coastguard Worker
128*4f2df630SAndroid Build Coastguard WorkerSoftware write protection can be toggled with `ectool --name=cros_fp flashprotect
129*4f2df630SAndroid Build Coastguard Workerenable/disable`, which sends the `EC_CMD_FLASH_PROTECT` command toggling
130*4f2df630SAndroid Build Coastguard Worker`EC_FLASH_PROTECT_RO_AT_BOOT` (changing `--name` to target different ECs).
131*4f2df630SAndroid Build Coastguard Worker
132*4f2df630SAndroid Build Coastguard Worker### Changing Software Write Protection with `ectool`
133*4f2df630SAndroid Build Coastguard Worker
134*4f2df630SAndroid Build Coastguard Worker#### `ectool flashprotect`
135*4f2df630SAndroid Build Coastguard Worker
136*4f2df630SAndroid Build Coastguard WorkerPrint out current flash protection state.
137*4f2df630SAndroid Build Coastguard Worker
138*4f2df630SAndroid Build Coastguard Worker```
139*4f2df630SAndroid Build Coastguard WorkerFlash protect flags: 0x0000000f wp_gpio_asserted ro_at_boot ro_now all_now
140*4f2df630SAndroid Build Coastguard WorkerValid flags:         0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
141*4f2df630SAndroid Build Coastguard WorkerWritable flags:      0x00000000
142*4f2df630SAndroid Build Coastguard Worker```
143*4f2df630SAndroid Build Coastguard Worker
144*4f2df630SAndroid Build Coastguard Worker`Flash protect flags` - Current flags that are set.
145*4f2df630SAndroid Build Coastguard Worker
146*4f2df630SAndroid Build Coastguard Worker`Valid flags` - All the options for flash protection.
147*4f2df630SAndroid Build Coastguard Worker
148*4f2df630SAndroid Build Coastguard Worker`Writable flags` - The flags that currently can be changed. (In this case, no
149*4f2df630SAndroid Build Coastguard Workerflags can be changed).
150*4f2df630SAndroid Build Coastguard Worker
151*4f2df630SAndroid Build Coastguard WorkerFlags:
152*4f2df630SAndroid Build Coastguard Worker
153*4f2df630SAndroid Build Coastguard Worker*   `wp_gpio_asserted` - Whether the hardware write protect GPIO is currently
154*4f2df630SAndroid Build Coastguard Worker    asserted (read only).
155*4f2df630SAndroid Build Coastguard Worker
156*4f2df630SAndroid Build Coastguard Worker*   `ro_at_boot` - Whether the EC will write protect the RO firmware on the next
157*4f2df630SAndroid Build Coastguard Worker    boot of the EC.
158*4f2df630SAndroid Build Coastguard Worker
159*4f2df630SAndroid Build Coastguard Worker*   `ro_now` - Protect the read-only portion of flash immediately. Requires
160*4f2df630SAndroid Build Coastguard Worker    hardware WP be enabled.
161*4f2df630SAndroid Build Coastguard Worker
162*4f2df630SAndroid Build Coastguard Worker*   `all_now` - Protect the entire flash (including RW) immediately. Requires
163*4f2df630SAndroid Build Coastguard Worker    hardware WP be enabled.
164*4f2df630SAndroid Build Coastguard Worker
165*4f2df630SAndroid Build Coastguard Worker*   `STUCK` - Flash protection settings have been fused and can’t be cleared
166*4f2df630SAndroid Build Coastguard Worker    (should not happen during normal operation. Read only.)
167*4f2df630SAndroid Build Coastguard Worker
168*4f2df630SAndroid Build Coastguard Worker*   `INCONSISTENT` - One or more banks of flash is not protected when it should
169*4f2df630SAndroid Build Coastguard Worker    be (should not happen during normal operation. Read only.).
170*4f2df630SAndroid Build Coastguard Worker
171*4f2df630SAndroid Build Coastguard Worker#### `ectool flashprotect enable`
172*4f2df630SAndroid Build Coastguard Worker
173*4f2df630SAndroid Build Coastguard WorkerSet `ro_at_boot` flag. The next time the EC is reset it will protect the flash.
174*4f2df630SAndroid Build Coastguard WorkerNote that this requires a cold reset.
175*4f2df630SAndroid Build Coastguard Worker
176*4f2df630SAndroid Build Coastguard Worker#### `ectool flashprotect enable now`
177*4f2df630SAndroid Build Coastguard Worker
178*4f2df630SAndroid Build Coastguard WorkerSet `ro_at_boot` `ro_now all_now` flags and immediately protect the flash. Note
179*4f2df630SAndroid Build Coastguard Workerthat this will fail if hardware write protect is disabled.
180*4f2df630SAndroid Build Coastguard Worker
181*4f2df630SAndroid Build Coastguard Worker#### `ectool flashprotect disable`
182*4f2df630SAndroid Build Coastguard Worker
183*4f2df630SAndroid Build Coastguard WorkerClear `ro_at_boot` flag. This can only be cleared if the EC booted without
184*4f2df630SAndroid Build Coastguard Workerhardware write protect enabled.
185*4f2df630SAndroid Build Coastguard Worker
186*4f2df630SAndroid Build Coastguard WorkerNote that you must reset the EC to clear write protect after removing the screw.
187*4f2df630SAndroid Build Coastguard WorkerIf the `ro_at_boot` flag set and the EC resets with the HW gpio disabled, the EC
188*4f2df630SAndroid Build Coastguard Workerwill leave the flash unprotected (`ro_now` and `all_now` flags are not set) but
189*4f2df630SAndroid Build Coastguard Workerleave `ro_at_boot` flag set.
190*4f2df630SAndroid Build Coastguard Worker
191*4f2df630SAndroid Build Coastguard Worker## `system_is_locked()`
192*4f2df630SAndroid Build Coastguard Worker
193*4f2df630SAndroid Build Coastguard WorkerThe [`system_is_locked()`] function in the EC code returns false if the HW
194*4f2df630SAndroid Build Coastguard Workerwrite protect GPIO is disabled or the read-only firmware is not protected.
195*4f2df630SAndroid Build Coastguard Worker
196*4f2df630SAndroid Build Coastguard WorkerOne way this is used in the FPMCU source is to compile test or debug
197*4f2df630SAndroid Build Coastguard Workerfunctionality into the firmware. Guarding the test functionality with
198*4f2df630SAndroid Build Coastguard Worker`system_is_locked` allows us to execute the test code in automated testing by
199*4f2df630SAndroid Build Coastguard Workerdisabling the hardware write protection; this means we can run the automated
200*4f2df630SAndroid Build Coastguard Workertests against the exact same firmware we ship, rather than a different version
201*4f2df630SAndroid Build Coastguard Workerthat has test functionality compiled in or out.
202*4f2df630SAndroid Build Coastguard Worker
203*4f2df630SAndroid Build Coastguard Worker## RDP1 {#rdp1}
204*4f2df630SAndroid Build Coastguard Worker
205*4f2df630SAndroid Build Coastguard WorkerStands for Readout Protection Level 1.
206*4f2df630SAndroid Build Coastguard Worker
207*4f2df630SAndroid Build Coastguard WorkerProtects user flash memory against a debugger (JTAG/SWD) or potential malicious
208*4f2df630SAndroid Build Coastguard Workercode stored in RAM by disabling access (a bus error is generated when read
209*4f2df630SAndroid Build Coastguard Workeraccess is requested). Otherwise (no debugger connected and no boot in RAM set),
210*4f2df630SAndroid Build Coastguard Workerall read/program/erase operations from/to flash are allowed.
211*4f2df630SAndroid Build Coastguard Worker
212*4f2df630SAndroid Build Coastguard WorkerWhen switching to a lower level of RDP (i.e., setting to 0), the user flash
213*4f2df630SAndroid Build Coastguard Workermemory is mass erased (set to all `0xFF`).
214*4f2df630SAndroid Build Coastguard Worker
215*4f2df630SAndroid Build Coastguard WorkerNote that this completely destroys *all* of the firmware, including the RO
216*4f2df630SAndroid Build Coastguard Workersection.
217*4f2df630SAndroid Build Coastguard Worker
218*4f2df630SAndroid Build Coastguard Worker### Additional References
219*4f2df630SAndroid Build Coastguard Worker
220*4f2df630SAndroid Build Coastguard Workerhttps://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1222094
221*4f2df630SAndroid Build Coastguard Worker
222*4f2df630SAndroid Build Coastguard Worker## EC Flash Read/Write Command Write Protection Checks
223*4f2df630SAndroid Build Coastguard Worker
224*4f2df630SAndroid Build Coastguard WorkerThe EC code command handlers (`command_flash_erase`, `command_flash_write`,
225*4f2df630SAndroid Build Coastguard Workeretc.) return an error if `EC_FLASH_PROTECT_ALL_NOW` is set.
226*4f2df630SAndroid Build Coastguard Worker
227*4f2df630SAndroid Build Coastguard Worker[write_protect_gpio]: https://chromium.googlesource.com/chromiumos/platform/ec/+/aaba1d5efd51082d143ce2ac64e6caf9cb14d5e5/include/ec_commands.h#1599
228*4f2df630SAndroid Build Coastguard Worker["CCD open"]: ./case_closed_debugging_gsc.md#Open-CCD
229*4f2df630SAndroid Build Coastguard Worker[Cr50 console]: ./case_closed_debugging_gsc.md#Consoles
230*4f2df630SAndroid Build Coastguard Worker[`OverrideWP`]: ./case_closed_debugging_gsc.md
231*4f2df630SAndroid Build Coastguard Worker[wp_screw]: https://www.chromium.org/chromium-os/firmware-porting-guide/firmware-ec-write-protection
232*4f2df630SAndroid Build Coastguard Worker[`system_is_locked()`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/aaba1d5efd51082d143ce2ac64e6caf9cb14d5e5/common/system.c#195
233*4f2df630SAndroid Build Coastguard Worker[Servo]: https://www.chromium.org/chromium-os/servo
234