Coreboot on the Lenovo Thinkpad X220

2016-12-30 11:00
I have finally come around to install Coreboot on my X220 laptop. It is an X220 with a Core i5-2520M and 16 GB of DDR3-1600 RAM.

Coreboot is an open source replacement for the BIOS/UEFI firmware of a variety of laptops and mainboards. Coreboot needs to be combined with a payload component, since Coreboot itself doesn't do a whole lot besides hardware initialization. The payload I am using here is SeaBIOS, which implements the features of a PC BIOS.

SeaBIOS payload

It allows you to boot most PC operating systems, including those that rely on the classic PC BIOS features. For UEFI support there is the TianoCore payload. It is also possible to use the GRUB bootloader as a payload or embed a Linux kernel as a payload (if the flash chip is large enough).

Why?

So what's the point of replacing the vendor firmware? There are several reasons why one might want to do that, including
  • Customizability due to the large number of payloads
  • Faster boot times
  • Privacy/trust concerns about the closed source vendor firmware
  • The urge to tinker with/destroy stuff

How?

On most machines, Coreboot cannot be flashed from a running system, because the flash chip is often locked by the vendor firmware. To be able to flash the Coreboot firmware anyway, an external SPI flasher can be used. I've used a Raspberry Pi 3, but several other single board computers can be used if they have an SPI interface. There are also flash tools dedicated to the task. The process of flashing is described in the Coreboot wiki, so I am not going into much detail here.

The recommended method of attaching your flasher to the SPI BIOS flash chip on the mainboard is through a clip that you can hook onto the chip. Pomona builds those clips. There are also cheaper chinese versions available.

Since I did not have either of those, I decided to solder wires directly to the SPI flash chip.

X220 SPI flash chip with wires attached

In the picture you can see the X220 with wires connected to the 8 pin SPI flash chip. It looks pretty messy, but it does the job.

As you can see in the picture, on the X220 there is an unpopulated place for a second flash chip. I was hoping the those two chips would be connected mostly in parallel, so I could solder onto the pads of the unpopulated chip, but this turned out not to be the case. Except for the power and ground connections.

I haven't been using an external power supply and instead used the 3.3 V supplied by the Raspberry Pi 3 and it worked just fine with my X220.

With all that in place, with the flashrom tool I was able to extract the original UEFI firmware from the chip and then extract the management engine, embedded controller and gigabit ethernet controller firmware blobs from the image, as explained on the Coreboot wiki. I have also extracted the VGA BIOS ROM from the original firmware.

Those components are necessary to build a working Coreboot image.

From this point on building a Coreboot image and flashing it to the X220 was pretty straigt forward, since it is explained rather well on the Wiki.

The not so obvious stuff

I have pulled Coreboot from the master branch of their git repository and the commit ID of the version I used is d0a648e18a7162f7361a13296beb0c1293acb16e (Tue Nov 29 23:20:07 2016 -0600). Things might be (slightly) different when using another version.

Although there is some documentation on the whole install and a few people wrote about installing it on their machines, I couldn't easily find information about a couple of things which are rather important to me. So in case anyone is wondering about the same things, here is what I figured out.

Things I could not easily find information on include the ability to configure battery thresholds and getting suspend-to-ram to work. Both things work fine with the Vendor firmware and I consider them rather important for a laptop.

Suspend to RAM kind of works with Coreboot, but at least in Linux pm-suspend needs some quirks to work correctly. Without the quirks, the machine would go to sleep, but when waking up, the screen would not come back on. Running pm-suspend with
pm-suspend --quirk-reset-brightness --quirk-vbe-post --quirk-vbestate-restore --quirk-vbemode-restore
lets the machine wake up as expected. While in suspended state, the power button LED does not flash like it does with the vendor UEFI firmware, but the moon-shaped LED on the outside is lit, so you can still tell if it is in suspend mode.

