0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自作OSでファイルシステムを実現する為にFAT16の構造を調べる

Posted at

「手探りでCUI OS作成に挑む」連載

この記事は「手探りでCUI OS作成に挑む」連載の一部です。
全体の目次は「手探りでCUI OS作成に挑む」連載目次を御覧下さい。

仮想HDDを作成しFAT16で初期化

BPBを見たいだけなのでパーティションは作らない。

# 1. 16MBの空ファイルを作成
dd if=/dev/zero of=disk.img bs=1M count=16

# 2. ループデバイスに割り当て
sudo losetup -f --show disk.img
# 例えば /dev/loop0 と表示される

# 3. ループデバイスに直接FAT16を作る(パーティションテーブルなしでOK)
sudo mkfs.fat -F 16 /dev/loop0

# 4. マウント用ディレクトリを作る
mkdir mnt

# 5. マウントして中身を見る
sudo mount /dev/loop0 mnt
ls mnt  # 空のはず

# 6. 書き込みなどしてみる
echo "hello" | sudo tee mnt/hello.txt

# 7. 中身確認
ls mnt
cat mnt/hello.txt

# 8. 終わったらアンマウント&ループデバイス解除
sudo umount mnt
sudo losetup -d /dev/loop0

FAT16 ブートセクタ(BPB)解析

ダンプを取る

xxd -l 512 disk.img
PBP
test@test-ThinkPad-X280:~/kaihatsu/disk$ xxd -l 512 disk.img
00000000: eb3c 906d 6b66 732e 6661 7400 0204 0400  .<.mkfs.fat.....
00000010: 0200 0200 80f8 2000 2000 0200 0000 0000  ...... . .......
00000020: 0000 0000 8000 294d 8f33 6a4e 4f20 4e41  ......)M.3jNO 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.

オフセット バイト数 項目 16進値 説明
0x00 3 ジャンプ命令 EB 3C 90 ブートセクタ先頭へのジャンプ
0x03 8 OEM名 6D 6B 66 73 2E 66 61 74 "mkfs.fat"作成ツール名
0x0B 2 バイト/セクタ 00 02 512 バイト/セクタ
0x0D 1 セクタ/クラスタ 04 1クラスタ = 4セクタ
0x0E 2 予約セクタ数 00 04 予約領域 4セクタ
0x10 1 FATコピー数 02 FATコピー数 2
0x11 2 ルートディレクトリエントリ数 00 02 512エントリ(リトルエンディアン)
0x13 2 総セクタ数(小) 80 F8 0xF880 = 63680 セクタ
0x15 1 メディアタイプ F8 メディアタイプ
0x16 2 FATサイズ(セクタ数) 20 00 FATサイズ 32 セクタ
0x18 2 セクタ/トラック 20 00 32 セクタ/トラック
0x1A 2 ヘッド数 00 00 0(未設定)
0x1C 4 隠しセクタ数 00 00 00 00 0(未設定)
0x20 4 総セクタ数(大) 00 00 00 00 0の場合、小さい方を使う
0x24 1 ドライブ番号 00 0x80 = 固定ディスク
0x25 1 予約 00 予約
0x26 1 目印 00 0x29 固定
0x27 4 ボリュームシリアル番号 00 00 00 00 シリアル番号
0x2B 11 ボリュームラベル 00 00 00 00 00 00 00 00 00 00 00 "NO NAME "(スペース)
0x36 8 ファイルシステムタイプ 00 00 00 00 00 00 00 00 "FAT16 "
0x1FE 2 ブートセクタ目印 55 AA MBRの最後の目印

各領域の開始セクタ計算

領域名 計算式 結果(セクタ番号) 説明
予約領域開始 0 0 ブートセクタ開始
予約領域終了 予約セクタ数 - 1 3 予約領域は4セクタ分
FAT1開始 予約セクタ数 4 予約領域の直後から
FAT1終了 FAT1開始 + FATサイズ - 1 35 32セクタ分
FAT2開始 FAT1終了 + 1 36 FATの2つ目コピー
FAT2終了 FAT2開始 + FATサイズ - 1 67 32セクタ分
ルートディレクトリ開始 FAT2終了 + 1 68 FATコピーの直後
ルートディレクトリサイズ ルートディレクトリエントリ数 × 32 / バイト/セクタ 512 × 32 / 512 = 32 512エントリ × 32バイト / 512バイト/セクタ
データ領域開始 ルートディレクトリ開始 + ルートディレクトリサイズ 68 + 32 = 100 ここからクラスタ領域(ファイルデータ)

FAT1のダンプ

開始セクタ = 予約セクタ数 = 4
開始バイト = 4 × 512 = 2048 バイト

