Links

Overview

I did all this over at my grandparents’ place during Thanksgiving…perhaps flaunting my anti-sociability instead of trying to do my best to interact…but I did most of it in the living room! (Except when I went upstairs for physical access to the pi after it finished the make process…) And I’m currently writing this while playing a card game with the folks who are staying the night, and I almost didn’t. Progress, not perfection.

I’ve got two Thinkpad X220s - one that I’ve had for several years and tried to flash before, one of my friend’s that I’ve had on my backlog to flash for about a year now.

From what I remember, the friend’s is a necessary step. We got all the way through installing Arch Linux and it wouldn’t boot, the BIOS was locked down. We bought it used. (Funnily enough, as soon as I got Coreboot working on it, it booted right into the install from a year ago!)

Mine, on the other hand, was in a questionable state. I had tried and failed back in 2023 (and previously, with another one that I managed to brick by losing the original firmware…long story) to flash it. I technically successfully flashed it, but not to my requirements. Let me outline those, as this is why this has been such a journey.

  1. Support boot from full-disk encryption with luks and lvm.
  2. Support boot from full-disk encryption with luks and lvm - with weird lvm names. (This is entirely my fault for not following convention ~6 years ago, and makes things especially interesting.)
  3. Have a custom bootsplash image - not as priority.

As far as I can tell, this means I am locked in to grub for the bootloader, or at least SeaBIOS into grub. I’ll get to that, but it’s been the most difficult part…

As for my friend’s, I didn’t need to worry about full disk encryption, and didn’t have any special requirements, so I just flashed SeaBIOS and went on my merry way. I’ll probably go back to this one and flash Libreboot, because why not, and it looks nicer.

I started with Coreboot. As we shall discover, things have changed since I tried this a while ago (actually it might have been the case around that time, but I was unaware) - Libreboot makes prebuilt binaries a whole lot easier.

Quick reference

Some helpful commands that saved my ass from both carpal tunnel and several hours of sleep last night.

# Set an alias for the flashroom command so you don't have to type it out a million times.
alias fr='sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=8192'
 
# Set chip name to a variable, again to reduce typing
CHIP="W25Q64.V"
 
# When combined:
fr -c "$CHIP" -r output.bin
# As opposed to...
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=8192 -c "W25Q64.V" -r output.bin

A “Coreboot tool dictionary” for my future reference - just how I understand the tools. I am probably inaccurate or plain wrong as to what exactly they do.

flashrom - tool installed via apt, reads and writes from the spi device connected to the raspberry pi - use to pull the stock ROM off the chip and to actually flash coreboot

# detect chip
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=8192
# read from chip
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=8192 -c "W25Q64.V" -r output.bin
# write to chip
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=8192 -c "W25Q64.V" -w input.rom

ifdtool - tool to extract a ROM file into separate files corresponding to its regions (descriptor, bios, intel me, and gbe) - use for extracting these pieces to pass to the Coreboot compiler

# extract a ROM into its given parts
./ifdtool -x output.rom

cbfstool - tool to view, extract, and edit individual files in a compiled ROM (use for extracting/replacing grub.cfg, bootsplash.jpg, etc)

# print contents of a rom file
./cbfstool path/to/rom print
 
# remove a file from the rom by name
./cbfstool path/to/rom remove -n bootsplash.jpg
 
# add a file to the rom (-t flag is type)
./cbfstool path/to/rom add -n bootsplash.jpg -f path/to/bootsplash.jpg -t bootsplash

Process

Friend’s

For this one, I basically followed the steps in the guide.

I did get a funny story out of it, though. This pi was my raspberry pi 4B, which I just recently pulled from my home setup. This bad boy was running as my pi-hole DNS server, home VPN, 3-years-prior-coreboot-flasher, as well as a million other things I had forgotten about. I had about 20 at-boot services I needed to stop when I finally got into it.

So anyway, I had just yeeted it off the shelf and grabbed a usb-c power cable. As an afterthought I grabbed my mini-HDMI cable - just in case. And if I hadn’t grabbed that cable, I wouldn’t have been able to do any of this project.

I had left it at a static IP of 10.0.0.2 - the IP of my DNS server back home. I didn’t think to change it. Now, you see, the issue is that my grandparents’ network uses the usual 192.168.1.0/24 network.

Upon figuring this out (mind you, after writing a nested for loop to ssh into all available IP addresses from the results of an nmap ping scan, using multiple ports, as I had forgotten my ssh port too), I was patting myself on the back for thinking to bring my mini-HDMI. I’m doing all of this upstairs in my granddad’s old office, and there’s a monitor sitting right there. Perfect. I turn it around - ancient monitor (not a CRT at least), but it’s VGA-only.

So, I go bother my brother who has just turned the lights out to go to bed - I plug the raspberry pi into the back of the TV in his room, grab a keyboard from my granddad’s office, and get to work - beautiful ASCII text at 1080p on a 50” screen.

Turns out getting into my raspberry pi was the hardest part of flashing my friend’s laptop.

One thing of note, actually related to the installation process, this is the first time I copied everything to another computer for the compilation. I installed all the build prerequisites on my Debian WSL, copied everything over, and compiled. And boy howdy, did it save me hours off my life. My computer (pretty powerful laptop I use for work) was able to compile SeaBIOS Coreboot in less than 5 minutes, and I had been used to it taking at least an hour on my pi previously.

Mine

Now we get to the fun part.

Finding the stock ROM

I had done a similar thing with this laptop as I had done with the one I ended up bricking - that is, I had flashed it mostly unsuccessfully, continued flashing and re-flashing, and then proceeded to abandon the project right where it was, as opposed to trying to do any sort of post-mortem or cleanup. Thus, I had many files sitting around on my raspberry pi, such as flash01.bin, intel_me_stripped.bin, coreboot.rom, etc etc. (After I got it flashed, I found even more on an old Debian mSATA I had left in the coreboot, when I was testing further with internal flashing…)

Luckily, the find command - which I’ve actually taken the effort to learn at this point in my Linux journey, when I hadn’t really back then - saved my ass.

find ~/ -size 8192k

Then it was a matter of copying all the results to a directory, and using md5sum to see how many I actually had. I had copied about 10 into the directory, but I had only 3 unique files. From there, it was a matter of educated guessing to figure out which one was the stock ROM - and I was crossing my fingers that one of them actually was the stock ROM. Turns out, the first one I flashed did the trick. Lucky that I still had it.

The Coreboot shuffle

So that part was out of the way. I had a working, stock ROM to pull the descriptor, me, and gbe from.

At this point I followed the guide, up until I got to the point of make nconfig. I had to change the payload to grub. For the first trial I left out two critical items: a list of extra modules to load, and a custom grub.cfg file. It built just fine and then flashed correctly, but I was left with a stark grub command prompt. Not much I could do with that.

I wasn’t unfamiliar with this process, stuff kept floating to the surface of my brain as I remembered having that issue in the past.

To abridge the majority of the day into roughly a paragraph, I would add modules, edit the grub.cfg, re-make, reflash, boot the machine up, and get a new error message as to why it couldn’t load. At a certain point, I just said screw it and added almost every single grub submodule (another link) - which added too many grub modules for the amount of space in the ROM to handle, and the make failed. Then it became removing the grub modules I thought were unnecessary, in waves, until the make succeeded. Then copy to my pi, flash, and boot.

The eventual list of the grub submodules I added, and seemed to (somewhat) work for at least booting into an encrypted drive, and were able to fit into the 8192k ROM:

cryptodisk nativedisk ehci ohci usb usbserial_pl2303 usbserial_ftdi usbserial_usbdebug jpeg usbms lvm luks all_video hashsum regexp gcry_sha256 gcry_sha512 gcry_rsa gcry_md5 gcry_rijndael gcry_des gcry_sha1

And the eventual contents of my grub.cfg (almost entirely lifted from the Libreboot project):

set prefix=(memdisk)/boot/grub

insmod nativedisk
insmod cryptodisk
insmod luks
insmod lvm
insmod ehci
insmod ohci
insmod uhci
insmod usb
insmod usbms
insmod usbserial_pl2303
insmod usbserial_ftdi
insmod usbserial_usbdebug
insmod gcry_sha256
insmod gcry_sha512
insmod gcry_md5
insmod gcry_rsa
insmod gcry_rijndael
insmod gcry_des
insmod gcry_sha1
insmod hashsum
insmod regexp
insmod all_video
insmod jpeg

# Set bootsplash image (and font)
background_image (cbfsdisk)/background.jpg
# loadfont (cbfsdisk)/dejavusansmono.pf2

# Serial and keyboard configuration, very important.
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
terminal_input --append  serial
terminal_output --append serial
terminal_input --append at_keyboard
terminal_output --append cbmemc

