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

  1. Download and flash the latest Raspberry Pi OS to the 8GB SD Card. The lite version is sufficient.

  2. Download me_cleaner

$ mkdir -p ~/Sources
$ cd ~/Sources
$ git clone https://github.com/corna/me_cleaner
  1. 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
  1. 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/
  1. Compile the ifdtool for extraction of the binary blobs later on.
$ cd ~/Sources/coreboot/util/ifdtool
$ make
$ sudo make install

Raspberry Pi

  1. On your Raspberry Pi, enable the following services from raspi-config, enable the SPI devices and remote GPIO.
SSH
SPI
I2C
Remote GPIO
  1. Enable SPI and reboot
$ sudo modprobe spi_bcm2835
$ sudo modprobe spidev
$ sudo reboot
  1. 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

  1. 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.

  2. 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”.

  1. 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 $ 
  1. 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 $
  1. 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 $
  1. 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

  1. 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/
  1. 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
  1. 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!
  1. 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

  1. Compiling on the Linux PC is preferable to compiling on the RPi.

  2. 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
  1. 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

  1. 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/
  1. 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.
  1. 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.
  1. Remove the test clip and reassemble the laptop. You now have a corebooted laptop!