mkdosfsで遊ぶ

FAT形式のファイルシステムを作成する「mkdosfs」を使って、面白いことを見つけたので
記事にまとめます。

用意するもの

ちょっとした驚きまでの手順

USBフラッシュメモリを使用し、/dev/sdbで認識しているとします。


やることは、/dev/sdbをmkdosfsでフォーマットするだけです。

$ sudo mkdosfs -I /dev/sdb
  • 何気なく指定している「-I」オプションや、「/dev/sdb1」のようにパーティション指定をしない点が重要です


ファイルは何も配置されていません。

$ sudo mount /dev/sdb /mnt/ 
$ ls -a /mnt/
.  ..
$ sudo umount /mnt/


ですが、このUSBフラッシュメモリを挿したままマシンを再起動すると・・・。
以下のメッセージが画面に表示されます!

This is not a bootable disk. Please insert a bootable floppy and
press any key to try again

  • ほっといても、もうどうしようもないので、電源ボタンで電源OFFしてください
  • 表示されず、通常通りOSが立ち上がってしまう場合は、BIOSでドライブの優先順位の設定を行なってみてください
    • bios ドライブ 優先順位」などで検索すると色々と出てきます

何が起きていたのか?

「中身が空」を確認していたのに。。。
ならどこから、あのメッセージは出てきたのか?
(また、どこにあのメッセージは保存されているのか?)
を考えると、少し不思議です。


答えは、ファイルシステムの中身を見るとわかります。

