This document describes known methods of flashing BIOS on xx20 and xx30 series of Lenovo ThinkPads without external programmer. The main goal is flashing coreboot while running stock BIOS.
**First** is the fact the SMM_BWP and BLE are not enabled in BIOS versions released before 2014. I have tested many versions on T430 and X230 and found out that SMM_BWP=1 only since the update, the changelog of which contains following line:
Below is a list of BIOS versions that are vulnerable enough for our goals, per model. The version number means that you need to downgrade to that or earlier version.
If your BIOS version is equal or lower, skip to the **[Examining and removing protections](#examining-and-removing-protections)** section. If not, go through the downgrade process, described next.
Lenovo states that BIOS has "security rollback prevention", meaning once you update it to some version X, you will not be able to downgrade it to pre-X version. That's not true. It seems that this is completely client-side restriction in flashing utilities (both Windows utility and Bootable CD). You just need to call `winflash.exe` or `dosflash.exe` directly. Therefore you need to modify the bootable CD image you just downloaded.
Now, before you process, make sure that AC adapter is connected! If your battery will die during the process, you'll likely need external programmer to recover.
Now boot to your Linux system and make sure that `/sys/firmware/efi` or `/sys/firmware/efivars` exist.
[Install CHIPSEC](https://github.com/chipsec/chipsec/wiki/Installing-CHIPSEC-in-Linux). You will need two patches for it, as they are not merged yet: [#737](https://github.com/chipsec/chipsec/pull/737) and [#738](https://github.com/chipsec/chipsec/pull/738). Without those patches, s3script_modify will not work.
- SPI Protected Range Registers (**PR0**-**PR4**) of SPI Configuration Registers (SPIBAR+0x74 - SPIBAR+0x84). Each register has bits that define protected range, plus WP bit, that defines whether write protection is enabled.
- **FLOCKDN** bit of HSFS register (SPIBAR+0x04) of SPI Configuration Registers. When set to 1, PR0-PR4 registers cannot be written. Once set to 1, cannot be changed anymore.
To be able to flash, we need SMM_BWP=0, BIOSWE=1, BLE=0, FLOCKDN=0 or SPI protected ranges (PRx) to have a WP bit set to 0.
Let's see what we have. Run this to examine HSFS register:
As you can see, the only thing we need is to unset WP on PR0-PR4. But that cannot be done once FLOCKDN is set to 1.
Now the fun part!
FLOCKDN may only be cleared by a hardware reset, which includes S3 state. On S3 resume boot path, the chipset configuration has to be restored and it's done by executing so-called S3 Boot Scripts. You can dump these scripts by executing:
These scripts are stored in memory. The vulnerability is that we can overwrite this memory, change these instructions and they will be executed on S3 resume. Once we patch that instruction to not set FLOCKDN bit, we will be able to write to PR0-PR4 registers.
**Note:** if you're flashing coreboot for the first time, you should have an external SPI programmer just in case. It will help you recover if you flash non-working ROM.
S3 Boot Scripts are unprotected on these models too (even on the most recent BIOS versions), but it's not useful, because FLOCKDN and SPI protected ranges are set by **LenovoFlashProtectPei** UEFI module. It is trivial to patch it, but it resides in protected range, so it can only be flashed externally.
Currenly there are no known methods to unlock PRs on these devices internally, but investigation is ongoing.