diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index 077645a5..84691a07 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -33,7 +33,7 @@ psp = "0.1.5" [target.'cfg(target_arch = "x86_64")'.dependencies] volatile = "0.2.6" -bootloader = "0.9.8" +bootloader = {version = "0.9.8", features = ["map_physical_memory"]} cpuio = { git = "https://github.com/anyusernameworks/cpuio.git" } x86_64 = "*" uart_16550 = "0.2.0" diff --git a/ableos/src/arch/x86_64/memory.rs b/ableos/src/arch/x86_64/memory.rs new file mode 100644 index 00000000..28f04957 --- /dev/null +++ b/ableos/src/arch/x86_64/memory.rs @@ -0,0 +1,81 @@ +use x86_64::{ + structures::paging::{ + FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, + }, + PhysAddr, VirtAddr, +}; + +pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> { + let level_4_table = active_level_4_table(physical_memory_offset); + OffsetPageTable::new(level_4_table, physical_memory_offset) +} + +unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable { + use x86_64::registers::control::Cr3; + + let (level_4_table_frame, _) = Cr3::read(); + + let phys = level_4_table_frame.start_address(); + let virt = physical_memory_offset + phys.as_u64(); + let page_table_ptr: *mut PageTable = virt.as_mut_ptr(); + + // THIS IS UNSAFE + &mut *page_table_ptr +} + +fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option { + use x86_64::registers::control::Cr3; + use x86_64::structures::paging::page_table::FrameError; + + let (level_4_table_frame, _) = Cr3::read(); + + let table_indexes = [ + addr.p4_index(), + addr.p3_index(), + addr.p2_index(), + addr.p1_index(), + ]; + let mut frame = level_4_table_frame; + + for &index in &table_indexes { + // convert the frame into a page table reference + let virt = physical_memory_offset + frame.start_address().as_u64(); + let table_ptr: *const PageTable = virt.as_ptr(); + let table = unsafe { &*table_ptr }; + + let entry = &table[index]; + frame = match entry.frame() { + Ok(frame) => frame, + Err(FrameError::FrameNotPresent) => return None, + Err(FrameError::HugeFrame) => panic!["huge pages not supported"], + }; + } + + Some(frame.start_address() + u64::from(addr.page_offset())) +} + +pub unsafe fn translate_addr(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option { + translate_addr_inner(addr, physical_memory_offset) +} + +pub fn create_example_mapping( + page: Page, + mapper: &mut OffsetPageTable, + frame_allocator: &mut impl FrameAllocator, +) { + use x86_64::structures::paging::PageTableFlags as Flags; + + let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); + let flags = Flags::PRESENT | Flags::WRITABLE; + + let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) }; + map_to_result.expect("map_to failed").flush(); +} + +pub struct EmptyFrameAllocator; + +unsafe impl FrameAllocator for EmptyFrameAllocator { + fn allocate_frame(&mut self) -> Option> { + None + } +} diff --git a/ableos/src/arch/x86_64/mod.rs b/ableos/src/arch/x86_64/mod.rs index f38307c9..2944251f 100644 --- a/ableos/src/arch/x86_64/mod.rs +++ b/ableos/src/arch/x86_64/mod.rs @@ -1,13 +1,15 @@ use x86_64::instructions::hlt; +use bootloader::BootInfo; pub mod drivers; pub mod gdt; pub mod init; pub mod interrupts; -#[no_mangle] -pub extern "C" fn _start() -> ! { - crate::kmain::kernel_main(); - sloop(); -} +pub mod memory; +// #[no_mangle] +// pub extern "C" fn _start(boot_info: &'static BootInfo) -> ! { +// crate::kmain::kernel_main(boot_info); +// // sloop(); +// } #[allow(unused)] pub fn shutdown() -> ! { diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs index f917606c..0dd8eebb 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -1,75 +1,96 @@ #![allow(clippy::empty_loop)] use crate::{ - arch::{drivers::graphics::GraphicsBuffer, init}, - driver_traits::{graphics::Graphics, serial::Serial}, - relib::math::rand::{linearshift::LinearShiftRegister, prand::PRand, RAND_HANDLE, RNG}, - serial_print, serial_println, + arch::{ + drivers::graphics::GraphicsBuffer, + init, + memory::{self, translate_addr}, + sloop, + }, + driver_traits::{graphics::Graphics, serial::Serial}, + relib::math::rand::{linearshift::LinearShiftRegister, prand::PRand, RAND_HANDLE, RNG}, + serial_print, serial_println, }; +use bootloader::{entry_point, BootInfo}; use lazy_static::lazy_static; +use x86_64::{VirtAddr, structures::paging::Page}; #[no_mangle] #[allow(unconditional_recursion)] pub extern "C" fn stack_overflow() -> u8 { - stack_overflow(); - 69 // NOTE: Any specific reason for this number asside from memes? + stack_overflow(); + // meme number + 69 // NOTE: Any specific reason for this number asside from memes? } use crate::keyboard::DecodedKey; lazy_static! { - pub static ref KEY_BUFFER: [DecodedKey; 256] = [DecodedKey::RawKey(123); 256]; - pub static ref KEY_BUFFER_POINTER: u8 = 0; + pub static ref KEY_BUFFER: [DecodedKey; 256] = [DecodedKey::RawKey(123); 256]; + pub static ref KEY_BUFFER_POINTER: u8 = 0; } +// Defines the entry point +entry_point![kernel_main]; #[no_mangle] -pub extern "C" fn kernel_main() { - init::init(); +pub fn kernel_main(boot_info: &'static BootInfo) -> ! { + init::init(); - GraphicsBuffer::draw(); - GraphicsBuffer::hide_cursor(); - GraphicsBuffer::show_cursor(); - seed_rng(); + GraphicsBuffer::draw(); + GraphicsBuffer::hide_cursor(); + GraphicsBuffer::show_cursor(); + seed_rng(); - /* If AES is present then AES init rng as well - // Maybe via a cfg - AES::init_rng(); + /* If AES is present then AES init rng as well + // Maybe via a cfg + AES::init_rng(); - */ - #[cfg(not(target_arch = "riscv64"))] - println!("init"); + */ + #[cfg(not(target_arch = "riscv64"))] + println!("init"); - { - use crate::experiments::mail::MailBoxes; - let mut x = MailBoxes::new(); - x.set_flag(1); - x.set_flag(2); - // x.dump_flags(); - } + { + use crate::experiments::mail::MailBoxes; + let mut x = MailBoxes::new(); + x.set_flag(1); + x.set_flag(2); + // x.dump_flags(); + } - // stack_overflow(); - // crate::arch::shutdown(); - loop {} + let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); + + let mut mapper = unsafe { memory::init(phys_mem_offset) }; + let mut frame_allocator = memory::EmptyFrameAllocator; + + let page = Page::containing_address(VirtAddr::new(0)); + memory::create_example_mapping(page, &mut mapper, &mut frame_allocator); + + let page_ptr: *mut u64 = page.start_address().as_mut_ptr(); + unsafe { page_ptr.offset(400).write_volatile(0xf021_f077_f065_f04e) }; + + // stack_overflow(); + // crate::arch::shutdown(); + sloop() } // TODO: reimplement for the random handler pub fn seed_rng() -> PRand { - println!("Seeding PRNG"); - let data = TICK.lock(); - let mut rand = PRand::new(); - let seed = rand.rand(); - println!("{:?}", seed); - rand.seed(*data); - println!("Seeded PRNG"); - rand + println!("Seeding PRNG"); + let data = TICK.lock(); + let mut rand = PRand::new(); + let seed = rand.rand(); + println!("{:?}", seed); + rand.seed(*data); + println!("Seeded PRNG"); + rand } lazy_static! { - // TODO: should have a sin wave influence contribution to entropy - pub static ref TICK: spin::Mutex = spin::Mutex::new(0); + // TODO: should have a sin wave influence contribution to entropy + pub static ref TICK: spin::Mutex = spin::Mutex::new(0); } /// called by arch specific timers to tick up all kernel related functions pub fn tick() { - let mut data = TICK.lock(); - *data += 1; - // serial_println!("{}", *data); - RAND_HANDLE.lock().seed_entropy_timer(*data); + let mut data = TICK.lock(); + *data += 1; + // serial_println!("{}", *data); + RAND_HANDLE.lock().seed_entropy_timer(*data); } pub fn key_entropy(key: u8) { - RAND_HANDLE.lock().seed_entropy_keyboard(key); + RAND_HANDLE.lock().seed_entropy_keyboard(key); }