Глава – 12
Чтение и изменение MBR с помощью программирования
Основная загрузочная запись (MBR) или основная таблица разделов (MPT)
Главная загрузочная запись (MBR), которую иногда называют главной таблицей разделов (MPT), создается на жестком диске путем выполнения команды FDISK.EXE в DOS.
MBR содержит небольшую программу для загрузки и запуска активного (или загрузочного) раздела с жесткого диска. Основная загрузочная запись содержит информацию обо всех четырех основных разделах жесткого диска, такую как начальный сектор, конечный сектор, размер раздела и т. д.
Главная загрузочная запись расположена в абсолютном секторе 0 или, можно сказать, в цилиндре 0, головке 0 и секторе 1, и если на диске присутствует более одного раздела, то существуют расширенные основные загрузочные записи, расположенные в начале каждого из них. расширенный объем раздела.
Подробное описание см. в главе «Логический подход к дискам и ОС», рассмотренной ранее в этой книге.
Формат основной загрузочной записи
Мы можем разделить жесткий диск на несколько логических дисков, которым DOS обычно присваивает собственную букву. Только один раздел может быть помечен как активный (или загрузочный).
Основная загрузочная запись имеет ограничение в четыре записи в таблице основных разделов. Однако местоположение расширенной основной загрузочной записи можно получить с помощью основной загрузочной записи, которая содержит расширенные таблицы разделов, формат которых точно такой же, как у основной таблицы разделов, за исключением того, что в ней нет загрузочного кода, и это пространство в 446 байт обычно зарезервировано для кода загрузки и остается пустым.
Все 512 байт основной загрузочной записи повреждены следующим образом, как указано в таблице:
Все расширенные разделы должны существовать в пространстве, зарезервированном записью расширенного раздела. Только два из расширенных разделов предназначены для использования, первый как обычный раздел, а второй как еще один расширенный раздел, если он существует.
Таким образом, с помощью одной основной таблицы разделов мы можем получить расположение другой расширенной основной таблицы разделов рядом с ней, если она присутствует.
Формат записи таблицы разделов
Формат записи в таблице разделов любого раздела в MBR указан в следующей таблице. Каждая запись раздела любой MBR может быть разбита на следующие байты с их конкретными значениями:
Написание программы для чтения таблицы разделов MBR
Далее была дана программа для чтения всех четырех записей раздела из таблицы разделов MBR. Программа отображает все параметры информации о разделах, записанной в таблице разделов MBR.
Код программы следующий:
/* Программа для чтения таблицы разделов MBR */
# include <bios.h>
/* структура для чтения записи раздела из таблицы разделов */
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 */
} ;
/* Структура для чтения 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();
/* Чтение первого сектора первого жесткого диска */
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the information of MBR
Partition Table */
getch();
}
/* Функция для отображения информации о таблице разделов 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;
}
Информация, выдаваемая программой, отображается примерно так, как показано ниже:
Комментарии по кодированию:
Раздел структуры используется для чтения различных параметров записи раздела раздела в таблице разделов MBR. Часть структуры используется для чтения информации MBR.
Функция display() отображает на экране информацию о параметрах таблицы разделов MBR. Как мы видим вывод программы, начальный и конечный цилиндр и номер сектора отображаются следующим образом:
Starting Sector = 1
Starting Cylinder = 0
Ending Sector = 63
Ending Cylinder = 701
Эти номера секторов и цилиндров вычисляются из комбинации двух байтов. В следующих таблицах показано, как рассчитываются эти числа:
Таким образом, начальный C-H-S раздела = 0-0-1.
Аналогично кодировка конечного цилиндра и номер сектора раздела указаны в следующей таблице:
Таким образом, окончание C-H-S раздела = 701-254-63.
Программа для поиска всех логических разделов и их информации
Программа, которую мы обсуждали ранее, предназначена для чтения информации о разделах из таблицы разделов MBR. Но просто прочитав MBR, мы не можем получить информацию о других логических разделах, которые находятся в расширенном разделе диска.
Мы уже обсуждали, что главная загрузочная запись имеет ограничение в четыре записи в главной таблице разделов. Однако местоположение расширенной основной загрузочной записи можно узнать с помощью основной загрузочной записи, содержащей расширенные таблицы разделов, формат которых точно такой же, как у основной таблицы разделов.
Все расширенные разделы должны существовать в пространстве, зарезервированном записью расширенного раздела. Только два из расширенных разделов предназначены для использования, первый как обычный раздел, а второй как еще один расширенный раздел, если он существует.
Таким образом, с помощью одной основной таблицы разделов мы можем получить расположение другой расширенной основной таблицы разделов рядом с ней, если она присутствует.
Следующая программа предназначена для поиска всех логических разделов и информации о записях их разделов, чтения MBR и расширенных MBR с диска. Кодировка программы следующая:
/* Программа для чтения параметров всех логических разделов, присутствующих на диске */
#include<dos.h>
har buffer[512], report_par[20];
unsigned drive_num =0x80;
unsigned long star_sec[20], sec;
/* Структура формата пакета адреса диска, который будет использоваться функцией 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();
}
Вывод программы будет отображаться примерно так:
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
Комментарии по кодированию:
Структура diskaddrpacket используется для чтения формата пакета Адрес диска, который будет использоваться функцией readabsolutesectors.
Функция All_partition_information() используется для поиска всех параметров всех разделов из записи раздела.
Хотя в этой программе мы отобразили только информацию о файловой системе и относительных секторах всех доступных логических разделов на диске, вы также можете распечатать информацию о других параметрах информации о разделах, используя функцию All_partition_information(). и еще немного printf.
Код функции следующий:
/* Функция поиска всех логических разделов’ информация, читающая их запись в разделе */
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;
/* Read absolute sector specified by *sec */
readabsolutesectors (drive_num,*sec,1,buffer);
/* ***** check for active partition ***** */
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 */
}
/* for extended 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_sec= *(unsigned long *)(buffer+454+active_pos*16);
/* Количество секторов в разделе */
no_sectors=*(long *)(buffer+458+active_pos*16);
/* Определите байт индикатора файловой системы */
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;
/* Для раздела FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Для раздела 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;
/* проверка наличия расширенного раздела */
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
/* проверьте наличие других неактивных первичных разделов в секторе 0 */
if(*sec==0)
{
for(i=0;i<4;i++)
{
active_par=buffer[446+i*16];
/* Определите индикатор файловой системы Byte */
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])
{
/* Для раздела NTFS */
case 0x07: report_par[*no_par]='N';
printf("\n Partition -%d = NTFS",
*no_par+1);
break;
/* Для раздела FAT32 */
case 0x0B:
case 0x0C: report_par[*no_par]='3';
printf("\n Partition -%d = FAT32",
*no_par+1);
break;
/* Для раздела FAT16 */
case 0x04:
case 0x06:
case 0x0E: report_par[*no_par]='1';
printf("\n Partition -%d = FAT16",
*no_par+1);
break;
} // End of switch
/* относительные секторы Количество разделов */
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;
}
Комментарии по кодированию:
Функция начинает считывать информацию о разделах из MBR, а затем при необходимости считывает расширенные MBR. Функция readabsolutesectors считывает абсолютный сектор, заданный *sec.
sectors_part[*no_par] — это массив для хранения количества секторов разделов. Номер раздела указывается *no_par, начиная с 0.
no_sectors – это количество секторов в разделе, а relative_sec – относительный номер сектора для этого раздела.
star_sec[*no_par] — это массив для хранения номеров секторов с указанием разделов. Номер раздела указывается *no_par, начиная с 0.
star_cyl, star_hea и star_sec — это массивы, в которых хранится информация о запуске каждого раздела с точки зрения CHS. star_cyl хранит информацию о стартовых цилиндрах, star_hea хранит информацию о стартовых головках, а star_sec хранит информацию о стартовых секторах разделов.
Описание функции readabsolutesectors см. в предыдущих главах этой книги.
Изменение MBR путем программирования
Пример программы, чтобы показать, как мы можем изменить значения записи таблицы разделов MBR, приведен ниже. Программа изменяет значения второй записи раздела таблицы разделов MBR.
Код программы приведен ниже:
/* Программа для изменения значений записи таблицы разделов MBR */
# include <bios.h>
/* структура для чтения записи раздела из таблицы разделов */
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 */
} ;
/* Структура для чтения 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();
/* Предположим, что мы хотим изменить информацию о разделе второй записи раздела из таблицы разделов MBR с этими значениями */
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 */
/* Запись новой информации в MBR *\
/* Чтобы записать значения в таблицу разделов MBR, раскомментируйте функцию biosdisk, приведенную ниже. */
// biosdisk ( 3, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the Modified
Information */
getch();
}
Комментарии по кодированию:
Приведенная выше программа является примером программы, показывающей, как мы можем изменить значения записи таблицы разделов MBR. Если вы хотите изменить значения записи раздела для таких логических разделов, которые лежат в расширенном разделе, вам необходимо изменить значения в таблице разделов расширенной MBR. .
Значения, которые были даны здесь для изменения записи в таблице разделов, предназначены только для демонстрации того, как изменять. Никогда не изменяйте таблицу разделов с недопустимыми или нелогичными значениями. При этом весь раздел может стать недоступным.
Раздел структуры используется для чтения записи раздела из таблицы разделов и части структуры для чтения MBR. Чтобы внести изменения в таблицу разделов, раскомментируйте функцию biosdisk().
Если вы хотите изменить значения начального и конечного секторов и номеров цилиндров раздела, рассчитайте значения, как описано в комментариях к программе для чтения и отображения таблицы разделов MBR, обсуждалось в начале этой главы.
Страница изменена: 16/03/2022