close

MBR:

電腦業界規定都存放於硬碟的第零磁柱、第零磁頭、第一磁區,也就是最前面的磁區裏,這個磁區稱為主啟動記錄 ( 即 MBR,master boot record )。 在 MBR 裏除了分割表外,還有啟動程式。前面提過,每個磁區都佔 512 個位元組,MBR 磁區中的前 446 個位元組 ( 0~445 ) 用來存放啟動資料與程式,而接下來的 64 個位元組就是分割表,最後一個字組 ( 2 個位元組 ) 是 AA55H,作為識別之用。

分割表共有 64 個位元組,恰好可以描述四個分割區的性質 ( 即三個主要分割與一個擴充分割 ),所以每個分割用 16 個位元組來表示這個分割區的性質,說明如下:

偏移位址
大小(位元組) 名  稱 說  明
00H 1 啟動狀態 80H 表示可啟動  00H 表示不可啟動
01H 1 起始磁頭 00H 表示不可啟動
02H 2

起始磁柱
與起始磁區

起始磁區佔用 6 個位元,而起始磁柱佔用 10 個位元,分配情形是:
起始磁區:  這兩個位元組中,低位元組的 0~5 位元為起始磁區
起始磁柱:  這兩個位元組的高位元組為起始磁柱的 0~7 位元,
               這兩個位元組中,低位元組的 6~7 位元為起始磁柱的最高兩個位元(第8~9 位元 )
04H 1 檔案系統

06H,0EH:FAT16
0BH,0CH:FAT32
05H,0FH:扩充分割
07H:NTFS 或 OS/2 HPFS

05H 1 結束磁頭
06H 2

結束磁柱
與磁區

同起始磁柱與磁區
08H 4 分割區
相對位置
距離 MBR 的磁區數,亦即此分割開始的 LBA 磁區編號或隱藏磁區數
0CH 4 磁區數 該分割磁區總數

因為我是用在SD CARD,所以只需要用到分割區相對位置就可以找到boot sector的實際物理位置,而分割表也只需要用到一個分割表,不需要用到4個分割表。
實際上在sd card在windows上format時,是格式化成硬碟形式的檔案系統,所以會有MBR的配置,我以為是軟碟式的,這樣比較方便可以找到fat16第一個bootsector的位置。

MBR的格式:

啟動資料與程式
主要分割表
主要分割表
主要分割表
擴充分割表
AA55H(EOF)
446bytes 16bytes 16bytes 16bytes 16bytes 2bytes




FAT16:

FAT16格式
啟動磁區 保留磁區 FAT1 FAT2副本 根目錄區 資料區 不足一簇區




一個FAT檔案系統包括四個不同的部份。

  1. 保留磁區
    位於最開始的位置。第一個保留磁區是啟動磁區(分割啟動記錄)。它包括一個稱為基本輸入輸出參數塊(BPB)的區域(包括一些基本的檔案系統資訊尤其是它的型別和其它指向其它磁區的指標),通常包括作業系統的啟動呼叫程式碼。保留磁區的總數記錄在引導磁區中的一個參數中。引導磁區中的重要資訊可以被DOS和OS/2中稱為驅動器參數塊的作業系統結構存取。
  2. FAT區域
    它包含有兩份文件分配表,這是出於系統冗餘考慮,儘管它很少使用,即使是磁碟修復工具也很少使用它。它是分割資訊的對映表,指示叢集是如何儲存的。
  3. 根目錄區域
    它是在根目錄中儲存文件和目錄資訊的目錄表。在FAT32下它可以存在分割中的任何位置,但是在早期的版本中它永遠緊隨FAT區域之後。
  4. 資料區域:
    這是實際的文件和目錄資料儲存的區域,它佔據了分割的絕大部份。透過簡單地在FAT中添加文件鏈結的個數可以任意增加文 件大小和子目錄個數(只要有空叢集存在)。然而需要注意的是每個叢集只能被一個文件佔有,這樣的話如果在32KB大小的叢集中有一個1KB大小的文件,那 麼31KB的空間就浪費掉了。
  5. 不足一磁叢:
    在format時可能會產生這個區域,假如format時選擇一簇大小為32kB,在SD卡為2G的是時候,會產生出28KB不滿足32KB的情形,這28KB就是這個區域,在WINHEX看是顯示出volume slack,這是浪費的區域。

 圖1:

 2011-05-01 21 23 44.png       


啟動磁區與基本輸入輸出參數塊BPB:

圖2:

