mittos64/doc/7_Multiboot_Data.md

2.0 KiB

Multiboot Data

In this chapter we'll parse the multiboot information structure passed to the kernel from the bootloader.

Passing the data to the kernel

When a multiboot compliant bootloader passes controll to the kernel, the registers eax and ebx contains a magic number and a pointer to the multiboot information structure respectively.

If we wish to pass those on to the kernel main function, we can do that according to the System V ABI calling convention. According to this, the first two arguments to a function should be passed in the rdi and rsi registers for x86_64. Those obviously correspond to edi and esi in 32-bit mode, and luckily those registers are unused throughout the entire long mode transition process, untill we call kmain.

So everything we need to to do preserve the information is to move it into those registers. Might as well do that as soon as possible.

src/kernel/boot/boot.S

...
_start:
  cli

  mov edi, eax
  mov esi, ebx

...

And kmain is updated accordingly: src/kernel/boot/kmain.c

...
void kmain(uint64_t multiboot_magic, void *multiboot_data)
{
...

Reading the multiboot information

Reading the data passed from the bootloader is actually pretty straight forward. It's stored as a list of "tags" with a 32 bit type and 32 bit size followed by the data.

I just step through the tag list and save the data I want into a global structure. The only possible pitfall is that tags are 8 byte alligned, so finding the next tag can look like:

int padded_size = tag->size + ((tag->size % 8)?(8-(tag->size%8)):0);
tag = incptr(tag, padded_size);

incptr is just a macro I made to move a pointer a number of bytes forward or backward. Quite useful.

#define incptr(p, n) ((void *)(((uintptr_t)(p)) + (n)))

For now, I only save the bootloader name (type 2) and kernel commandline (type 1), and that's just for testing purposes. Later we'll also want to save and parse the memory map (type 6) and any modules (type 3).