マスターブートレコードの解析

2002/06/16
マスターブートレコードの全体像

 私は以下のようにマスターブートレコードの構造を図示してきた。

[マスターブートレコードの構造]
マスターブートレコート

 ここではこれをもっと実際のデータに近いものを見ながら、その詳細を解析する。これからは「バイナリダンプ」とか「ヘキサ」という言葉をいちいち説明しないでも分かる人が対象となる。これらの言葉が分からない人には到底着いていける内容ではないからだ。

 尚、マスターブートレコードのヘキサダンプデータの取得は様々な方法があるが、WindowsNTのリソースキットに含まれるDiskProbe(dskprobe.exe)は非常に優れもので、GUIで様々なことが可能だ。Windows2000ではリソースキットではなくインストールCDにあるサポートツール(support\toolsからインストール)に含まれている。WindowsXPではサポートツールの中にはなかったが、Windows2000のdskprobe.exeがそのまま利用できた。またWindows 2000サポートツールをXPにインストールすることもできる。

 MS-DOSやWindows9x環境のみの方は、MBMのサブツールとして提供されているMBRXコマンドが手軽でお薦めだ。LinuxやFreeBSDなどのUNIX環境の場合は、ddコマンドマスターブートレコードをファイル化して、それをバイナリエディタhexdumpコマンドhdコマンドなどで表示またはダンプするのがいいだろう。

 実際にマスターブートレコード、512bytesをヘキサダンプしたのが以下のデータだ。

[マスターブートレコード全体のダンプデータ]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7  +8 +9 +A +B +C +D +E +F   0123456789ABCDEF
   
0000   EB 2C 4D 42 4D 20 52 30  2E 33 36 62 3A 20 4C 6F   .,MBM R0.36b: Lo
0010   61 64 69 6E 67 2E 2E 2E  00 4D 42 4D 20 68 61 73   ading....MBM has
0020   20 62 65 65 6E 20 62 72  6F 6B 65 6E 2E 00 33 C0    been broken..3.
0030   8E D8 8E C0 8E D0 BC 00  72 FC BE 02 7C AC 3C 00   ........r...|.<.
0040   74 08 32 FF B4 0E CD 10  EB F3 BB 00 08 B9 07 00   t.2.............
0050   BA 80 00 B8 11 02 CD 13  72 DF 53 33 C0 B9 00 11   ........r.S3....
0060   03 07 43 43 E2 FA 3B 06  92 7C 74 10 BE 19 7C AC   ..CC..;..|t...|.
0070   3C 00 74 FE 32 FF B4 0E  CD 10 EB F3 BE 8E 7C BF   <.t.2.........|.
0080   28 40 B9 17 00 F3 A4 A1  8E 7C A3 16 40 C3 00 00   (@.......|..@...
0090   05 00 D0 E3 00 13 D0 03  13 41 FF FF 70 00 00 00   .........A..p...
00A0   00 00 00 00 04 72 23 8A  C1 24 3F 98 8A DE 8A FC   .....r#..$?.....
00B0   43 F7 E3 8B D1 86 D6 B1  06 D2 EE 42 F7 E2 39 56   C..........B..9V
00C0   0A 77 23 72 05 39 46 08  73 1C B8 01 02 BB 00 7C   .w#r.9F.s......|
00D0   8B 4E 02 8B 56 00 CD 13  73 51 4F 74 4E 32 E4 8A   .N..V...sQOtN2..
00E0   56 00 CD 13 EB E4 8A 56  00 60 BB AA 55 B4 41 CD   V......V.`..U.A.
00F0   13 72 36 81 FB 55 AA 75  30 F6 C1 01 74 2B 61 60   .r6..U.u0...t+a`
0100   6A 00 6A 00 FF 76 0A FF  76 08 6A 00 68 00 7C 6A   j.j..v..v.j.h.|j
0110   01 6A 10 B4 42 8B F4 CD  13 61 61 73 0E 4F 74 0B   .j..B....aas.Ot.
0120   32 E4 8A 56 00 CD 13 EB  D6 61 F9 C3 49 6E 76 61   2..V.....a..Inva
0130   6C 69 64 20 70 61 72 74  69 74 69 6F 6E 20 74 61   lid partition ta
0140   62 6C 65 00 45 72 72 6F  72 20 6C 6F 61 64 69 6E   ble.Error loadin
0150   67 20 6F 70 65 72 61 74  69 6E 67 20 73 79 73 74   g operating syst
0160   65 6D 00 4D 69 73 73 69  6E 67 20 6F 70 65 72 61   em.Missing opera
0170   74 69 6E 67 20 73 79 73  74 65 6D 00 00 00 00 00   ting system.....
0180   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
0190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
01A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
01B0   00 00 00 00 00 2C 44 63  22 2B 23 2B 00 00 80 01   .....,Dc"+#+....
01C0   01 00 07 FE BF 09 3F 00  00 00 4B F5 7F 00 00 00   ......?...K.....
01D0   81 0A 07 FE FF FF 8A F5  7F 00 8A F5 7F 00 00 00   ................
01E0   C1 FF 0F FE FF FF 14 EB  FF 00 2F A2 2B 03 00 FE   ........../.+...
01F0   FF FF A5 FE FF FF 43 8D  2B 04 7E 04 7D 00 55 AA   ......C.+.~.}.U.
   

 オフセット0x0000から始まり、0x1BDまでの赤い部分プログラム領域で、その後ろオフセット0x1BEから0x1EDまでの青い部分パーティションテーブルがあり、最後2バイト(の部分)にマジックナンバーがあるのが見える。

 プログラム領域とパーティションテーブルは更に詳しくこの後見ていく。

 