Changing the battery thresholds can hugely increase the battery's lifespan. I usually configure the battery charging such that it gets charged to only about 80 % of the battery's capacity and starts charging again only if it is discharged below around 50 %. Whether or not that is accepable for you depends on how you use the machine, but it works fine for me and helps me greatly reduce the number of charging cycles.

Configuring this with the Vendor firmware under Linux is fairly well documented, but with Coreboot it doesn't work the same way. With the Vendor firmware you would always talk to the management engine (ME) which would then tell the embedded controller (EC) to set the charging thresholds. Coreboot tries to avoid using the ME, so you have to talk to the EC directly. Fortunately Coreboot comes with a couple of utilities, one of which is ectool. There doesn't seem to be much information about the tool, but what it basically does is set configuration data in address space of the EC. To set the battery charging thresholds to 53 % and 80 % for the lower and upper thresholds, one would execute ectool twice like this:
# Battery start threshold with coreboot: 0x35 = 53 %
./ectool -w 0xb0 -z 0x35
# Stop threshold 0x50 = 80%
./ectool -w 0xb1 -z 0x50


Secondary payloads and configuring system settings

Coreboot allows you to include more than one payload, but it wasn't obvious to me from the documentation how secondary Coreboot payloads are launched and if it is possible to configure things like enabling devices through Coreboot. If you want to try all this yourself, you can build Coreboot for a QEMU target. That way you don't have to risk bricking an actual machine.

As it turns out, when using SeaBIOS as the primary payload, launching secondary payloads is trivial. They appear in SeaBIOS' boot menu and can be launched from there. Changing the configuration of system setting is also possible to some extent and with the help of the nvramcui payload it is possible to change those things in a similar way as your typical BIOS setup would allow you to.

One thing that was especially of interest to me is the ability to disable the touchpad, since I don't like using it and very much prefer the Thinkpad's track point. Fortunately it is possible to disable it with Coreboot and nvramcui makes it pretty easy to change.

There are a couple of other payloads that are included with Coreboot and can be enabled through Coreboot's configuration at build time. Besides the already mentioned nvramcui, there is memtest86 which is quite neat to have built-in.

Memtest86 payload

The coreinfo payload prints some information about the machine on the screen.

Coreinfo payload

Then there is tint, a simple text based Tetris clone.

Privacy considerations and me_cleaner

When considering the use of Coreboot for privacy reasons on newer Intel machines, there is always this big elephant in the room, called management engine (ME). The ME consists of an additional processor that runs its own code in parallel to your operating system, with access to pretty much every system component. Nobody seems to know exactly what the ME is capable of. It certainly is capable of using the ethernet NIC, with its own MAC address.

Recently a couple of people made great progress in disabling parts of Intel's management engine found in all recent Intel CPUs. As it turns out it is possible to disable large parts of the ME without the machine being forcefully shut down after 30 minutes, which was previously believed to be difficult if not impossible. The me_cleaner tool makes it very easy to clean the extracted ME image from most of the stuff.

This is supposed to work with both Coreboot and vendor firmwares. So I thought I give it a shot. Unfortunately, at least on my machine, it didn't work reliably. While the modified ME image allowed me to boot the machine and use it for more than 30 minutes, it caused all kinds of weird behavior during operation. Programs that make use of the GPU (like games) would frequently crash, which they didn't when using the unmodified ME. The Linux kernel (version 4.8.11 at the time) even deadlocked in some disk I/O operation, which prevented multiple processes from terminating properly (even kill -9 didn't work). That eventually prevented the whole machine from properly shutting down. This also has never happened before. Going back to an unmodified ME image fixed all those issues.

Conclusion

So was it worth the trouble? I'd say, for me it was. The system works reliably with Coreboot and it boots up pretty quickly. I got all the important features working eventually. And of course, I always like to tinker with stuff. So what's not to like? ;) The only thing that didn't work as I had hoped was the cleaned ME. It would have been great to get rid of that thing (or at least part of it), but that really isn't Coreboot's fault.
 
