//! Kernel initialization and supervisor entry point. //! //! This module sets up the global heap, initializes core subsystems (VGA, filesystem, //! scheduler, and logging), and starts initial processes. #![no_std] #![no_main] // #![warn(clippy::pedantic)] #![allow(static_mut_refs)] #![feature( riscv_ext_intrinsics, str_from_raw_parts, arbitrary_self_types_pointers )] use core::sync::atomic::AtomicBool; use alloc::boxed::Box; use embedded_alloc::LlffHeap as Heap; use log::info; use crate::{ cursor::{clear_cursor, draw_cursor}, io::init_log, keymap::map_keycode, pci::{PciDeviceIterator, scan_virtio_devices}, riscv::enable_supervisor_interrupt, scheduler::{SCHEDULER, idle}, tty::TTY0, user::{proc2, test}, vga::Vga, virtio::{ Virtqueue, input::{EventCodeValue, VirtioInputEvent, VirtioPciDriver, init_plic_pci}, }, virtual_fs::{FILE_SYSTEM, VirtualFileSystem, init_file_system}, }; extern crate alloc; mod boot; mod critical_section; mod cursor; mod data_structures; mod draw; mod fs; mod interrupt; mod io; mod keymap; mod panic_handler; mod pci; mod process; mod riscv; mod scheduler; mod sync; mod syscall; mod time; mod tty; mod uart; mod user; mod vga; mod virtio; mod virtual_console; mod virtual_fs; pub const HEAP_SIZE: usize = 1024 * 1024 * 32; // 32Mo RAM #[global_allocator] static HEAP: Heap = Heap::empty(); static HEAP_INITIALIZED: AtomicBool = AtomicBool::new(false); // Usize is assumed to be an u64 in the whole kernel const _: () = assert!(core::mem::size_of::() == core::mem::size_of::()); #[cfg(not(target_endian = "little"))] compile_error! {"This kernel implementation assume endianness is little-endian. Some memory access like PCI could not work in big-endian."} #[derive(Debug, Clone, Copy, Default)] pub struct KeyboardState { // ctrl_modifier: bool, maj_modifier: bool, } impl KeyboardState { pub const fn new() -> Self { Self { // ctrl_modifier: false, maj_modifier: false, } } } static mut KBD_STATE: KeyboardState = KeyboardState::new(); static mut KBD_QUEUE: Virtqueue = unsafe { core::mem::zeroed() }; pub static mut KBD_DRIVER: VirtioPciDriver = unsafe { VirtioPciDriver::new( |event| { let mut kbd_buffer = FILE_SYSTEM.open("/dev/input/keyboard".as_ref()).unwrap(); kbd_buffer .write(core::mem::transmute::< &VirtioInputEvent, &[u8; size_of::()], >(event)) .unwrap(); if event.is_key() { let event = event.as_key_event(); if event.value == EventCodeValue::Pressed { #[allow(clippy::single_match)] match map_keycode(event.code, KBD_STATE.maj_modifier) { keymap::KeyType::Ascii(c) => { let mut buf = [0; 4]; let to_send = c.encode_utf8(&mut buf); for c in to_send.as_bytes() { println!("key: {}", c); TTY0.buffer.borrow_mut().push(*c); } } _ => {} } println!("event: {:#?}", event); } } else { // println!("key pressed, {:#?}", event); } }, &mut KBD_QUEUE, ) }; pub static mut MOUSE_POSITION: (u16, u16) = (0, 0); static mut MOUSE_QUEUE: Virtqueue = unsafe { core::mem::zeroed() }; pub static mut MOUSE_DRIVER: VirtioPciDriver = unsafe { VirtioPciDriver::new( |event| { if event.is_relative() { let event = event.as_relative_event(); clear_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1); match event.code { virtio::input::EventCodeRelative::X => { MOUSE_POSITION.0 = (MOUSE_POSITION.0 as i32 + event.value) as u16 } virtio::input::EventCodeRelative::Y => { MOUSE_POSITION.1 = (MOUSE_POSITION.1 as i32 + event.value) as u16 } _ => {} } draw_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1); // println!("mouse moved relatively, {:#?}", event); } else { // println!("mouse moved, {:#?}", event); } }, &mut MOUSE_QUEUE, ) }; #[unsafe(no_mangle)] pub extern "C" fn supervisor_mode_entry() { unsafe { embedded_alloc::init!(HEAP, HEAP_SIZE); HEAP_INITIALIZED.store(true, core::sync::atomic::Ordering::Relaxed); init_log().unwrap(); Vga::init(); init_file_system(); SCHEDULER.lock().init(); } info!("Hello World !"); // unsafe { Vga.draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) }; SCHEDULER.lock().create_process(Box::new(test), "proc1"); SCHEDULER.lock().create_process(Box::new(proc2), "proc2"); SCHEDULER .lock() .create_process_from_file("/usr/bin/test_pic"); enable_supervisor_interrupt(); for pci in PciDeviceIterator::new() { println!("{:x?}", pci.vendor_and_device_id()) } unsafe { let (pci_keyboard, pci_mouse) = scan_virtio_devices(); let (pci_keyboard, pci_mouse) = (pci_keyboard.unwrap(), pci_mouse.unwrap()); KBD_DRIVER.init( pci_keyboard.common_cfg, pci_keyboard.notify_cfg, pci_keyboard.isr_cfg, pci_keyboard.notify_multiplier, ); MOUSE_DRIVER.init( pci_mouse.common_cfg, pci_mouse.notify_cfg, pci_mouse.isr_cfg, pci_mouse.notify_multiplier, ); init_plic_pci(pci_keyboard.irq); init_plic_pci(pci_mouse.irq); } idle(); }