深入理解 GNU GRUB - 02 boot.S 2.1 相关BIOS例程

转载注明出处(cppgp: http://blog.csdn.net/cppgp )

 

2. boot.S: GRUB引导第一步
boot.S位于目录boot/i386/pc/。这部分指令被加载到0x7C00~0x7DFF。主要工作包括:配置寄存器;设置堆栈;检测引导盘;检测引导盘读取模式;读取另一扇区指令。这个过程用到几个BIOS例程,并且对主引导记录(MBR, Master Boot Record)结构有很大的依赖。因此boot.S我们分作四步进行详细描述:
1)    相关BIOS例程
2)    主引导记录MBR结构
3)    boot.S代码结构
4)    boot.S详细注释
在本节最后,我们实现一个简单的boot.S,这个boot.S仅仅通过BIOS例程,向终端输出文本。
2.1 相关BIOS例程
boot.S用到五个磁盘相关的BIOS例程。分别是:探测磁盘扩展读支持、LBA方式读、CHS参数获取、CHS方式读、磁盘复位。磁盘读取出现LBA/CHS两种模式(其实LBA又分为28-bit、48-bit、64-bit三种),是因为在磁盘的发展历史上,由于对磁盘容量的错误估量,导致容量屏障的出现,而不得不进行接口更改、扩展。历史上出现的容量屏障主要有四次:
1)    504MiB限制。也称作物理CHS寻址限制。早期的IDE/ATA磁盘接口规定柱面(C=Cylinder)、磁头(H=Head)、扇区(S=Sector)的位宽分别为C/H/S=16/4/8;而BIOS INT 13 H/02H读调用接口规定C/H/S=10/8/6。两者结合取位宽较少者,磁盘寻址参数C/H/S=10/4/6。扇区的起始编号是1而不是0,每扇区数据512字节,因此可寻址容量为210*24*(26-1)*512=528482304bytes=504MiB。
2)    7.88GiB限制。也称作逻辑CHS寻址限制。从1) 可以看出,BIOS INT 13 H/02H接口磁头H有4位是空闲的,因此逻辑上可以扩展磁头H为8位(而实际上连接到IDE/ATA时,磁头H有4位映射到柱面C,或者映射到柱面C和扇区S)。在BIOS接口上看,现在C/H/S寻址范围扩展到210*28*(26-1)*512=8455716864bytes=7.88GiB。
3)    128GiB限制。也称作LBA-28bits限制。在 2) 中,BISO接口的CHS寻址已经到了极限,无法再扩展了,而IDE/ATA是28 位(IDE/ATA内部C/H/S=16:4:8共28位)的,理论寻址容量为228*512=128GB,因此出现了LBA (Logical Block Addressing) 寻址。LBA是一个一维地址,从0~2N-1,其中N是地址宽度,在这里是28,而LBA到CHS的转换由BIOS和磁盘完成。28位LBA寻址容量为228*512=128GiB。
4)    2TiB限制。为了提供更大范围的寻址,Western Digital和Phoenix Technologies制定了EDD (BIOS Enhanced Disk Drive Services) 标准。它使用64位LBA寻址,同时也支持48位和28位寻址。48位LBA寻址容量为128PiB,而64位LBA寻址容量更是高达8ZiB,无论48位LBA或者64位LBA,在当前或可以预见的将来应该是足够的。但是历史悠久的MBR中保存有磁盘分区表DPT,而分区表中分区绝对起始扇区和分区总扇区数都是32位的,因此对于传统分区的磁盘,最大寻址范围由这两个32位值决定,大小为232*512=2TiB。为了解决该问题,引进了GPT (GUID Partition Table) 和EFI (Extensible Firmware Interface) 技术,本文不对其做详细描述,有兴趣的读者可以Google相关主题。
在磁盘容量的计算上,软件按照1024进行单位换算,而厂商按照1000进行单位换算,因此上述的504MiB限制、7.85GiB限制、128GiB限制又称为522MB限制、8.46GB限制、137GB限制。
除了上述限制,历史上还出现过一些软件导致的容量屏障,例如一些BIOS BUG或文件系统体系导致的容量屏障,本文 不再对其做进一步描述,有兴趣可以Google相关细节。BIOS例程及容量屏障描述参考如下网络资源:
http://en.wikipedia.org/wiki/INT_13H
http://en.wikipedia.org/wiki/INT_10H
http://www.pcguide.com/ref/hdd/bios/index.htm

2.1.1磁盘扩展探测: INT 13H, AH=41H
检测磁盘扩展读(LBA/CHS)支持情况。详细描述如下。
参数:
寄存器        描述
AH=0x41    扩展检测函数序号
DL        驱动器编号(第一块硬盘为0x80,第二块为0x81,依次类推)
BX        0x55AA

结果:
寄存器        描述
CF        支持清零,不支持置1
AH        错误码或者主版本号
BX        0x55AA
CX        接口支持掩码
        1 – 使用打包结构体存取设备
        2 – 驱动器加锁和弹出
        4 – 支持增强型磁盘驱动器(EDD)

