Flasher le BIOS du Lenovo Thinkpad X200 avec Libreboot

14/07/2018 in misc | tags : libreboot, bios, thinkpad, x200, spi, raspberrypi, rpi by Hackira

Pré-requis

  • Une pince SOP8 ou SOP16 (dépendant de votre chip) c'est le modèle que j'ai acheté, j'ai réussi à flasher, mais prenez plutôt celle-ci pour un SOP8 et celle-là pour un SOP16
  • 6 jumper female/female
  • Un Raspberry Pi
  • Un thinkpad X200

Préambule

IMPORTANT Ces commandes sont à entrer avec le Thinkpad X200 !

Il est possible de flasher le BIOS en démontant l'ordinateur une seule fois, les informations dont vous avez besoin est trouvable via l'OS (je connais mieux Linux que Windows, mais on va dire que ça se fait même avec un LiveUSB).

Il faudra trouver et noter l'adresse MAC de votre carte ethernet, vous pouvez regarder sur le sticker blanc qui se trouve sous la machine ou bien ouvrir un terminal sous linux et taper ip a - Pour les Debian-like, votre interface sera du style eth0 - Pour Arch, la mienne est notée enp3s0

[hoxton@pwnstar:~]$ ip a 
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether ac:16:3d:1c:fb:94 brd ff:ff:ff:ff:ff:ff 

Ici, mon adresse MAC est ac:16:3d:1c:fb:94, écrivons-ça quelque part Maintenant, partons à la recherche du modèle de chip utilisé par votre machine.

La méthode facile

Installons flashrom, une fois fait, on va simplement écrire dans un terminal flashrom -p internal Ceci nous donne le BIOS embarqué dans la machine, ainsi que sa taille, ce qui nous permet de déterminer quelle pince SOP se procurer. Si le modèle trouvé est à 8192 KB, votre BIOS nécessitera un clip SOP16 Si le modèle trouvé est à 4096 KB, votre BIOS nécessitera un clip SOP8 Note : J'utilise personnellement un kernel linux-hardened, ce qui empêche toute lecture par flashrom des composants interne pour des raisons de sécurité, dans ce cas, comme précisé plus tôt, utilisez un liveUSB.

La méthode qui défonce les yeux

Vous pouvez ouvrir votre Thinkpad X200, sortir le clavier de son logement et déclipser le repose-poignet, le chip BIOS se trouve tout en bas au centre de la carte mère, à gauche du haut-parleur. Si le chip a 4 broches de chaque côté, votre BIOS nécessite un clip SOP8 Si le chip a 8 broches de chaque côté, votre BIOS nécessite un clip SOP16 Il y a un sticker blanc sur le chip que vous devrez enlever pour lire le nom du modèle de la puce BIOS, si vous avez des difficultés passez un peu d'alcool à 90° pour enlever la colle, ou bien réferez-vous à la méthode facile. https://www.flashrom.org/Supported_hardware#Supported_flash_chips

La préparation des fichiers

J'ai vu ça et là des guides indiquant qu'il faut une machine x86 pour flasher le BIOS, cependant : Avec la méthode décrite dans ce guide, vous n'aurez besoin d'ouvrir votre Thinkpad X200 qu'à la toute fin de la procédure, avant ça, votre laptop est parfaitement fonctionnel et vous pouvez sans problèmes vous en servir pour générer votre nouveau BIOS puis les copier par la méthode de votre choix sur le Raspberry Pi. Vous pouvez également travailler ces fichiers avec votre Raspberry Pi puis flasher par la suite (même en CLI !) Je ne vais pas retracer toute la procédure pour générer les fichiers, voici cependant les liens de téléchargement

Les outilsLibreboot

Le BIOS

SI VOUS AVEZ UN BIOS SOP16 SEULEMENT

SI VOUS AVEZ UN BIOS SOP8 SEULEMENT

La préparation du Raspberry Pi

Dans mon cas, j'utilise un Raspberry Pi 3, qui a un port GPIO 40 pins, il est possible de flasher votre BIOS avec d'autres machines type Raspberry Pi 2 ou Zero, un Beagle Bone Black, mais je n'ai rien de tout ça Je suis parti d'une Raspbian fraichement installée pour éviter tout problème. Sinon, vous pouvez utiliser ce guide.

sudo apt update && sudo apt upgrade && sudo apt-get dist-upgrade && sudo apt install libftdi1 libftdi-dev libusb-dev libpci-dev subversion git && reboot

