第一部分簡介
一.硬盤結構簡介
1.硬盤參數釋疑
到目前為止,人們常說的硬盤參數還是古老的CHS(Cylinder/Head/Sector)參數。那麼為什麼要使用這些參數,它們的意義是什麼?它們的取值范圍是什麼?
很久以前(longlongago...),硬盤的容量還非常小的時候,人們采用與軟盤類似的結構生產硬盤。也就是硬盤盤片的每一條磁道都具有相同的扇區數。由此產生了所謂的3D參數(DiskGeometry)。即磁頭數(Heads),柱面數(Cylinders),扇區數(Sectors),以及相應的尋址方式。
其中:
磁頭數(Heads)表示硬盤總共有幾個磁頭,也就是有幾面盤片,最大為255(用8個二進制位存儲);
柱面數(Cylinders)表示硬盤每一面盤片上有幾條磁道,最大為1023(用10個二進制位存儲);
扇區數(Sectors)表示每一條磁道上有幾個扇區,最大為63(用6個二進制位存儲)。
每個扇區一般是512個字節,理論上講這不是必須的,但好象沒有取別的值的。
所以磁盤最大容量為:
255*1023*63*512/1048576=8024GB(1M=1048576Bytes)或硬盤廠商常用的單位:
255*1023*63*512/1000000=8414GB(1M=1000000Bytes)
在CHS尋址方式中,磁頭,柱面,扇區的取值范圍分別為0到Heads-1,0到Cylinders-1,1到Sectors(注意是從1開始)。
2.基本Int13H調用簡介
BIOSInt13H調用是BIOS提供的磁盤基本輸入輸出中斷調用,它可以完成磁盤(包括硬盤和軟盤)的復位,讀寫,校驗,定位,診斷,格式化等功能。它使用的就是CHS尋址方式,因此最大識能訪問8GB左右的硬盤(本文中如不作特殊說明,均以1M=1048576字節為單位)。
3.現代硬盤結構簡介
在老式硬盤中,由於每個磁道的扇區數相等,所以外道的記錄密度要遠低於內道,因此會浪費很多磁盤空間(與軟盤一樣)。為了解決這一問題,進一步提高硬盤容量,人們改用等密度結構生產硬盤。也就是說,外圈磁道的扇區比內圈磁道多。采用這種結構後,硬盤不再具有實際的3D參數,尋址方式也改為線性尋址,即以扇區為單位進行尋址。
為了與使用3D尋址的老軟件兼容(如使用BIOSInt13H接口的軟件),在硬盤控制器內部安裝了一個地址翻譯器,由它負責將老式3D參數翻譯成新的線性參數。這也是為什麼現在硬盤的3D參數可以有多種選擇的原因(不同的工作模式,對應不同的3D參數,如LBA,LARGE,NORMAL)。
4.擴展Int13H簡介
雖然現代硬盤都已經采用了線性尋址,但是由於基本Int13H的制約,使用BIOSInt13H接口的程序,如DOS等還只能訪問8G以內的硬盤空間。為了打破這一限制,Microsoft等幾家公司制定了擴展Int13H標准(ExtendedInt13H),采用線性尋址方式存取硬盤,所以突破了8G的限制,而且還加入了對可拆卸介質(如活動硬盤)的支持。
二.BootSector結構簡介
1.BootSector的組成
BootSector也就是硬盤的第一個扇區,它由MBR(MasterBootRecord),DPT(DiskPartitionTable)和BootRecordID三部分組成。
MBR又稱作主引導記錄占用BootSector的前446個字節(0to0x1BD),存放系統主引導程序(它負責從活動分區中裝載並運行系統引導程序)。
DPT即主分區表占用64個字節(0x1BEto0x1FD),記錄了磁盤的基本分區信息。主分區表分為四個分區項,每項16字節,分別記錄了每個主分區的信息(因此最多可以有四個主分區)。
BootRecordID即引導區標記占用兩個字節(0x1FEand0x1FF),對於合法引導區,它等於0xAA55,這是判別引導區是否合法的標志。
BootSector的具體結構如下圖所示:
Offset0000H
Offset01BDH
Offset01BEH
Offset01CDH
Offset01CEH
Offset01DDH
Offset01DEH
Offset01EDH
Offset01EEH
Offset01FDH
Offset01FEH
Offset01FFH
MasterBootRecord
主引導記錄(446字節)
分區信息1
分區信息2
分區信息3
分區信息4
校驗字0xAA55
2.分區表結構簡介
分區表由四個分區項構成,每一項的結構如下:
BYTEState :分區狀態,0=未激活,0x80=激活(注意此項)
BYTEStartHead :分區起始磁頭號
WORDStartSC :分區起始扇區和柱面號,底字節的低6位為扇區號,高2位為柱面號的第9,10位,高字節為柱面號的低8位
BYTEType :分區類型,如0x0B=FAT32,0x83=Linux等,00表示此項未用(注1)
BYTEEndHead :分區結束磁頭號
WORDEndSC :分區結束扇區和柱面號,定義同前
DWORDRelative :在線性尋址方式下的分區相對扇區地址(對於基本分區即為絕對地址)
DWORDSectors :分區大小(總扇區數)
注意:在DOS/Windows系統下,基本分區必須以柱面為單位劃分(Sectors*Heads個扇區),如對於CHS為764/255/63的硬盤,分區的最小尺寸為255*63*512/1048576=7.844MB。
3.擴展分區簡介
由於主分區表中只能分四個分區,無法滿足需求,因此設計了一種擴展分區格式。基本上說,擴展分區的信息是以鏈表形式存放的,但也有一些特別的地方。
首先,主分區表中要有一個基本擴展分區項,所有擴展分區都隸屬於它,也就是說其他所有擴展分區的空間都必須包括在這個基本擴展分區中。對於DOS/Windows來說,擴展分區的類型為0x05。
除基本擴展分區以外的其他所有擴展分區則以鏈表的形式級聯存放,後一個擴展分區的數據項記錄在前一個擴展分區的分區表中,但兩個擴展分區的空間並不重疊。
擴展分區類似於一個完整的硬盤,必須進一步分區才能使用。但每個擴展分區中只能存在一個其他分區。此分區在DOS/Windows環境中即為邏輯盤。因此每一個擴展分區的分區表(同樣存儲在擴展分區的第一個扇區中)中最多只能有兩個分區數據項(包括下一個擴展分區的數據項)。
擴展分區和邏輯盤關系請參考注1。
第二部分技術資料
第一章擴展Int13H技術資料
一.簡介
設計擴展Int13H接口的目的是為了擴展BIOS的功能,使其支持多於1024柱面的硬盤,以及可移動介質的鎖定,解鎖及彈出等功能。
二.數據結構
1.數據類型約定
BYTE 1字節整型( 8位)
WORD 2字節整型(16位)
DWORD4字節整型(32位)
QWORD8字節整型(64位)
2.磁盤地址數據包DiskAddressPacket(DAP)
DAP是基於絕對扇區地址的,因此利用DAP,Int13H可以輕松地逾越1024柱面的限制,因為它根本就不需要CHS的概念。
DAP的結構如下:
structDiskAddressPacket
{
BYTEPacketSize; //數據包尺寸(16字節)
BYTEReserved; //==0
WORDBlockCount; //要傳輸的數據塊個數(以扇區為單位)
DWORDBufferAddr; //傳輸緩沖地址(segment:offset)
QWORDBlockNum; //磁盤起始絕對塊地址
};
PacketSize保存了DAP結構的尺寸,以便將來對其進行擴充。在目前使用的擴展Int13H版本中PacketSize恆等於16。如果它小於16,擴展Int13H將返回錯誤碼(AH=01,CF=1)。
BlockCount對於輸入來說是需要傳輸的數據塊總數,對於輸出來說是實際傳輸的數據塊個數。BlockCount=0表示不傳輸任何數據塊。
BufferAddr是傳輸數據緩沖區的32位地址(段地址:偏移量)。數據緩沖區必須位於常規內存以內(1M)。
BlockNum表示的是從磁盤開始算起的絕對塊地址(以扇區為單位),與分區無關。第一個塊地址為0。一般來說,BlockNum與CHS地址的關系是:
BlockNum=(cylinder*NumberOfHeads+head)*SectorsPerTrack+sector-1;
其中cylinder,head,sector是CHS地址,NumberOfHeads是磁盤的磁頭數,SectorsPerTrack是磁盤每磁道的扇區數。
也就是說BlockNum是沿著扇區->磁道->柱面的順序記數的。這一順序是由磁盤控制器虛擬的,磁盤表面數據塊的實際排列順序可能與此不同(如為了提高磁盤速度而設置的間隔因子將會打亂扇區的排列順序)。
3.驅動器參數數據包DriveParametersPacket
驅動器參數數據包是在擴展Int13H的取得驅動器參數子功能調用中使用的數據包。格式如下:
structDriveParametersPacket
{
WORDInfoSize; //數據包尺寸(26字節)
WORDFlags; //信息標志
DWORDCylinders; //磁盤柱面數
DWORDHeads; //磁盤磁頭數
DWORDSectorsPerTrack; //每磁道扇區數
QWORDSectors; //磁盤總扇區數
WORDSectorSize; //扇區尺寸(以字節為單位)
};
信息標志用於返回磁盤的附加信息,每一位的定義如下:
0位:
0=可能發生DMA邊界錯誤
1=DMA邊界錯誤將被透明處理
如果這位置1,表示BIOS將自動處理DMA邊界錯誤,也就是說錯誤代碼09H永遠也不會出現.
1位:
0=未提供CHS信息
1=CHS信息合法
如果塊設備的傳統CHS幾何信息不適當的話,該位將置0.
2位:
0=驅動器不可移動
1=驅動器可移動
3位:表示該驅動器是否支持寫入時校驗.
4位:
0=驅動器不具備介質更換檢測線
1=驅動器具備介質更換檢測線
5位:
0=驅動器不可鎖定
1=驅動器可以鎖定
要存取驅動器號大於0x80的可移動驅動器,該位必須置1(某些驅動器號為0到0x7F的設備也需要置位)
6位:
0=CHS值是當前存儲介質的值(僅對於可移動介質),如果驅動器中有存儲介質,CHS值將被返回.
1=CHS值是驅動器支持的最大值(此時驅動器中沒有介質).
7-15位:保留,必須置0.
三.接口規范
1.寄存器約定
在擴展Int13H調用中一般使用如下寄存器約定:
ds:si==>磁盤地址數據包(diskaddresspacket)
dl==>驅動器號
ah==>功能代碼/返回碼
在基本Int13H調用中,0-0x7F之間的驅動器號代表可移動驅動器0x80-0xFF之間的驅動器號代表固定驅動器。但在擴展Int13H調用中0x80-0xFF之間還包括一些新出現的可移動驅動器,比如活動硬盤等。這些驅動器支持先進的鎖定,解鎖等功能。
ah返回的錯誤碼除了標准Int13H調用規定的基本錯誤碼以外,又增加了以下錯誤碼:
B0h驅動器中的介質未被鎖定
B1h驅動器中的介質已經鎖定
B2h介質是可移動的
B3h介質正在被使用
B4h鎖定記數溢出
B5h合法的彈出請求失敗
2.API子集介紹
1.x版的擴展Int13H調用中規定了兩個主要的API子集。
第一個子集提供了訪問大硬盤所必須的功能,包括檢查擴展In13H是否存在(41h),擴展讀(42h),擴展寫(43h),校驗扇區(44h),擴展定位(47h)和取得驅動器參數(48h)。
第二個子集提供了對軟件控制驅動器鎖定和彈出的支持,包括檢查擴展Int13H是否存在(41h),鎖定/解鎖驅動器(45h),彈出驅動器(46h),取得驅動器參數(48h),取得擴展驅動器改變狀態(49h),int15h。
如果使用了調用規范中不支持的功能,BIOS將返回錯誤碼ah=01h,CF=1。
3.API詳解
1)檢驗擴展功能是否存在
入口:
AH=41h
BX=55AAh
DL=驅動器號
返回:
CF=0
AH=擴展功能的主版本號
AL=內部使用
BX=AA55h
CX=API子集支持位圖
CF=1
AH=錯誤碼01h,無效命令
這個調用檢驗對特定的驅動器是否存在擴展功能。如果進位標志置1則此驅動器不支持擴展功能。如果進位標志為0,同時BX=AA55h,則存在擴展功能。此時CX的0位表示是否支持第一個子集,1位表示是否支持第二個子集.
對於1.x版的擴展Int13H來說,主版本號AH=1。AL是副版本號,但這僅限於BIOS內部使用,任何軟件不得檢查AL的值。
2)擴展讀
入口:
AH=42h
DL=驅動器號
DS:DI=磁盤地址數據包(DiskAddressPacket)
返回:
CF=0,AH=0成功
CF=1,AH=錯誤碼
這個調用將磁盤上的數據讀入內存。如果出現錯誤,DAP的BlockCount項中則記錄了出錯前實際讀取的數據塊個數。
3)擴展寫
入口:
AH=43h
AL
0位=0關閉寫校驗
1打開寫校驗
1-7位保留,置0
DL=驅動器號
DS:DI=磁盤地址數據包(DAP)
返回:
CF=0,AH=0成功
CF=1,AH=錯誤碼
這個調用將內存中的數據寫入磁盤。如果打開了寫校驗選項,但BIOS不支持,則會返回錯誤碼AH=01h,CF=1。功能48h可以檢測BIOS是否支持寫校驗。
如果出現錯誤,DAP的BlockCount項中則記錄了出錯前實際寫入的數據塊個數。
4)校驗扇區
入口:
AH=44h
DL=驅動器號
DS:DI=磁盤地址數據包(DiskAddressPacket)
返回:
CF=0,AH=0成功
CF=1,AH=錯誤碼
這個調用校驗磁盤數據,但並不將數據讀入內存.如果出現錯誤,DAP的BlockCount項中則記錄了出錯前實際校驗的數據塊個數。
5)鎖定/解鎖驅動器
入口:
AH=45h
AL
=0鎖定驅動器
=1驅動器解鎖
=02返回鎖定/解鎖狀態
=03h-FFh-保留
DL=驅動器號
返回:
CF=0,AH=0成功
CF=1,AH=錯誤碼
這個調用用來縮定指定驅動器中的介質.
所有標號大於等於0x80的可移動驅動器必須支持這個功能。如果在支持可移動驅動器控制功能子集的固定驅動器上使用這個功能調用,將會成功返回。
驅動器必須支持最大255次鎖定,在所有鎖定被解鎖之前,不能在物理上將驅動器解鎖。解鎖一個未鎖定的驅動器,將返回錯誤碼AH=B0h。如果鎖定一個已鎖定了255次的驅動器,將返回錯誤碼AH=B4h。
鎖定一個沒有介質的驅動器是合法的。
6)彈出可移動驅動器中的介質
入口:
AH=46h
AL=0保留
DL=驅動器號
返回:
CF=0,AH=0成功
CF=1,AH=錯誤碼
這個調用用來彈出指定的可移動驅動器中的介質.
所有標號大於等於0x80的可移動驅動器必須支持這個功能。如果在支持可移動驅動器控制功能子集的固定驅動器上使用這個功能調用,將會返回錯誤碼AH=B2h(介質不可移動)。如果試圖彈出一個被鎖定的介質將返回錯誤碼AH=B1h(介質被鎖定)。
如果試圖彈出一個沒有介質的驅動器,則返回錯誤碼Ah=31h(驅動器中沒有介質)。
如果試圖彈出一個未鎖定的可移動驅動器中的介質,Int13h會調用Int15h(AH=52h)來檢查彈出請求能否執行。如果彈出請求被拒絕則返回錯誤碼(同Int15h)。如果彈出請求被接受,但出現了其他錯誤,則返回錯誤碼AH=B5h。
7)擴展定位
入口:
AH=47h
DL=驅動器號
DS:DI=磁盤地址數據包(DiskAddressPacket)
返回:
CF=0,AH=0成功
CF=1,AH=錯誤碼
這個調用將磁頭定位到指定扇區。
8)取得驅動器參數
入口:
AH=48h
DL=驅動器號
DS:DI=返回數據緩沖區地址
返回:
CF=0,AH=0成功
CF=1,AH=錯誤碼
這個調用返回指定驅動器的參數。
9)取得擴展驅動器介質更換檢測線狀態
入口:
AH=49h
DL=驅動器號
返回:
CF=0,AH=0介質未更換
CF=1,AH=06h介質可能已更換
這個調用返回指定驅動器的介質更換狀態.
這個調用與Int13hAH=16h子功能調用相同,只是允許任何驅動器標號。如果對一台支持可移動介質功能子集的固定驅動器使用此功能,則永遠返回CF=0,AH=0。
簡單地將可移動介質鎖定再解鎖就可以激活檢測線,而無須真正更換介質。
10)Int15h可移動介質彈出支持
入口:
AH=52h
DL=驅動器號
返回:
CF=0,AH=0彈出請求可能可以執行
CF=1,AH=錯誤碼B1h或B3h彈出請求不能執行
這個調用是由Int13hAH=46h彈出介質功能調用內部使用的。