yggdrasil/kernel/src/arch/i686/boot/multiboot.rs

107 lines
2.5 KiB
Rust

use libk_mm::{
address::{PhysicalAddress, Virtualize},
phys::PhysicalMemoryRegion,
};
use crate::arch::x86::InitrdSource;
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MultibootInfo {
pub flags: u32,
pub mem_lower: u32,
pub mem_upper: u32,
pub boot_device: u32,
pub cmdline: u32,
pub mods_count: u32,
pub mods_addr: u32,
pub syms: [u32; 4],
pub mmap_length: u32,
pub mmap_addr: u32,
// ...
}
#[derive(Clone)]
pub struct MultibootMemoryMapIter<'a> {
multiboot_info: &'a MultibootInfo,
base: usize,
pos: usize,
}
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
pub struct MultibootMemoryMapEntry {
pub size: u32,
pub addr: u64,
pub len: u64,
pub ty: u32,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MultibootModuleEntry {
pub mod_start: u32,
pub mod_end: u32,
pub cmdline: u32,
_pad: u32,
}
impl Iterator for MultibootMemoryMapIter<'_> {
type Item = PhysicalMemoryRegion;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.pos + size_of::<MultibootMemoryMapEntry>()
>= self.multiboot_info.mmap_length as usize
{
return None;
}
let entry: &MultibootMemoryMapEntry =
unsafe { core::mem::transmute(self.base + self.pos) };
self.pos += entry.size as usize + size_of::<u32>();
if !entry.is_available() {
continue;
}
return Some(PhysicalMemoryRegion {
base: PhysicalAddress::from_u64(entry.addr),
size: entry.len.try_into().unwrap(),
});
}
}
}
impl MultibootInfo {
pub fn memory_map_iter(&self) -> MultibootMemoryMapIter {
MultibootMemoryMapIter {
multiboot_info: self,
base: PhysicalAddress::from_u32(self.mmap_addr).virtualize(),
pos: 0,
}
}
pub fn modules(&self) -> &[MultibootModuleEntry] {
let base = PhysicalAddress::from_u32(self.mods_addr).virtualize();
unsafe { core::slice::from_raw_parts(base as *const _, self.mods_count as usize) }
}
}
impl MultibootMemoryMapEntry {
pub fn is_available(&self) -> bool {
self.ty == 1
}
}
impl InitrdSource for MultibootModuleEntry {
fn start(&self) -> PhysicalAddress {
PhysicalAddress::from_u32(self.mod_start)
}
fn end(&self) -> PhysicalAddress {
PhysicalAddress::from_u32(self.mod_end)
}
}