Interrupts aren't working anymore

This commit is contained in:
2026-03-15 10:48:41 +01:00
parent de6ef959ce
commit b1aac20b57
17 changed files with 455 additions and 89 deletions

View File

@@ -142,3 +142,10 @@ impl From<&str> for PathBuf {
}
}
}
#[cfg(feature = "alloc")]
impl From<String> for PathBuf {
fn from(val: String) -> Self {
PathBuf { inner: val }
}
}

View File

@@ -1,6 +1,6 @@
use core::mem::MaybeUninit;
#[derive(Debug)]
#[derive(Debug, Copy)]
pub struct CircularBuffer<T, const SIZE: usize> {
buffer: [MaybeUninit<T>; SIZE],
head: usize,
@@ -8,6 +8,12 @@ pub struct CircularBuffer<T, const SIZE: usize> {
len: usize,
}
impl<T: Copy, const SIZE: usize> Clone for CircularBuffer<T, SIZE> {
fn clone(&self) -> Self {
*self
}
}
impl<T, const SIZE: usize> CircularBuffer<T, SIZE> {
pub const fn new() -> Self {
Self {

View File

@@ -14,7 +14,7 @@ use crate::{
clear_csr,
process::{ExecutionContext, exit_process, sleep},
read_csr,
riscv::disable_interrupt,
riscv::{disable_interrupt, dump_cpu},
scheduler::SCHEDULER,
set_csr, syscall,
time::{IRQ_M_EXTERNAL, IRQ_M_TIMER, setup_next_timer_interrupt},
@@ -85,7 +85,13 @@ unsafe extern "C" fn machine_trap_handler(
),
};
disable_interrupt();
panic!("{} at PC=0x{:x}, mtval={}", message, mepc, mtval);
panic!(
"{} at PC=0x{:x}, mtval={}\n\n{}",
message,
mepc,
mtval,
dump_cpu()
);
} else {
#[allow(clippy::single_match)]
match mcause & !(1 << 63) {
@@ -120,6 +126,12 @@ unsafe extern "C" fn supervisor_trap_handler(
unsafe {
(*interrupt_state).mepc = (*interrupt_state).mepc.byte_add(4);
}
// Get back to run the syscall again
fn loop_syscall(interrupt_state: *mut ExecutionContext) {
unsafe {
(*interrupt_state).mepc = (*interrupt_state).mepc.byte_sub(4);
}
}
// Environment call from S-mode
let syscall_u64: u64 = unsafe { (*interrupt_state).a[0] };
@@ -134,10 +146,19 @@ unsafe extern "C" fn supervisor_trap_handler(
let mut scheduler = SCHEDULER.lock();
let current_process = scheduler.get_current_process();
let fd = current_process.next_fd;
current_process.fd_table.insert(fd, virtual_node);
current_process.next_fd += 1;
unsafe { (*interrupt_state).a[0] = fd };
let fd = if let Some(fd) =
current_process.fd_table.iter().position(Option::is_none)
{
current_process.fd_table[fd] = Some(virtual_node);
fd
} else {
let fd = current_process.fd_table.len();
current_process.fd_table.push(Some(virtual_node));
fd
};
unsafe { (*interrupt_state).a[0] = fd as u64 };
}
SysCall::Write => {
let fd = a1;
@@ -146,7 +167,7 @@ unsafe extern "C" fn supervisor_trap_handler(
let mut scheduler = SCHEDULER.lock();
let current_process = scheduler.get_current_process();
let vnode = current_process.fd_table.get_mut(&fd).unwrap();
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
vnode.write(buf).unwrap();
}
SysCall::Read => {
@@ -156,8 +177,12 @@ unsafe extern "C" fn supervisor_trap_handler(
let mut scheduler = SCHEDULER.lock();
let current_process = scheduler.get_current_process();
let vnode = current_process.fd_table.get_mut(&fd).unwrap();
vnode.read(buf).unwrap();
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
let res = vnode.read(buf).unwrap();
if res == 0 && !buf.is_empty() {
loop_syscall(interrupt_state);
scheduler.schedule(&mut interrupt_state);
}
}
SysCall::Seek => {
let fd = a1;
@@ -169,7 +194,7 @@ unsafe extern "C" fn supervisor_trap_handler(
};
let mut scheduler = SCHEDULER.lock();
let current_process = scheduler.get_current_process();
let vnode = current_process.fd_table.get_mut(&fd).unwrap();
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
vnode.seek(seek).unwrap();
}
SysCall::Alloc => {
@@ -360,6 +385,17 @@ unsafe extern "C" fn _supervisor_mode_trap() {
csrr t0, sepc
sd t0, 248(sp)
csrr t0, sstatus
// Move SIE bit to SPIE. Restore_context, in the sret instruction, will do the inverse operation
// Isolate SIE bit (1)
andi t1, t0, 0x2
// li t1, 0x2
// Shift to bit 5 (SPIE)
slli t1, t1, 4
// Clear bit 1 and 5
li t2, ~0x22
and t0, t0, t2
// Add the SPIE bit
or t0, t0, t1
sd t0, 256(sp)
mv a0, sp

70
src/keyboard_forwarder.rs Normal file
View File

@@ -0,0 +1,70 @@
use crate::virtio::input::{EventCodeValue, VirtioKeyEvent};
use crate::{virtual_fs::FILE_SYSTEM, scheduler::SCHEDULER};
// Map some common linux input keycodes (evdev) to ASCII
fn keycode_to_ascii(code: u16) -> Option<char> {
match code as u32 {
// letters
30 => Some('a'), // KEY_A
48 => Some('b'), // KEY_B
46 => Some('c'),
32 => Some('d'),
18 => Some('e'),
33 => Some('f'),
34 => Some('g'),
35 => Some('h'),
23 => Some('i'),
36 => Some('j'),
37 => Some('k'),
38 => Some('l'),
50 => Some('m'),
49 => Some('n'),
24 => Some('o'),
25 => Some('p'),
16 => Some('q'),
19 => Some('r'),
31 => Some('s'),
20 => Some('t'),
22 => Some('u'),
47 => Some('v'),
17 => Some('w'),
45 => Some('x'),
21 => Some('y'),
44 => Some('z'),
// digits
2 => Some('1'),
3 => Some('2'),
4 => Some('3'),
5 => Some('4'),
6 => Some('5'),
7 => Some('6'),
8 => Some('7'),
9 => Some('8'),
10 => Some('9'),
11 => Some('0'),
// space, enter, backspace
57 => Some(' '),
28 => Some('\n'),
14 => Some('\x08'),
_ => None,
}
}
pub fn keyboard_forwarder() {
// Open keyboard device and stdin device
let mut kbd = unsafe { FILE_SYSTEM.open("/dev/input/keyboard".as_ref()).unwrap() };
let mut stdin = unsafe { FILE_SYSTEM.open("/dev/stdin".as_ref()).unwrap() };
let mut buf = [0u8; core::mem::size_of::<VirtioKeyEvent>()];
loop {
// Read full virtio key event
if let Ok(_) = kbd.read(&mut buf) {
let ev = unsafe { &*(buf.as_ptr() as *const VirtioKeyEvent) };
if ev.value == EventCodeValue::Pressed {
if let Some(c) = keycode_to_ascii(ev.code) {
let _ = stdin.write(&[c as u8]);
}
}
}
}
}

64
src/keymap.rs Normal file
View File

@@ -0,0 +1,64 @@
pub enum KeyType {
Ascii(char),
// Special, // F1, Home, etc.
Modifier, // Shift, Ctrl
Unknown,
}
pub const fn map_keycode(code: u16, shift: bool) -> KeyType {
match code {
// Numbers row
2..=11 => {
let val = if shift {
[')', '!', '@', '#', '$', '%', '^', '&', '*', '('][(code - 2) as usize]
} else {
(code as u8 - 2 + b'1') as char
};
if code == 11 && !shift {
KeyType::Ascii('0')
} else {
KeyType::Ascii(val)
}
}
// Letters (Simplified QWERTY)
16 => KeyType::Ascii(if shift { 'Q' } else { 'q' }),
17 => KeyType::Ascii(if shift { 'W' } else { 'w' }),
18 => KeyType::Ascii(if shift { 'E' } else { 'e' }),
19 => KeyType::Ascii(if shift { 'R' } else { 'r' }),
20 => KeyType::Ascii(if shift { 'T' } else { 't' }),
21 => KeyType::Ascii(if shift { 'Y' } else { 'y' }),
22 => KeyType::Ascii(if shift { 'U' } else { 'u' }),
23 => KeyType::Ascii(if shift { 'I' } else { 'i' }),
24 => KeyType::Ascii(if shift { 'O' } else { 'o' }),
25 => KeyType::Ascii(if shift { 'P' } else { 'p' }),
30 => KeyType::Ascii(if shift { 'A' } else { 'a' }),
31 => KeyType::Ascii(if shift { 'S' } else { 's' }),
32 => KeyType::Ascii(if shift { 'D' } else { 'd' }),
33 => KeyType::Ascii(if shift { 'F' } else { 'f' }),
34 => KeyType::Ascii(if shift { 'G' } else { 'g' }),
35 => KeyType::Ascii(if shift { 'H' } else { 'h' }),
36 => KeyType::Ascii(if shift { 'J' } else { 'j' }),
37 => KeyType::Ascii(if shift { 'K' } else { 'k' }),
38 => KeyType::Ascii(if shift { 'L' } else { 'l' }),
44 => KeyType::Ascii(if shift { 'Z' } else { 'z' }),
45 => KeyType::Ascii(if shift { 'X' } else { 'x' }),
46 => KeyType::Ascii(if shift { 'C' } else { 'c' }),
47 => KeyType::Ascii(if shift { 'V' } else { 'v' }),
48 => KeyType::Ascii(if shift { 'B' } else { 'b' }),
49 => KeyType::Ascii(if shift { 'N' } else { 'n' }),
50 => KeyType::Ascii(if shift { 'M' } else { 'm' }),
// Control
28 => KeyType::Ascii('\n'),
57 => KeyType::Ascii(' '),
14 => KeyType::Ascii('\x08'), // Backspace
1 => KeyType::Ascii('\x1b'), // Escape
// Modifiers
42 | 54 => KeyType::Modifier, // LShift, RShift
29 | 97 => KeyType::Modifier, // LCtrl, RCtrl
_ => KeyType::Unknown,
}
}

View File

@@ -21,14 +21,16 @@ 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, VirtioPciDriver, init_plic_pci},
input::{EventCodeValue, VirtioInputEvent, VirtioPciDriver, init_plic_pci},
},
virtual_fs::{FILE_SYSTEM, VirtualFileSystem, init_file_system},
};
@@ -42,6 +44,7 @@ mod draw;
mod fs;
mod interrupt;
mod io;
mod keymap;
mod panic_handler;
mod pci;
mod process;
@@ -69,17 +72,50 @@ 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."}
// 1. Allouer de la mémoire statique alignée pour la queue
#[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 {
println!("event: {:#?}", event);
kbd_buffer.write(&[event.code as u8]).unwrap();
#[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);
@@ -135,12 +171,12 @@ pub extern "C" fn supervisor_mode_entry() {
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(Box::new(test), "proc1");
// SCHEDULER.lock().create_process(Box::new(proc2), "proc2");
SCHEDULER
.lock()
.create_process_from_file("/usr/bin/test_pic");
// SCHEDULER
// .lock()
// .create_process_from_file("/usr/bin/test_pic");
enable_supervisor_interrupt();

View File

@@ -12,19 +12,22 @@ use core::time::Duration;
use alloc::{boxed::Box, format, string::String, vec::Vec};
use bffs::path::Path;
use goblin::elf::reloc::R_RISCV_RELATIVE;
use hashbrown::HashMap;
use shared::syscall::exit;
use crate::{
println,
scheduler::{SCHEDULER, Scheduler},
scheduler::{ACTIVE_PID, SCHEDULER, Scheduler},
time::elapsed_time_since_startup,
tty::TTY0,
virtual_fs::{FILE_SYSTEM, VirtualFileSystem, VirtualNode},
};
/// Size of the stack allocated to each process (in 64-bit words).
const STACK_SIZE: usize = 4096;
/// MSTATUS bit to enable supervisor mode interrupts.
const MSTATUS_SIE: u64 = 1 << 1;
/// MSTATUS bit to enable supervisor mode interrupts.
const MSTATUS_SPIE: u64 = 1 << 5;
@@ -91,9 +94,7 @@ pub struct Process {
/// Process stack.
pub stack: [u64; STACK_SIZE],
/// File descriptor table.
pub fd_table: HashMap<u64, Box<dyn VirtualNode>>,
/// Next available file descriptor.
pub next_fd: u64,
pub fd_table: Vec<Option<Box<dyn VirtualNode>>>,
}
unsafe impl Send for Process {}
@@ -118,8 +119,7 @@ impl Default for Process {
},
stack: [0; _],
entry: None,
fd_table: HashMap::new(),
next_fd: 0,
fd_table: Vec::new(),
}
}
}
@@ -297,10 +297,17 @@ impl Scheduler {
process.state = ProcessState::Activable;
process.entry = Some(code);
process.fd_table = HashMap::new();
process
.fd_table
.insert(0, FILE_SYSTEM.open("/dev/input/keyboard".into()).unwrap());
process.fd_table = Vec::new();
FILE_SYSTEM.mount(
format!("/proc/{}/0", process.pid).into(),
Box::new(TTY0.clone()),
);
// FD 0
process.fd_table.push(Some(
FILE_SYSTEM
.open(format!("/proc/{}/0", process.pid).as_ref())
.unwrap(),
));
// Configure execution context
// a0 contains the pointer to the function to execute
@@ -368,7 +375,7 @@ extern "C" fn process_launcher(code: *const Box<dyn Fn()>) {
pub fn exit_process(interrupt_context: &mut *mut ExecutionContext) {
// SAFETY: ACTIVE_PID is maintained by the scheduler and is always valid.
let mut scheduler = SCHEDULER.lock();
let active_pid = scheduler.active_pid;
let active_pid = ACTIVE_PID.load(core::sync::atomic::Ordering::Relaxed);
scheduler.process_table.remove(&active_pid).unwrap();
// Transfer control to the scheduler (does not return)
scheduler.schedule(interrupt_context)

View File

@@ -6,6 +6,10 @@
use core::arch::naked_asm;
use alloc::fmt::format;
use alloc::format;
use alloc::string::String;
use crate::clear_csr;
use crate::read_csr;
use crate::set_csr;
@@ -115,3 +119,22 @@ pub extern "C" fn exit_qemu() -> ! {
"
)
}
pub fn dump_cpu() -> String {
let mstatus: u64 = read_csr!(mstatus);
let mepc: u64 = read_csr!(mepc);
let sstatus: u64 = read_csr!(sstatus);
let sepc: u64 = read_csr!(sepc);
let stval: u64 = read_csr!(stval);
format!(
"-------- CPU DUMP --------
mstatus: {:#016x}
mepc: {:#016x}
sstatus: {:#016x}
sepc: {:#016x}
stval: {:#016x}
--------------------------",
mstatus, mepc, sstatus, sepc, stval
)
}

View File

@@ -3,7 +3,7 @@
//!
//! This module exposes the global process table, the scheduler initialization
//! and a simple round-robin scheduler used by the kernel.
use core::{arch::riscv64::wfi, cell::LazyCell, ops::Bound};
use core::{arch::riscv64::wfi, cell::LazyCell, ops::Bound, sync::atomic::AtomicU64};
use alloc::{boxed::Box, collections::BTreeMap};
use log::info;
@@ -17,13 +17,13 @@ use crate::{
#[derive(Debug)]
pub struct Scheduler {
pub next_pid: u64,
pub active_pid: u64,
pub process_table: BTreeMap<u64, Box<Process>>,
}
pub static ACTIVE_PID: AtomicU64 = AtomicU64::new(0);
pub static SCHEDULER: Mutex<LazyCell<Scheduler>> = Mutex::new(LazyCell::new(|| Scheduler {
next_pid: 0,
active_pid: 0,
process_table: BTreeMap::new(),
}));
@@ -60,7 +60,7 @@ impl Scheduler {
pub fn schedule(&mut self, interrupt_state: &mut *mut ExecutionContext) {
// info!("scheduler");
unsafe {
let prev_pid = self.active_pid;
let prev_pid = ACTIVE_PID.load(core::sync::atomic::Ordering::Relaxed);
if let Some(previous_process) = self.process_table.get_mut(&prev_pid) {
previous_process.ctx = **interrupt_state;
@@ -73,27 +73,31 @@ impl Scheduler {
.process_table
.range_mut((Bound::Excluded(prev_pid), Bound::Unbounded));
self.active_pid = loop {
if let Some((pid, current_process)) = current_process_iter.next() {
if current_process.state == ProcessState::Asleep
&& time::elapsed_time_since_startup() > current_process.wake_time
{
current_process.state = ProcessState::Activable;
ACTIVE_PID.store(
loop {
if let Some((pid, current_process)) = current_process_iter.next() {
if current_process.state == ProcessState::Asleep
&& time::elapsed_time_since_startup() > current_process.wake_time
{
current_process.state = ProcessState::Activable;
}
if current_process.state == ProcessState::Activable {
current_process.state = ProcessState::Active;
*interrupt_state = &raw mut current_process.ctx;
break *pid;
};
} else {
current_process_iter = self
.process_table
.range_mut((Bound::Unbounded, Bound::Included(prev_pid)))
}
if current_process.state == ProcessState::Activable {
current_process.state = ProcessState::Active;
*interrupt_state = &raw mut current_process.ctx;
break *pid;
};
} else {
current_process_iter = self
.process_table
.range_mut((Bound::Unbounded, Bound::Included(prev_pid)))
}
};
},
core::sync::atomic::Ordering::Relaxed,
);
}
}
pub fn get_current_process(&mut self) -> &mut Process {
self.process_table.get_mut(&self.active_pid).unwrap()
let active_pid = ACTIVE_PID.load(core::sync::atomic::Ordering::Relaxed);
self.process_table.get_mut(&active_pid).unwrap()
}
}

View File

@@ -26,7 +26,7 @@ const CLINT_TIMER: *const u64 = 0x0200_bff8 as *const u64;
/// The hardware timer frequency (Hz).
const TIMER_FREQUENCY: u64 = 10_000_000; // 10 MHz
/// The frequency at which timer interrupts should occur (Hz).
const INTERRUPT_FREQUENCY: u64 = 20; // 20 Hz
const INTERRUPT_FREQUENCY: u64 = 200; // 20 Hz
/// Stores the instant when the kernel started.
static START_TIME: AtomicU64 = AtomicU64::new(0);

View File

@@ -1,29 +1,35 @@
use core::cell::RefCell;
use core::cell::{LazyCell, RefCell};
use alloc::{boxed::Box, rc::Rc};
use io::{IoBase, Read, Seek, Write};
use crate::{
data_structures::circular_buffer::CircularBuffer,
virtual_console::VirtualConsole,
virtual_fs::{VirtualFileSystem, VirtualNode},
};
#[derive(Debug)]
pub const TTY_BUFFER_SIZE: usize = 4096; // 4Ko
pub static mut TTY0: LazyCell<Tty> = LazyCell::new(Tty::new);
#[derive(Debug, Clone)]
pub struct Tty {
pub buffer: Rc<RefCell<CircularBuffer<u8, TTY_BUFFER_SIZE>>>,
console: Rc<RefCell<VirtualConsole>>,
}
impl Tty {
pub fn new() -> Self {
Self {
buffer: RefCell::new(CircularBuffer::new()).into(),
console: RefCell::new(VirtualConsole::new()).into(),
}
}
}
#[derive(Debug)]
struct TtyNode {
console: Rc<RefCell<VirtualConsole>>,
struct TtyNode<'a> {
tty: &'a Tty,
}
impl VirtualFileSystem for Tty {
@@ -34,32 +40,36 @@ impl VirtualFileSystem for Tty {
if !path.is_empty() {
Err(())
} else {
Ok(Box::new(TtyNode {
console: self.console.clone(),
}))
Ok(Box::new(TtyNode { tty: self }))
}
}
}
impl IoBase for TtyNode {
impl IoBase for TtyNode<'_> {
type Error = ();
}
impl Read for TtyNode {
fn read(&mut self, _buf: &mut [u8]) -> Result<usize, Self::Error> {
unimplemented!()
impl Read for TtyNode<'_> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let mut buffer = self.tty.buffer.borrow_mut();
let max_len = buffer.len();
(0..buf.len().min(max_len)).for_each(|i| {
buf[i] = buffer.pop().unwrap();
});
Ok(buf.len().min(max_len))
}
}
impl Seek for TtyNode {
impl Seek for TtyNode<'_> {
fn seek(&mut self, _pos: io::SeekFrom) -> Result<u64, Self::Error> {
unimplemented!()
}
}
impl Write for TtyNode {
impl Write for TtyNode<'_> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.console
self.tty
.console
.borrow_mut()
.write_str(str::from_utf8(buf).unwrap());
Ok(buf.len())
@@ -70,4 +80,4 @@ impl Write for TtyNode {
}
}
impl VirtualNode for TtyNode {}
impl VirtualNode for TtyNode<'_> {}

View File

@@ -10,8 +10,14 @@ use io::{IoBase, Read, Seek, Write};
pub mod keyboard;
pub mod stdin;
pub mod virtual_stdin;
use crate::{fs::Disk, tty::Tty, vga::Vga, virtual_fs::keyboard::KeyboardBuffer};
use crate::{
fs::Disk,
tty::TTY0,
vga::Vga,
virtual_fs::{keyboard::KeyboardBuffer, virtual_stdin::VirtualStdin},
};
pub trait VirtualNode: IoBase<Error = ()> + Read + Write + Seek + Debug {}
@@ -55,12 +61,12 @@ pub static mut FILE_SYSTEM: LazyCell<MainFileSystem> = LazyCell::new(|| MainFile
pub unsafe fn init_file_system() {
unsafe {
FILE_SYSTEM.mount("/dev/fb0".into(), Box::new(VGAFileSystem));
FILE_SYSTEM.mount("/dev/tty0".into(), Box::new(Tty::new()));
FILE_SYSTEM.mount("/dev/tty0".into(), Box::new(TTY0.clone()));
FILE_SYSTEM.mount(
"/dev/input/keyboard".into(),
Box::new(KeyboardBuffer::new()),
);
// FILE_SYSTEM.mount("/dev/stdin".into(), Box::new(Stdin::new()));
FILE_SYSTEM.mount("/dev/stdin".into(), Box::new(VirtualStdin::new()));
}
}

View File

@@ -5,7 +5,6 @@ use io::{IoBase, Read, Seek, Write};
use crate::{
data_structures::circular_buffer::CircularBuffer,
println,
virtual_fs::{VirtualFileSystem, VirtualNode},
};
@@ -55,15 +54,15 @@ impl IoBase for KeyboardBufferNode<'_> {
impl Read for KeyboardBufferNode<'_> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let mut buffer = self.buffer.buffer.borrow_mut();
for i in 0..buf.len() {
(0..buf.len()).for_each(|i| {
buf[i] = buffer.pop().unwrap();
}
});
Ok(buf.len())
}
}
impl Seek for KeyboardBufferNode<'_> {
fn seek(&mut self, pos: io::SeekFrom) -> Result<u64, Self::Error> {
fn seek(&mut self, _pos: io::SeekFrom) -> Result<u64, Self::Error> {
todo!()
}
}

View File

@@ -3,19 +3,22 @@
// use alloc::boxed::Box;
// use io::{IoBase, Read, Seek, Write};
// use crate::virtual_fs::{VirtualFileSystem, VirtualNode};
// use crate::{
// data_structures::circular_buffer::CircularBuffer,
// virtual_fs::{VirtualFileSystem, VirtualNode},
// };
// pub const STDIN_BUFFER_SIZE: usize = 4096; // 4Ko
// #[derive(Debug)]
// pub struct Stdin {
// buffer: RefCell<[u8; STDIN_BUFFER_SIZE]>,
// buffer: RefCell<CircularBuffer<u8, STDIN_BUFFER_SIZE>>,
// }
// impl Stdin {
// pub fn new() -> Self {
// Self {
// buffer: RefCell::new([0; _]),
// buffer: RefCell::new(CircularBuffer::new()),
// }
// }
// }
@@ -44,7 +47,11 @@
// impl Read for StdinNode<'_> {
// fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
// todo!()
// let mut buffer = self.stdin.buffer.borrow_mut();
// for i in 0..buf.len() {
// buf[i] = buffer.pop().unwrap();
// }
// Ok(buf.len())
// }
// }

View File

@@ -0,0 +1 @@
pub struct SymbolicLink {}

View File

@@ -0,0 +1,84 @@
use alloc::{boxed::Box, format};
use io::{IoBase, Read, Seek, Write};
use crate::{
scheduler::ACTIVE_PID,
virtual_fs::{FILE_SYSTEM, VirtualFileSystem, VirtualNode},
};
#[derive(Debug)]
pub struct VirtualStdin {}
#[derive(Debug)]
pub struct VirtualStdinNode {}
impl VirtualStdin {
pub fn new() -> Self {
Self {}
}
}
impl VirtualFileSystem for VirtualStdin {
fn open(
&mut self,
path: &bffs::path::Path,
) -> Result<alloc::boxed::Box<dyn crate::virtual_fs::VirtualNode + '_>, ()> {
if !path.is_empty() {
Err(())
} else {
Ok(Box::new(VirtualStdinNode {}))
}
}
}
impl IoBase for VirtualStdinNode {
type Error = ();
}
impl Read for VirtualStdinNode {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let pid = ACTIVE_PID.load(core::sync::atomic::Ordering::Relaxed);
unsafe {
FILE_SYSTEM
.open(format!("/proc/{pid}/0").as_ref())
.unwrap()
.read(buf)
}
}
}
impl Seek for VirtualStdinNode {
fn seek(&mut self, pos: io::SeekFrom) -> Result<u64, Self::Error> {
let pid = ACTIVE_PID.load(core::sync::atomic::Ordering::Relaxed);
unsafe {
FILE_SYSTEM
.open(format!("/proc/{pid}/0").as_ref())
.unwrap()
.seek(pos)
}
}
}
impl Write for VirtualStdinNode {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
let pid = ACTIVE_PID.load(core::sync::atomic::Ordering::Relaxed);
unsafe {
FILE_SYSTEM
.open(format!("/proc/{pid}/0").as_ref())
.unwrap()
.write(buf)
}
}
fn flush(&mut self) -> Result<(), Self::Error> {
let pid = ACTIVE_PID.load(core::sync::atomic::Ordering::Relaxed);
unsafe {
FILE_SYSTEM
.open(format!("/proc/{pid}/0").as_ref())
.unwrap()
.flush()
}
}
}
impl VirtualNode for VirtualStdinNode {}

View File

@@ -12,13 +12,19 @@ fn main() {
// syscall::seek(&mut file, SeekFrom::End(-3));
// syscall::write(&mut file, &[255; 6400 * 50]);
syscall::sleep(Duration::from_secs_f64(2.0));
let mut stdin = syscall::open("/dev/input/keyboard");
let mut test = [0; 2];
syscall::read(&mut stdin, &mut test);
let mut stdin = syscall::open("/dev/tty0");
let mut file = syscall::open("/dev/tty0");
syscall::write(&mut file, b"Hi !\nnice tty\x08");
println!(
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! {:?}",
test
);
loop {
let mut test = [0; 2];
syscall::read(&mut stdin, &mut test);
let len = *test.iter().find(|x| **x == 0).unwrap_or(&1) + 1;
syscall::write(
&mut file,
str::from_utf8(&test[..len as usize]).unwrap().as_bytes(),
);
}
// println!(
// "Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! {:?}",
// str::from_utf8(&test)
// );
}