+++

title = "Passer un disque fait pour le BIOS en UEFI avec BTRFS"
date = 2018-09-14
aliases = [ "post/2018/09/14/Passer-un-disque-fait-pour-le-BIOS-en-UEFI-avec-BTRFS"]
[taxonomies]
tags = [ "système", "btrfs" ]
+++

Ça a pas l'air compliqué comme ça, mais en fait, c'est hyper chiant…

<!-- more -->

J'ai changé un très vieux PC portable récemment (12 ans !) vers un truc un peu plus neuf (seulement 3 ans) et je ne voulais pas réinstaller le système au complet (flemme). Bon en vérité, j'aurais très bien pu tout réinstaller et je n'aurais pas mis tant de temps que ça mais je n'avais vraiment pas envie de me bouger.

Problème : cette nouvelle machine ne reconnaît pas mon disque. Pour une raison assez simple : il a été formaté avec une table de partitions standard et pas UEFI. Donc pas moyen de démarrer quoique ce soit, je suis obligé de booter sur une clé USB qui contient GRUB.

J'aurais pu en rester là, mais ça n'aurait pas été drôle. Mon disque ne contient même pas de partition en fait : c'est un système BTRFS directement installé sur `/dev/sda` (c'est moche, mais ça marche).

À partir de ce moment, il y a deux possibilités :
* soit on possède un autre disque, et on peut tenter un `btrfs replace` dans un sens, reformater le disque et faire un `btrfs replace` dans l'autre sens ;
* soit, et c'est mon cas, on ne dispose pas de second disque auquel cas on va utiliser les *snapshots* BTRFS et la fonction *send/receive* pour sauvegarder l'ensemble du disque sur une machine distante.

Et du coup, autant que je documente le processus, ça pourrait toujours servir à d'autres.

#  Le bon système de fichiers, il snapshot…

Première étape essentiellement : faire des snapshots en lecture seule de l'ensemble des sous-volumes BTRFS. Pour cela rien de plus simple, il suffit de monter le disque BTRFS à la racine (si ton */* n'est pas à la racine) ou de créer carrément un sous-volume pour les stocker. Personnellement, mes sous-volumes ressemblent à ça :

```
# mount -t btrfs -o subvolid=0 /dev/sda /mnt
# btrfs sub list -a /mnt
ID 257 gen 202952 top level 5 path __root
ID 258 gen 202952 top level 5 path __home
ID 300 gen 202932 top level 257 path <FS_TREE>/__root/opt
ID 302 gen 202952 top level 257 path <FS_TREE>/__root/usr
ID 303 gen 202953 top level 257 path <FS_TREE>/__root/var
ID 801 gen 148907 top level 303 path <FS_TREE>/__root/var/lib/machines
ID 999 gen 194266 top level 303 path <FS_TREE>/__root/var/lib/portables
```

C'est donc pour moi assez simple : il faut créer un sous-volume cliché en __lecture seule__ pour chaque volume (sauf machines et portables qui ne me servent à rien et qui seront recréés par Docker/LXC) :
```
# btrfs subvolume snapshot -r /mnt/__home /mnt/__ro_home@$(date -I)
```

Opération à répéter pour chaque sous-volume. À noter qu'il faut impérativement tout mettre à la racine, même pour les sous-volumes *usr* et *var*.

À partir de ce moment-là, on peut commencer à le balancer sur une autre machine dans une autre partition BTRFS.

#  Et un snapshot pour la 12 !

Alors évidemment (ou plutôt malheureusement), il va falloir être *root* sur les deux machines : impossible de créer un snapshot si l'on n'est pas root sur la machine cible et imposible de lire complètement un snapshot pour la même raison sur la machine source. Pour le reste, c'est relativement facile.

J'ai commencé par créer un sous-volume cible sur une autre machine (*baybay-ponay* en l'occurence) :
```
# btrfs subvolume create /home/pinkypie/
```

Depuis la machine source (*pinkypie*), j'ai ensuite envoyé chacun des snapshots :

```
# btrfs send /mnt/__ro_home@2018-09-14/ | ssh root@baybay-ponay btrfs receive /home/pinkypie/
# btrfs send /mnt/__ro_var@2018-09-14/ | ssh root@baybay-ponay btrfs receive /home/pinkypie/
[…]
```

