GRUB2 在加载我的内核时产生 "multiboot header cannot be found" 错误

GRUB2 produces "multiboot header cannot be found" error when loading my kernel

我阅读了 GRUB Multiboot header not found 但我仍然无法加载我的内核

我尝试直接在 .s 文件中写入 multiboot2 header 然后 link 它。它应该出现在所有其他段之前:

[kheader.s]

.section .mbt2std
tag_start:
.long 0xE85250D6
.long 0
.long tag_end-tag_start
.long -1*(tag_end-tag_start + 0 +  0xE85250D6)
.short 0
.short 0
.short 8
tag_end:

[Link 脚本]

OUTPUT_FORMAT("elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(kmain)
SECTIONS
{
    . = 1M;
    .text ALIGN(4K):
    {
        *(.mbt2std)
        *(.text)
    }
    .rodata :
    {
        *(.data)
    }
    .data :
    {
        *(.data)
    }
    .bss :
    {
        *(.bss)
    }
}

[转储]

alan@alan-virtual-machine:~/git/Lithium-OS/src$ make dmp
objdump -s ../build/lithium.elf

../build/lithium.elf:     文件格式 elf64-x86-64

Contents of section .text:
 100000 d65052e8 00000000 16000000 14afad17  .PR.............
 100010 00000000 08005548 89e54883 ec104889  ......UH..H...H.
 100020 7df89048 8b45f848 83c0070f b6000fb6  }..H.E.H........
 100030 c089c748 b8b00510 00000000 00ffd0c0  ...H............

symbol table '.symtab' contains 36 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000100000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000100b50     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000100e20     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS ../build/kheader.o
     5: 0000000000100000     0 NOTYPE  LOCAL  DEFAULT    1 tag_start
     6: 0000000000100016     0 NOTYPE  LOCAL  DEFAULT    1 tag_end
     7: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS ata.c
     8: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS ioport.c
     9: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS kernel.c
    10: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS sysop.c
    11: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS univideo.c
    12: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS vbe.c
    13: 00000000001005ce    29 FUNC    GLOBAL DEFAULT    1 out_port16

    alan@alan-virtual-machine:~/git/Lithium-OS/src$ hexdump ../build/lithium.elf 
    0000000 457f 464c 0102 0001 0000 0000 0000 0000
    0000010 0002 003e 0001 0000 0606 0010 0000 0000
    0000020 0040 0000 0000 0000 1058 0010 0000 0000
    0000030 0000 0000 0040 0038 0002 0040 0007 0004
    0000040 0001 0000 0007 0000 0000 0000 0000 0000
    0000050 0000 0000 0000 0000 0000 0000 0000 0000
    0000060 0b62 0010 0000 0000 0e48 0010 0000 0000
    0000070 0000 0020 0000 0000 e551 6474 0007 0000
    0000080 0000 0000 0000 0000 0000 0000 0000 0000
    *
    00000a0 0000 0000 0000 0000 0008 0000 0000 0000
    00000b0 0000 0000 0000 0000 0000 0000 0000 0000
    *
    0100000 50d6 e852 0000 0000 0016 0000 af14 17ad //1MiB
    0100010 0000 0000 0008 4855 e589 8348 10ec 8948
    0100020 f87d 4890 458b 48f8 c083 0f07 00b6 b60f
    0100030 89c0 48c7 b0b8 1005 0000 0000 ff00 c0d0
    0100040 06e8 013c dd74 c990 55c3 8948 48e5 ec83
    0100050 4830 7d89 48e8 7589 48e0 5589 48d8 ffb8
    0100060 ffff ffff 00ff 4800 4539 76e0 480c c0c7
    0100070 ffff ffff 6fe9 0002 4800 458b 48e8 c789
    0100080 b848 0016 0010 0000 0000 d0ff 8b48 e845
    0100090 8348 01c0 b60f 0f00 c0b6 00be 0000 8900
    01000a0 48c7 ebb8 1005 0000 0000 ff00 48d0 458b

通过hexdump可以看到他准确的放在了1M地址处,所以Grub无法识别。如何让header放在文件的最前端?

这是生成日志

