Motivado por la tecnología, leo temas diferentes cada semana y algunos me llaman mucho la atención.
Libreboot.
¿Qué demonios es libreboot? Libreboot es una BIOS de código abierto. En resumen, no es tan malo. Puedes leer más sobre él en https://libreboot.org/
¿Por qué me llamó la atención este tema? Código abierto, hardware, tema nuevo (para mí), no hay mucha gente haciéndolo. No se me ocurre un tema mejor en el que trabajar.
Aunque pensar en una BIOS puede ser muy difícil (lo es), para nosotros no lo será tanto. Sólo se trata de descargar algún archivo y escribirlo en un dispositivo. Parece fácil, ¿verdad?.
Pasé mucho tiempo leyendo la documentación oficial. Pasé mucho tiempo no por la larga documentación, ni tampoco por la complejidad, sino, en mi sincera opinión, por la mala organización.
En primer lugar, aquí tienes el enlace a la documentación oficial https://libreboot.org/docs/install/t480.html
Requisitos previos
- Un portátil que funcione con Ubuntu 24.04 (éste no será el portátil en el que flashearé libreboot) con git
- Pico de frambuesa
- Clip 8 clavijas
- Cable Dupont hembra 2 macho
- Cable micro USB
Prepara el portátil programador
He clonado el repositorio git oficial de libreboot.
git clone https://codeberg.org/libreboot/lbmk
Dependencias instaladas para Ubuntu 24.04.
cd lbmk
./mk dependencies ubuntu2404
Aunque no tenga sentido, también tuve que instalar dependencias para el SO Debian. Instalar sólo las dependencias de Ubuntu 24.04 me dio un error al ejecutar algunas de las herramientas necesarias (lo pegaré un poco más adelante).
./mk dependencies debian
Antes de ejecutar el comando anterior, intenté ejecutar la herramienta flashprog, pero me dio el siguiente error. Por eso tuve que instalar las dependencias para el SO Debian.
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk$ CONFIG_feature=no ./mk -b flashprog config/data/flashprog/mkhelper.cfg missing config/flashprog/target.cfg already exists Loading flashprog config: config/flashprog/target.cfg config/data/flashprog/mkhelper.cfg missing config/flashprog/target.cfg already exists Loading flashprog config: config/flashprog/target.cfg make: Entering directory '/home/jjdiaz/git/libreboot/lbmk/src/flashprog' Replacing all version templates with p1.4-2-gf730186. Building flashprog version p1.4-2-gf730186 C compiler found: cc (Ubuntu 13.3.0-6ubuntu2\~24.04) 13.3.0 Target arch: x86 Target OS: Linux Target endian: little Dependency libpci found: yes 3.10.0 Checking for old "pci_get_dev()": no CFLAGS: -I/usr/include/x86_64-linux-gnu LDFLAGS: -lpci -lz -lresolv -ludev Dependency libusb1 found: yes 1.0.27 CFLAGS: -I/usr/include/libusb-1.0 LDFLAGS: -lusb-1.0 -ludev Dependency libjaylink found: no Dependency NI-845x found: no Dependency libftdi1 found: no Dependency libgpiod found: no Checking for header "mtd/mtd-user.h": yes Checking for header "linux/spi/spidev.h": yes Checking for header "linux/i2c-dev.h": yes Checking for header "linux/i2c.h": yes Checking for header "sys/utsname.h": yes Checking for function "clock_gettime": yes Checking for external "librt": yes The following features require libftdi1: CONFIG_FT2232_SPI=yes CONFIG_USBBLASTER_SPI=yes The following features require libgpiod: CONFIG_LINUX_GPIO_SPI=yes The following features require libjaylink: CONFIG_JLINK_SPI=yes You can disable individual features with CONFIG_feature=no in your make command. make: \*\*\* \[Makefile:968: config\] Error 1 make: Leaving directory '/home/jjdiaz/git/libreboot/lbmk/src/flashprog' ERROR ./mk: Unhandled error for: make -C src/flashprog -j1 WARNERROR=no ERROR ./mk: Unhandled error for: ./mk -b flashprog
Prepara el pico de frambuesa
He creado el firmware de la frambuesa. Dentro de la carpeta del repositorio clonado, ejecuté el siguiente comando.
./mk -b pico-serprog
El comando anterior generará algunos archivos en la carpeta ./bin.
Conecté la frambuesa pico mientras pulsaba el botón BOOTSEL de la frambuesa al USB del portátil. Ejecuté el comando lsusb para ver si el portátil detectaba la frambuesa correctamente (fíjate en el dispositivo de arranque Raspberry Pi RP2 ).

