GRUB 0.97 & x86-64 issues [solved]

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
User avatar
stealther
Posts: 18
Joined: Sun Dec 21, 2008 1:53 am
Location: Ukraine, Kyiv

GRUB 0.97 & x86-64 issues [solved]

Post by stealther »

Hi.
I used Windows/MSVS/ICC to develop my os. (it compiles for both x86 and x86-64)
But now I'm using Ubuntu for 2 month or so and I like *nix concept.
So I'm trying to get a minimal hello-world compiling in linux.
Started with bare-bones stuff and built x86-64 cross-compiler recently.
I'm using GRUB 0.97 and kludge method to load x86-64 binary.
When I create a floppy using

Code: Select all

dd  if=/dev/zero of=pad.bin bs=1 count=750
cat grub/stage1 grub/stage2 pad.bin build/kernel64.bin > floppy.img
there is no problem, it successfully boots with

Code: Select all

kernel 200+18
boot
But if I create a filesystem with grub installed, and configure menu.lst ... i get this:

Code: Select all

[Multiboot-kludge, loadaddr=0x200000, text-and-data=0x2000
Error 13: Invalid or unsupported executable format
Can anybody figure out what's happening wrong?
Thanks in advance. ;)

P.S. I attached the sources. [UPDATED]
you'll need nasm, gcc, qemu, make
just run

Code: Select all

make run
Last edited by stealther on Mon Jul 20, 2009 3:27 am, edited 7 times in total.
wrschlanger
Posts: 6
Joined: Tue Jul 14, 2009 9:06 am

Re: GRUB 0.97 & x86-64 issues

Post by wrschlanger »

Hi stealther, I had the same problem with my OS, using Ubuntu and GRUB to boot the 64bit OS.
Do you have an Elf64 kernel binary? I did get it to work, by using a 4kb "stub" that's in Elf32, then a separate 64bit kernel image file that's incbin'd and org'd to 4kb past the load address of the kernel.
For details, see here:
http://vm64dec.googlecode.com/files/options64-0.02.zip

That is an example of a 64bit OS that you can build using NASM and GCC. In fact, my version of Ubuntu came with a GCC compiler that can cross-compile to 64bit mode using the -m64 switch, there was no need for me to rebuild the compiler. See if this is true for you too.

./dold is the main "build the os" shell script file.
As you can see by examining it, I first build the Elf64 64-bit OS, then I assemble the 32bit Elf32 OS, then I patch the resulting binary file--see the above link for details.

Hope this helps,
Willow
User avatar
stealther
Posts: 18
Joined: Sun Dec 21, 2008 1:53 am
Location: Ukraine, Kyiv

Re: GRUB 0.97 & x86-64 issues

Post by stealther »

wrschlanger, you're right!
It was needless to build cross-compiler ;)
Thank's for reply. I'll check that link later.
P.S. Just created a usable Makefile. (The first Makefile in my whole life :D )

Edit:
But what's the problem with GRUB loading it from fs?
(It should be equivalent to loading from specified location)
User avatar
stealther
Posts: 18
Joined: Sun Dec 21, 2008 1:53 am
Location: Ukraine, Kyiv

Re: GRUB 0.97 & x86-64 issues

Post by stealther »

When I change output format to binary GRUB detects i386 binary as multiboot-kludge and refuses to load it (same with x86-64).
In my asm bootstrap code I have something like

Code: Select all

[bits 32]
align 4
section .text
mboot:
	dd MULTIBOOT_HEADER_MAGIC
	dd MULTIBOOT_HEADER_FLAGS
	dd MULTIBOOT_CHECKSUM
	dd mboot
	dd __text_start
	dd __data_end
	dd __kernel_end
	dd loader
User avatar
stealther
Posts: 18
Joined: Sun Dec 21, 2008 1:53 am
Location: Ukraine, Kyiv

Re: GRUB 0.97 & x86-64 issues [solved]

Post by stealther »

Hi.
Just fixed it. :D
I don't get it. I just removed .data section alignment. Now my ld script looks like this:

Code: Select all

ENTRY (loader)
SECTIONS {
	. = 0x200000;
	.text :
	{
		__text_start = .;
		*(.text)
		*(.rodata)
		__text_end = .;
	}
	/* . = ALIGN(0x1000); */
	.data :
	{
		__data_start = .;
		start_ctors = .;
		*(.ctor*)
		end_ctors = .;
		start_dtors = .;
		*(.dtor*)
		end_dtors = .;
		*(.data)
		__data_end = .;
	}
	.bss :
	{
		__bss_start = .;
		*(.bss)
		*(COMMON)
		__bss_end = .;
	}
	__kernel_end = .;
}
Any comments?
Maybe I'm doing something wrong?
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: GRUB 0.97 & x86-64 issues [solved]

