Removing SPI chip protection on xx20 ThinkPads
In order to be able to flash BIOS on SandyBridge Lenovo ThinkPads (X220, T420, T520), all SPI Protected Range registers (SPIBAR+0x74) must have WP bit set to 0 (or they must protect something else, but not the bios region). Other security measures, such as BLE and SMM_BWP are not enabled on these machines.
Lenovo BIOS uses PR0 register correctly and write-protects 0x00780000-0x01FFFFFF:
$ sudo python chipsec_main.py -m chipsec.modules.common.bios_wp
[*] BIOS Region: Base = 0x00500000, Limit = 0x007FFFFF
SPI Protected Ranges
------------------------------------------------------------
PRx (offset) | Value | Base | Limit | WP? | RP?
------------------------------------------------------------
PR0 (74) | 9FFF0780 | 00780000 | 01FFFFFF | 1 | 0
PR1 (78) | 00000000 | 00000000 | 00000000 | 0 | 0
PR2 (7C) | 00000000 | 00000000 | 00000000 | 0 | 0
PR3 (80) | 00000000 | 00000000 | 00000000 | 0 | 0
PR4 (84) | 00000000 | 00000000 | 00000000 | 0 | 0
You may want to patch the BIOS to disable this protection. One reason that comes to mind, as to why would you ever want that, is that if you're a coreboot developer and want to switch between stock BIOS and coreboot quickly and internally.
Open the BIOS dump in UEFITool, find the LenovoFlashProtectPei.efi module and extract the PE32 image body:
Disassemble the extracted file. You can use r2, but even objdump is enough in this case:
$ objdump -d LenovoFlashProtectPei.efi
Find the place where PR0 is set:
...
fffcc3e6: a1 f0 80 0f f8 mov 0xf80f80f0,%eax
fffcc3eb: c1 e9 0c shr $0xc,%ecx
fffcc3ee: 56 push %esi
fffcc3ef: 81 e1 ff 1f 00 00 and $0x1fff,%ecx
fffcc3f5: 81 c9 00 00 ff 9f or $0x9fff0000,%ecx ; Here the WP bit is set
fffcc3fb: 6a fe push $0xfffffffe
fffcc3fd: 8b d1 mov %ecx,%edx
fffcc3ff: 59 pop %ecx
fffcc400: 23 c1 and %ecx,%eax
fffcc402: 66 8b 80 04 38 00 00 mov 0x3804(%eax),%ax ; 0x3804 is the offset of HSFS
fffcc409: 8b 35 f0 80 0f f8 mov 0xf80f80f0,%esi
fffcc40f: 23 f1 and %ecx,%esi
fffcc411: 8b b6 74 38 00 00 mov 0x3874(%esi),%esi ; 0x3874 is the offset of PR0
fffcc417: 66 85 c0 test %ax,%ax
fffcc41a: b8 74 38 00 00 mov $0x3874,%eax
fffcc41f: 79 63 jns 0xfffcc484
...
You just need to change 0x9fff0000
to 0x0fff0000
. So find this place in hex editor:
81 c9 00 00 ff 9f 6a fe
and make it:
81 c9 00 00 ff 0f 6a fe
Replace the module:
Save updated image (File -> Save image file).
Now you can flash it using external SPI programmer and the PR0 region will not be write protected.