Page 1 of 1

cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 11:28 am
by songziming
Hi, i use grub to boot my kernel. Instead of cross compiling the kernel, I use objcopy to produce binary image to get rid of every host-specific information. mbchk indicates that the binary kernel is valid, however GRUB reports Error 13.

This is my kernel source (currently only one file)

Code: Select all

extern  kernel_load_addr
extern  kernel_data_end
extern  kernel_bss_end

MB_MAGIC    equ 0x1badb002
MB_FLAGS    equ 1<<0|1<<1|1<<16
MB_CHECK    equ -(MB_MAGIC+MB_FLAGS)

[SECTION    .boot]
[BITS       32]

    jmp     multiboot_entry
ALIGN   4
multiboot_header:
    dd      MB_MAGIC
    dd      MB_FLAGS
    dd      MB_CHECK
    dd      multiboot_header
    dd      kernel_load_addr
    dd      kernel_data_end
    dd      kernel_bss_end
    dd      multiboot_entry

multiboot_entry:
    cli

    mov     al, 'H'
    mov     ah, 0x0f
    mov     [0xb8000], ax

    jmp     $
And this is my link script

Code: Select all

OUTPUT_FORMAT(elf32-i386)
SECTIONS {
    . = 1M;
    kernel_load_addr = .;
    .text BLOCK(4K) : ALIGN(4K) {
        kernel_text_start = .;
        *(.boot)
        *(.text)
        kernel_text_end = .;
    } = 0x90
    .data BLOCK(4K) : ALIGN(4K) {
        kernel_data_start = .;
        *(.rodata)
        *(.data)
        kernel_data_end = .;
    } = 0x90
    .bss BLOCK(4K) : ALIGN(4K) {
        kernel_bss_start = .;
        *(COMMON)
        *(.bss)
        kernel_bss_end = .;
    } = 0x90
}
and the command for compile and linking is

Code: Select all

yasm -f elf multiboot.asm -o multiboot.o
ld -m elf_i386 -T link.lds multiboot.o -o kernel.elf
objcopy -O binary kernel.elf kernel.bin
Besides, I'm producing 32-bit code on a 64-bit Linux, does it matter?

Re: cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 11:45 am
by max
songziming wrote:Instead of cross compiling the kernel
Use a cross toolchain.

I'm sorry but we can't try to find a solution for all kinds of grotesque ways that people try to build their kernels. Using your systems linker will cause problems.

Re: cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 11:48 am
by songziming
I did try using cross compiler and change the output format in the link.lds to binary. But I still get the Error 13 from GRUB.

Re: cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 11:54 am
by max
songziming wrote:I did try using cross compiler and change the output format in the link.lds to binary. But I still get the Error 13 from GRUB.
If you're using a cross compiler, it shouldn't be necessary to specify the output format. I think you should not have that "jmp" instruction right before your multiboot header.

Re: cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 12:05 pm
by kzinti
You haven't defined an entry point in your linker script. Usually you want to use '_start'. Add a "_start" label before the jump over the multiboot header. Then add "ENTRY(_start)" to your linker script.

Re: cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 12:42 pm
by no92
songziming wrote:I did try using cross compiler and change the output format in the link.lds to binary. But I still get the Error 13 from GRUB.
Wait, wait, wait!
OSDev.org Wiki wrote:[...] making a cross-compiler is required, so as not to link in the development system's runtime files.
If it's written there, do it, for the love of programming. There's a reason for it. Just do it, even if you don't understand it yet.

While not having worked with linker scripts, I noticed two things: kzinti already pointed the first one, while I don't know what this is supposed to do:

Code: Select all

} = 0x90

Re: cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 2:39 pm
by Icee
Because you have no actual data in the .data section, it is not copied to the output file. However, the symbol kernel_data_end still has the address 0x101000 associated with it because of the enforced alignment in linker script. GRUB tries to load 0x1000 and cannot because the resulting file is smaller. You have two options: either remove the alignment directives (by the way, the ALIGN directive after the colon should not be there in the first place), or add something to the data section, like this:

Code: Select all

[SECTION .data]
DD 0
You should also not pad the .data and .bss sections with NOPs (=0x90), this is meaningless for .data and, in fact, erroneous for .bss because the latter must be zero-initialized.

Re: cannot make binary kernel work with GRUB

Posted: Wed Mar 11, 2015 10:46 pm
by songziming
Icee's method works!

To be clear, my purpose is to make a BINARY kernel, not ELF kernel. Because I think all the machine-dependencies have something to do with elf meta data.

Re: cannot make binary kernel work with GRUB

Posted: Thu Mar 12, 2015 12:03 am
by Roman
songziming wrote:I think all the machine-dependencies have something to do with elf meta data.
What? The code is machine-dependent because every ISA (instruction set architecture) has its own encoding.