假设我有一个带有kernel
和initrd
线的引导加载程序。出于所有意图和目的,我现在正在进行 2 或 3 个“内核”阶段:
- 固件
- grub(或其他引导加载程序)
- 实际的Linux内核
以上是针对 MBR 的。对于 EFI,引导加载程序(或引导管理器)只是一个 EFI 应用程序,它在固件是“内核”时运行:
- 固件,加载 EFI 应用程序
- 实际的Linux内核
实际的内核切换过程是什么? MBR grub 实际上做了什么才能从 2 变为 3,或者 EFI 固件从 1 变为 2?它类似于吗kexec
?
其次,在 EFI 的情况下,一些钩子被传递到 EFI 应用程序,然后传递到 Linux 内核(这样我们就可以做 efibootmgr 等事情),这是如何传递的?
最后,是否可以多次这样做?例如,如果我在加载“常规”操作系统之前需要做一些自定义工作,例如测量和验证 TPM 条目、解密等,也许使用 grub、rEFInd 或其他工具不容易完成的事情,我可以加载“临时”阶段内核和 initrd,执行它们,然后移交?
答案1
一些注释,主要是关于 BIOS/GRUB 系统。
带有 GRUB 的 BIOS 系统:
BIOS 启动时间地址0xfffffff0
(x86)。
进行各种测试,例如 POST。如果一切顺利,则按照 CMOS 中配置和保存的顺序检查设备。第一个具有有效 MBR(偏移量 510 处的签名为0x55aa
)的引导设备将加载到地址为 的内存中0x7c00
。
然后 BIOS 将控制权交给从 MBR 的 offset 处加载的代码(字节)0
。那是;留下控制的数据应该是处理器指令。一个程序。
例如,如果您查看 MBR 映像,您可能会发现类似于eb6390
开头的内容。这翻译成两条机器指令:
eb63 => jump to 0x63 (offset 0x65 in MBR as count is from end of instruction)
90 => No Operation
boot.S
在 GRUB 源中。汇编中MBR中的第一条指令:jmp LOCAL(after_BPB) nop
从这里开始,GRUB 加载下一阶段。通常第一扇区core.img
diskboot.S
在正常磁盘引导上的 GRUB 源中。
跳转到此代码,然后加载core.img
.这包括例如Reed-Solomon 纠错、解压缩等startup_raw.S
。当前的 GRUB 是基于模块的,这些也在这个阶段加载。
GRUB 配置文件被读取等,当它确定要运行哪个内核时,它将它从/boot
目录加载到内存中。然后初始 RAM 磁盘映像initrd
被加载到内存中。
引导加载程序还将配置字符串的内存地址写入内核内存空间。即启动选项。看标头字段标记的“调整”。
另请注意,引导加载程序在加载阶段通常会在实模式和保护模式之间交替。这样能够加载超过 1 MB 限制的数据。
完成此操作后,引导加载程序将控制权交给内核,就像 BIOS 通过 MBR 将控制权留给引导加载程序一样。这是在实模式下完成的。
内核(通常)是基于模块的。例如,这些模块中有文件系统模块。在启动时,内核可能必须从文件系统中读取文件,它需要一个模块来读取……这就是initrd
起作用的地方。开始所需的模块位于此处。
(U)EFI:
(U)EFI 启动过程能如果使用 uefigrub 安装等,则与 BIOS/GRUB 处于同一轨道。还可以选择使用EFI 引导存根它允许 EFI 固件将内核作为 EFI 可执行文件加载。
更远,从内核 3.14 开始,kexec
也是可用的,但不适用于冷启动。