名稱 位址範圍 位元組大小  
BS_jmpBoot 00-02 3 跳躍指令
BS_OEMName 03-0A 8 廠商軟體名。這是格式化此分割區的作業系統所填入的廠商名稱。如果用 Win 2000 格式化,此欄填入『MSDOS 5.0』。
BPB_BytsPerSec 0B-0C 2 每一磁區的位元組數。一般為 512 個位元組,但也可以是 1024, 2048 或 4096 數值,不過微軟不建議使用除了 512 以外的數。
BPB_SecPerCluster 0D 1 每一磁叢所佔磁區數。但是要注意不能使每磁叢所含位元組數大於 65536,亦即 BPB_SecPerClu 乘以 BPB_BytsPerSec 不能大於 65536。因此,當 BPB_BytsPerSec 等於 512 時,BPB_SecPerClu 可以是 1、2、4、8、16、32、64、128 等數值。
BPB_RsvdSecCnt 0E-0F 2 保留磁區數
BPB_NumFATs 10 1 FAT 份數。不管是 FAT12、FAT16、FAT32 都有兩份檔案配置表 ( FAT )。
BPB_RootEntCnt  11-12 2 根目錄所含 FDB 數。即根目錄裏可以存放的檔案名稱及子目錄名稱總和之FAT12/16不能超過 BPB_RootEntCnt;但是對 FAt32 而言,此欄位不用,填上 0。
BPB_TotSec16 13-14 2 邏輯磁區總數,若為零表示此硬碟大於 32MB,而在位址 20-23 記錄真正的邏輯磁區總數。但最多只能表示 0FFFFH,所以若一個磁碟的邏輯磁區大於 0FFFFH ( 或是說磁碟容量大於 32MB,32MB 是 10000H*512D 來的 ),則此欄位為 0,邏輯磁區總數記錄在 20H 處開始的雙字組。因為 FAT32 分割必定大於 32MB,故此欄位不使用,均填入 0。
BPB_Media 15 1 磁碟種類。 0F8H:硬碟
BPB_FATSz16 16-17 2 每份 FAT 所佔磁區數。但對 FAT32 而言,此欄位不用,填上 0,而每份 FAT 所佔磁區數記載於位址 24H~27H 處的雙字組。
BPB_SecPerTrk 18-19 2 每一磁軌之磁區數
BPB_NumHeads 1A-1B 2 磁頭數
BPB_HiddSec 1C-1F 4 隱藏磁區數。表示隱藏磁區數,與分割表或擴充分割表中的分割區相對位置的數值一樣
BPB_TotSec32 20-23 4 邏輯磁區總數。如果 16H~17H 欄為 0,則此欄不可為零。
BS_DrvNum 24 1 磁碟機編號
BS_Reserved1 25 1 保留
BS_BootSig 26 1 特徵碼
BS_VolID 27-2A 4 磁碟序號
BS_VolLab 2B-35 11 磁碟標籤 ( 磁碟卷名 )
BS_FilSysType 36-3D 8 字串『FAT16   』

3E-1FD
 

1FE-1FF 2  0x55aa

2011-05-01 21 29 29.png  

BPB_BytsPerSec(每一磁區的位元組數):
value=0x0200=512B,上面winhex顯示的是little endian格式。
 

BPB_SecPerCluster(每一磁叢所佔磁區數):
value= 0x40=64, 1 cluster = 64 sectors
 

BPB_RsvdSecCnt(保留磁區):
value = 0x0008,有8個保留磁區含啟動磁區。
 

BPB_NumFATs(FAT 份數):
value = 0x02,有兩份fat表。
 

BPB_RootEntCnt(根目錄所含 FDB 數):
value = 0x0200=512,可存放512個子目錄或檔案。一個FDB數為32B,所以總大小為32*512。
而1 sector = 512B。根目錄所佔sector為(32*512)/512=32sectors
 

BPB_TotSec16(邏輯磁區總數):
value=0
 

BPB_FATSz16(每份 FAT 所佔磁區數):
value= 0x00F0=240,每fat佔240個磁區
 

BPB_HiddSec(隱藏磁區數):
value=0x000000FF=255,隱藏255個磁區
 

BPB_TotSec32(邏輯磁區總數):
value=0x3BD300=3920640,總共有3920640個磁區

這些是比較重要的參數。

從圖1可以看到各區域對應到的sector(磁區)。

boot sector(啟動磁區):
在第0磁區這是固定的。

fat1:
在第8磁區=boot sector(第0磁區)+保留磁區(8)。

fat2:
在第248磁區=fat1(第8磁區)+每份fat所佔磁區數(240)。

root directry(根目錄區):
在第488磁區 = fat2(第248磁區)+每份fat所佔磁區數(240)。

free space(資料區):
在第520磁區 = 根目錄區(第488磁區) + 32磁區(sectors)(根目錄所佔磁區數)。

volume slack (不足一簇的區域):
因為選擇32kB為一磁叢,這裡只剩下28kB不滿一簇,所以產生這個區域,造成浪費空間,佔56磁區(sectors)。

