After successfully corebooting my ThinkPad X220 a while back, I decided to try the same with my ThinkPad T480. Unlike older ThinkPads, the T480 ships with Intel Boot Guard enabled, which means you can’t simply dump and flash the firmware as you could on earlier models.
The deguard utility from coreboot exploits a vulnerability in the Intel Management Engine to bypass Boot Guard. For the payload, I chose EDK2, giving me a full UEFI implementation.
I mostly followed the official coreboot documentation for the Skylake/Kabylake ThinkPads.
The Setup
- ThinkPad T480 (i5-8250U, 16GB RAM)
- Raspberry Pi for firmware extraction and flashing
- SOIC-8 clip for attaching to the BIOS chip
- 6 F/F jumper wires for attaching the SOIC clip to the Pi
- Another Computer for compiling coreboot
- A Phillips screwdriver and a spudger
Update Firmware
Before flashing coreboot, you need to get the stock firmware to the right versions. The coreboot docs require the EC firmware to be at version 1.22 (N24HT37W), and any BIOS version from 1.39 to 1.54 works.
Update the Thunderbolt Firmware
The ThinkPad T480 originally shipped with a buggy Thunderbolt 3 controller firmware that repeatedly wrote diagnostic data to its own SPI flash. Over time, this excessive logging could corrupt the controller and permanently break Thunderbolt functionality. I updated mine as soon as I got the machine.
If you haven’t done this yet, grab the update from Lenovo’s support page and apply it while you’re still on stock firmware.
Update the BIOS and EC
If your EC isn’t at version 1.22 yet, you’ll need to update that too. Download the BIOS update ISO from Lenovo’s support page and extract the El Torito boot image to a USB stick:
curl -fL -o geteltorito https://raw.githubusercontent.com/rainer042/geteltorito/refs/heads/main/geteltorito.pl
chmod +x geteltorito
./geteltorito -o t480_bios_update.img /path/to/downloaded.iso
sudo dd if=t480_bios_update.img of=/dev/sdX bs=4M conv=fsync status=progress
Before booting the updater, go into your BIOS setup and:
- Enable “Flash BIOS Updating by End Users”
- Disable “Secure Rollback Prevention”
- Enable Legacy/CSM boot (the updater boots in BIOS mode)
Boot from the USB (F12 at startup), select option 2, and follow the instructions.
Disassembly
Taking the T480 apart is straightforward:
- Disconnect AC power and remove the external battery.
- Remove the captive Phillips screws on the bottom cover, as shown in the picture below.
- Disconnect the internal battery, as well as the CMOS battery.
- Pry off the back cover, making sure to lift up the clips near the battery compartment.

The captive Phillips screws on the bottom of the T480
Dumping the Stock BIOS
The T480 has a single 16MB SOIC-8 flash chip (mine was a Winbond W25Q128.V), located roughly in the center of the board near the RAM.

BIOS chip location
Wiring the Raspberry Pi
I used the SPI pins on the Pi’s GPIO header. Here are the pinouts:
BIOS Flash Chip Pinout
______
CS 1 --|o |-- 8 VCC (3.3 V)
MISO 2 --| |-- 7 No Connection
No Connection 3 --| |-- 6 CLK
GND 4 --|______|-- 5 MOSI
Raspberry Pi GPIO Pinout
CS GND
2 | | 40
+-----------------------v-----v-----------+
| x x x x x x x x x x x x x x x x x x x x |
| x x x x x x x x x x x x x x x x x x x x |
+-----------------^-^-^-^-----------------+
1 | | | | 39
VCC | | CLK
MOSI/ \MISO
Wiring Table
| Chip Pin | Function | RPi GPIO Pin |
|---|---|---|
| 1 | CS | GPIO 8 (CE0) - Pin 24 |
| 2 | MISO | GPIO 9 (MISO) - Pin 21 |
| 3 | WP | No connection |
| 4 | GND | GND - Pin 25 |
| 5 | MOSI | GPIO 10 (MOSI) - Pin 19 |
| 6 | CLK | GPIO 11 (SCLK) - Pin 23 |
| 7 | HOLD | No connection |
| 8 | VCC | 3.3V - Pin 17 |

SOIC-8 clip attached to the flash chip