Une fois le reboot terminé, on va récupérer flashrom depuis Github (sans déconner, git n'est pas installé par défaut sur Raspbian, WTF?)

git clone http://github.com/flashrom/flashrom</i> 
cd flashrom 
make CONFIG_ENABLE_LIBUSB0_PROGRAMMERS=no CONFIG_ENABLE_LIBUSB1_PROGRAMMERS=no CONFIG_ENABLE_LIBPCI_PROGRAMMERS=no sudo make install CONFIG_ENABLE_LIBUSB0_PROGRAMMERS=no CONFIG_ENABLE_LIBUSB1_PROGRAMMERS=no CONFIG_ENABLE_LIBPCI_PROGRAMMERS=no

On va terminer par l'activation des connexions pour flasher le BIOS via le port GPIO du Raspberry Pi, pour ce faire :

sudo raspi-config
Interfacing Options > SPI (puis faire entrée, yes, entrée) 
Interfacing Options > I2C (puis faire entrée, yes, entrée) 

Avant de partir dans un ultime reboot, faites bien l'inventaire

  • Vous avez le BIOS modifié avec votre adresse MAC et copié sur votre Raspberry Pi
  • Tous les outils ont été installés et compilés
  • Vous avez tout le matériel (pince SOP, jumper female/female, tournevis PH00 ou PH1)

Parfait, alors éteignez complètement le Raspberry Pi. Il va falloir enlever toutes les visses qui retiennent le clavier ainsi que le repose-poignets (enlevez aussi la batterie et/ou le chargeur hein). Une fois libre, passez un tournevis plat, un mediator, ou votre CB pour passer sous le clavier et le soulever, tirez-le ensuite vers vous légèrement, enfin, débranchez-le (c'est pas obligatoire mais c'est plus confortable) Débranchez également la pile CMOS, il s'agit du rond jaune, enlevez le scotch noir doucement puis tirez légèrement sur le câble en direction de l'écran. Tel un chirurgien qui s'aprête à effectuer une opération à coeur ouvert, votre Thinkpad X200 est là, démuni, passez alors la pince SOP au-dessus du chip BIOS qui se trouve en bas de la machine, à gauche du haut-parleur, puis branchez les câbles en suivant les diagrammes celui-ci s'applique à mon cas, ayant un BIOS à 16 broches)

  • Note : bien que les sources indiquent que ce diagramme est faux , il a fonctionné pour moi
  • Note 2 : Il y avait sur ma carte mère un plastique protegeant les composants des liquides, il n'est pas nécessaire de le découper pour placer le clip SOP

Si tout est branché et la pince fermement placée sur la puce BIOS, vous pouvez booter le Raspberry Pi.

ATTENTION

spispeed étant défini à sa valeur la plus basse pour garantir une lecture et écriture avec le moins de risques possibles chaque commande peut prendre entre 10 et 15 minutes, NE DÉBRANCHEZ SURTOUT PAS LA PINCE SOP Si flashrom dit flashrom couldn't determine automaticaly [...], vérifiez vos branchements, prenez votre temps.

Voici toutes les commandes à taper :

pi@raspberry:~ $ flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -r factory1 -V 
pi@raspberry:~ $ flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -r factory1 -V -c MX25L6405
pi@raspberry:~ $ flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -r factory2 -V -c MX25L6405 
pi@raspberry:~ $ flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -r factory3 -V -c MX25L6405 
pi@raspberry:~ $ sha512sum factory* 
pi@raspberry:~ $ flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -w <fichierBIOSGénéré> -V -c MX25L6405 
pi@raspberry:~ $ flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -r factory1 -V 

L'important est que les 3 hash de vos dump soient les mêmes, si ce n'est pas le cas, effacez les dump et recommencez.

pi@raspberrypi:~ $ sha512sum factory* 
0551cc4ff2e72220d3da9a727864e200259968e6db049b946dcea8c9065108545a15795702f03c521bd11eacd3ce11d3eb7b5b9f7ed28299b777bd2829419dd1 factory1 
0551cc4ff2e72220d3da9a727864e200259968e6db049b946dcea8c9065108545a15795702f03c521bd11eacd3ce11d3eb7b5b9f7ed28299b777bd2829419dd1 factory2 
0551cc4ff2e72220d3da9a727864e200259968e6db049b946dcea8c9065108545a15795702f03c521bd11eacd3ce11d3eb7b5b9f7ed28299b777bd2829419dd1 factory3 
pi@raspberrypi:~ $ flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -w <fichierBIOSGénéré> -V -c MX25L6405 
flashrom p1.0-85-gb2154e8 on Linux 4.14.52-v7+ (armv7l) 
flashrom is free software, get the source code at https://flashrom.org 
flashrom was built with GCC 6.3.0 20170516, little endian Command line (7 args): flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=128 -w Using clock_gettime for delay 
loops (clk_id: 1, resolution: 1ns). 
Initializing linux_spi programmer Using device /dev/spidev0.0 Using 128 kHz clock linux_spi_init: 
Using value from /sys/module/spidev/parameters/bufsiz as max bu linux_spi_init: max_kernel_buf_size: 4096 
The following protocols are supported: 
SPI.
 Probing for Macronix MX25L6405, 8192 kB: probe_spi_rdid_generic: id1 0xc2, id2 