Tras insertar la frambuesa, debería aparecer como cualquier otro dispositivo de almacenamiento usb. Copié en él el archivo ./bin/serprog_pico/serprog_pico.uf2. Tras pegar el archivo, la frambuesa se reinició automáticamente. Volví a ejecutar el comando lsusb y observé que el nombre del dispositivo era diferente (fíjate en el dispositivo pico-serprog (pico) de libreboot.org ).

La frambuesa estaba lista para empezar a funcionar.
Preparar portátil thinkpad
He creado el firmware flashprog. Dentro de la carpeta del repositorio clonado, ejecuté el siguiente comando.
./mk -b flashprog
Una vez finalizada la compilación, se generaron algunos archivos binarios en ./elf/flashprog/flashprog
NOTA: ANTES DE CONECTAR EL PICO DE FRAMBUESA A LA PLACA THINKPAD, DESCONECTÉ LA BATERÍA THINKPAD Y LA BATERÍA CMOS. NO CONECTÉ EL PICO DE FRAMBUESA AL PUERTO USB DEL PORTÁTIL UBUNTU HASTA ESTAR SEGURO DE QUE ESTÁ COMPLETAMENTE ACOPLADO A LA PLACA THINKPAD.
Cableado del pico de frambuesa


Las imágenes de arriba muestran que los pines pico de la frambuesa deben conectarse a la BIOS y a los chips Thunderbolt.
- Pin 7 de la Raspberry pico conectado al pin 1 del clip
- Pin 6 de la Raspberry pico conectado al pin 2 del clip
- Pin 38 de la Raspberry pico conectado al pin 4 del clip
- Pin 5 de la Raspberry pico conectado al pin 5 del clip
- Pin 4 de la Raspberry pico conectado al pin 6 del clip
- Pin 36 de la Raspberry pico conectado al pin 8 del clip
La patilla 1 del chip está situada arriba a la izquierda y la patilla 5 abajo a la derecha.
La imagen de abajo muestra cómo quedaron las cosas después de hacer todas las conexiones.

Copia de seguridad del firmware thunderbolt
Es un problema muy común en los portátiles thinkpad t480s que el puerto thunderbolt no funcione como se espera debido a un error en el firmware. Estaba 100% seguro de que me afectaba este problema. No hay otra opción. Es necesario un flasheo externo para solucionar el problema.
Estaba 100% seguro de que me afectaba el problema porque recibía un mensaje de error cada vez que arrancaba mi portátil en Windows.

El primer paso antes de ponerme manos a la obra con el proceso de flasheo es volcar el firmware actual del thunderbolt por si algo va mal y poder restaurarlo (ten en cuenta que el problema no significa que el thunderbolt deje de funcionar, sino que sólo funciona con dispositivos usb y no carga tan rápido como debería).
Después de cablear completamente el pico de frambuesa y el clip, antes de conectar el pico de frambuesa al puerto usb del portátil ubuntu, conecté el clip al chip thunderbolt. La ubicación del chip se muestra en las siguientes imágenes (fíjate en el rectángulo rojo situado en la parte superior derecha de la placa).


