FAT16 をSTM8Sに移植するための調査

FAT16をSTM8Sに移植するという意味は、windowsのファイルシステムであるFAT16に準拠してSDカードにアクセスするプログラムを書 く、ということです.これができるとPCとSTM8Sの間でストレージのやりとりができるのでなにかと便利だと思います.

けれど、STM8SでFAT16にマトモにアクセスするのは難しそうでくじけそうです.
最低限やりたいことは、STM8Sで測定したデータをSDカードにストアし、それをPCで容易に読めることと決めまして、以下のように調査しました.した がって、directoryがどう実装されているのかは調査してません.


知ってお くべき用語

セクタ     SDカードのhardware的に決まっている、データアクセスする最小単位で、SDカードの容量に関わらずいつも512バイトであるらしい.このページ では、セクタという呼び名ではなくブロックという呼び名で統一しようと思います.

クラスタ   ブロック(セクタ)を何個か集めて1クラスタとする.クラスタはファイルシステムがデータアクセスする最小単位.ややこしいことに、何個かは決まっておら ず、下表のように、SDカードの容量に応じて変わる.

クラスタサイズ     下表のように2kB〜64kBまで様々.たった一行のTEXTファイルであっても、SDカード上の占有量はクラスタサイズになってしまいますので、ある意 味もったいなし.

FAT16 で確保できるSDカード容量と、クラスタサイズ

SDカード容量 ブロック(セクタ)サイズ
1クラスタのブロック(セクタ)数
クラスタサイズ
〜15MB


確保不能
16〜127MB
512BYTE
4
2kB
128〜255MB 512BYTE 8
4kB
256〜511MB 512BYTE 16
8kB
512〜1023MB 512BYTE 32
16kB
1024MB〜2048MB 512BYTE 64
32kB
2GB〜4GB 512BYTE 128
64kB
4GB〜8GB 512BYTE 256
128kB(NT4のみ)
8GB〜16GB 512BYTE 512
256kB(NT4のみ)

以下の調査では、2GBのSDカードを使ったので、1クラスタ=64ブロック(セクタ)で話が進んでゆきます.




SDカード上のファイルの格納状態解析(その1)

知りた いのは、SDカード上にファイルがどのように格納されているのかで
すが、ちょろっとダンプしてみただけだとさっぱりわかりません.
追いかけ方があります. その追いかけ方全般がFAT16ファイルシステムで決められています.

以下では、windows7で2GBのSDカードをFAT16でformatした状態をダンプして解析する様子を説明します.
SDカードには1つだけbeer.txtというファイルを置いてあって、その中身は、下記文字列を書いてあります.
    sapporo
    kirin
    asahi
    suntory



最初に、ブロック(セクタ)0を読みます.512BYTEありますが、さしあたり知りたいのはその先頭のところだけです.
様々な文献ではブロック(セクタ)0にはMasterBootRecord (MBR) という別の情報が書かれていると記載されています.
しかしwindows7でformatしたわたしのSDカードでは、ブロック(セクタ)0にはBIOS Parameter Block (BPB)という情報が書かれています.
これはたぶん、boot deviceとしてformatしたわけじゃないのでMBRが書かれていないのだと推測します.

block 0x00000000
eb 3c 90 4d 53 44 4f 53 35 2e 30 00 02 40 06 00  | .<.MSDOS5.0..@..
02 00 02 00 00 f8 e9 00 3f 00 ff 00 00 00 00 00  | ........?.......
00 10 3a 00 80 00 29 0d b7 1b a0 4e 4f 20 4e 41  | ..:...).キ.NO NA
4d 45 20 20 20 20 46 41 54 31 36 20 20 20 33 c9  | ME    FAT16   3ノ