Found Macronix flash chip "MX25L6405" (8192 kB, SPI) on linux_spi. 
Chip status register is 0x00. 
Chip status register: Status Register Write Disable (SRWD, SRP, ...) is not set 
Chip status register: Bit 6 is not set 
Chip status register: Block Protect 3 (BP3) is not set 
Chip status register: Block Protect 2 (BP2) is not set 
Chip status register: Block Protect 1 (BP1) is not set 
Chip status register: Block Protect 0 (BP0) is not set 
Chip status register: Write Enable Latch (WEL) is not set 
Chip status register: Write In Progress (WIP/BUSY) is not set 
Reading old flash chip contents... done. 
Erasing and writing flash chip... 
Trying erase function 0... 0x000000-0x00ffff: ERASE FAILED! 
Reading current flash chip contents... done. 
Looking for another erase function Trying erase function 1... 0x000000-0x00ffff:EW, 0x010000-0x01ffff:EW, 0x020000 ffff:EW, 0x0a0000-0x0affff:EW, 0x0b0000-0x0bffff:EW, 0x0c0000-0x0cffff:EW, 0x0d 4ffff:E, 
0x150000-0x15ffff:E, 0x160000-0x16ffff:E, 0x170000-0x17ffff:E, 0x18000 , 0x200000-0x20ffff:E, 0x210000-0x21ffff:E, 0x220000-0x22ffff:E, 0x230000-0x23f 000-0x2bffff:S, 0x2c0000-0x2cffff:S, 
0x2d0000-0x2dffff:S, 0x2e0000-0x2effff:S, 6ffff:S, 0x370000-0x37ffff:S, 0x380000-0x38ffff:S, 0x390000-0x39ffff:S, 0x3a000 , 0x420000-0x42ffff:S, 0x430000-0x43ffff:S, 0x440000-0x44ffff:S, 
0x450000-0x45f 000-0x4dffff:S, 0x4e0000-0x4effff:S, 0x4f0000-0x4fffff:S, 0x500000-0x50ffff:S, 8ffff:S, 0x590000-0x59ffff:S, 0x5a0000-0x5affff:S, 0x5b0000-0x5bffff:S, 0x5c000 , 
0x640000-0x64ffff:E, 0x650000-0x65ffff:E, 0x660000-0x66ffff:E, 0x670000-0x67f 000-0x6fffff:E, 0x700000-0x70ffff:E, 0x710000-0x71ffff:E, 0x720000-0x72ffff:E, affff:S, 0x7b0000-0x7bffff:E, 
0x7c0000-0x7cffff:S, 0x7d0000-0x7dffff:E, 0x7e000 
Erase/write done. 
Verifying flash... VERIFIED.

Vous êtes maintenant tiré d'affaire ! Voici quelques notes post-flash.

  • Il vous faut de la RAM en 2*4 chip, autrement la machine ne démarre pas
  • Il est possible d'avoir 2 barettes de RAM avec des capacités différentes
  • Pensez tout de même à acquérir une carte miniPCI avec un chip libre (cf : https://libreboot.org/docs/hardware/#recommended-wifi-chipsets)
  • J'avais pleins de problèmes de certificat SSL (openssl couldn't find location) parce que la date et l'heure de mon système n'étaient pas à jour, impossible de naviguer ou de mettre à jour, un simple
date -s "Sat Jul 14 15:30:33 CEST 2018" ; hwclock --systohc

ainsi qu'un reboot résoudront le problème.


Si vous avez des questions, vous pouvez me contacter en DM sur Twitter et je ferai de mon mieux pour vous aider

Modifier et mettre à jour Libreboot

Je l'ai déjà dit plus haut, j'utilise personnellement le kernel linux-libre-hardened, qui rend parfaitement impossible la lecture de /dev/mem, si c'est également votre cas, faites vos modifications normalement puis utilisez une liveUSB pour flasher.

Je vous conseille très fortement de conserver l'image ROM que vous venez de flasher comme base pour les modifications à venir, en effet, si vous avez suivi correctement les autres guides, votre adresse MAC est inscrite dans ce fichier.

