如果虚拟机的固件是传统BIOS,为什么我在Grub中无法引导带有Multiboot头的内核?
我用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,而不是 menutry 和 kernel。修正这些问题后,在传统BIOS下应该就能启动。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。