Gérer le MBR (Master Boot Record)

 
 

Par Forthman - Forthman@Wanadoo.fr



Objectifs :
Je me suis dit, pourquoi ne pas faire un programme pour manipuler le MBR en Forth ? Il est évident que certaines commandes sont délicates ( un malheur est si vite arrivé ! ), mais en suivant certaines précautions, le "rique zéro" peut être atteint. Et puis, même si vous ne voulez pas tripatouiller dans votre micro, c'est quand même un sujet passionant.
Mais avant de se lancer dans la programmation, un peu de théorie s'impose :-(


Sommaire

1) Structure des disques

2) Les outils pour accéder aux disques

3) Structure du MBR

4) Mise en oeuvre

5) Remerciements



1) Structure des disques

Qu'il s'agisse de disques durs ou de disquettes, le fonctionnement est le même, la seule différence est qu'un disque dur a plusieurs disques contrairement aux disquettes.

Un disque est constitué de plusieurs faces ( on parle de têtes pour les disques durs ), chaque face recoit un certain nombre de cylindres ou pistes ( suivant que l'on parle de disque dur ou de disquette ), chaque cylindre est découpé en secteurs, pour les disquettes 1.44Mo il y a 18 secteurs/piste, pour les 720Ko 9 secteurs/piste et pour la majorité des disques durs modernes, 63 secteurs/cylindre ( c'est le maximum que le bios supporte ) et enfin, chaque secteur se compose de 512 octets.

Donc pour accéder à un secteur de 512 octets, nous avons besoin de connaitre :

Retour au sommaire


2) Les outils pour accéder aux disques

Pour pouvoir lire ou écrire des données sur un disque, qu'il s'agisse d'un disque dur ou d'une disquette, on doit obligatoirement passer par le BIOS qui est le niveau le plus bas juste avant la programmation directe des ports (mais pour ca y'a un max de boulot !). Pour ce faire, le BIOS met a notre disposition l'interruption 13h, dont je vais passer en détail les fonctions utiles pour accéder à un disque dur ou une disquette.

Il faut savoir que :




 
 

Fonction 0 : Initialisation du contrôleur

A utilier après une erreur.

Entrée :
AH = 0
DL = Numéro du lecteur

Sortie :
AH = Etat

Fonction 1 : Lecture de l'état du lecteur

Renvoie la dernière erreur d'un lecteur.

Entrée :
AH = 1
DL = Numéro du lecteur

Sortie :
AH = Etat

Fonction 2 : Lecture de secteurs du disque

C'est l'une des fonction les plus utilisées, elle permet de lire directement des secteurs d'un disque et de les placer en mémoire.

Entrée :
AH = 2
DL = Numéro du lecteur
AL = Nombre de secteurs à lire
DH = Numéro de tête
CH = 8 bits de poids faible du numéro de cylindre ( ou piste )
CL :

ES:BX = Adresse du buffer dans lequel les secteurs seront placés

Sortie :
AH = Etat

Fonction 3 : Ecriture de secteurs du disque

C'est l'une des fonction les plus utilisées, elle permet d'écrire directement des secteurs d'un disque à partir de données en mémoire.

Entree :
AH = 3
DL = Numéro du lecteur
AL = Nombre de secteurs à écrire
DH = Numéro de tête
CH = 8 bits de poids faible du numéro de cylindre ( ou piste )
CL :

ES:BX = Adresse du buffer a écrire dans les secteurs

Sortie :
AH = Etat

Fonction 8 : Lire les paramètres du lecteur de disque dur

Renvoie les informations du lecteur spécifié.

Entrée :
AH = 8
DL = numéro du lecteur

Sortie :
AL = non défini
DL = nombre de contrôleurs ( le CD-ROM peut avoir son contrôleur )
DH = Nombre de têtes-1 ( 256 têtes maximum )
CH = bits de poids faible du nombre de cylindres
CL :

Retour au sommaire


3) Structure du MBR ( Méchante Bête Redoutable )

