Grub 2 не обнаруживает заголовок Multiboot в ядре

У меня проблема с 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 (плюс мое предыдущее ядро), но я не могу понять, что я делаю неправильно.

1 ответ

Я столкнулся с той же самой ошибкой с моим мультизагрузочным ядром. Я получил ту же ошибку, когда размер раздела.text превысил 4k. Причиной моей проблемы было то, что при компоновке я сначала указывал kernel.o, а затем loader.o - в аргументах ld (я написал Makefile, чтобы сделать мой проект, основанный на OSDev Wiki Bare Bones, более удобным для разработки). Multiboot должен искать заголовок в первых 4k, и по мере роста моего кода он выталкивал заголовок из этой области (так как он находился перед загрузчиком в разделе ядра.text). Вы использовали отдельный раздел для заголовка мультизагрузки, что может быть, а может и не быть хорошей идеей, я не знаю. Вещи, которые я бы попробовал:

  • удалите раздел.multiboot, поместите его содержимое в начало загрузчика и убедитесь, что loader.o является первым аргументом компоновщика, а kernel.o - после.
  • использование readelf -a kernel чтобы убедиться, что заголовок мультизагрузки действительно находится в первых 4k (то есть, если начало в 0x00100000, его смещение ниже 0x00101000,
Другие вопросы по тегам