扩展 Int13H 技术资料
一、简介
设计扩展 Int13H 接口的目的是为了扩展 BIOS 的功能,使其支持多于1024柱面的硬盘,以及可移动介质的琐定,解锁及弹出等功能。
二、数据结构
1. 数据类型约定
BYTE 1 字节整型 ( 8 位 )
WORD 2 字节整型 ( 16 位 )
DWORD 4 字节整型 ( 32 位 )
QWORD 8 字节整型 ( 64 位 )
2. 磁盘地址数据包 Disk Address Packet (DAP)
DAP 是基于绝对扇区地址的,因此利用 DAP,Int13H 可以轻松地逾越 1024 柱面的限制,因为它根本就不需要 CHS 的概念。
DAP 的结构如下:
struct DiskAddressPacket
{
BYTE PacketSize; // 数据包尺寸:
//(固定值,恒等于16,即10H,指本结构所占用的存储空间)
BYTE Reserved; // ==0
WORD BlockCount; // 要传输的数据块个数(以扇区为单位)
DWORD BufferAddr; // 传输缓冲地址(segment:offset)
QWORD BlockNum; // 磁盘起始绝对块地址
};
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. 驱动器参数数据包 Drive Parameters Packet
驱动器参数数据包是在扩展 Int13H 的取得驱动器参数子功能调用中使用的数据包。格式如下:
struct DriveParametersPacket
{
WORD InfoSize; // 数据包尺寸:
//(固定值,等于26,即1AH,指本结构所占用的存储空间)
WORD Flags; // 信息标志
DWORD Cylinders; // 磁盘柱面数
DWORD Heads; // 磁盘磁头数
DWORD SectorsPerTrack; // 每磁道扇区数
QWORD Sectors; // 磁盘总扇区数
WORD SectorSize; // 扇区尺寸 (以字节为单位)
};
信息标志用于返回磁盘的附加信息,每一位的定义如下:
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 ==> 磁盘地址数据包( disk address packet )
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),int 15h。如果使用了调用规范中不支持的功能,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 = 磁盘地址数据包(Disk Address Packet)
返回:
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 = 磁盘地址数据包(Disk Address Packet)
返回:
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 = 磁盘地址数据包(Disk Address Packet)
返回:
CF = 0,AH = 0 成功
CF = 1,AH = 错误码
这个调用将磁头定位到指定扇区。
8) 取得驱动器参数
入口:
AH = 48h
DL = 驱动器号
DS:DI = 返回数据缓冲区地址
返回:
CF = 0,AH = 0 成功 DS:DI 驱动器参数数据包地址,(参见前面的文章)
CF = 1,AH = 错误码
这个调用返回指定驱动器的参数。
9) 取得扩展驱动器介质更换检测线状态
入口:
AH = 49h
DL = 驱动器号
返回:
CF = 0,AH = 0 介质未更换
CF = 1,AH = 06h 介质可能已更换
这个调用返回指定驱动器的介质更换状态。
这个调用与 Int13h AH = 16h 子功能调用相同,只是允许任何驱动器标号。如果对一台支持可移动介质功能子集的固定驱动器使用此功能,则永远返回 CF = 0,AH = 0。简单地将可移动介质锁定再解锁就可以激活检测线,而无须真正更换介质。
10) Int 15h 可移动介质弹出支持
入口:
AH = 52h
DL = 驱动器号
返回:
CF = 0,AH = 0 弹出请求可能可以执行
CF = 1,AH = 错误码 B1h 或 B3h 弹出请求不能执行这个调用是由 Int13h AH=46h 弹出介质功能调用内部使用的。
|