test@test-ThinkPad-X280:~/kaihatsu/disk$ xxd -s 2048 -l 16384 disk.img
00000800: f8ff ffff 0000 ffff 0000 0000 0000 0000  ................
00000810: 0000 0000 0000 0000 0000 0000 0000 0000  ................
オフセット クラスタ番号 内容 (リトルエンディアン) 状態
0x0000 0 F8FF → 0xFFF8 メディア識別+予約領域
0x0002 1 FFFF → 0xFFFF 使用中(終端マーク)
0x0004 2 0000 → 0x0000 空きクラスタ
0x0006 3 FFFF → 0xFFFF 使用中(終端マーク)
0x0008〜 4〜 0000 → 空きクラスタ 空きクラスタ

1クラスタ未満のファイルしか保存していない為、FAT1は終端の情報しかない。

ルートディレクトリのダンプ

開始バイト = 68 × 512 = 34816 バイト

test@test-ThinkPad-X280:~/kaihatsu/disk$ xxd -s 34816 -l 16384 disk.img
00008800: 4168 0065 006c 006c 006f 000f 00f1 2e00  Ah.e.l.l.o......
00008810: 7400 7800 7400 0000 ffff 0000 ffff ffff  t.x.t...........
00008820: 4845 4c4c 4f20 2020 5458 5420 0099 9665  HELLO   TXT ...e
00008830: de5a de5a 0000 9665 de5a 0300 0600 0000  .Z.Z...e.Z......
00008840: 0000 0000 0000 0000 0000 0000 0000 0000  ................

ファイルは1つなのに2つのエントリが見えるが、上の方は長いファイル名(LFN)用の特殊なエントリなので、自作OSを作る上では無視してよい。

項目 内容
オフセット 0x00 41 順番(ビット7=1で最後のLFN)0x41=最後のエントリ
0x01〜0x0A 68 00 65 00 6C 00 6C 00 6F 00 UTF-16文字列 "hello"
0x0B 0F 属性(LFNの固定値)
0x0C 00 型(常に0、予約)
0x0D F1 チェックサム(8.3エントリ名との対応用)
0x0E〜0x19 2E 00 74 00 78 00 74 00 UTF-16文字列 "txt"(拡張子部分)
0x1A〜0x1B FF FF 未使用領域
0x1C〜0x1D FF FF 未使用領域
0x1E〜0x1F FF FF 未使用領域
オフセット 内容 説明
0x00〜0x07 48 45 4C 4C 4F 20 20 20 → "HELLO " ファイル名部分(8文字固定、パディングあり)
0x08〜0x0A 54 58 54 → "TXT" 拡張子部分(3文字固定)
0x0B 00 属性(通常ファイル、属性なし)
0x0C 99 予約(システム用、通常無視)
0x0D〜0x0E 96 65 作成時間(詳細は別途解析必要)
0x0F〜0x10 DE 5A 作成日(詳細は別途解析必要)
0x11〜0x12 DE 5A 最終アクセス日
0x13〜0x14 00 00 高位クラスタ番号(FAT16では未使用)
0x15〜0x16 96 65 最終更新時間
0x17〜0x18 DE 5A 最終更新日
0x1A〜0x1B 03 00 → 0x0003 先頭クラスタ番号
0x1C〜0x1F 06 00 00 00 → 0x00000006 ファイルサイズ(バイト単位)

ファイルのダンプ

ルートディレクトリによると先頭クラスタ番号 = 0x0003

データ領域開始セクタ = 予約セクタ数 + (FAT数 × FATセクタ数) + ルートディレクトリセクタ数

ルートディレクトリエントリ数 = 0x0200 = 512エントリ
1エントリ = 32バイト → 512エントリ × 32バイト = 16384バイト = 32セクタ

予約セクタ数 = 0x0004 = 4セクタ
FAT数 = 2
FATサイズ = 0x0020 = 32セクタ

データ領域開始 = 4 + (2 × 32) + 32 = 100セクタ目

先頭クラスタ3の位置 = データ領域開始 + (クラスタ番号 - 2) × セクタ/クラスタ
クラスタ番号 = 3、セクタ/クラスタ = 4

なので:
先頭クラスタ3の開始セクタ = 100 + (3 - 2) × 4 = 104セクタ目

test@test-ThinkPad-X280:~/kaihatsu/disk$ xxd -s 53248 -l 512 disk.img
0000d000: 6865 6c6c 6f0a 0000 0000 0000 0000 0000  hello...........
0000d010: 0000 0000 0000 0000 0000 0000 0000 0000  ................

ダンプを取るとテキストファイルの中身が確認出来る。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?