FAT16 ブートセクタの構造体
// FAT16 BPB (BIOS Parameter Block)
// オフセットはブートセクタの先頭 (0x0000) からの相対位置
#pragma pack(push, 1)
typedef struct {
// ジャンプ命令とOEM識別子(BPBの前の部分)
uint8_t BS_jmpBoot[3]; // 0x00: ブートコードへのジャンプ命令 (例: EB 3C 90)
char BS_OEMName[8]; // 0x03: フォーマットしたOS/ツールの識別子 (例: "MSDOS5.0")
// BPB要素
uint16_t BPB_BytsPerSec; // 0x0B: 1セクタのバイト数 (通常512)
uint8_t BPB_SecPerClus; // 0x0D: 1クラスタのセクタ数 (1,2,4,8,...,128)
uint16_t BPB_RsvdSecCnt; // 0x0E: 予約セクタ数 (FAT領域の前、通常1)
uint8_t BPB_NumFATs; // 0x10: FATの個数 (通常2)
uint16_t BPB_RootEntCnt; // 0x11: ルートディレクトリのエントリ数 (FAT16では通常512)
uint16_t BPB_TotSec16; // 0x13: 総セクタ数 (32MB未満の場合。0なら後続フィールドを使用)
uint8_t BPB_Media; // 0x15: メディア記述子 (0xF8=固定ディスク, 0xF0=リムーバブル)
uint16_t BPB_FATSz16; // 0x16: 1つのFATの大きさ(セクタ数)
uint16_t BPB_SecPerTrk; // 0x18: 1トラックあたりのセクタ数 (CHS用)
uint16_t BPB_NumHeads; // 0x1A: ヘッド数 (CHS用)
uint32_t BPB_HiddSec; // 0x1C: ボリューム前の隠蔽セクタ数
uint32_t BPB_TotSec32; // 0x20: 総セクタ数 (BPB_TotSec16が0の場合に使用)
// FAT16 拡張BPB (EBPB)
uint8_t BS_DrvNum; // 0x24: ドライブ番号 (INT 13h用)
uint8_t BS_Reserved1; // 0x25: 予約領域
uint8_t BS_BootSig; // 0x26: 拡張ブート署名 (0x29=次のフィールドが有効)
uint32_t BS_VolID; // 0x27: ボリュームシリアル番号
char BS_VolLab[11]; // 0x2B: ボリュームラベル
char BS_FilSysType[8]; // 0x36: ファイルシステムタイプ (例: "FAT16 ")
uint8_t BootCode[448]; // 0x3E: 機械語
uint16_t BS_BootSign; // 0x1FE: 0xAA55
} FAT16_BPB;
#pragma pack(pop)
BPBの手動解析
仮想ディスク生成
dd if=/dev/zero of=fat16.img bs=1M count=10
sudo mkfs.vfat -F 16 fat16.img
sudo mount -o loop,uid=$(id -u),gid=$(id -g) fat16.img /mnt
test@test-fujitsu:~/kaihatsu$ xxd fat16.img | head -32
00000000: eb3c 906d 6b66 732e 6661 7400 0204 0400 .<.mkfs.fat.....
00000010: 0200 0200 50f8 1400 2000 0200 0000 0000 ....P... .......
00000020: 0000 0000 8001 291c 89b5 e54e 4f20 4e41 ......)....NO NA
00000030: 4d45 2020 2020 4641 5431 3620 2020 0e1f ME FAT16 ..
00000040: be5b 7cac 22c0 740b 56b4 0ebb 0700 cd10 .[|.".t.V.......
00000050: 5eeb f032 e4cd 16cd 19eb fe54 6869 7320 ^..2.......This
00000060: 6973 206e 6f74 2061 2062 6f6f 7461 626c is not a bootabl
00000070: 6520 6469 736b 2e20 2050 6c65 6173 6520 e disk. Please
00000080: 696e 7365 7274 2061 2062 6f6f 7461 626c insert a bootabl
00000090: 6520 666c 6f70 7079 2061 6e64 0d0a 7072 e floppy and..pr
000000a0: 6573 7320 616e 7920 6b65 7920 746f 2074 ess any key to t
000000b0: 7279 2061 6761 696e 202e 2e2e 200d 0a00 ry again ... ...
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000130: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000140: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000150: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000160: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000170: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000180: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000190: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa ..............U.
uint8_t BS_jmpBoot[3]
BPBを飛ばしてThis is not a bootable disk. Please insert a bootable floppy and..press any key to try againを表示する機械語の保存されているオフセットまで跳ぶ命令。
eb3c 90 = jmp 0x7c3e nop
char BS_OEMName[8]
FAT16の初期化に使用したソフトの名称。今回使用したLinuxのソフトと一致する。
6d 6b66 732e 6661 74 = mkfs.fat
uint16_t BPB_BytsPerSec
1セクタのバイト数
00 02(0x200) = 512
uint8_t BPB_SecPerClus
1クラスタのセクタ数
04 = 4セクタ
1クラスタ=512*4=2048バイト
uint16_t BPB_RsvdSecCnt
FAT領域の前
04 00(0x04) = 4セクタ
uint8_t BPB_NumFATs
FAT表の個数。通常は2個ある。
02 = 2個
uint16_t BPB_RootEntCnt;
ルートディレクトリの要素数。通常は512個
00 02(0x200) = 512個
uint16_t BPB_TotSec16
総セクタ数
00 50(0x5000)=20,480
uint8_t BPB_Media;
記憶媒体の種類
f8 = 固定
uint16_t BPB_FATSz16
FATの大きさ(セクタ数)
1400(0x14)=20セクタ = 20*512 = 10240バイト
uint16_t BPB_SecPerTrk
2000(0x0020)=32セクタ/トラック
BPB_NumHeads
0200(0x0002)=2
uint32_t BPB_HiddSec
0000 0000
uint32_t BPB_TotSec32
0000 0000
uint8_t BS_DrvNum
80
uint8_t BS_Reserved1
予約領域
01
uint8_t BS_BootSig
29
uint32_t BS_VolID
1c 89b5 e5(0xe5b5891c)
char BS_VolLab[11]
4e 4f20 4e41 4d45 2020 2020 = NO NAME
char BS_FilSysType[8]
4641 5431 3620 2020 = FAT16
uint8_t BootCode[448]
以下を参照
FAT16の構造研究1ブートセクタ
uint8_t BootCode[448]
55aa
検証に当たってディレクトリ及びファイルを追加する
echo "Hello FAT16" | sudo tee /mnt/test.txt
cat /mnt/test.txt
sudo mkdir /mnt/dir1
sudo mkdir /mnt/dir2
Fat表
BPB_RsvdSecCnt=4セクタなのでFATはLBA4から始まる
test@test-fujitsu:~/kaihatsu$ xxd -s 2048 -l 512 fat16.img
00000800: f8ff ffff 0000 ffff ffff ffff 0000 0000 ................
00000810: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000820: 0000 0000 0000 0000 0000 0000 0000 0000 ................
...(省略)...
ルートディレクトリ
ルートディレクトリ開始セクタ = 予約セクタ + (FAT数 × FATo大きさ)
= 4 + (2 × 20) = 4 + 40 = 44セクタ
バイトオフセット: 44 × 512 = 22528バイト
test@test-fujitsu:~/kaihatsu$ xxd -s 22528 -l 512 fat16.img
00005800: 4174 0065 0073 0074 002e 000f 008f 7400 At.e.s.t......t.
00005810: 7800 7400 0000 ffff ffff 0000 ffff ffff x.t.............
00005820: 5445 5354 2020 2020 5458 5420 0042 2c8b TEST TXT .B,.
00005830: 9e5c 9e5c 0000 2c8b 9e5c 0300 0c00 0000 .\.\..,..\......
00005840: 4164 0069 0072 0031 0000 000f 00a8 ffff Ad.i.r.1........
00005850: ffff ffff ffff ffff ffff 0000 ffff ffff ................
00005860: 4449 5231 2020 2020 2020 2010 0044 2c8b DIR1 ..D,.
00005870: 9e5c 9e5c 0000 2c8b 9e5c 0400 0000 0000 .\.\..,..\......
00005880: 4164 0069 0072 0032 0000 000f 00aa ffff Ad.i.r.2........
00005890: ffff ffff ffff ffff ffff 0000 ffff ffff ................
000058a0: 4449 5232 2020 2020 2020 2010 0045 2c8b DIR2 ..E,.
000058b0: 9e5c 9e5c 0000 2c8b 9e5c 0500 0000 0000 .\.\..,..\......
000058c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................