5

我遇到了 Grub 2(和 QEMU's -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 中的常用代码(加上我以前的内核)进行了比较,但我似乎无法弄清楚我做错了什么。

4

1 回答 1

4

我的多重引导内核遇到了同样的错误。当 .text 部分的大小超过大约 4k 时,我得到了同样的错误。我的问题的原因是,在链接时,我首先指定了 kernel.o,然后在 ld 参数中指定了 loader.o(我编写了一个 Makefile 来使我的项目基于 OSDev Wiki Bare Bones 更易于开发)。Multiboot 应该在前 4k 中查找标头,并且随着我的代码增长,它将标头推出该区域(因为它位于内核 .text 部分中的加载程序之前)。您为多引导标头使用了一个单独的部分,我不知道这可能是一个好主意,也可能不是一个好主意。我会尝试的事情:

  • 删除 .multiboot 部分,并将其内容放入加载程序的开头,并确保 loader.o 是链接器的第一个参数,然后是 kernel.o。
  • 用于readelf -a kernel确保 multiboot 标头确实在前 4k 中(也就是说,如果开头是 at 0x00100000,则它的偏移量低于0x00101000.
于 2014-04-11T13:57:50.197 回答