Chip wired to the Raspberry Pi
Make sure SPI is enabled on the Pi (sudo raspi-config -> Interface Options -> SPI -> Enable).
Installing flashrom
Install the required build dependencies on the Pi first:
sudo apt install git libpci-dev libusb-1.0 libusb-dev
Clone the flashrom repo, compile and install the binary:
git clone https://github.com/flashrom/flashrom.git
cd flashrom
make
sudo make install
Reading the Flash
I took three dumps and verified they all matched:
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r t480_dump1.bin
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r t480_dump2.bin
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r t480_dump3.bin
sha256sum t480_dump*.bin
Building Coreboot
The rest of the process happened on my desktop computer.
Prerequisites
Install the required packages. You’ll need gcc-ada (GNAT) for libgfxinit support (Intel graphics init), nasm for EDK2, and imagemagick:
sudo pacman -S gcc-ada nasm imagemagick base-devel git python
Clone the Repos
mkdir ~/t480 && cd ~/t480
git clone https://review.coreboot.org/coreboot.git
cd coreboot
git submodule update --init --checkout
cd ..
git clone https://review.coreboot.org/deguard.git
Build the Coreboot Toolchain
cd ~/t480/coreboot
make crossgcc-i386 CPUS=$(nproc)
This takes a while.
Extract Blobs from the Stock Dump
cd util/ifdtool
make
./ifdtool -x -p sklkbl /path/to/t480_dump1.bin
mkdir -p ../../binaries
mv flashregion_0_flashdescriptor.bin ../../binaries/ifd.bin
mv flashregion_3_gbe.bin ../../binaries/gbe.bin
cd ../..
You’ll probably see some “Error while writing: Bad address” messages for unused regions (10–15) - these are harmless.
Prepare the ME with Deguard
The T480 has Intel Boot Guard, which needs to be bypassed using the deguard utility. This requires a “donor” ME image from a Dell system:
cd ~/t480
# Download the Dell firmware updater
wget "https://web.archive.org/web/20241110222323/https://dl.dell.com/FOLDER04573471M/1/Inspiron_5468_1.3.0.exe"
# Extract it
git clone https://github.com/vuquangtrong/Dell-PFS-BIOS-Assembler.git
python Dell-PFS-BIOS-Assembler/Dell_PFS_Extract.py Inspiron_5468_1.3.0.exe
# Find and copy the ME binary (should be ~2031616 bytes)
find . -size 2031616c
# Output: ./Inspiron_5468_1.3.0.exe_extracted/1 -- 3 Intel Management Engine (Non-VPro) Update v11.6.0.1126.bin
cp "./Inspiron_5468_1.3.0.exe_extracted/1 -- 3 Intel Management Engine (Non-VPro) Update v11.6.0.1126.bin" \
coreboot/binaries/me_donor.bin
# Verify the hash
sha256sum coreboot/binaries/me_donor.bin
# Expected: 912271bb3ff2cf0e2e27ccfb94337baaca027e6c90b4245f9807a592c8a652e1
Now run deguard:
cd ~/t480/deguard
./finalimage.py \
--delta data/delta/thinkpad_t480 \
--version 11.6.0.1126 \
--pch LP \
--sku 2M \
--fake-fpfs data/fpfs/zero \
--input ../coreboot/binaries/me_donor.bin \
--output ../coreboot/binaries/me_deguarded.bin
Set the HAP Bit on the IFD
The HAP bit is a special flag inside the Intel firmware configuration that tells the Intel Management Engine to disable most of its functionality after early initialization. To set this in the IFD:
cd ~/t480/coreboot
util/ifdtool/ifdtool -p sklkbl -M 1 binaries/ifd.bin
mv binaries/ifd.bin binaries/ifd.bin.orig
mv binaries/ifd.bin.new binaries/ifd.bin
Configure and Build
Create configs/defconfig:
CONFIG_VENDOR_LENOVO=y
CONFIG_BOARD_LENOVO_T480=y
CONFIG_IFD_BIN_PATH="binaries/ifd.bin"
CONFIG_ME_BIN_PATH="binaries/me_deguarded.bin"
CONFIG_GBE_BIN_PATH="binaries/gbe.bin"
CONFIG_HAVE_IFD_BIN=y
CONFIG_HAVE_ME_BIN=y
CONFIG_HAVE_GBE_BIN=y
CONFIG_PAYLOAD_EDK2=y
Then build:
make defconfig
make -j$(nproc)
A Note on GCC Compatibility
If you’re on a distro with GCC 14+, you may hit -Werror=discarded-qualifiers errors in both vboot’s cbfstool.c and EDK2’s BaseTools. I fixed this with:
# Fix vboot cbfstool
find . -path "*/host/lib/cbfstool.c" -exec sed -i \
's/char \*end = strchr(start/const char *end = strchr(start/' {} \;
# Fix EDK2 BaseTools (nuclear option - disables -Werror)
sed -i 's/-Werror/-Wno-error/' \
payloads/external/edk2/workspace/mrchromebox/BaseTools/Source/C/Makefiles/header.makefile
After these patches, the build completed successfully.
Inject the Original MAC Address
Since I extracted the original GBE from my stock dump, I injected it back in to preserve my real MAC address:
cd util/ifdtool && make && cd ../..
util/ifdtool/ifdtool -p sklkbl -i GBE:binaries/gbe.bin build/coreboot.rom
mv build/coreboot.rom build/coreboot.rom.old
mv build/coreboot.rom.new build/coreboot.rom
Flashing
Copy the ROM to the Raspberry Pi and flash:
scp build/coreboot.rom pi@raspberrypi:~/t480/
Flash the image, making sure the clip still has a good connection:
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -w coreboot.rom
Expected Output:
Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on linux_spi.
Reading old flash chip contents... done.
Erase/write done from 0 to ffffff
Verifying flash... VERIFIED.
The Result
Reassembled the laptop, popped the battery in, hit the power button and… SUCCESS!!!

Coreboot with EDK2 UEFI payload, running on my ThinkPad T480
Post-Flash Notes
- Internal microphone: Does not work under coreboot - this is a known issue.
- Thunderbolt & USB-C: As of March 2025, Thunderbolt data transfer is not supported upstream by coreboot. Charging, USB-C data transfer and video output through the Thunderbolt port work fine tough.
- Fn keys: Some Fn+F1–F12 combos aren’t handled correctly yet.
- thinkpad_acpi: Add
options thinkpad_acpi force_load=1to a file in/etc/modprobe.d/for fan control and thermal monitoring to work reliably. - Future updates: Once coreboot is installed, you can flash internally without the clip:
sudo flashrom -p internal -w coreboot.rom --ifd -i bios -N
Conclusion
Thats it! Coming from the X220, the biggest difference is the deguard step required to bypass Boot Guard - everything else is similar.
Massive thanks to Máté Kukri for the coreboot port and the deguard utility, and to the coreboot community for the excellent documentation.