プログラム領域

[プログラム領域]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7  +8 +9 +A +B +C +D +E +F   0123456789ABCDEF
   
0000   EB 2C 4D 42 4D 20 52 30  2E 33 36 62 3A 20 4C 6F   .,MBM R0.36b: Lo
0010   61 64 69 6E 67 2E 2E 2E  00 4D 42 4D 20 68 61 73   ading....MBM has
0020   20 62 65 65 6E 20 62 72  6F 6B 65 6E 2E 00 33 C0    been broken..3.
0030   8E D8 8E C0 8E D0 BC 00  72 FC BE 02 7C AC 3C 00   ........r...|.<.
0040   74 08 32 FF B4 0E CD 10  EB F3 BB 00 08 B9 07 00   t.2.............
0050   BA 80 00 B8 11 02 CD 13  72 DF 53 33 C0 B9 00 11   ........r.S3....
0060   03 07 43 43 E2 FA 3B 06  92 7C 74 10 BE 19 7C AC   ..CC..;..|t...|.
0070   3C 00 74 FE 32 FF B4 0E  CD 10 EB F3 BE 8E 7C BF   <.t.2.........|.
0080   28 40 B9 17 00 F3 A4 A1  8E 7C A3 16 40 C3 00 00   (@.......|..@...
0090   05 00 D0 E3 00 13 D0 03  13 41 FF FF 70 00 00 00   .........A..p...
00A0   00 00 00 00 04 72 23 8A  C1 24 3F 98 8A DE 8A FC   .....r#..$?.....
00B0   43 F7 E3 8B D1 86 D6 B1  06 D2 EE 42 F7 E2 39 56   C..........B..9V
00C0   0A 77 23 72 05 39 46 08  73 1C B8 01 02 BB 00 7C   .w#r.9F.s......|
00D0   8B 4E 02 8B 56 00 CD 13  73 51 4F 74 4E 32 E4 8A   .N..V...sQOtN2..
00E0   56 00 CD 13 EB E4 8A 56  00 60 BB AA 55 B4 41 CD   V......V.`..U.A.
00F0   13 72 36 81 FB 55 AA 75  30 F6 C1 01 74 2B 61 60   .r6..U.u0...t+a`
0100   6A 00 6A 00 FF 76 0A FF  76 08 6A 00 68 00 7C 6A   j.j..v..v.j.h.|j
0110   01 6A 10 B4 42 8B F4 CD  13 61 61 73 0E 4F 74 0B   .j..B....aas.Ot.
0120   32 E4 8A 56 00 CD 13 EB  D6 61 F9 C3 49 6E 76 61   2..V.....a..Inva
0130   6C 69 64 20 70 61 72 74  69 74 69 6F 6E 20 74 61   lid partition ta
0140   62 6C 65 00 45 72 72 6F  72 20 6C 6F 61 64 69 6E   ble.Error loadin
0150   67 20 6F 70 65 72 61 74  69 6E 67 20 73 79 73 74   g operating syst
0160   65 6D 00 4D 69 73 73 69  6E 67 20 6F 70 65 72 61   em.Missing opera
0170   74 69 6E 67 20 73 79 73  74 65 6D 00 00 00 00 00   ting system.....
0180   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
0190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
01A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
01B0   00 00 00 00 00 2C 44 63  22 2B 23 2B 00 00 80 01   .....,Dc"+#+....
01C0   01 00 07 FE BF 09 3F 00  00 00 4B F5 7F 00 00 00   ......?...K.....
01D0   81 0A 07 FE FF FF 8A F5  7F 00 8A F5 7F 00 00 00   ................
   

 オフセット0x0000から始まり、0x1BDまでのプログラム領域446バイトある訳だが、上記のダンプ例では実はここにはMBMがインストールされている。先頭の方の文字がそれを表現しているので気づいた方が多いだろう。(もっともMBMインストール前に存在したMicrosoftブートストラップローダの一部も残っているが)

 通常ここにはPC/AT互換機の標準ローダであるMicrosoftブートストラップローダがある。これについてはブートストラップローダの詳細を参照してほしい。このプログラムについて更に詳細に解説している。

 尚、領域自体は446バイトあるが、普通この領域を全部使うことはない。プログラムの無い、後ろの方がNULL(00)で埋まっている。

 しかし後ろの方に私がで色分けしたデータがあるのが見えるだろう。これはNTシグニチャと呼ばれるもので、Windows2000などのNT系OSがインストールされている場合、すべてのハードディスクのMBRのこのあたり(プログラム領域の最後の方)に書かれるハードディスクとパーティションを識別するサインとして書かれるものだ。

 このNTシグニチャがWindows2000の重大なバグの温床になっているが、NT系OSがWindows9xよりもドライブレターなどが柔軟に変更できるのはこのデータに依存している。

 


パーティションテーブルの解析

 パーティションテーブルは1エントリ16バイトが4エントリある全体で64バイトの領域であることは説明した。ダンプデータをエントリ毎に色分けすると以下のようになる。

[パーティションテーブルデータ(エントリ毎の色分け)]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F   0123456789ABCDEF
   
01B0   00 00 00 00 00 2C 44 63 22 2B 23 2B 00 00 80 01   .....,Dc"+#+....
01C0   01 00 07 FE BF 09 3F 00 00 00 4B F5 7F 00 00 00   ......?...K.....
01D0   81 0A 07 FE FF FF 8A F5 7F 00 8A F5 7F 00 00 00   ................
01E0   C1 FF 0F FE FF FF 14 EB FF 00 2F A2 2B 03 00 FE   ........../.+...
01F0   FF FF A5 FE FF FF 43 8D 2B 04 7E 04 7D 00 55 AA   ......C.+.~.}.U.
   

 第1エントリ(赤)第2エントリ(青)第3エントリ(緑)第4エントリ(バープル)と色分けしている。

 1エントリは以下のデータ項目で構成されている。

  1. ブートフラグ(1byte)
  2. パーティションの開始位置(CHSアドレス, 3bytes)
  3. パーティションタイプ(1bytes)
  4. パーティションの終了位置(CHSアドレス, 3bytes)
  5. パーティションの開始位置(LBAアドレス, 4bytes)
  6. パーティションの総セクター数(LBAアドレス, 4bytes)

 データを項目ごとでも色分けしてみよう。この方が分かりやすい場合もあるだろう。

[パーティションテーブルデータ(項目ごとの色分け)]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F   0123456789ABCDEF
   
01B0   00 00 00 00 00 2C 44 63 22 2B 23 2B 00 00 80 01   .....,Dc"+#+....
01C0   01 00 07 FE BF 09 3F 00 00 00 4B F5 7F 00 00 00   ......?...K.....
01D0   81 0A 07 FE FF FF 8A F5 7F 00 8A F5 7F 00 00 00   ................
01E0   C1 FF 0F FE FF FF 14 EB FF 00 2F A2 2B 03 00 FE   ........../.+...
01F0   FF FF A5 FE FF FF 43 8D 2B 04 7E 04 7D 00 55 AA   ......C.+.~.}.U.
   

 これに従って各エントリの中身を分解してみよう。まず第1エントリを見てみる。

[第1パーティションエントリ]

ブートフラグ 開始位置
(CHS)

パーティション
タイプ

終了位置
(CHS)
開始位置
(LBA)
総セクター数
(LBA)
80 010100 07 FEBF09 3F000000 4BF57F00

 ブートフラグは、0x80という値になっている。これはブートフラグが立っていることを示している。つまりこのパーティションがアクティブであることが分かる。尚ブートフラグが立っていない場合は「00」となる。

 前後するが、パーティションタイプ0x07という値になっている。これはこのパーティションがHPFSまたはNTFSの領域であることを示している。実際はNTFSだ。

 開始位置(LBA)後ろのバイトから読む。これはx86アーキテクチャがリトルエンディアン(この言葉の意味が分からなくても問題ない。興味のある人は自分で調べてくれ)になっているためだ。つまり「3F000000」は実は0x0000003Fだ。総セクター数(LBA)も同様に後ろのバイトから読む。従って0x007FF54Bとなる。

 CHSアドレスはそれぞれ3バイトずつで開始位置終了位置の2つがあるが、これらはちょっと面倒だ。CHSアドレスとはCylinder(シリンダー)Head(ヘッド)Sector(セクター)の3つの値からなるアドレスだが、それぞれが1バイトずつではないからである。

 ただし先頭の1バイトは、そのままヘッド値だ。

 次の2バイトがちょっと面倒だが、2バイト目の後ろ6bitセクター値3バイト目全部それの頭に2バイト目の先頭2bitをつけたものシリンダー値となる。

 計算方法としては2バイト目を64(0x40)で割った余りがセクター値となり、2バイト目を64(0x40)で割った商に256(0x100)を掛けてそれに3バイト目を足したものがシリンダー値となる。式を以下に示す。

 2バイト目 % 0x40 = セクター値
 
