将内核加载到内存中 - 如何自己编写加载程序?

Meh*_*dad 3 bootstrapping kernel portable-executable bootloader

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

背景:

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

问题

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

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

Ces*_*arB 8

GRUB是如何做到的?

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

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

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

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