我遇到了 Grub 2(和 QEMU 的 -kernel
)问题,无法检测到内核中的 Multiboot v1 header 。我将标题放在 .text
之前的单独部分中。
linker.ld
:
SECTIONS
{
. = 1M;
.multiboot ALIGN(4K) :
{
*(.multiboot)
}
.text ALIGN(4K) :
{
*(.text)
}
[snip]
boot.s
(GNU 语法):
.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1) # align, provide mem map
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
[snip]
我已经验证标题部分是按照魔数(Magic Number)指定添加的:
kernel.bin: file format elf32-i386
Contents of section .multiboot:
101000 02b0ad1b 03000000 fb4f52e4 .........OR.
Contents of section .text:
[snip]
但是 Grub 2 表示内核没有有效的 Multiboot header ,并且使用 QEMU 的 -kernel
选项会导致:
qemu: fatal: Trying to execute code outside RAM or ROM at 0x000a000
这似乎是 BIOS 映射范围内的地址,而不是 Multiboot 应该在的位置。
我已经与 Bran 和 OSDev 中的常用代码(加上我以前的内核)进行了比较,但我似乎无法弄清楚我做错了什么。
最佳答案
我的多重引导内核遇到了同样的错误。当 .text 部分的大小超过大约 4k 时,我遇到了同样的错误。我的问题的原因是,在链接时,我在 ld 参数中首先指定了 kernel.o,然后指定了 loader.o(我编写了一个 Makefile 以使我的项目基于 OSDev Wiki Bare Bones 更易于开发)。 Multiboot 应该在前 4k 中查找 header ,随着我的代码增长,它将 header 推出该区域(因为它位于内核 .text 部分中的加载器之前)。您对多重引导 header 使用了单独的部分,我不知道这可能是也可能不是一个好主意。我会尝试的事情:
- 删除 .multiboot 部分,并将其内容放入加载程序的开头,并确保 loader.o 是链接器的第一个参数,kernel.o 位于后面。
- 使用
readelf -a kernel
确保多重引导 header 确实位于前4k中(也就是说,如果开头位于0x00100000
,则其偏移量低于0x00101000
。
关于kernel - Grub 2 未检测到内核中的多重引导 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17539464/