Qu’est-ce que GRUB ?
Lors du démarrage d’un ordinateur, le premier logiciel lancé est le firmware, c’est à dire le BIOS ou l’UEFI. Celui-ci invoque l’étape suivante du démarrage. Cette étape suivante est le lancement du noyau d’un système d’exploitation ou, plus souvent, d’un bootloader.
Le rôle du bootloader est de charger l’étape suivante du démarrage. Souvent, l’étape qui suit le bootloader est la chargement du noyau d’un système d’exploitation. Cependant, il est possible de chaîner les bootloader.
Par exemple, dans le cas du dual-boot Windows et Linux (ou tout autre système d’exploitation), lorsqu’on démarre sous Windows le premier bootloader ne fait que passer la main au bootloader fourni par Windows. Certains bootloaders permettent à l’utilisateur de choisir quelle est l’étape suivant du démarrage de l’ordinateur.
Dans cet article nous allons étudier les bases de la configuration de GRUB.
GRand Unified Bootloader est un bootloader du projet GNU. Il est l’implémentation de référence de la spécification multiboot, il permet donc le démarrage sur plusieurs systèmes d’exploitation. Il existe en deux versions: GRUB et GRUB2. Ici, nous allons étudier uniquement GRUB2. Toute mention de GRUB fera référence à GRUB2.
GRUB est souvent mis en place lors de l’installation d’une distribution Linux. Il est configuré avec des paramètres fourni lors de l’installation du système. Cependant, GRUB est fait pour être configuré facilement après son installation. Il fourni ainsi des fichiers (éditable) qui servent à configurer son comportement.
Dans la suite de cet article, nous allons étudier l’architecture des fichiers de configuration de GRUB. GRUB possède un très grand nombre de points de personnalisation. Étudier en détail tout ces points prend beaucoup de temps. Nous allons donc nous concentrer sur la configuration d’une entrée du menu de choix du système d’exploitation.
Structure de la configuration de GRUB
Les fichiers de configuration de GRUB sont situé à plusieurs endroits.
/boot/grub/grub.cfg
C’est le fichier principal de configuration de GRUB. Comme il est indiqué en tête de ce fichier, il est déconseillé de modifier à la main grub.cfg
. En effet, il est généré automatiquement à partir d’autres fichiers de configuration. La génération de grub.cfg
se fait par l’intermédiaire de la commande update-grub
.
$ head -n 7 /boot/grub/grub.cfg # # DO NOT EDIT THIS FILE # # It is automatically generated by grub-mkconfig using templates # from /etc/grub.d and settings from /etc/default/grub #
/etc/grub.d/
Ce dossier contient des scripts de génération des entrées du menu de GRUB. Ces scripts peuvent être modifiés sans crainte d’être écrasés lors de l’appel à une commande de GRUB. Lors de la génération de /boot/grub/grub.cfg
, ces scripts vont être exécutés par update-grub
.
$ ls -l /etc/grub.d total 60 -rwxr-xr-x 1 root root 8871 23 nov. 21:42 00_header -rwxr-xr-x 1 root root 10400 23 nov. 21:42 10_linux -rwxr-xr-x 1 root root 10455 23 nov. 21:42 20_linux_xen -rwxr-xr-x 1 root root 11301 23 nov. 21:42 30_os-prober -rwxr-xr-x 1 root root 214 23 nov. 21:42 40_custom -rwxr-xr-x 1 root root 216 23 nov. 21:42 41_custom -rw-r--r-- 1 root root 483 23 nov. 21:42 README
Un fichier de ce dossier est un script shell
. Son nom suit le motif suivant: <numéro>_<nom>
. <numéro>
est un indice permettant à GRUB de déterminer l’ordre dans lequel il doit placer l’entrée dans le menu. Par exemple, l’entrée définie dans 10_linux
sera placée avant l’entrée 10_linux_xen
. Pour être pris en compte, un script doit être exécutable. Pour ajouter ou supprimer une entrée, il suffit donc de changer le droit d’exécution du fichier.
/etc/default/grub
C’est le fichier de configuration générale de GRUB. Il liste les options de configuration tels que le temps d’attente avant le démarrage automatique, l’entrée pré-séléctionnée, les options graphiques, … De même que pour /etc/grub.d/
, ce fichier peut être modifié et sert à générer grub.cfg
.
Exemple de configuration d’une entrée de GRUB
Intro
Dans cette partie, nous allons étudier les scripts de génération d’entrées du menu de GRUB. Nous allons donc nous concentrer sur les scripts de/etc/grub.d
et nous allons ignorer les options de configuration de /etc/default/grub
.
Cette étude est divisée en trois construction d’exemples: un exemple basique, un exemple de multiboot et un exemple de chainloading.
Lors de la modification d’une entrée du menu de GRUB, il est conseillé de garder une copie de sauvegarde de l’entrée originelle afin d’avoir un moyen de démarrer en cas d’erreur dans la configuration. Si la configuration de GRUB ne permet plus de démarrer, il reste possible de démarrer sur un live-cd afin de réparer GRUB.
Exemple basique
Tout d’abord, nous allons écrire un exemple basique d’entrée du menu de GRUB. Cette entrée va simplement lancer le noyau Linux. On crée le fichier 11_linux_boot_example. Ce fichier sera exécuté après 10_linux et avant 11_linux_xen. Ensuite il faut rendre le fichier exécutable avec, par exemple, chmod +x 11_linux_boot_example
.
Ensuite, il faut écrire le contenu du fichier. Notre script d’exemple est le suivant:
#!/bin/sh -e echo "Exemple d'entree" cat << EOF menuentry "Exemple" { set root=(hdX,Y) -- boot parameters -- } EOF
Les chaînes passées à la commande echo seront affichées lors de l’appel à la commande update-grub
.
Le contenu réel de l’entrée est tout le texte contenu entre la ligne cat << EOF
et la ligne EOF
. Une entrée possède un nom qui sera affiché dans le menu de GRUB. Ici, le nom de l’entrée est exemple. Le contenu de l’entrée est entre les accolades. Tout d’abord il faut indiquer à GRUB la partition dans laquelle le noyau est contenu. Pour cela, on donne une valeur à la variable root
. C’est fait grâce à la ligne set root=(hdX,Y)
. hdX
représente le disque dans lequel le noyau est localisé. Y
représente la partition. Les notations commencent à 1 (et non à 0). La première partition du premier disque est donc (hd1,1)
. Pour trouver la partition sur lequel le noyau est placé, on peut utiliser la commande lsblk -f
.
Par exemple, avec la commande suivante:
$ lsblk -f NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT sda ├─sda1 vfat BOOT 894B-7172 363,1M 27% /boot ├─sda2 swap b93f4e0e-a543-419f-9eca-327d80c8c568 [SWAP] ├─sda3 btrfs ROOT fb371bec-7d7d-4736-abfd-af67e7ed3294 4,5G 92% / ├─sda4 ntfs Récupération 3E5A60545A600ACB ├─sda5 vfat 9262-139F ├─sda6 └─sda7 ntfs 0646689846688A6F sdb ├─sdb1 btrfs HOME 0d7c2405-9ad1-4098-8575-93adc90c7a16 110,3G 84% /home └─sdb2 ntfs Data_Windows 32CE5F6FCE5F2A7D 79,7G 66% /media/Windows
On voit que le noyau est dans la partition sda1
qui est la première partition du premier disque. Dans GRUB, c’est donc représenté par (hd1,1)
. Souvent, les partitions /
et /boot
ne sont pas séparées. Si lsblk
n’affiche pas de partition /boot
, il est fortement probable que le noyau soit sur la partition contenant /
.
La ligne -- boot parameters --
est à remplacer par les vrais paramètres du noyau. Ces paramètres vont varier d’un système d’exploitation à l’autre. Ici, nous allons lancer Linux grâce aux lignes suivantes:
linux /boot/vmlinuz initrd /boot/initrd.img
L’explication de l’invocation du noyau Linux et des paramètres qu’on peut lui passer est hors de la porté de cet article. En effet, ce sujet nécessiterait un article à lui seul.
Le script final est le suivant:
$ cat /etc/grub.d/11_linux_boot_example #!/bin/sh -e echo "Exemple d'entree" cat << EOF menuentry "Exemple" { set root=(hdX,Y) linux /boot/vmlinuz initrd /boot/initrd.img } EOF
Une fois le script écrit et rendu exécutable, il faut lancer la commande update-grub
afin de mettre à jour /boot/grub/grub.cfg
. Lors de l’exécution de cette commande, les messages passés à echo
doivent apparaître dans le terminal. Si ce n’est pas le cas, c’est que le nouveau script n’a pas été pris en compte. Dans ce cas, vérifiez que le script est bien marqué comme exécutable.
Multiboot
Le multiboot se configure trivialement avec GRUB. En effet, il suffit de rajouter un script qui générera une entrée dans le menu pour rajouter un système sur lequel démarrer. Par exemple, si on rajoute le script 12_linux_boot_example_2
contenant :
$ cat /etc/grub.d/12_linux_boot_example_2 #!/bin/sh -e echo "Exemple d'entree" cat << EOF menuentry "Exemple 2" { set root=(hdX,Y) linux /boot/vmlinuz initrd /boot/initrd.img } EOF
Après l’exécution de update_grub
et le redémarrage, l’entrée Exemple 2 doit apparaître dans le menu de GRUB.
Chainloading
Certains systèmes d’exploitation ne peuvent pas être démarré par GRUB. L’exemple le plus courant est Windows. Pour contourner ce problème, GRUB peut invoquer un autre bootloader à la place du noyau d’un système d’exploitation. Ce mécanisme est appelé chainloading. Pour cela, on utilise la commande chainloader
de GRUB.
Par exemple, si considère le script suivant :
$ cat /etc/grub.d/99_loop #!/bin/sh -e echo "Exemple de chainloader: boucle sur GRUB" cat << EOF menuentry "Boucle de chainlader" { set root=(hd1,1) chainlader (hd1,1)+1 } EOF
Ce script génère une entrée qui va invoquer GRUB. Cela permet de lancer GRUB depuis GRUB. chainloader
prend en paramètre la partition (et le disque) sur lequel le prochain bootloader est situé. Le +1
est un élément de syntaxe de cette commande.
Dans certains cas, la commande chainloader
ne marchera pas. Ces cas sont des cas avancé et ne seront pas discuté dans cet article.
Conclusion
Dans la plupart des cas, GRUB a un outil (os-prober
) qui permet de configurer le menu en fonction des systèmes d’exploitation présents sur le ou les disques. Cependant, il peut être utile de savoir comment créer une entrée personnalisée pour le menu de GRUB. En effet, GRUB permet de créer des entrées basiques pour plusieurs systèmes relativement facilement, même si il faut déléguer le démarrage du système à un bootloader tierce par chainloading.
Vincent Bonnevalle, Djamal Checkroun, Hugo Pompougnac, Julien Rolland, Slimane Siroukane