gfxpayload=keep
terminal_output --append gfxterm

# Default to first option, automatically boot after 2 seconds
set default="0"
set timeout=2

# This is useful when using 'cat' on long files on GRUB terminal
set pager=1

keymap usqwerty

# ...
# The remainder is unchanged from the Libreboot grub.cfg

Eventually I managed to get to the point where I could boot an encrypted drive, albeit by typing in the commands manually. (I never did get the bootsplash working.) This has been a plague upon my existence ever since I encrypted these drives and then went on to flash Coreboot/Libreboot. I named the encrypted LVMs in a non-standard way (viz. not matrix) and this means that I have never figured out how to automatically boot after entering the decryption password, save by hard coding the name of the LVM into the grub.cfg.

My plan, when I get back home, is to just copy the contents of the drives onto my TrueNAS, then nuke the drives and start over. But part (eh, most) of the reason it’s taken me this long to get back around to Coreboot is I’ve been absolutely dreading returning to this problem.

My forehead hurts and the wall is looking bruised

That aside, I had plenty of time to think during the 20+ twiddle-your-thumbs-and-pray make processes, and it occurred to me that Libreboot should support the X220 board at this point. (I believe that this was part of some recent controversy surrounding a change regarding non-free software blobs included in their distributions - hence GNU Boot then Canoeboot - I know for a fact the X220 is a hack, due to the intense familiarity I have with extracting the stock rom, stripping the me firmware, and making sure those 3 extracted blobs are just so when compiling Coreboot. So I knew that they had to include those in some capacity, unless something else had massively changed. I could really care less about the controversy, all CPUs are running proprietary microcode anyway, and having a precompiled BIOS ROM is just very convenient, so thank you to the Libreboot devs.) But anyway, I remembered installing Libreboot at one point, and it was basically running a couple scripts on pre-built ROMs as opposed to the intense, sweaty process that is the Coreboot make, and I remember Libreboot having some sensible defaults. I in fact own a Librebooted X60 - very dusty, but I’m nonetheless a proud owner. I’m also very familiar with how to replace the grub.cfg and bootsplash. And Libreboot comes with the modules necessary for booting an encrypted disk, as well as loading a bootsplash image.

So, naturally, I went ahead and installed Libreboot. I can’t put my finger on exactly what’s up with their documentation, but it’s cryptic as hell in some capacity. When you actually dig down and read a sentence, the sentence makes sense. But I can’t get the big picture of what exactly I’m doing with any passage larger than a sentence. I eventually figured it out, but it was an odd experience. I’ll do my best to summarize below.

  1. Clone the Libreboot build system and switch to that directory
  2. Install dependencies with sudo ./mk dependencies debian
  3. Download the appropriate build of libreboot
    • stable (most recent) roms libreboot-[RELEASE]_x220_8mb.tar.xz (+ its .sha512 and .sig)
    • Alternatively, download the most recent release under the testing directory instead of stable
  4. Follow the instructions under this header

So I grabbed the ROM, added the appropriate vendor firmware according to the steps above (note that I did have to edit a single ROM file manually instead of adding all directly to the tarball as is suggested in the guide, but at this point in the process I couldn’t be bothered to figure out why it was having issues), and it flashed successfully. I’m still having issues decrypting and booting into my encrypted drives, but now I can boot into the aforementioned unencrypted Debian mSATA and do all my flashing internally. There also might be some helpful abandoned files there, I haven’t investigated it just yet.

Final thoughts

The main thing I’ve gotten out of this…experience…is that I feel a whole lot better about my decision to document. I mean I already did - but this one has been especially illustrative in terms of how I used to be. Most of the time spent on this project (outside of the usual fuckups that can be attributed to my general lack of planning) was figuring out where I had left off / retracing my steps, and then realizing that I had been through all this before and simply forgotten about it.

Now that this is here - with the relevant links, defined requirements, reasoning, processes, known issues, tips and tricks, etc etc - I can maybe start getting some sleep.

And I do have things left on my agenda (hence the Part 1 in the title):

Cleanup:

  • Backup encrypted drives, nuke them and start over.
  • Make organized backups of stock ROM, current Coreboot ROM, build config, edited bootsplash, etc…

Further configuration:

  • Replace the bootsplash image.
  • Replace the grub.cfg as necessary.
  • Document the process for both of those.

EOF