章 – 13
プログラミングによるMBRの読み取りと変更
DOSブートレコード(DBR)/ DOSブートセクター
DOSブートレコード(DBR)/ DOSブートセクター
パーティションテーブルに続いて、DOSブートレコード(DBR)またはDOSブートセクターと呼ばれることもある、ハードドライブで2番目に重要な情報です。
DBRの詳細については、この本の前半で説明した「ディスクとOSへの論理的アプローチ」の章を参照してください。
各DOSパーティションの最初の論理セクターには、DOSブートレコード(DBR)またはDOSブートセクターが含まれます。 DBRの役割は、オペレーティングシステムをハードディスクドライブからコンピュータのメインメモリにロードし、ロードされたプログラムにシステムの制御を与えることです。
ハードディスクの最初のパーティションのDOSブートレコード(DBR)は、通常、絶対セクター63(ディスクドライブの64番目のセクター)にあります。CHS形式では、C–H–S = 0–1と言うことができます。 –1ほとんどのドライブ。
ただし、この場所は、ドライブのSPT(トラックあたりのセクター数)によって異なる場合があります。たとえば、SPTが31しかない古い245MBドライブでは、ブートレコードは32番目のセクター(絶対セクター31)にありました。
フロッピーにはパーティションがないため、最初のセクターにMBRまたはマスターパーティションテーブルがなく、代わりに最初のセクターにDBRが含まれています。
DBRは、FDISKコマンドを使用してパーティション分割が行われた後、DOSのFORMATコマンドによって作成されます。 DBRが存在するセクターは、DOSの特定のパーティションの論理セクター1になります。 DOSで使用されるセクター番号は、DBRが配置されている物理セクターから始まります。
DBRには、マスターブートレコード(MBR)実行可能プログラムによって実行される小さなプログラムが含まれています。すべてのDOSパーティションには、マシンを起動する、つまりオペレーティングシステムをロードするためのプログラムコードが含まれていますが、そのパーティションのみが、パーティションテーブルエントリでアクティブパーティションとして指定されているマスターブートレコードによって制御されます。
DBRが何らかの方法で破損している場合、起動可能なフロッピーまたはCDからシステムを起動すると、ドライブにアクセスできるはずです。ハードディスクは起動できませんが(アクティブパーティションのDBRが破損している場合)、通常はディスクドライブのデータへのアクセスに影響を与えることはありません。ブータブルディスクを使用してシステムを起動した後、データにアクセスできます。
/ * フロッピーのブートパラメータを表示する */
# include <dos.h>
# include <stdio.h>
main( )
{
struct boot
{
unsigned char code[3] ; /* Jump Code */
unsigned char system_id[8] ;/* OEM Name and Version*/
int bytes_per_sec ; /* Bytes Per Sector */
char sec_per_clus ; /* Sectors Per Cluster */
int res_sec ; /* Reserved Sectors */
char fat_copies ; /* Number of FATs */
int root_dir_entry ; /* Number of Root
Directory Entries */
unsigned int no_sects ; /* Number of Sectors in
Logical Volume */
unsigned char format_id ; /* Media Descriptor Byte
*/
int sec_per_fat ; /* Sectors Per FAT */
int sec_per_trk ; /* Sectors Per Track */
int no_sides ; /* Number of Heads */
int no_sp_res_sect ; /* Number of Hidden
Sectors */
unsigned char rest_code[482] ; /* Rest of the code */
} ;
struct boot b ;
char temp[4] ;
int val, drive ;
val = absread(0, 1, 0, &b) ; /* Use For Floppy Disk*/
if ( val == -1 )
{
printf ( "Disk read Error...bad sector\n" ) ;
exit ( 1 ) ;
}
clrscr ( ) ;
printf ( "System ID = %s\n",
b.system_id ) ;
printf ( "Bytes per sector = %d\n",
b.bytes_per_sec ) ;
printf ( "Sectors per cluster = %d\n",
b.sec_per_clus ) ;
printf ( "Reserved sectors = %d\n",
b.res_sec ) ;
printf ( "FAT copies = %d\n",
b.fat_copies ) ;
printf ( "Root directory entries = %d\n",
b.root_dir_entry ) ;
printf ( "No. of sectors on disk = %u\n",
b.no_sects ) ;
printf ( "Media Descriptor Byte = %X\n",
b.format_id ) ;
printf ( "Sectors per FAT = %d\n",
b.sec_per_fat ) ;
printf ( "Sectors per track = %d\n",
b.sec_per_trk ) ;
printf ( "No. of sides = %d\n",
b.no_sides ) ;
printf ( "No. of reserved sectors = %d\n",
b.no_sp_res_sect ) ;
return 0;
}
このプログラムを実行して、1.44MのDBR、70トラック、両面、トラックあたり18セクター、セクター内512バイトの3½インチフロッピーディスクをテストすると、プログラムの出力は同様に表示されます。次のように:
System ID = +1<*uIHC
Bytes per sector = 512
Sectors per cluster = 1
Reserved sectors = 1
FAT copies = 2
Root directory entries = 224
No. of sectors on disk = 2880
Media Descriptor Byte = F0
Sectors per FAT = 9
Sectors per track = 18
No. of sides = 2
No. of reserved sectors = 0
大容量のDBRを読み取る
サイズが32MBを超えるパーティションボリュームは、32MB以下のボリュームのDBRとは異なる形式のDBRを持っています。
これは、大量のディスクをサポートするためです(詳細については、この本で前述した「ディスクとOSへの論理的アプローチ」の章を参照してください)。
FAT32ボリュームのDOSブートレコードの形式を次の表に示します。
次のプログラムは、サイズが32MBを超える大容量のDBRを読み取るためのものです。
/ * 大容量ディスクボリュームのブートパラメータを表示するプログラム */
# include "dos.h"
# include "stdio.h"
void main()
{
struct boot
{
unsigned char code[3] ; /* Jump Code */
unsigned char system_id[8] ; /* OEM name & Version */
int bytes_per_sec ; /* Bytes Per Sector */
char sec_per_clus ; /* Sectors Per Cluster*/
unsigned int res_sec ; /* Number of Reserved
Sectors */
char fat_copies ; /* Number of FATs */
unsigned int root_dir_entry ;/* Number of Root
Directory Entry */
unsigned int no_sects ; /* Number of Sectors in
Logical Volume (if
Volume is <= 32MB) */
unsigned char Media_id ; /* Media Descriptor Byte
*/
unsigned int sec_per_fat ; /* Sector Per FAT */
unsigned int sec_per_trk ; /* Sectors Per Track */
unsigned int no_sides ; /* Number of Heads */
unsigned long no_sp_res_sect ; /* Number of Hidden
Sectors */
unsigned long long_sec_num ; /* Total Sectors in
Logical Volume
( Size >32MB) */
unsigned long num_sec_per_FAT; /* Sectors Per FAT */
unsigned int binary_flags; /* Binary Flags */
unsigned char version_of_FAT1; /* First Byte of FAT
Version */
unsigned char version_of_FAT2; /* Second Byte of FAT
Version */
unsigned long root_dir_start_cluster;
/* Root Directory
Starting Cluster
Number */
unsigned int sec_num_of_file_sys;
/* Sector Number of
File System
Information Sector
*/
unsigned int sec_num_of_backup_boot_sec;
/* Sector Number of
Backup Boot Sector
*/
unsigned char reserved[12]; /* Reserved */
unsigned char logical_drive_number;
/* Physical Drive
Number of Logical
Volume */
unsigned char unused_byte; /* Unused Byte */
unsigned char hex_extd_boot_signature;
/* Extended Boot
Signature(29H) */
unsigned long binary_volume_ID;/* Binary Volume ID */
unsigned char volume_label[11];/* Volume Label */
unsigned char FAT_name[8]; /* FAT Name */
unsigned char rest_code[420] ; /* Rest 420 Bytes of
The DBR */
unsigned char magic_number[2]; /* Magic Number */
} ;
struct boot b ;
char temp[4] ;
int val, drive,i;
val = biosdisk( 2, 0x80, 1,0,1,1, &b ) ;
/* For First Hard Disk */
if ( val == -1 )
{
printf ( "Disk read Error...bad sector\n" ) ;
exit ( 1 ) ;
}
clrscr ( ) ;
printf ( " Jump Instruction Code = ");
for(i=0;i<=2;i++)
{
printf("%X",b.code[i]);
}
printf("(H)\n ");
printf ( "OEM name and version = %s\n ",
b.system_id ) ;
printf ( "Bytes per sector = %u\n ",
b.bytes_per_sec ) ;
printf ( "Sectors per cluster = %u\n ",
b.sec_per_clus ) ;
printf ( "Reserved sectors = %u\n ",
b.res_sec ) ;
printf ( "FAT copies = %d\n ",
b.fat_copies ) ;
printf ( "Root directory entries = %u\n ",
b.root_dir_entry ) ;
printf ( "No. of sectors on disk = %u\n ",
b.no_sects ) ;
printf ( "Media Descriptor Byte = %X(H)\n",
b.Media_id ) ;
printf ( "Sectors per FAT = %u\n ",
b.sec_per_fat ) ;
printf ( "Sectors per track = %u\n ",
b.sec_per_trk ) ;
printf ( "No. of sides = %u\n ",
b.no_sides ) ;
printf ( "No. of reserved (Hidden) sectors= %lu\n ",
b.no_sp_res_sect ) ;
printf ( "========== For Large(>32MB) Disks ========\n");
printf ( "No. of sectors,(if Volume is >32MB) = %lu\n ",
b.long_sec_num) ;
printf ( “Number of Sectors Per FAT = %lu\n “,
b.num_sec_per_FAT );
printf ( "Root Directory Starting Cluster = %lu\n ",
b.root_dir_start_cluster);
printf ( "File System Information Sector = %u\n ",
b.sec_num_of_file_sys);
printf ( "Sector Number of Backup Boot Sector = %u\n ",
b.sec_num_of_backup_boot_sec);
printf ( "Physical Drive Number = %X(H)\n",
b.logical_drive_number);
printf ( "Extended Boot Signature = %X(H)\n",
b.hex_extd_boot_signature);
printf ( "32-Bit Binary Volume ID = ");
Decimal_to_Binary (b.binary_volume_ID,32);
printf ( " (B)\n ");
printf ( "Volume Label = ");
for(i=0;i<=10;i++)
{
printf ( "%c",b.volume_label[i]);
}
printf ( "\n FAT name = ");
for(i=0;i<=7;i++)
{
printf ( "%c",b.FAT_name[i]);
}
printf ( "\n ");
printf ( "Magic Number = %X%X(H)",
b.magic_number[0],b.magic_number[1]);
getch();
}
//////// 10進数から2進数への変換関数 \\\\\\\\
Decimal_to_Binary(unsigned long input)
{
unsigned long i;
int count = 0;
int binary [32]; /* 32 Bit MAX only 32
elements total */
do
{
i = input%2; /* MOD 2 to get 1 or a 0*/
binary[count] = i; /* Load Elements into the
Binary Array */
input = input/2; /* Divide input by 2 to
decrement via binary */
count++; /* Count howy elements
are needed */
}while (input > 0);
/ * 2進数を反転して出力します */
do
{
printf ("%d", binary[count - 1]);
count--;
} while (count > 0);
return 0;
}
プログラムを実行して大容量のDBRを読み取ると、プログラムの出力は次のように表示されます。
Jump Instruction Code = EB5890 (H)
OEM name and version = MSWIN4.1
Bytes per sector = 512
Sectors per cluster = 8
Reserved sectors = 32
FAT copies = 2
Root directory entries = 0
No. of sectors on disk = 0
Media Descriptor Byte = F8 (H)
Sectors per FAT = 0
Sectors per track = 63
No. of sides = 255
No. of reserved (Hidden) sectors = 63
=========== For Large (>32MB) Disks ===========
No. of sectors, (if Volume is >32MB) = 11277567
Number of Sectors per FAT = 11003
Root Directory Starting Cluster = 2
File System Information Sector = 1
Sector Number of Backup Boot Sector = 6
Physical Drive Number = 80 (H)
Extended Boot Signature = 29 (H)
32-Bit Binary Volume ID = 110101010001100001110111100101 (B)
Volume Label = SAAYA
FAT name = FAT32
Magic Number = 55AA (H)
プログラムの出力では、次のパラメーターがゼロで示されていることがわかります。
- ルートディレクトリエントリ
- ディスク上のセクター数
- FATあたりのセクター数
これらのパラメータは、これらの値がゼロに設定されているためです。パーティションボリュームのサイズが32MBを超え、実際の情報がDBRの拡張ボリューム情報ブロックにある場合。
たとえば、DBR情報の最初の部分では、FATあたりのセクター数は0であり、DBRの拡張ボリューム情報ブロックでは、FATあたりのセクター数は11003です。これは、この大容量の実際の値です。 。
ボリュームのDBRには、プログラミング目的ですべてのデータ情報をリンクするために使用できるディスクパラメータに関する重要な情報があります。たとえば、ディスク上の他のパーティションボリュームのDBRにアクセスする場合は、DBRおよびその他の関連情報に書き込まれたセクター数で計算できます。
クラスターアプローチでディスクにアクセスする場合は、クラスターごとのセクター、FATごとのセクター、およびその他の情報を使用して計算を行うことができます。
8.4 GBを超えるハードディスクを使用している場合(この本の前半で説明した「ディスクとOSへの論理的アプローチ」の章を参照)、拡張機能を使用して8.4GBを超えるディスクのすべてのDBRにアクセスします。前の章で説明した拡張読み取り/書き込み関数を参照してください
プログラミングでDBRを回復する方法
トリッキーなアプローチと論理計算を使用して、ディスクボリュームのDBRを最大100%回復できます。この本の前半の「ディスクとOSへの論理的アプローチ」の章でファイルシステムの論理的アプローチについて説明したように、DBRのすべての情報はある程度の制限またはルールの範囲内で記述されています。
DBRで記述されたすべてのパラメーターには特定の意味があり、特定の規則と理由に従って記述されています。そのため、DBRの情報が失われた場合、これらのルールに従い、トリッキーな心を使って何をどのように治療するかを見つけると、手動で再リンクまたは書き換えることができます。
たとえば、次の表は、さまざまなファイルシステムのクラスターあたりのセクター数を示しています。これを使用して、ディスクのクラスターあたりのセクター数を確認できます。ディスクに約10GBのボリュームがあり、使用しているオペレーティングシステムがWindows98であると仮定します。
ここで、ボリュームのDBRの「クラスターあたりのセクター数」情報がどのように破損しているかを確認します。ディスクのボリュームにあるファイルシステムとクラスターあたりのセクター数を調べてみましょう。
ディスク内のオペレーティングシステムはWindows98であり、FATファイルシステムのみをサポートしているため、ボリュームのファイルシステムはFATでした。次に、ボリュームのサイズ(約10GB)について考えてみましょう。
10GBパーティションはFAT16でサポートされていないことがわかっているため(次の表を参照)、ボリュームのファイルシステムはFAT32である必要があります。
次に、ボリュームのクラスターあたりのセクター数を計算してみましょう。表からわかるように、8GBから16GBの範囲内のパーティションには、8セクターのクラスターが1つあります。
したがって、ボリューム内では、ファイルシステムはクラスターあたり8セクターのFAT32であると結論付けることができます。同様に、この本の前の章で説明した他の論理的アプローチを使用して、DBRの他の情報を組み立てることができます。
次のプログラムは、DBRのディスクパラメータ情報を1.44Mb、3½インチフロッピーディスク、80トラック、2ヘッド(サイド)、トラックあたり18セクターで書き換えるために作成されました。
/ * 1.44MB、3½インチフロッピーディスクのパラメータをDBRに書き換えるプログラム */
# include "dos.h"
# include "stdio.h"
struct boot
{
unsigned char code[3] ; /* Jump Code */
unsigned char system_id[8] ; /* OEM ID and Version*/
int bytes_per_sec ; /* Bytes Per Sector */
char sec_per_clus ; /* Number of Sectors
Per Cluster */
int res_sec ; /* Reserved Sectors */
char fat_copies ; /* Number of FATs */
int root_dir_entry ; /* Number of Root
Directory Entries */
unsigned int no_sects ; /* Number of Total
Sectors */
unsigned char format_id ; /* Media Descriptor
Byte */
int sec_per_fat ; /* Sectors Per FAT */
int sec_per_trk ; /* Sectors Per FAT */
int no_sides ; /* Number of
Sides(Heads) */
int no_sp_res_sect ; /* Number of Hidden
Sectors */
unsigned char rest_code[482] ;/* Rest 482 Bytes code
of DBR */
} ;
struct boot b ;
main( )
{
int val ;
val = absread(0, 1, 0, &b); /* Use For Floppy Disk */
if ( val == -1 )
{
printf ( "\n Disk read Error...bad sector\n" ) ;
exit ( 1 ) ;
}
clrscr ( ) ;
display_info();
getch();
printf("\n Now Recovering BDR of Floppy.....\n");
Recover_with_values();
printf ( "\n Disk Recovered Successfully." ) ;
display_info();
return 0;
}
/ * DBRのパラメータを変更する関数 */
Recover_with_values()
{
int val =0;
/* Jump Code of 3 Bytes For Floppy */
b.code[0] = 0xEB;
b.code[1]= 0x3E;
b.code[2]= 0x90 ;
/* System Id of 8 Bytes */
strcpy(b.system_id, "+05PSIHC");
/* Bytes Per Sector = 512 */
b.bytes_per_sec = 512;
/* Sector per Cluster for 1.44M 3.5" Floppy = 1 */
b.sec_per_clus = 1;
/* Number of Reserved Sectors = 1 */
b.res_sec =1;
/* Number of FAT Copies = 2 */
b.fat_copies =2;
/* Number of Root Directory Entry = 224 */
b.root_dir_entry =224;
/* Number of Sectors on Disk = 2880 */
b.no_sects =2880;
/* Media Descriptor Byte For Floppy = F0 (H) */
b.format_id =0xF0;
/* Sectors Per FAT = 9 */
b.sec_per_fat =9;
/* Sectors Per Track = 18 */
b.sec_per_trk =18;
/* Number of Sides = 2 */
b.no_sides =2;
/* Number of Special Reserved Sectors (or Hidden
Sectors) = 0 */
b.no_sp_res_sect =0;
/* Use For Floppy Disk*/
val = abswrite ( 0, 1, 0, &b ) ;
if ( val == -1 )
{
printf ( "\n Disk Write Error...bad sector\n" ) ;
printf ( " Disk was not Recovered." ) ;
exit ( 1 ) ;
}
return 0;
}
display_info()
{
printf ( "\n Jump Code (Hex) = %X%X%X (H)\n",
b.code[0],b.code[1],b.code[2]);
printf ( " System ID = %s\n",
b.system_id ) ;
printf ( " Bytes per sector = %d\n",
b.bytes_per_sec ) ;
printf ( " Sectors per cluster = %d\n",
b.sec_per_clus ) ;
printf ( " Reserved sectors = %d\n",
b.res_sec ) ;
printf ( " FAT copies = %d\n",
b.fat_copies ) ;
printf ( " Root directory entries = %d\n",
b.root_dir_entry ) ;
printf ( " No. of sectors on disk = %u\n",
b.no_sects ) ;
printf ( " Media Descriptor Byte = %X\n",
b.format_id ) ;
printf ( " Sectors per FAT = %d\n",
b.sec_per_fat ) ;
printf ( " Sectors per track = %d\n",
b.sec_per_trk ) ;
printf ( " No.sides = %d\n",
b.no_sides ) ;
printf ( " No. of reserved sectors = %d\n",
b.no_sp_res_sect ) ;
return 0;
}
コーディングに関するコメント:
構造体ブートは、DBRにアクセスし、ディスクのパラメーターを読み書きするために使用されます。関数display_info()は、DBRから読み取って、ディスクのさまざまなパラメーターを表示します。関数Recover_with_values()は、フロッピーのDBRのパラメーターを変更および回復するために使用されます。
関数Recover_with_values()で使用される値は、1.44MB、3½インチフロッピーディスクのDBRのパラメータ用です。これらの値の説明は、次の表に示されています。