Capitolo – 12
Lettura e Modifica MBR con Programmazione
Master Boot Record (MBR) o Master Partition Table (MPT)
Il Master Boot Record (MBR) o talvolta indicato come la tabella delle partizioni master (MPT), viene creato sul disco rigido eseguendo il comando FDISK.EXE di DOS.
L'MBR contiene un piccolo programma per caricare e avviare la partizione attiva (o avviabile) dal disco rigido. Il record di avvio principale contiene informazioni su tutte e quattro le partizioni primarie sull'unità disco rigido come il settore iniziale, il settore finale, la dimensione della partizione ecc.
L'MBR si trova al Settore Assoluto 0 o possiamo dire al cilindro 0, testa 0 e settore1 e se è presente più di una partizione nel disco ci sono i Master Boot Records estesi, che si trovano all'inizio di ogni volume della partizione esteso.
Per una descrizione dettagliata, fare riferimento al capitolo "Approccio logico a dischi e sistemi operativi", discusso in precedenza in questo libro.
Formato record di avvio principale
Potremmo partizionare l'unità disco rigido in più unità logiche a cui generalmente viene assegnata la propria lettera di unità da DOS). Solo una partizione alla volta può essere contrassegnata come partizione attiva (o avviabile).
Il Master Boot Record ha il limite di quattro voci nella Master Partition Table. Tuttavia la posizione del record di avvio principale esteso può essere ottenuta con l'aiuto del record di avvio principale che contiene tabelle di partizione estese, il cui formato è esattamente lo stesso della tabella di partizione principale tranne per il fatto che non esiste un codice di avvio e questo spazio di 446 byte è normalmente riservato al codice di avvio e rimane vuoto.
Tutti i 512 byte del Master Boot Record sono rotti come segue, indicati nella tabella:
Tutte le partizioni estese dovrebbero esistere all'interno dello spazio riservato dalla voce della partizione estesa. Solo due delle partizioni estese devono essere utilizzate, la prima come partizione normale e la seconda come un'altra partizione estesa, se esistente.
Così con l'aiuto di una tabella delle partizioni master possiamo ottenere la posizione di un'altra tabella delle partizioni master estesa accanto ad essa, se presente.
Formato di immissione della tabella delle partizioni
Il formato della voce della tabella delle partizioni di qualsiasi partizione in MBR è stato fornito nella tabella successiva. Ogni voce di partizione di qualsiasi MBR può essere suddivisa nei seguenti byte con i loro significati specifici:
Programma di scrittura per leggere la tabella delle partizioni di MBR
In seguito è stato fornito il programma per leggere tutte e quattro le voci di partizione dalla tabella delle partizioni di MBR. Il programma visualizza tutti i parametri delle informazioni sulla partizione, scritti nella tabella delle partizioni di MBR.
La codifica del programma è la seguente:
/* Programma per leggere la tabella delle partizioni 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 */
} ;
/* Struttura per leggere 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();
/* Leggi il primo settore del primo disco rigido */
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the information of MBR
Partition Table */
getch();
}
/* Funzione per visualizzare le informazioni sulla tabella delle partizioni di 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;
}
Le informazioni fornite dall'output del programma vengono visualizzate come indicato di seguito:
Commenti sulla codifica:
La partizione della struttura viene utilizzata per leggere i vari parametri di immissione della partizione della partizione nella tabella delle partizioni dell'MBR. La parte della struttura viene utilizzata per leggere le informazioni MBR.
La funzione display() mostra le informazioni sui parametri della tabella delle partizioni MBR sullo schermo. Come vediamo l'output del programma, il cilindro iniziale e finale e il numero del settore vengono visualizzati come segue:
Starting Sector = 1
Starting Cylinder = 0
Ending Sector = 63
Ending Cylinder = 701
Questi numeri di settore e cilindro sono calcolati dalla combinazione di due byte. Le tabelle seguenti mostrano come vengono calcolati questi numeri:
Iniziando così C-H-S della partizione= 0-0-1.
Allo stesso modo, nella tabella successiva sono stati forniti la codifica per il cilindro finale e il numero di settore della partizione:
Quindi il C-H-S finale della partizione = 701-254-63.
Programma per trovare tutte le partizioni logiche e le relative informazioni
Il programma di cui abbiamo discusso in precedenza consisteva nel leggere le informazioni sulla partizione dalla tabella delle partizioni di MBR. Ma solo solo leggendo l'MBR, non possiamo ottenere le informazioni di altre partizioni logiche che si trovano nella partizione estesa del disco.
Abbiamo già discusso del fatto che il Master Boot Record ha il limite di quattro voci nella Master Partition Table. Tuttavia, la posizione del record di avvio principale esteso può essere ottenuta con l'aiuto del record di avvio principale che contiene tabelle delle partizioni estese, il cui formato è esattamente lo stesso della tabella delle partizioni principale.
Tutte le partizioni estese dovrebbero esistere all'interno dello spazio riservato dalla voce della partizione estesa. Solo due delle partizioni estese devono essere utilizzate, la prima come partizione normale e la seconda come un'altra partizione estesa, se esistente.
Così con l'aiuto di una tabella delle partizioni master possiamo ottenere la posizione di un'altra tabella delle partizioni master estesa accanto ad essa, se presente.
Il seguente programma serve per trovare tutte le partizioni logiche e le relative informazioni sulla voce della partizione, leggere MBR e MBR estesi dal disco. La codifica del programma è la seguente:
/* Programma per leggere i parametri di tutte le partizioni logiche presenti nel disco */
#include<dos.h>
har buffer[512], report_par[20];
unsigned drive_num =0x80;
unsigned long star_sec[20], sec;
/* Struttura del formato del pacchetto Disk Address, da utilizzare con la funzione 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();
}
L'output del programma verrà visualizzato in modo simile a questo:
Partizione 1 - FAT32
Partizione 2 - FAT32
Partizione 3 - FAT32
Partizioni totali nel disco = 3
Numero del settore iniziale della partizione 1 = 63
Numero del settore iniziale della partizione 2 = 11277693
Numero del settore iniziale della partizione 3 = 25623738
Commenti sulla codifica:
La struttura diskaddrpacket viene utilizzata per leggere il formato del pacchetto Disk Address, da utilizzare con la funzione readabsolutesectors.
La funzione All_partition_information( ) viene utilizzata per trovare tutti i parametri di tutte le partizioni dalla voce della partizione.
Sebbene in questo programma abbiamo visualizzato solo le informazioni sul file system e sui settori relativi di tutte le partizioni logiche disponibili nel disco, puoi anche stampare le informazioni di altri parametri delle informazioni sulla partizione usando la funzione All_partition_information() con qualche stampa in più.
La codifica della funzione è la seguente:
/* Funzione per trovare tutte le partizioni logiche’ informazioni che leggono la loro voce di partizione */
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;
/* Leggi il settore assoluto specificato da *sec */
readabsolutesectors (drive_num,*sec,1,buffer);
/* ***** verifica la partizione attiva ***** */
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 */
}
/* per partizione estesa */
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 */
}
}
/* Settori relativi nella partizione */
relativi_sec= *(unsigned long *)(buffer+454+active_pos*16);
/* Numero di settori nella partizione */
no_sectors=*(long *)(buffer+458+active_pos*16);
/* Identifica il byte dell'indicatore del file system */
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;
/* Per partizione FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Per partizione 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;
/* verifica se esiste una partizione estesa */
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
/* controlla altre partizioni primarie non attive nel settore 0 */
if(*sec==0)
{
for(i=0;i<4;i++)
{
active_par=buffer[446+i*16];
/* Identifica il byte dell'indicatore del file system */
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])
{
/* Per partizione NTFS */
case 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*no_par+1);
break;
/* Per partizione FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Per partizione FAT16 */
case 0x04:
case 0x06:
case 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*no_par+1);
break;
} // End of switch
/* settori relativi Numero di partizione */
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;
}
Commenti sulla codifica:
La funzione inizia a leggere le informazioni sulle partizioni dall'MBR e quindi legge gli MBR estesi se necessario. La funzione readabsolutesectors legge il settore assoluto, specificato da *sec.
parte_settori[*no_par] è l'array in cui memorizzare il numero di settori di partizioni. Il numero di partizione è specificato da *no_par a partire da 0.
no_settori è il numero di settori nella partizione e relativi_sec è il numero di settore relativo per quella partizione.
star_sec[*no_par] è l'array per memorizzare i numeri di settore dichiarati delle partizioni. Il numero di partizione è specificato da *no_par a partire da 0.
star_cyl, star_hea e star_sec sono gli array che conservano le informazioni di avvio di ciascuna partizione in termini di CHS. star_cyl memorizza le informazioni sui cilindri iniziali, star_hea memorizza le informazioni sulle testine iniziali e star_sec memorizza le informazioni sui settori iniziali delle partizioni.
Per la descrizione della funzione readabsolutesectors fare riferimento ai capitoli forniti in precedenza in questo libro.
Modifica MBR mediante programmazione
Il programma di esempio per mostrare come possiamo modificare i valori di Voce della tabella delle partizioni MBR è stato fornito di seguito. Il programma modifica i valori della seconda voce della partizione della tabella delle partizioni MBR.
Di seguito è stata data la codifica del programma:
/* Programma per modificare i valori della voce della tabella delle partizioni di MBR */
# include <bios.h>
/* struttura per leggere la voce della partizione dalla tabella delle partizioni */
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 */
} ;
/* Struttura per leggere 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();
/* Supponiamo di voler modificare le informazioni sulla partizione della seconda voce di partizione dalla tabella delle partizioni di MBR, con questi valori */
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 */
/* Scrivi nuove informazioni su MBR *\
/* Per scrivere i valori nella tabella delle partizioni MBR, decommenta la funzione biosdisk indicata di seguito */
// biosdisk ( 3, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the Modified
Information */
getch();
}
Commenti sulla codifica:
Il programma fornito sopra è un programma di esempio per mostrare come possiamo modificare i valori di voce della tabella delle partizioni di MBR. Se desideri modificare i valori della voce di partizione per tali partizioni logiche, che si trovano in partizione estesa, devi modificare i valori nella tabella delle partizioni di MBR esteso .
I valori che sono stati forniti qui per modificare la voce della tabella delle partizioni sono solo per dimostrare come modificare. Non modificare mai la tabella delle partizioni con valori illegali o illogici. In questo modo l'intera partizione potrebbe diventare inaccessibile.
La partizione della struttura viene utilizzata per leggere la voce della partizione dalla tabella delle partizioni e dalla parte della struttura per leggere l'MBR. Per apportare effettivamente le modifiche nella tabella delle partizioni, decommentare la funzione biosdisk( ).
Se vuoi modificare i valori di inizio e fine, settori e numeri di cilindro della partizione, calcola i valori, come descritto nei commenti del programma per leggere e visualizzare la tabella delle partizioni di MBR >, discusso all'inizio di questo capitolo.
Pagina modificata il: 10/03/2022