How to Flash a Thinkpad X200 with Libreboot

This is a guide on how to flash a Thinkpad X200 with Libreboot using a BeagleBone Black. The steps are written out to be followed on a Linux machine and most of the information in here comes from the Libreboot project’s website.

There are a few requirements for this guide: a Thinkpad X200 (obviously); a BeagleBone Black; a USB cable or a power adapter for the BeagleBone; a 4GB microSD card; an ATX power supply or another source of 3.3V DC; either a Pomona 5250 or Pomona 5252 clip (depends on the size of the flash chip); 1 male-to-male and 7 male-to-female jumper wires, an internet connection, and basic experience with Linux and the command line.

Preparing the BeagleBone Black

First, the BeagleBone Black will need to be setup for flashing.  To start, the onboard eMMC flash storage will be updated with Debian 7. You can download the latest Debian 7 image here. Decompress the image using the following command (the filename may have changed since this was written):

unxz bone-debian-7.11-lxde-4gb-armhf-2016-06-15-4gb.img.xz

Now with the image file decompressed, write the file to a microSD card using dd. Note that the device name of the microSD card might not be the same as mine and that mine was “mmcblk0” in the command below.

sudo dd bs=4M if=bone-debian-7.11-lxde-4gb-armhf-2016-06-15-4gb.img of=/dev/mmcblk0; sync

Once that is complete, edit the “/boot/uEnv.txt” file on the card and remove the “#” on this line:


With the line uncommented, insert the card into the BeagleBone Black and power it on. When it powers on, it will start writing Debian from the microSD card onto the eMMC storage. The lights on the BeagleBone will start flashing and once the process is over, the device will power itself off.  Once that happens, remove the card from it and power it back on.

At this point we will need to SSH onto the BeagleBone. The two easiest ways to do this are to either connect to it via USB or by its wired network port. If connected by USB, it will set up a wired ethernet interface (this may need to be configured locally) and its IP is usually If connected to the wired network, the IP assigned by the network will need to be found.

ssh root@

Once connected, run apt-get update and apt-get upgrade to update all the software. Next the BeagleBone will need to have spidev enabled. Use nano to create the following file:

nano BB-SPI0-01-00A0.dts

Paste this into the nano interface:


