Chapitre – 12
Lecture et modification du MBR avec programmation
Master Boot Record (MBR) ou Master Partition Table (MPT)
Le Master Boot Record (MBR) ou parfois appelé la table de partition principale (MPT), est créé sur le disque dur en exécutant la commande FDISK.EXE de DOS.
Le MBR contient un petit programme pour charger et démarrer la partition active (ou amorçable) à partir du disque dur. L'enregistrement de démarrage principal contient des informations sur les quatre partitions principales du disque dur, telles que le secteur de départ, le secteur de fin, la taille de la partition, etc.
Le MBR est situé au secteur absolu 0 ou nous pouvons dire au cylindre 0, à la tête 0 et au secteur 1 et s'il y a plus d'une partition présente sur le disque, il y a des enregistrements de démarrage principaux étendus, situés au début de chaque volume de partition étendu.
Pour une description détaillée, reportez-vous au chapitre "Approche logique des disques et du système d'exploitation", abordé précédemment dans ce livre.
Format d'enregistrement de démarrage principal
Nous pouvons partitionner le disque dur en plusieurs lecteurs logiques qui se voient généralement attribuer leur propre lettre de lecteur par DOS). Une seule partition à la fois peut être marquée comme partition active (ou amorçable).
Le Master Boot Record a la limite de quatre entrées dans la Master Partition Table. Cependant, l'emplacement de l'enregistrement de démarrage principal étendu peut être obtenu à l'aide de l'enregistrement de démarrage principal qui contient des tables de partition étendues, dont le format est exactement le même que celui de la table de partition principale, sauf qu'il n'y a pas de code de démarrage et que cet espace de 446 octets est normalement réservé au code de démarrage et reste vide.
Tous les 512 octets de l'enregistrement de démarrage principal sont divisés comme suit, indiqués dans le tableau :
Toutes les partitions étendues doivent exister dans l'espace réservé par l'entrée de partition étendue. Seules deux des partitions étendues sont destinées à être utilisées, la première comme une partition normale et la seconde comme une autre partition étendue si elle existe.
Ainsi, à l'aide d'une table de partition principale, nous pouvons obtenir l'emplacement d'une autre table de partition principale étendue à côté, si elle est présente.
Format d'entrée de table de partition
Le format d'entrée de la table de partition de toute partition dans le MBR a été donné dans le tableau suivant. Chaque entrée de partition de n'importe quel MBR peut être divisée en octets suivants avec leurs significations spécifiques :
Programme d'écriture pour lire la table de partition du MBR
Le programme pour lire les quatre entrées de partition à partir de la table de partition du MBR a été donné ensuite. Le programme affiche tous les paramètres des informations de partition, écrites dans la table de partition du MBR.
Le codage du programme est le suivant :
/* Programmer pour lire la table de partition MBR */
# include <bios.h>
/* structure to read the partition entry from partition table */
struct partition
{
unsigned char bootable ; /* Active Partition Byte */
unsigned char start_side ;/* Starting Head */
unsigned int start_sec_cyl ; /* combination of
Starting sector and
cylinder number */
unsigned char parttype ; /* File system
Indicator Byte */
unsigned char end_side ; /* Ending Head */
unsigned int end_sec_cyl ; /* combination of
Starting sector and
cylinder number */
unsigned long part_beg ; /* Relative Sector
Number */
unsigned long plen ; /* Partition length in
sectors */
} ;
/* Structure pour lire le MBR */
struct part
{
unsigned char master_boot[446] ; /* IPL (Initial
Program Loader)*/
struct partition pt[4] ; /* Partition table */
int lasttwo ; /* Magic Number */
} ;
struct part p ;
void main()
{
clrscr();
/* Lire le premier secteur du premier disque dur */
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the information of MBR
Partition Table */
getch();
}
/* Fonction pour afficher les informations de la table de partition du MBR */
display()
{
unsigned int s_sec, s_trk, e_sec, e_trk, i, t1, t2 ;
char type[20], boot[5] ;
printf("\n\nPart. Boot Starting location
Ending Location Relative Number of");
printf("\nType Side Cylinder Sector
Side Cylinder Sector Sectors Sectors\n");
for ( i = 0 ; i <= 3 ; i++ )
{
if ( p.pt[i].bootable == 0x80 )
strcpy ( boot, "Yes" ) ;
else
strcpy ( boot, "No" ) ;
switch ( p.pt[i].parttype )
{
case 0x00 :
strcpy ( type, "Unused" ) ; break ;
case 0x1 :
strcpy ( type, "FAT12" ) ; break ;
case 0x2 :
strcpy ( type, "Xenix" ) ; break ;
case 0x3 :
strcpy ( type, "Xenix:usr" ) ; break ;
case 0x4 :
strcpy ( type, "FAT16<32M" ) ; break ;
case 0x5 :
strcpy ( type, "DOS-Ext." ) ; break ;
case 0x6 :
strcpy ( type, "FAT16>32M" ) ; break ;
case 0x7 :
strcpy ( type, "NTFS" ) ; break ;
case 0x0b :
strcpy ( type, "FAT32" ) ; break ;
case 0x0c :
strcpy ( type, "FAT32-LBA" ) ; break ;
case 0x0d :
strcpy ( type, "VFAT16" ) ; break ;
case 0x0e :
strcpy ( type, "VFAT16-LBA" ) ; break ;
case 0x0f :
strcpy ( type, "VFAT EXT" ) ; break ;
case 0x17 :
strcpy ( type, "HPFS" ) ; break ;
case 0x81 :
strcpy ( type, "Old LINUX" ) ; break ;
case 0x82 :
strcpy ( type, "LinuxSwap" ) ; break ;
case 0x83 :
strcpy ( type, "LinuxNative" ) ; break ;
case 0x85 :
strcpy ( type, "Linux Ext." ) ; break ;
default :
strcpy ( type, "Unknown" ) ; break ;
}
s_sec = ( p.pt[i].start_sec_cyl & 0x3f ) ; /* starting
Sector of the
partition */
t1 = ( p.pt[i].start_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].start_sec_cyl & 0x00c0 ) << 2 ;
s_trk = t1 | t2 ; /* Starting Cylinder */
e_sec = ( p.pt[i].end_sec_cyl & 0x3f ) ; /*Ending Sector */
t1 = ( p.pt[i].end_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].end_sec_cyl & 0x00c0 ) << 2 ;
e_trk = t1 | t2 ; /* ending Cylinder */
printf ( "\n%6s %3s", type, boot ) ;
printf ( "%4d %6d %8d", p.pt[i].start_side, s_trk,s_sec ) ;
printf ( "%7d %6u %8u", p.pt[i].end_side, e_trk, e_sec ) ;
printf ( " %10lu %10lu", p.pt[i].part_beg,
p.pt[i].plen ) ;
}
return 0;
}
Les informations fournies par la sortie du programme sont affichées comme ci-dessous :
Commentaires sur le codage :
La partition de structure est utilisée pour lire les différents paramètres d'entrée de partition de la partition dans la table de partition du MBR. La partie structure est utilisée pour lire les informations du MBR.
La fonction display() affiche les informations des paramètres de la table de partition MBR à l'écran. Comme nous voyons la sortie du programme, le cylindre de début et de fin et le numéro de secteur sont affichés comme suit :
Starting Sector = 1
Starting Cylinder = 0
Ending Sector = 63
Ending Cylinder = 701
Ces numéros de secteur et de cylindre sont calculés à partir de la combinaison de deux octets. Les tableaux suivants montrent comment ces chiffres sont calculés :
Thus Starting C-H-S of the partition= 0-0-1.
Similarly, the Encoding for the Ending Cylinder and Sector number of the partition have been given in the next table:
Ainsi le C-H-S de fin de la partition = 701-254-63.
Programme pour trouver toutes les partitions logiques et leurs informations
Le programme dont nous avons parlé précédemment consistait à lire les informations de partition à partir de la table de partition du MBR. Mais uniquement en lisant le MBR, nous ne pouvons pas obtenir les informations des autres partitions logiques qui se trouvent dans la partition étendue du disque.
Nous avons déjà discuté du fait que le Master Boot Record a la limite de quatre entrées dans la Master Partition Table. Cependant, l'emplacement de l'enregistrement de démarrage principal étendu peut être obtenu à l'aide de l'enregistrement de démarrage principal qui contient des tables de partition étendues, dont le format est exactement le même que celui de la table de partition principale.
Toutes les partitions étendues doivent exister dans l'espace réservé par l'entrée de partition étendue. Seules deux des partitions étendues sont destinées à être utilisées, la première comme une partition normale et la seconde comme une autre partition étendue si elle existe.
Ainsi, à l'aide d'une table de partition principale, nous pouvons obtenir l'emplacement d'une autre table de partition principale étendue à côté, si elle est présente.
Le programme suivant sert à trouver toutes les partitions logiques et leurs informations d'entrée de partition, lire les MBR et les MBR étendus à partir du disque. Le codage du programme est le suivant :
/* Programme pour lire les paramètres de toutes les partitions logiques présentes sur le disque */
#include<dos.h>
har buffer[512], report_par[20];
unsigned drive_num =0x80;
unsigned long star_sec[20], sec;
/* Structure du format de paquet d'adresse de disque, à utiliser par la fonction readabsolutesectors */
struct diskaddrpacket
{
char packetsize ; /* Size of Packet, generally 10H */
char reserved ; /* Reserved (0) */
int blockcount ; /* Number of Blocks to Transfer */
char far *bufferaddress ; /* address to Transfer
Buffer */
unsigned long blocknumber[2] ; /* Starting Absolute
Block Number */
} ;
void main()
{
int no_par,i;
clrscr();
no_par = 0;
All_partition_information (star_sec,&no_par, &sec, buffer,
report_par);
printf(" \n\n Total Partitions in Disk = %d\n ",
no_par);
for(i=0;i<no_par;i++)
{
printf("\n Starting Sector Number of Partition %d =
%lu " , i+1, star_sec[i]);
}
printf("\n");
getch();
}
La sortie du programme sera affichée comme suit :
Partition 1 - FAT32
Partition 2 - FAT32
Partition 3 - FAT32
Nombre total de partitions sur le disque = 3
Numéro de secteur de départ de la partition 1 = 63
Numéro de secteur de départ de la partition 2 = 11277693
Numéro de secteur de départ de la partition 3 = 25623738
Commentaires sur le codage :
La structure diskaddrpacket est utilisée pour lire le format de paquet d'adresse de disque, à utiliser par la fonction readabsolutesectors.
La fonction All_partition_information( ) est utilisée pour trouver tous les paramètres de toutes les partitions à partir de l'entrée de partition.
Bien que dans ce programme, nous ayons affiché uniquement le système de fichiers et les informations relatives au secteur de toutes les partitions logiques disponibles sur le disque, vous pouvez également imprimer les informations d'autres paramètres d'informations de partition en utilisant la fonction All_partition_information() avec un peu plus de printf.
Le codage de la fonction est le suivant :
/* Fonction pour trouver toutes les partitions logiques’ informations lisant leur entrée de partition */
All_partition_information( unsigned long *star_sec,
unsigned *no_par,
long *sec, char *buffer,
unsigned char *report_par )
{
unsigned long fat_check;
unsigned long *sectors_part;
static long se_p;
int temp_var1,active_offset,active_pos=0,i, extended_pos=0, partloc1;
unsigned long b_sec,se;
unsigned char active_par;
long relative_sec;
long no_sectors;
if(*sec==0 || *sec==1)
se_p=0;
do{
se=*sec;
/* Lire le secteur absolu spécifié par *sec */
readabsolutesectors (drive_num,*sec,1,buffer);
/* ***** vérifier la partition active ***** */
if(*sec==se && *no_par==0) /*if primary
partition */
{
*sec=se=0;
for(active_offset=446; active_offset<=494;active_offset+=16)
{
active_par=buffer[active_offset];
if(active_par==0x80) /* check for active
partition */
break;
else
active_pos++; /* position of active
partition */
}
/* pour une partition étendue */
for(active_offset=450; active_offset<=511;active_offset+=16)
{
active_par=buffer[active_offset];
if(active_par==0x05 | active_par==0x0F)
/*check for extended partition */
break;
else
extended_pos++; /*position of extended
partition */
}
if(active_pos==4)
active_pos=1;
if(extended_pos==4)
extended_pos=1;
partloc1=0x1C0+extended_pos*16;
}
else
{
active_pos=0;
extended_pos=1;
partloc1=0x1D0;
if(se_p!=0)
{
*sec=se=se_p; /*starting of extended
partition */
}
}
/* Secteurs relatifs dans la partition */
relative_sec= *(long non signé *)(buffer+454+active_pos*16);
/* Nombre de secteurs dans la partition */
no_sectors=*(long *)(buffer+458+active_pos*16);
/* Identifier l'octet indicateur du système de fichiers */
if( buffer[0x1C2+active_pos*16]==0x04 ||
buffer[0x1C2+active_pos*16]==0x05 ||
buffer[0x1C2+active_pos*16]==0x06 ||
buffer[0x1C2+active_pos*16]==0x0B ||
buffer[0x1C2+active_pos*16]==0x0C ||
buffer[0x1C2+active_pos*16]==0x0E ||
buffer[0x1C2+active_pos*16]==0x0F ||
buffer[0x1C2+active_pos*16]==0x07)
{
switch(buffer[0x1C2+active_pos*16])
{
/* For NTFS Partition */
case 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*no_par+1);
break;
/* Pour les partitions FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Pour les partitions FAT16 */
case 0x04:
case 0x06:
case 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*no_par+1);
break;
} // End of the Switch
b_sec=*sec+relative_sec;
sectors_part[*no_par]=no_sectors; /* Array to store Number of sectors of partitions */
} //End of if Condition
else
{ /* if partition indicator not match */
if(*sec==0)
{ no_par=0;
break;
}
if((fat_check!=0x3631)&&(fat_check!=0x3233))
b_sec=*sec=0;
}
if((b_sec!=0)&&(sec!=0))
{
star_sec[*no_par]=b_sec;
(*no_par)++;
}
else
break;
/* vérifier si la partition étendue existe */
if(buffer[0x1C2+extended_pos*16]==0x05 ||
buffer[0x1C2+extended_pos*16]==0x0F )
{
temp_var1=(unsigned )buffer[partloc1];
*sec=temp_var1 & 0x003F; /* sector of
extended
partition */
if(*sec!=0)
{
se_p=se+relative_sec+no_sectors;
*sec=se_p;
}
else
{ *sec=-1;
break;
}
} //close of if statement
else
{
if(*sec>0)
*sec=-1;
break;
}
} while(1); // close of do–while loop
/* recherche d'autres partitions principales non actives sur le secteur 0 */
if(*sec==0)
{
for(i=0;i<4;i++)
{
active_par=buffer[446+i*16];
/* Identifiez l'octet de l'indicateur de système de fichiers */
if((buffer[0x1C2+i*16]==(char)0x06 ||
buffer[0x1C2+i*16]==(char)0x0B ||
buffer[0x1C2+i*16]==(char)0x0C ||
buffer[0x1C2+i*16]==(char)0x07 ||
buffer[0x1C2+i*16]==(char)0x0E ||
buffer[0x1C2+i*16]==(char)0x04) && active_par!=0x80)
{
switch(buffer[0x1C2+active_pos*16])
{
/* Pour partition NTFS */
case 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*no_par+1);
break;
/* Pour les partitions FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Pour les partitions FAT16 */
case 0x04:
case 0x06:
case 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*no_par+1);
break;
} // End of switch
/* secteurs relatifs Nombre de partition */
relative_sec=*(long *)(buffer+454+i*16);
no_sectors=*(long *)(buffer+458+i*16); /* number of
sectors in
partition*/
sectors_part[*no_par]=no_sectors; /* Array to store
Number of
sectors of
partitions */
*sec=star_sec[*no_par]=relative_sec;
(*no_par)++;
}
} //loop close of for(i=0;i<4;i++)
} //loop close of if(*sec==0)
return;
}
Commentaires sur le codage :
La fonction commence à lire les informations sur les partitions à partir du MBR, puis lit les MBR étendus si nécessaire. La fonction readabsolutesectors lit le secteur absolu, spécifié par *sec.
sectors_part[*no_par] est le tableau pour stocker le nombre de secteurs de partitions. Le numéro de partition est spécifié par *no_par à partir de 0.
no_sectors est le nombre de secteurs dans la partition et relative_sec est le numéro de secteur relatif pour cette partition.
star_sec[*no_par] est le tableau pour stocker les numéros de secteur des partitions. Le numéro de partition est spécifié par *no_par à partir de 0.
star_cyl, star_hea et star_sec sont les tableaux qui conservent les informations de démarrage de chaque partition en termes de CHS. star_cyl stocke les informations des cylindres de démarrage, star_hea stocke les informations des têtes de démarrage et star_sec stocke les informations des secteurs de démarrage des partitions.
Pour la description de la fonction readabsolutesectors, reportez-vous aux chapitres donnés précédemment dans ce livre.
Modifier le MBR par programmation
L'exemple de programme pour montrer, comment nous pouvons modifier les valeurs de l'entrée de table de partition MBR a été donné ci-dessous. Le programme modifie les valeurs de la seconde entrée de partition de la table de partition MBR.
Le codage du programme a été donné ci-dessous :
/* Programme pour modifier les valeurs de l'entrée de la table de partition du MBR */
# inclure <bios.h>
/* structure pour lire l'entrée de partition à partir de la table de partition */
struct partition
{
unsigned char bootable ; /* Active Partition
Byte */
unsigned char start_side ; /* Starting Head */
unsigned int start_sec_cyl ; /* combination of
Starting sector and
cylinder number */
unsigned char parttype ; /* File system
Indicator Byte */
unsigned char end_side ; /* Ending Head */
unsigned int end_sec_cyl ; /* combination of
Starting sector and
cylinder number */
unsigned long part_beg ; /* Relative Sector
Number */
unsigned long plen ; /* Partition length in
sectors */
} ;
/* Structure pour lire le MBR */
struct part
{
unsigned char master_boot[446] ; /* IPL (Initial
Program Loader)*/
struct partition pt[4] ; /* Partition table*/
int lasttwo ; /* Magic Number */
} ;
struct part p ;
void main()
{
unsigned int t1,t2;
clrscr();
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* display the partition
Table information */
getch();
/* Supposons que nous voulons modifier les informations de partition de la deuxième entrée de partition de la table de partition du MBR, avec ces valeurs */
p.pt[1].bootable = 0x80 ; /* Partition de démarrage active */
p.pt[1].parttype = 0x7 ; /* Partition NTFS */
p.pt[1].start_side = 0 ; /* Tête de départ =0 */
p.pt[1].end_side = 31 ; /* Tête de fin == 31 */
p.pt[1].part_beg = 808416;/* Secteur Relatif = 808416 */
p.pt[1].plen = 405216 ; /* Total des secteurs dans la partition = 405216 */
/* Écrire de nouvelles informations dans le MBR *\
/* Pour écrire les valeurs dans la table de partition MBR, décommentez la fonction biosdisk indiquée ci-dessous */
// biosdisk ( 3, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the Modified
Information */
getch();
}
Commentaires sur le codage :
Le programme donné ci-dessus est un exemple de programme pour montrer comment nous pouvons modifier les valeurs de l'entrée de table de partition de MBR. Si vous souhaitez modifier les valeurs de l'entrée de partition pour ces partitions logiques, qui se trouvent dans la partition étendue, vous devez modifier les valeurs dans la table de partition du MBR étendu .
Les valeurs qui ont été données ici pour modifier l'entrée de la table de partition sont juste pour démontrer, comment modifier. Ne modifiez jamais la table de partition avec des valeurs illégales ou illogiques. Ce faisant, la partition entière peut devenir inaccessible.
La partition de structure est utilisée pour lire l'entrée de partition à partir de la table de partition et la partie de structure pour lire le MBR. Pour effectuer réellement les modifications dans la table de partition, décommentez la fonction biosdisk( ).
Si vous souhaitez modifier les valeurs de début et de fin, les secteurs et les numéros de cylindre de la partition, calculez les valeurs, comme décrit dans les commentaires du programme pour lire et afficher la table de partition de MBR, discuté au début de ce chapitre.
Page modifiée le: 09/03/2022