210 lines
5.9 KiB
Rust
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();
|
|
}
|