4

我正在努力在 D 中制作自己的引导加载程序和内核,但遇到了一个绊脚石。

背景:

  • 我从头开始写一切。所以引导扇区正在组装中。而且我没有使用 GRUB。
  • 我正在使用 Qemu 进行测试。
  • 引导扇区从“磁盘”(目前只是一个平面二进制文件,其第一个扇区是引导加载程序,其余部分是内核代码)中读取内核到虚拟地址 0xC0000000,并调用kmain()我的入口点核心。
  • 我正在为我的内核使用PE 文件格式。(请不要告诉我使用 Elf——我的选择是 PE。)

问题

能够加载 PE 文件是内核工作的一部分。那么我如何首先将内核本身加载到内存中,以便它可以真正正确执行?

我不能从引导扇区执行此操作,因为 (1) 它不适合 512 字节,并且 (2)在汇编中这样做很痛苦。显然,我也不能在内核本身中做到这一点。那么我该怎么做呢?

4

1 回答 1

10

GRUB 是如何做到的?

在 GRUB 中,512 字节的引导扇区不会加载内核。相反,它会加载引导加载程序的其余部分,这比 512 字节大得多。正是这个第二阶段的引导加载程序加载了内核。你将不得不做类似的事情。

加载第二阶段的代码比加载完整内核的代码要简单得多——它基本上将几个扇区直接加载到一个固定的内存地址中(在低内存中——此时它仍处于实模式)并跳转到一个固定的内存地址。

第二阶段主要可以用 C 语言编写。您只需要在汇编中进行一些设置(进入保护模式、设置堆栈以及其他一些低级处理器的东西),然后跳转到 C 函数来完成其余的工作的设置。

Linux 内核过去曾做过类似的事情。您可以将原始内核直接复制到软盘中。它的前 512 个字节是软盘引导扇区,它将接下来的几个扇区(仍处于实模式)加载到低内存中的固定地址中。接下来的几个扇区有代码(仍在汇编中)将内核的其余部分加载到一个固定的内存地址,并跳转到它的真正入口点。如今,IIRC 的大部分代码都被删除了,Linux 内核现在依赖于外部引导加载程序。

于 2011-06-19T22:53:55.217 回答