Chapter 7: Multiboot Data - COMPLETE
This commit is contained in:
parent
e4e891bb86
commit
25ef5f4688
66
doc/7_Multiboot_Data.md
Normal file
66
doc/7_Multiboot_Data.md
Normal file
@ -0,0 +1,66 @@
|
||||
# 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`
|
||||
```asm
|
||||
...
|
||||
_start:
|
||||
cli
|
||||
|
||||
mov edi, eax
|
||||
mov esi, ebx
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
And `kmain` is updated accordingly:
|
||||
`src/kernel/boot/kmain.c`
|
||||
```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:
|
||||
|
||||
```c
|
||||
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.
|
||||
|
||||
```c
|
||||
#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).
|
@ -9,4 +9,5 @@
|
||||
[Chapter 4: "Higher Half" Kernel](4_Higher_Half_Kernel.md)<br>
|
||||
[Chapter 5: Unit Testing Framework](5_Unit_Testing.md)<br>
|
||||
[Chapter 6: Debug output](6_Debug_Output.md)<br>
|
||||
[Chapter 7: Multiboot Data](7_Multiboot_Data.md)<br>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user