Skip to content

Commit

Permalink
safer setposition macro
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Gubler committed Jun 7, 2018
1 parent 6175bfe commit 46a67a4
Show file tree
Hide file tree
Showing 14 changed files with 552 additions and 27 deletions.
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ crate-type = ["staticlib"]
rlibc = "1.0"
volatile = "0.1.0"
spin = "0.4.5"
multiboot2 = "0.1.0"
multiboot2 = "0.1.0"
bitflags = "0.9.1"
x86_64 = "0.1.2"
Binary file modified build/arch/x86_64/boot.o
Binary file not shown.
Binary file modified build/kernel-x86_64.bin
Binary file not shown.
Binary file modified build/os-x86_64.iso
Binary file not shown.
3 changes: 3 additions & 0 deletions src/arch/x86_64/boot.asm
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ start:
hlt

setup_page_tables:
mov eax, p4_table
or eax, 0b11 ; present + writable
mov [p4_table + 511 * 8], eax
; map first P4 entry to P3 table
mov eax, p3_table
or eax, 0b11 ; present + writable
Expand Down
1 change: 1 addition & 0 deletions src/graphics/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

52 changes: 32 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
#![feature(lang_items)]
#![no_std]
#![feature(unique)]
#![feature(const_fn)]
#![feature(const_unique_new)]
#![feature(unique)]
#![no_std]
#![feature(ptr_internals)]
//All external dependencies

extern crate multiboot2;
extern crate rlibc;
extern crate spin;
extern crate volatile;
use vga_buffer::*;
#[macro_use]
extern crate bitflags;
extern crate x86_64;

#[macro_use]
mod vga_buffer;
mod graphics;
mod memory;
use graphics::*;
use memory::*;
use vga_buffer::*;

#[no_mangle]
pub extern "C" fn rust_main(multiboot_information_address: usize) {
vga_buffer::clear_screen();
println!("Hello World{}", "!");
setcolor!(&13);
println!("Second Hello World");
setposition!(78, 24, 'H');
setposition!(79, 24, 'I');

let boot_info = unsafe { multiboot2::load(multiboot_information_address) };
let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");

Expand All @@ -25,49 +40,46 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
area.base_addr, area.length
);
}

let elf_sections_tag = boot_info
.elf_sections_tag()
.expect("Elf-sections tag required");

println!("kernel sections:");
for section in elf_sections_tag.sections() {
println!(
/*println!(
" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}",
section.addr, section.size, section.flags
);
);*/
}

let kernel_start = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
let kernel_end = elf_sections_tag
.sections()
.map(|s| s.addr + s.size)
.max()
.unwrap();

let multiboot_start = multiboot_information_address;
let multiboot_end = multiboot_start + (boot_info.total_size as usize);

println!("Kernel start: {}, Kernel end: {}", kernel_start, kernel_end);
println!(
"Multiboot start: {}, Multiboot end: {}",
multiboot_start, multiboot_end
let mut frame_allocator = memory::AreaFrameAllocator::new(
kernel_start as usize,
kernel_end as usize,
multiboot_start,
multiboot_end,
memory_map_tag.memory_areas(),
);
setcolor!(Color::White, Color::Black);
println!("Hello, {}", "it's me");
setcolor!(Color::Green, Color::White);
println!("Hello, {}", "it's me");
setposition!(0, 0, ' ');

memory::test_paging(&mut frame_allocator);
loop {}
}

#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn eh_personality() {}
extern "C" fn eh_personality() {}

#[lang = "panic_fmt"]
#[no_mangle]
pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
println!("\n\nNeblogOS is panicking in {} at line {}:", file, line);
println!("\n\nNEBLOGOS IS PANICKING in {} at line {}:", file, line);
println!(" {}", fmt);
loop {}
}
96 changes: 96 additions & 0 deletions src/memory/area_frame_allocator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use 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 allocate_frame(&mut self) -> Option<Frame> {
if let Some(area) = self.current_area {
// "Clone" the frame to return it if it's free. Frame doesn't
// implement Clone, but we can construct an identical frame.
let frame = Frame {
number: self.next_free_frame.number,
};

// the last frame of the current area
let current_area_last_frame = {
let address = area.base_addr + area.length - 1;
Frame::containing_address(address as usize)
};

if frame > current_area_last_frame {
// all frames of current area are used, switch to next area
self.choose_next_area();
} else if frame >= self.kernel_start && frame <= self.kernel_end {
// `frame` is used by the kernel
self.next_free_frame = Frame {
number: self.kernel_end.number + 1,
};
} else if frame >= self.multiboot_start && frame <= self.multiboot_end {
// `frame` is used by the multiboot information structure
self.next_free_frame = Frame {
number: self.multiboot_end.number + 1,
};
} else {
// frame is unused, increment `next_free_frame` and return it
self.next_free_frame.number += 1;
return Some(frame);
}
// `frame` was not valid, try it again with the updated `next_free_frame`
self.allocate_frame()
} else {
None // no free frames left
}
}

fn deallocate_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(0),
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.choose_next_area();
allocator
}

fn choose_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;
}
}
}
}
30 changes: 30 additions & 0 deletions src/memory/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
pub use self::area_frame_allocator::AreaFrameAllocator;
pub use self::paging::test_paging;
use self::paging::PhysicalAddress;

mod area_frame_allocator;
mod paging;

pub const PAGE_SIZE: usize = 4096;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Frame {
number: usize,
}

impl Frame {
fn containing_address(address: usize) -> Frame {
Frame {
number: address / PAGE_SIZE,
}
}

fn start_address(&self) -> PhysicalAddress {
self.number * PAGE_SIZE
}
}

pub trait FrameAllocator {
fn allocate_frame(&mut self) -> Option<Frame>;
fn deallocate_frame(&mut self, frame: Frame);
}
47 changes: 47 additions & 0 deletions src/memory/paging/entry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use memory::Frame;

pub struct Entry(u64);

impl Entry {
pub fn is_unused(&self) -> bool {
self.0 == 0
}

pub fn set_unused(&mut self) {
self.0 = 0;
}

pub fn flags(&self) -> EntryFlags {
EntryFlags::from_bits_truncate(self.0)
}

pub fn pointed_frame(&self) -> Option<Frame> {
if self.flags().contains(PRESENT) {
Some(Frame::containing_address(
self.0 as usize & 0x000fffff_fffff000,
))
} else {
None
}
}

pub fn set(&mut self, frame: Frame, flags: EntryFlags) {
assert!(frame.start_address() & !0x000fffff_fffff000 == 0);
self.0 = (frame.start_address() as u64) | flags.bits();
}
}

bitflags! {
pub struct EntryFlags: u64 {
const PRESENT = 1 << 0;
const WRITABLE = 1 << 1;
const USER_ACCESSIBLE = 1 << 2;
const WRITE_THROUGH = 1 << 3;
const NO_CACHE = 1 << 4;
const ACCESSED = 1 << 5;
const DIRTY = 1 << 6;
const HUGE_PAGE = 1 << 7;
const GLOBAL = 1 << 8;
const NO_EXECUTE = 1 << 63;
}
}

0 comments on commit 46a67a4

Please sign in to comment.