Coreboot and the Lenovo T430
One of the things which I always wanted to do to my Lenovo T430 is to modify the BIOS to run CoreBoot. Coreboot is a freeware alternative that replaces a computer’s BIOS. One of the main advantages of running Coreboot is removing the whitelist for certain WLAN and WWAN cards. This has become a sticking point as WLAN cards move into 802.11ac and 802.11ax iterations. Yet another advantage, especially for privacy-minded individuals is the removal of the Intel Management Engine software that exists in many vendor ROMs and which has been shown to possess certain vulnerabilities.
For the T430 to be flashed to Coreboot, the T430 has to be disassembled completely. This is done to gain access to the 2 BIOS chips on the underside of the motherboard. It is also a good idea to take the opportunity to clean and reapply the heatsink compound - it would have dried up anyway.
You will need a Raspberry Pi to run Flashrom and another Linux PC to compile Coreboot. I used a Raspberry Pi 2 Model B, a 8GB microSD card, a SOIC-8 test clip and 8 female to female jumper wires.
Preparation
Linux PC
-
Download and flash the latest Raspberry Pi OS to the 8GB SD Card. The lite version is sufficient.
-
Download me_cleaner
$ mkdir -p ~/Sources
$ cd ~/Sources
$ git clone https://github.com/corna/me_cleaner
- Download Coreboot
$ cd ~/Sources
$ git clone --recursive https://github.com/coreboot/coreboot
$ cd ~/Sources/coreboot/3rdparty
$ git clone http://review.coreboot.org/p/blobs.git
- Create the necessary folder in the coreboot directory for our T430 target machine
$ mkdir -p ~/Sources/coreboot/3rdparty/blobs/mainboard/lenovo/t430
$ mkdir -p ~/Sources/roms/
- Compile the ifdtool for extraction of the binary blobs later on.
$ cd ~/Sources/coreboot/util/ifdtool
$ make
$ sudo make install
Raspberry Pi
- On your Raspberry Pi, enable the following services from raspi-config, enable the SPI devices and remote GPIO.
SSH
SPI
I2C
Remote GPIO
- Enable SPI and reboot
$ sudo modprobe spi_bcm2835
$ sudo modprobe spidev
$ sudo reboot
- Connect the jumper wires as such from the Raspberry PI to the SOIC-8 test clip.
SOIC-8 1 <---> Pi 24 (GPIO 8 - SPI0 CE0)
SOIC-8 2 <---> Pi 21 (GPIO 9 - SPI0 MISO)
SOIC-8 3 <---> Unused
SOIC-8 4 <---> Pi 25 (Ground)
SOIC-8 5 <---> Pi 19 (GPIO 10 - SPI0 MISI)
SOIC-8 6 <---> Unused
SOIC-8 7 <---> Pi 23 (GPIO 11 - SPI0 SCLK)
SOIC-8 8 <---> Pi 17 (3.3V)
RPi pinouts are available at pinouts.xyz.
Backup
-
Clip the SOIC-8 test clip on the 8MB chip. This is the chip labelled UE46. Be sure to align Pin 1 of the clip with Pin 1 of the BIOS chip.
-
On the RPi, test the connection between the RPi and the chip.
pi@raspberrypi:~/ $ mkdir rom
pi@raspberrypi:~/ $ cd rom
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L6405" (8192 kB, SPI) on linux_spi.
Found Macronix flash chip "MX25L6405D" (8192 kB, SPI) on linux_spi.
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on linux_spi.
Found Macronix flash chip "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F" (8192 kB, SPI) on linux_spi.
Multiple flash chip definitions match the detected chip(s): "MX25L6405", "MX25L6405D", "MX25L6406E/MX25L6408E", "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F"
Please specify which chip definition to use with the -c <chipname> option.
pi@raspberrypi:~/rom $
The 8MB flash chip detected may be different for different T430 models. You can ascertain this by examining the chip itself and noting the model number. In my case, the model detected is “MX25L6406E/MX25L6408E”.
- I am paranoid, so I backup the ROM 3 times.
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L6406E/MX25L6408E" -r ./backup_rom1.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on linux_spi.
Reading flash... done.
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L6406E/MX25L6408E" -r ./backup_rom2.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on linux_spi.
Reading flash... done.
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L6406E/MX25L6408E" -r ./backup_rom3.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on linux_spi.
Reading flash... done.
pi@raspberrypi:~/rom $
- Remove the clip and relocate it to the 4MB chip. This is the chip labelled UE66. Again, align Pin 1 of both the clip and the chip. Check connectivity.
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L3205D/MX25L3208D" (4096 kB, SPI) on linux_spi.
Reading flash... done.
pi@raspberrypi:~/rom $
- Backup the ROM 3 times.
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L3205D/MX25L3208D" -r ./backup_rom4.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L3205D/MX25L3208D" (4096 kB, SPI) on linux_spi.
Reading flash... done.
pi@raspberrypi:~/rom $
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L3205D/MX25L3208D" -r ./backup_rom5.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L3205D/MX25L3208D" (4096 kB, SPI) on linux_spi.
Reading flash... done.
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L3205D/MX25L3208D" -r ./backup_rom6.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L3205D/MX25L3208D" (4096 kB, SPI) on linux_spi.
Reading flash... done.
pi@raspberrypi:~/rom $
- Check SHA checksum to make sure the ROMs are the same.
pi@raspberrypi:~/rom $ sha512sum ./*.bin
1d6c6e8fd64499dfe75156dc3f6f3fc55f1c9c963da93e75e98b9c45809637378af810efdf392da6fc8435a98ac10572f9457887643a81093bb450b61ec8f871 ./backup_rom1.bin
1d6c6e8fd64499dfe75156dc3f6f3fc55f1c9c963da93e75e98b9c45809637378af810efdf392da6fc8435a98ac10572f9457887643a81093bb450b61ec8f871 ./backup_rom2.bin
1d6c6e8fd64499dfe75156dc3f6f3fc55f1c9c963da93e75e98b9c45809637378af810efdf392da6fc8435a98ac10572f9457887643a81093bb450b61ec8f871 ./backup_rom3.bin
9ce1857888ca99893102d94f627ca321b4aba1f15c76f624c2e924b2a0221f41105b927af758986e9029892a6802c113d01f626d9ae79ca2d05e504fec8439ae ./backup_rom4.bin
9ce1857888ca99893102d94f627ca321b4aba1f15c76f624c2e924b2a0221f41105b927af758986e9029892a6802c113d01f626d9ae79ca2d05e504fec8439ae ./backup_rom5.bin
9ce1857888ca99893102d94f627ca321b4aba1f15c76f624c2e924b2a0221f41105b927af758986e9029892a6802c113d01f626d9ae79ca2d05e504fec8439ae ./backup_rom6.bin
Combination, ME Cleaning and Extraction
- Copy 1 8MB ROM and 1 4MB ROM to the Linux PC via
scp
. All following steps are on the Linux PC.
$ scp -r ./backup_rom1.bin ./backup_rom4.bin <user>@<linuxpc>:~/Sources/rom/
- Combine the 2 ROMS to make a complete 12MB image. Prepare an image for ME cleaning as well.
$ cd ~/Sources/roms
$ cat ./backup_rom1.bin ./backup_rom4.bin > ./t430_original.bin
$ cp ./t430_original.bin ./t430_cleaned.bin
- Remove the Intel Management Engine by using ME Cleaner
$ ~/Sources/me_cleaner/me_cleaner.py -S ./t430_cleaned.bin
Full image detected
Found FPT header at 0x3010
Found 23 partition(s)
Found FTPR header: FTPR partition spans from 0x180000 to 0x24a000
ME/TXE firmware version 8.1.72.3002 (generation 2)
Public key match: Intel ME, firmware versions 7.x.x.x, 8.x.x.x
The AltMeDisable bit is NOT SET
Reading partitions list...
???? (0x000003c0 - 0x000000400, 0x00000040 total bytes): removed
FOVD (0x00000400 - 0x000001000, 0x00000c00 total bytes): removed
MDES (0x00001000 - 0x000002000, 0x00001000 total bytes): removed
FCRS (0x00002000 - 0x000003000, 0x00001000 total bytes): removed
EFFS (0x00003000 - 0x0000df000, 0x000dc000 total bytes): removed
BIAL (NVRAM partition, no data, 0x0000add0 total bytes): nothing to remove
BIEL (NVRAM partition, no data, 0x00003000 total bytes): nothing to remove
BIIS (NVRAM partition, no data, 0x00036000 total bytes): nothing to remove
NVCL (NVRAM partition, no data, 0x00010511 total bytes): nothing to remove
NVCM (NVRAM partition, no data, 0x0000493f total bytes): nothing to remove
NVCP (NVRAM partition, no data, 0x0000a553 total bytes): nothing to remove
NVJC (NVRAM partition, no data, 0x00004000 total bytes): nothing to remove
NVKR (NVRAM partition, no data, 0x0001257d total bytes): nothing to remove
NVOS (NVRAM partition, no data, 0x00034af5 total bytes): nothing to remove
NVSH (NVRAM partition, no data, 0x00007609 total bytes): nothing to remove
NVTD (NVRAM partition, no data, 0x00001eac total bytes): nothing to remove
PLDM (NVRAM partition, no data, 0x0000a000 total bytes): nothing to remove
GLUT (0x000df000 - 0x0000e3000, 0x00004000 total bytes): removed
LOCL (0x000e3000 - 0x0000e7000, 0x00004000 total bytes): removed
WCOD (0x000e7000 - 0x000140000, 0x00059000 total bytes): removed
MDMV (0x00140000 - 0x000180000, 0x00040000 total bytes): removed
FTPR (0x00180000 - 0x00024a000, 0x000ca000 total bytes): NOT removed
NFTP (0x0024a000 - 0x0004a4000, 0x0025a000 total bytes): removed
Removing partition entries in FPT...
Removing EFFS presence flag...
Correcting checksum (0x2f)...
Reading FTPR modules list...
UPDATE (LZMA , 0x1cc508 - 0x1cc6c6 ): removed
ROMP (Huffman, fragmented data, ~2 KiB ): NOT removed, essential
BUP (Huffman, fragmented data, ~56 KiB ): NOT removed, essential
KERNEL (Huffman, fragmented data, ~135 KiB ): removed
POLICY (Huffman, fragmented data, ~91 KiB ): removed
HOSTCOMM (LZMA , 0x1cc6c6 - 0x1d343f ): removed
RSA (LZMA , 0x1d343f - 0x1d872a ): removed
CLS (LZMA , 0x1d872a - 0x1ddec0 ): removed
TDT (LZMA , 0x1ddec0 - 0x1e45be ): removed
FTCS (Huffman, fragmented data, ~18 KiB ): removed
ClsPriv (LZMA , 0x1e45be - 0x1e499f ): removed
SESSMGR (LZMA , 0x1e499f - 0x1f32cb ): removed
The ME minimum size should be 1667072 bytes (0x197000 bytes)
The ME region can be reduced up to:
00003000:00199fff me
Setting the AltMeDisable bit in PCHSTRP10 to disable Intel ME...
Checking the FTPR RSA signature... VALID
Done! Good luck!
- Extract the various bin files using
ifdtool
. Copy them into the coreboot directory.
$ cd ~
$ ifdtool -x ~/t430_cleaned.bin
$ cd ~/Sources/coreboot/3rdparty/blobs/mainboard/lenovo/t430/
$ mv ~/Sources/roms/flashregion_0_flashdescriptor.bin ./descriptor.bin
$ mv ~/Sources/roms/flashregion_2_intel_me.bin ./me.bin
$ mv ~/Sources/roms/flashregion_3_gbe.bin ./gbe.bin
CoreBoot
-
Compiling on the Linux PC is preferable to compiling on the RPi.
-
Configure coreboot with the appropriate options.
$ make nconfig
While there are no one-size-fits-all configuration, the below configuration is suggested as the minimum.
General Setup
Use CMOS for configuration values
Mainboard
Mainboard vendor >>> Select >> Lenovo
Mainboard model >>> Select >>> T430
ROM chip size (12288 KB (12 MB))
(0x100000) Size of CBFS filesystem in ROM
Chipset
Add Intel descriptor.bin file
Add Intel ME/TXE firmware
Add gigabit ethernet configuration
Devices
Enable PCIe Clock Power Management
Enable PCIe ASPM L1 SubState
Generic Driver
Support Intel PCI-e WiFi adapters
PS/2 keyboard init
- Start the compilation. Build the gcc toolchain and build coreboot after that.
$ make crossgcc-i386 CPUS=2
$ make iasl
$ make
The result will be a coreboot.rom
in the ~/Sources/coreboot/build
directory.
Flashing the Coreboot ROM
- We will have to split the coreboot.rom file into 2 files, 1 8MB and 1 4MB before flashing.
scp
the result back to the RPi. All following commands are performed on the RPi.
$ cp ~/Sources/coreboot/build/coreboot.rom ~/Sources/roms
$ cd ~/Sources/roms
$ dd if=./coreboot.rom of=./coreboot8.rom bs=1M count=8
$ dd if=./coreboot.rom of=./coreboot4.rom bs=1M skip=8
$ scp -r ./coreboot8.rom ./coreboot4.rom pi@raspberrypi:~/rom/
- Assuming that the SOIC-8 test clip was left on the 4MB flash chip (U66), flash that chip first.
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L3205D/MX25L3208D" -w ./coreboot4.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L3205D/MX25L3208D" (4096 kB, SPI) on linux_spi.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.
- Remove the test clip and relocate to the 8MB flash chip (U46).
pi@raspberrypi:~/rom $ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -c "MX25L6406E/MX25L6408E" -w ./coreboot8.bin
flashrom v1.2 on Linux 5.10.63+ (armv6l)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on linux_spi.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.
- Remove the test clip and reassemble the laptop. You now have a corebooted laptop!