Page 1 of 1

Bad magic with Grub and the multiboot spec

Posted: Tue Aug 31, 2010 5:11 am
by programLyrique
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 :

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
and my kernel entry :

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

 }
finally, my linker script :

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

Re: Bad magic with Grub and the multiboot spec

Posted: Tue Aug 31, 2010 5:51 am
by xenos
So if the magic and address are on the stack of kmain, maybe you could check whether they are 1. correctly passed to your printk function, and 2. your printk function correctly prints a hex number and an address. It seem that the magic value is lost somewhere on that way.

Re: Bad magic with Grub and the multiboot spec

Posted: Tue Aug 31, 2010 6:07 am
by programLyrique
In fact, the right values are not on the stack for kmain : there are the wrong ones 0xe861 and 0x200000 on the stack as I said at the end of my post (I may have explained the problem badly ; magic should be 0x2BADB002). The printk function correctly prints those wrong values.
When I put breakpoints at _start and at kmain : the instructions in asm I showed in the first posted code doesn't seem to be executed (when I inspect the instruction flow with "next") ; I can't see the pushes of eax and ebx for instance. It's quite strange.

Re: Bad magic with Grub and the multiboot spec

Posted: Tue Aug 31, 2010 1:02 pm
by xenos
Sorry, that was my fault - you explained correctly what's on the stack, I simply misread your post.

It looks really strange to me and I can't see any obvious mistake in your code. Have you tried disassembling your kernel to check whether the push instructions are present in the output file? objdump with option "-d" is very helpful for this purpose, you should also check for the correct entry point. Your multiboot header also looks fine to me - it should take the entry point from the ELF header...

Re: Bad magic with Grub and the multiboot spec

Posted: Tue Aug 31, 2010 2:14 pm
by programLyrique
For section multiboot_entry, i have :
00200010 <multiboot_entry>:
200010: bd 80 4a 20 00 mov $0x204a80,%ebp
200015: 89 ec mov %ebp,%esp
200017: 6a 00 push $0x0
200019: 9d popf
20001a: 53 push %ebx
20001b: 50 push %eax
20001c: e8 03 00 00 00 call 200024 <kmain>
200021: fa cli
200022: f4 hlt
That seems right, I have my push instructions...
However, I had to use objdump -D : multiboot_entry is not marked as executable nor alloc (the flags of the section) when I use readelf. It would be very odd if it were the point...
readelf tells me :
Entry point address: 0x200000

At this address, I have a jmp instruction towards the multiboot_entry.
I heard Grub2 doesn't support the multiboot spec I use but implements a new one, but I use Grub 0.97.

EDIT: a grammar error

Re: Bad magic with Grub and the multiboot spec

Posted: Tue Aug 31, 2010 3:15 pm
by programLyrique
When I do that .... it works !!
Thank you for you reply.
However, it looks like a linker magic. May you explain me why it didn't work before, in a special section : because of the non executable and alloc flag ?

Re: Bad magic with Grub and the multiboot spec

Posted: Wed Sep 01, 2010 1:59 am
by programLyrique
Ok, thank you.
Using the /DISCARD/ command is also a good tip. The linker put me .comment before .text so that I had to put .comment at the end, but /DISCARD/ is better.