Page 1 of 1

Multibtoot2 header information loaded to kernel

Posted: Thu Feb 25, 2021 6:06 pm
by finarfin
Hi everyone! :)
After many years far from osdev, i decided to go back and create a new kernel from scratch (64bit this time) in the free time, with no real big objective, just try to go back into the fun of low level programming... after being forced to use javascript at work for some time! (but recently i moved to python lol)

Btw here my question, i was following various tutorial on how to create a hello world 64bit kernel, like this one: https://intermezzos.github.io/book/firs ... aders.html

and i followed it, and launched my C kernel, printed lot of stuff, started to write some print functions etc.. everything works fine.

Now in my previous OS, that used multiboot1 specs, i was able to pass a data structure to the kernel containing some useful info (like the flags, mem_lower, mem_uppper, cmdline, etc) the multiboot_info_t data structure.

And as far as i know it is possible with multiboot2 too.

What i understood is that the information should be stored in ebx (this is written in the documentation), and eax should contain the magic number.

So on my new kernel i have done the exact same thing i did in the previous one, pushed content of ebx just before doing the long jump.

Code: Select all

push rbx 
call kernel_start
I used rbx, because i already switched to the long mode. But the problem is that when i enter into the kernel the value at the address provided looks pretty random.

My problem is that i haven't a clear idea of what is the data type i should expect from the bootloader, if there is any, or need to guess like here https://www.gnu.org/software/grub/manua ... rnel_002ec

Btw before entering into the kernel i switched to 32bit thant to 64bit, that means that loaded paging, and gdt. And mapped the kernel into memory. So probably this can be one of the issues. But in theory i never touch ebx (unless something else does). Or could be that once i enabled paging


My multiboot_header looks like it now:

Code: Select all

section .multiboot_header
header_start:
    dd 0xe85250d6   ;magic_number
    dd 0            ;Protected mode
    dd header_end - header_start    ;Header length

    ;compute checksum
    dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))

    dd  0x4 ;Add memory information tag
    dd  0x10    ; Size of the current tag
    ;end tag
    dw 0    ;type
    dw 0    ;flags
    dd 8    ;size
header_end:
This is my linked script:

Code: Select all

ENTRY(start)

SECTIONS {
    . = 1M;

    .boot :
    {
        /* Be sure that multiboot header is at the beginning */
        *(.multiboot_header)
    }

    .text :
    {
        *(.text)
    }

    end = .;
}

Actually i tried to add a flag to get the memory information, but where this should be stored? And what if if i put more flags? How they should be accessed? Sequentially? And another thing that is not clear, the end tag has to be one per earch tag?

Most of the code of the boot sequence is pretty similar to the one in the link posted above (the intermezzos book).

What information i'm missing? And mainly when the ebx content should be pushed into the stack?

Thanks! :)

Re: Multibtoot2 header information loaded to kernel

Posted: Thu Feb 25, 2021 6:42 pm
by Octocontrabass
finarfin wrote:So on my new kernel i have done the exact same thing i did in the previous one, pushed content of ebx just before doing the long jump.
That's probably why it doesn't work. The System V AMD64 psABI passes some function arguments in registers instead of the stack. I'd guess you need to move the value in EDX to EDI before calling kernel_start.

You might want to check the wiki for some other important ABI differences between 32-bit and 64-bit.

Re: Multibtoot2 header information loaded to kernel

Posted: Thu Feb 25, 2021 7:24 pm
by finarfin
Ok, let me see if i understood crrectly:
  • In i386 when calling a c function from Assembly, the c function parameters were all passed on the stack
  • On x86_64 instead the parameter passed in order (i suppose) first on the registers: rdi, rsi, etc, then after the registers are finished they are passed on the stack.
I tried to move ebx into the edi register, and now i get i different number much smaller but i need to check if this one is what i'm expecting (i'll do it tomorrow that now is very late here :D) but looks promising.
I also moved eax, into esi and added it as a parameter of the kernel C function and now the content is the expected magic number 0x36d76289.

Thanks!