|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +title: Lenovo T480s Maximized |
| 4 | +permalink: /T480s-maximized-flashing/ |
| 5 | +nav_order: 1 |
| 6 | +parent: Step 2 - Flashing Guides |
| 7 | +grand_parent: Installing and configuring |
| 8 | +--- |
| 9 | + |
| 10 | +Lenovo T480s (Maximized) |
| 11 | +=== |
| 12 | + |
| 13 | +[T480s Hardware Maintenance Manual](https://download.lenovo.com/pccbbs/mobiles_pdf/t480s-hmm_en.pdf) |
| 14 | + |
| 15 | +Accessing and flashing the BIOS chip on a T-series machine has never been easier. The process is straightforward and takes approximately 10 minutes. |
| 16 | + |
| 17 | +The ThinkPad T480s has two SPI flash chips important for the port. The first chip holds the BIOS, ME, etc., while the second holds the Thunderbolt firmware. To access these chips, you only need to remove the back panel, which is secured by six screws. |
| 18 | + |
| 19 | +For whole procedure you will need: |
| 20 | +- A Phillips screwdriver +1 (PH1), which is standard for most laptop screws. |
| 21 | +- An assembled Raspberry Pi or CH341A SPI programmer. You should use a CH341A revision 1.6 or later (e.g., 1.6, 1.7, etc.) because these versions have a properly implemented and enforced voltage regulator, ensuring stable 3.3V operation (3.3V is important!) (e.g. [Modified CH341A SPI programmer](https://novacustom.com/product/modded-ch341a-bios-firmware-programmer-3v/) by Novacustom) or [open-source Tigard tool](https://github.com/tigard-tools/tigard). Using Raspberry Pi pico is described in the [Libreboot flash guide](https://libreboot.org/docs/install/spi.html). |
| 22 | +- Other laptop/PC with a Linux-based OS installed. |
| 23 | +- Optional: A plastic guitar pick or an old credit card to help detach the bottom case from the clips holding it in place. Otherwise, it can be difficult to remove, increasing the risk of breaking the tabs or the top part of the bottom case above the battery connector. |
| 24 | + |
| 25 | +There is still debate over which programmer and software should be used (flashprog vs. flashrom). Before following this guide, make sure you read [README.md](https://github.com/linuxboot/heads/tree/master/blobs/xx80/README.md) and the related information. |
| 26 | + |
| 27 | +Some ThinkPad T480s units on the used market, like the T480, are affected by an Intel bug in the Thunderbolt firmware. In short, the flash chip becomes full, causing Thunderbolt fast charging to stop working, though slow charging still functions. This issue can also affect the USB-C port. For convenience, Heads provides a fixed and padded Thunderbolt firmware that resolves the "charging problem" if your laptop is affected. Board testers did not encounter this issue, and it is unlikely to occur if your laptop was in use for more than 12 months before flashing. If you do experience the "charging bug," it is possible to fix it with external flashing. Also, the update is possible prior flashing heads using [fwupd from a Linux distribution](https://www.reddit.com/r/thinkpad/comments/12tf6xv/psa_t480_thunderbolt_controller_v23_is_now_on/) |
| 28 | + |
| 29 | +Please note that as of March 2025, Thunderbolt data transfer is not supported upstream by [coreboot](https://review.coreboot.org/c/coreboot/+/83274). However, video output through Thunderbolt and charging still work. This means only the USB-C charging port can be used for data transfer. |
| 30 | + |
| 31 | +## (Optional) Updating EC Firmware |
| 32 | + |
| 33 | +Before flashing heads, it is advisable to update the EC Firmware on the laptop. Some old EC firmware may be vulnerable to some serious CVEs. See [Heads-threat-model]({{ site.baseurl }}/Heads-threat-model/#binary-blobs-microcode-updates-and-transient-execution-vulnerabilities) for additional information. |
| 34 | + |
| 35 | +The only way to update the EC Firmware, called ECP (Embedded Controller Program) by Lenovo, is to use their proprietary BIOS Update utility which typically requires a Windows system. However, you can use the BIOS Update .iso file to create a bootable USB to boot directly into the BIOS Update Utility by using geteltorito. |
| 36 | + |
| 37 | +Locate the latest Bootable CD (.iso) file from lenovo: [BIOS Update (Bootable CD)](https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/thinkpad-t-series-laptops/thinkpad-t480s-type-20l7-20l8/downloads/ds502226) |
| 38 | + |
| 39 | +As of writting, the latest T480s BIOS Update is n22ur40w.iso (v1.60) published on April 16th, 2025 (so the following wget command could be oudated). |
| 40 | + |
| 41 | +```shell |
| 42 | +wget https://download.lenovo.com/pccbbs/mobiles/n22ur40w.iso |
| 43 | +``` |
| 44 | + |
| 45 | +Acquire the geteltorito script. On debian, the genisoimage package contains geteltorito: |
| 46 | +```shell |
| 47 | +sudo apt install genisoimage |
| 48 | +``` |
| 49 | + |
| 50 | +Generate a bootable image from the .iso: |
| 51 | +```shell |
| 52 | +geteltorito -o t480s_bootable_update_utility.img n22ur40w.iso |
| 53 | +``` |
| 54 | + |
| 55 | +Write the resulting image to a USB Flash drive: |
| 56 | +```shell |
| 57 | +sudo dd if=t480s_bootable_update_utility.img of=/dev/sdX status=progress |
| 58 | +``` |
| 59 | + |
| 60 | +Boot from the USB on the laptop and follow the update prompts. |
| 61 | + |
| 62 | +## Flashing Heads |
| 63 | + |
| 64 | +First, disconnect the power cable from your device then begin removing the back panel by removing the screws. A guitar pick or an old credit card can be helpful for detaching the panel. |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | +The back panel and the battery are removed. Important, ensure that all batteries, including the CMOS battery, are disconnected. Arrows indicate the direction you should pull the connectors. Pull the plastic part, not the wires, as the wires are thin and can be damaged. |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | +The top-right chip corresponds to the Thunderbolt SPI flash chip (1 MB). The chip located in the middle of the board corresponds to the BIOS (16 MB) chip, respectively. |
| 73 | + |
| 74 | +The chip located in the middle of the board contains the [Intel Management Engine (ME)](https://www.flashrom.org/ME) firmware. |
| 75 | + |
| 76 | + |
| 77 | + |
| 78 | +First [download]({{ site.baseurl }}/Downloading) or build (please see [general building]({{ site.baseurl }}/general-building/) / [building x230]({{ site.baseurl }}/x230-maximized-building/)) the board rom for this board and verify its hash value. |
| 79 | + |
| 80 | +Try to read the name of the SPI flash chip. The dot on the chip helps to identify the correct clip orientation. |
| 81 | + |
| 82 | + |
| 83 | + |
| 84 | +First, connect the clip of the CH341A or similar (Raspberry Pi Pico was used in the sample commands) programmer to the chip. Next, connect the programmer to the USB port of your other Linux-based computer with flashrom installed. In my setup, the red wire should be where the dot is (the dot indicates pin 1). Here, please also see the flashing guide for the T430. |
| 85 | + |
| 86 | +Use flashrom/flashprog to check the chip you are connected to: |
| 87 | + |
| 88 | +```shell |
| 89 | +sudo flashprog -p serprog:dev=/dev/ttyACM0:spispeed=16M |
| 90 | +``` |
| 91 | + |
| 92 | +Here is my output. |
| 93 | + |
| 94 | +``` |
| 95 | +flashprog p1.3-2-geb2c041 on Linux 6.12.21-1.qubes.fc37.x86_64 (x86_64) |
| 96 | +flashprog is free software, get the source code at https://flashprog.org |
| 97 | +
|
| 98 | +Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). |
| 99 | +serprog: Programmer name is "pico-serprog" |
| 100 | +Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. |
| 101 | +No operations were specified. |
| 102 | +``` |
| 103 | + |
| 104 | +Read from the chip twice (where the name of the flash chip is `YYY`): |
| 105 | + |
| 106 | +```shell |
| 107 | +sudo flashprog -r ~/t480s_original_bios.bin --programmer serprog:dev=/dev/ttyACM0:spispeed=16M -c YYY |
| 108 | +``` |
| 109 | + |
| 110 | +First output can be seen here. |
| 111 | + |
| 112 | +``` |
| 113 | +flashprog p1.3-2-geb2c041 on Linux 6.12.21-1.qubes.fc37.x86_64 (x86_64) |
| 114 | +flashprog is free software, get the source code at https://flashprog.org |
| 115 | +
|
| 116 | +Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). |
| 117 | +serprog: Programmer name is "pico-serprog" |
| 118 | +Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. |
| 119 | +Reading flash... done. |
| 120 | +``` |
| 121 | + |
| 122 | + |
| 123 | +```shell |
| 124 | +sudo flashprog -r ~/t480s_original_bios_1.bin --programmer serprog:dev=/dev/ttyACM0:spispeed=16M -c YYY |
| 125 | +``` |
| 126 | +Second output can be seen here. |
| 127 | + |
| 128 | +``` |
| 129 | +flashprog p1.3-2-geb2c041 on Linux 6.12.21-1.qubes.fc37.x86_64 (x86_64) |
| 130 | +flashprog is free software, get the source code at https://flashprog.org |
| 131 | +
|
| 132 | +Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). |
| 133 | +serprog: Programmer name is "pico-serprog" |
| 134 | +Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. |
| 135 | +Reading flash... done. |
| 136 | +``` |
| 137 | + |
| 138 | +Make sure that the dump matches the chip content. If this is the case, the output of the following command will state `Verifying flash... VERIFIED` |
| 139 | + |
| 140 | +```shell |
| 141 | +sudo flashprog -v ~/t480_original_bios.bin --programmer serprog:dev=/dev/ttyACM0:spispeed=16M -c YYY |
| 142 | +``` |
| 143 | +Make sure that files do not differ. |
| 144 | + |
| 145 | +```shell |
| 146 | +sha256sum t480s_original_bios.bin |
| 147 | +sha256sum t480s_original_bios_1.bin |
| 148 | +``` |
| 149 | + |
| 150 | +My dumps were the same. |
| 151 | + |
| 152 | +``` |
| 153 | +[user@flashing ~]$ sha256sum t480s_original_bios.bin |
| 154 | +54d58fdf217f41d4385576bb74f45f20de233d1a9d9ea2d6f1543b86111e1062 t480s_original_bios.bin |
| 155 | +[user@flashing ~]$ sha256sum t480s_original_bios_1.bin |
| 156 | +54d58fdf217f41d4385576bb74f45f20de233d1a9d9ea2d6f1543b86111e1062 t480s_original_bios_1.bin |
| 157 | +``` |
| 158 | + |
| 159 | +Alternative comparison is bit-by-bit. If the files are the same, there should be no output of this command. Otherwise, you will see a bit-by-bit difference between the files. |
| 160 | + |
| 161 | +```shell |
| 162 | +diff <(hexdump -C t480s_original_bios.bin) <(hexdump -C t480s_original_bios_1.bin) |
| 163 | +``` |
| 164 | + |
| 165 | +If the files differ or the chip content does not match the dump, try reconnecting your programmer to the SPI flash chip and make sure your flashrom/flashprog software is up-to-date. |
| 166 | + |
| 167 | + |
| 168 | +If they are the same, then write `t480s-hotp-maximized.rom` to the SPI flash chip: |
| 169 | + |
| 170 | +```shell |
| 171 | +sudo flashprog -p serprog:dev=/dev/ttyACM0:spispeed=16M -c YYY -w ~/heads/build/x86/t480s-hotp-maximized/heads-t480s-hotp-maximized.rom |
| 172 | +``` |
| 173 | + |
| 174 | +Here is a successful attempt. Be patient, it may take a while. |
| 175 | + |
| 176 | +``` |
| 177 | +flashprog p1.3-2-geb2c041 on Linux 6.12.21-1.qubes.fc37.x86_64 (x86_64) |
| 178 | +flashprog is free software, get the source code at https://flashprog.org |
| 179 | +
|
| 180 | +Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). |
| 181 | +serprog: Programmer name is "pico-serprog" |
| 182 | +Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. |
| 183 | +Reading old flash chip contents... done. |
| 184 | +Erasing and writing flash chip... Erase/write done. |
| 185 | +Verifying flash... VERIFIED. |
| 186 | +``` |
| 187 | + |
| 188 | +If all goes, well you can connect the CMOS and internal battery, press the power button and you should see the keyboard LED flash. After that, Heads will boot into its GUI. |
| 189 | + |
| 190 | +Two reboots are sometimes needed after flashing. Force a power off by holding the power button for 10 seconds. Since the memory training data was wiped by the content of the fully flashed ROM, this is normal. |
| 191 | + |
| 192 | +You should then follow through with [configuring keys]({{ site.baseurl }}/Configuring-Keys/). |
| 193 | + |
| 194 | +## Flash Thunderbolt firmware |
| 195 | +Important, ensure that power supply and all batteries, including the CMOS battery, are disconnected. After connecting the clip to the Thunderbolt chip as shown in the figure above read from the chip, making sure the connection is stable. The procedure is similar to the flashing Heads on the SPI chip. Therefore, comments are skipped. |
| 196 | + |
| 197 | +Check the chip you are connected to: |
| 198 | +```shell |
| 199 | +sudo flashprog -p serprog:dev=/dev/ttyACM0:spispeed=16M |
| 200 | +``` |
| 201 | +Output: |
| 202 | +``` |
| 203 | +flashprog p1.3-2-geb2c041 on Linux 6.12.21-1.qubes.fc37.x86_64 (x86_64) |
| 204 | +flashprog is free software, get the source code at https://flashprog.org |
| 205 | +
|
| 206 | +Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). |
| 207 | +serprog: Programmer name is "pico-serprog" |
| 208 | +Found Winbond flash chip "W25Q80.V" (1024 kB, SPI) on serprog. |
| 209 | +No operations were specified. |
| 210 | +``` |
| 211 | + |
| 212 | +```shell |
| 213 | +sudo flashrom -r ~/t480s_original_tb.bin --programmer ch341a_spi -c YYY |
| 214 | +``` |
| 215 | + |
| 216 | +```shell |
| 217 | +sudo flashrom -r ~/t480s_original_tb_1.bin --programmer ch341a_spi -c YYY |
| 218 | +``` |
| 219 | + |
| 220 | +```shell |
| 221 | +sudo flashrom -v ~/t480s_original_tb.bin --programmer ch341a_spi -c YYY |
| 222 | +``` |
| 223 | + |
| 224 | +```shell |
| 225 | +sha256sum t480s_original_tb.bin |
| 226 | +sha256sum t480s_original_tb_1.bin |
| 227 | +``` |
| 228 | + |
| 229 | +```shell |
| 230 | +diff <(hexdump -C t480_original_tb.bin) <(hexdump -C t480_original_tb_1.bin) |
| 231 | +``` |
| 232 | + |
| 233 | +Flash the padded Thunderbolt firmware. The firmware file tb.bin is located in the blobs folder after you build the Heads locally, or in the CircleCI artifacts. |
| 234 | + |
| 235 | +```shell |
| 236 | +sudo flashrom -p ch341a_spi -c YYY -w ~/t480s_tb.bin |
| 237 | +``` |
| 238 | +Done. |
0 commit comments