Multiboot Kernel

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.
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Multiboot Kernel

Post by Bughunter »

This is my first attempt at a kernel in C, before I used ASM for a long time (and used it for OS dev). I moved on to C last year and it was time to try a kernel in it :)

I've followed the 'basickernel.pdf' from osdever.net and Tim Robinson's documents about C kernels.

I'm using a native GNU/Linux environment to build my kernel.

When trying to boot my kernel with GRUB; it says: "Invalid or unsupported executable format".

I've ran objdump against all object files and against the final executable, they are all in the ELF format. So, the AOUT kludge should not be needed (according to what I've read when searching for a solution at this forum).

Also, GRUB's "mbchk" tool says all test passed and that the multiboot header was found at offset 4096 in the final executable.

In the attachments I'm including the output of 'objdump -x'. If anyone needs more information regarding the problem or wants to view source codes, please ask.

EDIT: "mbchk" says "Address fields is turned off." (I'm using ELF though)
Attachments
log.txt
Output of 'objdump -x' ran on all object files and the final executable.
(5.68 KiB) Downloaded 93 times
Pyrofan1
Member
Member
Posts: 234
Joined: Sun Apr 29, 2007 1:13 am

Post by Pyrofan1 »

Are you sure you're linking it properly?
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Your trying to load at address zero. GRUB won't allow that. Load to 1MB instead.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post by Bughunter »

Pyrofan1 wrote:Are you sure you're linking it properly?
Not sure but it I copied it pretty much from tutorials so it should be fine. Do you want to see my linker script?
mystran wrote:Your trying to load at address zero. GRUB won't allow that. Load to 1MB instead.
How can I change this? In the linker script? In my multiboot stub?
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

bughunter wrote:
Pyrofan1 wrote:Are you sure you're linking it properly?
Not sure but it I copied it pretty much from tutorials so it should be fine. Do you want to see my linker script?
mystran wrote:Your trying to load at address zero. GRUB won't allow that. Load to 1MB instead.
How can I change this? In the linker script? In my multiboot stub?
In linker script. Here's the script I use:

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)

load_address = 0x100000; /* at 1M */

SECTIONS
{
    . = load_address;

    .text :
    {
        *(.multiboot.header)    /* must be within 8k, so put first */

        *(.text)
        *(.rodata*)
    }

    .data : {
        data = .;
        *(.data)
    }

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

    _kernel_end = .;
}
The .multiboot.header is a special section defined in my boot.S since I don't like the idea of relying on order of parameters on command line. You don't need it if you don't mind having to but the file with the multiboot header first on your linker command line..
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
Assembler
Member
Member
Posts: 30
Joined: Fri Oct 27, 2006 5:26 am
Contact:

Post by Assembler »

bughunter wrote: Do you want to see my linker script?
Better for you
bughunter wrote: How can I change this? In the linker script? In my multiboot stub?
something like that :

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(entry)
virt = 0xC0000000; /* 3 GB */
phys = 0x100000; /* 1 MB */
SECTIONS
{   .text virt : AT(phys)
    {   code = .;
        *(.text)
        . = ALIGN(4096); 
    }
    .data :  AT(phys + (data - code))
    {   data = .;
         *(.data)
         . = ALIGN(4096); 
    }
    .bss :  AT(phys + (bss - code))
    {   bss = .;
        *(.bss)
        *(COMMON)
        . = ALIGN(4096); 
    }
    end = .; 
}
For higher kernel

Code: Select all

ENTRY (start)

SECTIONS
{
    . = 0x00100000;

    .text :
    {
        *(.text)
    }

    .rodata ALIGN (0x1000) :
    {
        *(.rodata)
    }

    .data ALIGN (0x1000) :
    {
        *(.data)
    }

    .bss :
    {
        _sbss = .;
        *(COMMON)
        *(.bss)
        _ebss = .;
    }
}
For lower kernel
Systems and Computer Engineering Researcher
"Do you pine for the nice days of Minix-1.1, when men were men and wrote their own device drivers?" -- Linus Torvalds
http://sce.carleton.ca/~maslan
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post by Bughunter »