如何判斷為fat12,fat16,fat32?
當磁叢數小於 4085 時為 FAT12;大於或等於 4085 且小於 65525 時為 FAT16;大於或等於 65525 為 FAT32。

資料區(第520磁區)=啟動磁區,fat1,fat2,根目錄區的總和。
value slack = (3920640(總磁區數)-520(資料區))/64 餘數為56磁區。
總可用磁區數=總磁區數3920640-不足一簇磁區56=3920584
總磁叢數=(總磁區數-資料區-不足一磁叢區)/每一磁叢所佔磁區數=(3920640-520-56)/64=61251
所以總磁叢數=61251<65525,為fat16。


FAT區:

圖2:

2011-05-01 23 54 07.png  

     位址

1000-1001     磁叢0    FFF8     系統保留磁叢
1002-1003     磁叢1    FFFF     系統保留磁叢   
1004-1005     磁叢2    0003    指向第三個磁叢
1006-1007     磁叢3    0004    指向第四個磁叢
1008-1009     磁叢4    0005    指向第五個磁叢
100A-100B     磁叢5    FFFF     表示磁叢結束
100C-100D     磁叢6   FFFF      表示磁叢結束
100E-100F     磁叢7    FFFF      表示磁叢結束
1010-1011     磁叢8    FFFF      表示磁叢結束
1012-1013     磁叢9    FFFF      表示磁叢結束
1014-1015    磁叢10   FFFF      表示磁叢結束

FAT表的含意:

表1 FAT的取值含意(16进制)
FAT12 FAT16 FAT32 對應磁叢的表現情況
000 0000 00000000 未分配的磁叢 
002~FFF 0002~FFEF 00000002~FFFFFFEF 已分配的磁叢
FF0~FF6 FFF0~FFF6 FFFFFFF0~FFFFFFF6 系統保留
FF7 FFF7 FFFFFFF7 壞掉磁叢 
FF8~FFF FFF8~FFFF FFFFFFF8~FFFFFFFF 文件结束磁叢


FDT:在根目錄下,為32Byte

表2:

位元組偏移      長度 描述
0x00 8 DOS檔名(附加空格)

第一個位元組可以是下面的特殊數值:

0x00 這個條目有用並且後面沒有被佔用條目
0x05 最初字元確實是0xE5
0x2E '點'條目;'.'或者'..'
0xE5 這個條目曾經被刪除不再有用。取消刪除文件工具作為取消刪除的一步必須使用一個正常的字元取代它。
0x08 3 DOS副檔名(空格補齊)
0x0b 1 文件內容

第一個位元組可以是下面一些特殊值:

掩碼 描述
0 0x01 唯讀
1 0x02 隱藏
2 0x04 系統
3 0x08 卷標
4 0x10 子目錄
5 0x20 檔案
6 0x40 裝置(內部使用,磁碟上看不到)
7 0x80 沒有使用

內容值0x0F用來表示長檔名條目。

0x0c 1 保留,NT使用(參見後面)
0x0d 1 建立時間,最小時間解析度:10ms單位,數值從0到199。
0x0e 2 建立時間。小時、分鐘和秒根據後面的圖示描述進行編碼:
描述
15-11 小時(0-23)
10-5 分鐘(0-59)
4-0 秒/2(0-29)

注意只保存了2秒的解析度。更細解析度的文件建立時間在偏移0x0d處。

0x10 2 建立日期。年、月和日根據後面的圖示編碼:
描述
15-9 年(0 = 1980, 127 = 2107)
8-5 月(1 = 1月,12 = 12月)
4-0 日(1 - 31)
0x12 2 最近存取時間;參見偏移0x0e處的描述。
0x14 2 FAT12和FAT16中的EA-Index(OS/2和NT使用),FAT32中第一個叢集的兩個高位元組
0x16 2 最後更改時間;參見偏移0x0e處的描述。
0x18 2 最後更改日期; 參見偏移0x10處的描述。
0x1a 2 FAT12和FAT16中的第一個叢集。FAT32中第一個叢集的兩個低位元組。
0x1c 4

文件大小

圖3:

2011-05-01 23 56 12.png  

    位址

3D0C0-3D0C7       檔名(不滿足8byte,用空隔補滿)                WER
3D0C8-3D0CA       副檔名                                                  TXT
3D0CB                   20h(表示建立是檔案)10h(建立是子目錄)
3D0CE-3D0CF       建立時間    0xBDAF
3D0D0-3D0D1       建立日期    0x3EA1
3D0D2-3D0D3       最近存取時間  0x3EA1
3D0D6-3D0D7       最後更改時間  0xBDB4
3D0D8-3D0D9       最後更改日期  0x3EA1
3D0DA-3D0DB       FAT16第一個磁叢 0x000A
3D0DC-3D0DF       檔案大小
3D080-3D0CF        為長檔名部分

