问题的标题和正文提出了两个不同的问题。
关于引导加载程序,或者更好的说法是 IPL(初始程序加载器)如何检测要引导的设备,您可以 check this specification 看到它在第 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 extensions 而不是INT13h 本身,尽管出于教育目的后者更简单。
如果您正在编写 VBR 引导加载程序,那么从技术上讲,您只能靠自己,VBR 和 MBR 代码之间没有标准接口。
但是,每个 MBR 引导加载程序至少会向 VBR 引导加载程序提供驱动程序编号(仍在 dl 中)
通常会传递更多元数据,但此类数据是专有的。
加载 MBR/VBR 代码后要做什么取决于程序员,例如 GRUB 有一个硬编码的 LBA(在安装期间编写)。
此 LBA 用于加载第二阶段,使用 BIOS 中的驱动程序编号。
第二阶段有一个小文件系统驱动程序,用于通过它们的路径读取内核的配置文件。
最重要的是,引导加载程序必须以某种方式知道在哪里可以找到要加载的其余代码。
这通常是通过在将引导加载程序写入磁盘之前将一些元数据写入引导加载程序的二进制映像来完成的。另一种策略是依靠 MBR 代码传递分区号/开始,这样,如果第二阶段在第一阶段之前放置了固定数量的扇区,则引导加载程序知道它在磁盘上的位置,因此第二阶段在哪里阶段是。
说到元数据,我们会看到BIOS Parameter Block。
尽管名称如此,但它不是由 BIOS 创建的,而是操作系统安装/格式化过程的结果。
自定义加载器并非绝对必要,使用它有两个原因:
- 它包含驱动程序的几何形状。
对于软盘来说,这很重要,因为软件必须告诉 FDC 要使用的几何形状(即扇区有多大)。
现在,由于 4KiB 扇区 HDD 的存在,这再次变得重要。
- 它包含查找文件系统的信息。
一些 BIOS 假定存在 BPB,并可能尝试修补相同的值,尤其是在从 USB 引导时,因此最好像 NT 引导加载程序一样至少包含一个 DOS 3.31 BPB。
一般来说,首先要做的就是决定一个分区的布局,这包括FS类型和VBR格式。
一般格式是
+------------+------------------------------------+
| boot block | FS block |
+------------+------------------------------------+
在分区的开头为引导加载程序代码保留了一些空间,VBR 包含指向 FS 块的指针。
如果 FS 足够简单(玩具操作系统可能就是这种情况)或有特殊支持,则引导加载程序可以直接加载内核,从而将引导块仅缩小到第一个扇区。
作为替代方案,引导加载程序加载第二阶段,该阶段将具有最小但通用的 FS 驱动程序,以按名称定位内核。
一般来说,VBR 代码并不完全独立于卷的 FS 类型。
例如,要在 NTFS 分区上安装 GRUB,您需要使用它的特殊版本 GRUB4DOS,它不使用经典的第二阶段。