NOTA: La patilla 1 del chip es la que está marcada con un punto. La patilla 1 del clip debe estar conectada a la patilla 1 del chip.
Una vez conectado el clip, es hora de empezar a volcar el firmware thunderbolt.
Antes de poder empezar a hacer la copia de seguridad, tuve que localizar dónde está montada la frambuesa pico en el portátil ubuntu. Para obtener la ubicación correcta, ejecuté el siguiente comando.
sudo dmesg -wH
Mientras se ejecutaba el comando, conecté la raspberry pico al portátil ubuntu y apareció un mensaje como el siguiente fragmento de código.
\[jun 1 16:07\] usb 1-2: new full-speed USB device number 9 using xhci_hcd \[ +0,152742\] usb 1-2: New USB device found, idVendor=cafe, idProduct=4001, bcdDevice= 1.00 \[ +0,000014\] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 \[ +0,000006\] usb 1-2: Product: pico-serprog (pico) \[ +0,000005\] usb 1-2: Manufacturer: libreboot.org \[ +0,000004\] usb 1-2: SerialNumber: 503558607A67521F \[ +0,033213\] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
En mi caso, significa que el pico de la frambuesa está montado en /dev/ttyACM0.
Para estar seguro, cogí 3 volcados y los comparé para asegurarme de que todos eran exactamente iguales.
DUMP 1
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/thunderbolt$ ../../elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0,spispeed=16M -r dump1.bin flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64) flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). serprog: Programmer name is "pico-serprog" Found Winbond flash chip "W25Q80.V" (1024 kB, SPI) on serprog. Reading flash... done.
DUMP 2
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/thunderbolt$ ../../elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0,spispeed=16M -r dump2.bin
flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64)
flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
serprog: Programmer name is "pico-serprog"
Found Winbond flash chip "W25Q80.V" (1024 kB, SPI) on serprog.
Reading flash... done.
DUMP 3
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/thunderbolt$ ../../elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0,spispeed=16M -r dump3.bin
flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64)
flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
serprog: Programmer name is "pico-serprog"
Found Winbond flash chip "W25Q80.V" (1024 kB, SPI) on serprog.
Reading flash... done.
Después de conseguir los tres volcados, para comprobar que todos tienen exactamente el mismo contenido, sólo era cuestión de comprobar el sha de todos ellos y compararlos.
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/thunderbolt$ sha512sum dump1.bin
831acf633b19ba806db400072b9f00562f39add0511836f6bd950d5cbd255088c23842a5fbedaecc0898a1869403cadcec17a81a16a9c2d3a3ae107e3c35b2bd dump1.bin
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/thunderbolt$ sha512sum dump2.bin
831acf633b19ba806db400072b9f00562f39add0511836f6bd950d5cbd255088c23842a5fbedaecc0898a1869403cadcec17a81a16a9c2d3a3ae107e3c35b2bd dump2.bin
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/thunderbolt$ sha512sum dump3.bin
831acf633b19ba806db400072b9f00562f39add0511836f6bd950d5cbd255088c23842a5fbedaecc0898a1869403cadcec17a81a16a9c2d3a3ae107e3c35b2bd dump3.bin
Construir firmware thunderbolt
Una vez completada la copia de seguridad, es hora de flashear el firmware correcto para solucionar el problema del puerto thunderbolt.
Dentro de la carpeta del repositorio clonado, ejecuté el siguiente comando.
./mk -d coreboot t480s_vfsp_16mb
El comando generó un archivo. Se encontraba en ./vendorfiles/t480s/tb.bin
Flashear firmware thunderbolt
Antes de flashear el nuevo firmware, tuve que eliminar el contenido del chip. Para ello, creé un archivo cuyo contenido son 0s completos.
dd if=/dev/zero of=null.bin bs=1M count=1
Después, he flasheado el archivo en el chip thunderbolt.
./elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0 -w null.bin
El resultado del comando se parecía al siguiente fragmento de código
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk$ ./elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0 -w null.bin flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64) flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
serprog: Programmer name is "pico-serprog"
Found Winbond flash chip "W25Q80.V" (1024 kB, SPI) on serprog.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.
Una vez borrado completamente el chip, tuve que volver a montarlo todo (batería CMOS, batería thinkpad) y arrancar el ordenador. Una vez arrancado completamente el SO, apagué completamente el thinkpad y volví a quitar las baterías CMOS y thinkpad.
Ahora, he flasheado el nuevo firmware thunderbolt en el chip.
./elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0 -w vendorfiles/t480s/tb.bin
Una vez completado el flasheo, el código de salida se parecía al siguiente fragmento de código
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk$ ./elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0 -w vendorfiles/t480s/tb.bin
flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64)
flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
serprog: Programmer name is "pico-serprog"
Found Winbond flash chip "W25Q80.V" (1024 kB, SPI) on serprog.
Reading old flash chip contents... done.
Erasing and writing flash chip... FAILED at 0x0000205c! Expected=0xff, Found=0xef, failed byte count from 0x00000000-0x0000ffff: 0x17
ERASE FAILED!
FAILED!
Uh oh. Erase/write failed. Checking if anything has changed.
Reading current flash chip contents... done.
Apparently at least some data has changed.
Your flash chip is in an unknown state.
Please report this to the mailing list at [email protected]
or on IRC (see https://www.flashprog.org/Contact for details), thanks!
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk$ ./elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0 -w vendorfiles/t480s/tb.bin
flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64)
flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
serprog: Programmer name is "pico-serprog"
Found Winbond flash chip "W25Q80.V" (1024 kB, SPI) on serprog.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.
Ten en cuenta que tuve que flashearlo dos veces porque la primera falló al borrar el chip.
Una vez finalizado el flasheo, reinicié el portátil y el error de thunderbolt que aparecía arriba había desaparecido. ¡Lo he conseguido!
Copia de seguridad del firmware de la BIOS
Al igual que hice con el firmware del thunderbolt, hice exactamente lo mismo con el firmware de la BIOS. Antes de actualizar la BIOS, por motivos de seguridad, hice una copia de seguridad de la BIOS.
La ubicación del chip se muestra en la imagen inferior (observa el rectángulo rojo situado en la parte superior central de la placa).


