diff --git a/Cargo.toml b/Cargo.toml index f7dd3b1..1561936 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,14 +11,12 @@ spin = "0.9.1" x86_64 = "0.14.10" rlibc = "1.0" multiboot2 = { version = "0.14.0", optional = true } -acpi = { version = "4.1.1", optional = true } linked_list_allocator = { version = "0.9.0", optional = true } [dependencies.lazy_static] version = "1.4.0" features = ["spin_no_std"] [features] -default = ["f_multiboot2", "f_ll_alloc", "f_debug_verbose"] -f_debug_verbose = [] -f_multiboot2 = ["dep:multiboot2", "dep:acpi"] +default = ["f_multiboot2", "f_ll_alloc"] +f_multiboot2 = ["dep:multiboot2"] f_ll_alloc = ["dep:linked_list_allocator"] \ No newline at end of file diff --git a/serial.log b/serial.log index c5b92ba..ef292d9 100644 --- a/serial.log +++ b/serial.log @@ -7,12 +7,6 @@ BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1 WARNING: no console will be available to OS error: no suitable video mode found. using serial port 0 as console -debug: setup GDT -debug: GDT loaded -debug: CS set -debug: SS set -debug: TSS loaded -debug: IDT loaded @@ -22,29 +16,3 @@ initialising mapper...[OK] initialising frame allocator...[OK] initialising heap...[OK] testing heap...[OK] -checking for apic compatibility...[OK] -disabling PIC...[OK] -initialising apic...[debug] read_phys_memory32: addr fee000f0 not mapped -[debug] allocated frame: PhysFrame[4KiB](0x1c000) -[debug] mapped page: Page[4KiB](0xfee00000) -[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfee00000))) -[OK] -setting up apic interrupts...[debug] write_phys_memory32: addr fec00000 not mapped -[debug] allocated frame: PhysFrame[4KiB](0x1f000) -[debug] mapped page: Page[4KiB](0xfec00000) -[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfec00000))) -[OK] -[debug] keyboard interrupt ----KERNEL FUCKY WUKKY UWU--- -double fault! -stack frame: InterruptStackFrame { - instruction_pointer: VirtAddr( - 0x120ef1, - ), - code_segment: 8, - cpu_flags: 0x200002, - stack_pointer: VirtAddr( - 0x140c00, - ), - stack_segment: 16, -} diff --git a/src/boot/mod.rs b/src/boot/mod.rs index d8ec989..3491cce 100644 --- a/src/boot/mod.rs +++ b/src/boot/mod.rs @@ -1,12 +1,8 @@ -use alloc::sync::Arc; use core::marker::PhantomData; -use acpi::{AcpiHandler, PhysicalMapping}; -use crate::{debug, KernelArgs}; +use crate::KernelArgs; #[cfg(feature = "f_multiboot2")] use multiboot2::{load, MemoryMapTag, BootInformation}; -use x86_64::structures::paging::{FrameAllocator, OffsetPageTable}; -use crate::memory::BootInfoFrameAllocator; pub struct KernelInfo { kernel_start: u64, @@ -55,65 +51,4 @@ impl KernelInfo { pub fn safe_memory_start(&self) -> u64 { self.safe_mem_start } - - pub fn acpi_get_ioapic_addr(&self, mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator) -> u64 { - #[cfg(feature = "f_multiboot2")] - { - let acpi_tag = self.boot_info.rsdp_v1_tag().expect("no acpi tag"); - let rsdp = acpi_tag; - let rsdp = unsafe { &*rsdp }; - let rsdt = rsdp.rsdt_address(); - #[derive(Clone)] - struct Handler<'a> { - mem_mapper: Arc<&'a mut OffsetPageTable<'a>>, - frame_allocator: Arc<&'a mut BootInfoFrameAllocator>, - } - impl<'a> AcpiHandler for Handler<'a> { - unsafe fn map_physical_region(&self, physical_address: usize, size: usize) -> PhysicalMapping { - let frame_allocator = self.frame_allocator.clone(); - debug!("read_phys_memory32: addr {:x} not mapped", physical_address); - // map the page - let frame = frame_allocator.allocate_frame().unwrap(); - debug!("allocated frame: {:?}", frame); - let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; - let page = x86_64::structures::paging::Page::containing_address(initaladdr); - debug!("mapped page: {:?}", page); - let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; - debug!("map_to_result: {:?}", map_to_result); - if map_to_result.is_err() { - panic!("Failed to map page"); - } - let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; - if let Some(addr) = addr { - let addr = addr.as_u64() as *const u32; - unsafe { *addr } - } else { - panic!("Failed to map page"); - } - } - - fn unmap_physical_region(region: &PhysicalMapping) { - todo!() - } - } - let rsdt = acpi::AcpiTables::from_rsdt(rsdt).expect("failed to get acpi tables"); - let mut ioapic_addr = 0; - for entry in rsdt.entries() { - let entry = unsafe { &*entry }; - if entry.signature() == *b"APIC" { - let apic = entry.as_apic(); - let apic = unsafe { &*apic }; - for entry in apic.entries() { - let entry = unsafe { &*entry }; - if entry.signature() == *b"IOAP" { - let ioapic = entry.as_ioapic(); - let ioapic = unsafe { &*ioapic }; - ioapic_addr = ioapic.address(); - } - } - } - } - ioapic_addr - } - } } \ No newline at end of file diff --git a/src/internals/cpu.rs b/src/internals/cpu.rs deleted file mode 100644 index 8fdd444..0000000 --- a/src/internals/cpu.rs +++ /dev/null @@ -1,142 +0,0 @@ -use core::arch::asm; -use x86_64::{PhysAddr, VirtAddr}; -use x86_64::structures::idt::InterruptStackFrame; -use x86_64::structures::paging::OffsetPageTable; -use crate::{debug, print, println}; -use crate::memory::{BootInfoFrameAllocator, read_phys_memory32, write_phys_memory32}; -use crate::serial::{command, read}; - -// todo! maybe abstract this into different sections for different parts of cpu func? - -pub fn check_apic_compat() -> bool { - unsafe { - let mut eax: u32; - let mut edx: u32; - asm!("cpuid", - in("eax") 1, - lateout("eax") eax, - lateout("edx") edx, - ); - edx & (1 << 9) != 0 - } -} - -pub fn set_apic_base(apic: usize) { - const IA32_APIC_BASE_MSR_ENABLE: u32 = 0x800; - let mut edx = 0u32; - let mut eax = (apic & 0xfffff0000) as u32 | IA32_APIC_BASE_MSR_ENABLE; - unsafe { - asm!("wrmsr", - in("ecx") 0x1b, - in("eax") eax, - in("edx") edx, - ); - } -} - -pub fn get_apic_base() -> usize { - let mut edx = 0u32; - let mut eax = 0u32; - unsafe { - asm!("rdmsr", - in("ecx") 0x1b, - lateout("eax") eax, - lateout("edx") edx, - ); - } - ((edx as usize) << 32) | (eax as usize) -} - -pub fn enable_apic(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator) { - // PIC should be disabled by now - // now enable local apic - // 1. set bit 8 of spurious interrupt vector register - let sivr_addr = 0xfee000f0; - let sivr = read_phys_memory32(mem_mapper, frame_alloc, sivr_addr); - write_phys_memory32(mem_mapper, frame_alloc, sivr_addr, sivr | (1 << 8)); -} - -pub fn apic_read_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32) -> u32 { - write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg); - read_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10) -} - -pub fn apic_write_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32, val: u32) { - write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg); - write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10, val); -} - -pub fn disable_pic() { - command(0x20, 0x11); - command(0xa0, 0x11); - - command(0x21, 0xe0); - command(0xa1, 0xe8); - - command(0x21, 0x04); - command(0xa1, 0x02); - - command(0x21, 0x01); - command(0xa1, 0x01); - - command(0x21, 0xff); - command(0xa1, 0xff); -} - -pub fn ioapic_set_irq(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, irq: u8, apic_id: u64, vector:u8) { - let lo_index: u32 = (0x10 + irq*2 ) as u32; - let hi_index: u32 = (0x10 + irq*2 + 1) as u32; - - let mut high = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, hi_index); - // set apic id - high &= !(0xff000000); - high |= (apic_id as u32) << 24; - apic_write_io(mem_mapper, frame_alloc, ioapicaddr, hi_index, high); - - let mut low = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, lo_index); - - // unmask - low &= !(1 << 16); - // set to physical delivery - low &= !(1 << 11); - // set to fixed delivery - low &= !(0x700); - // set vector - low &= !(0xff); - low |= vector as u32; - - apic_write_io(mem_mapper, frame_alloc, ioapicaddr, lo_index, low); -} - -pub fn apic_eoi() { - unsafe { - asm!("mov eax, 0", - "mov ecx, 0xb0", - "wrmsr", - in("ecx") 0x80b, - in("eax") 0, - ); - } -} - -// todo! in the future this will be removed, it is only for testing basic apic functionality -pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) { - debug!("keyboard interrupt"); - unsafe { asm!("iretq"); } - let scancode = read(0x60); - - print!("ksc: {},", scancode); - - // reset keyboard controller - let mut a = read(0x61); - a |= 0x82; - command(0x61, a); - a &= 0x7f; - command(0x61, a); -} - -// todo! we should abstract this away -pub fn setup_apic_interrupts(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize) { - // set keyboard irq to interrupt 40 - ioapic_set_irq(mem_mapper, frame_alloc, ioapicaddr, 1, 0, 40); -} \ No newline at end of file diff --git a/src/internals/mod.rs b/src/internals/mod.rs index 9ef5c0f..4050443 100644 --- a/src/internals/mod.rs +++ b/src/internals/mod.rs @@ -1,8 +1,8 @@ pub mod errors; -pub mod interrupts; -pub mod cpu; pub mod WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood { + use core::arch::asm; + use core::marker::PhantomData; #[derive(Clone, Copy)] pub struct Point { diff --git a/src/lib.rs b/src/lib.rs index 35409fe..bbea6ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ #![feature(default_alloc_error_handler)] #![feature(panic_info_message)] #![feature(asm_const)] -#![feature(const_mut_refs)] #![feature(alloc_error_handler)] #![no_std] #![no_main] @@ -12,16 +11,12 @@ extern crate alloc; use alloc::rc::Rc; use alloc::vec; -use core::arch::asm; use lazy_static::lazy_static; use core::panic::PanicInfo; use multiboot2::MemoryAreaType; use spin::Mutex; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; -use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor}; -use x86_64::structures::tss::TaskStateSegment; use x86_64::{PhysAddr, VirtAddr}; -use x86_64::registers::segmentation::{CS, Segment, SS}; use x86_64::structures::paging::Translate; use crate::boot::KernelInfo; use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*; @@ -36,16 +31,11 @@ mod memory; mod macros; lazy_static! { - static ref GDT: Mutex = { - let mut gdt = GlobalDescriptorTable::new(); - Mutex::new(gdt) - }; static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(internals::errors::breakpoint_exception); idt.double_fault.set_handler_fn(internals::errors::double_fault); idt.page_fault.set_handler_fn(internals::errors::page_fault); - idt[40].set_handler_fn(internals::cpu::keyboard_irq); idt }; } @@ -102,60 +92,6 @@ pub extern fn kernel_main(args: KernelArgs) -> ! { println!("using serial port {} as console", i); } - // temporarily disable interrupts - x86_64::instructions::interrupts::disable(); - println!("debug: setup GDT"); - // load TSS - static mut tss: TaskStateSegment = TaskStateSegment::new(); - { - unsafe { - tss.interrupt_stack_table[0] = { - const STACK_SIZE: usize = 4096 * 5; - static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; - let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); - let stack_end = stack_start + STACK_SIZE; - stack_end - }; - // set word at offset 102 to 0x68 and last two bytes of the tss to 0xffff - // this is a hack to make the tss valid - let tss_ptr = &tss as *const TaskStateSegment as *mut u8; - unsafe { - *tss_ptr.add(102) = 0x68; - *tss_ptr.add(104) = 0xff; - *tss_ptr.add(105) = 0xff; - } - } - let kcs = GDT.lock().add_entry(Descriptor::kernel_code_segment()); - let kds = GDT.lock().add_entry(Descriptor::kernel_data_segment()); - let tsss = unsafe { GDT.lock().add_entry(Descriptor::tss_segment(&tss)) }; - // load GDT - unsafe { - GDT.lock().load_unsafe(); - } - println!("debug: GDT loaded"); - // set code segment to kernel code segment - unsafe { - CS::set_reg(kcs); - } - println!("debug: CS set"); - // set data segment to kernel data segment - unsafe { - SS::set_reg(kds); - } - println!("debug: SS set"); - // load TSS - unsafe { - x86_64::instructions::tables::load_tss(tsss); - } - println!("debug: TSS loaded"); - - // load IDT - IDT.load(); - println!("debug: IDT loaded"); - // enable interrupts - x86_64::instructions::interrupts::enable(); - } - println!(); println!(); @@ -163,58 +99,28 @@ pub extern fn kernel_main(args: KernelArgs) -> ! { println!("welcome to wukkOS!"); println!("(c) 2022 Real Microsoft, LLC"); let kern_info = Mutex::new(KernelInfo::init_from_kernel_args(args)); + print!("initialising mapper..."); + let mut mapper = unsafe { memory::init(VirtAddr::new(0)) }; + println!("[OK]"); + print!("initialising frame allocator..."); + let mut frame_allocator = unsafe { memory::BootInfoFrameAllocator::init(kern_info) }; + println!("[OK]"); + print!("initialising heap..."); + memory::allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap init failed"); + println!("[OK]"); - // memory stuff - let mut mapper = None; - let mut frame_allocator = None; - { - print!("initialising mapper..."); - mapper = Some(unsafe { memory::init(VirtAddr::new(0)) }); + print!("testing heap..."); + let reference_counted = Rc::new(vec![1, 2, 3]); + let cloned = reference_counted.clone(); + let test_1 = Rc::strong_count(&reference_counted) == 2; + drop(cloned); + let test_2 = Rc::strong_count(&reference_counted) == 1; + if test_1 && test_2 { println!("[OK]"); - print!("initialising frame allocator..."); - frame_allocator = Some(unsafe { memory::BootInfoFrameAllocator::init(kern_info) }); - println!("[OK]"); - print!("initialising heap..."); - memory::allocator::init_heap(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()).expect("heap init failed"); - println!("[OK]"); - - print!("testing heap..."); - let reference_counted = Rc::new(vec![1, 2, 3]); - let cloned = reference_counted.clone(); - let test_1 = Rc::strong_count(&reference_counted) == 2; - drop(cloned); - let test_2 = Rc::strong_count(&reference_counted) == 1; - if test_1 && test_2 { - println!("[OK]"); - } else { - println!("[FAIL]"); - } - drop(reference_counted); + } else { + println!("[FAIL]"); } + drop(reference_counted); - // apic stuff - { - print!("checking for apic compatibility..."); - let apic_compatible = unsafe { internals::cpu::check_apic_compat() }; - if apic_compatible { - println!("[OK]"); - } else { - println!("[FAIL]"); - panic!("apic required at the moment"); - } - print!("disabling PIC..."); - unsafe { internals::cpu::disable_pic() }; - println!("[OK]"); - print!("initialising apic..."); - unsafe { internals::cpu::enable_apic(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) }; - println!("[OK]"); - print!("setting up apic interrupts..."); - unsafe { internals::cpu::setup_apic_interrupts(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) }; - println!("[OK]"); - // enable interrupts - x86_64::instructions::interrupts::enable(); - } - - loop { - } + loop {} } \ No newline at end of file diff --git a/src/macros/mod.rs b/src/macros/mod.rs index 11c85f3..390ce73 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -12,24 +12,8 @@ macro_rules! println { ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); } -#[macro_export] -macro_rules! debug { - ($($arg:tt)*) => ($crate::macros::_debug(format_args!($($arg)*))); -} - #[doc(hidden)] pub fn _print(args: fmt::Arguments) { use core::fmt::Write; ST.writer.lock().write_fmt(args).unwrap(); -} - -#[doc(hidden)] -pub fn _debug(args: fmt::Arguments) { - use core::fmt::Write; - #[cfg(feature = "f_debug_verbose")] - { - ST.log("[debug] "); - ST.writer.lock().write_fmt(args).unwrap(); - ST.logln(""); - } } \ No newline at end of file diff --git a/src/memory/allocator.rs b/src/memory/allocator.rs index 229b2a3..c8f3624 100644 --- a/src/memory/allocator.rs +++ b/src/memory/allocator.rs @@ -1,102 +1,15 @@ -use core::alloc::GlobalAlloc; -use core::mem; -use core::ptr::NonNull; use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB}; use x86_64::structures::paging::mapper::MapToError; use x86_64::VirtAddr; -use super::Locked; pub const HEAP_START: u64 = 0x_4444_4444_0000; pub const HEAP_SIZE: u64 = 100 * 1024; // 100 KiB +#[cfg(feature = "f_ll_alloc")] +use linked_list_allocator::LockedHeap; + #[global_allocator] -static ALLOCATOR: Locked = Locked::new(FixedSizeBlockAllocator::new()); - -const BLOCK_SIZES: &[usize] = &[8, 16, 32, 64, 128, 256, 512, 1024, 2048]; - -pub struct FixedSizeBlockAllocator { - list_heads: [Option<&'static mut FixedSizeBlockNode>; BLOCK_SIZES.len()], - #[cfg(feature = "f_ll_alloc")] - fallback_allocator: linked_list_allocator::Heap, -} - -pub struct FixedSizeBlockNode { - next: Option<&'static mut FixedSizeBlockNode>, -} - -impl FixedSizeBlockAllocator { - pub const fn new() -> Self { - const EMPTY: Option<&'static mut FixedSizeBlockNode> = None; - Self { - list_heads: [EMPTY; BLOCK_SIZES.len()], - #[cfg(feature = "f_ll_alloc")] - fallback_allocator: linked_list_allocator::Heap::empty(), - } - } - - pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) { - self.fallback_allocator.init(heap_start, heap_size); - } - - fn fallback_alloc(&mut self, layout: core::alloc::Layout) -> *mut u8 { - match self.fallback_allocator.allocate_first_fit(layout) { - Ok(ptr) => ptr.as_ptr(), - Err(_) => core::ptr::null_mut(), - } - } -} - -unsafe impl GlobalAlloc for Locked { - unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { - let mut allocator = self.lock(); - match list_index(&layout) { - Some(index) => { - match allocator.list_heads[index].take() { - Some(node) => { - allocator.list_heads[index] = node.next.take(); - node as *mut FixedSizeBlockNode as *mut u8 - } - None => { - // no block exists in list => allocate new block - let block_size = BLOCK_SIZES[index]; - // only works if all block sizes are a power of 2 - let block_align = block_size; - let layout = core::alloc::Layout::from_size_align(block_size, block_align) - .unwrap(); - allocator.fallback_alloc(layout) - } - } - } - None => allocator.fallback_alloc(layout), - } - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) { - let mut allocator = self.lock(); - match list_index(&layout) { - Some(index) => { - let new_node = FixedSizeBlockNode { - next: allocator.list_heads[index].take(), - }; - // verify that block has size and alignment required for storing node - assert!(mem::size_of::() <= BLOCK_SIZES[index]); - assert!(mem::align_of::() <= BLOCK_SIZES[index]); - let new_node_ptr = ptr as *mut FixedSizeBlockNode; - new_node_ptr.write(new_node); - allocator.list_heads[index] = Some(&mut *new_node_ptr); - } - None => { - let ptr = NonNull::new(ptr).unwrap(); - allocator.fallback_allocator.deallocate(ptr, layout); - } - } - } -} - -fn list_index(layout: &core::alloc::Layout) -> Option { - let required_block_size = layout.size().max(layout.align()); - BLOCK_SIZES.iter().position(|&s| s >= required_block_size) -} +static ALLOCATOR: LockedHeap = LockedHeap::empty(); pub fn init_heap( mapper: &mut impl Mapper, diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 9b2a305..125c885 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,26 +1,8 @@ pub mod allocator; -use alloc::boxed::Box; -use alloc::sync::Arc; -use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate}; +use x86_64::structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB}; use x86_64::{PhysAddr, VirtAddr}; -pub struct Locked { - inner: spin::Mutex, -} - -impl Locked { - pub const fn new(inner: A) -> Self { - Locked { - inner: spin::Mutex::new(inner), - } - } - - pub fn lock(&self) -> spin::MutexGuard { - self.inner.lock() - } -} - pub unsafe fn init(phys_mem_offset: VirtAddr) -> OffsetPageTable<'static> { let level_4_table = active_level_4_table(phys_mem_offset); OffsetPageTable::new(level_4_table, phys_mem_offset) @@ -42,7 +24,6 @@ unsafe fn active_level_4_table(phys_mem_offset: VirtAddr) -> &'static mut PageTa use multiboot2::{MemoryMapTag, BootInformation}; use spin::Mutex; use crate::boot::KernelInfo; -use crate::{debug, print, println}; pub struct BootInfoFrameAllocator { kern_info: Mutex, @@ -84,62 +65,4 @@ unsafe impl FrameAllocator for BootInfoFrameAllocator { frame } } -} - -pub fn read_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32) -> u32 { - let initaladdr = VirtAddr::new(addr as u64); - let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; - if let Some(addr) = addr { - let addr = addr.as_u64() as *const u32; - unsafe { *addr } - } else { - debug!("read_phys_memory32: addr {:x} not mapped", initaladdr.as_u64()); - // map the page - let frame = frame_allocator.allocate_frame().unwrap(); - debug!("allocated frame: {:?}", frame); - let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; - let page = x86_64::structures::paging::Page::containing_address(initaladdr); - debug!("mapped page: {:?}", page); - let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; - debug!("map_to_result: {:?}", map_to_result); - if map_to_result.is_err() { - panic!("Failed to map page"); - } - let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; - if let Some(addr) = addr { - let addr = addr.as_u64() as *const u32; - unsafe { *addr } - } else { - panic!("Failed to map page"); - } - } -} - -pub fn write_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32, value: u32) { - let initaladdr = VirtAddr::new(addr as u64); - let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; - if let Some(addr) = addr { - let addr = addr.as_u64() as *mut u32; - unsafe { *addr = value }; - } else { - debug!("write_phys_memory32: addr {:x} not mapped", initaladdr.as_u64()); - // map the page - let frame = frame_allocator.allocate_frame().unwrap(); - debug!("allocated frame: {:?}", frame); - let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; - let page = x86_64::structures::paging::Page::containing_address(initaladdr); - debug!("mapped page: {:?}", page); - let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; - debug!("map_to_result: {:?}", map_to_result); - if map_to_result.is_err() { - panic!("Failed to map page"); - } - let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; - if let Some(addr) = addr { - let addr = addr.as_u64() as *mut u32; - unsafe { *addr = value }; - } else { - panic!("Failed to map page"); - } - } } \ No newline at end of file diff --git a/src/serial/mod.rs b/src/serial/mod.rs index a2628a4..bb07bdc 100644 --- a/src/serial/mod.rs +++ b/src/serial/mod.rs @@ -4,6 +4,7 @@ use core::arch::asm; use core::borrow::{Borrow, BorrowMut}; use core::ops::Deref; +pub mod ps2; pub mod terminal_helpers; pub mod terminal; @@ -59,14 +60,14 @@ pub struct SerialPorts { } #[cfg(any(target_arch="x86", target_arch="x86_64"))] -pub fn command(port: u16, data: u8) { +fn command(port: u16, data: u8) { unsafe { asm!("out dx, al", in("al") data, in("dx") port); } } #[cfg(any(target_arch="x86", target_arch="x86_64"))] -pub fn read(port: u16) -> u8 { +fn read(port: u16) -> u8 { let mut data: u8; unsafe { asm!("in al, dx", out("al") data, in("dx") port); diff --git a/src/serial/ps2/mod.rs b/src/serial/ps2/mod.rs new file mode 100644 index 0000000..f187b81 --- /dev/null +++ b/src/serial/ps2/mod.rs @@ -0,0 +1,70 @@ +use super::*; +use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::{KernelError, ErrorKind, ErrorLevel}; + +pub enum PS2Type { + AncientKeyboard, + Keyboard, + Mouse, + FiveButtonMouse, + ScrollWheelMouse, + Unknown, +} + +enum Messages { + MSGDisableScanning = 0xF5, + MSGIdentify = 0xF2, + MSGACK = 0xFA, +} + +pub fn probePort(port : Port) -> Result { + let mut response : u8; + response = port.transrecv(Messages::MSGDisableScanning as u8); + // check for ACK + if response != Messages::MSGACK as u8 { + return Err(KernelError::new(ErrorKind::HardwareFuckUp, ErrorLevel::Warning, "Did not receive ACK", port.base.to_string())); + } + response = port.transrecv(Messages::MSGIdentify as u8); + // check for ACK + if response != Messages::MSGACK as u8 { + return Err(KernelError::new(ErrorKind::HardwareFuckUp, ErrorLevel::MinorFuckUp, "Did not receive ACK after asking port to identify", port.base.to_string())); + } + // read the response with a timeout of x cpu cycles, this can be quite low as it will only matter on slow machines + response = port.receive(0xFFFF); + // if there's no response, it's a really old keyboard (IBM or whoever, why did you have to do this??)\ + if response == 0 { + return Ok(PS2Type::AncientKeyboard); + } else { + // switch on the response + match response { + 0x00 => { // standard mouse + return Ok(PS2Type::Mouse); + }, + 0x03 => { // mouse with scroll wheel + return Ok(PS2Type::ScrollWheelMouse); + }, + 0x04 => { // 5 button mouse + return Ok(PS2Type::FiveButtonMouse); + }, + 0xAB => { // some type of keyboard, we'll need to read another byte to be sure + response = port.receive(0xFFFF); + match response { + 0x41 => { // some keyboard idfk + return Ok(PS2Type::Keyboard); + }, + 0xC1 => { // same as above + return Ok(PS2Type::Keyboard); + }, + 0x83 => { // keyboard after taking normal pills + return Ok(PS2Type::Keyboard); + }, + _ => { // what? + return Ok(PS2Type::Unknown); + } + } + }, + _ => { // some other device idk + return Ok(PS2Type::Unknown); + } + } + } +} \ No newline at end of file diff --git a/src/serial/ps2controller.rs b/src/serial/ps2controller.rs new file mode 100644 index 0000000..ca3f6bf --- /dev/null +++ b/src/serial/ps2controller.rs @@ -0,0 +1,3 @@ +static DATA_PORT: u16 = 0x60; +static COMMAND_PORT: u16 = 0x64; + diff --git a/src/internals/interrupts.rs b/src/serial/ps2keyboard.rs similarity index 100% rename from src/internals/interrupts.rs rename to src/serial/ps2keyboard.rs diff --git a/src/serial/terminal.rs b/src/serial/terminal.rs index 6edab88..0246bc2 100644 --- a/src/serial/terminal.rs +++ b/src/serial/terminal.rs @@ -2,7 +2,6 @@ use core::fmt; use core::ops::Deref; use lazy_static::lazy_static; use spin::Mutex; -use x86_64::instructions::interrupts::without_interrupts; use crate::serial::Port; pub struct SerialTerminal { @@ -33,30 +32,24 @@ impl SerialTerminal { } pub fn log(&self, message: &str) { - without_interrupts(|| { - if let Some(port) = self.port.lock().deref() { - port.transmit_string(message); - } - }); + if let Some(port) = self.port.lock().deref() { + port.transmit_string(message); + } } pub fn logln(&self, message: &str) { - without_interrupts(|| { - if let Some(port) = self.port.lock().deref() { - port.transmit_string(message); - port.transmit_string("\r\n"); - } - }); + if let Some(port) = self.port.lock().deref() { + port.transmit_string(message); + port.transmit_string("\r\n"); + } } } impl fmt::Write for SerialTerminalWriter { fn write_str(&mut self, s: &str) -> fmt::Result { - without_interrupts(|| { - if let Some(port) = self.port.lock().deref() { - port.transmit_string(s); - } - }); + if let Some(port) = self.port.lock().deref() { + port.transmit_string(s); + } Ok(()) } } \ No newline at end of file