From 959a93e653684b1ed8db4bd21eaca9831e372fb0 Mon Sep 17 00:00:00 2001 From: Tianhao Wang Date: Wed, 29 May 2024 01:18:02 +0200 Subject: multiboot: basic support for multiboot info well, it's not trivial to use bios function because thanks to grub + multiboot, we are already in protected mode when the startup code takes control. Also the MB info is easier to play with than BIOS (or ACPI) Signed-off-by: Tianhao Wang --- src/arch/x86_64/asm/e820.s | 2 -- src/lib.rs | 10 ++++-- src/machine/mod.rs | 1 + src/machine/multiboot.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) delete mode 100644 src/arch/x86_64/asm/e820.s create mode 100644 src/machine/multiboot.rs (limited to 'src') diff --git a/src/arch/x86_64/asm/e820.s b/src/arch/x86_64/asm/e820.s deleted file mode 100644 index 59c672a..0000000 --- a/src/arch/x86_64/asm/e820.s +++ /dev/null @@ -1,2 +0,0 @@ -; getting an E820 memory map, code from osdev wiki. -; this only works in real mode ... how to do it in long mode? diff --git a/src/lib.rs b/src/lib.rs index 759c7c0..3651a81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,13 +8,13 @@ mod ds; mod io; mod machine; mod mm; +use crate::machine::key::Modifiers; use arch::x86_64::interrupt; use arch::x86_64::interrupt::pic_8259; use arch::x86_64::interrupt::pic_8259::PicDeviceInt; use core::panic::PanicInfo; use machine::cgascr::CGAScreen; - -use crate::machine::key::Modifiers; +use machine::multiboot; #[cfg(not(test))] #[panic_handler] @@ -28,14 +28,18 @@ pub extern "C" fn _entry() -> ! { // init code io::set_attr(0x1f); io::clear_screen(); + assert!(multiboot::check_magic(), "bad multiboot magic!"); + let mbi = multiboot::get_mb_info().expect("bad multiboot info flags"); + println!("MB INFO: {:#X?}", mbi); interrupt::init(); pic_8259::allow(PicDeviceInt::KEYBOARD); interrupt::interrupt_enable(); - io::print_welcome(); let mut framemap = mm::pma::FMap::new(); framemap.init(); println!("Bitmap starting from : {:p}", framemap.bm.as_ptr()); println!("Skip first {} bytes", framemap.skip_byte); + println!("system init .. done!"); + // io::print_welcome(); // busy loop query keyboard loop { diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 46ca961..a2cf730 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -4,5 +4,6 @@ pub mod interrupt; pub mod key; pub mod keyctrl; pub mod mem; +pub mod multiboot; // TODO: this module *should* be arch independent. diff --git a/src/machine/multiboot.rs b/src/machine/multiboot.rs new file mode 100644 index 0000000..3056db3 --- /dev/null +++ b/src/machine/multiboot.rs @@ -0,0 +1,77 @@ +use crate::io::*; +// provide functions to parse information provided by grub multiboot +// see docs/multiboot.txt +extern "C" { + static mb_magic: u32; + static mb_info_addr: u32; +} + +#[repr(C)] +#[repr(packed)] +#[derive(Debug)] +pub struct MultibootMmap { + pub size: u32, + pub addr: u64, + pub len: u64, + pub mtype: u32, +} + +#[repr(C)] +#[repr(packed)] +#[derive(Debug, Clone, Copy)] +pub struct MultibootInfo { + pub flags: MultibootInfoFlags, + pub mem_lower: u32, + pub mem_upper: u32, +} + +use bitflags::bitflags; +bitflags! { + /// the MultibootInfoFlags indicate which fields are valid in the MultibootInfo + /// atm we only need the MEM and MMAP flags for memory management info. + #[derive(Copy, Clone, Debug)] + pub struct MultibootInfoFlags: u32 { + const MEM = 1 << 0; + const BOOT_DEVICE = 1 << 1; + const CMDLINE = 1 << 2; + const MODS = 1 << 3; + const SYM_TBL = 1 << 4; + const SHDR = 1 << 5; + const MMAP = 1 << 6; + const DRIVES = 1 << 7; + const CONF_TBL = 1 << 8; + const BL_NAME = 1 << 9; + const APM_TBL = 1 << 10; + const VBE_TBL = 1 << 11; + const FRAMEBUFFER = 1 << 12; + } +} + +impl MultibootInfoFlags { + /// only 13 bits of the MB info flags are defined. The other flag bits must + /// be zero for the info block to be valie. + const VALID_MASK: u32 = 0x1FFF; + + pub fn check_valid(&self) -> bool { + return self.bits() <= Self::VALID_MASK; + } +} + +pub fn check_magic() -> bool { + return unsafe { mb_magic == 0x2BADB002 }; +} + +pub fn get_mb_info() -> Option { + if !check_magic() { + return None; + } + let mbi = unsafe { *(mb_info_addr as *mut MultibootInfo) }; + let flags = mbi.flags; + if !flags.check_valid() { + return None; + } + return Some(mbi); +} + +// TODO: expand MultibootInfo struct defs if needed. + -- cgit v1.2.3-70-g09d2