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;
30
31impl ConsoleScheme {
32 pub fn new() -> Self {
34 ConsoleScheme
35 }
36}
37
38impl Scheme for ConsoleScheme {
39 fn open(&self, _path: &str, _flags: OpenFlags) -> Result<OpenResult, SyscallError> {
41 let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
42 Ok(OpenResult {
43 file_id: id,
44 size: None,
45 flags: FileFlags::DEVICE,
46 })
47 }
48
49 fn read(&self, _file_id: u64, _offset: u64, _buf: &mut [u8]) -> Result<usize, SyscallError> {
56 Err(SyscallError::Again)
57 }
58
59 fn write(&self, _file_id: u64, _offset: u64, buf: &[u8]) -> Result<usize, SyscallError> {
65 if let Ok(s) = core::str::from_utf8(buf) {
66 crate::serial_print!("{}", s);
68 if crate::arch::vga::is_available() {
72 crate::vga_print!("{}", s);
73 }
74 } else {
75 for &b in buf {
76 crate::serial_print!("{}", b as char);
77 }
78 }
79 Ok(buf.len())
80 }
81
82 fn close(&self, _file_id: u64) -> Result<(), SyscallError> {
84 Ok(())
85 }
86
87 fn stat(&self, _file_id: u64) -> Result<FileStat, SyscallError> {
89 Ok(finalize_pseudo_stat(
90 FileStat {
91 st_ino: 0,
92 st_mode: 0o020666,
93 st_nlink: 1,
94 st_size: 0,
95 st_blksize: 1,
96 st_blocks: 0,
97 ..FileStat::zeroed()
98 },
99 DEV_CONSOLE,
100 1,
101 ))
102 }
103}
104
105pub fn init_console_scheme() -> Arc<ConsoleScheme> {
107 let scheme = Arc::new(ConsoleScheme::new());
108 *CONSOLE.lock() = Some(scheme.clone());
109 scheme
110}
111
112pub fn setup_stdio(fd_table: &mut FileDescriptorTable) {
114 let scheme = match CONSOLE.lock().clone() {
115 Some(s) => s as DynScheme,
116 None => return,
117 };
118
119 let r0 = match scheme.open("console", OpenFlags::READ) {
121 Ok(r) => r,
122 Err(_) => return,
123 };
124 let stdin = Arc::new(OpenFile::new(
125 scheme.clone(),
126 r0.file_id,
127 String::from("/dev/console"),
128 OpenFlags::READ,
129 FileFlags::DEVICE,
130 None,
131 ));
132 fd_table.insert_at(0, stdin);
133
134 let r1 = match scheme.open("console", OpenFlags::WRITE) {
136 Ok(r) => r,
137 Err(_) => return,
138 };
139 let stdout = Arc::new(OpenFile::new(
140 scheme.clone(),
141 r1.file_id,
142 String::from("/dev/console"),
143 OpenFlags::WRITE,
144 FileFlags::DEVICE,
145 None,
146 ));
147 fd_table.insert_at(1, stdout);
148
149 let r2 = match scheme.open("console", OpenFlags::WRITE) {
151 Ok(r) => r,
152 Err(_) => return,
153 };
154 let stderr = Arc::new(OpenFile::new(
155 scheme,
156 r2.file_id,
157 String::from("/dev/console"),
158 OpenFlags::WRITE,
159 FileFlags::DEVICE,
160 None,
161 ));
162 fd_table.insert_at(2, stderr);
163}