Post by Creature »

I believe normally every section should be page-aligned in order to be loaded correctly. You can do this by putting a

Code: Select all

. = ALIGN(4096);
or a

Code: Select all

. = ALIGN(0x1000);
at the end of very section, for example:

Code: Select all

SECTIONS
{
	KERNEL_START = 0x100000;

	.text KERNEL_START :
	{
		*(.text)
		*(.rodata*)
		. = ALIGN(4096);
	}

	.data :
	{
		/* Constructor and destructor variables. */		
		LdConstrStart = .;
		*(.ctor*)
		LdConstrEnd = .;
	
		*(.data)
		. = ALIGN(4096);
	}

	.bss :
	{
		*(.COMMON*)
		*(.bss*)
		. = ALIGN(4096);
	}

	LdEnd = .;
}
I'm not sure how it works in 64-bits though, normally paging and page-aligning should work the same way, except for the fact that you can have address extensions and such (PAE?). I guess someone else should confirm it as well.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
stealther
Posts: 18
Joined: Sun Dec 21, 2008 1:53 am
Location: Ukraine, Kyiv

Re: GRUB 0.97 & x86-64 issues [solved]

Post by stealther »

Okay,
I guess page-alignment is nedded to make sections with different accessibility. (.text, .rodata - ro, .data - rw)
But why GRUB refuses loading my kernel?

aout kludge is present, sections are page-aligned, and GRUB is acting according to this scheme:

Code: Select all

if (output == elf){
    if (i386){
        detects as elf
        boots it 
    } else if (x86_64)
        detects as kludge (but doesn't print entry point)
        refuses to boot
    }
} else if (output == binary) {
    if (i386){
        detects as kludge (but doesn't print entry point)
        refuses to boot
    } else if (x86_64)
        detects as kludge (but doesn't print entry point)
        refuses to boot
    }
}
if I remove page-alignment:

Code: Select all

if (output == elf){
    if (i386){
        detects as elf
        boots it
    } else if (x86_64)
        detects as kludge [b](prints entry point)[/b]
        boots it
    }
} else if (output == binary) {
    if (i386){
        detects as kludge (but doesn't print entry point)
        refuses to boot
    } else if (x86_64)
        detects as kludge
        boots it
    }
}
So you can see the only working combination is no page alignment of sections and ELF output.
That raises some questions ;)

Why GRUB detects my i386 elf binary as elf regardless of aout kludge (I thought kludge has grater priority)
Why can't I get my i386 version booted as flat binary?
Why it works witout page-alignemt?
And so on.. :D
Help me please. I'm feeling miserous.
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: GRUB 0.97 & x86-64 issues [actually NOT solved]

Post by Creature »

All I've had experience with is 32-bits ELF kernels and I only know that there, you won't need the AOUT_KLUDGE. From your linker script, I can see your kernel is indeed being loaded above 1 MB, so that should be correct. Besides that, you could try (if you haven't already), explicitely setting the format inside the linker script. For example:

Code: Select all

OUTPUT_FORMAT("elf32-i386")
For 32-bits. I believe 64-bits ELF will require the following output format:

Code: Select all

OUTPUT_FORMAT(elf64-x86-64)
I'm telling you this since obviously, GRUB doesn't recognize your kernel's format. Have you also tried to set all the Assembly files to compile as ELF?
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
stealther
Posts: 18
Joined: Sun Dec 21, 2008 1:53 am
Location: Ukraine, Kyiv

Re: GRUB 0.97 & x86-64 issues [actually NOT solved]

Post by stealther »

Creature wrote:Have you also tried to set all the Assembly files to compile as ELF?
Yes.
Creature wrote:I'm telling you this since obviously, GRUB doesn't recognize your kernel's format.
It does recognize elf-i386.
I'd like my kernels to be flat binaries. (Using AOUT_KLUDGE)
User avatar
stealther
Posts: 18
Joined: Sun Dec 21, 2008 1:53 am
Location: Ukraine, Kyiv

Re: GRUB 0.97 & x86-64 issues [solved]

Post by stealther »

Victory! ;)
Finally I can say: I solved the problem ;)
Now I have both kernels linking into binary format.
There are also page alignments.
Grub successfully loads both of them.
This is achieved without dark magic like patching or concatenating executables and making elf-32 stubs.
There is only 1 asm loader per kernel.
Hooray! ;)
My x64 loader isn't going into long mode. It's just spinning in the loop for now.
If there are some interested people, I can upload the sources (after switching to long mode and fixing Makefile).
Post Reply