Capítulo – 12
Lectura y modificación de MBR con programación
Registro de arranque maestro (MBR) o tabla de partición maestra (MPT)
El registro de arranque maestro (MBR) o, a veces, la tabla de partición maestra (MPT), se crea en la unidad de disco duro ejecutando el comando FDISK.EXE de DOS.
El MBR contiene un pequeño programa para cargar e iniciar la partición activa (o de arranque) desde la unidad de disco duro. El registro de arranque maestro contiene información sobre las cuatro particiones primarias en la unidad de disco duro, como el sector inicial, el sector final, el tamaño de la partición, etc.
El MBR está ubicado en Absolute Sector 0 o podemos decir en el cilindro 0, head 0 y sector1 y si hay más de una partición presente en el disco, hay Extended Master Boot Records, ubicados al comienzo de cada volumen de partición extendido.
Para obtener una descripción detallada, consulte el capítulo "Enfoque lógico de los discos y el sistema operativo", que se analizó anteriormente en este libro.
Formato de registro de arranque maestro
Podemos particionar la unidad de disco duro en varias unidades lógicas a las que DOS generalmente les asigna su propia letra de unidad). Solo se puede marcar una partición a la vez como partición activa (o de arranque).
El registro de arranque maestro tiene un límite de cuatro entradas en la tabla de particiones maestra. Sin embargo, la ubicación del registro de inicio maestro extendido se puede obtener con la ayuda del registro de inicio maestro que contiene tablas de particiones extendidas, cuyo formato es exactamente el mismo que el de la tabla de particiones principal, excepto que no hay código de inicio y este espacio de 446 bytes es normalmente reservado para el código de arranque y permanece vacío.
Todos los 512 bytes de The Master Boot Record se dividen de la siguiente manera, según se indica en la tabla:
Todas las particiones extendidas deben existir dentro del espacio reservado por la entrada de partición extendida. Solo dos de las particiones extendidas están diseñadas para usarse, la primera como una partición normal y la segunda como otra partición extendida, si existe.
Por lo tanto, con la ayuda de una tabla de particiones maestra, podemos obtener la ubicación de otra tabla de particiones maestra extendida junto a ella, si está presente.
Formato de entrada de la tabla de particiones
El formato de entrada de la tabla de particiones de cualquier partición en MBR se proporciona en la siguiente tabla. Cada entrada de partición de cualquier MBR se puede dividir en los siguientes bytes con sus significados específicos:
Programa de escritura para leer la tabla de particiones de MBR
El programa para leer las cuatro entradas de partición de la tabla de partición de MBR se proporciona a continuación. El programa muestra todos los parámetros de información de partición, escritos en la tabla de partición de MBR.
La codificación del programa es la siguiente:
/* Programa para leer la tabla de particiones 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 */
} ;
/* Estructura para leer 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();
/* Leer primer sector del primer disco duro */
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the information of MBR
Partition Table */
getch();
}
/* Función para mostrar la información de la tabla de particiones de 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;
}
La información proporcionada por la salida del programa se muestra de la siguiente manera:
Comentarios sobre la codificación:
La partición de estructura se utiliza para leer los diversos parámetros de la entrada de partición de la partición en la tabla de partición de MBR. La parte de la estructura se utiliza para leer información MBR.
La función display() muestra la información de los parámetros de la tabla de particiones MBR en la pantalla. Como vemos la salida del programa, el cilindro inicial y final y el número de sector se muestran de la siguiente manera:
Starting Sector = 1
Starting Cylinder = 0
Ending Sector = 63
Ending Cylinder = 701
Estos números de sector y cilindro se calculan a partir de la combinación de dos bytes. Las siguientes tablas muestran cómo se calculan estos números:
Así Iniciando C-H-S de la partición= 0-0-1.
Del mismo modo, la codificación para el cilindro final y el número de sector de la partición se proporcionan en la siguiente tabla:
Así el Final C-H-S de la Partición = 701-254-63.
Programa para encontrar todas las particiones lógicas y su información
El programa que discutimos anteriormente era para leer la información de partición de la tabla de partición de MBR. Pero solo leyendo el MBR, no podemos obtener la información de otras particiones lógicas que están en la partición extendida del disco.
Ya hemos comentado que el Registro de arranque maestro tiene un límite de cuatro entradas en la Tabla de particiones maestra. Sin embargo, la ubicación del Registro de inicio maestro extendido se puede obtener con la ayuda del Registro de inicio maestro que contiene Tablas de partición extendidas, cuyo formato es exactamente el mismo que el de la Tabla de partición principal.
Todas las particiones extendidas deben existir dentro del espacio reservado por la entrada de partición extendida. Solo dos de las particiones extendidas están diseñadas para usarse, la primera como una partición normal y la segunda como otra partición extendida, si existe.
Por lo tanto, con la ayuda de una tabla de particiones maestra, podemos obtener la ubicación de otra tabla de particiones maestra extendida junto a ella, si está presente.
El siguiente programa es para encontrar todas las particiones lógicas y su información de entrada de partición, leyendo MBR y MBR extendidos del disco. La codificación del programa es la siguiente:
/* Programa para leer los parámetros de todas las particiones lógicas presentes en el disco */
#include<dos.h>
har buffer[512], report_par[20];
unsigned drive_num =0x80;
unsigned long star_sec[20], sec;
/* Estructura del formato del paquete de dirección de disco, que utilizará la función 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 salida del programa se mostrará de forma similar a esto:
Partition 1 - FAT32
Partition 2 - FAT32
Partition 3 - FAT32
Total Partitions in Disk = 3
Starting Sector Number of Partition 1 = 63
Starting Sector Number of Partition 2 = 11277693
Starting Sector Number of Partition 3 = 25623738
Comentarios sobre la codificación:
La estructura diskaddrpacket se usa para leer el formato del paquete de dirección de disco, para ser usado por la función readabsolutesectors.
La función All_partition_information( ) se usa para encontrar todos los parámetros de todas las particiones desde la entrada de la partición.
Aunque en este programa, hemos mostrado solo el sistema de archivos y la información relativa al sector de todas las particiones lógicas disponibles en el disco, también puede imprimir la información de otros parámetros de información de partición usando la función All_partition_information( ) con algo más de printf.
La codificación de la función es la siguiente:
/* Función para buscar todas las particiones lógicas’ información leyendo su entrada de partición */
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;
/* Leer sector absoluto especificado por *sec */
readabsolutesectors (drive_num,*sec,1,buffer);
/* ***** comprobar si hay una partición activa ***** */
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 */
}
/* para partición extendida */
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 */
}
}
/* Sectores relativos en partición */
relative_sec= *(unsigned long *)(buffer+454+active_pos*16);
/* Número de sectores en la partición */
no_sectors=*(long *)(buffer+458+active_pos*16);
/* Identificar el byte indicador del sistema de archivos */
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;
/* Para partición FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Para partición 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;
/* comprobando si existe una partición extendida */
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
/* compruebe si hay otras particiones primarias no activas en el sector 0 */
if(*sec==0)
{
for(i=0;i<4;i++)
{
active_par=buffer[446+i*16];
/* Identifique el byte indicador del sistema de archivos */
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])
{
/* Para partición NTFS */
case 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*no_par+1);
break;
/* Para partición FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Para partición FAT16 */
case 0x04:
case 0x06:
case 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*no_par+1);
break;
} // End of switch
/* sectores relativos Número de partición */
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;
}
Comentarios sobre la codificación:
La función comienza leyendo la información de las particiones del MBR y luego lee los MBR extendidos si es necesario. La función readabsolutesectors lee el sector absoluto, especificado por *sec.
sectors_part[*no_par] es la matriz para almacenar el número de sectores de particiones. El número de partición se especifica con *no_par a partir de 0.
no_sectors es el número de sectores en la partición y relative_sec es el número de sector relativo para esa partición.
star_sec[*no_par] es la matriz para almacenar los números de sector de las particiones. El número de partición se especifica con *no_par a partir de 0.
star_cyl, star_hea y star_sec son los arreglos que mantienen la información de inicio de cada partición en términos de CHS. star_cyl almacena la información de los cilindros de arranque, star_hea almacena la información de los cabezales de arranque y star_sec almacena la información de los sectores de arranque de las particiones.
Para obtener una descripción de la función readabsolutesectors, consulte los capítulos anteriores de este libro.
Modificar MBR por Programación
El programa de muestra para mostrar cómo podemos modificar los valores de la entrada de la tabla de particiones MBR se proporciona a continuación. El programa modifica los valores de la segunda entrada de partición de la tabla de particiones MBR.
La codificación del programa se muestra a continuación:
/* Programa para modificar los valores de entrada de la tabla de particiones de 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 */
} ;
/* Estructura para leer 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();
/* Supongamos que queremos modificar la información de partición de la segunda entrada de partición de la tabla de partición de MBR, con estos valores */
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 */
/* Escribir nueva información en MBR *\
/* Para escribir los valores en la tabla de particiones MBR, elimine los comentarios de la función biosdisk que se indica a continuación */
// biosdisk ( 3, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the Modified
Information */
getch();
}
Comentarios sobre la codificación:
El programa anterior es un programa de muestra para mostrar cómo podemos modificar los valores de entrada de la tabla de particiones de MBR. Si desea modificar los valores de entrada de partición para dichas particiones lógicas, que se encuentran en partición extendida, debe modificar los valores en la tabla de particiones de MBR extendido .
Los valores que se han proporcionado aquí para modificar la entrada de la tabla de particiones son solo para demostrar cómo modificar. Nunca modifique la tabla de particiones con valores ilegales o ilógicos. Al hacerlo, toda la partición puede volverse inaccesible.
La partición de estructura se usa para leer la entrada de partición de la tabla de partición y la parte de estructura para leer MBR. Para realizar las modificaciones en la tabla de particiones, descomente la función biosdisk().
Si desea modificar los valores de inicio y finalización, sectores y números de cilindros de la partición, calcule los valores, como se describe en los comentarios del programa para leer y mostrar la tabla de partición de MBR, discutido al comienzo de este capítulo.
Página modificada el: 17/01/2022