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