this shit compiles but crashes after fighting for eternity with the borrow checker

This commit is contained in:
Jack Halford 2018-03-01 16:37:26 +01:00
parent 0f5bf89493
commit edfffc3b13
8 changed files with 109 additions and 68 deletions

View file

@ -9,3 +9,7 @@ crate-type = ["staticlib"]
[dependencies] [dependencies]
rlibc = "1.0" rlibc = "1.0"
multiboot2 = { path = "multiboot2-elf64" } multiboot2 = { path = "multiboot2-elf64" }
[dependencies.lazy_static]
version = "0.2.4"
features = ["spin_no_std"]

View file

@ -4,7 +4,7 @@ extern crate multiboot2;
use acpi; use acpi;
use cpuio; use cpuio;
use core::char; use core::char;
use context::CONTEXT; use context::*;
use vga::*; use vga::*;
fn dispatch(command: &str) -> Result <(), &'static str> { fn dispatch(command: &str) -> Result <(), &'static str> {
@ -120,7 +120,7 @@ fn print_stack() -> Result <(), &'static str> {
} }
fn mb2_memory() -> 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() let memory_map_tag = boot_info.memory_map_tag()
.expect("Memory map tag required"); .expect("Memory map tag required");
@ -134,7 +134,8 @@ fn mb2_memory() -> Result <(), &'static str> {
} }
fn mb2_sections() -> 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() let elf_sections_tag = boot_info.elf_sections_tag()
.expect("Elf-sections tag required"); .expect("Elf-sections tag required");
@ -147,7 +148,7 @@ fn mb2_sections() -> Result <(), &'static str> {
} }
fn mb2_info() -> 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() let command_line_tag = boot_info.command_line_tag()
.expect("Elf-sections tag required"); .expect("Elf-sections tag required");

View file

@ -1,22 +1,56 @@
extern crate core; use multiboot2;
use memory;
use vga; use vga;
use cpuio;
pub static mut CONTEXT: Context = Context { pub static mut CONTEXT: Option<Context> = None;
current_term: 0,
boot_info_addr: 0,
vga1: vga::Writer::new(),
vga2: vga::Writer::new(),
};
pub struct Context { pub struct Context {
pub current_term: u8, 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 vga1: vga::Writer,
pub vga2: 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) { pub fn switch_term(&mut self) {
self.current_term = { self.current_term = {
if self.current_term == 0 { 1 } 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"),
}
}
}

View file

@ -1,7 +1,7 @@
extern crate core; extern crate core;
use cpuio; use cpuio;
use context::CONTEXT; use context::*;
const MAX_KEYS: usize = 59; const MAX_KEYS: usize = 59;
const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ const KEYMAP_US: [[u8;2]; MAX_KEYS] = [
@ -93,23 +93,18 @@ pub fn kbd_callback() {
0x38 => {ALT = !is_release}, 0x38 => {ALT = !is_release},
0x1D => {CTRL = !is_release}, 0x1D => {CTRL = !is_release},
0x0F if !is_release => { 0x0F if !is_release => {
CONTEXT.switch_term(); context().switch_term();
CONTEXT.current_term().flush(); context().current_term().flush();
}, },
0x0E if !is_release => { 0x0E if !is_release => {
CONTEXT.current_term().backspace(); context().current_term().backspace();
} }
_ => {} _ => {}
} }
}, },
Some(ascii) if !is_release => { Some(ascii) if !is_release => {
let mut terminal = CONTEXT.current_term(); let sym = if SHIFT { ascii[1] } else { ascii[0] };
if SHIFT { context().current_term().keypress(sym);
terminal.keypress(ascii[1]);
}
else {
terminal.keypress(ascii[0]);
}
}, },
Some(_) => {}, Some(_) => {},
None =>{}, None =>{},

View file

@ -8,6 +8,8 @@
extern crate rlibc; extern crate rlibc;
extern crate multiboot2; //slightly modified fork from official 0.3.2 extern crate multiboot2; //slightly modified fork from official 0.3.2
#[macro_use]
extern crate lazy_static;
/// 80x25 screen and simplistic terminal driver /// 80x25 screen and simplistic terminal driver
#[macro_use] pub mod vga; #[macro_use] pub mod vga;
@ -24,21 +26,15 @@ pub mod acpi;
/// simple area frame allocator implementation /// simple area frame allocator implementation
pub mod memory; 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}; use vga::{Color, ColorCode};
#[no_mangle] #[no_mangle]
pub extern fn kmain(multiboot_information_address: usize) -> ! { pub extern fn kmain(multiboot_info_addr: usize) -> ! {
if let Err(msg) = init_kernel(multiboot_information_address) { unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) };
println!("Kernel initialization has failed: {}", msg); acpi::init().unwrap();
cpuio::halt();
}
set_color!(White, Cyan); set_color!(White, Cyan);
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
format_args!("{: ^80}", r#" ,--, "#), format_args!("{: ^80}", r#" ,--, "#),
@ -57,9 +53,7 @@ pub extern fn kmain(multiboot_information_address: usize) -> ! {
format_args!("{: ^80}", r#" '--' `---' "#)); format_args!("{: ^80}", r#" '--' `---' "#));
set_color!(); set_color!();
unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } context();
unsafe { CONTEXT.vga2.prompt(); }
loop { keyboard::kbd_callback(); } loop { keyboard::kbd_callback(); }
} }

