require("../global.php"); entete(); ?>
Pour reconnaitre ce programme, le BIOS va aller regarder les 2 derniers octets du secteur, si ils sont égaux à 55h et 0AAh c'est bon. Dans ce cas, il charge le secteur en 0000:7C00h et donne la main au programme. Sinon il affiche un message d'erreur et attend une disquette de boot.
C'est à ce moment là que l'on distingue une disquette d'un disque dur. Dans le cas d'une disquette, le programme de boot va charger directement le système, par exemple IO.SYS et MSDOS.SYS pour le DOS, et lui passer la main. Dans le cas d'un disque dur, c'est un peu plus compliqué car ce secteur est en fait le secteur de partition. Comme c'est celui qui nous intéresse plus particulièrement je lui ai réservé le chapitre suivant...
Pour savoir quel secteur charger, il regarde la fameuse table de partition située providentiellement à la fin du secteur de partition juste avant le 55h,AAh. Comme le BIOS vient de charger ce secteur, la table se trouve en mémoire à l'adresse 07C0h:1BEh et occupe 64 octets.
Cette table permet de diviser un disque dur en morçeaux de taille variable appelés partitions. Ces morceaux sont indépendants et cela permet donc d'avoir plusieurs systèmes d'exploitation sur un même disque dur. Comme la place est limitée dans le secteur de partition, on n'a que quatre entrées dans la table (à mon avis, on avait de la place pour un peu plus mais bon c'est comme ca, il faut faire avec). Chaque entrée contient les informations suivantes :
Adresse | Taille | Fonction |
0 | 1 | Etat de la partition (80h bootable sinon 00h) |
1 | 1 | Tête où commence la partition |
2 | 2 | Secteur et cylindre où commence la partition |
4 | 1 | Type de partition (ex 04h DOS avec FAT 16 bits) |
5 | 1 | Tête de fin de partition |
6 | 2 | Secteur et cylindre de fin de partition |
8 | 4 | Position du secteur de boot de la partition en secteur par rapport au secteur de partition |
12 | 4 | Nombre de secteur de la partition |
Avant de vous donner la source accompagnant cet article, je vais vous parler des partition étendues. Les partitions étendues prennent la place d'une des quatre partitions principales avec 5 comme code de type de partition. Le secteur de boot de cette partition est alors spécial et comprend uniquement une table de partition à deux entrées (quelle gâchis : on n'utilise même pas 5% du secteur !). La première entrée donne le secteur de boot de la première partition étendue. La seconde entrée donne la position du secteur de partition étendue suivant. Ainsi il se forme une liste chainée de secteur de partition étendue jusqu'à ce que le type de la deuxième entrée de ces tables de partition soit nulle.
C'est un programme un peu spécial car il est chargé par le BIOS en 0:7C00h et se déplace en 0:600h (vous pouvez changer l'adresse). Le problème étant de faire avaler cela à l'assembleur puis au linker, personnellement j'ai utilisé TASM, ce qui à mon avis n'est pas le meilleur choix. Mais on y arrive en compilant le programme à l'adresse 0 et en rajoutant à toutes les adresses l'offset de début du programme. Puis on linke cela en tant qu'exécutable et on peut alors récupérer le code avec EXE2BIN. Ce programme existe dans le DOS 5 mais pour les nouveaux, j'en ai refait un qui fait le même boulot et normalement il accompagnera l'article.
De plus pour pouvoir changer facilement le secteur de partition de votre propre disque, je vous ai fait un petit programme nommé WRMBOOT qui fait cela très bien. Attention, avant de l'utiliser, lisez attentivement la documentation car il peut vous faire perdre toutes les données de votre disque dur si vous faites n'importe quoi.
Il ne devrait pas y avoir de problème, mais c'est quand même une manipulation un peu délicate donc c'est peut être pas la peine de vous lancer dedans, si vous débutez. Lors des tests, j'ai rencontré un problème car ma table de partition contenait deux partitions exécutables (surement dû à des tests précédents) et comme vous le verrez dans le programme, dans ce cas, le boot s'arrête. Il n'y a pas de raison de paniquer vous avez juste à changer le programme de boot ou la table de partition.
Allez amusez vous bien mais faites quand même attention à votre disque dur.....
;**************************************************************************** ;* Programme du secteur de partition de mon disque dur ;* ;* (C) 1990 American Megatrends Inc IDEAL STRUC PART_ENTRY ; Structure d'une entrée de la table State DB 0 ; de partition StartHead DB 0 StartSector DW 0 Type DB 0 EndHead DB 0 EndSector DW 0 FirstSector DD 0 NbSector DD 0 ENDS BIOS_BOOT_OFF EQU 7C00h ; adresse où le BIOS charge le boot NEW_BOOT_OFF EQU 600h ; adresse où l'on déplace le boot BOOT_SIZE EQU 512 ; taille du boot secteur NB_PART EQU 4 ; nombre d'entrée dans la table de partition NB_READ_TRY EQU 5 ; nombre maximum de lecture du secteur de boot PART_OFF EQU 1BEh ; offset de la table de partition dans le ; secteur de partition MAGIC_OFF EQU 7DFEh ; offset du nombre magic 0AA55h SEGMENT BOOT public 'CODE' ASSUME cs:BOOT ; Au début on est en 7C00h mais ; ca va pas durer start_boot: cli xor ax,ax mov ss,ax ASSUME ss:BOOT mov sp,BIOS_BOOT_OFF ; On place la pile dans un coin ; Pour l'instant il n'y a que ; le BIOS en mémoire alors on ; a de la place mov si,sp push ax pop es push ax pop ds ASSUME es:BOOT,ds:BOOT ; Voilà tous les registres de segment ; sont chargé sti ; et hop on se recopie en 600h cld mov di, NEW_BOOT_OFF mov cx, BOOT_SIZE/2 repne movsw jmp FAR 0:NEW_BOOT_OFF+1Dh ; C'est pas cool les assembleurs qui ; se croient malin....:-( ORG 1Dh ; évitez d'écraser le début du ; du programme start: ; Là on commence les choses sérieuses mov si, offset Partition_Tab+NEW_BOOT_OFF mov bl, NB_PART Search_bootable: ; recherche une partition bootable ; l'etat de la partition peut être ; 80h bootable ou 00h non bootable ; sinon il y a une erreur cmp [(PART_ENTRY PTR si).State], 80h jz Find_Bootable cmp [(PART_ENTRY PTR si).State], 0 jnz Part_error add si, SIZE PART_ENTRY dec bl jnz Search_bootable int 18h ; Aucune partition bootable ; Appel du basic en ROM !!! Find_Bootable: ; Ouf on a trouvé une partition ; bootable ; Pour dx il y a une ruse car 80h ; correspond aussi au premier disque ; dur mov dx, [word ptr ((PART_ENTRY si).State)] mov cx, [(PART_ENTRY si).StartSector] mov bp, si Test_part: ; On verifie qu'il y a qu'une partition ; bootable add si, SIZE PART_ENTRY dec bl jz Only_one_boot cmp [byte ptr si], 0 jz Test_part Part_error: ; Aih, il y a eut un problème mov si, offset No_Part_msg+NEW_BOOT_OFF Print_error: ; Affiche un message d'erreur lodsb cmp al, 0 jz Endless_loop push si ; Affiche un caratère mov bx, 7 mov ah, 0Eh int 10h pop si jmp Print_error Endless_loop: ; Quand on a affiché tous le message ; d'erreur, attend la fin du monde jmp Endless_loop Only_one_boot: ; Ouf, on a trouvé une et une seule ; partition bootable mov di, NB_READ_TRY Retry: mov bx,BIOS_BOOT_OFF ; Essaye de lire le secteur de boot mov ax,201h ; de la partition choisie push di int 13h pop di jnb Load_ok xor ax, ax ; Problème, reset et reessaye int 13h dec di jnz Retry mov si, offset Disk_error_msg+NEW_BOOT_OFF jmp Print_error ; Impossible de lire le disque Load_ok: ; Ouf, on est arrivé à lire ; le secteur de boot mov si, offset No_system_msg+NEW_BOOT_OFF mov di, MAGIC_OFF cmp [word ptr di], 0AA55h jnz Print_error ; damned, il n'est pas executable mov si, bp jmp far ptr 0:7C00h ; C'est fini, on peut aller ; executer le boot No_Part_msg DB 'Table de partition non valide',0 Disk_error_msg DB 'Erreur au cours du chargement du système d''exploitation',0 No_system_msg DB 'Système d''exploitation absent' ORG PART_OFF Partition_Tab PART_ENTRY NB_PART DUP (?) dw 0AA55h ENDS END start_bootPiedDePage(); ?>