章 – 12
プログラミングによるMBRの読み取りと変更
マスターブートレコード(MBR)またはマスターパーティションテーブル(MPT)
マスターブートレコード(MBR)またはマスターパーティションテーブル(MPT)と呼ばれることもありますが、DOSのFDISK.EXEコマンドを実行することにより、ハードディスクドライブ上に作成されます。
MBRには、ハードディスクドライブからアクティブな(または起動可能な)パーティションをロードして起動するための小さなプログラムが含まれています。マスターブートレコードには、開始セクター、終了セクター、パーティションのサイズなど、ハードディスクドライブ上の4つのプライマリパーティションすべてに関する情報が含まれています。
MBRは絶対セクター0にあります。つまり、シリンダー0、ヘッド0、セクター1にあり、ディスクに複数のパーティションが存在する場合は、それぞれの先頭に拡張マスターブートレコードがあります。拡張パーティションボリューム。
詳細な説明については、章を参照してください “ディスクとOSへの論理的アプローチ”, この本の前半で説明しました。
マスターブートレコード形式
ハードディスクドライブをいくつかの論理ドライブに分割する場合があります。これらの論理ドライブには、通常、DOSによって独自のドライブ文字が割り当てられます。アクティブな(または起動可能な)パーティションとしてマークできるのは、一度に1つのパーティションのみです。
マスターブートレコードには、マスターパーティションテーブルのエントリが4つに制限されています。ただし、拡張マスターブートレコードの場所は、拡張パーティションテーブルを含むマスターブートレコードを使用して取得できます。この形式は、ブートコードがなく、通常は446バイトのスペースである点を除いて、メインパーティションテーブルとまったく同じです。ブートコード用に予約されており、空のままです。
マスターブートレコードの512バイトはすべて、次のように壊れています。表に示されています。
すべての拡張パーティションは、拡張パーティションエントリによって予約されたスペース内に存在する必要があります。拡張パーティションのうち2つだけが使用されるようになっています。最初のパーティションは通常のパーティションとして使用され、2番目のパーティションは存在する場合は別の拡張パーティションとして使用されます。
したがって、1つのマスターパーティションテーブルを使用して、その隣にある別の拡張マスターパーティションテーブルの場所を取得できます(存在する場合)。
パーティションテーブルの入力形式
MBR内のパーティションのパーティションテーブルエントリの形式は、次の表に示されています。 MBRのすべてのパーティションエントリは、特定の意味を持つ次のバイトに分割される場合があります。
MBRのパーティションテーブルを読み取るプログラムを作成する
次に、MBRのパーティションテーブルから4つのパーティションエントリすべてを読み取るプログラムを示します。プログラムは、MBRのパーティションテーブルに書き込まれたパーティション情報のすべてのパラメータを表示します。
プログラムのコーディングは次のとおりです。
/ * 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 */
} ;
/ * 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情報を読み取るために使用されます。
関数 画面() 画面にMBRパーティションテーブルパラメータの情報を表示します。プログラムの出力を見ると、開始シリンダーと終了シリンダー、およびセクター番号が次のように表示されます。
Starting Sector = 1
Starting Cylinder = 0
Ending Sector = 63
Ending Cylinder = 701
これらのセクター番号とシリンダー番号は、2バイトの組み合わせから計算されます。次の表は、これらの数値の計算方法を示しています。
したがって、パーティションのC-H-Sを開始します= 0-0-1。
同様に、パーティションの終了シリンダーとセクター番号のエンコードは次の表に示されています。
したがって、パーティションの終了C-H-S = 701-254-63です。
すべての論理区画とその情報を見つけるためのプログラム
前に説明したプログラムは、MBRのパーティションテーブルからパーティション情報を読み取ることでした。ただし、MBRを読み取るだけでは、ディスクの拡張パーティションにある他の論理パーティションの情報を取得することはできません。
すでに議論しました マスターブートレコード に4つのエントリの制限があります マスターパーティションテーブル. ただし、拡張マスターブートレコードの場所は、次の内容を含むマスターブートレコードを使用して取得できます。 拡張パーティションテーブル, そのフォーマットはメインのパーティションテーブルとまったく同じです。
すべての拡張パーティションは、拡張パーティションエントリによって予約されたスペース内に存在する必要があります。拡張パーティションのうち2つだけが使用されるようになっています。最初のパーティションは通常のパーティションとして使用され、2番目のパーティションは存在する場合は別の拡張パーティションとして使用されます。
したがって、1つのマスターパーティションテーブルを使用して、その隣にある別の拡張マスターパーティションテーブルの場所を取得できます(存在する場合)。
次のプログラムは、すべての論理パーティションとそのパーティションエントリ情報を検索するためのものです。 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;
/ * secで指定された絶対セクターを読み取ります */
readabsolutesectors(drive_num、* sec、1、buffer);
/ * ***** アクティブなパーティションを確認します ***** */
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(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];
/ * ファイルシステムインジケータバイトを識別します */
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で指定された絶対セクターを読み取ります。
ectors_part [* no_par]は、パーティションのセクター数を格納する配列です。パーティション番号は、0から始まる* no_parで指定されます。
no_sectorsはパーティション内のセクター数であり、relative_secはそのパーティションの相対セクター数です。
star_sec [* no_par]は、パーティションのセクター番号を格納するための配列です。パーティション番号は、0から始まる* no_parで指定されます。
star_cyl、star_hea、star_secは、CHSの観点から各パーティションの開始情報を保持する配列です。 star_cylは開始シリンダーの情報を格納し、star_heaは開始ヘッドの情報を格納し、star_secはパーティションの開始セクターの情報を格納します。
readabsolutesectors関数の説明については、この本の前半に記載されている章を参照してください。
プログラミングによるMBRの変更
MBRパーティションテーブルエントリの値を変更する方法を示すサンプルプログラムを以下に示します。プログラムは、2番目の 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のパーティションテーブルから2番目のパーティションエントリのパーティション情報をこれらの値で変更するとします。 */
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のパーティションテーブルを読み取って表示します。 >、この章の冒頭で説明しました。