我在使用 Grub 2(以及 QEMU 的-kernel
)没有检测到我的内核中的 Multiboot v1 标头。我之前将标题放在单独的部分中.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]
我已经验证标题部分是按照幻数指定添加的:
kernel.bin: file format elf32-i386
Contents of section .multiboot:
101000 02b0ad1b 03000000 fb4f52e4 .........OR.
Contents of section .text:
[snip]
然而 Grub 2 表示内核没有有效的 Multiboot 标头,并且使用 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 中查找标头,随着我的代码增长,它将标头推出该区域(因为它位于内核 .text 部分中的加载器之前)。您对多重引导标头使用了单独的部分,我不知道这可能是也可能不是一个好主意。我会尝试的事情:
- 删除 .multiboot 部分,并将其内容放入加载程序的开头,并确保 loader.o 是链接器的第一个参数,kernel.o 紧随其后。
- use
readelf -a kernel
确保多重引导标头确实位于前 4k 中(也就是说,如果开头位于0x00100000
,其偏移量低于0x00101000
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)