扩展Int 13H调用规范
第一部分简介
一.硬盘结构简介
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弹出介质功能调用内部使用的。