Dans mon exemple, le fichier BIOS est bios.rom

Nous aurons besoin des outils Libreboot

Desactiver le bluetooth

On commence par vérifier si l'option est bien présente et référencée dans l'image du BIOS

nvramtool -C /chemin/vers/bios.rom -a

On voit bien bluetooth = Enable

Pour savoir quelles options prend le paramètres bluetooth

nvramtool -C /chemin/vers/bios.rom -e bluetooth
Disable
Enable

Y'a plus qu'à

nvramtool -C /chemin/vers/bios.rom -w bluetooth=Disable

Vous pouvez refaire un nvramtool -a pour vous assurer que l'option a bien été prise en compte.

sudo ./flash update /chemin/vers/bios.rom

Modifier le code de GRUB

Un poil plus compliqué, mais ça va bien se passer

L'idée va être d'extraire un fichier de l'image du BIOS, le modifier, puis le remettre dans l'image et re-flasher. Pour des raisons de sécurité assez évidente, on va d'abord modifier grubtest.cfg puis, si tout se passe bien, refaire les manipulations sur grub.cfg

Ici, on va remonter l'option de boot en AHCI en première position, comme ça je pourrais booter plus rapidement

cbfstool /chemin/vers/bios.rom print
Performing operation on 'COREBOOT' region...
Name                           Offset     Type         Size
cbfs master header             0x0        cbfs header  32
config                         0x80       raw          357
revision                       0x240      raw          560
cmos.default                   0x4c0      cmos_default 256
cmos_layout.bin                0x600      cmos_layout  1944
fallback/dsdt.aml              0xe00      raw          13374
bootorder                      0x42c0     raw          15
etc/show-boot-menu             0x4340     raw          8
etc/ps2-keyboard-spinup        0x4380     raw          8
lbversion                      0x43c0     raw          10
grub.cfg                       0x4440     raw          4623
grubtest.cfg                   0x56c0     raw          4615
(empty)                        0x6900     null         38488
fallback/romstage              0xff80     stage        55380
fallback/ramstage              0x1d840    stage        65909
fallback/payload               0x2da00    payload      60319
img/grub2                      0x3c600    payload      579230
background.jpg                 0xc9d00    raw          233004
(empty)                        0x102b80   null         7314776
bootblock                      0x7fc900   bootblock    1480

On voit bien grubtest.cfg, il va falloir l'extraire maintenant.

cbfstool /chemin/vers/bios.rom extract -n grubtest.cfg -f grubtest.cfg

Le fichier est extrait dans le dossier en cours. Je vais simplement copier le bloc "menuentry 'Search ISOLINUX menu (AHCI) [a]'" et le placer au-dessus de "menuentry 'Load Operating System (incl. fully encrypted disks) [o]'" Puis le renommer "menuentry 'The Game'" (C'est mon BIOS, je fais ce que je veux :-)) et bien sûr on oublie pas de sauvegarder.

On va d'abord effacer le fichier grubtest.cfg original qui se trouve dans l'image du BIOS, pour ce faire

cbfstool /chemin/vers/bios.rom remove -n grubtest.cfg

Ensuite, on va y copier notre grubtest modifié

cbfstool /chemin/vers/bios.rom add -n grubtest.cfg -f grubtest.cfg -t raw

Notre image est prête, on va pouvoir la flasher

sudo ./flash update /chemin/vers/bios.rom

Maintenant il faut tester notre nouvelle configuration, démarrez l'ordinateur et appuyez sur t (ou allez sur Load Test Configuration puis faites entrée)

Si tout vous semble bon, vous pouvez appliquer les modifications à grub.cfg comme suit

mv grubtest.cfg grub.cfg
cbfstool /chemin/vers/bios.rom remove -n grub.cfg
cbfstool /chemin/vers/bios.rom add -n grub.cfg -f grub.cfg -t raw
sudo ./flash update /chemin/vers/bios.rom

De cette manière, vous pouvez complètement modifier le BIOS, y compris l'image de fond (image au format JPEG, 228ko max 1280*800 pixels pour les dimensions)

Sources:

  • https://www.reddit.com/r/libreboot/comments/7dajn6/x200_libreboot_tutorial_for_raspberry_pi_with/
  • https://www.flashrom.org/Supported_hardware#Supported_flash_chips
  • https://libreboot.org/docs/hardware/x200.html
  • https://www.youtube.com/watch?v=CyxgYnOcsTw
  • https://libreboot.org/docs/gnulinux/grub_cbfs.html

Comments !