135 lines
3.5 KiB
Rust
135 lines
3.5 KiB
Rust
use core::{cell::LazyCell, fmt::Debug};
|
|
|
|
use alloc::boxed::Box;
|
|
use bffs::{
|
|
Fat32FileSystem,
|
|
path::{Path, PathBuf},
|
|
};
|
|
use hashbrown::HashMap;
|
|
use io::{IoBase, Read, Seek, Write};
|
|
|
|
pub mod keyboard;
|
|
pub mod null;
|
|
pub mod stdin;
|
|
pub mod virtual_stdin;
|
|
|
|
use crate::{
|
|
fs::Disk,
|
|
tty::TTY0,
|
|
vga::Vga,
|
|
virtual_fs::{keyboard::KeyboardBuffer, null::Null, virtual_stdin::VirtualStdin},
|
|
};
|
|
|
|
pub trait VirtualNode: IoBase<Error = ()> + Read + Write + Seek + Debug {
|
|
fn close(&mut self) {}
|
|
}
|
|
|
|
pub trait VirtualFileSystem: Debug {
|
|
fn open(&mut self, path: &Path) -> Result<Box<dyn VirtualNode + '_>, ()>;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct MainFileSystem {
|
|
root: Box<dyn VirtualFileSystem>,
|
|
mounts: HashMap<PathBuf, Box<dyn VirtualFileSystem>>,
|
|
}
|
|
|
|
impl MainFileSystem {
|
|
pub fn mount(&mut self, path: PathBuf, fs: Box<dyn VirtualFileSystem>) {
|
|
self.mounts.insert(path, fs);
|
|
}
|
|
}
|
|
|
|
impl VirtualFileSystem for MainFileSystem {
|
|
fn open(&mut self, path: &Path) -> Result<Box<dyn VirtualNode + '_>, ()> {
|
|
let mut max = &mut self.root;
|
|
let mut max_path = Path::new("/");
|
|
let mut path_remaining = path;
|
|
for (mount, fs) in self.mounts.iter_mut() {
|
|
if path.starts_with(mount) && mount.starts_with(max_path) {
|
|
max = fs;
|
|
max_path = mount;
|
|
path_remaining = path.without(mount);
|
|
}
|
|
}
|
|
max.open(path_remaining)
|
|
}
|
|
}
|
|
|
|
pub static mut FILE_SYSTEM: LazyCell<MainFileSystem> = LazyCell::new(|| MainFileSystem {
|
|
root: Box::new(Fat32FileSystem::new(Disk::new(1024 * 1024 * 16)).unwrap()),
|
|
mounts: HashMap::new(),
|
|
});
|
|
|
|
pub unsafe fn init_file_system() {
|
|
unsafe {
|
|
FILE_SYSTEM.mount("/dev/fb0".into(), Box::new(VGAFileSystem));
|
|
FILE_SYSTEM.mount("/dev/tty0".into(), Box::new(TTY0.clone()));
|
|
FILE_SYSTEM.mount("/dev/null".into(), Box::new(Null));
|
|
FILE_SYSTEM.mount(
|
|
"/dev/input/keyboard".into(),
|
|
Box::new(KeyboardBuffer::new()),
|
|
);
|
|
FILE_SYSTEM.mount("/dev/stdin".into(), Box::new(VirtualStdin::new()));
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct VGAFileSystem;
|
|
|
|
#[derive(Debug)]
|
|
struct VGAVirtualNode {
|
|
position: u64,
|
|
}
|
|
|
|
impl VirtualNode for VGAVirtualNode {}
|
|
|
|
impl IoBase for VGAVirtualNode {
|
|
type Error = ();
|
|
}
|
|
|
|
impl Seek for VGAVirtualNode {
|
|
fn seek(&mut self, pos: io::SeekFrom) -> Result<u64, Self::Error> {
|
|
self.position = match pos {
|
|
io::SeekFrom::Start(v) => v,
|
|
io::SeekFrom::End(v) => {
|
|
((crate::vga::WIDTH * crate::vga::HEIGHT * size_of::<crate::draw::Color>()) as i64
|
|
+ v) as u64
|
|
}
|
|
io::SeekFrom::Current(v) => (self.position as i64 + v) as u64,
|
|
};
|
|
Ok(self.position)
|
|
}
|
|
}
|
|
|
|
impl Read for VGAVirtualNode {
|
|
fn read(&mut self, _buf: &mut [u8]) -> Result<usize, ()> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl Write for VGAVirtualNode {
|
|
fn write(&mut self, buf: &[u8]) -> Result<usize, ()> {
|
|
let start = self.position;
|
|
buf.iter().for_each(|val| {
|
|
unsafe { Vga::write_u8_unsafe(self.position as usize, *val) };
|
|
self.position += 1;
|
|
});
|
|
Ok((self.position - start) as usize)
|
|
}
|
|
|
|
fn flush(&mut self) -> Result<(), Self::Error> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl VirtualFileSystem for VGAFileSystem {
|
|
fn open(&mut self, path: &Path) -> Result<Box<dyn VirtualNode + '_>, ()> {
|
|
if !path.is_empty() {
|
|
Err(())
|
|
} else {
|
|
Ok(Box::new(VGAVirtualNode { position: 0 }))
|
|
}
|
|
}
|
|
}
|