Boot x86

Guillaume Charifi, le 7 mars 2017

Quand on appuie sur le bouton d'alimentation, la broche #PWR_ON du connecteur d'alimentation ATX est reliée au #GND, ce qui déclenche l'allumage complet de l'alimentation et l'activation de toutes les broches.

Le BIOS est activé et mappé à l'adresse physique0xD0000000 (en général), quelques périphériques s'initialisent tous seuls.

Le processeur reçoit brièvement le signal #RST, qui le fait se réinitialiser en mode réel 16 bits et définir le registre pointeur d'instructions à 0xF000:FFF0

l'adresse physique correspondante, 0xFFFF0 est mappée tout à la fin du BIOS, et elle contient un saut vers le code d'initialisation du BIOS

Chose importante, la RAM n'est pas initialisée à ce moment là, donc le BIOS peut seulement utiliser les registres processeur pour bosser

Et donc la première chose qu'il va faire, c'est initialiser la RAM via le chipset

Optionnellement effectuer quelques tests dessus

Puis le BIOS va initialiser le chipset, les périphériques de base, activer certaines fonctionnalités du processeur (virtualisation, ...), exécuter la ROM de la carte graphique (pour pouvoir afficher des trucs sur l'écran), puis parcourir tous les périphériques pour trouver ceux de stockage

Sur chacun d'eux, il cherche l'existence d'une signature située dans les 2 derniers octets du premier secteur du disque : 0xAA 0x55, qui lui informe qu'il s'agit bien d'un secteur d'amorçage (et donc bootable)

Il boote sur le premier qu'il trouve (ou le premier spécifié par l'utilisateur via le boot menu ou d'autres fonctionnalités) : il le copie en mémoire (512 octets) à l'adresse physique 0x7C00, toujours en mode réel 16 bits, par un saut long vers 0x0:7c00 (sauf BIOS buggués qui bootent à l'adresse 0x7c0:0), et ainsi le bootloader prend la main

Petite précision, le BIOS passe au bootloader dans le registre DL l'identifiant du périphérique de démarrage sur lequel il a booté à utiliser avec l'int 13h disque

D'ailleurs, la table des vecteurs d'interruption (IVT) est située à l'adresse 0 en général et contient 256 vecteurs sous la forme seg16:off16, utilisés par l'OS (ou le bootloader, ...) en l'absence de pilotes pour pouvoir accéder aux ressources principales (DD, ...), et elle est initialisée par le BIOS

À noter également que la ROM vidéo modifie l'IVT pour rajouter ses propres entrées dedans (notamment pour l'interruption 10h qui lui est spécifique, et permet de changer la résolution d'écran, ...)

Une des premières choses que va faire le bootloader, c'est activer la porte A20

Par défaut, à cause d'un comportement hérité des vieux processeurs, les seuls les 20 premiers bits d'une adresse sont pris en compte, les autres étant ignorés (donc l'adresse physique maximale que l'on peut obtenir est 0xFFFFF), ce qui est un peu problématique pour bosser avec plus de 1 Mo de RAM

Le bootloader, en activant la porte A20, supprime cette limitation et laisse à l'OS la possibilité d'accéder à toute la RAM

Malheureusement, cette procédure n'est pas standard, et le bootloader de PifOS ne compte pas moins de 4 tentatives différentes pour l'activer, consommant la plus grande partie de l'espace disponible (espace très limité : 512-2-4*16 = seulement 446 octets)

Après ça, il passe souvent en mode protégé linéaire, pour pouvoir accéder à 4 Go de RAM

Puis il charge optionnellement un deuxième étage, qui lui permet de faire plus des 446 octets ridicules

Et ensuite il trouve et charge le noyau de l'OS

Dans PifOS, il est situé à l'intérieur du kmicrofs

Qui peut contenir d'autres fichiers, comme des fichiers de configuration, etc

Et ensuite le noyau fait ce qu'il veut, il peut passer en long mode (64 bits), mapper la RAM, etc

Et voilà.

Commentaires