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

Amorçage avec qemu

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

  1. 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.