Heu... non en fait c'est plutot Master Boot Records, mais bon, la première définition me paraît plus juste ;-).
Ce fameux MBR se trouve sur le premier secteur ( 1 ) de la première piste ( 0 ) de la première face ( 0 ) et tiend sur 1 seul secteur ( 512 octets ).
En voici sa composition : Je ne détaillerais pas les 446 octets de programme, il faut juste savoir que celui-ci teste la validité des données contenues dans la définition des 4 partitions, ainsi que la présence d'une partition active (et uniquement une), et une fois tout vérifié, il charge en mémoire le secteur boot de la partition active.
Les 4 séries de 16 octets suivantes contiennent les définitions de chaque partition.
Voici comment tout ceci est codé : On peut noter que : Donc la taille maximale pour un disque : 1024*63*256*512 = 8Go environ !
Pourtant me direz-vous, on trouve dans le commerce des disques de taille supérieure ! Et bien dans ce cas seules les valeurs exprimées en secteurs sont valides (2^32*512 = 2To).
De plus, il faut aussi savoir que "physiquement" les disques ne peuvent avoir plus de 16 têtes et donc si le nombre de têtes dépasse cette valeur ce n'est que pour diminuer le nombre de pistes, c'est une simulation du BIOS à cause de certains OS qui ne supportent pas plus de 512 cylindres voire même 256.
Voici la formule pour connaitre l'adresse relative d'une partition :

premiere piste * ( nombre de têtes -1 ) * nombre de secteurs/piste + premiere tête * nombre de secteurs/piste + premier secteur - 1

C'est un peu long mais c'est ça.
Pour connaitre le nombre de secteur d'une partition, il suffit d'appliquer ce calcul avec la derniere tête, derniere piste et dernier secteur, de soustraire au résultat l'adresse relative, et d'ajouter 1 au résultat.
Le calcul inverse, càd à partir de l'adresse sous forme de secteurs, retrouver les piste, tête et secteur :

Adresse relative MOD secteurs/piste = n° secteur-1
Adresse relative / secteurs/piste MOD nombre de tetes = n° tête
Adresse relative / secteurs/piste / nombre de têtes = n° piste

En clair, voici 2 programmes Forth :


Variable TETES ( nombre de tetes de l'unite )
Variable Sect/piste ( nombre de secteurs par piste )

>ADR
----
Convertit 3 valeurs ( Piste Tete Secteur ) en une adresse relative :
>ADR ( Piste Tete Secteur --- Adresse )
1- >R
Swap
Tetes @ *
+
Sect/piste @
*
R> +
;
 

ADR>
----
Convertit une adresse relative en 3 valeurs ( Piste Tete Secteur ) :
ADR> ( Adresse32 --- Piste Tete Secteur )
Sect/piste @ MU/Mod
Tetes @ UM/Mod
;


Si le programme ADR> marche parfaitement, en contrepartie, le programme >ADR ne fonctionne que sur de très petites valeurs, car le résultat doit tenir sur 16 bits alors qu'une adresse est codée sur 32 bits. Ceci est dû au fait qu'il n'existe pas de mot Forth permettant de multiplier deux nombres 32bits entre eux. Voici donc un nouveau mot à ajouter au vocabulaire : D*

En entrée : 2 nombres 32 bits
En sortie : 1 nombre 32 bits = à la multiplication des deux précédents

Ce programme ne fonctionne que sur processeurs 386 minimum et avec TF386.COM
ou TFX386.EXE

Code D* ( d1 d2 --- d3 )
EAX Pop
EDX Pop
16 # EAX Rol
16 # EDX Rol
EDX Mul
16 # EAX Rol
EAX Push
Next
End-code
 

Et voici la nouvelle definition de >ADR :

>ADR
----
Convertit 3 valeurs ( Secteur-1 Tete Piste ) en une adresse relative :
>ADR ( Secteur-1 Tete Piste --- Adresse )
0 Swap
Tetes @ *D
D+
Sect/piste @ 0
D*
Rot 0 D+
;

Retour au sommaire


4) Mise en oeuvre (enfin !)

