From 67f536d7c6c11be7f10a7f0153e7c44f4c7cc217 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Mon, 28 Jan 2019 11:27:52 +0100 Subject: [PATCH] Add a BootInfoFrameAllocator --- src/memory.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/memory.rs b/src/memory.rs index e20b8781..612f4209 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,3 +1,4 @@ +use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; use x86_64::structures::paging::{ FrameAllocator, Mapper, Page, PageTable, PhysFrame, RecursivePageTable, Size4KiB, }; @@ -20,6 +21,24 @@ pub unsafe fn init(level_4_table_addr: usize) -> RecursivePageTable<'static> { init_inner(level_4_table_addr) } +/// Create a FrameAllocator from the passed memory map +pub fn init_frame_allocator( + memory_map: &'static MemoryMap, +) -> BootInfoFrameAllocator> { + // get usable regions from memory map + let regions = memory_map + .iter() + .filter(|r| r.region_type == MemoryRegionType::Usable); + // map each region to its address range + let addr_ranges = regions.map(|r| r.range.start_addr()..r.range.end_addr()); + // transform to an iterator of frame start addresses + let frame_addresses = addr_ranges.flat_map(|r| r.into_iter().step_by(4096)); + // create `PhysFrame` types from the start addresses + let frames = frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))); + + BootInfoFrameAllocator { frames } +} + /// Returns the physical address for the given virtual address, or `None` if /// the virtual address is not mapped. pub fn translate_addr(addr: u64, recursive_page_table: &RecursivePageTable) -> Option { @@ -53,3 +72,19 @@ impl FrameAllocator for EmptyFrameAllocator { None } } + +pub struct BootInfoFrameAllocator +where + I: Iterator, +{ + frames: I, +} + +impl FrameAllocator for BootInfoFrameAllocator +where + I: Iterator, +{ + fn allocate_frame(&mut self) -> Option { + self.frames.next() + } +}