> La date est complètement optionnelle hein, c'est juste pour se repérer plus facilement…

Avec un peu de patience, on obtient donc un transfert binaire absolument parfait de l'ensemble des partitions du système. On peut alors effacer complètement le disque d'origine, la sauvegarde du système est totalement réalisée.

#  Reformatage du disque

À partir de ce moment-là, la suite des opérations se passent sur un disque de boot (Archlinux en l'occurence mais en théorie n'importe quel disque de boot doit faire l'affaire à condition que BTRFS et UEFI soit supporté dessus).

Comme ma machine cible est une machine UEFI 100%, nous allons utiliser `fdisk` pour la repartitionner en GPT (__ah ah ah ah__). Pour cela, on va se servir de l'option g dans le menu principal :
```
# fdisk /dev/sda

Bienvenue dans fdisk (util-linux 2.32.1).
Les modifications resteront en mémoire jusqu'à écriture.
Soyez prudent avant d'utiliser la commande d'écriture.


Commande (m pour l'aide) : g
Une nouvelle étiquette de disque GPT a été créée (GUID : LOLILOL).
L'ancienne signature iso9660 sera enlevée par une commande d'écriture.
```

Il suffit donc de créer une partition de type *EFI System* (256M doivent largement suffire, la bonne pratique recommande environ 100Mio), puis une seconde partition de type *Linux filesystem* pour le reste du disque.

On valide l'écriture et c'est parti mon kiki.

#  Recréation d'un système de fichiers BTRFS

Là encore, c'est finalement relativement simple :
```
# mkfs.btrfs --label GG /dev/sda2
# mount LABEL=GG /mnt
```

On peut alors aller récupérer les données depuis *baybay-ponay* où on les avait entreposées bien au chaud :
```
# ssh root@baybay-ponay btrfs send /home/pinkypie/__ro_home@2018-09-14 | btrfs receive /mnt
```

On va alors récupérer un sous-volume en lecture seule. Pour le rendre inscriptible, rien de plus simple :
```
# btrfs subvolume snapshot /mnt/__ro_home@2018-09-14 /mnt/__home
# btrfs subvolume delete /mnt/__ro_home@2018-09-14
```

Et à ce moment, on récupère bien une partition parfaitement utilisable en écriture ! Il suffit donc de reprendre la même opération pour chaque sous-volume et de réorganiser ça bien gentiment.

#  Réinstallation de ce qu'il faut sous Archlinux

Jusqu'à présent, nous avons fait des choses relativement universelles : BTRFS, partitionnement GPT (__ah ah ah ah__) et *send/receive*. Cette dernière partie est plus spécifique à Archlinux et est surtout là pour me servir de pense-bête.

Après avoir modifié correctement `/etc/fstab`, et monter toutes les partitions au bon endroit, on peut entamer la modification en profondeur du système pour le rendre compatible UEFI. Il faut donc supprimer le dossier `/boot@ de la racine du système cible, formater la partition *EFI System* précédemment créée en FAT32 et la monter au bon endroit :

```
# rm -rf /mnt/boot
# mkfs.vfat /dev/sda1
# mount /dev/sda1 /mnt/boot
```

Il faut ensuite balancer une commande *grub* bien spécifique pour créer tous les fichiers nécessaires au boot UEFI du système :

```
# grub-install --target=x86_64-efi --efi-directory=/mnt/boot --bootloader-id=GRUB
```

Voilà, maintenant il devrait y avoir tout ce qu'il faut au niveau de la carte mère pour arriver à booter correctement cette Archlinux. Néanmoins, comme nous avons supprimé la partition `/boot`, il va quand même falloir penser à réinstaller deux ou trois bricoles :

```
# for f in sys dev proc; do mount --bind /${f} /mnt/${f}
# chroot /mnt
# pacman -S linux
```

`pacman` va s'occuper de tout réinstaller bien gentiment à la bonne place avec les bonnes permissions et tout le toutim.

On redémarre, on va se chercher une bière bien méritée et on peut retourner glander tranquillement devant son PC en UEFI.
