After having made a working C kernel (text mode), I'm following this tutorial (https://intermezzos.github.io/book/firs ... world.html) to get a basic rust kernel working. It all ran fine and printed hello world to screen.
I want to switch to VGA graphics mode and as I understand this is done by passing the multiboot header info to the kernel main, then getting the framebuffer address. (see https://github.com/29jm/SnowflakeOS/blo ... oot/boot.S , line 98)
The problem is, my kernel panics when trying to parse the header (because "panic occurred" is printed to screen).
I've determined this is because the mb header pointer from asm is invalid: https://docs.rs/multiboot2/0.12.2/multi ... tml#safety
Pretty much no knowledge of assembly other than that you push and pop to pass function parameters, and that there are differences between 32-bit and 64-bit mode. I think what causes the issue is my "long_mode_start" function. I read that in 64-bit mode you should push r*x instead of e*x and Nasm doesn't allow me to push e*x in 64-bit mode, which is why I changed it.
my rust main:
Code: Select all
#![no_main]
#![feature(lang_items)]
#![no_std]
use multiboot2::load;
use core::panic::PanicInfo;
// was trying to see what the issue is.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
if let Some(s) = _info.payload().downcast_ref::<&str>() {
vga::print_something(s);
} else {
vga::print_something("panic occurred");
}
loop {}
}
mod vga;
#[no_mangle]
pub extern fn kmain(multiboot_info_ptr: u64, magic: u64) -> ! {
let boot_info = unsafe { load(multiboot_info_ptr as usize).unwrap() };
vga::print_something("Hello World");
loop { }
}
Code: Select all
extern kmain
global start
section .text
bits 32
start:
; Point the first entry of the level 4 page table to the first entry in the
; p3 table
mov eax, p3_table
or eax, 0b11
mov dword [p4_table + 0], eax
; Point the first entry of the level 3 page table to the first entry in the
; p2 table
mov eax, p2_table
or eax, 0b11
mov dword [p3_table + 0], eax
; point each page table level two entry to a page
mov ecx, 0 ; counter variable
.map_p2_table:
mov eax, 0x200000 ; 2MiB
mul ecx
or eax, 0b10000011
mov [p2_table + ecx * 8], eax
inc ecx
cmp ecx, 512
jne .map_p2_table
;;;;;;;
; move page table address to cr3
mov eax, p4_table
mov cr3, eax
; enable PAE
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; set the long mode bit
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
; enable paging
mov eax, cr0
or eax, 1 << 31
or eax, 1 << 16
mov cr0, eax
lgdt [gdt64.pointer]
; update selectors
mov ax, gdt64.data
mov ss, ax
mov ds, ax
mov es, ax
; .data
;str:
; .string "Abcdef"
; jump to long mode!
jmp gdt64.code:long_mode_start
section .bss
align 4096
p4_table:
resb 4096
p3_table:
resb 4096
p2_table:
resb 4096
section .rodata
gdt64:
dq 0
.code: equ $ - gdt64
dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)
.data: equ $ - gdt64
dq (1<<44) | (1<<47) | (1<<41)
.pointer:
dw .pointer - gdt64 - 1
dq gdt64
section .text
bits 64
long_mode_start:
push dword rax
push dword rbx
call kmain