Capítulo – 12
Lendo e alterando MBR usando programação
Master Boot Record (MBR) ou Tabela de Partição Mestre (MPT)
O Master Boot Record (MBR) ou às vezes chamado de Master Partition Table (MPT) é criado no disco rígido executando o comando FDISK.EXE DOS.
O MBR contém um pequeno programa para carregar e executar a partição ativa (ou de inicialização) do disco rígido. O Master Boot Record contém informações sobre todas as quatro partições primárias do disco rígido, como setor inicial, setor final, tamanho da partição, etc.
O MBR está localizado no setor absoluto 0 ou podemos dizer no cilindro 0, cabeça 0 e setor 1 e se houver mais de uma partição no disco, então há registros mestres de inicialização estendidos localizados no início de cada volume da partição estendida.
Para uma descrição detalhada, consulte o capítulo "Uma abordagem lógica para discos e sistemas operacionais", discutido anteriormente neste livro.
Formato do Master Boot Record
Podemos particionar o disco rígido em várias unidades lógicas, às quais o DOS geralmente atribui sua própria letra de unidade. Somente uma partição por vez pode ser marcada como partição ativa (ou de inicialização).

O registro mestre de inicialização tem um limite de quatro entradas na tabela de partição primária. Entretanto, a localização do MBR estendido pode ser obtida usando o MBR que contém as tabelas de partição estendidas, que tem o mesmo formato da tabela de partição primária, exceto que não contém código de inicialização e que 446 bytes de espaço geralmente são reservados para o código de inicialização e são deixados vazios.
Todos os 512 bytes do registro mestre de inicialização são divididos conforme mostrado na tabela:

Todas as partições estendidas devem existir no espaço reservado pela entrada da partição estendida. Apenas duas das partições estendidas devem ser usadas: a primeira como uma partição regular e a segunda como outra partição estendida, se houver uma.
Então, usando uma Tabela de Partição Mestre, podemos obter a localização de outra Tabela de Partição Mestre Estendida próxima a ela, se houver uma.
Formato de entrada da tabela de partição
O formato de entrada da tabela de partição de qualquer partição no MBR é mostrado na tabela a seguir. Cada entrada de partição de qualquer MBR pode ser dividida nos seguintes bytes com seus significados específicos:

Escrevendo um programa para ler a tabela de partição MBR
Abaixo está um programa para ler todas as quatro entradas de partição da tabela de partição MBR. O programa exibe todos os parâmetros das informações de partição registradas na tabela de partição MBR.
A codificação do programa se parece com isso:
/* Programa para leitura de tabela de partição MBR */
# incluir <bios.h>
/* estrutura para leitura de entrada de partição da tabela de partição */
seção estrutural
{
char não assinado inicializável; /* Byte ativo da seção */
unsigned char start_side ;/* Cabeçalho inicial */
int não assinado start_sec_cyl; /* combinação
Setor inicial e
número do cilindro */
tipo de parte char não assinado; /* Sistema de arquivos
Byte indicador */
char sem sinal fim_lado; /* Fim do cabeçalho */
inteiro sem sinal end_sec_cyl ; /* combinação
Setor inicial e
número do cilindro */
unsigned long part_beg ; /* Setor relativo
Número */
inteiro longo sem sinal; /* Comprimento da seção em
setor */
} ;
/* Estrutura para leitura de MBR */
parte da estrutura
{
char não assinado master_boot[446] ; /* IPL (Inicial
Carregador de programa)*/
estrutura partição pt[4] ; /* Tabela de partição */
int últimos dois; /* Número mágico */
} ;
parte da estrutura p ;
main() inválido
{
clrscr();
/* Lendo o primeiro setor do primeiro disco rígido */
biosdisco ( 2, 0x80, 0, 0, 1, 1, &p ) ;
mostrar(); /* Exibir informações do MBR
Tabela de partição */
pegar();
}
/* Função para exibir informações sobre a tabela de partição MBR */
mostrar()
{
inteiro sem sinal s_sec, s_trk, e_sec, e_trk, i, t1, t2 ;
tipo de caractere[20], boot[5] ;
printf("\n\nParte. Local de carregamento inicial
Localização final Quantidade relativa");
printf("\nTipo Lado Cilindro Setor
Setor do Cilindro Lateral Setores Setores\n");
para ( i = 0 ; i <= 3 ; i++ )
{
se ( p.pt[i].bootable == 0x80 )
strcpy ( boot, "Sim" ) ;
outro
strcpy ( boot, "Não" ) ;
interruptor ( p.pt[i].parttype )
{
caso 0x00:
strcpy ( tipo, "Não utilizado" ) ; break ;
caso 0x1:
strcpy ( tipo, "FAT12" ) ; quebrar ;
caso 0x2:
strcpy ( tipo, "Xenix" ) ; quebrar ;
caso 0x3:
strcpy ( tipo, "Xenix:usr" ) ; quebrar ;
caso 0x4:
strcpy ( tipo, "FAT16<32M" ) ; quebrar ;
caso 0x5:
strcpy ( tipo, "DOS-Ext." ) ; quebrar ;
caso 0x6:
strcpy ( tipo, "FAT16>32M" ) ; quebrar ;
caso 0x7:
strcpy ( tipo, "NTFS" ) ; quebrar ;
caso 0x0b:
strcpy ( tipo, "FAT32" ) ; quebrar ;
caso 0x0c:
strcpy ( tipo, "FAT32-LBA" ) ; quebrar ;
caso 0x0d:
strcpy ( tipo, "VFAT16" ) ; quebrar ;
caso 0x0e:
strcpy ( tipo, "VFAT16-LBA" ) ; quebrar ;
caso 0x0f:
strcpy ( tipo, "VFAT EXT" ) ; quebrar ;
caso 0x17:
strcpy ( tipo, "HPFS" ) ; quebrar ;
caso 0x81:
strcpy ( tipo, "LINUX antigo" ) ; break ;
caso 0x82:
strcpy ( tipo, "LinuxSwap" ) ; quebrar ;
caso 0x83:
strcpy ( tipo, "LinuxNative" ) ; quebrar ;
caso 0x85:
strcpy ( tipo, "Linux Ext." ) ; quebrar ;
padrão :
strcpy ( tipo, "Desconhecido" ) ; break ;
}
s_sec = ( p.pt[i].start_sec_cyl & 0x3f ) ; /* iniciando
Setor do
partição */
t1 = ( p.pt[i].start_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].start_sec_cyl & 0x00c0 ) << 2 ;
s_trk = t1 | t2 ; /* Cilindro de partida */
e_sec = ( p.pt[i].end_sec_cyl & 0x3f ) ; /*Setor final */
t1 = ( p.pt[i].end_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].end_sec_cyl & 0x00c0 ) << 2 ;
e_trk = t1 | t2 ; /* Cilindro final */
printf("\n%6s %3s", tipo, inicialização);
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 ) ;
}
retornar 0;
}
As informações fornecidas pela saída do programa são exibidas mais ou menos como mostrado abaixo:

Comentários sobre codificação:
A partição de estrutura é usada para ler os vários parâmetros de entrada de partição da partição na tabela de partição do MBR. A parte de estrutura é usada para ler informações do MBR.
A função display() exibe as informações dos parâmetros da Tabela de Partição MBR na tela. Como vemos na saída do programa, o cilindro inicial e final e o número do setor são exibidos da seguinte forma:
Setor Inicial = 1
Cilindro de partida = 0
Setor final = 63
Cilindro final = 701
Esses números de setor e cilindro são calculados a partir da combinação de dois bytes. As tabelas a seguir mostram como esses números são calculados:

Portanto, o CHS inicial da partição = 0-0-1.
Da mesma forma, a codificação para o cilindro final e o número do setor da partição foram fornecidos na próxima tabela:

Portanto, o CHS final da partição = 701-254-63.
Programa para encontrar todas as partições lógicas e suas informações
O programa que discutimos anteriormente era para ler as informações de partição da tabela de partição do MBR. Mas somente lendo o MBR, não podemos obter as informações de outras partições lógicas que estão na partição estendida do disco.
Já discutimos que o Master Boot Record tem o limite de quatro entradas na Master Partition Table . No entanto, a localização do Extended Master Boot Record pode ser obtida com a ajuda do Master Boot Record que contém Extended Partition Tables , cujo formato é exatamente o mesmo da Partition Table principal.
Todas as partições estendidas devem existir dentro do espaço reservado pela entrada de partição estendida. Apenas duas das partições estendidas devem ser usadas, a primeira como uma partição normal e a segunda como outra partição estendida, se existir.
Assim, com a ajuda de uma Tabela de Partição Mestre, podemos obter a localização de outra Tabela de Partição Mestre Estendida próxima a ela, se presente.
O programa a seguir é para encontrar todas as partições lógicas e suas informações de entrada de partição, lendo MBR e MBRs estendidos do disco. A codificação do programa é a seguinte:
/* Programa para ler os parâmetros de todas as partições lógicas presentes no disco */
#include<dos.h>
tem buffer[512], report_par[20];
unsigned drive_num =0x80;
estrela longa sem sinal_sec[20], seg;
/* Estrutura do formato do pacote de endereço de disco, a ser usado pela função readabsolutesectors */
estrutura diskaddrpacket
{
char packetsize ; /* Tamanho do pacote, geralmente 10H */
char reservado ; /* Reservado (0) */
int blockcount ; /* Número de blocos a transferir */
char far *bufferaddress ; /* endereço para transferência
Tampão */
unsigned long blocknumber[2] ; /* Iniciando Absoluto
Número do bloco */
} ;
vazio principal()
{
int não_par,i;
clrscr();
nenhum_par = 0;
All_partition_information (star_sec,&no_par, &sec, buffer,
relatório_par);
printf(" \n\n Total de partições no disco = %d\n ",
nenhum_par);
para(i=0;i<sem_par;i++)
{
printf("\n Número do setor inicial da partição %d =
%lu " , i+1, estrela_sec[i]);
}
printf("\n");
obter();
}
A saída do programa será exibida semelhante a esta:
Partição 1 - FAT32
Partição 2 - FAT32
Partição 3 - FAT32
Total de partições no disco = 3
Número do setor inicial da partição 1 = 63
Número do setor inicial da partição 2 = 11277693
Número do setor inicial da partição 3 = 25623738
Comentários sobre codificação:
A estrutura diskaddrpacket é usada para ler o formato do pacote de endereço de disco, a ser usado pela função readabsolutesectors.
A função All_partition_information( ) é usada para encontrar todos os parâmetros de todas as partições da entrada da partição.
Embora neste programa tenhamos exibido apenas o sistema de arquivos e informações relativas ao setor de todas as partições lógicas disponíveis no disco, você também pode imprimir as informações de outros parâmetros de informações de partição usando a função All_partition_information( ) com mais algum printf.
A codificação da função é a seguinte:
/* Função para encontrar todas as informações das partições lógicas lendo sua entrada de partição */
All_partition_information( unsigned long *star_sec,
não assinado *no_par,
longo *seg, char *buffer,
char não assinado *report_par )
{
verificação longa e sem sinal de gordura;
unsigned long *sectors_part;
estático longo se_p;
int temp_var1,deslocamento_ativo,pos_ativa=0,i, pos_extendida=0, partloc1;
sem sinal longo b_sec,se;
char não assinado active_par;
segundo_relativo longo;
longo no_setores;
se(*seg==0 || *seg==1)
se_p=0;
fazer{
se=*seg;
/* Lê o setor absoluto especificado por *sec */
leiasetoresabsolutos(unidade_num,*seg,1,buffer);
/* ***** verificar partição ativa ***** */
if(*sec==se && *no_par==0) /*se primário
partição */
{
*sec=se=0;
para(deslocamento_ativo=446; deslocamento_ativo<=494; deslocamento_ativo+=16)
{
active_par=buffer[deslocamento_ativo];
if(active_par==0x80) /* verificar se há ativo
partição */
quebrar;
outro
active_pos++; /* posição do ativo
partição */
}
/* para partição estendida */
para(deslocamento_ativo=450; deslocamento_ativo<=511; deslocamento_ativo+=16)
{
active_par=buffer[deslocamento_ativo];
se(par_ativo==0x05 | par_ativo==0x0F)
/*verificar se há partição estendida*/
quebrar;
outro
extended_pos++; /*posição do estendido
partição */
}
se(posição_ativa==4)
posição_ativa=1;
se(pos_extendida==4)
pos_estendida=1;
partloc1=0x1C0+pos_extendida*16;
}
outro
{
posição_ativa=0;
pos_estendida=1;
partloc1=0x1D0;
se(se_p!=0)
{
*sec=se=se_p; /*início de estendido
partição */
}
}
/* Setores relativos na partição */
relative_sec= *(longo sem sinal *)(buffer+454+posição_ativa*16);
/* Número de setores na partição */
no_sectors=*(long *)(buffer+458+active_pos*16);
/* Identificar o Byte Indicador do Sistema de Arquivos */
se( buffer[0x1C2+pos_ativa*16]==0x04 ||
buffer[0x1C2+pos_ativa*16]==0x05 ||
buffer[0x1C2+pos_ativa*16]==0x06 ||
buffer[0x1C2+posição_ativa*16]==0x0B ||
buffer[0x1C2+posição_ativa*16]==0x0C ||
buffer[0x1C2+posição_ativa*16]==0x0E ||
buffer[0x1C2+posição_ativa*16]==0x0F ||
buffer[0x1C2+posição_ativa*16]==0x07)
{
switch(buffer[0x1C2+pos_ativa*16])
{
/* Para partição NTFS */
caso 0x07: report_par[*no_par]='N';
printf("\n Partição -%d = NTFS",
*não_par+1);
quebrar;
/* Para partição FAT32 */
caso 0x0B:
caso 0x0C: report_par[*no_par]='3';
printf("\n Partição -%d = FAT32",
*não_par+1);
quebrar;
/* Para partição FAT16 */
caso 0x04:
caso 0x06:
caso 0x0E: report_par[*no_par]='1';
printf("\n Partição -%d = FAT16",
*não_par+1);
quebrar;
} // Fim da troca
b_sec=*seg+segundo_relativo;
sectors_part[*no_par]=no_sectors; /* Matriz para armazenar o número de setores das partições */
} //Fim da condição if
outro
{ /* se o indicador de partição não corresponder */
se(*seg==0)
{ no_par=0;
quebrar;
}
se((verificação_de_gordura!=0x3631)&&(verificação_de_gordura!=0x3233))
b_sec=*seg=0;
}
se((b_sec!=0)&&(sec!=0))
{
star_sec[*sem_par]=b_sec;
(*não_par)++;
}
outro
quebrar;
/* verificando se a partição estendida existe */
se(buffer[0x1C2+pos_extendida*16]==0x05 ||
buffer[0x1C2+posição_extendida*16]==0x0F )
{
temp_var1=(sem sinal)buffer[partloc1];
*sec=temp_var1 & 0x003F; /* setor de
estendido
partição */
se(*seg!=0)
{
se_p=se+sec_relativo+sem_setores;
*sec=se_p;
}
outro
{ *seg=-1;
quebrar;
}
} //fechamento da instrução if
outro
{
se(*seg>0)
*seg=-1;
quebrar;
}
} while(1); // fechamento do loop do–while
/* verificar outras partições primárias não ativas no setor 0 */
se(*seg==0)
{
para(i=0;i<4;i++)
{
ativo_par=buffer[446+i*16];
/* Identifica o Byte indicador do sistema de arquivos */
se((buffer[0x1C2+i*16]==(caracteres)0x06 ||
buffer[0x1C2+i*16]==(caracteres)0x0B ||
buffer[0x1C2+i*16]==(caracteres)0x0C ||
buffer[0x1C2+i*16]==(caracteres)0x07 ||
buffer[0x1C2+i*16]==(caracteres)0x0E ||
buffer[0x1C2+i*16]==(caracteres)0x04) && par_ativo!=0x80)
{
switch(buffer[0x1C2+pos_ativa*16])
{
/* Para partição NTFS */
caso 0x07: report_par[*no_par]='N';
printf("\n Partição -%d = NTFS",
*não_par+1);
quebrar;
/* Para partição FAT32 */
caso 0x0B:
caso 0x0C: report_par[*no_par]='3';
printf("\n Partição -%d = FAT32",
*não_par+1);
quebrar;
/* Para partição FAT16 */
caso 0x04:
caso 0x06:
caso 0x0E: report_par[*no_par]='1';
printf("\n Partição -%d = FAT16",
*não_par+1);
quebrar;
} // Fim da troca
/* setores relativos Número de Partição */
relativo_sec=*(longo *)(buffer+454+i*16);
no_sectors=*(long *)(buffer+458+i*16); /* número de
setores em
partição*/
sectors_part[*no_par]=no_sectors; /* Matriz para armazenar
Número de
setores de
partições */
*sec=star_sec[*no_par]=relative_sec;
(*não_par)++;
}
} //fechamento do loop de for(i=0;i<4;i++)
} //fechamento do loop de if(*sec==0)
retornar;
}
Comentários sobre codificação:
A função começa a ler as informações das partições do MBR e então lê os MBRs Estendidos , se necessário. A função readabsolutesectors lê o setor absoluto, especificado por *sec.
sectors_part[*no_par] é o array para armazenar o número de setores de partições. O número da partição é especificado por *no_par começando em 0.
no_sectors é o número de setores na partição e relative_sec é o número relativo do setor para essa partição.
star_sec[*no_par] é o array para armazenar os números de setor de declaração das partições. O número da partição é especificado por *no_par começando de 0.
star_cyl, star_hea e star_sec são as matrizes que mantêm as informações de início de cada partição em termos de CHS. star_cyl armazena as informações dos cilindros iniciais, star_hea armazena as informações das cabeças iniciais e star_sec armazena as informações dos setores iniciais das partições.
Para a descrição da função readabsolutesectors, consulte os capítulos fornecidos anteriormente neste livro.
Modificar MBR por programação
O programa de exemplo para mostrar como podemos modificar os valores da entrada da tabela de partição MBR foi fornecido abaixo. O programa modifica os valores da segunda entrada da partição da tabela de partição MBR .
A codificação do programa foi dada abaixo:
/* Programa para modificar os valores da entrada da tabela de partição do MBR */
# incluir <bios.h>
/* estrutura para ler a entrada da partição da tabela de partição */
partição de estrutura
{
unsigned char bootable ; /* Partição Ativa
Byte */
unsigned char start_side ; /* Cabeçalho inicial */
unsigned int start_sec_cyl ; /* combinação de
Setor inicial e
número do cilindro */
unsigned char parttype ; /* Sistema de arquivos
Byte Indicador */
unsigned char end_side ; /* Cabeçalho final */
unsigned int end_sec_cyl ; /* combinação de
Setor inicial e
número do cilindro */
unsigned long part_beg ; /* Setor Relativo
Número */
unsigned long plen ; /* Comprimento da partição em
setores */
} ;
/* Estrutura para ler MBR */
parte da estrutura
{
unsigned char master_boot[446] ; /* IPL (Inicial
Carregador de Programas)*/
struct partition pt[4] ; /* Tabela de partição*/
int lasttwo ; /* Número mágico */
} ;
estrutura parte p;
vazio principal()
{
int sem sinal t1,t2;
clrscr();
biosdisco ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* exibe a partição
Informações da tabela */
obter();
/* Vamos supor que queremos modificar as informações de partição da segunda entrada de partição da tabela de partição do MBR, com estes valores */
p.pt[1].bootable = 0x80; /* Partição de inicialização ativa */
p.pt[1].parttype = 0x7; /* Partição NTFS */
p.pt[1].start_side = 0; /* Cabeçalho inicial =0 */
p.pt[1].fim_lado = 31; /* Fim do Cabeçalho == 31 */
p.pt[1].part_beg = 808416;/* Setor relativo = 808416 */
p.pt[1].completo = 405216; /* Número total de setores na partição = 405216 */
/* Escrever novas informações no MBR *\
/* Para escrever valores na tabela de partição MBR, descomente a função biosdisk abaixo */
// biosdisk ( 3, 0x80, 0, 0, 1, 1, &p ) ;
mostrar(); /* Exibição alterada
Informação */
pegar();
}
Comentários de codificação:
O programa acima é um programa de exemplo para mostrar como podemos alterar os valores da entrada da tabela de partição MBR . Se você quiser alterar os valores de entrada da partição para essas partições lógicas que estão em uma partição estendida , será necessário alterar os valores na tabela de partição MBR estendida .
Os valores que foram fornecidos aqui para alterar a entrada da tabela de partição são apenas para demonstrar como alterar. Nunca modifique a tabela de partição com valores inválidos ou ilógicos. Como resultado, a seção inteira pode ficar inacessível.
A seção de estrutura é usada para ler o registro de partição da tabela de partição, e a parte de estrutura é usada para ler o MBR. Para fazer alterações na tabela de partições, descomente a função biosdisk() .
Se você quiser alterar os valores inicial e final, os números de setor e cilindro de uma partição, calcule os valores conforme descrito nos comentários do programa para leitura e exibição da tabela de partição MBR discutido no início deste capítulo.