diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 63983b02..8acf6e4c 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -9,3 +9,7 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" multiboot2 = { path = "multiboot2-elf64" } + +[dependencies.lazy_static] +version = "0.2.4" +features = ["spin_no_std"] diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index b43620e8..42566a12 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -4,7 +4,7 @@ extern crate multiboot2; use acpi; use cpuio; use core::char; -use context::CONTEXT; +use context::*; use vga::*; fn dispatch(command: &str) -> Result <(), &'static str> { @@ -120,7 +120,7 @@ fn print_stack() -> Result <(), &'static str> { } fn mb2_memory() -> Result <(), &'static str> { - let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + let boot_info = &context().boot_info; let memory_map_tag = boot_info.memory_map_tag() .expect("Memory map tag required"); @@ -134,7 +134,8 @@ fn mb2_memory() -> Result <(), &'static str> { } fn mb2_sections() -> Result <(), &'static str> { - let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + let boot_info = &context().boot_info; + let elf_sections_tag = boot_info.elf_sections_tag() .expect("Elf-sections tag required"); @@ -147,7 +148,7 @@ fn mb2_sections() -> Result <(), &'static str> { } fn mb2_info() -> Result <(), &'static str> { - let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + let boot_info = &context().boot_info; let command_line_tag = boot_info.command_line_tag() .expect("Elf-sections tag required"); diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 2b6b3b93..418b98d5 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -1,22 +1,56 @@ -extern crate core; - +use multiboot2; +use memory; use vga; +use cpuio; -pub static mut CONTEXT: Context = Context { - current_term: 0, - boot_info_addr: 0, - vga1: vga::Writer::new(), - vga2: vga::Writer::new(), -}; +pub static mut CONTEXT: Option = None; pub struct Context { pub current_term: u8, - pub boot_info_addr: usize, + pub multiboot_start: usize, + pub multiboot_end: usize, + pub kernel_start: usize, + pub kernel_end: usize, + pub boot_info: multiboot2::BootInformation, + pub frame_allocator: memory::AreaFrameAllocator, pub vga1: vga::Writer, pub vga2: vga::Writer, } -impl Context { +impl Context +{ + pub fn new(multiboot_start: usize) -> Context { + let boot_info = multiboot2::load(multiboot_start); + let multiboot_end = multiboot_start + boot_info.total_size(); + + let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); + let memory_map_tag = boot_info.memory_map_tag().unwrap(); + + let kernel_start = elf_sections_tag.sections().map( + |s| s.start_address()) + .min().unwrap() as usize; + let kernel_end = elf_sections_tag.sections().map( + |s| s.start_address() + s.size()) + .max().unwrap() as usize; + + let frame_allocator = memory::AreaFrameAllocator::new( + kernel_start, kernel_end, multiboot_start, + multiboot_end, memory_map_tag.memory_areas()); + + Context { + current_term: 0, + multiboot_start, + multiboot_end, + kernel_start, + kernel_end, + boot_info, + frame_allocator, + vga1: vga::Writer::new(), + vga2: vga::Writer::new(), + } + } + + pub fn switch_term(&mut self) { self.current_term = { if self.current_term == 0 { 1 } @@ -33,3 +67,11 @@ impl Context { } } +pub fn context() -> Context { + unsafe { + match CONTEXT.take() { + Some(context) => context, + None => panic!("heeelp"), + } + } +} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index e9832de5..7084495a 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,7 +1,7 @@ extern crate core; use cpuio; -use context::CONTEXT; +use context::*; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ @@ -93,23 +93,18 @@ pub fn kbd_callback() { 0x38 => {ALT = !is_release}, 0x1D => {CTRL = !is_release}, 0x0F if !is_release => { - CONTEXT.switch_term(); - CONTEXT.current_term().flush(); + context().switch_term(); + context().current_term().flush(); }, 0x0E if !is_release => { - CONTEXT.current_term().backspace(); + context().current_term().backspace(); } _ => {} } }, Some(ascii) if !is_release => { - let mut terminal = CONTEXT.current_term(); - if SHIFT { - terminal.keypress(ascii[1]); - } - else { - terminal.keypress(ascii[0]); - } + let sym = if SHIFT { ascii[1] } else { ascii[0] }; + context().current_term().keypress(sym); }, Some(_) => {}, None =>{}, diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 69fbe349..abb9a3b2 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -8,6 +8,8 @@ extern crate rlibc; extern crate multiboot2; //slightly modified fork from official 0.3.2 +#[macro_use] +extern crate lazy_static; /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; @@ -24,21 +26,15 @@ pub mod acpi; /// simple area frame allocator implementation pub mod memory; -use context::CONTEXT; +use context::*; -fn init_kernel(multiboot_information_address: usize) -> Result <(), &'static str> { - unsafe { CONTEXT.boot_info_addr = multiboot_information_address }; - acpi::init()?; - Ok(()) -} use vga::{Color, ColorCode}; #[no_mangle] -pub extern fn kmain(multiboot_information_address: usize) -> ! { - if let Err(msg) = init_kernel(multiboot_information_address) { - println!("Kernel initialization has failed: {}", msg); - cpuio::halt(); - } +pub extern fn kmain(multiboot_info_addr: usize) -> ! { + unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; + acpi::init().unwrap(); + set_color!(White, Cyan); print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", format_args!("{: ^80}", r#" ,--, "#), @@ -57,9 +53,7 @@ pub extern fn kmain(multiboot_information_address: usize) -> ! { format_args!("{: ^80}", r#" '--' `---' "#)); set_color!(); - unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } - unsafe { CONTEXT.vga2.prompt(); } - + context(); loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs index 4ce96334..09304cb6 100644 --- a/kernel-rs/src/memory/area_allocator.rs +++ b/kernel-rs/src/memory/area_allocator.rs @@ -1,7 +1,7 @@ use memory::*; use multiboot2::{MemoryAreaIter, MemoryArea}; -pub struct AreaAllocator { +pub struct AreaFrameAllocator { next_free_frame: Frame, current_area: Option<&'static MemoryArea>, areas: MemoryAreaIter, @@ -12,10 +12,10 @@ pub struct AreaAllocator { } impl AreaFrameAllocator { - pub fn new(kernel_start: usize, kernel_end: usize - multiboot_start: usize, multiboot_end: usize - memory_areas: MemoryAreaIter) -> AreaAllocator { - let mut allocator = AreaAllocator { + 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, @@ -23,7 +23,7 @@ impl AreaFrameAllocator { 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 } @@ -32,10 +32,10 @@ impl AreaFrameAllocator { // get next area with free frames self.current_area = self.areas.clone().filter(|area| { Frame::containing_address(area.end_address()) >= self.next_free_frame - }).min_by_key(|area| area.start_addr()); + }).min_by_key(|area| area.start_address()); if let Some(area) = self.current_area { - let start_frame = Frame::containing_address(area.start_addr()); + let start_frame = Frame::containing_address(area.start_address()); if self.next_free_frame < start_frame { self.next_free_frame = start_frame; } @@ -45,27 +45,31 @@ impl AreaFrameAllocator { impl FrameAllocator for AreaFrameAllocator { fn allocate_frame(&mut self) -> Option { - if let Some(area) = sef.current_area { - let frame = Frame { number: self.next_free_frame.number }, + if let Some(area) = self.current_area { + let frame = Frame { number: self.next_free_frame.number }; let current_area_last_frame = Frame::containing_address(area.end_address()); if frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); - } else if frame >= self.kernel_start && frame <= kernel_end { + } else if frame >= self.kernel_start && frame <= self.kernel_end { // frame used by kernel self.next_free_frame = Frame { - number: self.kernel_end.number + 1; + number: self.kernel_end.number + 1, } - } else if frame >= self.multiboot_start && frame <= multiboot_end { + } else if frame >= self.multiboot_start && frame <= self.multiboot_end { // frame used by multiboot self.next_free_frame = Frame { - number: self.multiboot_end.number + 1; + number: self.multiboot_end.number + 1, } } else { - self.next_free_frame_number += 1; - return Some(Frame); + self.next_free_frame.number += 1; + return Some(frame); } - } else { None } + // try again with next_free_frame + self.allocate_frame() + } else { + None + } } fn deallocate_frame(&mut self, frame: Frame) { diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 667a07cf..aa2b620e 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,6 +1,8 @@ pub const PAGE_SIZE: usize = 4096; -// pub use self::area_allocator::*; +mod area_allocator; + +pub use self::area_allocator::*; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Frame { diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index c448f91c..fa2efba8 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,11 +1,10 @@ -#[macro_use] pub mod color; pub use self::color::{Color, ColorCode}; -use ::context::CONTEXT; +use context::*; use cpuio; -use ::console; +use console; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -26,21 +25,21 @@ macro_rules! println { } macro_rules! flush { - () => (unsafe { CONTEXT.current_term().flush() }); + () => (context().current_term().flush()); } macro_rules! set_color { - () => (unsafe { CONTEXT.current_term().color_code = - ColorCode::new(Color::White, Color::Black) }); - ($fg:ident) => (unsafe { CONTEXT.current_term().color_code = - ColorCode::new(Color::$fg, Color::Black) }); - ($fg:ident, $bg:ident) => (unsafe { CONTEXT.current_term().color_code = - ColorCode::new(Color::$fg, Color::$bg) }); + () => (context().current_term().color_code = + ColorCode::new(Color::White, Color::Black)); + ($fg:ident) => (context().current_term().color_code = + ColorCode::new(Color::$fg, Color::Black)); + ($fg:ident, $bg:ident) => (context().current_term().color_code = + ColorCode::new(Color::$fg, Color::$bg)); } pub fn print(args: fmt::Arguments) { use core::fmt::Write; - unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; + context().current_term().write_fmt(args).unwrap(); } extern crate core;