MBR復旧

Windows Vistaの入ったディスクのMBRにインストールしてあったgrubを消したかったのだが、Linuxからえいやっと

dd if=/dev/zero of=/dev/sda bs=512 count=1

としてしまった。大事なパーティションテーブルまで吹っ飛ばしてしまった。バックアップは取ってない。

NTFSパーティションは先頭からだいたい250GB位までだった記憶を元にfdiskコマンドでパーティションを作成。先頭番地としては1を指定。作成後mountしようにも、NTFSとして認識されてない。

調べてみるとNTFSパーティションは"eb 52 90 4e 54 46 53 20 20 20 20"で始まるようだ。ところが、作ったパーティションはそうはなっていない。

dd if=/dev/sda1 of=sda1.img bs=512 count=1
hd -C sda1.img

とすると"00 00 00 ..."となっている。調べてみると、

dd if=/dev/sda of=sda.img bs=512 count=100000
hd -C sda.img | grep 'eb 52 90 4e' 

このバイト列は、実際にはディスクの0x100000バイト目から書かれていた。

mount -t ntfs -o ro,offset=0x100000 /dev/sda /mnt

とすると実際にマウントできた。

sda1は0x100000から始まらなければならないところ、実際には0x7e00から始まっていた。再度fdiskコマンドでパーティションを作成しなおした。今度は先頭番地として2を指定。今度はsda1は0x7d8200番地から始まっている。ふむ先頭番地は1では前過ぎるし、2では後ろすぎる。

もう少しパーティションテーブルの構造を調べた。0x1beバイト目から一つのパーティション毎16byteづつ書かれている。

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

大きなディスクはCHSは無効であり、LBAで使われており、fdiskのプロンプトで開始位置に1を指定したときだと、 パーティションの開始位置(LBA)は、"3f 00 00 00" = 63となっておりセクタの大きさ512byteを掛けるとちょうど期待される0x7e00になっている。

fdiskが飛び飛びの値しか設定できないようなので、直接パーティションテーブルを変更する方針にした。

bvi mbr

sda1の開始位置が0x100000となるように、"00 08 00 00"を指定。対象のディスクにはVista以外のパーティションは存在しないので、総セクタ数には、最大の"30 60 38 3a"を指定。

dd if=mbr of=/dev/sda bs=512 count=1

で書き戻した。

VistaのDVDでbootして、コマンドプロンプトを起動し、MBRを復旧。

bootrec /fixmbr

無事、Vistaがbootできるようになった。実際のパーティションファイルシステムの大きさがあっていないはずなので、Vistaの「ボリュームの圧縮」を実施して300MB程度に縮めた。本当はもっと小さかったはずだがなぜかこれ以下にはできなかった。

C:ドライブのプロパティを見ると、期待するサイズより大幅に小さい73GB程度になっていた。再度Vistaの「ボリュームの拡張」を実施し、20GBほど増やしてみた。今度は期待するサイズに一致した。なんでか分からないけど。

危ないことをするときは、慎重にバックアップを取らないと駄目ですな。