/ {
    compatible = "ti,beaglebone", "ti,beaglebone-black";

    /* identification */
    part-number = "spi0pinmux";

    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            spi0_pins_s0: spi0_pins_s0 {
                pinctrl-single,pins = <
                  0x150 0x30  /* spi0_sclk, INPUT_PULLUP | MODE0 */
                  0x154 0x30  /* spi0_d0, INPUT_PULLUP | MODE0 */
                  0x158 0x10  /* spi0_d1, OUTPUT_PULLUP | MODE0 */
                  0x15c 0x10  /* spi0_cs0, OUTPUT_PULLUP | MODE0 */

    fragment@1 {
        target = <&spi0>;
        __overlay__ {
             #address-cells = <1>;
             #size-cells = <0>;

             status = "okay";
             pinctrl-names = "default";
             pinctrl-0 = <&spi0_pins_s0>;

             spidev@0 {
                 spi-max-frequency = <24000000>;
                 reg = <0>;
                 compatible = "linux,spidev";

Save the file. It will then need to be compiled and installed with the following commands:

dtc -O dtb -o BB-SPI0-01-00A0.dtbo -b 0 -@ BB-SPI0-01-00A0.dts
cp BB-SPI0-01-00A0.dtbo /lib/firmware/
echo BB-SPI0-01 > /sys/devices/bone_capemgr.*/slots

To check if the installation went correctly, run the line below:

cat /sys/devices/bone_capemgr.*/slots

The output should have something similar to the output below. The last line should match:

 0: 54:PF--- 
 1: 55:PF--- 
 2: 56:PF--- 
 3: 57:PF--- 
 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
 7: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-SPI0-01

Now verify that spidev exists with:

ls -al /dev/spid*

The command should list the device like this:

crw-rw---T 1 root spi 153, 0 Feb 29 05:39 /dev/spidev1.0

The last thing that needs to be done is to setup the BeagleBone to have the changes persist after restarting. Make the last line of  “/etc/default/capemgr” match the following:


Accessing the Flash Chip

To access the flash chip, first unscrew all the screws from the bottom of the Thinkpad that are marked with red circles in the picture below.


With the bottom facing upward, copy down the MAC address of the laptop. There is typically a sticker on the bottom-right side that has the address. Alternatively, you can unscrew the access panel to the memory and under the memory sticks is another sticker with the address.

Now with everything unscrewed, flip the laptop over and access the keyboard. Push the keyboard slightly downward and towards the screen. This should pop up the keyboard. Slowly lift it. The keyboard will be attached to the mainboard with a ribbon cable and should look like image below.

keyboard_ribbonTo release the ribbon, pull on the tab directly above the connector shown in the image above. If the laptop has a finger print reader, pull up the ribbon cable that is in the next image.

fingerprint_ribbonWith the cables disconnected, gently lift up the palm rest by pulling upward from the top until it comes off. Once it comes off, it should look similar to the next photo. Look for the chip in the red box.


Now there could be either a 4MB or 8MB chip, with the smaller being 8 pin and the larger being 16 pin. Below is a closer picture of the two different versions. The 4MB will need the Pomona 5250 and the 8MB will need the Ponoma 5252 clip.


Flashing the Chip

Now with access to the flash chip, the next step is to connect the BeagleBone to the flash chip. Connect the correct sized Pomona clip to the flash drive so that it is securely seated and flush with the pins. The next step is to connect the clip to the BeagleBone and to its power source. Start by connecting the male-to-female jumper cables from the clip to the BeagleBone according to the wiring diagram below. Do not connect the 3.3V power source yet. The top of the image below corresponds to the LCD screen and the bottom of the image is near the bottom of the palmrest.diagram

Simply match the numbers to the corresponding pin on the clip to the matching socket on the BeagleBone. The picture below shows how to orientate the device. Take note that the top row is the even numbered sockets and the bottom is the odd numbered sockets. The lowest numbers start near the barrel connector. Make sure that no part of the BeagleBone is touching anything that could cause a short. This can be easily avoided by placing something non-conductive underneath it like a strip of cardboard. bbb_pinout

If you’re using an ATX power supply as the source of the 3.3V, connect the male-to-male jumper header to any of the black (ground) wire sockets on the 20/24 pin ATX power supply connector. Using electrical tape to secure this connection in place is rather helpful. Wikipedia has a good diagram of the connector to use as a guide for choosing the correct socket. Next, connect another male-to-female jumper cable to the cable that was just connected to the ATX connector, and now connect it to the #2 socket on the BeagleBone Black. The last connection is for 3.3V power. Follow the same steps above with the jumper cables but connect to one of the 3.3V power sources on the ATX connector (pin 1 is a good choice) and connect the other end to the Pomona clip’s correspond pin. To start the ATX PSU, two of the sockets of the connector will need to be jumped. Seasonic has a great guide for this here.

If you’re using another source for power, make sure to connect the ground of that power source to socket #2 on the BeagleBone and the 3.3V to the right pin on the clip.

With all connections in order, it’s time to download the Libreboot ROM and utilities. On the SSH session, download the latest utility archive and the corresponding ROM image for the size of the flash chip from the Libreboot website using wget.  (Note: the URLs in the example below may have changed since this was written.)


Now uncompress the tarballs to the current directory (assuming this is the home directory for root).

tar xf libreboot_util.tar.xz
tar xf libreboot_x200_8mb.tar.xz

After extracting the files, the flashrom and ich9gen utilities will need to be made executable.

chmod u+x libreboot_util/ich9deblob/armv7l/ich9gen libreboot_util/flashrom/armv7l/flashrom

To test if everything is setup and connected correctly run the following command:

./libreboot_util/flashrom/armv7l/flashrom -p linux_spi:dev=/dev/spidev1.0,spispeed=512

If everything is working correctly, a similar output as below should result.

flashrom v0.9.8-unknown on Linux 3.8.13-bone79 (armv7l)
flashrom is free software, get the source code at

Calibrating delay loop... OK.
Found Macronix flash chip "MX25L3205D/MX25L3208D" (4096 kB, SPI) on linux_spi.
No operations were specified.

Now if everything seems to be in working order, it’s time to backup the current firmware.  These three backups will be made to make sure there weren’t any errors when reading the chip.

./libreboot_util/flashrom/armv7l/flashrom -p linux_spi:dev=/dev/spidev1.0,spispeed=512 -r factory1.rom
./libreboot_util/flashrom/armv7l/flashrom -p linux_spi:dev=/dev/spidev1.0,spispeed=512 -r factory2.rom
./libreboot_util/flashrom/armv7l/flashrom -p linux_spi:dev=/dev/spidev1.0,spispeed=512 -r factory3.rom

Compare each of the firmware dumps by comparing their hashes, using this command:

sha512sum factory*.rom

If all three of the hashes are not the same, check your wiring and connections, and make sure no steps were skipped or done incorrectly and then redump the firmware. Once you are sure that the backup is correct, save a copy of one of the three files to a secure location.

The final step before flashing is to add the current MAC address to the ROM before flashing. This can be accomplished with the ich9gen utility. Replace the X’s in the command below with the one written down from earlier in this guide.

./libreboot_util/ich9deblob/armv7l/ich9gen --macaddress XX:XX:XX:XX:XX:XX

That command will create two bin files, one of which will need to be added to the ROM image. Which one depends again on the flash chip size. The next commands will make a copy of the Libreboot file and patch it using dd.

For 4MB flash chips:

cp x200_4mb/x200_4mb_usqwerty_vesafb.rom .
dd if=ich9fdgbe_4m.bin of=x200_4mb_usqwerty_vesafb.rom bs=1 count=12k conv=notrunc

For 8MB flash chips:

cp x200_8mb/x200_8mb_usqwerty_vesafb.rom .
dd if=ich9fdgbe_8m.bin of=x200_8mb_usqwerty_vesafb.rom bs=1 count=12k conv=notrunc

Now it’s time to write the new image to the chip using the command below.  Make sure to change the name of the file to the one that matches the correct chip size. If the flash was successful, it should say at the end “verified” or something similar. If you get an error that indicates the flash didn’t go successfully, check the connections and run the command again. If a message about the current image on the chip being exactly the same as the image about to be flashed then running the command again, this means the first flash was actually successful.

./libreboot_util/flashrom/armv7l/flashrom -p linux_spi:dev=/dev/spidev1.0,spispeed=512 -w x200_4mb_usqwerty_vesafb.rom

After the flash, boot the machine and a GRUB menu should appear.

This indicates that everything was done correctly. Once again, the Libreboot project’s website has a lot of great documentation that is useful on configuring Libreboot and GRUB.

If you see any technical or grammatical errors, or if you have any suggestions on how to improve this guide, please let me know.