BPBの主要なパラメータ
+B-C
bytesPerSector
1ブロック(セクタ)のバイト数 0002→0200→512BYTE
+D
sectorsPerClaster
1クラスタのブロック(セクタ)数 0x40→64     ゆえに512x64=32kBクラスタである
+E-F
reservedSectors
systemが占有しているブロック(セクタ)サイズ 0600→0006→6block     ゆえにblock0006がFATの先頭である.
0600を0006と読み替えているのは、桁数の多い2進数をバイトアクセスなメモリに格納するために下位バイトから順に格納す るという決まりだからです.こういう並びをリトルエンディアンと呼称します.
+13-14
totalSectors ブロック(セクタ)の総数 0000の場合は、 後述のbigTotalSectorsがとって替わるようになって いる
+16-17
sectorsPerFAT
FATがSDカード上に占めるセクタ数 e900→00e9→233       ゆえに233x512=119296BYTE  FAT16ですから2BYTEで1クラスタの情報を管理しているのですから、このSDカード上のFATは119296/2=59648クラスタを管理して いることになります.1クラスタあたり32kBYTEですので、SDカードの容量=32kB x 59648=1.9GBとなり、だいたいSDカード容量とつじつまが合います.
+20-23
bigTotalSectors ブロック(セクタ)の総数 00103a00→003a1000→3805184   ゆえに3805184x512=1.9GBとなり、だいたいSDカード容量とつじつまが合います.

次に、reservedSectors を通り越した先のブロック6をみます.
そこにはFATテーブルがあります.

block 0x00000006
f8 ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................


FAT16という名前が示すとおり、先頭から16bit区切りにすると、次のような数字が見えます.
    f8ff->fff8
    ffff
    ffff
    0000

意味は下表だそうです.ただし、先頭のfff8とffffは無視して、本当にSDカードに記録されているデータについ て述べているのは3つ目以降だそうです.
未使用クラスタ 0x0000
予約クラスタ 0x0001
有効なユーザ・データ・クラスタ 0x0002 〜 0xffff6
不良クラスタ 0xfff7
最終クラスタ 0xfff8 〜 0xffff
し たがって、3番目のffffに着目すると、そこがファイルの先頭クラスタでかつ最終クラスタでもあるという意味になっています.

それで、ファイルの先頭クラスタはどこにあるのよ? という疑問が生じますが、それはBPBの情報から計算して求めます.
sectorsPerFATという情報がありました.233でした.
いまFATの先頭ブロック(セクタ)が6ですから、6+232=238ブロック(セクタ)までがFAT領域だと計算されます.
したがって、そのつぎ、ブロック239がファイルの先頭セクタだと推測されます.

ではブロック(セクタ)239=efを表示してみましょう.
ありゃ? 同じFATがまた出てきちゃった.
これはなんでかというと、メディアエラー防止のためにFATは2重書きされているからだそうです.

block 0x000000ef
f8 ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................


気をとりなおして計算し直します.
FATが2重化されているのですから、FAT領域の占有区間は、
ブロック(セクタ)6を先頭にして、
6+232+233=471ブロック(セクタ)までだと改めて計算し直します.

そして、FATの次のブロック(セクタ)である 472=1d8ブロックを表示してみましょう.
それっぽいのが出てきましたが、まだファイル本体ではないらしいです.
これはなんでしょうか?
Root Directory Entry(RDE)という情報だそうです.まだファイル本体ではありません.

RDEは32BYTE毎に1つのファイルについて表しています.下記では、何か意味のありそうな3つのファイルについて書かれているようにひとまず見えます.

block 0x000001d8
53 44 43 41 52 44 20 20 20 20 20 08 00 00 00 00  | SDCARD     .....
00 00 00 00 00 00 08 91 93 3f 00 00 00 00 00 00  | .........?......

42 45 45 52 20 20 20 20 54 58 54 20 18 3e 10 91  | BEER    TXT .>..
93 3f 93 3f 00 00 cc 90 93 3f 02 00 20 00 00 00  | .?.?..フ..?.. ...
e5 5a 5a 20 20 20 20 20 54 58 54 20 18 12 af 91  | .ZZ     TXT ..ッ.
93 3f 93 3f 00 00 ac 91 93 3f 03 00 16 03 00 00  | .?.?..ャ..?......
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................