Assembler wrote: For lower kernel
I used exactly that one.

@mystran: the multiboot header is found at 4kB (says "mbchk"). By the way, I'd like to define my multiboot header just like yours, how can I define it in my assembly file (I'm using NASM)?
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

I have absolutely no idea about Nasm. I've never even had it installed on any system I've had.. but in Gas you'd do it like this:

Code: Select all

      .section .multiboot.header
Look at NASM documentation. I would guess it can't be too different.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post by Bughunter »

Yeah I was already thinking about porting it to GAS, this encourages me to do so, as I also don't like to rely on the order of specifying files on the command line.

Anyways, I figured out my error. I was building on one system, and then transferring the files by FTP to another machine. You might already know what's wrong... I wasn't setting the transfer type to binary (I used Linux' console FTP program). It now works!

Another question though:
I've also setup a Cygwin environment on my XP box, and when building my kernel with Cygwin (using a cross compiler targeted for i586-elf) the output is about 6kB. But when compiling it under native Linux (slackware + GCC 3.4.2 is what I used) the final output is about 10kB. Does anybody have an idea why this happens?

EDIT: The Cygwin GCC cross compiler version is 4.1.2
urxae
Member
Member
Posts: 149
Joined: Sun Jul 30, 2006 8:16 am
Location: The Netherlands

Post by urxae »

bughunter wrote:Yeah I was already thinking about porting it to GAS, this encourages me to do so, as I also don't like to rely on the order of specifying files on the command line.
It's easy in NASM too. My multiboot header starts with:

Code: Select all

SECTION mb-header ALIGN=4
I use a different section name, but the principle is the same. (The ALIGN=4 may not be needed, but I added it to be safe. It may be ELF-specific though)
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

bughunter wrote: Another question though:
I've also setup a Cygwin environment on my XP box, and when building my kernel with Cygwin (using a cross compiler targeted for i586-elf) the output is about 6kB. But when compiling it under native Linux (slackware + GCC 3.4.2 is what I used) the final output is about 10kB. Does anybody have an idea why this happens?
The 4.1.2 series GCC supposedly has much better optimizer, so maybe it can generate smaller code? The other possibility is that your native Linux compiler includes more symbols or something.. you could try playing with strip and see if it can bring the filesize down. Not that it should matter.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post by Bughunter »

urxae wrote: It's easy in NASM too. My multiboot header starts with:

Code: Select all

SECTION mb-header ALIGN=4
I use a different section name, but the principle is the same. (The ALIGN=4 may not be needed, but I added it to be safe. It may be ELF-specific though)
Thanks, but I already ported it to GAS now :P I also liked GAS because then everyone with the binutils can assemble it.
mystran wrote: The 4.1.2 series GCC supposedly has much better optimizer, so maybe it can generate smaller code? The other possibility is that your native Linux compiler includes more symbols or something.. you could try playing with strip and see if it can bring the filesize down. Not that it should matter.
I don't think it should make _that_ much difference, as the test kernel I started with in C is just one or two functions. And I used '-s' already while compiling, but I'll try strip. Posting results here shortly.

EDIT: On Cygwin, using 'strip -s' on the compiled kernel resulted in 4688 bytes. On Slackware Linux it resulted in a kernel of 8648 bytes. Hmm? Big difference :?
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

That sounds a lot like page alignment of the first page in the file, where the Linux executable did do that (text + rodata at 0x1000, data + bss at 0x2000) and the Win-ish executable didn't (text+rodata right after headers, data and bss with a page delay).
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post by Bughunter »

So how can it be fixed? In my linker script? I used one exactly the same as the second example given by Assembler.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Don't bother. Extra 4k for the kernel size hardly matters, especially as it's only the disk-size, not the final loaded size (assuming Candy is correct). Plus if you really care about disk-size, then you can gzip the resulting binary (Grub loads those as well) at which point the difference probably reduces to insignificance.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
Post Reply