Niveau :
Résumé : grub ; noyau ; mandelbrot
Vous souvenez-vous du bon vieux temps ? Je vous parle du temps de l'autoexec.bat et des driver de quelques ko, le temps où on écrivait directement en mémoire vidéo, le temps de l'assembleur, du mode réel et des interruptions.
Hé bien cette époque bien que révolue nous a laissé des traces. Il est toujours possible de coder sans noyau, de faire son propre noyau, de se passer de système d'exploitation ou de booter directement sur une application en quelques secondes.
Boot loader
Choisissons un bootloader, grub par exemple, nous allons lui demander de lancer notre programme. Avec grub il existe plusieurs méthodes pour charger un os, entre autres :
- Chainloader charge 512 octets, met le processeur en mode en mode réel, tel qu'il serait après le passage du bios. Pratique pour partir de zéro, mais 512 octet c'est un peu petit et nous n'avons pas vraiment envie de gérer le chargement de fichier sur le disque en plus.
- Linux charge un noyau au format zimage ou bzimage et lui passe le contrôle en mode réel 16 bits. Il est possible de charger des fichiers de plusieurs méga avec le format bzimage.
- Multiboot charge un noyau au format multiboot et lui passe le contrôle en mode protégé 32 bits après un certain nombre d'initialisations. On utilisera cette méthode une prochaine fois.
zImage
On commence par une solution simple à mettre en place, un exécutable au format zImage. Le format est décrit dans la documentation des sources du noyau linux : /usr/src/linux-2.X.XX/Documentation/i386/boot.txt. C'est dans ce format que nous allons développer un binaire bootable directement.
Le bootloader (grub) lit l'en-tête du fichier zImage puis pose la première section (attention, taille limitée à quelques dizaines de ko) à l'adresse 0x90000, Ensuite, il lit le reste du fichier et le place en 0x1000 (pour une zImage, limitée à 512ko) ou en 0x100000 (pour une bzImage). Ensuite, dans le cas de linux, le noyau s'amuse à redéplacer tout ça selon un processus plus ou moins compliqué décrit ici et ici. Attention, ne prenez pas ces documents pour argent comptant, ils sont un peu dépassés. En pratique nous n'irons pas si loin puisque nous resterons en mode réel et que 512ko nous seront largement suffisant (640Ko ça devrait suffire pour tout le monde !).
Nous allons donc faire simple et récupérer le code de boot de linux pour lancer notre petit projet. Le fichier qui contient le code de lancement ainsi que les en-têtes qui vont bien s'appelle header.S.
Attention, il est écrit en assembleur GNU (gas), celui-ci diffère beaucoup de l'assembleur intel. Le point le plus important est que les arguments sont inversés (source puis destination).
header.S
Apportons quelques modifications au fichier pour qu'il corresponde à nos besoins :
continuer la lecture...