Booting a 64-bit executable with Grub
Posted: Wed Mar 07, 2007 10:22 am
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:
My linker script:
When I link to binary, I get this output from grub:
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:
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]
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
...
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 = .;
}
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]
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...