それぞれの32BYTEの意味は、このようになっていて、だいぶおなじみの情報にたどり着きました.
検察官が改ざんしたのはここの情報なんですねw.


最初のエントリ
2番目のエントリ
3番目のエントリ
+0-7
00だったら、それ以降にはファイル情報が書かれてない.
E5だったら、それは削除されたファイルである.
2Eだったら、サブディレクトリに関係する.ここでは割愛する.
それ以外なら8文字のファイル名
SDCARD
BEER
先頭がE5なので消去済みの意味
+8-A
3文字の拡張子

TXT
TXT
+B
ファイル種別
bit5    作成変更時に1
bit4    directory flag
bit3    volume flag
bit2    hidden flag
bit1    system flag
bit0    read only flag
08→1000B

ゆえにボリューム名がSDCARD
20H→00100000B
bit5=1なので作成されたばっかりということか?

ゆえに、ファイル名がBEER.TXT
20H
+C
reserved
00
18H
18H
+D
作成mSec   (0-199mSec)
00
3EH→62
12H
+E-F
作成時間
0000
1091→9110H→1001000100010000B

bit 15 〜 11       時       10010B→18時
bit 10 〜  5       分       
001000B→8分
bit  4 〜  0       秒÷2   10000B→32分
AF91→91AFH
+10-11
作成日付
0000
933F→3F93H→0011111110010011B

bit 15 〜 9      年 (1980年をゼロ年とする)   
0011111B→31→2011年
bit  8 〜 5      月 (1 〜 12)     1100B→12月
bit  4 〜 0      日 (1 〜 31)     10011B→19日
933F→3F93H
+12-13
アクセス日付
0000
933F→3F93H 933F→3F93H
+14-15
FAT32でだけつかうのでFAT16では無視
0000
0000
0000
+16-17
変更時間
0891→9108H→37128
cc90→90ccH AC91→91ACH
+18-19
変更日付
933F→3F93H→16275
933f→3F93H 933F→3F93H
+1A-1B
開始クラスタ
0000
0200→0002 0300→0003
+1C-1F
ファイルサイズ 単位はBYTE
00000000
20000000→20H→32BYTE
16030000→00000316H→790BYTE

RDEの開始クラスタ情報から、BEER.TXTのクラスタ開始は2だと判りました.
でもクラスタ2ってどこですか?
やぶれかぶれ的にダンプしまくったら、それっぽいのがブロック(セクタ)504=1F8に見つかりました.
たしかに、ファイルサイズは32BYTEのようです.
でも、なんでブロック(セクタ)504なんだろ????

block 0x000001f8
73 61 70 70 6f 72 6f 0d 0a 6b 69 72 69 6e 0d 0a  | sapporo..kirin..
61 73 61 68 69 0d 0a 73 75 6e 74 6f 72 79 0d 0a  | asahi..suntory..
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................

たぶん、Root Directory Entry(RDE)の最高数が512個だという制約に関係すると思います.
つまり、ファイル数が512個までですということ.
RDEは1ファイルで32BYTEなので、512個だと、16384BYTE.
ゆえに、16384/512=32ブロックがRDEとして消費されます.
RDEの先頭はブロック472でしたから、RDEの末尾ブロックは472+31=503だと計算されます.

す・る・と、データが格納されている先頭ブロック(セクタ)は504=1F8と計算されます.
ちょうど、下記のファイルデータが見つかったブロック(セクタ)と同じ場所に当たりました.
この考え方で正しいんでしょう.きっと.

し・か・し、まだ問題が.どうしてクラスタ2がブロック(セクタ)504というデータクラスタの先頭を示すのか?
クラスタ0ならわかるけど.....  これ、調べたけど、なぜかクラスタ番号−2にするもののようです.



FAT16のファイル探索のまとめ(暫定版)

さて、ここまでで、紆余曲折を経て、短いファイルのあり場所までFAT16を探索することができました.

もういちど、FAT16のファイルシステムの中のファイルを探す手順を一覧にしてみます.

