heap allocator in place, no free yet
This commit is contained in:
parent
36b51236b3
commit
3dfc440d20
10 changed files with 247 additions and 185 deletions
2
kernel-rs/Xargo.toml
Normal file
2
kernel-rs/Xargo.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[target.x86-bluesnow.dependencies]
|
||||
alloc = {}
|
||||
|
|
@ -3,24 +3,28 @@ extern crate core;
|
|||
|
||||
use acpi;
|
||||
use cpuio;
|
||||
use context;
|
||||
use memory;
|
||||
use x86;
|
||||
use core::char;
|
||||
use vga::*;
|
||||
|
||||
fn dispatch(command: &str) -> Result <(), &'static str> {
|
||||
match command {
|
||||
"acpi" => self::acpi_info(),
|
||||
"help" | "h" => self::help(),
|
||||
"memory" => self::mb2_memory(),
|
||||
"multiboot" => self::mb2_info(),
|
||||
|
||||
// multiboot
|
||||
// "memory" => self::mb2_memory(),
|
||||
// "multiboot" => self::mb2_info(),
|
||||
// "sections" => self::mb2_sections(),
|
||||
|
||||
// ACPI
|
||||
"acpi" => self::acpi_info(),
|
||||
"reboot" => self::reboot(),
|
||||
"sections" => self::mb2_sections(),
|
||||
"shutdown" | "halt" | "q" => self::shutdown(),
|
||||
|
||||
// others
|
||||
"stack" => self::print_stack(),
|
||||
"test" => self::test(),
|
||||
"regs" => self::regs(),
|
||||
|
||||
_ => Err("Command unknown. (h|help for help)"),
|
||||
}
|
||||
}
|
||||
|
|
@ -48,12 +52,6 @@ fn help() -> Result <(), &'static str> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn test() -> Result<(), &'static str>
|
||||
{
|
||||
memory::test_paging(context::frame_allocator());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reboot the kernel
|
||||
///
|
||||
/// If reboot failed, will loop on a halt cmd
|
||||
|
|
@ -129,49 +127,49 @@ fn print_stack() -> Result <(), &'static str> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn mb2_memory() -> Result <(), &'static str> {
|
||||
let boot_info = context::boot_info();
|
||||
// fn mb2_memory() -> Result <(), &'static str> {
|
||||
// let boot_info = context::boot_info();
|
||||
|
||||
let memory_map_tag = boot_info.memory_map_tag()
|
||||
.expect("Memory map tag required");
|
||||
// let memory_map_tag = boot_info.memory_map_tag()
|
||||
// .expect("Memory map tag required");
|
||||
|
||||
println!("memory areas:");
|
||||
for area in memory_map_tag.memory_areas() {
|
||||
println!(" start: 0x{:x}, length: 0x{:x}",
|
||||
area.start_address(), area.size());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// println!("memory areas:");
|
||||
// for area in memory_map_tag.memory_areas() {
|
||||
// println!(" start: 0x{:x}, length: 0x{:x}",
|
||||
// area.start_address(), area.size());
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
fn mb2_sections() -> Result <(), &'static str> {
|
||||
let boot_info = context::boot_info();
|
||||
// fn mb2_sections() -> Result <(), &'static str> {
|
||||
// let boot_info = context::boot_info();
|
||||
|
||||
let elf_sections_tag = boot_info.elf_sections_tag()
|
||||
.expect("Elf-sections tag required");
|
||||
// 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!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}",
|
||||
section.name(), section.start_address(), section.size(), section.flags());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// println!("kernel sections:");
|
||||
// for section in elf_sections_tag.sections() {
|
||||
// println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}",
|
||||
// section.name(), section.start_address(), section.size(), section.flags());
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
fn mb2_info() -> Result <(), &'static str> {
|
||||
let boot_info = context::boot_info();
|
||||
// fn mb2_info() -> Result <(), &'static str> {
|
||||
// let boot_info = context::boot_info();
|
||||
|
||||
let command_line_tag = boot_info.command_line_tag()
|
||||
.expect("Elf-sections tag required");
|
||||
// let command_line_tag = boot_info.command_line_tag()
|
||||
// .expect("Elf-sections tag required");
|
||||
|
||||
let bootloader_tag = boot_info.boot_loader_name_tag()
|
||||
.expect("Elf-sections tag required");
|
||||
// let bootloader_tag = boot_info.boot_loader_name_tag()
|
||||
// .expect("Elf-sections tag required");
|
||||
|
||||
println!("bootloader: {}", bootloader_tag.name());
|
||||
if command_line_tag.command_line().len() != 0 {
|
||||
println!("command line: {}", command_line_tag.command_line());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// println!("bootloader: {}", bootloader_tag.name());
|
||||
// if command_line_tag.command_line().len() != 0 {
|
||||
// println!("command line: {}", command_line_tag.command_line());
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn acpi_info() -> Result <(), &'static str> {
|
||||
acpi::info()?;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ pub static mut CONTEXT: Option<Context> = None;
|
|||
|
||||
pub struct Context {
|
||||
pub current_term: u8,
|
||||
pub boot_info: multiboot2::BootInformation,
|
||||
pub frame_allocator: memory::AreaFrameAllocator,
|
||||
pub vga1: vga::Writer,
|
||||
pub vga2: vga::Writer,
|
||||
}
|
||||
|
|
@ -15,94 +13,14 @@ pub struct Context {
|
|||
impl Context
|
||||
{
|
||||
pub fn new(multiboot_start: usize) -> Context {
|
||||
let boot_info = unsafe { 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());
|
||||
|
||||
let vga1 = vga::Writer::new();
|
||||
let vga2 = vga::Writer::new();
|
||||
|
||||
Context {
|
||||
current_term: 0,
|
||||
boot_info,
|
||||
frame_allocator,
|
||||
vga1,
|
||||
vga2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_screen() {
|
||||
set_color!(White, Cyan);
|
||||
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
format_args!("{: ^80}", r#" ,--, "#),
|
||||
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
|
||||
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
|
||||
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
|
||||
format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
|
||||
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
|
||||
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
|
||||
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
|
||||
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
|
||||
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
|
||||
format_args!("{: ^80}", r#" ' ; |./__; : "#),
|
||||
format_args!("{: ^80}", r#" | : ;| : .' "#),
|
||||
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
|
||||
format_args!("{: ^80}", r#" '--' `---' "#));
|
||||
set_color!();
|
||||
context().vga1.prompt();
|
||||
context().vga2.prompt();
|
||||
context().vga1.flush();
|
||||
}
|
||||
|
||||
pub fn frame_allocator() -> &'static mut memory::AreaFrameAllocator {
|
||||
&mut context().frame_allocator
|
||||
}
|
||||
|
||||
pub fn boot_info() -> &'static multiboot2::BootInformation {
|
||||
&context().boot_info
|
||||
}
|
||||
|
||||
pub fn switch_term() {
|
||||
context().current_term = {
|
||||
if context().current_term == 0 { 1 }
|
||||
else { 0 }
|
||||
};
|
||||
}
|
||||
|
||||
pub fn current_term() -> &'static mut vga::Writer{
|
||||
if context().current_term == 0 {
|
||||
&mut context().vga1
|
||||
} else {
|
||||
&mut context().vga2
|
||||
}
|
||||
}
|
||||
|
||||
fn context() -> &'static mut Context {
|
||||
unsafe {
|
||||
match CONTEXT {
|
||||
Some(ref mut x) => &mut *x,
|
||||
None => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(multiboot_info_addr: usize) {
|
||||
unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) };
|
||||
|
||||
memory::remap_the_kernel(frame_allocator(), boot_info());
|
||||
self::init_screen();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
extern crate core;
|
||||
|
||||
use cpuio;
|
||||
use context;
|
||||
use vga;
|
||||
|
||||
const MAX_KEYS: usize = 59;
|
||||
const KEYMAP_US: [[u8;2]; MAX_KEYS] = [
|
||||
|
|
@ -91,19 +91,20 @@ pub fn kbd_callback() {
|
|||
0x2A | 0x36 => {SHIFT = !is_release},
|
||||
0x38 => {ALT = !is_release},
|
||||
0x1D => {CTRL = !is_release},
|
||||
0x0F if !is_release => {
|
||||
context::switch_term();
|
||||
context::current_term().flush();
|
||||
},
|
||||
// terminal switching
|
||||
// 0x0F if !is_release => {
|
||||
// context::switch_term();
|
||||
// context::current_term().flush();
|
||||
// },
|
||||
0x0E if !is_release => {
|
||||
context::current_term().backspace();
|
||||
vga::VGA.backspace();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
Some(ascii) if !is_release => {
|
||||
let sym = if SHIFT { ascii[1] } else { ascii[0] };
|
||||
context::current_term().keypress(sym);
|
||||
vga::VGA.keypress(sym);
|
||||
},
|
||||
Some(_) => {},
|
||||
None =>{},
|
||||
|
|
|
|||
|
|
@ -5,15 +5,17 @@
|
|||
#![feature(const_fn)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(asm)]
|
||||
#![feature(alloc)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(global_allocator)]
|
||||
|
||||
extern crate rlibc;
|
||||
extern crate multiboot2; //slightly modified fork from official 0.3.2
|
||||
extern crate multiboot2;
|
||||
#[macro_use] extern crate bitflags;
|
||||
#[macro_use] extern crate alloc;
|
||||
|
||||
/// 80x25 screen and simplistic terminal driver
|
||||
#[macro_use] pub mod vga;
|
||||
/// kernel init and environment
|
||||
pub mod context;
|
||||
/// PS/2 detection and processing
|
||||
pub mod keyboard;
|
||||
/// simplisitc kernel commands
|
||||
|
|
@ -24,17 +26,37 @@ pub mod cpuio;
|
|||
pub mod acpi;
|
||||
/// physical frame allocator + paging module
|
||||
pub mod memory;
|
||||
/// a few x86 instruction wrappers
|
||||
/// a few x86 register and instruction wrappers
|
||||
pub mod x86;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn kmain(multiboot_info_addr: usize) -> ! {
|
||||
context::init(multiboot_info_addr);
|
||||
// println!("init done!");
|
||||
// acpi::init().unwrap();
|
||||
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
||||
enable_write_protect_bit();
|
||||
|
||||
vga::init();
|
||||
memory::init(&boot_info);
|
||||
|
||||
use alloc::boxed::Box;
|
||||
let mut heap_test = Box::new(42);
|
||||
*heap_test -= 15;
|
||||
let heap_test2 = Box::new("Hello");
|
||||
println!("{:?} {:?}", heap_test, heap_test2);
|
||||
|
||||
let mut vec_test = vec![1,2,3,4,5,6,7];
|
||||
vec_test[3] = 42;
|
||||
for i in &vec_test {
|
||||
print!("{} ", i);
|
||||
}
|
||||
|
||||
loop { keyboard::kbd_callback(); }
|
||||
}
|
||||
|
||||
fn enable_write_protect_bit() {
|
||||
unsafe { x86::cr0_write(x86::cr0() | (1 << 16)) };
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"] #[no_mangle]
|
||||
pub extern fn eh_personality() {
|
||||
|
||||
|
|
@ -51,3 +73,11 @@ pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32
|
|||
|
||||
}
|
||||
|
||||
use memory::BumpAllocator;
|
||||
|
||||
pub const HEAP_START: usize = (1 << 22); //first entry of p2
|
||||
pub const HEAP_SIZE: usize = 100 * 1024; //100 KiB
|
||||
|
||||
#[global_allocator]
|
||||
static HEAP_ALLOCATOR: BumpAllocator = BumpAllocator::new(HEAP_START,
|
||||
HEAP_START + HEAP_SIZE);
|
||||
|
|
|
|||
60
kernel-rs/src/memory/heap_allocator.rs
Normal file
60
kernel-rs/src/memory/heap_allocator.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use alloc::heap::{Alloc, AllocErr, Layout};
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BumpAllocator {
|
||||
heap_start: usize,
|
||||
heap_end: usize,
|
||||
next: AtomicUsize,
|
||||
}
|
||||
|
||||
impl BumpAllocator {
|
||||
pub const fn new(heap_start: usize, heap_end: usize) -> Self {
|
||||
Self { heap_start, heap_end, next: AtomicUsize::new(heap_start) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> Alloc for &'a BumpAllocator {
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||
loop {
|
||||
// load current state of the `next` field
|
||||
let current_next = self.next.load(Ordering::Relaxed);
|
||||
let alloc_start = align_up(current_next, layout.align());
|
||||
let alloc_end = alloc_start.saturating_add(layout.size());
|
||||
|
||||
if alloc_end <= self.heap_end {
|
||||
// update the `next` pointer if it still has the value `current_next`
|
||||
let next_now = self.next.compare_and_swap(current_next, alloc_end,
|
||||
Ordering::Relaxed);
|
||||
if next_now == current_next {
|
||||
return Ok(alloc_start as *mut u8);
|
||||
}
|
||||
} else {
|
||||
return Err(AllocErr::Exhausted{ request: layout })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&mut self, pt: *mut u8, layout: Layout) {
|
||||
// TODO
|
||||
// do nothing, leak memory
|
||||
}
|
||||
}
|
||||
|
||||
/// Align downwards. Returns the greatest x with alignment `align`
|
||||
/// so that x <= addr. The alignment must be a power of 2.
|
||||
pub fn align_down(addr: usize, align: usize) -> usize {
|
||||
if align.is_power_of_two() {
|
||||
addr & !(align - 1)
|
||||
} else if align == 0 {
|
||||
addr
|
||||
} else {
|
||||
panic!("`align` must be a power of 2");
|
||||
}
|
||||
}
|
||||
|
||||
/// Align upwards. Returns the smallest x with alignment `align`
|
||||
/// so that x >= addr. The alignment must be a power of 2.
|
||||
pub fn align_up(addr: usize, align: usize) -> usize {
|
||||
align_down(addr + align - 1, align)
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
pub const PAGE_SIZE: usize = 4096;
|
||||
|
||||
mod area_allocator;
|
||||
mod heap_allocator;
|
||||
mod paging;
|
||||
|
||||
pub use self::area_allocator::*;
|
||||
pub use self::paging::test_paging;
|
||||
pub use self::heap_allocator::*;
|
||||
pub use self::paging::remap_the_kernel;
|
||||
use self::paging::PhysicalAddress;
|
||||
use multiboot2;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Frame {
|
||||
|
|
@ -57,3 +59,36 @@ impl Iterator for FrameIter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// memory initialisation should only be called once
|
||||
pub fn init(boot_info: &multiboot2::BootInformation) {
|
||||
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()
|
||||
.filter(|s| s.is_allocated())
|
||||
.map(|s| s.start_address())
|
||||
.min().unwrap();
|
||||
|
||||
let kernel_end = elf_sections_tag.sections()
|
||||
.filter(|s| s.is_allocated())
|
||||
.map(|s| s.start_address() + s.size())
|
||||
.max().unwrap();
|
||||
|
||||
let mut frame_allocator = self::AreaFrameAllocator::new(
|
||||
kernel_start as usize, kernel_end as usize,
|
||||
boot_info.start_address(), boot_info.start_address(),
|
||||
memory_map_tag.memory_areas());
|
||||
|
||||
let mut active_table = paging::remap_the_kernel(&mut frame_allocator,
|
||||
boot_info);
|
||||
use self::paging::Page;
|
||||
use {HEAP_START, HEAP_SIZE};
|
||||
|
||||
let heap_start_page = Page::containing_address(HEAP_START);
|
||||
let heap_end_page = Page::containing_address(HEAP_START + HEAP_SIZE - 1);
|
||||
|
||||
for page in Page::range_inclusive(heap_start_page, heap_end_page) {
|
||||
active_table.map(page, paging::EntryFlags::WRITABLE, &mut frame_allocator);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const ENTRY_COUNT: usize = 1024;
|
|||
pub type PhysicalAddress = usize;
|
||||
pub type VirtualAddress = usize;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Page {
|
||||
number: usize,
|
||||
}
|
||||
|
|
@ -46,6 +46,33 @@ impl Page {
|
|||
fn p1_index(&self) -> usize {
|
||||
(self.number >> 0) & 0x3ff
|
||||
}
|
||||
|
||||
pub fn range_inclusive(start: Page, end: Page) -> PageIter {
|
||||
PageIter {
|
||||
start,
|
||||
end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PageIter {
|
||||
start: Page,
|
||||
end: Page,
|
||||
}
|
||||
|
||||
impl Iterator for PageIter {
|
||||
type Item = Page;
|
||||
|
||||
fn next(&mut self) -> Option<Page> {
|
||||
if self.start <= self.end {
|
||||
let page = self.start;
|
||||
self.start.number += 1;
|
||||
Some(page)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ActivePageTable {
|
||||
|
|
@ -99,14 +126,12 @@ impl ActivePageTable {
|
|||
|
||||
let p2_frame = Frame::containing_address(x86::cr3() as usize);
|
||||
|
||||
println!("old p2_frame at {}", p2_frame.number);
|
||||
let old_table = InactivePageTable {
|
||||
p2_frame,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let frame = Frame::containing_address(new_table.p2_frame.start_address());
|
||||
println!("new p2_frame at {:#x}", new_table.p2_frame.start_address());
|
||||
x86::cr3_write(frame.start_address());
|
||||
}
|
||||
|
||||
|
|
@ -166,9 +191,6 @@ pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation)
|
|||
assert!(section.start_address() % PAGE_SIZE as u64 == 0,
|
||||
"sections need to be page aligned");
|
||||
|
||||
println!("mapping section at addr: {:#x}, size: {:#x}",
|
||||
section.start_address(), section.size());
|
||||
|
||||
let flags = EntryFlags::from_elf_section_flags(§ion);
|
||||
let start_frame = Frame::containing_address(section.start_address() as usize);
|
||||
let end_frame = Frame::containing_address(section.end_address() as usize - 1);
|
||||
|
|
@ -192,31 +214,5 @@ pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation)
|
|||
|
||||
active_table.unmap(old_p2_page, allocator);
|
||||
|
||||
println!("guard page at {:#x}", old_p2_page.start_address());
|
||||
println!("cr3 = {:#x}", x86::cr3());
|
||||
|
||||
active_table
|
||||
}
|
||||
|
||||
pub fn test_paging<A>(allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
{
|
||||
let mut page_table = unsafe { ActivePageTable::new() };
|
||||
|
||||
let addr = 0xffff_f000;
|
||||
let page = Page::containing_address(addr);
|
||||
let frame = allocator.allocate_frame().expect("no more frames");
|
||||
println!("None = {:?}, map to {:?}",
|
||||
page_table.translate(addr),
|
||||
frame);
|
||||
println!("check 0");
|
||||
flush!();
|
||||
page_table.map_to(page, frame, EntryFlags::empty(), allocator);
|
||||
println!("check 1");
|
||||
flush!();
|
||||
println!("Some = {:?}", page_table.translate(addr));
|
||||
flush!();
|
||||
println!("next free frame: {:?}", allocator.allocate_frame());
|
||||
flush!();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ impl<L> Table<L> where L: HierarchicalLevel
|
|||
where A: FrameAllocator
|
||||
{
|
||||
if self.next_table(index).is_none() {
|
||||
println!("index={} flags={:#b}", index, self[index].flags());
|
||||
assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE),
|
||||
"mapping code does not support huge pages");
|
||||
let frame = allocator.allocate_frame().expect("no frames available");
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ pub mod color;
|
|||
|
||||
pub use self::color::{Color, ColorCode};
|
||||
|
||||
use context;
|
||||
use cpuio;
|
||||
use console;
|
||||
|
||||
pub static mut VGA: Writer = self::Writer::new();
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct ScreenChar {
|
||||
|
|
@ -25,21 +26,21 @@ macro_rules! println {
|
|||
}
|
||||
|
||||
macro_rules! flush {
|
||||
() => ($crate::context::current_term().flush());
|
||||
() => (unsafe { $crate::vga::VGA.flush() });
|
||||
}
|
||||
|
||||
macro_rules! set_color {
|
||||
() => ($crate::context::current_term().color_code =
|
||||
$crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black));
|
||||
($fg:ident) => ($crate::context::current_term().color_code =
|
||||
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black));
|
||||
($fg:ident, $bg:ident) => ($crate::context::current_term().color_code =
|
||||
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg));
|
||||
() => (unsafe { $crate::vga::VGA.color_code =
|
||||
$crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)} );
|
||||
($fg:ident) => (unsafe { $crate::vga::VGA.color_code =
|
||||
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)} );
|
||||
($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code =
|
||||
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} );
|
||||
}
|
||||
|
||||
pub fn print(args: fmt::Arguments) {
|
||||
use core::fmt::Write;
|
||||
context::current_term().write_fmt(args).unwrap();
|
||||
unsafe { self::VGA.write_fmt(args).unwrap(); }
|
||||
}
|
||||
|
||||
extern crate core;
|
||||
|
|
@ -195,3 +196,25 @@ impl fmt::Write for Writer {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
set_color!(White, Cyan);
|
||||
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
format_args!("{: ^80}", r#" ,--, "#),
|
||||
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
|
||||
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
|
||||
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
|
||||
format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
|
||||
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
|
||||
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
|
||||
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
|
||||
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
|
||||
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
|
||||
format_args!("{: ^80}", r#" ' ; |./__; : "#),
|
||||
format_args!("{: ^80}", r#" | : ;| : .' "#),
|
||||
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
|
||||
format_args!("{: ^80}", r#" '--' `---' "#));
|
||||
set_color!();
|
||||
unsafe { VGA.prompt(); }
|
||||
unsafe { VGA.flush(); }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue