准备加载内核

Dav*_*zer 5 linux boot assembly

即使有完美的引导装载机可供使用,我也在业余时间一次打开和关闭作为教育练习.我遇到了一个问题.

我能够执行初始启动和链接加载其他扇区没有问题.如果我正在编写自己的操作系统,我会很高兴.:)相反,我正在尝试引导Linux.我所面临的挑战是双重的.

  1. 我知道我需要将内核(Linux)加载到0x100000的内存中.我知道我应该在内核的偏移量0x202处找到"HdrS"签名.我也知道起始地址应该是0x214.但是,当我跳到该位置的地址时,它会停止.显然,围绕这个包装调试器非常困难.:) 我是否遗漏了确定内核正确起始地址所必需的这一系列事实?
  2. 我怀疑(1)的答案可能与需要用硬件发现信息填充一些内存区域有关.我已经在OSDev Wiki上看到了几个对此的引用,但我似乎错过了这里,并且确切地说需要哪些数据. 引导加载程序是否负责硬件发现?如果是这样,需要将哪些数据放在哪里?

需要注意的另一点是我已经处于32位保护模式,因为我正在处理创建EFI启动系统,因此16位实模式在这里不是一个真正的选项,从而消除了实际模式的起始位置.核心.

Dav*_*zer 3

@Jester 找到了我的问题并回答了这两个问题。解决方案实际上位于我链接的文件中,尽管我错过了相关部分。我将相关的文章放在这里供后代使用:

在32位启动协议中,加载Linux内核的第一步应该是设置启动参数(struct boot_params,传统上称为“零页”)。struct boot_params 的内存应该被分配并初始化为全零。然后,应将内核映像偏移 0x01f1 处的设置标头加载到 struct boot_params 中并进行检查。设置头的结尾可以计算如下:

0x0202 + 偏移量 0x0201 处的字节值

除了像 16 位引导协议那样读取/修改/写入 struct boot_params 的设置头之外,引导加载程序还应该填充 struct boot_params 的附加字段,如 Zero-page.txt 中所述。

设置struct boot_params后,引导加载程序可以像16位引导协议一样加载32/64位内核。

在32位启动协议中,内核是通过跳转到32位内核入口点来启动的,该入口点是加载的32/64位内核的起始地址。

进入时,CPU 必须处于 32 位保护模式并禁用分页;GDT 必须加载选择器 __BOOT_CS(0x10) 和 __BOOT_DS(0x18) 的描述符;两个描述符都必须是4G扁平段;__BOOT_CS必须有执行/读权限,__BOOT_DS必须有读/写权限;CS 必须为 __BOOT_CS,DS、ES、SS 必须为 __BOOT_DS;必须禁用中断;%esi 必须保存 struct boot_params 的基地址;%ebp、%edi 和 %ebx 必须为零。

64 位指令也可以在同一文档中找到。