@ブロック(セクタ)とはSDカードをアクセスする最小単位のことで512BYTEです.

A
ブロック(セクタ)0を読みます.512BYTEを得ます.BIOS Parameter Block (BPB)

B+E〜Fの2BYTEからなる
reservedSectorsを切り出すと、6が書かれていた.
ブロック(セクタ)6がFATテーブルの先頭である.

C+16H〜17Hの2BYTEからなる
sectorsPerFATを表示すると、233になっていた.
6+233+233=472から、ブロック(セクタ)6〜471がFAT領域である.

Dブロック472を読みます.
ブロック472は、Root Directory Entry(RDE)の始まり
であって、32BYTE区切りでファイル名などの情報が入っている.
ファイル名が書かれた場所が判ったので、ファイル名で検索できるようになりました.
ファイル名のエントリは最大で512の領域が確保されているので、RDEは、472〜503ブロックまでを占有していると計算される.
よって、ファイル名探索のためには、472〜503ブロックまでを探索しなくてはいけない可能性があります.

ERDEの中から目的のファイル名BEER.TXTが見つかったら、その32BYTEの中の、
+1A〜1B番目の2BYTEを取り出す.
これは、開始クラスタ番号です.2になっていました.

ブロック503までがRDEだったので、504がデータクラスタの先頭です.
なんで2が先頭なのかは不明です.

FBEER.TXTを含むRDEの最後の4BYTEが、データサイズです.32BYTEという値が入っていました.

G
クラスタ番号2が目的のクラスタだとわかったので、ブロック504を読みます.
先頭から32BYTEが、得たいファイルの中身です.

H   Bで
ブロック6がFATテーブルの先頭だと判っています.
FATテーブルを見ると、次にどこのクラスタの内容を得ればファイルの続きのデータを得られるかが判ります.
ただし、このBEER.txtはたった32BYTEのファイルなので、最初のクラスタでおしまいになっていますので、FATテーブルのお世話にはならずに処理が終わります.



大きなファイルを記録したSDカードのFAT16の探索をやってみる

ルートディレクトリに、70kBの大きさのTEXTファイルを2ヶ置きました.beer.txtとbeer2.txtです.
このSDカードのFAT16を解析してみましょう.こんどはスラスラと読めることを期待します.

Aまずは、おなじみのブロック(セクタ)0のBPBを表示します.

