diff --git a/posts/DRAFT-remapping-the-kernel.md b/posts/DRAFT-remapping-the-kernel.md index 5b4c563c..72b8f9bd 100644 --- a/posts/DRAFT-remapping-the-kernel.md +++ b/posts/DRAFT-remapping-the-kernel.md @@ -8,6 +8,25 @@ TODO ## The Multiboot Information Structure When a Multiboot compliant bootloader loads a kernel, it passes a pointer to a boot information structure in the `ebx` register. We can use it to get information about available memory and loaded kernel sections. +First, we need to pass this pointer to our kernel as an argument to `rust_main`. To find out how arguments are passed to functions, we can look at the [calling convention of Linux]: + +[calling convention of Linux]: https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI + +> The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9 + +So to pass the pointer to our kernel, we need to move it to `rdi` before calling the kernel. Since we're not using the `rdi`/`edi` register in our bootstrap code right now, we can simply set the `edi` register right after booting (in `boot.asm`): + +```nasm +start: + mov esp, stack_top + mov edi, ebx ; Move Multiboot info pointer to edi +``` +Now we can add the argument to our `rust_main`: + +```rust +pub extern fn rust_main(multiboot_information_address: usize) { ... } +``` + ## Start and End of Kernel We can now use the ELF section tag to calculate the start and end address of our loaded kernel: diff --git a/src/arch/x86_64/boot.asm b/src/arch/x86_64/boot.asm index c424e39a..c0fa155e 100644 --- a/src/arch/x86_64/boot.asm +++ b/src/arch/x86_64/boot.asm @@ -19,6 +19,9 @@ section .text bits 32 start: mov esp, stack_top + ; Move Multiboot info pointer to edi to pass it to the kernel. We must not + ; modify the `edi` register until the kernel it called. + mov edi, ebx call test_multiboot call test_cpuid diff --git a/src/arch/x86_64/long_mode_init.asm b/src/arch/x86_64/long_mode_init.asm index 1dfb0186..47927d58 100644 --- a/src/arch/x86_64/long_mode_init.asm +++ b/src/arch/x86_64/long_mode_init.asm @@ -20,7 +20,7 @@ bits 64 long_mode_start: call setup_SSE - ; call rust main + ; call rust main (with multiboot pointer in rdi) call rust_main .os_returned: ; rust main returned, print `OS returned!` diff --git a/src/lib.rs b/src/lib.rs index 5d469e52..741a5669 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ extern crate spin; mod vga_buffer; #[no_mangle] -pub extern fn rust_main() { +pub extern fn rust_main(multiboot_information_address: usize) { // ATTENTION: we have a very small stack and no guard page vga_buffer::clear_screen(); println!("Hello World{}", "!");