Como he dicho para el chip thunderbolt, el pin 1 del chip es el que está marcado con un punto. La patilla 1 del clip debe estar conectada a la patilla 1 del chip.
Es hora de empezar a descargar el firmware.
DUMP 1
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/bios$ ../../elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0,spispeed=16M -r dump1.bin flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64) flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). serprog: Programmer name is "pico-serprog" Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. Reading flash... done.
DUMP 2
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/bios$ ../../elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0,spispeed=16M -r dump2.bin flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64) flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). serprog: Programmer name is "pico-serprog" Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. Reading flash... done.
DUMP 3
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/bios$ ../../elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0,spispeed=16M -r dump3.bin flashprog p1.4-2-gf730186 on Linux 6.8.0-60-generic (x86_64) flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). serprog: Programmer name is "pico-serprog" Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. Reading flash... done.
Una vez que conseguí todos los volcados, los comparé para asegurarme de que el contenido de todos ellos era exactamente el mismo.
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/bios$ sha512sum dump1.bin 71251f4c4e41832a66aaaae91d01119988c5253e66c1d4b61ce6975e2d04fb4e80524f797bf1c9102a1cd9a7239775291d0be18a67704666547acc8746d9b518 dump1.bin
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/bios$ sha512sum dump2.bin 71251f4c4e41832a66aaaae91d01119988c5253e66c1d4b61ce6975e2d04fb4e80524f797bf1c9102a1cd9a7239775291d0be18a67704666547acc8746d9b518 dump2.bin
jjdiaz@laptop-HN-WX9X:\~/git/libreboot/lbmk/dumps/bios$ sha512sum dump3.bin 71251f4c4e41832a66aaaae91d01119988c5253e66c1d4b61ce6975e2d04fb4e80524f797bf1c9102a1cd9a7239775291d0be18a67704666547acc8746d9b518 dump3.bin
Activar hyper-threading
Por defecto, libreboot no está configurado para gestionar hyper-threading. Esto significa que, para el thinkpad t480s, en lugar de poder utilizar 8 hilos, sólo estarían disponibles 4.
Para poder utilizar toda la potencia del procesador, configuré el hyper-threading antes de crear el firmware de la BIOS.
Para ello, dentro de la carpeta del repositorio clonado, ejecuté el siguiente comando.
./mk -m coreboot t480s_vfsp_16mb
El comando abrió una ventana de terminal donde se pueden hacer diferentes personalizaciones.
Para activar el hyper-threading, tuve que ir a Chipset -> Activar Hyper - Threading y marcarlo.
Construir el firmware de la BIOS
Dentro de la carpeta del repositorio clonado, ejecuté el siguiente comando.
./mk -b coreboot t480s_vfsp_16mb
Una vez finalizado el comando, los archivos generados se colocaron en ./bin/t480s_vfsp_16mb
Configurar la dirección MAC ethernet
Por defecto, libreboot configura la misma dirección MAC de ethernet para todos los dispositivos. Esto significa que si más de un dispositivo que utiliza libreboot está conectado a la misma red, tendrán problemas de conectividad debido a la coincidencia de las direcciones MAC ethernet.
La solución para evitar esta situación es configurar la dirección MAC de ethernet en la configuración de libreboot para que sea la definida por el fabricante para la tarjeta ethernet del portátil.
Lo primero que hice fue instalar ifdtool. Dentro de la carpeta del repositorio clonado, ejecuté el siguiente comando.
cd src/coreboot/default/util/ifdtool && make
También instalé nvmutil. Dentro de la carpeta del repositorio clonado, ejecuté el siguiente comando.
cd util/nvmutil && make
Ya he generado un archivo bin que flashearé en la BIOS. Este es el archivo en el que tengo que trabajar para establecer la dirección MAC adecuada. Tuve que desbloquear el archivo de la BIOS antes de extraer la dirección MAC. Este comando creará un nuevo archivo llamado bin/t480s_vfsp_16mb/seabios_t480s_vfsp_16mb_libgfxinit_corebootfb.rom.new
./src/coreboot/default/util/ifdtool/ifdtool --platform sklkbl --unlock bin/t480s_vfsp_16mb/seabios_t480s_vfsp_16mb_libgfxinit_corebootfb.rom
Ejecuté el siguiente comando para dividir el archivo de la BIOS en varios archivos relacionados con las diferentes secciones que hay en la BIOS.
./src/coreboot/default/util/ifdtool/ifdtool --platform sklkbl -x bin/t480s_vfsp_16mb/seabios_t480s_vfsp_16mb_libgfxinit_corebootfb.rom.new
La MAC se encuentra en uno de los archivos generados llamado flashregion_3_gbe.bin
He ejecutado el siguiente comando para establecer la MAC correcta.
./util/nvmutil/nvm flashregion_3_gbe.bin setmac ex:6x:6x:4x:ax:9x
El archivo también contiene una suma de comprobación y debe ser válida. Como he cambiado el contenido del archivo, es necesario actualizar la suma de comprobación. Para ello, he ejecutado los siguientes comandos.
./util/nvmutil/nvm flashregion_3_gbe.bin setchecksum 0
./util/nvmutil/nvm flashregion_3_gbe.bin setchecksum 1
El último paso es inyectar la nueva dirección MAC en el archivo de la BIOS generado anteriormente
./src/coreboot/default/util/ifdtool/ifdtool --platform sklkbl -i gbe:flashregion_3_gbe.bin bin/t480s_vfsp_16mb/seabios_t480s_vfsp_16mb_libgfxinit_corebootfb.rom.new
Se genera un nuevo archivo llamado bin/t480s_vfsp_16mb/seabios_t480s_vfsp_16mb_libgfxinit_corebootfb.rom.new.new. Este es el archivo que tuve que flashear en el chip de la BIOS.
Flashear el firmware de la BIOS
Flashear la BIOS fue tan sencillo como ejecutar el siguiente comando
./elf/flashprog/flashprog -p serprog:dev=/dev/ttyACM0 -w ../bin/t480s_vfsp_16mb/seabios_t480s_vfsp_16mb_libgfxinit_corebootfb.rom.new.new

En este punto, se completó el proceso de flasheo de la BIOS.
En mi caso, tuve que instalar un SO porque mi portátil no tenía ningún SO que utilizara grub para arrancar. Hay un montón de tutoriales en internet para instalar un SO, así que no lo describiré.
Espero que te haya gustado esta lectura. Disfruté mucho haciendo todos los pasos, así como escribiendo mi experiencia.
Gracias por leer mi blog. ¡Nos vemos en el próximo post!