2バイト目 ÷ 0x40 × 0x100 + 3バイト目 = シリンダー値

 例えば、このエントリの終了位置0xFEBF09の場合、先頭の1バイト0xFEはそのままヘッド値。次の1バイト0xBFを前2bit(0x40で割った商)、後ろ6bit(0x40で割った余り)に分けると、0x020x3Fに分かれるので、後者がそのままセクター値。前者を3バイト目の頭につけた0x209シリンダー値となる訳だ。

 この解析に従って得た第1エントリのデータを整理すると次の表になる。

[第1パーティションエントリ解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 80 7 0 1 1 209 FE 3F 3F 7FF54B
10進数 128 7 0 1 1 521 254 63 63 8,385,867

 解析は以上だが、この中でちょっと注目してほしいデータがある。それはパーティションの開始位置で、CHSアドレスでは、シリンダー値0ヘッド値1セクター値1となっている。このうちシリンダー値とセクター値はそれぞれその値の最小値だが、ヘッド値第2値である1となっている(最小値は「0」)。シリンダー値0、ヘッド値0、セクター値1というすべてが最小値となる、言わば先頭セクターはマスターブートレコードだが、マスターブートレコードの次のセクターはシリンダー値0、ヘッド値0、セクター値2だ。つまり最初のパーティションはマスターブートレコードの次のセクターから始まっている訳ではないのだ。

 LBAアドレスを見ると一層そのことが明確になる。開始位置が63セクターとなっていて、マスターブートレコードの後、62セクターが未使用であることが分かる。

 これはIBMの技術書に書かれた約束事で、「最初のパーティションは第2トラック(シリンダー0、ヘッド1)から始めなければいけない」(第2トラック規定)というものだ。この決まりは、後述する「シリンダー境界規定」と合わせて、極めて重要なのでよく覚えておいてほしい。

 次に第2エントリも解析してみよう。

[第2パーティションエントリ]

ブートフラグ 開始位置
(CHS)

パーティション
タイプ

終了位置
(CHS)
開始位置
(LBA)
総セクター数
(LBA)
00 00810A 07 FEFFFF 8AF57F00 8AF57F00

[第2パーティションエントリ解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 0 7 20A 0 1 3FF FE 3F 7FF58A 7FF58A
10進数 0 7 522 0 1 1023 254 63 8,385,930 8,385,930

 ブートフラグが立っていない(00)こと、従ってこの領域がアクティブでないこと、パーティションタイプが0x07でここもNTFS領域であることなどが見て取れるだろう。

 その他注目点は、CHSアドレス開始位置ヘッド値セクター値だ。それぞれ最小値となっている。これを説明するにはそもそも話をしなければならないが、簡単に言うとパーティションは必ずシリンダー境界で作成すべきというIBMMicrosoftで決めた決まりシリンダー境界規定がある。従ってこの決まりに従えばパーティションの開始位置アドレスは必ずヘッド値とセクター値はその最小値になる訳だ。

 先ほどの第2トラック規定も実はこのシリンダー境界規定の言わば延長、または基本的にこの規定に則った上での特別規定と言えるものだ。先頭シリンダーにはマスターブートレコードがあるので、このシリンダーをパーティションが全部使うことはできない。だから本来この規定に従えば第1パーティションは第2シリンダーから始めるべきだということになる。しかしそうすると第1シリンダーがたった1セクターのマスターブートレコードのために不使用になり非常に勿体無い。そこで第1パーティションだけは第2トラックからでいいということになった訳だ。

 もうひとつ注目してほしいのが、CHSアドレス終了位置だ。FEFFFFとなっていて、シリンダー値1023ヘッド値254セクター値63という、それぞれの値の最大値だ。これはCHSが24bitまでしか表現できないために8GB以降の領域を表現しきれないことを象徴的に表している。

 既に第2エントリまででハードディスクの先頭から8GBを超えたため、第2エントリの終了位置はもうCHSアドレスでは表現できなくなっている。もはやこの値は不正なのだ。この場合、CHSアドレスでは「FEFFFF」というCHSアドレスの最大値をとりあえずパーティションテーブルには書いておくというのが習慣となっている。ヘッド値が「FF」でなく「FE」となっていてフルビット立っていない理由はよくわからないが、これはヘッド値の最大値が255ではなく、254であることを示している。

 基本的に不正なアドレスだから、OSなどから参照されることはない訳で、ある意味どんな値が入っていても構わない訳だ。どうせ正しいアドレスを書くことは不可能であり、正しいアドレスはLBAアドレスに任せておけばいいのだが、だれが作った習慣かは知らないが(Microsoftだろうが)、多くのOSの採用している習慣で、LinuxやFreeBSDなども従っている。
 

 同様に他のエントリも解析できると思うので、興味のある人は解析してみてほしい。従ってここでは他のエントリに関してはポイントだけ見てみいくことにする。もう一度項目ごとに色分けしたデータを見てほしい。

[パーティションテーブルデータ(項目ごとの色分け)]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F   0123456789ABCDEF
   
01B0   00 00 00 00 00 2C 44 63 22 2B 23 2B 00 00 80 01   .....,Dc"+#+....
01C0   01 00 07 FE BF 09 3F 00 00 00 4B F5 7F 00 00 00   ......?...K.....
01D0   81 0A 07 FE FF FF 8A F5 7F 00 8A F5 7F 00 00 00   ................
01E0   C1 FF 0F FE FF FF 14 EB FF 00 2F A2 2B 03 00 FE   ........../.+...
01F0   FF FF A5 FE FF FF 43 8D 2B 04 7E 04 7D 00 55 AA   ......C.+.~.}.U.
   

 ブートフラグは先頭のエントリ以外、「0x00」となりブートフラグが立ってないのが分かるだろう。

 パーティションタイプを見ると、第3エントリは「0F」となっていて、ここが拡張領域であることが分かる。最後の第4エントリは「A5」となっている。これはFreeBSDの領域であることを示している。

 注目したいのは第3エントリのCHSアドレス開始位置00C1FFというCHSアドレスの最大値でないことだ。第2エントリパーティションの終了位置が既に8GBを超えているなら、当然第3エントリパーティションの開始位置も8GBを超えている訳で、にも関わらず開始位置が「00C1FF」とは一体どういうことだろう。

 この「00C1FF」をさっきから解説している解析方法で分解すると、シリンダー値1023ヘッド値0セクター値1となる。これはそれぞれシリンダー値の最大値ヘッド値の最小値セクター値の最小値となる。

 賢明な読者はもう気づいただろう。これは先ほど説明したシリンダー境界既定に従っている訳だ。

 この規定はパーティションの開始位置アドレスは必ずヘッド値とセクター値はその最小値にすべきというものだった。たとえ不正なアドレスであろうとも、この決まりは守って書こうというのが、その決まりを決めた当人であるMicrosoftの習慣だ。従ってMicrosoftのツールで作成したパーティションは、8GBを超えた領域のCHS開始位置は「00C1FF」で、終了位置が「FEFFFF」となっている。

 他のOSでもこの習慣(8GB超の領域にもシリンダー境界規定を適用する)に従っているものもあるが、勿論従っていないものも多い。第4エントリのCHS開始位置が「FEFFFF」になっているのを既に皆さんは気づいているだろう。これでFreeBSDは開始位置に関してはこの習慣に従っていないことが分かると思う。

 因みにLinuxも開始位置はこの習慣には従ってない。よってLinuxのfdiskなどが作る8GB越えの領域のCHS開始位置アドレスは「FEFFFF」だ。

 


拡張パーティションテーブルの解析

 拡張領域論理領域は下図のように入れ子になっているので順次追跡していく必要がある。

[拡張領域と論理領域の入れ子構造]

 拡張領域と論理領域の情報は拡張領域の先頭セクターである拡張パーティションブートレコード(EPBR)にある。現在拡張パーティションブートレコードをダンプする適当なツールはないので、拡張領域と論理領域の追跡はやはりddコマンドが必須となる。従って解析したいハードディスクにUNIX OSをインストールするか、UNIX OSから解析したいハードディスクを見える状態にする必要があるだろう。今回はLinuxでddコマンドを使いながらこれを追跡してみる。

 まず最初に今回のサンプルの第3エントリである拡張領域を解析してみよう。まず生データを見てみる。

[拡張領域の生データ]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F   0123456789ABCDEF
   
01B0   00 00 00 00 00 2C 44 63 22 2B 23 2B 00 00 80 01   .....,Dc"+#+....
01C0   01 00 07 FE BF 09 3F 00 00 00 4B F5 7F 00 00 00   ......?...K.....
01D0   81 0A 07 FE FF FF 8A F5 7F 00 8A F5 7F 00 00 00   ................
01E0   C1 FF 0F FE FF FF 14 EB FF 00 2F A2 2B 03 00 FE   ........../.+...
01F0   FF FF A5 FE FF FF 43 8D 2B 04 7E 04 7D 00 55 AA   ......C.+.~.}.U.
   

 これを先ほどの手法により解析すると以下のデータとなると思う。

