engineer's notebook ÷ internet homepage
est. somewhere on the old web

← notes / 2026.08.18

build log: thinkpad x220

thinkpadlibrebootcorebootflashromlinuxhardwareproject-log

no github repo for this one, it lives in photos and a parts list.

the project was to take my x220, flash libreboot onto it, and rebuild the hardware while i was in there. the firmware half is done as of 2026.08.18. libreboot 25.06 is on the machine, it went through on the first attempt, and the kali install that was already there booted like nothing happened. what follows starts from before i had any of the parts.

the microcenter run

went to microcenter and picked up the start of the flashing rig.

  • raspberry pi zero 2 w
  • microsd card
  • jumper cables

i still need to order a pomona clip, a ram stick, a new display, the usb-c charging port upgrade, and a few other odds and ends before the build actually starts.

the plan

get the libreboot rom onto the raspberry pi. i opted for running the pi over ssh instead of a debian system or some other linux distro alternative, mostly because it was easier and honestly i wanted a raspberry pi anyway.

once the physical parts arrive i can disassemble it, clip onto the flash chip, and begin flashing.

the honest part

a bit worried about this one because i don’t want it to go wrong. external flashing is the kind of process where one loose jumper turns a laptop into a paperweight. going slow, reading everything twice, flashing once.

it worked (2026.08.18)

libreboot 25.06 is on the machine and it booted first try. kali came back up without me touching anything, because libreboot’s grub payload chainloaded it directly. the whole session ran about seven hours end to end, and most of that was waiting.

the machine is an x220 i bought refurbished for $160, an i5-2520m with 8gb and a 256gb ssd. it already had the last bios lenovo ever shipped for it on there, 8det76ww from 2018, which meant no ec update was needed first. that mattered, because libreboot can’t update the ec after the fact. the flash chip is a single winbond w25q64, 8mb, soic-8, sitting bottom left near the expresscard cage under a bit of black anti-static film and silkscreened SPI1.

the pi couldn’t actually do the whole job

first real surprise. i’d assumed the pi would be the entire setup, but preparing the rom has to happen on an x86_64 machine. libreboot’s build kit wants x86-specific packages like libx86 and x86 cross compilers that debian doesn’t ship for arm, so ./mk dependencies debian just fails on the pi.

so the debian box i said i was skipping in favor of the pi turned out to be mandatory anyway. the pi’s job is strictly to be the spi programmer.

vendor injection isn’t optional on sandy bridge

before flashing, intel me firmware has to get injected into the rom. libreboot ships the release roms with DO_NOT_FLASH in the filename and a byte of padding, and the inject step pulls down the me firmware, runs me_cleaner on it, and strips both of those markers on success. a nice built-in way to know it actually worked.

me_cleaner pulled KERNEL, POLICY, HOSTCOMM, RSA, CLS, TDT and FTCS out, leaving only BUP, then truncated the me region down to its 84992 byte minimum. on sandy bridge this step is mandatory rather than a nice to have. skip it and the board doesn’t boot at all.

wire length matters more than i thought

first detection attempt came back with this:

Found Generic flash chip "unknown SPI chip (RDID)" (0 kB, SPI)

my first instinct was that i’d clipped the chip on backwards. it wasn’t that. the chip was responding, the id just wasn’t parsing, which is a signal problem and not an orientation problem. my jumpers are 30cm, and at spispeed=128 that’s enough capacitance and crosstalk to corrupt things.

dropping to spispeed=32 fixed it completely:

Found Winbond flash chip "W25Q64BV/W25Q64CV/W25Q64FV" (8192 kB, SPI)

the lesson i’m keeping is that partial detection isn’t the same thing as wrong orientation, and that with long wires you slow the clock down instead of fighting the connection.

the backup is the entire safety net

three full reads of the stock firmware before writing anything, run inside tmux so an ssh drop couldn’t kill one halfway through. at spispeed=32 each read took about an hour.

all three hashed identically. i copied them over to the debian server and verified them again there, so there were two physically separate verified copies before a single byte got written. that’s the thing that turns this from “i might kill a laptop” into “worst case i re-clip and restore”.

the write

sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=32 \
  -c "W25Q64BV/W25Q64CV/W25Q64FV" -w libreboot_x220.rom

about three hours in three phases, roughly an hour each to read the old contents, erase and write, and verify. it ended on VERIFIED. which is a very good word to see after that long.

then power down the pi before unclipping, since you never disconnect from a live rail, film back on, reassemble, battery in.

it booted. dmidecode reports smbios 3.0.0 now instead of the stock 2.6, which is coreboot’s, so that’s independent confirmation the firmware actually changed rather than me just hoping it did.

the ram is a different story

the plan was 16gb in dual channel, so i bought an a-tech 8gb ddr3l stick to sit alongside the samsung 8gb that came with the machine. the stick is dead on arrival.

i worked that out by elimination instead of guessing:

testresult
a-tech and samsung togetheronly 8gb detected, dmidecode shows one module and no second entry at all
a-tech alonedoesn’t post
samsung alone, slot 1boots fine
samsung alone, slot 2boots fine

both slots are good and the samsung is good, which isolates it to the a-tech. it’s going back under warranty and the replacement goes in when it arrives.

one thing worth remembering for the retry is that coreboot does its own sandy bridge memory init rather than using lenovo’s. 2x8gb on an x220 under coreboot is normally fine, but if a known good replacement also fails in a pair, then raminit compatibility becomes the suspect instead of the stick.

what’s left

the firmware project is closed. what’s left is a short list of optional hardware.

  • ram to 16gb. install the warranty replacement when it shows up, which also gets the machine into dual channel, which it isn’t running right now.
  • wifi card swap. libreboot removing the whitelist is what makes this possible at all, since the stock firmware would refuse to boot with a card lenovo hadn’t blessed. the appeal is wifi 5 and bluetooth, and it’s the cheapest thing on this list by a good margin.
  • fhd ips display mod, budget permitting. worth knowing that 60hz is a hard ceiling on this platform, the hd 3000 display engine can’t go past it no matter what panel goes in, so there’s no high refresh or oled version of this mod.
  • usb-c charging mod, also budget permitting. a 20v pd trigger feeding the barrel jack. the x220’s ec is permissive enough that this is cleaner here than it would be on an x230.

arch is deferred. it was the original plan and i’ve pushed it back. kali is already installed, configured, and working well, and this isn’t a machine i use to a crazy degree, so tearing down a working setup i’ve put real config effort into isn’t worth the disruption right now. arch stays on the table purely as something to explore later.

once the ram is in and the wifi card, display, and usb-c are either done or passed on, this project and this machine are closed.


← back to all notes