strat9_kernel/vfs/
console_scheme.rs1use alloc::{string::String, sync::Arc};
2use core::sync::atomic::{AtomicU64, Ordering};
3
4use crate::{sync::SpinLock, syscall::error::SyscallError};
5
6use super::{
7 fd::FileDescriptorTable,
8 file::OpenFile,
9 scheme::{
10 finalize_pseudo_stat, DynScheme, FileFlags, FileStat, OpenFlags, OpenResult, Scheme,
11 DEV_CONSOLE,
12 },
13};
14
15static NEXT_ID: AtomicU64 = AtomicU64::new(1);
16static CONSOLE: SpinLock<Option<Arc<ConsoleScheme>>> = SpinLock::new(None);
17
18pub struct ConsoleScheme;
19
20impl ConsoleScheme {
21 pub fn new() -> Self {
23 ConsoleScheme
24 }
25}
26
27impl Scheme for ConsoleScheme {
28 fn open(&self, _path: &str, _flags: OpenFlags) -> Result<OpenResult, SyscallError> {
30 let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
31 Ok(OpenResult {
32 file_id: id,
33 size: None,
34 flags: FileFlags::DEVICE,
35 })
36 }
37
38 fn read(&self, _file_id: u64, _offset: u64, buf: &mut [u8]) -> Result<usize, SyscallError> {
40 let mut count = 0;
41 for slot in buf.iter_mut() {
42 match crate::arch::x86_64::keyboard::read_char() {
43 Some(ch) => {
44 *slot = ch;
45 count += 1;
46 }
47 None => break,
48 }
49 }
50 Ok(count)
51 }
52
53 fn write(&self, _file_id: u64, _offset: u64, buf: &[u8]) -> Result<usize, SyscallError> {
55 if let Ok(s) = core::str::from_utf8(buf) {
56 crate::serial_print!("{}", s);
57 if crate::arch::x86_64::vga::is_available() {
58 crate::vga_print!("{}", s);
59 }
60 } else {
61 for &b in buf {
62 crate::serial_print!("{}", b as char);
63 }
64 }
65 Ok(buf.len())
66 }
67
68 fn close(&self, _file_id: u64) -> Result<(), SyscallError> {
70 Ok(())
71 }
72
73 fn stat(&self, _file_id: u64) -> Result<FileStat, SyscallError> {
75 Ok(finalize_pseudo_stat(
76 FileStat {
77 st_ino: 0,
78 st_mode: 0o020666,
79 st_nlink: 1,
80 st_size: 0,
81 st_blksize: 1,
82 st_blocks: 0,
83 ..FileStat::zeroed()
84 },
85 DEV_CONSOLE,
86 1,
87 ))
88 }
89}
90
91pub fn init_console_scheme() -> Arc<ConsoleScheme> {
93 let scheme = Arc::new(ConsoleScheme::new());
94 *CONSOLE.lock() = Some(scheme.clone());
95 scheme
96}
97
98pub fn setup_stdio(fd_table: &mut FileDescriptorTable) {
100 let scheme = match CONSOLE.lock().clone() {
101 Some(s) => s as DynScheme,
102 None => return,
103 };
104
105 let r0 = scheme.open("console", OpenFlags::READ).unwrap();
107 let stdin = Arc::new(OpenFile::new(
108 scheme.clone(),
109 r0.file_id,
110 String::from("/dev/console"),
111 OpenFlags::READ,
112 FileFlags::DEVICE,
113 None,
114 ));
115 fd_table.insert_at(0, stdin);
116
117 let r1 = scheme.open("console", OpenFlags::WRITE).unwrap();
119 let stdout = Arc::new(OpenFile::new(
120 scheme.clone(),
121 r1.file_id,
122 String::from("/dev/console"),
123 OpenFlags::WRITE,
124 FileFlags::DEVICE,
125 None,
126 ));
127 fd_table.insert_at(1, stdout);
128
129 let r2 = scheme.open("console", OpenFlags::WRITE).unwrap();
131 let stderr = Arc::new(OpenFile::new(
132 scheme,
133 r2.file_id,
134 String::from("/dev/console"),
135 OpenFlags::WRITE,
136 FileFlags::DEVICE,
137 None,
138 ));
139 fd_table.insert_at(2, stderr);
140}