107 lines
2.5 KiB
Rust
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)
|
|
}
|
|
}
|