View file

@ -1,7 +1,7 @@
use memory::*; use memory::*;
use multiboot2::{MemoryAreaIter, MemoryArea}; use multiboot2::{MemoryAreaIter, MemoryArea};
pub struct AreaAllocator { pub struct AreaFrameAllocator {
next_free_frame: Frame, next_free_frame: Frame,
current_area: Option<&'static MemoryArea>, current_area: Option<&'static MemoryArea>,
areas: MemoryAreaIter, areas: MemoryAreaIter,
@ -12,10 +12,10 @@ pub struct AreaAllocator {
} }
impl AreaFrameAllocator { impl AreaFrameAllocator {
pub fn new(kernel_start: usize, kernel_end: usize pub fn new(kernel_start: usize, kernel_end: usize,
multiboot_start: usize, multiboot_end: usize multiboot_start: usize, multiboot_end: usize,
memory_areas: MemoryAreaIter) -> AreaAllocator { memory_areas: MemoryAreaIter) -> AreaFrameAllocator {
let mut allocator = AreaAllocator { let mut allocator = AreaFrameAllocator {
next_free_frame: Frame::containing_address(0), next_free_frame: Frame::containing_address(0),
current_area: None, current_area: None,
areas: memory_areas, areas: memory_areas,
@ -23,7 +23,7 @@ impl AreaFrameAllocator {
kernel_end: Frame::containing_address(kernel_end), kernel_end: Frame::containing_address(kernel_end),
multiboot_start: Frame::containing_address(multiboot_start), multiboot_start: Frame::containing_address(multiboot_start),
multiboot_end: Frame::containing_address(multiboot_end), multiboot_end: Frame::containing_address(multiboot_end),
} };
allocator.choose_next_area(); allocator.choose_next_area();
allocator allocator
} }
@ -32,10 +32,10 @@ impl AreaFrameAllocator {
// get next area with free frames // get next area with free frames
self.current_area = self.areas.clone().filter(|area| { self.current_area = self.areas.clone().filter(|area| {
Frame::containing_address(area.end_address()) >= self.next_free_frame 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 { 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 { if self.next_free_frame < start_frame {
self.next_free_frame = start_frame; self.next_free_frame = start_frame;
} }
@ -45,27 +45,31 @@ impl AreaFrameAllocator {
impl FrameAllocator for AreaFrameAllocator { impl FrameAllocator for AreaFrameAllocator {
fn allocate_frame(&mut self) -> Option<Frame> { fn allocate_frame(&mut self) -> Option<Frame> {
if let Some(area) = sef.current_area { if let Some(area) = self.current_area {
let frame = Frame { number: self.next_free_frame.number }, let frame = Frame { number: self.next_free_frame.number };
let current_area_last_frame = Frame::containing_address(area.end_address()); let current_area_last_frame = Frame::containing_address(area.end_address());
if frame > current_area_last_frame { if frame > current_area_last_frame {
// all frames are taken in this area // all frames are taken in this area
self.choose_next_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 // frame used by kernel
self.next_free_frame = Frame { 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 // frame used by multiboot
self.next_free_frame = Frame { self.next_free_frame = Frame {
number: self.multiboot_end.number + 1; number: self.multiboot_end.number + 1,
} }
} else { } else {
self.next_free_frame_number += 1; self.next_free_frame.number += 1;
return Some(Frame); return Some(frame);
} }
} else { None } // try again with next_free_frame
self.allocate_frame()
} else {
None
}
} }
fn deallocate_frame(&mut self, frame: Frame) { fn deallocate_frame(&mut self, frame: Frame) {

View file

@ -1,6 +1,8 @@
pub const PAGE_SIZE: usize = 4096; 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)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Frame { pub struct Frame {

View file

@ -1,11 +1,10 @@
#[macro_use]
pub mod color; pub mod color;
pub use self::color::{Color, ColorCode}; pub use self::color::{Color, ColorCode};
use ::context::CONTEXT; use context::*;
use cpuio; use cpuio;
use ::console; use console;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C)] #[repr(C)]
@ -26,21 +25,21 @@ macro_rules! println {
} }
macro_rules! flush { macro_rules! flush {
() => (unsafe { CONTEXT.current_term().flush() }); () => (context().current_term().flush());
} }
macro_rules! set_color { macro_rules! set_color {
() => (unsafe { CONTEXT.current_term().color_code = () => (context().current_term().color_code =
ColorCode::new(Color::White, Color::Black) }); ColorCode::new(Color::White, Color::Black));
($fg:ident) => (unsafe { CONTEXT.current_term().color_code = ($fg:ident) => (context().current_term().color_code =
ColorCode::new(Color::$fg, Color::Black) }); ColorCode::new(Color::$fg, Color::Black));
($fg:ident, $bg:ident) => (unsafe { CONTEXT.current_term().color_code = ($fg:ident, $bg:ident) => (context().current_term().color_code =
ColorCode::new(Color::$fg, Color::$bg) }); ColorCode::new(Color::$fg, Color::$bg));
} }
pub fn print(args: fmt::Arguments) { pub fn print(args: fmt::Arguments) {
use core::fmt::Write; use core::fmt::Write;
unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; context().current_term().write_fmt(args).unwrap();
} }
extern crate core; extern crate core;