1use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
6
7#[cfg(not(target_arch = "aarch64"))]
8use spin::RwLock;
9
10#[cfg(target_arch = "aarch64")]
11use super::bare_lock::RwLock;
12use super::{DirEntry, Filesystem, Metadata, NodeType, Permissions, VfsNode};
13use crate::error::{FsError, KernelError};
14
15struct DevNode {
17 name: String,
18 node_type: NodeType,
19 _major: u32,
20 _minor: u32,
21 permissions: Permissions,
22}
23
24impl DevNode {
25 fn new_char(name: String, major: u32, minor: u32) -> Self {
26 Self {
27 name,
28 node_type: NodeType::CharDevice,
29 _major: major,
30 _minor: minor,
31 permissions: Permissions::default(),
32 }
33 }
34
35 #[allow(dead_code)] fn new_block(name: String, major: u32, minor: u32) -> Self {
37 Self {
38 name,
39 node_type: NodeType::BlockDevice,
40 _major: major,
41 _minor: minor,
42 permissions: Permissions::default(),
43 }
44 }
45}
46
47impl VfsNode for DevNode {
48 fn node_type(&self) -> NodeType {
49 self.node_type
50 }
51
52 fn read(&self, _offset: usize, buffer: &mut [u8]) -> Result<usize, KernelError> {
53 match self.name.as_str() {
55 "null" => {
56 Ok(0)
58 }
59 "zero" => {
60 buffer.fill(0);
62 Ok(buffer.len())
63 }
64 "random" | "urandom" => {
65 for byte in buffer.iter_mut() {
67 *byte = (crate::read_timestamp() & 0xFF) as u8;
68 }
69 Ok(buffer.len())
70 }
71 "console" | "tty0" => {
72 #[cfg(target_arch = "x86_64")]
79 {
80 use crate::drivers::terminal;
81
82 let canonical = terminal::is_canonical_mode();
83 let echo = terminal::is_echo_enabled();
84 let verase = terminal::get_verase();
85 let vmin = terminal::get_vmin() as usize;
86
87 if canonical {
88 let mut line_buf: [u8; 4096] = [0u8; 4096];
97 let mut line_len: usize = 0;
98
99 loop {
100 let byte = loop {
101 let lsr: u8;
102 unsafe {
104 core::arch::asm!(
105 "in al, dx",
106 out("al") lsr,
107 in("dx") 0x3FDu16,
108 options(nomem, nostack)
109 );
110 }
111 if lsr & 1 != 0 {
112 let data: u8;
113 unsafe {
115 core::arch::asm!(
116 "in al, dx",
117 out("al") data,
118 in("dx") 0x3F8u16,
119 options(nomem, nostack)
120 );
121 }
122 break data;
123 }
124 core::hint::spin_loop();
125 };
126
127 if byte == verase || byte == 8 {
129 if line_len > 0 {
131 line_len -= 1;
132 if echo {
133 for &b in &[8u8, b' ', 8u8] {
135 unsafe {
137 while {
138 let s: u8;
139 core::arch::asm!(
140 "in al, dx",
141 out("al") s,
142 in("dx") 0x3FDu16,
143 options(nomem, nostack)
144 );
145 s & 0x20 == 0
146 } {
147 core::hint::spin_loop();
148 }
149 core::arch::asm!(
150 "out dx, al",
151 in("al") b,
152 in("dx") 0x3F8u16,
153 options(nomem, nostack)
154 );
155 }
156 }
157 }
158 }
159 continue;
160 }
161
162 let byte = if byte == b'\r' { b'\n' } else { byte };
164
165 if line_len < line_buf.len() {
167 line_buf[line_len] = byte;
168 line_len += 1;
169 }
170
171 if echo {
173 let echo_byte = byte;
174 unsafe {
176 while {
177 let s: u8;
178 core::arch::asm!(
179 "in al, dx",
180 out("al") s,
181 in("dx") 0x3FDu16,
182 options(nomem, nostack)
183 );
184 s & 0x20 == 0
185 } {
186 core::hint::spin_loop();
187 }
188 core::arch::asm!(
189 "out dx, al",
190 in("al") echo_byte,
191 in("dx") 0x3F8u16,
192 options(nomem, nostack)
193 );
194 if echo_byte == b'\n' {
196 while {
197 let s: u8;
198 core::arch::asm!(
199 "in al, dx",
200 out("al") s,
201 in("dx") 0x3FDu16,
202 options(nomem, nostack)
203 );
204 s & 0x20 == 0
205 } {
206 core::hint::spin_loop();
207 }
208 core::arch::asm!(
209 "out dx, al",
210 in("al") b'\r',
211 in("dx") 0x3F8u16,
212 options(nomem, nostack)
213 );
214 }
215 }
216 }
217
218 if byte == b'\n' || byte == 4 {
220 let copy_len = line_len.min(buffer.len());
222 buffer[..copy_len].copy_from_slice(&line_buf[..copy_len]);
223 return Ok(copy_len);
224 }
225 }
226 } else {
227 let target = if vmin == 0 { 1 } else { vmin.min(buffer.len()) };
230 let max_spins: u64 = if terminal::get_vtime() > 0 {
231 (terminal::get_vtime() as u64) * 10_000_000
233 } else if vmin == 0 {
234 1
236 } else {
237 u64::MAX
239 };
240
241 let mut bytes_read = 0usize;
242 let mut total_spins: u64 = 0;
243
244 while bytes_read < target {
245 let lsr: u8;
246 unsafe {
248 core::arch::asm!(
249 "in al, dx",
250 out("al") lsr,
251 in("dx") 0x3FDu16,
252 options(nomem, nostack)
253 );
254 }
255 if lsr & 1 != 0 {
256 let data: u8;
257 unsafe {
259 core::arch::asm!(
260 "in al, dx",
261 out("al") data,
262 in("dx") 0x3F8u16,
263 options(nomem, nostack)
264 );
265 }
266 buffer[bytes_read] = data;
267 bytes_read += 1;
268
269 if echo {
271 unsafe {
273 while {
274 let s: u8;
275 core::arch::asm!(
276 "in al, dx",
277 out("al") s,
278 in("dx") 0x3FDu16,
279 options(nomem, nostack)
280 );
281 s & 0x20 == 0
282 } {
283 core::hint::spin_loop();
284 }
285 core::arch::asm!(
286 "out dx, al",
287 in("al") data,
288 in("dx") 0x3F8u16,
289 options(nomem, nostack)
290 );
291 }
292 }
293
294 total_spins = 0;
296 } else {
297 total_spins += 1;
298 if total_spins >= max_spins {
299 break;
300 }
301 core::hint::spin_loop();
302 }
303 }
304
305 Ok(bytes_read)
306 }
307 }
308 #[cfg(not(target_arch = "x86_64"))]
310 {
311 let _ = buffer;
312 Ok(0)
313 }
314 }
315 "input/event0" | "input/event1" => {
317 let minor = self._minor;
318 let bytes_read = crate::drivers::evdev::read_device(minor, buffer);
319 Ok(bytes_read)
320 }
321 "dri/card0" | "dri/renderD128" => {
323 Ok(0)
326 }
327 _ => {
328 if let Some(fw) = crate::services::driver_framework::try_get_driver_framework() {
330 let devices = fw.list_devices();
332 for dev in &devices {
333 if let Some(ref driver_name) = dev.driver {
334 if dev.name == self.name {
336 return fw.read_device(dev.id, _offset as u64, buffer).map_err(
338 |_| KernelError::OperationNotSupported {
339 operation: "device read failed",
340 },
341 );
342 }
343 let _ = driver_name; }
345 }
346 }
347 Err(KernelError::OperationNotSupported {
348 operation: "read on unregistered device",
349 })
350 }
351 }
352 }
353
354 fn write(&self, _offset: usize, data: &[u8]) -> Result<usize, KernelError> {
355 match self.name.as_str() {
356 "null" => {
357 Ok(data.len())
359 }
360 "console" | "tty0" => {
361 for &_byte in data {
363 crate::print!("{}", _byte as char);
364 }
365 Ok(data.len())
366 }
367 _ => {
368 if let Some(fw) = crate::services::driver_framework::try_get_driver_framework() {
370 let devices = fw.list_devices();
371 for dev in &devices {
372 if let Some(ref driver_name) = dev.driver {
373 if dev.name == self.name {
374 return fw.write_device(dev.id, _offset as u64, data).map_err(
375 |_| KernelError::OperationNotSupported {
376 operation: "device write failed",
377 },
378 );
379 }
380 let _ = driver_name;
381 }
382 }
383 }
384 Err(KernelError::OperationNotSupported {
385 operation: "write on unregistered device",
386 })
387 }
388 }
389 }
390
391 fn metadata(&self) -> Result<Metadata, KernelError> {
392 Ok(Metadata {
393 node_type: self.node_type,
394 size: 0,
395 permissions: self.permissions,
396 uid: 0,
397 gid: 0,
398 created: 0,
399 modified: 0,
400 accessed: 0,
401 inode: 0,
402 })
403 }
404
405 fn readdir(&self) -> Result<Vec<DirEntry>, KernelError> {
406 Err(KernelError::FsError(FsError::NotADirectory))
407 }
408
409 fn lookup(&self, _name: &str) -> Result<Arc<dyn VfsNode>, KernelError> {
410 Err(KernelError::FsError(FsError::NotADirectory))
411 }
412
413 fn create(
414 &self,
415 _name: &str,
416 _permissions: Permissions,
417 ) -> Result<Arc<dyn VfsNode>, KernelError> {
418 Err(KernelError::OperationNotSupported {
419 operation: "create in device node",
420 })
421 }
422
423 fn mkdir(
424 &self,
425 _name: &str,
426 _permissions: Permissions,
427 ) -> Result<Arc<dyn VfsNode>, KernelError> {
428 Err(KernelError::OperationNotSupported {
429 operation: "mkdir in device node",
430 })
431 }
432
433 fn unlink(&self, _name: &str) -> Result<(), KernelError> {
434 Err(KernelError::OperationNotSupported {
435 operation: "unlink device node",
436 })
437 }
438
439 fn truncate(&self, _size: usize) -> Result<(), KernelError> {
440 Err(KernelError::OperationNotSupported {
441 operation: "truncate device node",
442 })
443 }
444}
445
446struct DevSubDir {
450 #[allow(dead_code)] name: String,
452 devices: RwLock<BTreeMap<String, Arc<DevNode>>>,
453}
454
455impl DevSubDir {
456 fn new(name: String) -> Self {
457 Self {
458 name,
459 devices: RwLock::new(BTreeMap::new()),
460 }
461 }
462
463 fn add_device(&self, dev_name: String, node: Arc<DevNode>) {
464 self.devices.write().insert(dev_name, node);
465 }
466}
467
468impl VfsNode for DevSubDir {
469 fn node_type(&self) -> NodeType {
470 NodeType::Directory
471 }
472
473 fn read(&self, _offset: usize, buffer: &mut [u8]) -> Result<usize, KernelError> {
474 let _ = buffer;
478 Err(KernelError::FsError(FsError::IsADirectory))
479 }
480
481 fn write(&self, _offset: usize, _data: &[u8]) -> Result<usize, KernelError> {
482 Err(KernelError::FsError(FsError::IsADirectory))
483 }
484
485 fn metadata(&self) -> Result<Metadata, KernelError> {
486 Ok(Metadata {
487 node_type: NodeType::Directory,
488 size: 0,
489 permissions: Permissions::default(),
490 uid: 0,
491 gid: 0,
492 created: 0,
493 modified: 0,
494 accessed: 0,
495 inode: 0,
496 })
497 }
498
499 fn readdir(&self) -> Result<Vec<DirEntry>, KernelError> {
500 let devices = self.devices.read();
501 let mut entries = Vec::new();
502
503 entries.push(DirEntry {
504 name: String::from("."),
505 node_type: NodeType::Directory,
506 inode: 0,
507 });
508
509 entries.push(DirEntry {
510 name: String::from(".."),
511 node_type: NodeType::Directory,
512 inode: 0,
513 });
514
515 for (name, device) in devices.iter() {
516 entries.push(DirEntry {
517 name: name.clone(),
518 node_type: device.node_type,
519 inode: 0,
520 });
521 }
522
523 Ok(entries)
524 }
525
526 fn lookup(&self, name: &str) -> Result<Arc<dyn VfsNode>, KernelError> {
527 let devices = self.devices.read();
528 devices
529 .get(name)
530 .map(|node| node.clone() as Arc<dyn VfsNode>)
531 .ok_or(KernelError::FsError(FsError::NotFound))
532 }
533
534 fn create(
535 &self,
536 _name: &str,
537 _permissions: Permissions,
538 ) -> Result<Arc<dyn VfsNode>, KernelError> {
539 Err(KernelError::OperationNotSupported {
540 operation: "create in device subdir",
541 })
542 }
543
544 fn mkdir(
545 &self,
546 _name: &str,
547 _permissions: Permissions,
548 ) -> Result<Arc<dyn VfsNode>, KernelError> {
549 Err(KernelError::OperationNotSupported {
550 operation: "mkdir in device subdir",
551 })
552 }
553
554 fn unlink(&self, _name: &str) -> Result<(), KernelError> {
555 Err(KernelError::OperationNotSupported {
556 operation: "unlink device subdir node",
557 })
558 }
559
560 fn truncate(&self, _size: usize) -> Result<(), KernelError> {
561 Err(KernelError::FsError(FsError::IsADirectory))
562 }
563}
564
565struct DevRoot {
567 devices: RwLock<BTreeMap<String, Arc<DevNode>>>,
568 subdirs: RwLock<BTreeMap<String, Arc<DevSubDir>>>,
570}
571
572impl DevRoot {
573 fn new() -> Self {
574 let mut devices = BTreeMap::new();
575
576 devices.insert(
578 String::from("null"),
579 Arc::new(DevNode::new_char(String::from("null"), 1, 3)),
580 );
581
582 devices.insert(
583 String::from("zero"),
584 Arc::new(DevNode::new_char(String::from("zero"), 1, 5)),
585 );
586
587 devices.insert(
588 String::from("random"),
589 Arc::new(DevNode::new_char(String::from("random"), 1, 8)),
590 );
591
592 devices.insert(
593 String::from("urandom"),
594 Arc::new(DevNode::new_char(String::from("urandom"), 1, 9)),
595 );
596
597 devices.insert(
598 String::from("console"),
599 Arc::new(DevNode::new_char(String::from("console"), 5, 1)),
600 );
601
602 devices.insert(
603 String::from("tty0"),
604 Arc::new(DevNode::new_char(String::from("tty0"), 4, 0)),
605 );
606
607 let dri_dir = Arc::new(DevSubDir::new(String::from("dri")));
609 dri_dir.add_device(
610 String::from("card0"),
611 Arc::new(DevNode::new_char(String::from("dri/card0"), 226, 0)),
612 );
613 dri_dir.add_device(
614 String::from("renderD128"),
615 Arc::new(DevNode::new_char(String::from("dri/renderD128"), 226, 128)),
616 );
617
618 let input_dir = Arc::new(DevSubDir::new(String::from("input")));
620 input_dir.add_device(
621 String::from("event0"),
622 Arc::new(DevNode::new_char(String::from("input/event0"), 13, 64)),
623 );
624 input_dir.add_device(
625 String::from("event1"),
626 Arc::new(DevNode::new_char(String::from("input/event1"), 13, 65)),
627 );
628
629 let mut subdirs = BTreeMap::new();
630 subdirs.insert(String::from("dri"), dri_dir);
631 subdirs.insert(String::from("input"), input_dir);
632
633 Self {
634 devices: RwLock::new(devices),
635 subdirs: RwLock::new(subdirs),
636 }
637 }
638}
639
640impl VfsNode for DevRoot {
641 fn node_type(&self) -> NodeType {
642 NodeType::Directory
643 }
644
645 fn read(&self, _offset: usize, _buffer: &mut [u8]) -> Result<usize, KernelError> {
646 Err(KernelError::FsError(FsError::IsADirectory))
647 }
648
649 fn write(&self, _offset: usize, _data: &[u8]) -> Result<usize, KernelError> {
650 Err(KernelError::FsError(FsError::IsADirectory))
651 }
652
653 fn metadata(&self) -> Result<Metadata, KernelError> {
654 Ok(Metadata {
655 node_type: NodeType::Directory,
656 size: 0,
657 permissions: Permissions::default(),
658 uid: 0,
659 gid: 0,
660 created: 0,
661 modified: 0,
662 accessed: 0,
663 inode: 0,
664 })
665 }
666
667 fn readdir(&self) -> Result<Vec<DirEntry>, KernelError> {
668 let devices = self.devices.read();
669 let subdirs = self.subdirs.read();
670 let mut entries = Vec::new();
671
672 entries.push(DirEntry {
673 name: String::from("."),
674 node_type: NodeType::Directory,
675 inode: 0,
676 });
677
678 entries.push(DirEntry {
679 name: String::from(".."),
680 node_type: NodeType::Directory,
681 inode: 0,
682 });
683
684 for (name, _) in subdirs.iter() {
686 entries.push(DirEntry {
687 name: name.clone(),
688 node_type: NodeType::Directory,
689 inode: 0,
690 });
691 }
692
693 for (name, device) in devices.iter() {
694 entries.push(DirEntry {
695 name: name.clone(),
696 node_type: device.node_type,
697 inode: 0,
698 });
699 }
700
701 Ok(entries)
702 }
703
704 fn lookup(&self, name: &str) -> Result<Arc<dyn VfsNode>, KernelError> {
705 {
707 let subdirs = self.subdirs.read();
708 if let Some(subdir) = subdirs.get(name) {
709 return Ok(subdir.clone() as Arc<dyn VfsNode>);
710 }
711 }
712
713 let devices = self.devices.read();
714 devices
715 .get(name)
716 .map(|node| node.clone() as Arc<dyn VfsNode>)
717 .ok_or(KernelError::FsError(FsError::NotFound))
718 }
719
720 fn create(
721 &self,
722 _name: &str,
723 _permissions: Permissions,
724 ) -> Result<Arc<dyn VfsNode>, KernelError> {
725 Err(KernelError::OperationNotSupported {
726 operation: "create in /dev",
727 })
728 }
729
730 fn mkdir(
731 &self,
732 _name: &str,
733 _permissions: Permissions,
734 ) -> Result<Arc<dyn VfsNode>, KernelError> {
735 Err(KernelError::OperationNotSupported {
736 operation: "mkdir in /dev",
737 })
738 }
739
740 fn unlink(&self, _name: &str) -> Result<(), KernelError> {
741 Err(KernelError::OperationNotSupported {
742 operation: "unlink in /dev",
743 })
744 }
745
746 fn truncate(&self, _size: usize) -> Result<(), KernelError> {
747 Err(KernelError::FsError(FsError::IsADirectory))
748 }
749}
750
751pub struct DevFs {
753 root: Arc<DevRoot>,
754}
755
756impl DevFs {
757 pub fn new() -> Self {
758 Self {
759 root: Arc::new(DevRoot::new()),
760 }
761 }
762}
763
764impl Default for DevFs {
765 fn default() -> Self {
766 Self::new()
767 }
768}
769
770impl Filesystem for DevFs {
771 fn root(&self) -> Arc<dyn VfsNode> {
772 self.root.clone() as Arc<dyn VfsNode>
773 }
774
775 fn name(&self) -> &str {
776 "devfs"
777 }
778
779 fn is_readonly(&self) -> bool {
780 false
781 }
782
783 fn sync(&self) -> Result<(), KernelError> {
784 Ok(())
785 }
786}