Kapitel – 12
Lesen und Ändern des MBR mithilfe der Programmierung
Master Boot Record (MBR) oder Master Partition Table (MPT)
Der Master Boot Record (MBR), manchmal auch Master Partition Table (MPT) genannt, wird auf der Festplatte durch Ausführen des DOS-Befehls FDISK.EXE erstellt.
Der MBR enthält ein kleines Programm zum Laden und Ausführen der aktiven (oder Boot-)Partition von der Festplatte. Der Master Boot Record enthält Informationen zu allen vier primären Partitionen auf der Festplatte wie Startsektor, Endsektor, Partitionsgröße usw.
MBR befindet sich im absoluten Sektor 0 oder, anders ausgedrückt, in Zylinder 0, Kopf 0 und Sektor 1. Falls sich auf der Festplatte mehr als eine Partition befindet, befinden sich am Anfang jedes Datenträgers der erweiterten Partition erweiterte Master Boot Records.
Eine ausführliche Beschreibung finden Sie im Kapitel „Ein logischer Ansatz für Festplatten und Betriebssysteme“, das weiter oben in diesem Buch besprochen wurde.
Master-Boot-Record-Format
Wir können die Festplatte in mehrere logische Laufwerke partitionieren, denen DOS normalerweise einen eigenen Laufwerksbuchstaben zuweist. Es kann immer nur eine Partition als aktive (oder Boot-)Partition markiert werden.

Der Master Boot Record ist auf vier Einträge in der primären Partitionstabelle begrenzt. Der Speicherort des erweiterten MBR kann jedoch mithilfe des MBR ermittelt werden, der die erweiterten Partitionstabellen enthält. Dieser hat dasselbe Format wie die primäre Partitionstabelle, mit der Ausnahme, dass er keinen Startcode enthält und dass 446 Byte Speicherplatz normalerweise für den Startcode reserviert und leer gelassen werden.
Die gesamten 512 Bytes des Master Boot Record sind wie in der Tabelle dargestellt aufgeteilt:

Alle erweiterten Partitionen müssen in dem durch den erweiterten Partitionseintrag reservierten Speicherplatz vorhanden sein. Es ist vorgesehen, dass nur zwei der erweiterten Partitionen verwendet werden: die erste als normale Partition und die zweite als weitere erweiterte Partition (sofern vorhanden).
Mithilfe einer Masterpartitionstabelle können wir also den Speicherort einer anderen, erweiterten Masterpartitionstabelle daneben ermitteln, sofern eine vorhanden ist.
Format der Partitionstabelleneinträge
Das Format der Partitionstabelleneinträge aller Partitionen im MBR wird in der folgenden Tabelle angezeigt. Jeder Partitionseintrag eines MBR kann in die folgenden Bytes mit ihrer spezifischen Bedeutung zerlegt werden:

