如果虚拟机的固件是传统BIOS,为什么我在Grub中无法引导带有Multiboot头的内核?

编程语言 2026-07-10

我用Multiboot标头创建了一个内核,但如果虚拟机固件是传统BIOS,GRUB就无法启动。

链接器脚本:

ENTRY(_start) /* the name of the entry label */

SECTIONS {
    . = 0x00100000; /* the code should be loaded at 1 MB */
    .text ALIGN (0x1000) : /* align at 4 KB */
    {
        *(.text) /* all text sections from all files */
    }
    .rodata ALIGN (0x1000) : /* align at 4 KB */
    {
        *(.rodata*) /* all read-only data sections from all files */
    }
    .data ALIGN (0x1000) : /* align at 4 KB */
    {
        *(.data) /* all data sections from all files */
    }
    .bss ALIGN (0x1000) : /* align at 4 KB */
    {
        *(COMMON) /* all COMMON sections from all files */
        *(.bss) /* all bss sections from all files */
    }
}

内核加载器:

bits 32

MB_MAGIC        equ 0x1BAD002
MB_FLAGS        equ 0x0010003
MB_CHECKSUM     equ -(MB_MAGIC + MB_FLAGS)

section .multiboot
align 4
    dd MB_MAGIC
    dd MB_FLAGS
    dd MB_CHECKSUM

global _start
extern kinit
_start:
    cli
    call kinit
.loop:
    jmp .loop

section .note.GNU-stack noalloc noexec nowrite progbits

内核:

#include <stdint.h>
#include <cga.h>

void kinit() {
    print("Hello Crix!", CGA_COLOR_BLACK, CGA_COLOR_WHITE);
}

用于构建ISO映像的Makefile:

CC = gcc
ASM = nasm
TARGET_DIR = target

JUNKS = *.o *.a *.bin *.elf *.log *.img *.iso *.cpio* crix*

.PHONY: build
build:
    @$(MAKE) clean
    @mkdir -p $(TARGET_DIR)/boot/grub
    @$(MAKE) -C kernel
    @cp kernel/crix $(TARGET_DIR)/boot

    @echo set timeout=0 > $(TARGET_DIR)/boot/grub/grub.cfg
    @echo menutry ""Crix"" { >> $(TARGET_DIR)/boot/grub/grub.cfg
    @echo "    kernel /boot/crix" >> $(TARGET_DIR)/boot/grub/grub.cfg
    @echo } >> $(TARGET_DIR)/boot/grub/grub.cfg
    @grub-mkrescue $(TARGET_DIR) -o crix.iso

clean:
    @$(foreach JUNK, $(JUNKS), $(shell find . -name "$(JUNK)" -delete))
    @rm -rf $(TARGET_DIR)

export CC
export ASM

启动错误

源代码

解决方案

这不是BIOS问题,GRUB未能看到一个有效的Multiboot内核。你的头部魔数错误(0x1BADB002,不是 0x1BAD002),你的标志位在没有必需的地址字段的情况下错误地把第16位设为1,你的链接脚本应该把 \*(.multiboot) 放在首位,以确保头部位于前8 KiB内,而 grub.cfg 应该使用 menuentry 加上 multiboot /boot/crix,而不是 menutrykernel。修正这些问题后,在传统BIOS下应该就能启动。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章