block 0x00000000
eb 3c 90 4d 53 44 4f 53 35 2e 30 00 02 40 06 00  | .<.MSDOS5.0..@..
02 00 02 00 00 f8 e9 00 3f 00 ff 00 00 00 00 00  | ........?.......
00 10 3a 00 80 00 29 21 0e bd b0 4e 4f 20 4e 41  | ..:...)!.スーNO NA
4d 45 20 20 20 20 46 41 54 31 36 20 20 20 33 c9  | ME    FAT16   3ノ
8e d1 bc f0 7b 8e d9 b8 00 20 8e c0 fc bd 00 7c  | .?.{.?. .タ.ス.|


B+DのところにsectorsPerClaster=40H=64ブロックで1クラスタと書かれている.

C+E〜Fの2BYTEからなるreservedSectorsを切り出すと、6が書かれている.
ブロック(セクタ)6がFATテーブルの先頭である.

D+16H〜17Hの2BYTEからなるsectorsPerFATを表示すると、E9=233になっている.
6+233+233=472から、ブロック472を得る.
これは、FATがブロック(セクタ)471まで占有していて、その次のブロック(セクタ)472には別の情報が書かれていることを示しています.

Eブロック472を読みます.
ブロック472は、Root Directory Entry(RDE)の始まり
であって、32BYTE区切りでファイル名などの情報が入っている.
ファイル名が書かれた場所が判ったので、ファイル名で検索できるようになりました.
ファイル名のエントリは最大で512の領域が確保されているので、RDEは、472〜503ブロックまでを占有していると計算される.
よって、ファイル名探索のためには、472〜503ブロックまでを探索しなくてはいけない可能性があります.


block 0x000001d8
53 44 43 41 52 44 20 20 20 20 20 08 00 00 00 00  | SDCARD     .....
00 00 00 00 00 00 08 91 93 3f 00 00 00 00 00 00  | .........?......
42 45 45 52 20 20 20 20 54 58 54 20 18 3e 10 91  | BEER    TXT .>..
93 3f 93 3f 00 00 b5 ab 93 3f 02 00 c0 14 01 00  | .?.?..オォ.?..タ...
e5 5a 5a 20 20 20 20 20 54 58 54 20 18 12 af 91  | .ZZ     TXT ..ッ.
93 3f 93 3f 00 00 ac 91 93 3f 03 00 16 03 00 00  | .?.?..ャ..?......
42 45 45 52 32 20 20 20 54 58 54 20 18 59 73 36  | BEER2   TXT .Ys6
94 3f 94 3f 00 00 b5 ab 93 3f 05 00 c0 14 01 00  | .?.?..オォ.?..タ...
e5 66 00 54 00 65 00 73 00 74 00 0f 00 49 2e 00  | .f.T.e.s.t...I..
74 00 6d 00 70 00 00 00 ff ff 00 00 ff ff ff ff  | t.m.p...........
e5 52 00 65 00 61 00 64 00 79 00 0f 00 49 42 00  | .R.e.a.d.y...IB.
6f 00 6f 00 73 00 74 00 50 00 00 00 65 00 72 00  | o.o.s.t.P...e.r.
e5 45 41 44 59 42 7e 31 54 4d 50 20 00 c7 76 36  | .EADYB~1TMP .ヌv6
94 3f 94 3f 00 00 7a 36 94 3f 08 00 00 00 80 00  | .?.?..z6.?......
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................


FRDEの中から目的のファイル名BEER.TXTとBEER2.TXTが見つかりました.
その32BYTEの中の、
+1A〜1B番目の2BYTEを取り出す.
BEER.TXT   →   0200 → 0002 → 2
BEER2.TXT   →  0500 →  0005  →  5
これらは、開始クラスタ番号です.

ブロック(セクタ)503までがRDEだったので、504がデータクラスタの先頭です.
したがって、
BEER.TXT  →  ブロック(セクタ)504がデータの先頭
BEER2.TXT   →   ブロック(セクタ)507かというと、
クラスタサイズがあるのでちがうはずです.

Bの情報から
sectorsPerClaster=64ブロックで1クラスタってことになっているので、BEER.txtの先頭クラスタは、先頭ブロックが504であるのは合っているとしても、その範囲は、504+63=567ブロックまで広がっているはずです.
クラスタ番号とブロックのあり場所を一覧表にすると、こうなっていると予想されます.


開始ブロック(セクタ)
終了ブロック(セクタ)
クラスタ番号2
最初のクラスタ 504
567
クラスタ番号3 2番目のクラスタ
568
631
クラスタ番号4 3番目のクラスタ 632
698
クラスタ番号5 4番目のクラスタ 696
759
クラスタ番号6 5番目のクラスタ 760
823
クラスタ番号7 6番目のクラスタ 824
887

したがって、こう予想されます.
BEER.TXT  →  クラスタ2が先頭 → ブロック(セクタ)504=1F8Hがデータの先頭
BEER2.TXT   → クラスタ5が先頭  →  ブロック(セクタ)696=2B8Hがデータの先頭

予想される場所をダンプしてみました.結果はビンゴでした.ファイルの先頭が現れました.
これらのファイルは同じファイルをコピーしたものなので同じで良いのです.

block 0x000001f8
4f 6e 20 74 68 65 20 4f 72 69 67 69 6e 20 6f 66  | On the Origin of
20 47 72 61 76 69 74 79 0d 0a 61 6e 64 20 74 68  |  Gravity..and th
65 20 4c 61 77 73 20 6f 66 20 4e 65 77 74 6f 6e  | e Laws of Newton
0d 0a 45 72 69 6b 20 56 65 72 6c 69 6e 64 65 31  | ..Erik Verlinde1

block 0x000002b8
4f 6e 20 74 68 65 20 4f 72 69 67 69 6e 20 6f 66  | On the Origin of
20 47 72 61 76 69 74 79 0d 0a 61 6e 64 20 74 68  |  Gravity..and th
65 20 4c 61 77 73 20 6f 66 20 4e 65 77 74 6f 6e  | e Laws of Newton
0d 0a 45 72 69 6b 20 56 65 72 6c 69 6e 64 65 31  | ..Erik Verlinde1


G  Eで切り出したRDEの最後の4BYTEが、データサイズです.
BEER.TXT  →  c0140100  →
000114c0 → 70848BYTE
BEER2.TXT  →  c0140100  → 000114c0 → 70848BYTE
これらのファイルは同じファイルをコピーしたものなので、ファイルサイズは同じであってます.
また、windowsのファイルのプロパティで表示されるファイルサイズとピッタリあってます.

H   Cでブロック6がFATテーブルの先頭だと判っています.
FATテーブルを見ると、次にどこのクラスタの内容を得ればファイルの続きのデータを得られるかが判ります.
BEER.TXTは約70kBYTEなので、たぶん3つのクラスタにまたがって存在していると予想しているんですが、ただしいかどうか?

block 0x00000006
f8 ff ff ff 03 00 04 00 ff ff 06 00 07 00 ff ff  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................

先頭のf8ffffffは無視してその次から読むと、こういう意味だと推測されます.
0300  → 0003  → 3 → クラスタ2の次はクラスタ3だよ
0400  → 0004  → 4 → クラスタ3の次はクラスタ4だよ
ffff → そのファイルの最後のクラスタ → クラスタ4で最後だよ
0600  →  0006  → 6 →
クラスタ5の次はクラスタ6だよ
0700  →  0007  → 7 → クラスタ6の次はクラスタ7だよ
ffff  →  そのファイルの最後のクラスタ  →  クラスタ7で最後だよ

これらの情報から、ファイルの場所を総まとめすると、こうなるはずです.

BEER.TXTは、
ブロック(セクタ)504から始まり、クラスタ2とクラスタ3は全部消費してブロック(セクタ)631(=504+63+64)まで占有する.
そこから先は
ブロック(セクタ)632から始まる最終クラスタ4へ突入するが、途中で終わるはず.
途中で終わる終わり方は、70848−32768−32768=5312BYTEがクラスタ4を占有する.
5312−512x10=192 の計算から、最終クラスタ4の11ブロック(セクタ)がファイルの終わりと推測される.
つまり、最終ブロック(セクタ)は、632+10=642ブロック(セクタ)であるはずだ.
したがって、ブロック(セクタ)504〜642が、BEER.TXTの格納場所だと推測される.

果たして結果は如何に? ブロック(セクタ)642=282Hはまさにファイルの最終部分でした.
このブロックの文字は192文字であるはずなので、191=BFHで終わっているはずですが、どうでしょうか?
ただしく、BFHのところで終わっています.下記の赤い文字がそれです.

block 0x00000282
69 67 68 74 73 2c 22 0d 0a 61 72 58 69 76 3a 30  | ights,"..arXiv:0
39 31 31 2e 35 30 30 34 20 5b 67 72 2d 71 63 5d  | 911.5004 [gr-qc]
2c 20 61 6e 64 20 72 65 66 65 72 65 6e 63 65 73  | , and references
20 74 68 65 72 65 69 6e 2e 0d 0a 5b 31 35 5d 20  |  therein...[15]
4a 2e 20 44 2e 20 42 65 6b 65 6e 73 74 65 69 6e  | J. D. Bekenstein
2c 20 5c 41 20 55 6e 69 76 65 72 73 61 6c 20 55  | , \A Universal U
70 70 65 72 20 42 6f 75 6e 64 20 4f 6e 20 54 68  | pper Bound On Th
65 20 45 6e 74 72 6f 70 79 20 54 6f 20 45 6e 65  | e Entropy To Ene
72 67 79 20 52 61 74 69 6f 0d 0a 46 6f 72 20 42  | rgy Ratio..For B
6f 75 6e 64 65 64 20 53 79 73 74 65 6d 73 2c 22  | ounded Systems,"
20 50 68 79 73 2e 20 52 65 76 2e 20 44 20 32 33  |  Phys. Rev. D 23
20 28 31 39 38 31 29 20 32 38 37 2e 0d 0a 32 39  |  (1981) 287...29
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................


BEER2.TXTは、
ブロック(セクタ)696から始まり、クラスタ5とクラスタ6は全部消費してブロック(セクタ)823(=696+64+63)まで占有する.
そこから先は
ブロック(セクタ)824から始まる最終クラスタ7へ突入するが、途中で終わるはず.
途中で終わる終わり方は、70848−32768−32768=5312BYTEがクラスタ7を占有する.
5312−512x10=192 の計算から、最終クラスタ7の11ブロック(セクタ)がファイルの終わりと推測される.
つまり、最終ブロック(セクタ)は、824+10=834ブロック(セクタ)であるはずだ.
したがって、ブロック(セクタ)696〜834が、BEER2.TXTの格納場所だと推測される.

ブロック(セクタ)834=342Hを表示すると、ただしくファイルの最終部分がそこにありました.

block 0x00000342
69 67 68 74 73 2c 22 0d 0a 61 72 58 69 76 3a 30  | ights,"..arXiv:0
39 31 31 2e 35 30 30 34 20 5b 67 72 2d 71 63 5d  | 911.5004 [gr-qc]
2c 20 61 6e 64 20 72 65 66 65 72 65 6e 63 65 73  | , and references
20 74 68 65 72 65 69 6e 2e 0d 0a 5b 31 35 5d 20  |  therein...[15]
4a 2e 20 44 2e 20 42 65 6b 65 6e 73 74 65 69 6e  | J. D. Bekenstein
2c 20 5c 41 20 55 6e 69 76 65 72 73 61 6c 20 55  | , \A Universal U
70 70 65 72 20 42 6f 75 6e 64 20 4f 6e 20 54 68  | pper Bound On Th
65 20 45 6e 74 72 6f 70 79 20 54 6f 20 45 6e 65  | e Entropy To Ene
72 67 79 20 52 61 74 69 6f 0d 0a 46 6f 72 20 42  | rgy Ratio..For B
6f 75 6e 64 65 64 20 53 79 73 74 65 6d 73 2c 22  | ounded Systems,"
20 50 68 79 73 2e 20 52 65 76 2e 20 44 20 32 33  |  Phys. Rev. D 23
20 28 31 39 38 31 29 20 32 38 37 2e 0d 0a 32 39  |  (1981) 287...29
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ................



FAT16のファイル探索のまとめ(最終版)

@ブロック(セクタ)とはSDカードをアクセスする最小単位のことで512BYTEです.

A
ブロック(セクタ)0を読みます.512BYTEを得ます.BIOS Parameter Block (BPB)

B+DのところにsectorsPerClaster=64ブロックで1クラスタと書かれている.

C+E〜Fの2BYTEからなるreservedSectorsを切り出すと、6が書かれている.
ブロック(セクタ)6がFATテーブルの先頭である.

D+16H〜17Hの2BYTEからなるsectorsPerFATを表示すると、233になっている.
6+233+233=472から、ブロック472を得る.
これは、FATがブロック(セクタ)471まで占有していて、その次のブロック(セクタ)472には別の情報が書かれていることを示しています.

Eブロック472を読みます.
ブロック472は、Root Directory Entry(RDE)の始まり
であって、32BYTE区切りでファイル名などの情報が入っている.
ファイル名が書かれた場所が判ったので、ファイル名で検索できるようになりました.
ファイル名のエントリは最大で512の領域が確保されているので、RDEは、472〜503ブロックまでを占有していると計算される.(472+31=503)
よって、ファイル名探索のためには、472〜503ブロックまでを探索しなくてはいけない可能性があります.

FRDEの中から目的のファイル名BEER.TXTとBEER2.TXTが見つかったら、その32BYTEの中の、
+1A〜1B番目の2BYTEを取り出す.これは、開始クラスタ番号です.
BEER.TXT   →   0200 → 0002 → クラスタ番号2が先頭クラスタ
BEER2.TXT   →  0500 →  0005  →  クラスタ番号5が先頭クラスタ

G  Bで1クラスタが64ブロック(セクタ)であると判っています.
また、ブロック(セクタ)503までがRDEだったので、ブロック(セクタ)504がクラスタの先頭です.
したがって、データ領域の先頭付近のクラスタとブロック(セクタ)の対応表は芋づる式に下表のように決まります.
この表から、次のように判明します.
BEER.TXT   →   0200 → 0002 → クラスタ番号2が先頭クラスタ  → ブロック(セクタ)504が先頭
BEER2.TXT   →  0500 →  0005  →  クラスタ番号5が先頭クラスタ  → ブロック(セクタ)696が先頭


開始ブロック(セクタ)
終了ブロック(セクタ)
クラスタ番号2
最初のクラスタ504
567
クラスタ番号32番目のクラスタ
568
631
クラスタ番号43番目のクラスタ632
698
クラスタ番号54番目のクラスタ696
759
クラスタ番号65番目のクラスタ760
823
クラスタ番号76番目のクラスタ824
887

H   Fで切り出したRDEの最後の4BYTEが、データサイズです.
BEER.TXT  →  c0140100  → 000114c0 → 70848BYTE
BEER2.TXT  →  c0140100  → 000114c0 → 70848BYTE

I   Cでブロック6がFATテーブルの先頭だと判っています.
FATテーブルを見ると、次にどこのクラスタの内容を得ればファイルの続きのデータを得られるかが判ります.
FAT16なので2BYTE区切りで読みます.
先頭のf8ff+ffffは無視してその次から読むと、こういう意味だと推測されます.
0300  → 0003  → 3 → クラスタ2の次はクラスタ3だよ
0400  → 0004  → 4 → クラスタ3の次はクラスタ4だよ
ffff → そのファイルの最後のクラスタ → クラスタ4で最後だよ
0600  →  0006  → 6 → 
クラスタ5の次はクラスタ6だよ
0700  →  0007  → 7 → クラスタ6の次はクラスタ7だよ
ffff  →  そのファイルの最後のクラスタ  →  クラスタ7で最後だよ

J   Iの情報から、BEER.TXTとBEER2.TXTの格納場所を完全に推測すると、こうなります.
BEER.TXT
クラスタ2とクラスタ3は全部消費する.
クラスタ4の途中で終わる.
クラスタ4の終わり方は、70848−32768−32768=5312BYTEがクラスタ4を占有する.
5312−512x10=192 の計算から、クラスタ4の11ブロック(セクタ)がファイルの終わり(EOF)と推測される.
つまり、最終ブロック(セクタ)は、632+10=642ブロック(セクタ)であるはずだ.
642ブロック(セクタ)の文字は192文字のはずなので、191=BFHで終わっているはず.

BEER2.TXT
クラスタ5とクラスタ6は全部消費する.
クラスタ7の途中で終わる.
クラスタ7の終わり方は、70848−32768−32768=5312BYTEがクラスタ7を占有する.
5312−512x10=192 の計算から、クラスタ7の11ブロック(セクタ)がファイルの終わり(EOF)と推測される.
つまり、最終ブロック(セクタ)は、824+10=834ブロック(セクタ)であるはずだ.
642ブロック(セクタ)の文字は192文字のはずなので、191=BFHで終わっているはず.



開始ブロック(セクタ)
終了ブロック(セクタ)
BEER.TXT
クラスタ番号2
504
567
クラスタ番号3568
631
クラスタ番号4632
642のアドレス+BFHでEOF
BEER2.TXT
クラスタ番号5696
759
クラスタ番号6760
823
クラスタ番号7824
834のアドレス+BFHでEOF


inserted by FC2 system