Files
riscv64-kernel/src/main.rs

210 lines
5.9 KiB
Rust

//! 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::<usize>() == core::mem::size_of::<u64>());
#[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::<VirtioInputEvent>()],
>(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();
}