gccx86-64osdevgrub2multiboot

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


I read GRUB Multiboot header not found but I cannot still load my kernel

I tries to write the multiboot2 header directly in the .s file then link it. It is supposed to appear before all other segment:

[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 Script]

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)
    }
}

[Dump]

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

Through hexdump, you can see that he was accurately placed at the 1M address, so Grub could not identify it. How to make the header be placed at the front end of the file?

This is the make log

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

Solution

  • Looking at hexdump the Multiboot2 header is 1MiB into the file which is why it can't find it. The Multiboot2 header has to be in the first 32KiB of the ELF executable and be 64-bit aligned. Because the code was generated by a 64-bit compiler the sections were probably 2MiB page aligned. You will want to change this to be 4KiB alignment to ensure the Multiboot header can be found.

    Modify your link command line to be:

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

    The option -z max-page-size=0x1000 modifies the maximum page alignment to be 0x1000 (4096 or 4KiB) rather than 2MiB.