引导加载程序如何实际移交给内核?

dei*_*tch 6 boot kernel boot-loader grub2

假设我有一个带有kernelinitrd线的引导程序。出于所有意图和目的,我现在有 2 或 3 个“内核”阶段:

  1. 固件
  2. grub(或其他引导加载程序)
  3. 真正的 linux 内核

以上将适用于 MBR。对于 EFI,引导加载程序(或引导管理器)只是一个 EFI 应用程序,它在固件是“内核”时运行:

  1. 固件,加载 EFI 应用程序
  2. 真正的 linux 内核

实际的内核切换过程是什么。从 2 到 3,或者 EFI 固件从 1 到 2,MBR grub 实际上做了什么?它类似于kexec?

其次,在 EFI 的情况下,一些钩子被传递给 EFI 应用程序,然后传递给 Linux 内核(所以我们可以做像 efibootmgr 之类的事情),它是如何传递的?

最后,是否有可能不止一次这样做?例如,如果我在加载“常规”操作系统之前需要做一些自定义工作,例如测量和验证 TPM 条目、解密等,也许使用 grub、rEFInd 或其他方法不容易完成的事情,我可以加载“临时”阶段内核和initrd,执行它们,然后移交?

Run*_*ium 3

一些注释,主要是关于 BIOS/GRUB 系统。

\n\n

带有 GRUB 的 BIOS 系统:

\n\n

BIOS 从地址0xfffffff0(x86)开始。

\n\n

进行各种测试,例如 POST。如果一切顺利,则按照 CMOS 中配置和保存的顺序检查设备。第一个具有有效 MBR(偏移量 510 处的签名为0x55aa)的引导设备将加载到地址为 的内存中0x7c00

\n\n

然后 BIOS 将控制权交给从 MBR 的 offset 处加载的代码(字节)0。那是; 留下控制的数据应该是处理器指令。一个程序。

\n\n

例如,如果您查看 MBR 映像,您可能会发现类似于eb6390开头的内容。这翻译成两条机器指令:

\n\n
eb63 => jump to 0x63 (offset 0x65 in MBR as count is from end of instruction)\n90   => No Operation\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n

从这里开始,GRUB 加载下一阶段。通常是第一扇区core.img

\n\n
    \n
  • diskboot.S在正常磁盘引导上的 GRUB 源中。
  • \n
\n\n

跳转到此代码,然后加载core.img. 这包括例如Reed-Solomon 纠错、解压缩等startup_raw.S。当前的 GRUB 是基于模块的,这些也在这个阶段加载。

\n\n

GRUB 配置文件被读取等,当它确定要运行哪个内核时,它将它从/boot目录加载到内存中。然后初始 RAM 磁盘映像initrd被加载到内存中。

\n\n

引导加载程序还将配置字符串的内存地址写入内核内存空间。即启动选项。请参阅标有“修改”的标头字段

\n\n

另请注意,引导加载程序在加载阶段通常会在实模式和保护模式之间交替。这样能够加载超过 1 MB 限制的数据。

\n\n

完成此操作后,引导加载程序将控制权交给内核,就像 BIOS 通过 MBR 将控制权留给引导加载程序一样。这是在实模式下完成的。

\n\n

内核(通常)是基于模块的。例如,这些模块中有文件系统模块。在启动时,内核可能必须从文件系统读取文件,它需要一个模块来读取 \xe2\x80\xa6 这就是initrd起作用的地方。开始所需的模块位于此处。

\n\n

(U)EFI

\n\n

如果使用 uefigrub 安装等,(U)EFI 引导过程可以与 BIOS/GRUB 处于同一轨道。还可以选择使用EFI Boot Stub,它允许 EFI 固件将内核作为 EFI 可执行文件加载。

\n\n

此外,从内核 3.14 开始kexec也可用,但不适合冷启动。

\n