Booting a 64-bit executable with Grub

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
speal
Member
Member
Posts: 43
Joined: Wed Mar 07, 2007 10:09 am
Location: Minneapolis, Minnesota
Contact:

Booting a 64-bit executable with Grub

Post by speal »

After fighting with it for a few days now, I've decided it's time to ask for help.

I have code very much like Barebones on the osdevfaqwiki that I want to compile and link into an executable format that supports long mode instructions on the AMD64. I have no trouble doing this, as I've built a cross compiler. The trouble comes when I try to boot it.

I'm creating the multiboot header correctly (as shown in barebones as well), and I'm using the aout kludge. No matter what output_format I specify in my linker script, I cannot get grub to load the executable correctly. I'm not using anything 64 bit yet, so I can still compile/link into elf32, and grub will load this with no complaints.

First few lines of loader.asm, following 'global's and 'extern's:

Code: Select all

start:
       jmp _loader

...

;setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
AOUT_KLUDGE equ  1<<16

FLAGS       equ  MODULEALIGN | MEMINFO | AOUT_KLUDGE ; this is the Multiboot 'flag' field
MAGIC       equ    0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required

BASE equ 0x100000

section .text
align 4
MultiBootHeader:
	dd MAGIC
	dd FLAGS
	dd CHECKSUM
	
	dd MultiBootHeader ; these are PHYSICAL addresses
	dd code  ; start of kernel .text (code) section
	dd bss ; end of kernel .data section
	dd end   ; end of kernel BSS
	dd start ; kernel entry point (initial EIP)

;Use a 16K stack for the kernel
STACKSIZE equ 0x4000

_loader:
    mov esp, stack+STACKSIZE    ;Set up the stack
    push eax                    ;Pass the multiboot magic number to _main
    push ebx                    ;Pass the multiboot info structure to _main

...
My linker script:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY (start)
phys = 0x00100000;
SECTIONS
{
    .text phys : AT(phys)
    {
		code = .;
        *(.text)
		. = ALIGN(4096);
    }

    .rodata : AT(phys + (rodata - code))
    {
		rodata = .;
        *(.rodata)
		. = ALIGN(4096);
    }

    .data : AT(phys + (data - code))
    {
		data = .;
        start_ctors = .;
        *(.ctor*)
        end_ctors = .;
        start_dtors = .;
        *(.dtor*)
        end_dtors = .;
        *(.data)
		_edata = .;
		. = ALIGN(4096);
    }

    .bss : AT(phys + (bss - code))
    {
		bss = .;
        _sbss = .;
        *(COMMON)
        *(.bss)
        _ebss = .;
		. = ALIGN(4096);
    }
	end = .;
}
When I link to binary, I get this output from grub:

Code: Select all

  Booting 'My Kernel'

root (fd0)
 Filesystem type is fat, using whole disk
kernel /kernel.bin
    [Multiboot-kludge, loadaddr=0x100000, text-and-data=0x5000, bss=0x7000, entry=0x100000]
and then it just hangs (the 32 bit one continues on to set up the GDT and IDT, clear the screen and print some information about the cpu and memory system).

When I link to elf64-little, Grub tells me this:

Code: Select all

  Booting 'My Kernel'

root (fd0)
 Filesystem type is fat, using whole disk
kernel /kernel.bin
    [Multiboot-kludge, loadaddr=0x100000, text-and-data=0x5000, symtab=0x2, strtab=0x11301fc(bad), entry=0x100000]

Error 30: Invalid argument

Press any key to continue...
Anybody know what I'm doing wrong? I've tried some things with objcopy as well, but I don't know enough about it to know what I was doing, or why it didn't work. Any sort of specific directions on how to get grub to load a 64 bit executable (just into pmode) would be great, since I'm all set to enable long mode once I'm there.[/code]
Post Reply