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