KeyJ (web) says:
2016-12-30 14:33:25
Is there any specific reason why you chose SeaBIOS over GRUB as the primary payload? Did you want to boot Windows?
wej (web) says:
2016-12-30 16:13:33
Hi KeyJ, I don't plan on booting Windows, but using SeaBIOS is probably the easiest payload to use, since I don't need to create a configuration for it to work and it can easily boot from other media such as USB sticks. As far as I can tell, it should even be possible to have SeaBIOS as the primary payload and have GRUB as a second payload as well as the other way around. I haven't tried that though.
Maybe I'll try a GRUB payload at some point, now that I got a basic Coreboot setup working. A GRUB payload on the flash chip with a fully encrypted hard disk with no unencrypted data would be pretty neat, I guess.
Chris (web) says:
2017-01-01 04:39:43
I put coreboot on my T420 and also used the SeaBIOS Payload. I did it because its easy/hasslefree and i use syslinux as my Bootloader. For me there was simply no need to use GRUB as a payload.

Just my 2 Cents.
Quade321 (web) says:
2017-01-05 15:21:04
Hey. I was wondering what method you used to retrieve a VBIOS dump. I've been trying to get a valid one for a while now, and I've never gotten it to boot with it. I imagine I'm doing something wrong with the dump process.
Thank you!
wej (web) says:
2017-01-05 15:56:10
Quade321: I have used UEFITool to extract the VGA ROM from Lenovo's firmware. I extracted it from their latest BIOS update files, not from the firmware I got off of my flash chip. The process for extracting the VGA ROM is explained here: https://www.coreboot.org/VGA_support#How_to_retrieve_a_good_video_bios
("UEFI Method" section)
norpol (web) says:
2017-01-06 17:19:51
Those are the two scripts that implement the pm-suspend "quirks" reset-brightness, vbe-post, vbestate-restore, vbemode-restore:
- https://cgit.freedesktop.org/pm-utils/tree/pm/sleep.d/99video
- https://cgit.freedesktop.org/pm-utils/tree/pm/sleep.d/98video-quirk-db-handler

reset-brightness just reads /sys/class/backlight/intel_backlight/brightness, sets it to 0 and then restores brightness from before.

vbe is a reference for vbetool, which does plenty of things. Fedora doesn't ship this anymore, but my Debian does, so I've decided to collect all the sources I could find and put them in this repository https://github.com/norpol/vbetool

Best luck!
dwhacks (web) says:
2017-01-29 22:52:43
I'm trying to get coreboot on my x220 aswell. I've got it but did not extract the VGA option rom. I cant seem to figure out how to do this, nor where to find/download a stock bios.

Without it, it does seem to work, except I cannot boot a windows7 install disk which I need.

From chat on the coreboot IRC, someone says windows10 boots fine but windows 7 will not. Any ideas?
wej (web) says:
2017-01-31 17:30:25
dwhacks: Please have a look at my comment above. Quade321 had the same issue. You can extract it from the vendor BIOS image.
as.nielo (web) says:
2017-03-29 22:12:23
I'm now typing it from me disabled x220. No coreboot since I need UEFI boot possible - I'm on hacked macOS. Did spend some time yesterday evening trying to compile required .fd file to get tiancore payload working but no success. Do you know any workaround?
wej (web) says:
2017-03-30 18:33:32
as.nielo: I haven't used Tianocore with Coreboot, so I'm afraid I can't help you there.
zhongfu (web) says:
2017-04-02 07:15:57
Just a note: if you've checked "Devices > Use native graphics initialization", you won't need the VGABIOS blob. However, you might run into some problems with that, like not being able to show a bootsplash before the payload loads, and having to use quirks while suspending.

