Créez votre propre disquette d'amorçage
Gazette Linux n°084 - novembre 2002
par Muhammad Torabi Dashti (Copyright © 2002) <mtdashti AT mehr DOT sharif DOT edu>
traduction française par Sébastien Marbrier (tous droits réservés) <sebastien DOT marbrier AT laposte DOT net>
Table des matières :
Sommaire
Introduction
En lisant un fascinant article dans le numéro 77 de la Gazette Linux, Écrivez votre micro OS (1ère partie) de Krishnakumar R. [1]; j'ai vu une bizarrerie, les deux derniers octets du secteur d'amorçage devraient contenir 0x55AA! Et comme le prouve les commentaires de cet article, je n'étais pas le seul à jouer avec les valeurs magiques. J'ai donc réécris le secteur d'amorçage de Krishnakumar avec nasm [2] (je ne connais pas as86) et j'ai supprimé de write.c la ligne insérant 0x55AA. Et que s'est-il passé ? Mon PC a démarré ! Alors pourquoi Krishnakumar a t-il écrit cette partie ? Ou plus généralement, qui lit le secteur d'amorçage ? La réponse est simple : Le BIOS ! Un autre point intéressant et qu'IBM a publié le code source du BIOS de son XT dans La Référence Technique du XT [3]. Jetons-y un coup d'oeuil : (J'y ai apporté quelques modifications, il n'est pas aussi complet que l'original)
Code d'amorçage du XT
;---INT 19H BOOT_STRAP: ;INITIALISATIONS MOV CX,3 ;COMPTEUR DE REPRISES H1: PUSH CX SUB DX,DX SUB AX,AX INT 13H ;INITIALISATION DISQUETTE JC H2 MOV AX,0201H SUB DX,DX MOV ES,DX ;BOOT_LOCN A ETE DEFINIE PRECEDEMMENT ;ORG 7C00H ;BOOT_LOCN LABEL FAR MOV BX, OFFSET BOOT_LOCN MOV CX,1 INT 13H ;LIT LE SECTEUR 0 DE LA DISQUETTE H2: POP CX JNC H4 CMP AH,80H ;VERIFIE L'EXPIRATION DU COMPTEUR JZ H5 LOOP H1 JMP H5 H4: JMP BOOT_LOCN H5: ;RECHERCHE D'UN DISQUE DUR SUB AX,AX SUB DX,DX INT 13H MOV CX,3 H6: PUSH CX MOV DX,0080H SUB AX,AX INT 13H JC H7 MOV AX,0201H SUB BX,BX MOV ES,BX MOV BX,OFFSET BOOT_LOCN MOV DX,80H MOV CX,1 INT 13H H7: POP CX JC H8 MOV AX, WORD PTR BOOT_LOCN+510D CMP AX,0AA55H ;NOMBRE MAGIQUE! JZ H4 H8: LOOP H6 INT 18H ;ECHEC COMPLET!
Très bien ! Tout est clair à présent. Cette valeur 0x55AA est testée seulement si le secteur d'amorçage est chargé depuis un disque dur, Krishnakumar l'a donc utilisée pour s'assurer de la compatibilité. Notez également que toute chaîne aléatoire de bits dans le secteur 0 d'une disquette est considérée comme un secteur d'amorçage et le système l’exécute !
Mais j'utilise un Windows 2000 en plus de mon Linux et mes disquettes ont toujours un système de fichier msdos (fat 12) pour que chaque système d'exploitation puisse les lire. Faisons à présent une expérience simple : formatons une disquette avec Windows (ou tout système d'exploitation basé sur le DOS) et laissons l'ordinateur démarrer avec cette disquette. Vous verrez un message indiquant que la disquette n'est pas amorçable et vous demandant de la remplacer et d'appuyer sur une touche. C'est également la même chose lorsque l'on formatte la disquette sous Linux et que l'on utilise un système de fichers msdos (on peut utilise la commande mkfs -V -t msdos /dev/fd0, ou bien l'utilitaire de formatage de disquettes de KDE). Cela devient encore plus étrange quand on utilise le système de fichier ext2 sur la disquette (#mkfs -V -t ext2 /dev/fd0). L'ordinateur ne traitement pas la disquette et transfère simplement le contrôle au secteur d'amorçage du disque dur (ex. LiLo). Alors quelle est la différence entre ces deux formats et notre disquette de démarrage ? J'ai modifié le write.c de Krishnakumar et le read.c lit le secteur d'amorçage d'une disquette et le copie dans le fichier boot.sec; il l'affiche aussi élégamment. Vous pouvez, si vous le souhaiter, utiliser les outils Linux pour la même chose: pour écrire le secteur d'amorçage sur la disquette (#dd if=boot.sec of=/dev/fd0 bs=1 count=512) et pour le lire (#dd if=boot.sec of=/dev/fd0 bs=1 count=512 skip=0).
Observez le secteur d'amorçage d'un ext2. Il n'y a que des zéros ! Mais le secteur d'amorçage msdos contient quelques instructions. Désassemblons-le (j'utilise ndisasm[2]):
1. insérez une disquette au format msdos.
2. exécutez "./read"
3. exécutez "ndisasm boot.sec | more"
4. la première instruction est un saut à l'adresse 0x3e mais le code n'est pas correctement indenté.
5. exécutez "ndisasm -s 0x3e boot.sec | more" pour voir le code indenté.
OK, nous avons donc ici un minuscule secteur d'amorçage, il se contente d'afficher un message (le message dépend du système d'exploitation, et vous pouvez le modifier au moyen d'un éditeur binaire quelconque, tels que ceux de KDE. A titre d'exemple, modifions boot.sec afin d'afficher un message amusant et réécrivons-le en utilisant le write.c de Krishnakumar's write.c sur la disquette !) attendons ensuite un touche et invoquons à nouveau l'interruption 0x19 (la procédure du BIOS boot_starp). En réalité, MS DOS utilisait l'espace entre le saut et l'adresse 0x3e pour stocker des informations (la FAT) et cette méthode fut perpétuée par ses successeurs; c'est pour cela qu'il y a un saut ici. Vous trouverez des informations sur le système de fichier MS-DOS sur le net ou bien vous pouvez consulter [4].
Jusqu'ici, tout est logique, le BIOS se contente d’exécuter tout ce qu'il trouve sur le secteur d'amorçage, ce peut être notre exemple "écris un 'A' et c'est tout" ou bien un élégant secteur d'amorçage tel que celui de MS DOS. Mais lorsque j'ai désassemblé le secteur d'amorçage ext2, rien n'était clair. C'est remplit de zéros ce qui implique la présence de nombreuses instructions ADD inutiles ! Pourquoi le BIOS le passe t-il et ne reste pas bloqué dedans ? Tout simplement parce que le BIOS à changé entre le XT et le AT ! J'ai trouvé un code source du BIOS AT sur le net (il n'y a malheureusement aucune référence, mais il est probable que la Référence Technique de l'IBM AT contienne également ce code d'amorçage.)
Code d'amorçage de l'AT
;---INT 19H BOOT_STRAP_1 PROC NEAR ;INITIALISATIONS ;PURGE @BOOT_LOCN STI MOV CX,4 H1: PUSH CX KTOV AH,0 INT 13H JC H2 MOV AX,201H SUB DX,DX MOV ES,DX MOV SX,OFFSET @BOOT_LOCN MOV CX,1 INT 13H H2: POP CX JNC H4 CMP AH,80H JZ H5 LOOP H1 JMP SHORT H5 H4: CMP BYTE PTR @BOOT_LOCN,06H ;TEST#1 JB H10 MOV DI,OFFSET @BOOT_LOCN MOV CX,8 MOV AX,WORD PTR @BOOT_LOCN H4A: ADD DI,2 CMP AX,[DI] ;TEST#2 LOOPZ H4A JZ H10 H4_A: JMP @BOOT_LOCN H5: ;INTIALISATIONS ET PRE-TESTS SUB AX,AX SUB DX,DX INT 13H MOV CX,3 H6: PUSH CX MOV DX,0080H MOV AX,0201H SUB BX,BX MOV ES,BX MOV BX,OFFSET @BOOT_LOCN MOV CX,1 INT 13H POP CX JC H8 CMP WORD PTR @BOOT_LOCN+510D,0AA55H ; NOMBRE MAGIQUE! JZ H4_A H8: PUSH CX MOV DX,0080H SUB AX,AX INT 13H POP CX JC H10A LOOP H6 H9: ;PARTIE QUI NE NOUS INTERESSE PAS INT 18H H10A: LOOP H8 JMP H9 H10: ;AFFICHE UN MESSAGE H11: jmp H11 BOOT_STRAP_1 ENDP
Deux nouveaux tests sont ajoutés au secteur d'amorçage de la disquette:
1. Son premier octet doit être supérieur à 0x6 ! Celà signifie que la première instruction ne peut être ADD (les OpCode 0 à 5 sont utilisées par les différents modes de different modes de ADD). La raison est logique; aucun programmeur responsable ne voudrait additionner des valeurs inconnues du registre au démarrage. Et c'est pour cela (tel que dans le cas du ext2) un message s'affiche et le PC attend un redémarrage. L'énigme est partiellement résolue ! Sur mon PC, le contrôle est donné au secteur de démarrage du disque dur. C'est bien entendu préférable, de nos jours presque tous les PC ont un disque dur. Il est possible que le BIOS a changé depuis les premiers AT.
2. Ses huit premiers mots ne peuvent être identiques, je n'en connais pas la raison; mais il semblerait que ce soit purement arbitraire. Vous pouvez facilement faire le test en ajoutant 16 NOP (0x90) au secteur d'amorçage de Krishnakumar, vous verrez que votre PC ne démarrera pas !
Vous pouvez soit utiliser ces outils (read.c and write.c) ou bien les outils de Linux (par ex. l'adorable commande 'dd') pour investiguer dans la structure des secteurs d'amorçage. Voici une expérience intéressante pour quiconque ayant Windows et Linux installés côte-à-côte et qui utilisent LiLo en tant que gestionnaire d'amorçage (installé sur le MBR): réalisez un menu de démarrage récursif ! Les étapes sont les suivantes :
1. utilisez 'dd' ou 'read.c' pour lire le MBR: #dd if=/dev/hda of=mbr.sec bs=1 count=512 skip=0
2. copiez mbr.sec sur votre partition amorçable de Windows (presque toujours c:\). Vous pouvez utiliser les élégants programmes de John Newbigin si toutes vos tentatives échouent.
3. éditez boot.ini en ajoutant à la fin une ligne telle que : c:\mbr.sec = "LiLo Again!"
Et le processus de démarrage se poursuit...
Références
[1]http://www.tldp.org/LDP/LG/issue77/krishnakumar.html
[2]http://nasm.sourceforge.net/
[3]IBM, "IBM Personal Computer XT Technical Reference", Vol.2,1981.
[4]M.A.Mazidi, J.G.Mazidi, "The 80X86 IBM PC & Compatible Computers",Vol.2, Prentice Hall, 1995.
Adaptation française de la Gazette Linux
L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux
Cet article est publié selon les termes de la Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.
Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site http://www.traduc.org/Gazette_Linux
Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.