diff options
| author | Tianhao Wang <shrik3@mailbox.org> | 2024-05-29 01:18:02 +0200 |
|---|---|---|
| committer | Tianhao Wang <shrik3@mailbox.org> | 2024-06-11 15:17:10 +0200 |
| commit | 959a93e653684b1ed8db4bd21eaca9831e372fb0 (patch) | |
| tree | 152426d2f9eb39ff26941204aaa149840e59578a | |
| parent | 590d29c3e44fc06bc79c2624fc94273434505b9d (diff) | |
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 <shrik3@mailbox.org>
| -rw-r--r-- | boot/startup-x86_64.s | 14 | ||||
| -rw-r--r-- | defs/x86_64-linker.ld | 8 | ||||
| -rw-r--r-- | docs/multiboot.txt | 45 | ||||
| -rw-r--r-- | src/arch/x86_64/asm/e820.s | 2 | ||||
| -rw-r--r-- | src/lib.rs | 10 | ||||
| -rw-r--r-- | src/machine/mod.rs | 1 | ||||
| -rw-r--r-- | src/machine/multiboot.rs | 77 |
7 files changed, 150 insertions, 7 deletions
diff --git a/boot/startup-x86_64.s b/boot/startup-x86_64.s index 448576a..6392d0f 100644 --- a/boot/startup-x86_64.s +++ b/boot/startup-x86_64.s @@ -11,7 +11,8 @@ MAX_MEM: equ 512 [GLOBAL startup] [GLOBAL pml4] [GLOBAL pdp] - +[GLOBAL mb_magic] +[GLOBAL mb_info_addr] ; functions from other parts of rustubs [EXTERN vectors_start] [EXTERN idt] @@ -28,6 +29,12 @@ MAX_MEM: equ 512 startup: cld cli + ; with multiboot specs, grub initialzes the registers: + ; EAX: magic value 0x2BADB002 + ; EBX: 32-bit physical address of the multiboot information struct + ; we store them in global variables for future uses in rust code. + mov dword [mb_magic], eax + mov dword [mb_info_addr], ebx ; setup GDT by loading GDT descriptor ; see docs/x86_gdt.txt lgdt [gdt_80] @@ -156,6 +163,11 @@ gdt_80: dw 4*8 - 1 ; GDT limit=24, 4 GDT entries - 1 dq gdt ; GDT address +; multiboot info +mb_magic: + dd 0x00000000 +mb_info_addr: + dd 0x00000000 [SECTION .bss] diff --git a/defs/x86_64-linker.ld b/defs/x86_64-linker.ld index caecb48..39d8876 100644 --- a/defs/x86_64-linker.ld +++ b/defs/x86_64-linker.ld @@ -1,5 +1,10 @@ /* defs for Multiboot headers */ +/* https://www.gnu.org/software/grub/manual/multiboot/multiboot.txt */ MB_MAGIC = 0x1badb002; +/* bit 0 + * all boot modules loaded along with the operating system must be + * aligned on page (4KB) bit 1 must include mem_* structures + */ MB_FLAGS = 0x3; MB_CHKSUM = 0x100000000 - (MB_MAGIC + MB_FLAGS); @@ -9,7 +14,8 @@ SECTIONS .boot : { - header_start = .; LONG(MB_MAGIC) + header_start = .; + LONG(MB_MAGIC) LONG(MB_FLAGS) LONG(MB_CHKSUM) LONG(0) diff --git a/docs/multiboot.txt b/docs/multiboot.txt new file mode 100644 index 0000000..4762e45 --- /dev/null +++ b/docs/multiboot.txt @@ -0,0 +1,45 @@ +https://www.gnu.org/software/grub/manual/multiboot/multiboot.txt + + +-------------------+ +0 | flags | (required) + +-------------------+ +4 | mem_lower | (present if flags[0] is set) +8 | mem_upper | (present if flags[0] is set) + +-------------------+ +12 | boot_device | (present if flags[1] is set) + +-------------------+ +16 | cmdline | (present if flags[2] is set) + +-------------------+ +20 | mods_count | (present if flags[3] is set) +24 | mods_addr | (present if flags[3] is set) + +-------------------+ +28 - 40 | syms | (present if flags[4] or + | | flags[5] is set) + +-------------------+ +44 | mmap_length | (present if flags[6] is set) +48 | mmap_addr | (present if flags[6] is set) + +-------------------+ +52 | drives_length | (present if flags[7] is set) +56 | drives_addr | (present if flags[7] is set) + +-------------------+ +60 | config_table | (present if flags[8] is set) + +-------------------+ +64 | boot_loader_name | (present if flags[9] is set) + +-------------------+ +68 | apm_table | (present if flags[10] is set) + +-------------------+ +72 | vbe_control_info | (present if flags[11] is set) +76 | vbe_mode_info | +80 | vbe_mode | +82 | vbe_interface_seg | +84 | vbe_interface_off | +86 | vbe_interface_len | + +-------------------+ +88 | framebuffer_addr | (present if flags[12] is set) +96 | framebuffer_pitch | +100 | framebuffer_width | +104 | framebuffer_height| +108 | framebuffer_bpp | +109 | framebuffer_type | +110-115 | color_info | + +-------------------+ 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? @@ -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<MultibootInfo> { + 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. + |
