Une clef USB multi-OS
Dans le cadre de mon nouveau boulot, je viens de recevoir un nouvel ordinateur portable… sous Windows 10. Je souhaiterais le basculer rapidement sur un Linux. Cependant j’hésite beaucoup entre plusieurs distrubutions Linux bien que je pense finalement choisir une Debian.
Au début, je voulais me créer autant de live-usb que de distributions à tester pour les comparer un peu… Et puis, étant donné la taille de ma clef USB (128 GB), j’ai réalisé qu’il était préférable de mettre tous les systèmes sur la même clef et de les choisir au démarrage via GRUB.
Ca tombe bien, ça faisait quelques temps que j’avais envie de me familiariser avec GRUB :)
Au début, je n’avais pas trop d’idée sur la façon de procéder. J’imaginais un découpage de la clef avec une partition par système et un GRUB tout au début qui pointerait vers les différents systèmes. Et puis j’ai découvert que GRUB pouvait booter des images iso directement ce qui est super. C’est parti pour mettre les mains dans le camboui !
Installation de Grub
Je souhaite avoir une clef bootable directement en UEFI sans passer par la retro-comptibilité BIOS. Je créé donc plusieurs partitions sur ma clef :
- une minuscule partition de 9 MiB pour contenir l’amorce UEFI
- une partition de boot plus conséquente (environ 50 GB), qui contiendra l’essentiel de GRUB ainsi que les différentes images que je serais amené à utiliser (pour référence, l’image de la live-usb Debian fait 2.7 GB). Autant rester large ici, si d’aventure je souhaite rajouter d’autres images
- le reste de la clef sera utilisée comme partition générique data en ext4 pour stocker d’éventuelles données
On identifie tout d’abord la clef à l’aide de fdisk
:
$ sudo fdisk -l
...
Disque /dev/sdc : 114,6 GiB, 123048296448 octets, 240328704 secteurs
Modèle de disque : SanDisk 3.2Gen1
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : gpt
Identifiant de disque : D06B2C20-7C48-4D5E-9999-85798D862CF1
Notons dès présent l’identifiant de disque, il pourra nous être utile par la suite !
On utilise parted
pour créer la table de partition gpt ainsi que nos trois partitions.
(parted) mklabel gpt
(parted) mkpart dmuefi 1MiB 10MiB
(parted) mkpart dmboot 10MiB 50GiB
(parted) mkpart dmdata 50GiB 100%
On ajoute le flag esp
à la partition UEFI afin qu’elle soit repérée au démarrage de l’ordinateur :
(parted) set 1 esp on
On vérife ensuite que nos trois partitions sont bien créées comme on le souhaitait :
(parted) print
Number Start End Size File system Name Flags
1 1049kB 10,5MB 9437kB dmuefi boot, esp
2 10,5MB 53,7GB 53,7GB dmboot
3 53,7GB 123GB 69,4GB dmdata
Il nous faut ensuite créér les systèmes de fichier : FAT pour la partition UEFI1, EXT4 pour les deux autres :
$ mkfs.fat /dev/sdc1
$ mkfs.ext4 /dev/sdc2
$ mkfs.ext4 /dev/sdc3
On note ensuite les UUID de ces partitions à l’aide de la commande blkid
:
$ sudo blkid /dev/sdc?
/dev/sdc1: SEC_TYPE="msdos" UUID="82D5-6F7A" TYPE="vfat" PARTLABEL="dmuefi" PARTUUID="a2e27682-0048-4586-b498-b295d3198091"
/dev/sdc2: UUID="0464d76d-a5b7-4d64-86c8-8604b57c0273" TYPE="ext4" PARTLABEL="dmboot" PARTUUID="bf17dce5-1359-43b3-8335-b88bd3eb78d4"
/dev/sdc3: UUID="f7302fe1-e9c6-4e63-ad01-27e543597071" TYPE="ext4" PARTLABEL="dmdata" PARTUUID="46f01b0a-24bc-4c40-bbc0-f8ab9c801283"
Partition | Type | PARTLAB | UUID | PARTUUID |
---|---|---|---|---|
sdc1 | UEFI | dmuefi | 82D5-6F7A | a2e27682-0048-4586-b498-b295d3198091 |
sdc2 | BOOT | dmboot | 0464d76d-a5b7-4d64-86c8-8604b57c0273 | bf17dce5-1359-43b3-8335-b88bd3eb78d4 |
sdc3 | DATA | dmdata | f7302fe1-e9c6-4e63-ad01-27e543597071 | 46f01b0a-24bc-4c40-bbc0-f8ab9c801283 |
Avant de passer à l’installation de GRUB proprement dite, on vérifie qu’on démarre bien en 64 bits :
$ more /sys/firmware/efi/fw_platform_size
64
On installe ensuite GRUB sur la clef. Comme il ne s’agit pas d’une installation système, on doit lui indiquer les répertoires efi et boot à l’aide des options --efi-directory
et boot-directory
. On spécifie également la plateforme (ici on est donc en 64 bits). Initialement, j’utilisais l’option supplémentaire --removable
car l’installation se fait sur une clef amovible (je ne suis pas sûr d’avoir bien compris les détails de ce que cela impliquait pour Grub). Néanmoins, cela ne fonctionnait pas. Après quelques tatônnements, j’ai trouvé que les deux options --force-extra-removable
et --no-nvram
résolvaient le soucis. Enfin --recheck
supprime la table des correspondances des disques si cette dernière existait déjà.
$ sudo grub-install --target=x86_64-efi --recheck --force-extra-removable --no-nvram --efi-directory="./efi" --boot-directory="./boot"
Installation pour la plate-forme x86_64-efi.
Installation terminée, sans erreur.
On constate que les fichiers ont bien été créés
$ tree efi/
efi/
└── EFI
└── BOOT
├── BOOTX64.CSV
├── BOOTX64.EFI
├── fbx64.efi
├── grub.cfg
├── grubx64.efi
└── mmx64.efi
2 directories, 6 files
$ tree data/
data/
├── boot
│ └── grub
│ ├── fonts
│ │ └── unicode.pf2
│ ├── grubenv
│ ├── locale
│ │ ├── ast.mo
│ │ ├── ...
│ │ ├── fr.mo
│ │ ├── ...
│ │ └── zh_TW.mo
│ └── x86_64-efi
│ ├── acpi.mod
│ ├── ...
│ ├── gfxmenu.mod
│ ├── gfxterm_background.mod
│ ├── gfxterm_menu.mod
│ ├── gfxterm.mod
│ ├── gptsync.mod
│ ├── grub.efi
│ ├── ...
│ └── zfs.mod
└── lost+found [error opening dir]
6 directories, 308 files
A partir de ce stade, si on redémarre et qu’on boote sur la clef, on arrive à un GRUB minimal qui affiche une invite de commande en GRUB shell.
Mais redémarrer le pc à chaque fois qu’on bouge une virgule sur la clef, c’est long et fastidieux. Pour s’éviter cela, on va utiliser une machine virtuelle minimaliste : qemu
. Le soucis est que cette dernière ne gère pas nativement l’amorçage en UEFI. Le site papy-tux décrit les étapes pour rajouter cette possibilité. Au final après quelques manipulations, on peut désormais démarrer en UEFI !
$ sudo qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd /dev/sdc
Paramètrage de grub.cfg et ajout des images
Sur la partition efi, le fichier grub.cfg attire notre attention. Voici son contenu :
$ more efi/EFI/debian/grub.cfg
search.fs_uuid 0464d76d-a5b7-4d64-86c8-8604b57c0273 root hd2,gpt2
set prefix=($root)'/grub'
configfile $prefix/grub.cfg
La partition d’UUID 0464d76d-a5b7-4d64-86c8-8604b57c0273
correspond à dmboot
, identifiée par mon système par sdc2
(rappelons-nous le retour de blkid
plus haut). On comprend donc que l’amorçage UEFI, qui contient le noyau de GRUB, va chercher le reste sur la partition dmboot
et va
Les paramètres du menu affiché par notre grub seront donc définis dans boot/grub/grub.cfg. Mais ce fichier n’existe pas, il faut donc le créér. Il va consister en une suite de menu-entry
, chacun définissant comment démarrer une live-usb donnée. Pour savoir comment définir ces entrées, il est nécessaire de monter les live-usb pour comprendre comment elles ont été construites.
Analyse et ajout de la live-usb Debian
Commençons par ma chouchoute : la live-usb Debian 11. Un file
nous permet de connaître le format du fichier et quelques caractéristiques macroscopiques : ici on apprend que la table des partitions est DOS/MBR (pour avoir une clef compatible avec la majorité des systèmes) et que la partition de démarrage est la deuxième.
$ file debian-live-11.3.0-amd64-gnome.iso
debian-live-11.3.0-amd64-gnome.iso: DOS/MBR boot sector; partition 2 : ID=0xef, start-CHS (0x3ff,254,63), end-CHS (0x3ff,254,63), startsector 1536, 5226 sectors
Un fdisk
ou un parted
permettent d’en savoir un peu plus. Le retour de fdisk
reproduit ci-dessous nous confirme que la table des partitions est au format DOS et que la partition EFI est la deuxième. La première partition est une mystérieuse partition vide
$ fdisk -l debian-live-11.3.0-amd64-gnome.iso
Disque debian-live-11.3.0-amd64-gnome.iso : 2,6 GiB, 2804809728 octets, 5478144 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0x10612bc7
Périphérique Amorçage Début Fin Secteurs Taille Id Type
debian-live-11.3.0-amd64-gnome.iso1 * 0 5478143 5478144 2,6G 0 Vide
debian-live-11.3.0-amd64-gnome.iso2 1536 6761 5226 2,6M ef EFI (FAT-12/16/32)
Le retour de parted
nous donne peu ou prou les mêmes indications sauf que la première partition n’apparaît pas :
$ sudo parted debian-live-11.3.0-amd64-gnome.iso print
Model: (file)
Disk /data/work/iso/debian-live-11.3.0-amd64-gnome.iso: 2805MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
2 786kB 3462kB 2676kB primary esp
Je n’ai pas creusé plus en détail tout cela, car ce que je souhaite c’est récupérer l’emplacement du noyau et de l’initrd. Pour cela, il est nécessaire de monter l’iso dans un répertoire temporaire.
$ sudo mount -o loop debian-live-11.3.0-amd64-gnome.iso ./Debian
Il y a plusieurs fichiers de configuration de Grub, celui qui nous intéresse est boot/grub/grub.cfg
, il contient notamment :
menuentry "Debian GNU/Linux Live (kernel 5.10.0-13-amd64)" {
linux /live/vmlinuz-5.10.0-13-amd64 boot=live components splash quiet "${loopback}"
initrd /live/initrd.img-5.10.0-13-amd64
}
Bingo ! Nous avons l’emplacement du noyaux Linux (repéré par la directive GRUB linux
) ainsi que l’initrd (repéré par la directive GRUB initrd
). Un file
bien placé nous renseigne sur les caractéristiques de ces fichiers, il est désormais clair que vmlinuz-5.10.0-13-amd64
est un noyau Linux.
$ file vmlinuz-5.10.0-13-amd64
vmlinuz-5.10.0-13-amd64: Linux kernel x86 boot executable bzImage, version 5.10.0-13-amd64 (debian-kernel@lists.debian.org) #1 SMP Debian 5.10.106-1 (2022-03-17), RO-rootFS, swap_dev 0x6, Normal VGA
$ file initrd.img-5.10.0-13-amd64
initrd.img-5.10.0-13-amd64: gzip compressed data, was "mkinitramfs-MAIN_pqyD8S", last modified: Sat Mar 26 16:00:28 2022, from Unix, original size 166584320
Au passage cest fichiers sont relativement petits : 6.6 Mo pour le premier et 47 Mo pour le second. Dans ce même répertoire live, un autre fichier a néanmoins retenu mon attention de part sa grande taille : filesystem.squashfs
et ses quelques 2.3 Go (soit la quasi-totalité des 2.7 Go de notre fichier iso !). Squashfs est un système de fichier ultra compressé en lecture seule, on peut utiliser mount
pour voir un peu ce qu’il y a là dedans :
$ sudo mount filesystem.squashfs /var/tmp/test_squashfs -t squashfs -o loop
Bingo ! On y découvre l’arborescence de notre Linux ! Toutes les librairies et tous les binaires utilisés par la live-usb sont présents ici, et c’est là que se cachent la quasi totalité de l’espace utilisé par la clef !
$ ll /var/tmp/test_squashfs/
total 0
lrwxrwxrwx 1 root root 7 mars 26 16:22 bin -> usr/bin
drwxr-xr-x 2 root root 144 mars 26 17:00 boot
drwxr-xr-x 4 root root 191 mars 26 17:00 dev
drwxr-xr-x 135 root root 3850 mars 26 17:08 etc
drwxr-xr-x 2 root root 3 mars 19 14:46 home
lrwxrwxrwx 1 root root 31 mars 26 16:23 initrd.img -> boot/initrd.img-5.10.0-13-amd64
lrwxrwxrwx 1 root root 31 mars 26 16:23 initrd.img.old -> boot/initrd.img-5.10.0-13-amd64
lrwxrwxrwx 1 root root 7 mars 26 16:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 mars 26 16:22 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 mars 26 16:22 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 mars 26 16:22 libx32 -> usr/libx32
drwxr-xr-x 2 root root 3 mars 26 16:22 media
drwxr-xr-x 2 root root 3 mars 26 16:22 mnt
drwxr-xr-x 2 root root 3 mars 26 16:22 opt
drwxr-xr-x 2 root root 3 mars 19 14:46 proc
drwx------ 3 root root 60 mars 26 16:56 root
drwxr-xr-x 9 root root 152 mars 26 17:00 run
lrwxrwxrwx 1 root root 8 mars 26 16:22 sbin -> usr/sbin
drwxr-xr-x 2 root root 3 mars 26 16:22 srv
drwxr-xr-x 2 root root 3 mars 19 14:46 sys
drwxrwxrwt 2 root root 3 mars 26 17:01 tmp
drwxr-xr-x 14 root root 253 mars 26 16:22 usr
drwxr-xr-x 11 root root 172 mars 26 16:22 var
lrwxrwxrwx 1 root root 28 mars 26 16:23 vmlinuz -> boot/vmlinuz-5.10.0-13-amd64
lrwxrwxrwx 1 root root 28 mars 26 16:23 vmlinuz.old -> boot/vmlinuz-5.10.0-13-amd64
Mais refermons notre parenthèse et retournons à notre clef. Sur la partition de boot, on créé un repertoire iso et nous y plaçons notre image Debian.
$ sudo cp ./boot/iso
$ sudo cp debian-live-11.3.0-amd64-gnome.iso ./boot/iso
On créé ensuite ./boot/grub/grub.cfg
et on y défini notre première entrée :
$ more grub.cfg
menuentry "Debian de Donut" {
set iso_path="/iso/debian-live-11.3.0-amd64-gnome.iso"
search --set=root --file $iso_path
loopback loop $iso_path
echo "Lancement de l'iso de Debian en cours..."
linux (loop)/live/vmlinuz-5.10.0-13-amd64 iso-scan/filename="${iso_path}" boot=live components splash quiet "${loopback}"
initrd (loop)/live/initrd.img-5.10.0-13-amd64
}
NB : j’ai donc repris exactement les mêmes entrées que dans le grub de l’iso mais j’ai rajouté l’option iso-scan/filename="${iso_path}"
sans laquelle le menu Grub refuse de s’afficher. Donc Grub de toute évidence teste la validité de chaque entrée avant d’afficher le menu ?
Par ailleurs, il faut lancer qemu
avec assez de ram sinon l’iso refuse de se lancer :
$ sudo qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -m 2048M /dev/sdc
En l’état :
BusyBox v1.30.1 (Debian 1:1.30.1-6+b3) built-in shell (ash)
Enter 'help' for a list of built-in commands.
(initramfs) exit
No supported filesystem images found at /live
xdg-open /usr/share/desktop-base/futureprototype-theme/grub/grub-4x3.png
Essai suggéré par Pascal : partition efi en 2eme position
(parted) mklabel gpt
(parted) mkpart pvboot 1MiB 4GiB (parted) mkpart pvuefi 5GiB 6GiB (parted) set 2 esp on
$ sudo mkfs.ext4 /dev/sdX1 $ sudo mkfs.fat -F32 /dev/sdX2
$ sudo mount /dev/sdh1 /home/pierre/test/mnt/efi
$ sudo mount /dev/sdc1 ./boot $ sudo mount /dev/sdc2 ./efi
sudo grub-install –target=x86_64-efi –bootloader-id=”Donut-UEFI” –recheck –removable –efi-directory=”./efi” –boot-directory=”./boot”
Tuto utile ??? https://teejeetech.medium.com/linux-multiboot-with-btrfs-luks-and-efi-part-1-9b2325494e0f
Spécification UEFI https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf
Options suggérées par Pascal
sudo grub-install –target=x86_64-efi –bootloader-id=”Donut-UEFI” –recheck –force-extra-removable –no-nvram –efi-directory=”./efi” –boot-directory=”./boot”
A REMETTRE AU PROPRE Partition UEFI après grub-install : 7.9 M
ISO Ubuntu : 3.5 GB ISO Debian : 2.7 GB
-
la partition étant très petite, elle sera en FAT16 et non pas en FAT32. Sur ma machine, cela fonctionne mais il se peut que cela pose problème selon la version de l’UEFI et le modèle de la carte mère. ↩