$ hexdump -C /dev/sdb | head
00000000  eb 3c 90 6d 6b 64 6f 73  66 73 00 00 02 08 08 00  |.<.mkdosfs......|
00000010  02 00 02 00 00 f8 f8 00  3d 00 08 00 00 00 00 00  |........=.......|
00000020  00 a0 07 00 00 00 29 c0  f0 f7 b6 20 20 20 20 20  |......)....     |
00000030  20 20 20 20 20 20 46 41  54 31 36 20 20 20 0e 1f  |      FAT16   ..|
00000040  be 5b 7c ac 22 c0 74 0b  56 b4 0e bb 07 00 cd 10  |.[|.".t.V.......|
00000050  5e eb f0 32 e4 cd 16 cd  19 eb fe 54 68 69 73 20  |^..2.......This |
00000060  69 73 20 6e 6f 74 20 61  20 62 6f 6f 74 61 62 6c  |is not a bootabl|
00000070  65 20 64 69 73 6b 2e 20  20 50 6c 65 61 73 65 20  |e disk.  Please |
00000080  69 6e 73 65 72 74 20 61  20 62 6f 6f 74 61 62 6c  |insert a bootabl|
00000090  65 20 66 6c 6f 70 70 79  20 61 6e 64 0d 0a 70 72  |e floppy and..pr|
000000a0  65 73 73 20 61 6e 79 20  6b 65 79 20 74 6f 20 74  |ess any key to t|
000000b0  72 79 20 61 67 61 69 6e  20 2e 2e 2e 20 0d 0a 00  |ry again ... ...|


hexdumpは、引数で指定したファイルを16進や、その他の形式でダンプするコマンドです。
この場合は、USBフラッシュメモリに書かれているバイナリ列を16進(中央列)とASCII(右列)でダンプしています。
(左の列はアドレスです)


ASCIIの列を見ると、「This is not a ...」のメッセージがあり、
やはり、あのメッセージはUSBメモリに書かれていたのだとわかります。


「ファイル」としては見えないけど、mkdosfsはコッソリと、
あのメッセージをUSBフラッシュメモリに書いていたのです。

なぜ、mkdosfsはこんなことをしているのか?

PCの電源投入時、BIOSは起動デバイスとして設定されたデバイスの先頭512バイトをメモリにロードします。
この512バイトが、基本的にブートローダーのプログラムで、このブートローダーがOS起動のための処理を行います。


「先頭512バイト」は、アドレスで0x000〜0x1FFで、あのメッセージが書かれていた場所です。
mkdosfsは、フォーマットしたデバイスが誤って起動デバイスとして選択されてしまった時のために、
「『これはブート用のデバイスではないよ』というメッセージを画面表示するプログラム」
を先頭512バイトに書いていたわけです。


ちなみに、mkdosfs実行時に「-I」オプションを指定したり、パーティション指定をしなかったりしたのは、
パーティションがあると、デバイスの先頭にパーティションテーブルが配置されてしまうためです。

QEMUで試す場合

「デバイスファイル」でなくても、「通常のファイル」に対してもファイルシステムを作成することが可能です。


まず、空のファイルを用意します。(この場合は1Mバイト)

$ dd if=/dev/zero of=mkdosfs_test.img bs=1M count=1
1+0 レコード入力
1+0 レコード出力
1048576 バイト (1.0 MB) コピーされました、 0.0036791 秒、 285 MB/秒


ファイル自体が空の状態です。

$ hexdump -Cv mkdosfs_test.img | head
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  |................|


mkdosfsでファイルシステムを作成します。

$ sudo mkdosfs mkdosfs_test.img 
mkdosfs 3.0.13 (30 Jun 2012)
  • sudoを使わず、/sbin/mkdosfsでもOKです


マウントし、何もファイルが無いことを確認します。

$ sudo mount -o loop mkdosfs_test.img /mnt/
$ ls -a /mnt/
.  ..
$ sudo umount /mnt/


QEMUで起動デバイスとして指定し、起動します。

$ qemu -fda mkdosfs_test.img


以下のメッセージが表示されると思います。

This is not a bootable disk. Please insert a bootable floppy and
press any key to try again


hexdumpで確認すると、あのメッセージが書かれていることがわかります。

$ hexdump -C mkdosfs_test.img | head -n 12
00000000  eb 3c 90 6d 6b 64 6f 73  66 73 00 00 02 04 01 00  |.<.mkdosfs......|
00000010  02 00 02 00 08 f8 02 00  20 00 40 00 00 00 00 00  |........ .@.....|
00000020  00 00 00 00 00 00 29 2f  fe ee a7 20 20 20 20 20  |......)/...     |
00000030  20 20 20 20 20 20 46 41  54 31 32 20 20 20 0e 1f  |      FAT12   ..|
00000040  be 5b 7c ac 22 c0 74 0b  56 b4 0e bb 07 00 cd 10  |.[|.".t.V.......|
00000050  5e eb f0 32 e4 cd 16 cd  19 eb fe 54 68 69 73 20  |^..2.......This |
00000060  69 73 20 6e 6f 74 20 61  20 62 6f 6f 74 61 62 6c  |is not a bootabl|
00000070  65 20 64 69 73 6b 2e 20  20 50 6c 65 61 73 65 20  |e disk.  Please |
00000080  69 6e 73 65 72 74 20 61  20 62 6f 6f 74 61 62 6c  |insert a bootabl|
00000090  65 20 66 6c 6f 70 70 79  20 61 6e 64 0d 0a 70 72  |e floppy and..pr|
000000a0  65 73 73 20 61 6e 79 20  6b 65 79 20 74 6f 20 74  |ess any key to t|
000000b0  72 79 20 61 67 61 69 6e  20 2e 2e 2e 20 0d 0a 00  |ry again ... ...|

おわりに

面白いネタだと思って、勢いで書いた割には「当たり前」なことばかりの記事になってしまいました。


なお、今回のネタは、「QEMUで試す場合」で紹介した「通常ファイルをフォーマットする」方法で、色々なファイルシステムでフォーマットし、バイナリをダンプして眺める事を繰り返している中で見つけました。


マウントし、ファイルをいくつか配置した後、ダンプすれば、
ファイル名やファイル内容が管理されている様子を見ることができ、面白いです。

  • ASCII文字のファイル名で、ASCII文字のテキストファイルを配置するとわかりやすいです


# mkdosfsが先頭512バイトに警告メッセージのプログラムを配置するネタから、
# 古いプレステ等のゲーム用CD-ROMにあった警告音声を思い出しました。
# - ゲーム用CD−ROMの警告メッセージ: 面白ゲーム変遷史 名作からクソゲーまで