Niveau :
Résumé : lilo ; grub
Même si la plupart des distributions sont passées à grub, on s'est longtemps posé la question d'utiliser lilo ou grub. Il servent tous les deux à charger linux (le noyau), voyons comment ça marche.
Bios
Avant de nous intéresser au bootloader, étudions le processus de démarrage d'une machine (x86 type intel).
- Appui sur le bouton
- Allumage de l'alimentation, électricité dans la carte mère
- Allumage du processeur dans un état connu
- Passage du contrôle au bios
- Lecture d'un disque, chargement du secteur de boot nommé MBR (généralement un bootloader)
- Chargement du noyau et d'éventuels modules, passage du contrôle au noyau
- Montage d'un système de fichier et passage du contrôle au processus d'init (sur les unix)
Bon, le début, vous connaissez.
L'état connu du processeur c'est : mode réel, 16bits, exécution pointant sur les derniers octets du premier Mo (FFFF:0000). Ici se trouve mappé statiquement le bios qui va se lancer et initialiser le matériel qu'il connaît. Il laisse disponible quelques fonctions via des interruptions, par exemple pour accéder à la carte vidéo ou au disque dur. Et il termine en chargeant le premier secteur (512 octets) du premier périphérique (disque, dur, clé usb ...) bootable qu'il trouve et lui passe la main (à l'adresse 0000:7C00).
C'est ici qu'on trouve lilo, grub, syslinux et même parfois linux lui-même sur de vieilles versions. Comme vous le constatez, 512 octets c'est très petit pour coder un bootloader (surtout que les octets ne sont pas tous disponibles à cause de la table des partitions). C'est pourquoi les bootloaders ont tous une architecture un peu bizarre avec plusieurs étapes.
Lilo
Lilo est un bootloader spécifique à linux (LInux LOader). Il fonctionne en 2 temps, un secteur de boot qui va charger un fichier un peu plus gros dont il connaît les secteurs sur le disque. Ce dernier peut éventuellement proposer un menu puis charge le bon noyau et lui passe la main.
Lilo utilise un fichier de configuration /etc/lilo.conf. À chaque modification de ce fichier, il faut lancer la commande lilo. Cette commande va lire le fichier et réécrire le secteur de boot à la racine du disque. Il va aussi écrire un fichier map qui contient la liste des secteurs sur le disque où trouver les étapes suivantes de chargement ainsi qu'une version compilée du fichier de configuration. En pratique cette deuxième étape se trouve à l'intérieur du binaire lilo lui-même (depuis la version 22.x x<4).
Grub
Grub est un bootloader qui se veut générique (la version 2 commence à être utilisable sur d'autres architectures). Il est capable de booter de nombreux formats de noyaux.
Son secteur de boot (stage1) est statique et est installé une fois pour toutes (ou presque). Celui-ci se contente de charger un autre fichier (stage2) qui sait lire les systèmes de fichiers et donc peut lire sa propre configuration directement. Cela lui permet de ne pas nécessiter de manipulation après chaque modification de sa configuration. Il est aussi beaucoup plus flexible puisque cette deuxième étape contient un shell qui permet de choisir soi-même ce qui se passe pendant le boot (pratique pour les récupérations d'urgence).
La limitation de cette technique est qu'il faut encore réinstaller grub dans le secteur de boot lorsque le shell (stage2) a été modifié. Mais on peut faire mieux, il existe la possibilité d'ajouter une étape, le stage1.5, qui sait lire un système de fichier. Ce code est suffisamment petit pour qu'on puisse l'installer dans un espace vide du disque juste derrière la table des partitions. Il est donc dans un endroit qui ne bougera jamais et il saura lire le shell où qu'il soit et aucune réinstallation ne sera plus nécessaire.
Il reste tout de même un cas où il faut le réinstaller : quand on change le type de système de fichier ou la partition qui contient le shell grub.
Travaux pratiques
Nous allons nous exercer sur un loopback (un disque virtuel) pour éviter les larmes en cas d'erreur (ayez toujours un liveCD sur vous, on ne sait jamais). Installez aussi qemu, ça vous permettra de tester ce que vous faites (c'est pratique même sur des vrais disque pour ne pas rebooter).
Préparation du disque virtuel pour nos tests :
# 50Mo c'est déjà beaucoup pour un disque :-) $ dd if=/dev/zero of=/tmp/test bs=1M count=50 # Le disque entier $ losetup /dev/loop0 /tmp/test # On le partitionne (une partition, tout l'espace) $ cfdisk /dev/loop0 # On repère le premier secteur de la partition $ fdisk -l -u /dev/loop0 # -> start, en général 63 # On transforme cette partition en device $ losetup -o $((63*512)) /dev/loop1 /tmp/test # On crée un système de fichier sur cette partition $ mke2fs /dev/loop1 # On le monte $ mount /dev/loop1 /mnt # On y place un noyau pour faire joli $ cp /boot/vmlinuz-* /mnt # on fait un test avec qemu pour vérifier que ça ne marche pas $ sync # pour ne pas avoir à démonter la partition $ qemu /tmp/test
Vous aurez aussi besoin de grub et lilo, mais votre système ne vous permettra pas d'installer les deux en même temps. Alors vous pouvez soit les recompiler, soit lire les récupérer sous forme binaire, soit sauter la partie correspondante :-). Pour les debianistes :
$ aptitude download lilo $ dpkg -x lilo*.deb ~/tmp/
Lilo
Créons nous un fichier de configuration pour notre noyau (/mnt/etc/lilo.conf) :
# définition de la correspondance bios <-> linux disk=/dev/loop0 bios=0x80 sectors=63 cylinders=12 heads=255 partition=/dev/loop1 start=63 # où mettre le secteur de boot boot=/dev/loop0 # disque dur moderne lba32 # on demande a l'utilisateur son avis prompt # avec un menu c'est plus joli install=menu # on stocke la liste des secteurs quelque part sur la partition map=/mnt/lilo/map # on ne seuvegarde pas le secteur de boot backup=/dev/null # une seule entrée dans notre menu image=/mnt/vmlinuz-2.6.25 label=Mon beau noyau, roi des os ...
Vous aurez remarqué le premier paragraphe. Il n'est nécessaire que parce que nous travaillons sur des loopbacks. Il s'agit d'expliquer à lilo que lors du boot, le bios (et donc lilo) verra ce qui est actuellement /dev/loop0 comme le premier disque (0x80). On lui indique aussi comment il est partitionné puisqu'il ne peut pas deviner tout seul que /dev/loop1 est sur le disque /dev/loop0. Et enfin on lui indique la géométrie du disque telle que nous l'a donnée la commande fdisk un peu plus haut car un loopback n'a pas de géométrie.
Le reste du fichier est le minimum pour avoir quelque chose de correct qui ne casse pas votre machine et qui propose une entrée de menu. Pour plus de fioritures, vous pouvez regarder la documentation vraiment bien détaillée. Vous pouvez vous amuser à mettre des images, ou même un boot animé, il y a même un boot casse briques.
Et maintenant installons lilo :
# on a défini ce répertoire dans lilo.conf (d'habitude on met /boot) $ mkdir /mnt/lilo # on met à jour le bootloader $ lilo -c /mnt/etc/lilo.conf # et on teste pour faire joli $ sync && qemu /tmp/test
Wahoo, c'est beau ! Maintenant, faisons de même avec ...
Grub
Nous pourrions jouer la facilité et lancer grub-install. Mais non, ce n'est pas notre genre. Il faut comprendre comment ça marche avant de tout casser. Tout comme il faut savoir calculer avant de se servir d'une calculatrice.
Commençons par l'indispensable, un fichier de configuration :
# une entrée, c'est déjà bien assez title Mon Bô noyau, que j'aime ta verdure kernel (hd0,0)/vmlinuz-2.6.25
Vous remarquerez deux choses. Tout d'abord grub utilise sa propre notation pour les disques et partitions (hé oui linux ne sera plus là quand il bootera). (hd0) est le premier disque vu par le bios, (hd1) le 2e, etc. De même pour les partitions, (hd0,0) est la première partition du premier disque, (hd0,1) la 2e etc. Ensuite, le chemin est relatif à la partition telle qu'elle sera lue au boot et non pas à l'arborescence actuelle (on ne met pas /mnt/vmlinuz-2.6.25).
Le stage2 (le shell) doit être disponible sur le nouveau disque pour que le boot fonctionne.
$ mkdir /mnt/grub $ cp /boot/grub/stage2 /mnt/grub/
Créons un fichier device.map pour faire correspondre les loopback aux disques qui seront vus par le bios (même problème que pour lilo) :
(hd0) /dev/loop0 (hd1) /dev/hda
Le hd1 est bien utilecar on va lire des fichiers qui ne sont pas stockés sur le loopback (on pourrait aussi les y copier :-).
Ensuite lançons un shell grub pour faire l'installation :
$ grub --device-map=/tmp/device.map # on met un stage1.5 pour être complet # il se trouve sur /dev/hda1 dans /boot/grub et on le met sur /dev/loop0 $ embed (hd1,0)/boot/grub/e2fs_stage1_5 (hd0) > 15 sectors are embedded. # on va installer le stage1 et paramétrer tout ça : # --stage2=... parce que la partition est montée, il faut écrire dessus en utilisant le noyau # (hd1,0)/boot/grub/stage1 : on va chercher le stage1 où il est stocké actuellement # (hd0) : on installe sur le mbr de /dev/loop0 # (hd0)1+15 : on lui dit d'utiliser le stage1.5 installé précédemment (mbr+1, 15 secteurs) pour lire le stage2 # p (hd0,0)/grub/stage2 : on dit au stage1.5 où trouver le stage2 # /grub/menu.lst : on dit à stage2 où aller chercher sa configuration $ install --stage2=/mnt/grub/stage2 (hd1,0)/boot/grub/stage1 (hd0) (hd0)1+15 p (hd0,0)/grub/stage2 /grub/menu.lst $ quit
Remarquez le embed, il met le stage 1.5 dans l'espace disponible derrière la table des partitions comme nous l'avons déjà vu.
Si vous vouliez sauter le stage1.5 cela aurait donné :
$ grub --device-map=/tmp/device.map $ install --stage2=/mnt/grub/stage2 (hd1,0)/boot/grub/stage1 (hd0) (hd0,0)/grub/stage2 /grub/menu.lst $ quit
Et comme je suis gentil, je vous montre comment le faire sans s'embêter (et sans hd1) :
$ cp -r /boot/grub /mnt $ grub --device-map=/mnt/grub/device.map $ setup --stage2=/mnt/grub/stage2 (hd0) (hd0,0) $ quit
Et si vous voulez installer grub pour le système en cours d'exécution il y a encore plus simple :
$ grub-install /dev/hda
Test :
$ sync && qemu /tmp/test
Ça y est ! La gloire est à nos portes !
Choix
Et maintenant, lequel choisir ? Cela dépend de votre situation et de vos besoins. Faisons un petit résumé des avantages de chacun.
Grub:
- peut lancer plus de systèmes
- dispose d'un shell au boot pour les réparations ou les changements de paramètres
- résiste aux modifications du système de fichier
Lilo :
- plus léger
- sait contourner les bugs d'un grand nombre de vieux bios
C'est ce qui fait que grub est de plus en plus souvent choisi comme bootloader face à lilo.
Comments