圖2:

2011-05-01 23 54 07.png

圖3可以看到有兩個檔案一個資料夾,檔案名為wer.txt與ex.pps,資料夾為SDJ。

WER.TXT檔案,位址3D0DA-3D0DB為0x0A表示wer.txt存放在第10磁叢的位址,位址3D0CB為0x20表示為檔案。
資料磁區是從520磁區(第2磁叢,第0,1磁叢為系統保留磁叢)開始,第10磁叢是在520+(10-2)*64=1032磁區的位址上,看到圖2 fat表的第10磁叢的位址(1014-1015)為FFFF,表示此磁叢是最後一個磁叢(結束磁叢)。

EX.PPS檔案,位址3D01A-3D01B為0x02表示ex.pps存放在第2磁叢的位址,位址3D00B為0x20表示為檔案。
第2磁叢是在520+(2-2)*64=520磁區的位址上,也就是在資料磁區開始的地方,看到圖2 fat表的第2磁叢,位址1003-1004為0x0003,表示此檔案大於一個磁叢的大小,指向磁叢3是在520+(3-2)*64=584磁區的位址上,fat表第3磁叢指向第4磁叢,第4磁叢指向第5磁叢,第5磁叢為FFFF,表示此磁叢為最後一個磁叢。此檔案佔4個磁叢的大小,實際檔案大小為117KB/32KB(一個磁叢大小)=3.21,還剩下21KB佔第4磁叢。

SDJ資料夾,位址3D07A-3D07B為0x0006表示sdj存放在第6磁叢的位址,位址3D06B為0x10表示為子目錄。
第6磁叢是在520+(6-2)*64=776磁區的位址上。

SDJ的內容:

2011-05-02 02 07 03.png  

在子目錄內都會有兩個子目錄項.(本目錄)和..(上一層目錄),也會記錄本目錄(6101A)與上一層目錄(6103A)是在第幾個磁叢,上一層目錄(6103A)如果是根目錄的話記錄開始磁叢為0,實際是在第2磁叢。

在SDJ資料夾內有一個DFSH.TXT與SDE的資料夾,DFSH.TXT開始第7磁叢(位址6109A=0x0007),SDE資料夾開始在第8磁叢(位址610FA=0x0008),都只佔一個磁叢。

SDE資料夾內容:

2011-05-02 02 23 42.png  

在SDE資料夾裡,一樣有.(本目錄)和..(上一層目錄)這兩個子目錄項,記錄了本目錄是在第8磁叢,上一層目錄是在第6磁叢。

在SDE資料夾裡有一個SDFHJE.TXT的檔案,是在第9磁叢開始存放,只放一個磁叢。

長檔名:

位址 長度
(位元組)
意  義
0 1 長檔名形式的 FDB 順序,一個具有長檔名的檔案很可能擁有數個長檔名形式的 FDB,這些 FDB 由短檔名形式的 FDB 開始向低位址排列,而這個位元組就表示其順序,由 1 開始,最多到 20,但是如果是最後一個 FDB,則須加上 40H。
1~0AH 0AH 長檔名,此部份可以存 5 個萬國碼字元
0BH 1 長檔名形式 FDB 屬性,必為 0FH,檢查此位元組,若為 0FH,表示此 FDB 為長檔名形式的 FDB
0CH 1 保留,必為 00H
0DH 1 查核碼
0EH~19H 0CH 長檔名,此部份可以存 6 個萬國碼字元
1AH~1BH 2 保留,必為 00H
1CH~1FH 4 長檔名,此部份可以存 2 個萬國碼字元

35個W的長檔名檔案:

2011-05-02 02 50 46.png  

在棕色藍色橘色為長檔名部分(是由高位址往低位址長),黃色為短檔名部分

查核碼:是由短檔名11的BYTE所組成,規則為

1.The ASCII value of the first character is the base sum.
2.Rotate the sum bitwise one bit to the right.  rotate是循環右移
3.Add the ASCII value of the next character to the sum.
4.Repeat step 2 and 3 until all 11 characters has been added.

int i; unsigned char sum = 0;

for (i = 0; i < 11; i++)
{
      sum = (sum >> 1) + ((sum & 1) << 7); /* rotate */
      sum += name[i]; /* add next name byte */
}




轉載於:
http://home.educities.edu.tw/wanker742126/index.html
http://www.maverick-os.dk/FileSystemFormats/VFAT_LongFileNames.html
http://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html
http://zh.wikipedia.org/wiki/FAT
http://technet.microsoft.com/en-us/library/cc776720%28WS.10%29.aspx

arrow
arrow
    全站熱搜

    部落格 發表在 痞客邦 留言(0) 人氣()