Et oui, nous arrivons à la fin de notre escapade, à la programmation. Comme je l'ai dit plus haut, il n'est nullement question de modifier le MBR ! Car des manipulations hasardeuses peuvent entraîner un plantage de la machine et dont le remède le plus courrant est tout simplement un reformatage pur et dur du disque dur ! ( pas glop... )

La suite peut être copiée/collée dirrectement dans un fichier *.FTH pour être compilée en turbo Forth ( je laisse le soin a Jacques de faire les quelques modifs pour l'utiliser en WForth, à moins qu'il n'ait pas le temps).





 Pour lire un secteur ( 512 octets ) il nous faut une zone mémoire definie :

  Create Sector_buffer 512 Allot

 on passe en Hexadécimal

  Hex



 Un mot en assembleur pour initialiser le lecteur au cas ou ...

  Code Init_HD

    0 # AH Mov   Fonction 0

    80 # DL Mov  Lecteur 80h ( 1er disque dur )

    13 Int

    10 # AX Shr  Décale les 8 bits de AH vers AL en effacant AH

    1Push        on renvoie l'etat du lecteur sur la pile

                 1Push est équivalent à "AX Push Next"

   End-code

    

 Puis un petit bout de programme en assembleur pour lire le secteur MBR

  Code Read_MBR

    2 # AH Mov   Fonction de lecture

    80 # DL Mov  Lecteur 80h = Disque dur

    1 # AL Mov   Nombre de secteurs à lire

    0 # DH Mov   Tête "0"

    0 # CH Mov   Cylindre "0"

    1 # CL Mov   Cylindre "0", secteur "1"

    DS Push      Envoie DS sur la pile

    ES Pop       Recupère cette valeur dans ES ( DS ES Mov n'est pas possible )

    Sector_buffer # BX Mov  Adresse du buffer dans ES:BX

    13 Int       lance l'interruption 13h

    10 # AX Shr  Décale les 8 bits de AH vers AL en effacant AH

    1Push        on renvoie l'état du lecteur sur la pile

   End-code



 Un mot qui affiche un message d'erreur et arrête le programme si une

 erreur se produit avec le lecteur

  : Erreur?

    If   Si valeur sur la pile <> 0 alors il y a erreur

     ." Erreur d'acces au disue dur !"

     Beep  J'aime bien le bruit ;-)

     Abort

    Then

   ;



 Il Faut maintenant "traduire" les infos contenues dans le buffer

 Juste celles qui nous interressent en fait

  : MBR?

    Decimal  Force le passage en décimal pour afficher les valeurs

    Init_HD Erreur?   initialise le disque dur, pas d'erreurs ?

    Read_MBR Erreur?  lecture du MBR, pas d'erreurs ?

    4 0 Do

     Cr

     Sector_buffer 1BE + I 10 * +  calcule l'adresse pour chaque partition



     ." Partition " I .

     Dup C@ 80 = If ."  Amorcable" Then

     10 Spaces



     Dup 4 + C@ 0= If

       ." Non attribuee"

       Cr

      Else

       ." nø systeme :"

       Dup 4 + C@ .

       Cr



       ." Tete de debut     : "

       Dup 1+ C@ 5 .R



       ."   Tete de fin     : "

       Dup 5 + C@ .

       Cr



       ." Cylindre de debut : "

       Dup 2+ C@

       Over 3 + C@ 64 / 256 * + 5 .R



      ."   Cylindre de fin  : "

       Dup 6 + C@

       Over 7 + C@ 64 / 256 * + .

       Cr



       ." Secteur de debut  : "

       Dup 3 + C@ 63 And 5 .R



       ."   Secteur de fin  : "

       Dup 7 + C@ 63 And .

       Cr

       

     Then



     Drop

    Loop

   ;
 

5) Remerciements

Document écrit par  Forthman - Forthman@Wanadoo.fr

Libre reproduction et diffusion autorisée - modifications interdites sans autorisation de l'auteur


[ Retour au sommaire ] - [ Retour à la page bas niveau] - [ Retour à la page d'acceuil ]