diff --git a/src/main.rs b/src/main.rs index 6391b9e7..c31a92b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,14 +11,14 @@ use core::panic::PanicInfo; entry_point!(kernel_main); fn kernel_main(boot_info: &'static BootInfo) -> ! { - use blog_os::memory; + use blog_os::memory::{self, BootInfoFrameAllocator}; use x86_64::{structures::paging::Page, VirtAddr}; println!("Hello World{}", "!"); blog_os::init(); let mut mapper = unsafe { memory::init(boot_info.physical_memory_offset) }; - let mut frame_allocator = memory::init_frame_allocator(&boot_info.memory_map); + let mut frame_allocator = BootInfoFrameAllocator::init(&boot_info.memory_map); // map a previously unmapped page let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000)); diff --git a/src/memory.rs b/src/memory.rs index e05d9740..2e110fce 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -23,24 +23,6 @@ pub unsafe fn init(physical_memory_offset: u64) -> impl MapperAllSizes { MappedPageTable::new(level_4_table, phys_to_virt) } -/// 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.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 a mutable reference to the active level 4 table. /// /// This function is unsafe because the caller must guarantee that the @@ -83,18 +65,39 @@ impl FrameAllocator for EmptyFrameAllocator { } } -pub struct BootInfoFrameAllocator -where - I: Iterator, -{ - frames: I, +/// A FrameAllocator that returns usable frames from the bootloader's memory map. +pub struct BootInfoFrameAllocator { + memory_map: &'static MemoryMap, + next: usize, } -impl FrameAllocator for BootInfoFrameAllocator -where - I: Iterator, -{ - fn allocate_frame(&mut self) -> Option { - self.frames.next() +impl BootInfoFrameAllocator { + /// Create a FrameAllocator from the passed memory map. + pub fn init(memory_map: &'static MemoryMap) -> Self { + BootInfoFrameAllocator { + memory_map, + next: 0, + } + } + + /// Returns an iterator over the usable frames specified in the memory map. + fn usable_frames(&self) -> impl Iterator { + // get usable regions from memory map + let regions = self.memory_map.iter(); + let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); + // map each region to its address range + let addr_ranges = usable_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.step_by(4096)); + // create `PhysFrame` types from the start addresses + frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) + } +} + +impl FrameAllocator for BootInfoFrameAllocator { + fn allocate_frame(&mut self) -> Option { + let frame = self.usable_frames().nth(self.next); + self.next += 1; + frame } }