Bad magic with Grub and the multiboot spec
Posted: Tue Aug 31, 2010 5:11 am
Hello, I'm starting to program a hobby OS, after a careful reading of numerous docs and wikis. I test it in Bochs. I follow the multiboot spec to load my kernel and I am encountering a problem, although my code is not far different from the example in the spec : I receive a wrong magic.
The code that supports the multiboot spec :
and my kernel entry :
finally, my linker script :
I use the following flags to compile with gcc ($(ARCH) is the target architecture defined in a makefile ) : -D $(ARCH) -Wall -fno-hosted -m32 -mtune=i586 and to link : -melf_i386 -Tsupport/os.ld bin/*.o -Map=OS.map (I use a bin directory where I put all my object files).
When I used the Bochs debugger, I can't find the asm intructions I used in my multiboot code (i.e. between _start and kmain), and particularly the pushes of eax and ebx. It is as if some instructions were forgotten by the compiler. My kernel prints "Magic is 0xe861 and addr is 0x20000." which are indeed on the stack, and don't seem like random values, as 0x200000 is my kernel's loading address.
I found a similar topic http://forum.osdev.org/viewtopic.php?f= ... gic#p85984 but it doesn't solve my problem.
The code that supports the multiboot spec :
Code: Select all
#ifdef HAVE_ASM_USCORE
# define EXT_C(sym) _ ## sym
#else
# define EXT_C(sym) sym
#endif
/* The size of our stack (16KB). */
#define STACK_SIZE 0x4000
/* The flags for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
# define MULTIBOOT_HEADER_FLAGS 0x00000003
/*The multiboot header has to be localized at the beginning of the kernel :
the section multiboot takes place at the start of linker script.*/
.section ".multiboot"
.globl start, _start
start:
_start:
jmp multiboot_entry
/* Align 32 bits boundary. */
.align 4
/* Multiboot header. */
multiboot_header:
/* magic */
.long MULTIBOOT_HEADER_MAGIC
/* flags */
.long MULTIBOOT_HEADER_FLAGS
/* checksum */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
/* Our stack area. */
.comm stack, STACK_SIZE,32
multiboot_entry:
/* Initialize the stack pointer. */
movl $(stack + STACK_SIZE), %ebp
movl %ebp, %esp
// Reset EFLAGS.
pushl $0
popf
/* Push the pointer to the Multiboot information structure. */
pushl %ebx
/* Push the magic value. */
pushl %eax
/* Now enter the C main function... */
call EXT_C(kmain)
cli
hlt
Code: Select all
void kmain(unsigned long magic, unsigned long addr)
{
cls();
printk("Entering OS.\nLoading boot information.\n");
printk("Magic is %x and addr is %p.", magic, addr);
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
{
printk("\nThe loader has to be multiboot standard compliant.);
return;
}
}
Code: Select all
/*The first executed byte is here, i.e. in multiboot.asm*/
ENTRY(_start)
OUTPUT(Kernel)
SECTIONS
{
/*The adress where the kernel is loaded*/
. = 0x200000;
__b_load = .;
/*We put the multiboot header at the beginning of the kernel */
.multiboot :
{
*(.multiboot);
}
__b_kernel = . ;
.text :
{
*(.text)
PROVIDE(_etext = .);
}
.data :
{
*(.data)
PROVIDE(_edata = .);
}
.rodata :
{
*(.rodata)
PROVIDE(_rodata = . );
}
__e_load = . ;
.bss :
{
*(COMMON)
*(.bss)
PROVIDE(_ebss = . );
}
___e_kernel = . ;
.comment : { *(.comment) }
}
When I used the Bochs debugger, I can't find the asm intructions I used in my multiboot code (i.e. between _start and kmain), and particularly the pushes of eax and ebx. It is as if some instructions were forgotten by the compiler. My kernel prints "Magic is 0xe861 and addr is 0x20000." which are indeed on the stack, and don't seem like random values, as 0x200000 is my kernel's loading address.
I found a similar topic http://forum.osdev.org/viewtopic.php?f= ... gic#p85984 but it doesn't solve my problem.