我正在学习操作系统开发。我最近读到硬盘用 80h 表示,依此类推。但是在 MBR 中,MBR 必须检测到多个 HDD 才能选择启动。
这是怎么做到的?如何检测多个硬盘驱动器的可用性并从中切换?
我在用着:
Ubuntu
气体组装机
注意:我想在系统的实模式下用汇编语言回答。
谢谢。
我正在学习操作系统开发。我最近读到硬盘用 80h 表示,依此类推。但是在 MBR 中,MBR 必须检测到多个 HDD 才能选择启动。
这是怎么做到的?如何检测多个硬盘驱动器的可用性并从中切换?
我在用着:
Ubuntu
气体组装机
注意:我想在系统的实模式下用汇编语言回答。
谢谢。
您问题的标题和正文提出了两个不同的问题。
关于引导加载程序,或者更好的说法是 IPL(初始程序加载器)如何检测要引导的设备,您可以查看此规范以查看第 6.5.1 节中的内容
这样一来,一旦引导处理程序成功地将设备的引导扇区加载到地址 0000:7C00h 的内存中,就可以使用以下寄存器内容传输执行控制:
- ES:DI = 指向 PnP 安装检查结构的指针
- DL = 用于 INT 13h(00h、80h 等)的驱动器号
因此,IPL 给出了从中加载设备的驱动程序编号。
然后 IPL 可以将其与INT13h一起使用以加载第二阶段引导加载程序。
简单来说,如果你在写MBR bootloader,可以在里面找到驱动号dl
,保存前不要覆盖。
;Simple snippet that load one sector from the booting device
mov ax, LOAD_SEG
mov es, ax
mov bx, LOAD_OFF ;ES:BX = Where to load the data
mov ax, 0201h ;AL = How many sectors
mov cx, 0001h ;CX = Cylinder and sector
xor dh, dh ;DH = Head, DL = Driver number (As given by the BIOS)
int 13h
jc _handle_err
最好使用INT13h 扩展而不是INT13h本身,尽管出于教育目的后者更简单。
如果您正在编写VBR引导加载程序,那么从技术上讲,您是靠自己的,VBR 和 MBR 代码之间没有标准接口。
但是,每个 MBR 引导加载程序至少会向 VBR 引导加载程序提供驱动程序编号(仍在 中dl
)
通常会传递更多元数据,但此类数据是专有的。
加载 MBR/VBR 代码后要做什么取决于程序员,例如GRUB有一个硬编码的 LBA(在安装期间编写)。
此 LBA 用于加载第二阶段,使用 BIOS 中的驱动程序编号。第二阶段有一个小文件系统驱动程序,用于通过它们的路径读取内核的配置文件。
最重要的是,引导加载程序必须以某种方式知道在哪里可以找到要加载的其余代码。
这通常是通过在将引导加载程序写入磁盘之前将一些元数据写入引导加载程序的二进制映像来完成的。另一种策略是依靠 MBR 代码传递分区号/开始,这样,如果第二阶段在第一阶段之前放置了固定数量的扇区,则引导加载程序知道它在磁盘上的位置,因此第二阶段在哪里舞台是。
说到元数据,我们来到了BIOS 参数块。
尽管名称如此,但它不是由 BIOS 创建的,而是操作系统安装/格式化过程的结果。
自定义加载器不是绝对必要的,使用它有两个原因:
一些 BIOS 假定存在 BPB,并且可能会尝试修补相同的值,尤其是在从 USB 引导时,因此最好像 NT 引导加载程序那样包含至少一个DOS 3.31 BPB 。
一般来说,首先要做的是决定一个分区的布局,这包括FS类型和VBR格式。
一般格式是
+------------+------------------------------------+
| boot block | FS block |
+------------+------------------------------------+
在分区的开头为引导加载程序代码保留了一些空间,VBR 包含指向 FS 块的指针。
如果 FS 足够简单(玩具操作系统可能就是这种情况)或有特殊支持,则引导加载程序可以直接加载内核,从而仅将引导块缩小到第一个扇区。
作为替代方案,引导加载程序加载第二阶段,该阶段将具有最小但通用的 FS 驱动程序,以按名称定位内核。
还是一般来说,VBR 代码并不完全独立于卷的 FS 类型。
例如,要在 NTFS 分区上安装 GRUB,您需要使用它的特殊版本,即不使用经典第二阶段的GRUB4DOS 。