使用AT&T语法实现这个调用的例子如下(默认使用0x80作为驱动器):


调用结束后,如果CF置1、或者BX不等于0xAA55、或者CX不等于1,都表示不支持LBA,因此进入CHS处理。注意,BIOS调用可能更改掉DL寄存器值,因此需要重置。

2.1.2 LBA模式读: INT 13H, AH=42H
LBA模式的读采用打包的数据结构作为参数。
参数:
寄存器        描述
AH=42H    扩展读函数序号
DL        驱动器编号(第一块硬盘为0x80,第二块为0x81,依次类推)
DS:SI        segment:offset指针,指向磁盘地址包DAP (Disk Address Packet)

DAP结构体的格式描述如下:
偏移量        大小        描述
00H        1 Byte        DAP大小=16=0x10
01H        1 Byte        未用,必须置0
02H~03H    2 Bytes        需要读的扇区数
(有些BIOS限制不能超过127扇区)
04H~07H    4 Bytes        segment:offset指针,指向内存缓冲区,读取到的
扇区内容放置在该缓冲区
08H~0FH    8 Bytes        需要读的连续扇区的起始扇区编号
(第一个扇区的编号是0)

结果:
寄存器        描述
CF        失败置1,成功清零
AH        返回码

使用AT&T语法实现这个调用的例子如下(假定我们使用0x80作为驱动器,从第2个扇区开始连续读取4个扇区):


调用结束后,通过检测CF来判断是否成功。需要注意字节序的问题,80x86采用小端序。

2.1.3 CHS参数获取: INT 13H, AH=08H
获取驱动器CHS参数。如下。
参数:
寄存器        描述
AH=0x08    驱动器CHS参数读取函数序号
DL        驱动器编号(第一块硬盘为0x80,第二块为0x81,依次类推)
BX        0x55AA

结果:
寄存器        描述
CF        成功清零,失败置1
AH        返回码
DL        驱动器号
DH        逻辑磁头最大索引值(number_of-1因为索引从0开始)
CX        逻辑柱面索引最大值和逻辑扇区数
        逻辑柱面最大索引=number_of-,因为索引从0开始
        逻辑扇区数=number_of,因为索引从1开始
柱面占10位,CH表示柱面低8位,CL高2位表示柱面9~10位
扇区占6位,CL低6位表示扇区

使用AT&T语法实现这个调用的例子很简单:


调用结束后,通过检测CF来判断参数获取调用是否成功。

2.1.4 CHS模式读: INT 13H, AH=02H

CHS模式读扇区。需要注意缓冲区没有超出该段寻址范围。
参数:
寄存器        描述
AH=0x02    CHS模式读扇区函数序号
AL        需读取扇区数
CX        柱面和扇区,柱面占10位,扇区占6位
CH表示柱面低8位,CL高2位表示柱面9~10位
CL低6位表示扇区(从1~63)
DH        磁头
DL        驱动器编号
第一软盘为0x00,第二软盘为0x01,依次类推
第一硬盘为0x80,第二硬盘为0x81,依次类推
ES:BX        segment:offset缓冲区地址指针

结果:
寄存器        描述
CF        成功清零,失败置1
AH        返回码
AL        实际读取的扇区数

CHS读存在7.88GiB容量限制,现在几乎没有硬盘使用这种模式读,并且也很少有人使用软盘(你还有软驱吗?),因此CHS读扇区只是作为残留机制存在,很少用到。
使用AT&T语法实现这个调用的例子如下,因为要用到移位等,汇编代码看起来稍微有点麻烦。这里我们依然假定使用0x80作为驱动器,以C/H/S=0/0/1开始连续读取4个扇区。另外,需要用到2.1.3描述的CHS参数获取的结果。


CHS读结束后,通过CF判断是否成功。

2.1.5 复位磁盘驱动器: INT 13H, AH=00H
复位磁盘驱动器。如下。
参数:
寄存器        描述
AH=0x00    驱动器复位函数序号
DL        驱动器编号(第一块硬盘为0x80,第二块为0x81,依次类推)

结果:
寄存器        描述
CF        成功清零,失败置1
AH        状态

使用AT&T语法实现这个调用的例子非常简单:


通过CF判断复位是否成功。软盘的读取和CHS模式的读

2.1.6 字符输出: INT 10H, AH=0EH
BIOS使用INT 10H图形服务,可以用来设置图形模式、输出字符或字符串、以及基本图形(图形模式下读取/写入像素)。
AH=0EH提供用来向终端输出单一字符。如下。
参数:
寄存器        描述
AH=0x0E    电传输出函数序号
AL=Character    需要输出的字符
BL=Color    输出字符颜色,只对图形终端有效

结果:
无返回

使用AT&T语法实现这个调用的例子如下:

INT 10H, AH=0EH调用无返回值。

 

 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏

cppgp

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者