With the native gfx initialization, I wasn't able to get the screen to come back on after waking from `systemctl suspend`. However, suspend worked fine after I switched to using the VGABIOS blob, so if you aren't wary about binary blobs (and perhaps a marginally slower boot), you could do that instead.
wej (web) says:
2017-04-02 08:13:24
zhongfu: Yes, native graphics initialization basically works okay, but since I had problems with the machine properly waking up from suspend, I then have tried with the VGA BIOS blob. I still needed to use some of pm-suspend's quirks to get it working properly. So maybe this is even possible with the native gfx init. I haven't investigated further after I got it working.
Bora (web) says:
2017-09-29 01:50:31
Nice website!
alex (web) says:
2017-10-11 02:40:29
Hey, I just went through with this, same laptop, same idea I guess. I too have 16GB of DDR3-1600 RAM, and when I run memtest I see both sticks, but it only gives me 8GB of ram, I was wondering if you came across this issue during your flash?
wej (web) says:
2017-10-11 08:24:42
alex: No, I did not. My memory was detected properly right from the start. What happens when you remove one stick? Does it still see 8 GB or does it go down to 4?
alex (web) says:
2017-10-14 21:09:25
So when I remove 1 stick, it sees 8gb, and when I have both it sees 8gb, I checked both sticks to make sure they weren't dead too. When memtest starts the test and shows the ram modules on the lower screen it lists both so it can detect them.

I also had some DDR3-1866 ram which is supposedly supported by coreboot too, but that just plain doesn't boot. I've gone a tried reflashing my stock bios to test from there, and it seems like I can't do that, I get a 1-3-3 post code after the flash to stock, gonna go look that up...

I also see a "Ignore vendor programmed fuses that limit max. DRAM frequency" in make nconfig under Chipset, I wonder what that'll do.
alex (web) says:
2017-10-14 22:31:34
here's some pics of it finally booting with the 1866 ram, this is the same with the 1600 ram.
https://imgur.com/a/gSaLD

Does yours boot with only 1 stick in slot B? Mine won't boot with only that one and I'm scared I may have killed the ram slot on my x220 mobo.
wej (web) says:
2017-10-15 16:17:32
alex: I've just checked if the machine boots with just one memory module and it works perfectly fine with just one module. I have tested both memory slots. So it looks like you might have an issue with your seconds slot. Maybe there just some dust inside the slot. You could try blowing some air on the slot to clean it.
janes (web) says:
2017-10-27 16:34:18
I have the same problem with the blank screen after resume. I'm using arch linux and gnome. Suspend is handled by systemd and the kernel suspend features.

The relevant vbetool parts out of the pm-utils 99video script are not working for me (to get vbetool working at all, KMS must not be set).

anynone any ideas howto trigger such kind of quirks for the kernel?
janes (web) says:
2017-10-28 15:10:53
not using me_cleaner improves the blank screen after resumeing issue. still evaluating further implications...
as.nielo (web) says:
2018-12-05 19:31:15
Hi there, I did some progress recently and want to share:

NOT using the native coreboot ram init fixes the 8GB available (when 16GB installed). There is config flag to ignore 1333MHz bus limit for the native raminit (if one wish to stay with 8gigs)

You may wish to set nvram/CMOS variable gfx_uma_size=224MB for an extra boost. I have 16Gigs of 1866MHz memory installed and can run Tormet: Tides of Numenera with decent framerate, a feat unreachable on stock bios

Setting "usb_always_on=AC and battery" makes cd drive from docking station to work. Actually the entire station works good with coreboot but CD only with this settings

I'm using nvramtool linux command and nvramcui to read/write CMOS

Do you know other meanings of different EC memory registers (like b0 for start threshold and b1 for stop)? Default Lenovo threshold is 96% to stop charge. 100% would definetely harm the battery.
wej (web) says:
2018-12-06 20:33:12
as.nielo, thanks for your progress report. I haven't much further investigated the other EC registers, since there was nothing else that I wanted to change, that was controlled by the EC. What you can do by modifying EC registers, is changing the fan speed and fan control behavior. The register for that seems to be 0x2F, according to https://www.thinkwiki.org/wiki/How_to_control_fan_speed

That page also mentions registers 0x84 (LSB) and 0x85 (MSB) for fan RPM.

Generally, I would advise to be cautious when poking around with EC registers.

Leave a comment

Name
E-Mail
Website
Homepage
Comment