diff --git a/src/arch/x86_64/memory/area_frame_allocator.rs b/src/arch/x86_64/memory/area_frame_allocator.rs
new file mode 100644
index 0000000..1f73ac0
--- /dev/null
+++ b/src/arch/x86_64/memory/area_frame_allocator.rs
@@ -0,0 +1,89 @@
+use arch::x86_64::memory::{Frame, FrameAllocator};
+use multiboot2::{MemoryArea, MemoryAreaIter};
+
+pub struct AreaFrameAllocator {
+ next_free_frame: Frame,
+
+ current_area: Option<&'static MemoryArea>,
+ areas: MemoryAreaIter,
+
+ kernel_start: Frame,
+ kernel_end: Frame,
+ multiboot_start: Frame,
+ multiboot_end: Frame,
+}
+
+impl FrameAllocator for AreaFrameAllocator {
+ fn alloc_frame(&mut self) -> Option {
+ if let Some(area) = self.current_area {
+ // This is the next frame up for allocation
+ let frame = Frame {index: self.next_free_frame.index};
+
+ // Calculate the current area's last frame
+ let current_area_last_frame = {
+ let addr = area.base_addr + area.length - 1;
+ Frame::containing_address(addr as usize)
+ };
+
+ // Check if the frame we're considering is OK; if it is, we'll return it,
+ // if not, we'll update the frame we're looking at and try again.
+ if frame > current_area_last_frame {
+ // If the frame we wanted to allocate is past the end of the current frame,
+ // switch to the next area
+ self.next_area();
+ } else if frame >= self.kernel_start && frame <= self.kernel_end {
+ // The frame under consideration is used by the kernel,
+ // so jump over the kernel code area.
+ self.next_free_frame = self.kernel_end.next_frame();
+ } else if frame >= self.multiboot_start && frame <= self.multiboot_end {
+ // The frame under consideration is used by Multiboot,
+ // so jump over the multiboot area.
+ self.next_free_frame = self.multiboot_end.next_frame();
+ } else {
+ // Frame is unused!
+ self.next_free_frame.index += 1; // We'll consider the next frame next time we need to alloc
+ return Some(frame);
+ }
+ // The frame we were looking at wasn't valid; try again with our updated `next_free_frame`
+ return self.alloc_frame();
+ } else {
+ None // no free frames left!
+ }
+ }
+
+ fn dealloc_frame(&mut self, frame: Frame) {
+ unimplemented!();
+ }
+}
+
+impl AreaFrameAllocator {
+ pub fn new(kernel_start: usize, kernel_end: usize,
+ multiboot_start: usize, multiboot_end: usize,
+ memory_areas: MemoryAreaIter) -> AreaFrameAllocator {
+ let mut allocator = AreaFrameAllocator {
+ next_free_frame: Frame::containing_address(0x0),
+ current_area: None,
+ areas: memory_areas,
+ kernel_start: Frame::containing_address(kernel_start),
+ kernel_end: Frame::containing_address(kernel_end),
+ multiboot_start: Frame::containing_address(multiboot_start),
+ multiboot_end: Frame::containing_address(multiboot_end),
+ };
+ allocator.next_area();
+ allocator
+ }
+
+ fn next_area(&mut self) {
+ self.current_area = self.areas.clone().filter(|area| {
+ let address = area.base_addr + area.length - 1;
+ Frame::containing_address(address as usize) >= self.next_free_frame
+ }).min_by_key(|area| area.base_addr);
+
+ if let Some(area) = self.current_area {
+ let start_frame = Frame::containing_address(area.base_addr as usize);
+ if self.next_free_frame < start_frame {
+ self.next_free_frame = start_frame;
+ }
+ }
+ }
+}
diff --git a/src/arch/x86_64/memory/mod.rs b/src/arch/x86_64/memory/mod.rs
new file mode 100644
index 0000000..35e6853
--- /dev/null
+++ b/src/arch/x86_64/memory/mod.rs
@@ -0,0 +1,40 @@
+//! Memory management for x86_64 platforms.
+//!
+//! Heavly inspired/lovingly ripped off from Phil Oppermann's [os.phil-opp.com](http://os.phil-opp.com/).
+
+mod area_frame_allocator;
+mod paging;
+
+pub use self::area_frame_allocator::AreaFrameAllocator;
+
+/// The physical size of each frame.
+pub const PAGE_SIZE: usize = 4096;
+
+/// A representation of a frame in physical memory.
+#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
+pub struct Frame {
+ index: usize,
+}
+
+impl Frame {
+ /// Retrieves the frame containing a particular physical address.
+ fn containing_address(address: usize) -> Frame {
+ Frame {index: address/PAGE_SIZE}
+ }
+
+ /// Returns the frame after this one.
+ fn next_frame(&self) -> Frame {
+ Frame {index: self.index + 1}
+ }
+
+ fn start_address(&self) -> usize {
+ self.index * PAGE_SIZE
+ }
+}
+
+/// A trait which can be implemented by any frame allocator, to make the frame allocation system
+/// pluggable.
+pub trait FrameAllocator {
+ fn alloc_frame(&mut self) -> Option;
+ fn dealloc_frame(&mut self, frame: Frame);
+}
diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs
index 91f2d96..80f2bd6 100644
--- a/src/arch/x86_64/mod.rs
+++ b/src/arch/x86_64/mod.rs
@@ -1 +1,2 @@
-pub mod device;
\ No newline at end of file
+pub mod device;
+pub mod memory;
diff --git a/src/lib.rs b/src/lib.rs
index 5e98e38..05b0048 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,6 +9,8 @@ extern crate log;
extern crate rlibc;
extern crate spin;
extern crate volatile;
+#[macro_use]
+extern crate bitflags;
extern crate x86;
extern crate multiboot2;