Schreiben eines Programms zum Lesen der MBR-Partitionstabelle
Unten finden Sie ein Programm zum Lesen aller vier Partitionseinträge aus der MBR-Partitionstabelle. Das Programm zeigt alle Parameter der Partitionsinformationen an, die in der MBR-Partitionstabelle aufgezeichnet sind.
Die Programmkodierung sieht folgendermaßen aus:
/* Programm zum Lesen der MBR-Partitionstabelle */
# include <bios.h>
/* Struktur zum Lesen des Partitionseintrags aus der Partitionstabelle */
Strukturabschnitt
{
vorzeichenloser Charakter, bootfähig; /* Aktives Byte des Abschnitts */
unsigned char start_side ;/* Startkopf */
vorzeichenlose Ganzzahl start_sec_cyl; /* Kombination
Startsektor und
Zylindernummer */
vorzeichenloser Zeichenteiltyp; /* Dateisystem
Indikatorbyte */
vorzeichenloses Zeichen Endseite; /* Header beenden */
vorzeichenlose Ganzzahl end_sec_cyl; /* Kombination
Startsektor und
Zylindernummer */
vorzeichenloser langer Teilanfang; /* Relativer Sektor
Nummer */
vorzeichenlose lange Ganzzahl; /* Abschnittslänge in
Sektor */
} ;
/* Struktur zum Lesen des MBR */
Teil der Struktur
{
unsigned char master_boot[446] ; /* IPL (Anfängliche
Programmlader)*/
Strukturpartition pt[4]; /* Partitionstabelle */
int letztezwei; /* Magische Zahl */
} ;
Teil der Struktur p;
ungültiges main()
{
clrscr();
/* Lesen des ersten Sektors der ersten Festplatte */
Biosdisk (2, 0x80, 0, 0, 1, 1, &p);
Anzeige(); /* MBR-Informationen anzeigen
Partitionstabelle */
erhalten();
}
/* Funktion zum Anzeigen von Informationen zur MBR-Partitionstabelle */
Anzeige()
{
vorzeichenlose Ganzzahl s_sec, s_trk, e_sec, e_trk, i, t1, t2;
Zeichentyp[20], Boot[5] ;
printf("\n\nTeil. Ursprünglicher Ladeort
Endgültiger Standort Relative Menge");
printf("\nTyp Seite Zylinder Sektor
Seite Zylinder Sektor Sektoren Sektoren\n");
für (i = 0; i <= 3; i++)
{
wenn (p.pt[i].bootable == 0x80)
strcpy (boot, "Ja");
anders
strcpy (boot, "Nein");
Schalter ( p.pt[i].parttype )
{
Fall 0x00:
strcpy (Typ, „Unbenutzt“); Unterbrechung;
Fall 0x1:
strcpy (Typ „FAT12“); Unterbrechung;
Fall 0x2:
strcpy (Typ „Xenix“); Unterbrechung;
Fall 0x3:
strcpy (Typ „Xenix:usr“); Unterbrechung;
Fall 0x4:
strcpy (Typ „FAT16<32M“); Unterbrechung;
Fall 0x5:
strcpy (Typ „DOS-Ext.“); Unterbrechung;
Fall 0x6:
strcpy (Typ „FAT16>32M“); Unterbrechung;
Fall 0x7:
strcpy (Typ „NTFS“); Unterbrechung;
Fall 0x0b:
strcpy (Typ „FAT32“); Unterbrechung;
Fall 0x0c:
strcpy (Typ „FAT32-LBA“); Unterbrechung;
Fall 0x0d:
strcpy (Typ „VFAT16“); Unterbrechung;
Fall 0x0e:
strcpy (Typ „VFAT16-LBA“); Unterbrechung;
Fall 0x0f:
strcpy (Typ „VFAT EXT“); Unterbrechung;
Fall 0x17:
strcpy (Typ „HPFS“); Unterbrechung;
Fall 0x81:
strcpy (Typ „Altes LINUX“); Unterbrechung;
Fall 0x82:
strcpy (Typ „LinuxSwap“); Unterbrechung;
Fall 0x83:
strcpy (Typ „LinuxNative“); Unterbrechung;
Fall 0x85:
strcpy (Typ „Linux Ext.“); Unterbrechung;
Standard :
strcpy (Typ „Unbekannt“); Unterbrechung;
}
s_sec = ( p.pt[i].start_sec_cyl & 0x3f ) ; /* Start
Sektor der
Partition */
t1 = ( p.pt[i].start_sec_cyl & 0xff00 ) >> 8 ;
t2 = (p.pt[i].start_sec_cyl & 0x00c0) << 2;
s_trk = t1 | t2 ; /* Startzylinder */
e_sec = ( p.pt[i].end_sec_cyl & 0x3f ) ; /*Endsektor */
t1 = ( p.pt[i].end_sec_cyl & 0xff00 ) >> 8 ;
t2 = (p.pt[i].end_sec_cyl & 0x00c0) << 2;
e_trk = t1 | t2 ; /* Endzylinder */
printf ( "\n%6s %3s", Typ, Booten ) ;
printf ( "%4d %6d %8d", p.pt[i].start_seite, 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 ) ;
}
gebe 0 zurück;
}
Die durch die Programmausgabe bereitgestellten Informationen werden in etwa wie folgt angezeigt:

Anmerkungen zur Kodierung:
Die Strukturpartition wird verwendet, um die verschiedenen Parameter des Partitionseintrags der Partition in der Partitionstabelle des MBR zu lesen. Der Strukturteil wird verwendet, um MBR-Informationen zu lesen.
Die Funktion display() zeigt die Informationen zu den Parametern der MBR-Partitionstabelle auf dem Bildschirm an. Wie wir in der Ausgabe des Programms sehen, werden der Start- und Endzylinder sowie die Sektornummer wie folgt angezeigt:
Startsektor = 1
Startzylinder = 0
Endsektor = 63
Endzylinder = 701
Diese Sektor- und Zylindernummern werden aus der Kombination von zwei Bytes berechnet. Die folgenden Tabellen zeigen, wie diese Nummern berechnet werden:

Daher ist der Start-CHS der Partition = 0-0-1.
Ebenso sind die Kodierung für den Endzylinder und die Sektornummer der Partition in der nächsten Tabelle angegeben:

Somit lautet die End-CHS der Partition 701-254-63.
Programm zum Finden aller logischen Partitionen und ihrer Informationen
Das Programm, das wir zuvor besprochen haben, sollte die Partitionsinformationen aus der Partitionstabelle des MBR lesen. Aber nur durch das Lesen des MBR können wir keine Informationen über andere logische Partitionen erhalten, die sich in der erweiterten Partition der Festplatte befinden.
Wir haben bereits besprochen, dass der Master Boot Record auf vier Einträge in der Master Partition Table begrenzt ist . Der Speicherort des Extended Master Boot Record kann jedoch mithilfe des Master Boot Record ermittelt werden, der Extended Partition Tables enthält , deren Format genau dem der Hauptpartitionstabelle entspricht.
Alle erweiterten Partitionen sollten innerhalb des durch den erweiterten Partitionseintrag reservierten Speicherplatzes vorhanden sein. Nur zwei der erweiterten Partitionen sind für die Verwendung vorgesehen, die erste als normale Partition und die zweite als weitere erweiterte Partition, sofern vorhanden.
Mithilfe einer Masterpartitionstabelle können wir somit den Speicherort einer anderen, erweiterten Masterpartitionstabelle daneben ermitteln, sofern vorhanden.
Das folgende Programm dient zum Auffinden aller logischen Partitionen und ihrer Partitionseintragsinformationen und zum Lesen von MBR und erweiterten MBRs von der Festplatte. Die Codierung des Programms lautet wie folgt:
/* Programm zum Lesen der Parameter aller auf der Festplatte vorhandenen logischen Partitionen */
#include<dos.h>
hat Puffer[512], report_par[20];
vorzeichenlose Laufwerksnummer =0x80;
unsigned long star_sec[20], Sek.;
/* Struktur des Disk-Adresspaketformats, das von der Funktion readabsolutesectors verwendet werden soll */
Struktur Diskaddrpacket
{
char packetsize ; /* Größe des Pakets, normalerweise 10H */
char reserviert; /* Reserviert (0) */
int blockcount ; /* Anzahl der zu übertragenden Blöcke */
char far *bufferaddress ; /* zu übertragende Adresse
Puffer */
unsigned long blocknumber[2] ; /* Startabsoluter Wert
Blocknummer */
} ;
void main()
{
int nicht gerade,i;
clrscr();
nicht_eventuell = 0;
Alle_Partitionsinformationen (Star_Sek.,&kein_Par., &Sek., Puffer,
Bericht_Par);
printf(" \n\n Gesamtzahl der Partitionen auf der Festplatte = %d\n ",
nein_gerade);
für (i = 0; i < no_par; i++)
{
printf("\n Startsektornummer der Partition %d =
%lu " , i+1, Stern_Sek[i]);
}
printf("\n");
getch();
}
Die Ausgabe des Programms wird ungefähr wie folgt angezeigt:
Partition 1 - FAT32
Partition 2 - FAT32
Partition 3 - FAT32
Gesamtzahl der Partitionen auf der Festplatte = 3
Startsektornummer der Partition 1 = 63
Startsektornummer der Partition 2 = 11277693
Startsektornummer der Partition 3 = 25623738
Anmerkungen zur Kodierung:
Die Struktur „diskaddrpacket“ wird zum Lesen des Disk-Adresspaketformats verwendet, das von der Funktion „readabsolutesectors“ verwendet werden soll.
Mit der Funktion All_partition_information( ) werden alle Parameter aller Partitionen aus dem Partitionseintrag ermittelt.
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 mit der Funktion All_partition_information() und einigen weiteren printf-Befehlen auch Informationen zu anderen Parametern der Partitionsinformationen ausdrucken .
Die Kodierung der Funktion lautet wie folgt:
/* Funktion zum Suchen der Informationen aller logischen Partitionen durch Lesen ihres Partitionseintrags */
Alle_Partitionsinformationen( unsigned long *star_sec,
unsigniertes *no_par,
lang *Sek., char *Puffer,
unsigned char *report_par )
{
vorzeichenloser langer Fat_Check;
vorzeichenloser langer *Sektorenteil;
statisches langes se_p;
int temp_var1, aktiver_Offset, aktive_Position = 0, i, erweiterte_Position = 0, partloc1;
vorzeichenloses langes b_sec,se;
vorzeichenloses Zeichen active_par;
lange relative_Sekunde;
lange keine_Sektoren;
wenn(*sec==0 || *sec==1)
se_p=0;
Tun{
se=*Sekunde;
/* Absoluten Sektor lesen, angegeben durch *sec */
readabsolutesectors (Laufwerknummer,*Sek.,1,Puffer);
/* ***** Prüfung auf aktive Partition ***** */
if(*sec==se && *no_par==0) /*wenn primär
Partition */
{
*Sek=se=0;
für (Aktivoffset = 446; Aktivoffset <= 494; Aktivoffset + = 16)
{
active_par=Puffer[active_offset];
if(active_par==0x80) /* auf aktiv prüfen
Partition */
brechen;
anders
active_pos++; /* Position des aktiven
Partition */
}
/* für erweiterte Partition */
für (Aktiv_Offset = 450; Aktiv_Offset <= 511; Aktiv_Offset + = 16)
{
active_par=Puffer[active_offset];
wenn(active_par==0x05 | active_par==0x0F)
/*auf erweiterte Partition prüfen */
brechen;
anders
extended_pos++; /*Position der erweiterten
Partition */
}
wenn(active_pos==4)
aktive_position=1;
wenn(erweiterte_position==4)
erweiterte_position=1;
Teillokal1 = 0x1C0 + erweiterte_Position * 16;
}
anders
{
aktive_position=0;
erweiterte_position=1;
Teillokal1 = 0x1D0;
wenn(se_p!=0)
{
*sec=se=se_p; /*Starten der erweiterten
Partition */
}
}
/* Relative Sektoren in der Partition */
relative_sec= *(unsigned long *)(Puffer+454+active_pos*16);
/* Anzahl der Sektoren in der Partition */
keine_Sektoren=*(lang *)(Puffer+458+aktive_Position*16);
/* Identifizieren Sie das Dateisystem-Indikatorbyte */
wenn (Puffer [0x1C2 + Active_Pos * 16] == 0x04 ||
Puffer[0x1C2+active_pos*16]==0x05 ||
Puffer[0x1C2+active_pos*16]==0x06 ||
Puffer[0x1C2+active_pos*16]==0x0B ||
Puffer[0x1C2+active_pos*16]==0x0C ||
Puffer[0x1C2+active_pos*16]==0x0E ||
Puffer[0x1C2+active_pos*16]==0x0F ||
Puffer[0x1C2+active_pos*16]==0x07)
{
Schalter(Puffer[0x1C2+active_pos*16])
{
/* Für NTFS-Partition */
Fall 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*nicht_gerade+1);
brechen;
/* Für FAT32-Partition */
Fall 0x0B:
Fall 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*nicht_gerade+1);
brechen;
/* Für FAT16-Partition */
Fall 0x04:
Fall 0x06:
Fall 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*nicht_gerade+1);
brechen;
} // Ende des Schalters
b_sec=*sec+relative_sec;
sector_part[*no_par]=no_sectors; /* Array zum Speichern der Anzahl der Sektoren von Partitionen */
} //Ende der if-Bedingung
anders
{ /* wenn der Partitionsindikator nicht übereinstimmt */
wenn(*sec==0)
{ kein_Par=0;
brechen;
}
wenn((fat_check!=0x3631)&&(fat_check!=0x3233))
b_sec=*sec=0;
}
wenn((b_sec!=0)&&(sec!=0))
{
Stern_Sek.[*kein_Par]=b_Sek.;
(*nicht_gerade)++;
}
anders
brechen;
/* prüfen, ob eine erweiterte Partition vorhanden ist */
wenn(Puffer[0x1C2+extended_pos*16]==0x05 ||
Puffer[0x1C2+erweiterte_Position*16]==0x0F )
{
temp_var1=(unsigniert)Puffer[partloc1];
*sec=temp_var1 & 0x003F; /* Sektor von
erweitert
Partition */
wenn(*sec!=0)
{
se_p=se+relative_sec+anzahl_sektoren;
*Sekunde=se_p;
}
anders
{ *Sek=-1;
brechen;
}
} //Abschluss der if-Anweisung
anders
{
wenn(*sec>0)
*Sek=-1;
brechen;
}
} while(1); // Schließen der do–while–Schleife
/* Suche nach anderen nicht aktiven primären Partitionen im Sektor 0 */
wenn(*sec==0)
{
für (i = 0; i < 4; i++)
{
active_par=Puffer[446+i*16];
/* Identifizieren Sie das Dateisystemindikator-Byte */
wenn ((Puffer[0x1C2+i*16]==(char)0x06 ||
Puffer[0x1C2+i*16]==(char)0x0B ||
Puffer[0x1C2+i*16]==(char)0x0C ||
Puffer[0x1C2+i*16]==(char)0x07 ||
Puffer[0x1C2+i*16]==(char)0x0E ||
Puffer[0x1C2+i*16]==(char)0x04) && active_par!=0x80)
{
Schalter(Puffer[0x1C2+active_pos*16])
{
/* Für NTFS-Partition */
Fall 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*nicht_gerade+1);
brechen;
/* Für FAT32-Partition */
Fall 0x0B:
Fall 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*nicht_gerade+1);
brechen;
/* Für FAT16-Partition */
Fall 0x04:
Fall 0x06:
Fall 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*nicht_gerade+1);
brechen;
} // Ende des Schalters
/* relative Sektoren Anzahl der Partitionen */
relative_sec=*(lang *)(Puffer+454+i*16);
no_sectors=*(long *)(buffer+458+i*16); /* Anzahl der
Sektoren in
partition*/
sector_part[*no_par]=no_sectors; /* Zu speicherndes Array
Anzahl der
Sektoren von
Partitionen */
*Sek=Stern_Sek[*Kein_Par]=relative_Sek;
(*nicht_gerade)++;
}
} //Schleife schließen von for(i=0;i<4;i++)
} //Schleife schließen von if(*sec==0)
zurückkehren;
}
Anmerkungen zur Kodierung:
Die Funktion beginnt mit dem Lesen der Partitionsinformationen aus dem MBR und liest dann bei Bedarf die erweiterten MBRs . Die Funktion readabsolutesectors liest den absoluten Sektor, angegeben durch *sec.
sector_part[*no_par] ist das Array zum Speichern der Anzahl der Partitionssektoren. 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 Startinformationen jeder Partition in Bezug auf CHS enthalten. star_cyl speichert die Informationen zu den Startzylindern, star_hea speichert die Informationen zu den Startköpfen und star_sec speichert die Informationen zu den Startsektoren der Partitionen.
Eine Beschreibung der Funktion „readabsolutesectors“ finden Sie in den früheren Kapiteln dieses Buches.
MBR durch Programmierung ändern
Unten sehen Sie ein Beispielprogramm, das zeigt, wie wir die Werte des MBR-Partitionstabelleneintrags ändern können . Das Programm ändert die Werte des zweiten Partitionseintrags 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 */
Strukturpartition
{
unsigned char bootable ; /* Aktive Partition
Byte */
unsigned char start_side ; /* Startkopf */
unsigned int start_sec_cyl ; /* Kombination aus
Startsektor und
Zylindernummer */
unsigned char parttype ; /* Dateisystem
Indikator-Byte */
unsigned char end_side ; /* Endkopf */
unsigned int end_sec_cyl ; /* Kombination aus
Startsektor und
Zylindernummer */
unsigned long part_beg ; /* Relativer Sektor
Nummer */
unsigned long plen ; /* Partitionslänge in
Sektoren */
} ;
/* Struktur zum Lesen des MBR */
Strukturteil
{
unsigned char master_boot[446] ; /* IPL (Erste
Programmlader)*/
struct partition pt[4] ; /* Partitionstabelle*/
int lasttwo; /* Magische Zahl */
} ;
Strukturteil p;
void main()
{
vorzeichenlose Ganzzahl t1,t2;
clrscr();
Biosdisk (2, 0x80, 0, 0, 1, 1, &p);
display(); /* zeige die Partition an
Tabelleninformationen */
getch();
/* Nehmen wir an, wir möchten die Partitionsinformationen des zweiten Partitionseintrags aus der Partitionstabelle des MBR mit diesen Werten ändern */
p.pt[1].bootable = 0x80; /* Aktive Boot-Partition */
p.pt[1].parttype = 0x7; /* NTFS-Partition */
p.pt[1].start_side = 0; /* Startkopf =0 */
p.pt[1].end_side = 31; /* Endheader == 31 */
p.pt[1].part_beg = 808416;/* Relativer Sektor = 808416 */
p.pt[1].voll = 405216; /* Gesamtzahl der Sektoren in der Partition = 405216 */
/* Neue Informationen in MBR schreiben *\
/* Um Werte in die MBR-Partitionstabelle zu schreiben, heben Sie die Kommentierung der Biosdisk-Funktion unten auf */
// Biosdisk (3, 0x80, 0, 0, 1, 1, &p);
Anzeige(); /* Anzeige geändert
Information */
erhalten();
}
Kodierungskommentare:
Das obige Programm ist ein Beispielprogramm, das zeigt, wie wir die Werte des MBR-Partitionstabelleneintrags ändern können . Wenn Sie die Partitionseintragswerte für solche logischen Partitionen ändern möchten, die in einer erweiterten Partition liegen , müssen Sie die Werte in der erweiterten MBR-Partitionstabelle ändern .
Die hier angegebenen Werte zum Ändern des Partitionstabelleneintrags dienen lediglich zur Demonstration der Änderung. Ändern Sie die Partitionstabelle niemals mit ungültigen oder unlogischen Werten. Dies kann dazu führen, dass der gesamte Abschnitt nicht mehr zugänglich ist.
Der Strukturabschnitt wird zum Lesen des Partitionsdatensatzes aus der Partitionstabelle verwendet und der Strukturteil zum Lesen des MBR. Um Änderungen an der Partitionstabelle vorzunehmen, heben Sie die Kommentierung der Funktion biosdisk() auf .
Wenn Sie Start- und Endwerte, Sektor- und Zylindernummern einer Partition ändern möchten, berechnen Sie die Werte wie in den Kommentaren zum am Anfang dieses Kapitels besprochenen Programm zum Lesen und Anzeigen der MBR-Partitionstabelle beschrieben.