MBR的功能就是读取PBR到0x7C00然后转移控制权,说到底就是对于磁盘的操作,如何读扇区。
根据资料得知,硬盘目前有三种工作模式:
1.NOMAL模式(支持最大容量为528MB)
2.LBA模式=Logical Block Addressing Mode(线性表示扇区,支持最大容量为137.4GB)
3.LARGE模式
PBR在什么位置决定了读取方式,而不是仅由硬盘容量判断。
比如一个2T硬盘,但PBR在528MB以内,则NOMAL模式就能读取。
当前已经实现了LBA方式读取PBR,貌似就是BIOS的扩展磁盘服务,其定义如下:
;BIOS服务中断定义
;从下一设备启动
BIOS_BOOT_FROM_NEXT_DEVICE = 0x18
;直接磁盘服务,功能号=AH,下面列出
BIOS_DIRECT_DISK_SERVICE = 0x13
;复位驱动器
BIOS_DDS_RESET_DEVICE = 0x00
;读取驱动器参数
;成功返回值:DH=磁头,DL=驱动器数,CL低6位=扇区
BIOS_DDS_READ_DEVICE_PARAMETER = 0x08
;读扇区
;参数:AL=扇区数,CH=柱面,CL=扇区,DH=磁头
;DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
;ES:BX=缓冲区的地址
BIOS_DDS_READ_SECTOR = 0x02
;检测扩展DDS是否存在
;参数:DL=驱动器,0x80=第一块硬盘,0x81=第二块硬盘......
BIOS_DDS_CHECK_EXTENSION = 0x41
;扩展直接硬盘读写数据包结构
struct STRUCT_DDS_EXTENSION_PACK
;大小必须=0x10
Size db ?
;保留
Resvered1 db ?
;数据块数量
BlockCount dw ?
;缓冲区段偏移
BufferOffset dw ?
;缓冲区段值
BufferSegment dw ?
SC_L dw ?
SC_H dw ?
;未知=0
Unknown1 dd ?
ends
BIOS_DDS_EXTENSION_READ = 0x42
BIOS_DDS_EXTENSION_WRITE = 0x43
通过LBA读取PBR的核心代码如下:
mov dl, [bp + STRUCT_PARTITION_TABLE.State];驱动器
mov ah, BIOS_DDS_CHECK_EXTENSION;参数
int BIOS_DIRECT_DISK_SERVICE
jc .LoadPbrByLarge;不支持LBA模式,尝试LARGE模式(失败时CF=1)
mov si, Pack_Extend
mov ax, [bp + STRUCT_PARTITION_TABLE.InfoAreaSectors_L]
mov [si + STRUCT_DDS_EXTENSION_PACK.SC_L], ax
mov ax, [bp + STRUCT_PARTITION_TABLE.InfoAreaSectors_H]
mov [si + STRUCT_DDS_EXTENSION_PACK.SC_H], ax
mov ah, BIOS_DDS_EXTENSION_READ
int BIOS_DIRECT_DISK_SERVICE
jc .LoadPbrByLarge
jmp 成功
至此,已经完成了MBR的工作,还要研究一下其他模式,以保证兼容性。
不过对于一般的活动分区都能用LBA模式读取,因此这一种模式是最常用的。