Kapitel – 12
Lesen und Ändern von MBR mit Programmierung
Master Boot Record (MBR) oder Master Partition Table (MPT)
Der Master Boot Record (MBR) oder manchmal auch als Master Partition Table (MPT) bezeichnet, wird auf der Festplatte erstellt, indem der Befehl FDISK.EXE von DOS ausgeführt wird.
Der MBR enthält ein kleines Programm zum Laden und Starten der aktiven (oder bootfähigen) Partition von der Festplatte. Der Master Boot Record enthält Informationen über alle vier primären Partitionen auf der Festplatte, wie Startsektor, Endsektor, Größe der Partition usw.
Der MBR befindet sich im absoluten Sektor 0 oder wir können sagen bei Zylinder 0, Kopf 0 und Sektor1, und wenn mehr als eine Partition auf der Festplatte vorhanden ist, gibt es Extended Master Boot Records, die sich am Anfang jedes erweiterten Partitionsvolumens befinden.
Eine detaillierte Beschreibung finden Sie im Kapitel „Logischer Ansatz für Festplatten und Betriebssysteme“, das weiter oben in diesem Buch besprochen wurde.
Master-Boot-Record-Format
Wir können das Festplattenlaufwerk in mehrere logische Laufwerke partitionieren, denen im Allgemeinen von DOS ein eigener Laufwerksbuchstabe zugewiesen wird). Es kann immer nur eine Partition als aktive (oder bootfähige) Partition markiert werden.
Der Master Boot Record hat die Grenze von vier Einträgen in der Master-Partitionstabelle. Der Speicherort des Extended Master Boot Record kann jedoch mit Hilfe des Master Boot Record ermittelt werden, der erweiterte Partitionstabellen enthält, deren Format genau das gleiche ist wie das der Hauptpartitionstabelle, außer dass es keinen Bootcode gibt und dieser Platz von 446 Bytes normalerweise ist reserviert für den Bootcode und bleibt leer.
Alle 512 Bytes des Master Boot Record sind wie folgt gebrochen, wie in der Tabelle angegeben:
Alle erweiterten Partitionen sollten innerhalb des Speicherplatzes existieren, der durch den erweiterten Partitionseintrag reserviert ist. Nur zwei der erweiterten Partitionen sollen verwendet werden, die erste als normale Partition und die zweite als eine weitere erweiterte Partition, falls vorhanden.
Mit Hilfe einer Master-Partitionstabelle können wir also den Speicherort einer anderen erweiterten Master-Partitionstabelle daneben ermitteln, falls vorhanden.
Eingabeformat der Partitionstabelle
Das Format des Partitionstabelleneintrags einer beliebigen Partition im MBR ist in der nächsten Tabelle angegeben. Jeder Partitionseintrag eines beliebigen MBR kann in die folgenden Bytes mit ihren spezifischen Bedeutungen aufgeteilt werden:
Schreibprogramm zum Lesen der Partitionstabelle des MBR
Als nächstes wurde das Programm zum Lesen aller vier Partitionseinträge aus der Partitionstabelle des MBR angegeben. Das Programm zeigt alle Parameter der Partitionsinformationen an, die in die Partitionstabelle des MBR geschrieben sind.
Die Codierung des Programms ist wie folgt:
/* Programm zum Lesen der MBR-Partitionstabelle */
# 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 */
} ;
/* Struktur zum Lesen von 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();
/* Lesen Sie den ersten Sektor der ersten Festplatte */
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the information of MBR
Partition Table */
getch();
}
/* Funktion zum Anzeigen der Informationen der Partitionstabelle des 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;
}
Die von der Ausgabe des Programms bereitgestellten Informationen werden etwa wie folgt angezeigt:
Anmerkungen zur Codierung:
Die Strukturpartition wird verwendet, um die verschiedenen Parameter des Partitionseintrags der Partition in der Partitionstabelle des MBR zu lesen. Der Strukturteil wird zum Lesen von MBR-Informationen verwendet.
Die Funktion Anzeige() zeigt die Informationen der Parameter der MBR-Partitionstabelle auf dem Bildschirm an. Wie wir die Ausgabe des Programms sehen, werden der Start- und Endzylinder und die Sektornummer wie folgt angezeigt:
Starting Sector = 1
Starting Cylinder = 0
Ending Sector = 63
Ending Cylinder = 701
Diese Sektor- und Zylindernummern werden aus der Kombination zweier Bytes berechnet. Die folgenden Tabellen zeigen, wie diese Zahlen berechnet werden:
Also Start C-H-S der Partition = 0-0-1.
In ähnlicher Weise wurden die Codierung für den Endzylinder und die Sektornummer der Partition in der nächsten Tabelle angegeben:
Somit ist das Ende C-H-S der Partition = 701-254-63.
Programm, um alle logischen Partitionen und ihre Informationen zu finden
Das zuvor besprochene Programm bestand darin, die Partitionsinformationen aus der Partitionstabelle des MBR zu lesen. Aber nur durch Lesen des MBR können wir keine Informationen über andere logische Partitionen erhalten, die sich in der erweiterten Partition der Festplatte befinden.
Das haben wir bereits besprochen Master Boot Record hat das Limit von vier Einträgen in der Master-Partitionstabelle. Der Speicherort des Extended Master Boot Record kann jedoch mit Hilfe des Master Boot Record ermittelt werden, der enthält Erweiterte Partitionstabellen, deren Format genau das gleiche ist wie das der Hauptpartitionstabelle.
Alle erweiterten Partitionen sollten innerhalb des Speicherplatzes existieren, der durch den erweiterten Partitionseintrag reserviert ist. Nur zwei der erweiterten Partitionen sollen verwendet werden, die erste als normale Partition und die zweite als eine weitere erweiterte Partition, falls vorhanden.
Mit Hilfe einer Master-Partitionstabelle können wir also den Speicherort einer anderen erweiterten Master-Partitionstabelle daneben ermitteln, falls vorhanden.
Das folgende Programm dient zum Auffinden aller logischen Partitionen und ihrer Partitionseintragsinformationen, Lesen von MBR und erweiterten MBRs von der Festplatte. Die Codierung des Programms ist wie folgt:
/* Programm zum Lesen der Parameter aller logischen Partitionen auf der Festplatte */
#include<dos.h>
har buffer[512], report_par[20];
unsigned drive_num =0x80;
unsigned long star_sec[20], sec;
/* Struktur des Plattenadresspaketformats, das von der readabsolutesectors-Funktion verwendet werden soll */
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();
}
Die Ausgabe des Programms wird ähnlich wie folgt angezeigt:
Partition 1 - FAT32
Partition 2 - FAT32
Partition 3 - FAT32
Gesamtzahl der Partitionen auf der Festplatte = 3
Startsektornummer von Partition 1 = 63
Startsektornummer von Partition 2 = 11277693
Startsektornummer von Partition 3 = 25623738
Anmerkungen zur Codierung:
Die Struktur diskaddrpacket wird verwendet, um das Disk Address-Paketformat zu lesen, das von der readabsolutesectors-Funktion verwendet wird.
Die Funktion Alle_Partitionsinformationen( ) wird verwendet, um alle Parameter aller Partitionen aus dem Partitionseintrag zu finden.
Obwohl wir in diesem Programm nur das Dateisystem und die relativen Sektorinformationen aller verfügbaren logischen Partitionen auf der Festplatte angezeigt haben, können Sie auch die Informationen anderer Parameter der Partitionsinformationen ausdrucken, indem Sie die Funktion verwenden Alle_Partitionsinformationen( ) mit etwas mehr printf.
Die Codierung der Funktion ist wie folgt:
/* Funktion zum Suchen aller logischen Partitionen’ Informationen, die ihren Partitionseintrag lesen */
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;
/* Absoluten Sektor lesen, angegeben durch *sec */
readabsolutesectors (drive_num,*sec,1,buffer);
/* ***** nach aktiver Partition suchen ***** */
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 */
}
/* für erweiterte Partition */
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 */
}
}
/* Relative Sektoren in der Partition */
relative_sec= *(unsigned long *)(buffer+454+active_pos*16);
/* Anzahl der Sektoren in der Partition */
no_sectors=*(long *)(buffer+458+active_pos*16);
/* Identifizieren Sie das File System Indicator Byte */
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;
/* Für FAT32-Partition */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Für FAT16-Partition */
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;
/* Überprüfen, ob eine erweiterte Partition vorhanden ist */
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
/* Suchen Sie nach anderen nicht aktiven primären Partitionen in Sektor 0 */
if(*sec==0)
{
for(i=0;i<4;i++)
{
active_par=buffer[446+i*16];
/* Identifizieren Sie das Byte des Dateisystemindikators */
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])
{
/* Für NTFS-Partition */
case 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*no_par+1);
break;
/* Für FAT32-Partition */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Für FAT16-Partition */
case 0x04:
case 0x06:
case 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*no_par+1);
break;
} // End of switch
/* relative Sektoren Nummer der 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;
}
Anmerkungen zur Codierung:
Die Funktion startet Lesen der Partitionsinformationen aus dem MBR und liest dann die Erweiterte MBRs Falls erforderlich. Die Funktion readabsolutesectors liest den absoluten Sektor, spezifiziert durch *sec.
sector_part[*no_par] ist das Array zum Speichern der Anzahl der Sektoren von Partitionen. Die Partitionsnummer wird durch *no_par beginnend bei 0 angegeben.
no_sectors ist die Anzahl der Sektoren in der Partition und relative_sec ist die relative Sektornummer für diese Partition.
star_sec[*no_par] ist das Array zum Speichern der Sektornummern der Partitionen. Die Partitionsnummer wird durch *no_par beginnend bei 0 angegeben.
star_cyl, star_hea und star_sec sind die Arrays, die die Informationen zum Starten jeder Partition in Form von CHS halten. star_cyl speichert die Informationen von Startzylindern, star_hea speichert die Informationen von Startköpfen und star_sec speichert die Informationen von Startsektoren von Partitionen.
Zur Beschreibung der Funktion readabsolutesectors siehe die Kapitel weiter oben in diesem Buch.
Ändern Sie den MBR durch Programmierung
Das Beispielprogramm soll zeigen, wie wir die Werte von ändern können MBR-Partitionstabelleneintragwurde unten angegeben. Das Programm modifiziert die Werte als zweites Partitionseintrag der MBR-Partitionstabelle.
Die Codierung des Programms ist unten angegeben:
/* Programm zum Ändern der Werte des Partitionstabelleneintrags des MBR */
# include <bios.h>
/* Struktur zum Lesen des Partitionseintrags aus der Partitionstabelle */
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 */
} ;
/* Struktur zum Lesen von 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();
/* Nehmen wir an, dass wir die Partitionsinformationen des zweiten Partitionseintrags aus der Partitionstabelle des MBR mit diesen Werten ändern möchten */
p.pt[1].bootable = 0x80; /* Active Boot Partition */
p.pt[1].parttype = 0x7; /* NTFS Partition */
p.pt[1].start_side = 0; /* Starting Head =0 */
p.pt[1].end_side = 31; /* Ending Head == 31 */
p.pt[1].part_beg = 808416;/* Relative Sector = 808416 */
p.pt[1].plen = 405216; /* Total Sectors in Partition = 405216 */
/* Neue Informationen in MBR schreiben *\
/* Um die Werte in die MBR-Partitionstabelle zu schreiben, kommentieren Sie die unten angegebene biosdisk-Funktion aus */
// biosdisk ( 3, 0x80, 0, 0, 1, 1, & p ) ;
display(); /* Display the Modified
Information */
getch();
}
Anmerkungen zur Codierung:
Das oben angegebene Programm ist ein Beispielprogramm, um zu zeigen, wie wir die Werte von ändern können Partitionstabelleneintrag von MBR. Wenn Sie die Werte des Partitionseintrags für solche ändern möchten logische Partitionen, die darin liegen erweiterte Partition, Sie müssen die Werte in ändern Partitionstabelle des erweiterten MBR.
Die Werte, die hier angegeben wurden, um den Partitionstabelleneintrag zu ändern, dienen nur zur Demonstration, wie man Änderungen vornimmt. Ändern Sie niemals die Partitionstabelle mit illegalen oder unlogischen Werten. Dadurch kann die gesamte Partition unzugänglich werden.
Die Strukturpartition wird verwendet, um den Partitionseintrag aus der Partitionstabelle und den Strukturteil zu lesen, um den MBR zu lesen. Um die Änderungen in der Partitionstabelle tatsächlich vorzunehmen, kommentieren Sie die aus Biosdisk( ) Funktion.
Wenn Sie die Werte für Anfang und Ende, Sektoren und Zylindernummern der Partition ändern möchten, berechnen Sie die Werte, wie in den Kommentaren des Programms zum Lesen und Anzeigen der Partitionstabelle des MBR beschrieben am Anfang dieses Kapitels.
Seite Geändert am: 08/03/2022