[第3パーティションエントリ解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 0F 3FF 0 1 3FF FE 3F FFEB14 32BA22F
10進数 0 15 1023 0 1 1023 254 63 16,771,860 53,191,215

 これによりこのパーティションがハードディスクの先頭から0xFFEB14(16771860)セクター先から始まっていることがわかる。従ってその先頭に最初の拡張パーティションブートレコードがあるはずだ。こういう時リニアアドレスであるLBA値は便利である。

 ddコマンドでハードディスクの先頭からこのセクター数分だけスキップしてファイル化する。
  dd if=/dev/hda of=epbr1 bs=512 count=1 skip=16771860 

 因みに第1拡張パーティションブートレコードは、if=/dev/hda3 などというそのパーティションのデバイスファイル名でもファイル化できる。しかしその後の拡張パーティションブートレコードは、if=/dev/hda3 を起点にskip指定でファイル化することができないので、最初から常に /dev/hda を起点にしている。

 さてこのファイル「epbr1」をダンプしてみる。

[第1拡張パーティションブートレコード(EPBR)のダンプデータ]
ADDRESS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
-------------------------------------------------------------------------
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 テ...............
000001C0 C1 FF 07 FE FF FF 3F 00 00 00 4B F5 7F 00 00 00 チ.....?...K.....
000001D0 C1 FF 05 FE FF FF 8A F5 7F 00 8A F5 7F 00 00 00 チ.....忌..忌....
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ
   

 見ての通りプログラム領域には何もデータがないのが分かるだろう。またパーティションテーブルも第1エントリと第2エントリしかデータがない。これを拡張パーティションテーブルと呼ぶ。

 この第1エントリが論理領域(この場合第1論理領域)のデータで、第2エントリが次の拡張領域のデータとなる訳だ。

 まず第1エントリである第1論理領域のデータを解析してみよう。

[第1拡張パーティションテーブルの第1エントリ(第1論理領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 07 3FF 1 1 3FF FE 3F 3F 7FF54B
10進数 0 7 1023 1 1 1023 254 63 63 8,385,867

 まず注目したいのは、LBAアドレスの開始位置はハードディスクの先頭からではなく、この拡張パーティションブートレコードからの相対位置であるということだ。これは実はOSによってまちまちで、ハードディスクの先頭からの絶対位置で記録するものもある。相対位置での記録はMicrosoftの習慣だが、殆どのOSがこれに従っている。

 尚、CHSアドレスは3次元アドレスなのでそもそも「相対」という概念がない。必ず絶対位置になる。ただしこのデータは既に8GBを超えているので、前述したように既に不正な値だ。

 またCHSアドレス開始位置のヘッド値は1、LBAアドレス開始位置も63となっていて、ここでも第2トラック規定が適用されているのが分かる。これは拡張パーティションブートレコードがあるためで、マスターブートレコードと第1基本パーティションの関係と同じだ。

 次に第2エントリである次の拡張領域(第2拡張領域)のデータを解析してみよう。

[第1拡張パーティションテーブルの第2エントリ(第2拡張領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 05 3FF 0 1 3FF FE 3F 7FF58A 7FF58A
10進数 0 5 1023 0 1 1023 254 63 8,385,930 8,385,930

 LBAアドレス開始位置が第1拡張パーティションブートレコードからの相対位置であるという点は第1エントリと同じだ。

 注目点としては、まずパーティションタイプがある。これは05となっている。現在拡張領域は「05」LBA対応の「0Fの二つがある(特別にLinux拡張領域もあるが)。第1拡張領域のパーティションタイプは「0F」だった。これはこの拡張領域が既に8GB超にあるためだ。先頭だけでなく一部でも8GB超にかかっている場合、「0F」というパーティションタイプになる。しかし拡張領域は、たとえ8GB超に存在したとしてもパーティションタイプは必ず05が記録される。

 次に、実はこのデータだけでは分かりにくいのだが、LBAの総セクター数残りの拡張領域全部ではなくて、次の論理領域を包含する領域だけを指している。私は拡張領域と論理領域の構成イメージを以下のような図で示してきた。

[拡張領域と論理領域の入れ子構造]

 この図のイメージからすると第2拡張領域は残りの論理領域全部を包含した、つまり第1拡張領域から第1論理領域を引いたもののように見える。しかし実際第1拡張パーティションテーブルに書かれた第2拡張領域のデータは第2論理領域だけを包含したサイズになっている。

 これは多分、子拡張領域のサイズはあまり重要ではないからだろう。誰もこのサイズを必要とするものはない。だから面倒くさい引き算をするよりは論理領域作成時にそのサイズと1トラック分を足した方が簡単だから、そのような値を書いていると思われる。

 
 さて、更に次の第2拡張パーティションブートレコードに進んでみよう。

 ddコマンドでのスキップ数は、ハードディスクの先頭から第1拡張パーティションブートレコードまでと、更に第1論理領域分を加えたものになる。

 計算方法としては、以下の2通りがある。

  1. 第1拡張領域のLBA開始位置 + 第1論理領域のLBA開始位置 + 第1論理領域のLBA総セクター数
  2. 第1拡張領域のLBA開始位置 + 第2拡張領域のLBA開始位置

 今回の例を例えば後者で計算すると、16,771,860 + 8,385,930 = 25,157,790 となる。
 
  dd if=/dev/hda of=epbr2 bs=512 count=1 skip=25157790 

 このファイル「epbr2」をダンプしてみよう。もうプログラム領域はどうせ全部00なのは分かっているのでパーティションテーブルの部分だけを見てみる。

[第2拡張パーティションブートレコード(EPBR)のダンプデータ]
ADDRESS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
-------------------------------------------------------------------------
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
000001C0 C1 FF 07 FE FF FF 3F 00 00 00 4B F5 7F 00 00 00 チ.....?...K.....
000001D0 C1 FF 05 FE FF FF 14 EB FF 00 D9 E5 3F 01 00 00 チ.........ル.....
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ
   

 同様に第1エントリから解析する。

[第2拡張パーティションテーブルの第1エントリ(第2論理領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 07 3FF 1 1 3FF FE 3F 3F 7FF54B
10進数 0 7 1023 1 1 1023 254 63 63 8,385,867

 第1論理領域と全く同じである。LBA開始位置もこの第2拡張パーティションブートレコードからの相対位置となっている。

 先ほどの子拡張領域の総セクター数の説明として、この領域のLBA開始位置と総セクター数を足したもの 63 + 8,385,867 = 8,385,930 が先の子拡張領域の総セクター数になっているのも分かると思う。

 次に第2エントリである次の拡張領域(第3拡張領域)のデータを解析してみよう。

[第2拡張パーティションテーブルの第2エントリ(第3拡張領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 05 3FF 0 1 3FF FE 3F FFEB14 13FE5D9
10進数 0 5 1023 0 1 1023 254 63 16,771,860 20,964,825

 この値で気をつけたいのがLBA開始位置だ。第1エントリの論理領域と違って、相対位置は相対位置なのだが、この第2拡張パーティションブートレコードからの相対位置ではなく、第1拡張パーティションブートレコードからの相対位置になっている。これは後に続くすべての拡張パーティションブートレコードで共通で、すべて第1拡張パーティションブートレコードからの相対位置となる。

 従って次の第3拡張パーティションブートレコード位置の算出も、第1拡張パーティションブートレコードのLBA開始位置 + 第3拡張領域のLBA開始位置だけでOKだ。(第2拡張パーティションブートレコードのLBA開始位置を足す必要はない)

 

 それでは早速次ぎのデータに進もう。上記のことからddコマンドのスキップ値は、16,771,860 + 16,771,860 = 33,543,720 となるのは分かるだろう。
  
  dd if=/dev/hda of=epbr3 bs=512 count=1 skip=33543720 

[第3拡張パーティションブートレコード(EPBR)のダンプデータ]
ADDRESS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
-------------------------------------------------------------------------
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
000001C0 C1 FF 0B FE FF FF 3F 00 00 00 9A E5 3F 01 00 00 チ.....?...壼?...
000001D0 C1 FF 05 FE FF FF ED D0 3F 02 10 EC 03 00 00 00 チ.....?.......
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ
   

[第3拡張パーティションテーブルの第1エントリ(第3論理領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 0B 3FF 1 1 3FF FE 3F 3F 13FE59A
10進数 0 11 1023 1 1 1023 254 63 63 20,964,762

 パーティションタイプが0Bなのでこの第3論理領域はFAT32の領域であることがわかる。それ以外は今まで説明したとおりで、特筆すべきことはない。

[第3拡張パーティションテーブルの第2エントリ(第4拡張領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 05 3FF 0 1 3FF FE 3F 23FD0ED 3EC10
10進数 0 5 1023 0 1 1023 254 63 37,736,685 257,040

 こちらも特筆すべきことはない。まあ総セクター数が少ないので次の論理領域はきっと小さな領域だなというのが分かる程度だ。

 


 さて、更に先に進もう。ddコマンドのスキップ値は、16,771,860 + 37,736,685 = 54,508,545 であるのはもう分かるだろう。
 
  dd if=/dev/hda of=epbr4 bs=512 count=1 skip=54508545 

[第4拡張パーティションブートレコード(EPBR)のダンプデータ]
ADDRESS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
-------------------------------------------------------------------------
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FE ................
000001C0 FF FF 82 FE FF FF 3F 00 00 00 D1 EB 03 00 00 00 ......?...ム.....
000001D0 C1 FF 05 FE FF FF FD BC 43 02 7E 43 3E 00 00 00 チ......シC.~C>...
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ
   

[第4拡張パーティションテーブルの第1エントリ(第4論理領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 82 3FF FE FF 3FF FE 3F 3F 3EBD1
10進数 0 130 1023 254 63 1023 254 63 63 256,977

 パーティションタイプが82なのでこの第4論理領域はLinux Swapの領域であることがわかる。またCHSアドレス開始位置がCHSの最大値になっていて、Microsoftの習慣には従っていないことが見て取れる。

[第4拡張パーティションテーブルの第2エントリ(第5拡張領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 05 3FF 0 1 3FF FE 3F 243BCFD 3E437E
10進数 0 5 1023 0 1 1023 254 63 37,993,725 4,080,510

 こちらはCHS値がすべてMicrosoftの習慣に従っている。Linuxも中途半端なのか?

 

 さて、まだ先に進もう。ddコマンドのスキップ値は、16,771,860 + 37,993,725 = 54,765,585 だ。
 
  dd if=/dev/hda of=epbr5 bs=512 count=1 skip=54765585 

[第5拡張パーティションブートレコード(EPBR)のダンプデータ]
ADDRESS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
-------------------------------------------------------------------------
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FE ................
000001C0 FF FF 83 FE FF FF 3F 00 00 00 3F 43 3E 00 00 00 ......?...?C>...
000001D0 C1 FF 05 FE FF FF 7B 00 82 02 3F 82 3E 00 00 00 チ.....{...?.....
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ
   

[第5拡張パーティションテーブルの第1エントリ(第5論理領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 83 3FF FE FF 3FF FE 3F 3F 3E433F
10進数 0 131 1023 254 63 1023 254 63 63 4,080,447

 パーティションタイプが83なのでこの第5論理領域はext2fs(Linux Native)の領域であることがわかる。また開始位置CHSがCHSの最大値になっていて、やはりMicrosoftの習慣には従っていないことが見て取れる。

[第5拡張パーティションテーブルの第2エントリ(第6拡張領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 05 3FF 0 1 3FF FE 3F 282007B 3E823F
10進数 0 5 1023 0 1 1023 254 63 42,074,235 4,096,575

 こちらも第5論理領域同様CHS値がすべてMicrosoftの習慣に従っている。

 

 さあ大分疲れてきたが。これで最後なのでもうひとつ進もう。ddコマンドのスキップ値は、16,771,860 + 42,074,235 = 58,846,095 だ。
 
  dd if=/dev/hda of=epbr6 bs=512 count=1 skip=58846095 

[第6拡張パーティションブートレコード(EPBR)のダンプデータ]
ADDRESS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
-------------------------------------------------------------------------
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
000001C0 C1 FF 83 FE FF FF 3F 00 00 00 00 82 3E 00 00 00 チ.....?.........
000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ
   

 ついに第2エントリが無くなった。もうこれ以上論理領域がないことを示している。

[第6拡張パーティションテーブルの第1エントリ(第6論理領域)の解析結果]

  ブートフラグ パーティションタイプ CHSアドレス LBAアドレス
開始位置 終了位置 開始位置 総セクター数
C H S C H S
16進数 00 83 3FF 1 1 3FF FE 3F 3F 3E8200
10進数 0 131 1023 1 1 1023 254 63 63 4,096,512

 パーティションタイプが83なのでこの第6論理領域もext2fs(Linux Native)の領域であることがわかる。また開始位置CHSがMicrosoftの習慣には従っている。なんかLinuxのポリシーが何だかさっぱりわからなくなってきた。

 以上で論理領域の追跡調査は終了だ。ああ疲れた。