alan@alan-virtual-machine:~/git/Lithium-OS/src$ make
make clean
make[1]: Entering directory '/home/alan/git/Lithium-OS/src'
rm -rf ../build/
mkdir ../build/
make[1]: Leaving directory '/home/alan/git/Lithium-OS/src'
time make all
make[1]: Entering directory '/home/alan/git/Lithium-OS/src'
[II] Making Libs
make -C ./lib libs
make[2]: Entering directory '/home/alan/git/Lithium-OS/src/lib'
[II] Making IO Lib
make -C ./io lib-io
make[3]: Entering directory '/home/alan/git/Lithium-OS/src/lib/io'
gcc -mcmodel=large -fno-builtin -I ../include -m64 -c -Wall -nostdinc -nostdlib ioport.c -o ../../../build/ioport.o 2>>../../../build/cmplog >>../../../build/cmplog
gcc -mcmodel=large -fno-builtin -I ../include -m64 -c -Wall -nostdinc -nostdlib ata.c -o ../../../build/ata.o 2>>../../../build/cmplog >>../../../build/cmplog
make[3]: Leaving directory '/home/alan/git/Lithium-OS/src/lib/io'
[II] Making SYS Lib
make -C ./sys lib-sys
make[3]: Entering directory '/home/alan/git/Lithium-OS/src/lib/sys'
gcc -mcmodel=large -fno-builtin -I ../include -m64 -c -Wall -nostdinc -nostdlib sysop.c -o ../../../build/sysop.o 2>>../../../build/cmplog >>../../../build/cmplog
make[3]: Leaving directory '/home/alan/git/Lithium-OS/src/lib/sys'
[II] Making Video Lib
make -C ./video lib-video
make[3]: Entering directory '/home/alan/git/Lithium-OS/src/lib/video'
gcc -mcmodel=large -fno-builtin -I ../include -m64 -c -Wall -nostdinc -nostdlib vbe.c -o ../../../build/vbe.o 2>>../../../build/cmplog >>../../../build/cmplog
gcc -mcmodel=large -fno-builtin -I ../include -m64 -c -Wall -nostdinc -nostdlib univideo.c -o ../../../build/univideo.o 2>>../../../build/cmplog >>../../../build/cmplog
make[3]: Leaving directory '/home/alan/git/Lithium-OS/src/lib/video'
[II] All Libs Ok
make[2]: Leaving directory '/home/alan/git/Lithium-OS/src/lib'
[II] Making KernelHeader
as --64 -o ../build/kheader.o kheader.s
[II] Header is OK
[II] Making Kernel
gcc -mcmodel=large -fno-builtin -I ./lib/include -m64 -c -Wall -nostdinc -nostdlib kernel.c -o ../build/kernel.o 2>>../build/cmplog >>../build/cmplog
[II] EveryLib is Ok,Start Linking
[II] Linking
ld -T kernel.lds --build-id=none -b elf64-x86-64 -o ../build/lithium~dirty.o ../build/*.o
[II] Cleaning Other Section
objcopy -R ".eh_frame" -R ".comment" ../build/lithium~dirty.o ../build/lithium.elf
make[1]: Leaving directory '/home/alan/git/Lithium-OS/src'
0.26user 0.23system 0:00.51elapsed 96%CPU (0avgtext+0avgdata 18220maxresident)k
0inputs+176outputs (0major+21075minor)pagefaults 0swaps
[II] Compile Complete.
[II] Kernel:../build/lithium.elf

ls -l ../build/lithium.elf
-rwxrwxr-x 1 alan alan 1053208 10月 24 14:18 ../build/lithium.elf

objdump -f ../build/lithium.elf

../build/lithium.elf:     文件格式 elf64-x86-64
体系结构:i386:x86-64, 标志 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
起始地址 0x0000000000100606

[II] Checking Vaild MB2
make chkmb
make[1]: Entering directory '/home/alan/git/Lithium-OS/src'
grub-file --is-x86-multiboot2  ../build/lithium.elf
Makefile:59: recipe for target 'chkmb' failed
make[1]: *** [chkmb] Error 1
make[1]: Leaving directory '/home/alan/git/Lithium-OS/src'
Makefile:26: recipe for target 'system' failed
make: *** [system] Error 2

查看 hexdump,Multiboot2 header 在文件中有 1MiB,这就是它找不到它的原因。 Multiboot2 header 必须在 first 32KiB of the ELF executable and be 64-bit aligned 中。因为代码是由 64 位编译器生成的,所以这些部分可能是 2MiB 页对齐的。您需要将其更改为 4KiB 对齐以确保可以找到 Multiboot header。

将您的 link 命令行修改为:

ld -z max-page-size=0x1000 -T kernel.lds --build-id=none -b elf64-x86-64 -o ../build/lithium~dirty.o ../build/*.o .

选项 -z max-page-size=0x1000 将最大页面对齐修改为 0x1000(4096 或 4KiB)而不是 2MiB。