since I recently managed to conquer the challenges of the x86 bootstrap process with my 32-bit mini-kernel, I wanted to go a step further and port my code base to x86_64 and finally enter long mode. From this point on, my progress got frozen: For some reason, qemu and bochs do not recognize the multiboot header of my image. I tried the same with a multiboot2 header - without any success. I found a lot of similar issues on the web and as well here in the forum but, they did not help. Which is why I am reopening this topic and really hope for constructive hints.
In other threads, a wrong placement of the multiboot header appeared to be the issue. However in my case, at least according to readelf and objdump, the multibootheader is placed correctly within the first page at the start address 0x100000.
Here is my bootstrap entry code (Within the code, a multiboot and multiboot2 header are present: Please note that I used only one multiboot header at a time for testing):
Code: Select all
.intel_syntax noprefix
.code32
# ----------------------------------------------------------------------
# .multiboot: declare header in mutliboot standard
.section .multiboot
.code32
.align 8
# constants for multiboot header:
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set FLAGS, ALIGN | MEMINFO # multiboot flags
.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find header
.set CHECKSUM, (-(MAGIC + FLAGS) & 0xffffffff) # checksum of the mboot header
/* multiboot header */
.long MAGIC
.long FLAGS
.long CHECKSUM
/* performing tests with the multiboot2 header */
mboot2_start:
.long 0xe85250d6
.long mboot2_end - mboot2_start
.long (-(0xe85250d6 + 0 + (mboot2_end - mboot2_start)) & 0xffffffff)
mboot2_end:
# ----------------------------------------------------------------------
# allocate some stack space
.section .bootstrap.stack, "aw", @nobits
stack_bottom:
.skip 16384 # 16 KB
stack_top:
# ----------------------------------------------------------------------
# .text: the global function _start represents our kernel entry point in
# our .text segment
.section .text
.code32
.globl _start
.type _start, @function
_start:
cli
lea esp, stack_top
.hang:
cli
hlt
jmp .hang
Code: Select all
NTRY(_start)
SECTIONS
{
. = 0x00100000;
.text ALIGN(0x1000) :
{
*(.multiboot)
*(.text .text.* .gnu.linkonce.t.*)
}
.rodata ALIGN(0x10) :
{
PROVIDE (_srodata = .);
start_ctors = .;
*(SORT(.ctors*))
end_ctors = .;
start_dtors = .;
*(SORT(.dtors*))
end_dtors = .;
*(.rodata*)
*(.gnu.linkonce.r*)
PROVIDE (_erodata = .);
}
.data ALIGN(0x10) :
{
PROVIDE (_sdata = .);
*(.data*)
*(.gnu.linkonce.d*)
PROVIDE (_edata = .);
}
.bss ALIGN(0x10) :
{
*(.bss .bss.* .gnu.linkonce.b.*)
*(.bootstrap.stack)
}
/DISCARD/ :
{
*(.note)
*(.comment)
/* *(.eh_frame) */ /* discard this, unless you are implementing runtime support for C++ exceptions. */
}
}