better (but still bad) vfs solution
This commit is contained in:
2
Makefile
2
Makefile
@@ -199,7 +199,7 @@ run-aarch64:
|
|||||||
qemu-system-aarch64 ${QEMU_OPTS} -cpu cortex-a72 -device ramfb -device qemu-xhci -device usb-kbd -boot d
|
qemu-system-aarch64 ${QEMU_OPTS} -cpu cortex-a72 -device ramfb -device qemu-xhci -device usb-kbd -boot d
|
||||||
|
|
||||||
line-count:
|
line-count:
|
||||||
cloc --quiet --exclude-dir=bin --csv src/ | tail -n 1 | awk -F, '{print $$5}'
|
cloc --quiet --exclude-dir=bin --include-lang=Rust --csv src/ | tail -n 1 | awk -F, '{print $$5}'
|
||||||
clean:
|
clean:
|
||||||
cargo clean
|
cargo clean
|
||||||
rm -rf ${ARTIFACTS_PATH}
|
rm -rf ${ARTIFACTS_PATH}
|
||||||
|
|||||||
@@ -49,11 +49,8 @@ fn get_function_name(function_address: u64) -> Result<(String, u64), ()> {
|
|||||||
// TODO: dont rely on initramfs being mounted at /
|
// TODO: dont rely on initramfs being mounted at /
|
||||||
let mut symbols_fd = vfs_open("/symbols.table")?;
|
let mut symbols_fd = vfs_open("/symbols.table")?;
|
||||||
|
|
||||||
let symbols_table_bytes = symbols_fd.ops.open(
|
let symbols_table_bytes =
|
||||||
0,
|
symbols_fd.open(0, crate::drivers::fs::vfs::UserCred { uid: 0, gid: 0 })?;
|
||||||
crate::drivers::fs::vfs::UserCred { uid: 0, gid: 0 },
|
|
||||||
symbols_fd.as_ptr(),
|
|
||||||
)?;
|
|
||||||
let symbols_table = core::str::from_utf8(&symbols_table_bytes).ok().ok_or(())?;
|
let symbols_table = core::str::from_utf8(&symbols_table_bytes).ok().ok_or(())?;
|
||||||
|
|
||||||
let mut previous_symbol: Option<(&str, u64)> = None;
|
let mut previous_symbol: Option<(&str, u64)> = None;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use alloc::{boxed::Box, string::String, sync::Arc};
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
|
use alloc::{string::String, sync::Arc};
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum DeviceType {
|
pub enum DeviceType {
|
||||||
@@ -11,7 +13,7 @@ pub struct Device {
|
|||||||
typ: DeviceType,
|
typ: DeviceType,
|
||||||
block_size: usize,
|
block_size: usize,
|
||||||
name: String,
|
name: String,
|
||||||
ops: Box<dyn DeviceOperations>,
|
ops: NonNull<dyn DeviceOperations>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DeviceOperations {
|
pub trait DeviceOperations {
|
||||||
|
|||||||
@@ -534,17 +534,7 @@ impl FsOps for FatFs {
|
|||||||
directory_cluster: root_cluster,
|
directory_cluster: root_cluster,
|
||||||
});
|
});
|
||||||
|
|
||||||
return super::vfs::VNode {
|
return VNode::new(Box::new(file), super::vfs::VNodeType::Directory, vfsp);
|
||||||
flags: 0,
|
|
||||||
ref_count: 0,
|
|
||||||
shared_lock_count: 0,
|
|
||||||
exclusive_lock_count: 0,
|
|
||||||
ops: Box::new(file),
|
|
||||||
node_data: None,
|
|
||||||
parent: vfsp,
|
|
||||||
typ: super::vfs::VNodeType::Directory,
|
|
||||||
data: core::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fid(&mut self, _path: &str, _vfsp: *const super::vfs::Vfs) -> Option<super::vfs::FileId> {
|
fn fid(&mut self, _path: &str, _vfsp: *const super::vfs::Vfs) -> Option<super::vfs::FileId> {
|
||||||
@@ -573,7 +563,7 @@ enum File {
|
|||||||
Dir(FatDirectory),
|
Dir(FatDirectory),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VNodeOperations for File {
|
impl VNodeOperations for File {
|
||||||
fn access(&mut self, _m: u32, _c: super::vfs::UserCred, _vp: *const VNode) {
|
fn access(&mut self, _m: u32, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||||
todo!("VNODE OPERATIONS");
|
todo!("VNODE OPERATIONS");
|
||||||
}
|
}
|
||||||
@@ -641,7 +631,7 @@ impl<'a> VNodeOperations for File {
|
|||||||
_c: super::vfs::UserCred,
|
_c: super::vfs::UserCred,
|
||||||
vp: *const VNode,
|
vp: *const VNode,
|
||||||
) -> Result<super::vfs::VNode, ()> {
|
) -> Result<super::vfs::VNode, ()> {
|
||||||
let fat_fs = unsafe { (*(*vp).parent).data.cast::<FatFs>() };
|
let fat_fs = unsafe { (*(*vp).parent_vfs).data.cast::<FatFs>() };
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
File::Dir(directory) => unsafe {
|
File::Dir(directory) => unsafe {
|
||||||
@@ -662,17 +652,7 @@ impl<'a> VNodeOperations for File {
|
|||||||
File::Archive(FatFile { file_entry })
|
File::Archive(FatFile { file_entry })
|
||||||
};
|
};
|
||||||
|
|
||||||
let vnode = VNode {
|
let vnode = VNode::new(Box::new(file), file_typ, (*vp).parent_vfs);
|
||||||
flags: 0,
|
|
||||||
ref_count: 0,
|
|
||||||
shared_lock_count: 0,
|
|
||||||
exclusive_lock_count: 0,
|
|
||||||
ops: Box::new(file),
|
|
||||||
node_data: None,
|
|
||||||
parent: (*vp).parent,
|
|
||||||
typ: file_typ,
|
|
||||||
data: core::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(vnode)
|
Ok(vnode)
|
||||||
},
|
},
|
||||||
@@ -698,7 +678,7 @@ impl<'a> VNodeOperations for File {
|
|||||||
) -> Result<Arc<[u8]>, ()> {
|
) -> Result<Arc<[u8]>, ()> {
|
||||||
match self {
|
match self {
|
||||||
File::Archive(archive) => {
|
File::Archive(archive) => {
|
||||||
let fat_fs = unsafe { (*(*vp).parent).data.cast::<FatFs>() };
|
let fat_fs = unsafe { (*(*vp).parent_vfs).data.cast::<FatFs>() };
|
||||||
|
|
||||||
let mut file: Vec<u8> = Vec::with_capacity(archive.file_entry.file_size as usize);
|
let mut file: Vec<u8> = Vec::with_capacity(archive.file_entry.file_size as usize);
|
||||||
let mut file_ptr_index = 0;
|
let mut file_ptr_index = 0;
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ impl<'a, F: Fn(&[u8]) -> Result<Vec<u8>, ()>> ChunkReader<'a, F> {
|
|||||||
|
|
||||||
while total_length != chunk {
|
while total_length != chunk {
|
||||||
chunk_idx += 1;
|
chunk_idx += 1;
|
||||||
total_length += (self.chunks[0].len() as usize + HEADER_SIZE) as u64;
|
total_length += (self.chunks[0].len() + HEADER_SIZE) as u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = chunk_idx;
|
chunk = chunk_idx;
|
||||||
@@ -132,7 +132,7 @@ impl<'a, F: Fn(&[u8]) -> Result<Vec<u8>, ()>> ChunkReader<'a, F> {
|
|||||||
block_end = block_start + size;
|
block_end = block_start + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.extend(self.chunks[i][block_start..block_end].into_iter());
|
data.extend(self.chunks[i][block_start..block_end].iter());
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ impl Squashfs<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_inode_block_offset(&self, inode: u64) -> (u64, u16) {
|
fn get_inode_block_offset(&self, inode: u64) -> (u64, u16) {
|
||||||
let inode_block = ((inode >> 16) & 0x0000FFFFFFFFFFFF) as u64;
|
let inode_block = (inode >> 16) & 0x0000FFFFFFFFFFFF;
|
||||||
let inode_offset = (inode & 0xFFFF) as u16;
|
let inode_offset = (inode & 0xFFFF) as u16;
|
||||||
|
|
||||||
(inode_block, inode_offset)
|
(inode_block, inode_offset)
|
||||||
@@ -359,17 +359,7 @@ impl<'a> FsOps for Squashfs<'a> {
|
|||||||
fn root(&mut self, vfsp: *const super::vfs::Vfs) -> super::vfs::VNode {
|
fn root(&mut self, vfsp: *const super::vfs::Vfs) -> super::vfs::VNode {
|
||||||
let root_dir = self.read_root_dir();
|
let root_dir = self.read_root_dir();
|
||||||
|
|
||||||
super::vfs::VNode {
|
return VNode::new(Box::new(root_dir), VNodeType::Directory, vfsp);
|
||||||
flags: 0,
|
|
||||||
ref_count: 0,
|
|
||||||
shared_lock_count: 0,
|
|
||||||
exclusive_lock_count: 0,
|
|
||||||
ops: Box::new(root_dir),
|
|
||||||
node_data: None,
|
|
||||||
parent: vfsp,
|
|
||||||
typ: super::vfs::VNodeType::Directory,
|
|
||||||
data: core::ptr::null_mut(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fid(&mut self, _path: &str, _vfspp: *const super::vfs::Vfs) -> Option<super::vfs::FileId> {
|
fn fid(&mut self, _path: &str, _vfspp: *const super::vfs::Vfs) -> Option<super::vfs::FileId> {
|
||||||
@@ -424,7 +414,7 @@ impl VNodeOperations for Inode {
|
|||||||
_c: super::vfs::UserCred,
|
_c: super::vfs::UserCred,
|
||||||
vp: *const VNode,
|
vp: *const VNode,
|
||||||
) -> Result<Arc<[u8]>, ()> {
|
) -> Result<Arc<[u8]>, ()> {
|
||||||
let squashfs = unsafe { (*(*vp).parent).data.cast::<Squashfs>() };
|
let squashfs = unsafe { (*(*vp).parent_vfs).data.cast::<Squashfs>() };
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Inode::BasicFile(file) => unsafe {
|
Inode::BasicFile(file) => unsafe {
|
||||||
@@ -556,7 +546,7 @@ impl VNodeOperations for Inode {
|
|||||||
_c: super::vfs::UserCred,
|
_c: super::vfs::UserCred,
|
||||||
vp: *const VNode,
|
vp: *const VNode,
|
||||||
) -> Result<super::vfs::VNode, ()> {
|
) -> Result<super::vfs::VNode, ()> {
|
||||||
let squashfs = unsafe { (*(*vp).parent).data.cast::<Squashfs>() };
|
let squashfs = unsafe { (*(*vp).parent_vfs).data.cast::<Squashfs>() };
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Inode::BasicDirectory(_) | Inode::ExtendedDirectory(_) => unsafe {
|
Inode::BasicDirectory(_) | Inode::ExtendedDirectory(_) => unsafe {
|
||||||
@@ -566,17 +556,7 @@ impl VNodeOperations for Inode {
|
|||||||
Inode::BasicFile(_) => VNodeType::Regular,
|
Inode::BasicFile(_) => VNodeType::Regular,
|
||||||
};
|
};
|
||||||
|
|
||||||
let vnode = VNode {
|
let vnode = VNode::new(Box::new(inode), vnode_type, (*vp).parent_vfs);
|
||||||
flags: 0,
|
|
||||||
ref_count: 0,
|
|
||||||
shared_lock_count: 0,
|
|
||||||
exclusive_lock_count: 0,
|
|
||||||
ops: Box::new(inode),
|
|
||||||
node_data: None,
|
|
||||||
parent: (*vp).parent,
|
|
||||||
typ: vnode_type,
|
|
||||||
data: core::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(vnode);
|
return Ok(vnode);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// is this terrible? God yes, but it works
|
||||||
|
|
||||||
use core::{fmt::Debug, ptr::NonNull};
|
use core::{fmt::Debug, ptr::NonNull};
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
@@ -38,12 +40,66 @@ impl Vfs {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ptr(&self) -> *const Vfs {
|
fn as_ptr(&self) -> *const Self {
|
||||||
core::ptr::addr_of!(*self)
|
core::ptr::addr_of!(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_mut_ptr(&mut self) -> *mut Vfs {
|
pub fn mount(&mut self, path: &str) {
|
||||||
core::ptr::addr_of_mut!(*self)
|
if self.ops.is_none() {
|
||||||
|
panic!("FsOps is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
let vfsp = self.as_ptr();
|
||||||
|
|
||||||
|
unsafe { self.ops.unwrap().as_mut().mount(path, &mut self.data, vfsp) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unmount(&mut self) {
|
||||||
|
if self.ops.is_none() {
|
||||||
|
panic!("FsOps is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.ops.unwrap().as_mut().unmount(self.as_ptr()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root(&mut self) -> VNode {
|
||||||
|
if self.ops.is_none() {
|
||||||
|
panic!("FsOps is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.ops.unwrap().as_mut().root(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn statfs(&mut self) -> StatFs {
|
||||||
|
if self.ops.is_none() {
|
||||||
|
panic!("FsOps is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.ops.unwrap().as_mut().statfs(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sync(&mut self) {
|
||||||
|
if self.ops.is_none() {
|
||||||
|
panic!("FsOps is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.ops.unwrap().as_mut().sync(self.as_ptr()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fid(&mut self, path: &str) -> Option<FileId> {
|
||||||
|
if self.ops.is_none() {
|
||||||
|
panic!("FsOps is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.ops.unwrap().as_mut().fid(path, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vget(&mut self, fid: FileId) -> VNode {
|
||||||
|
if self.ops.is_none() {
|
||||||
|
panic!("FsOps is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.ops.unwrap().as_mut().vget(fid, self.as_ptr()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,21 +149,162 @@ pub enum VNodeType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct VNode {
|
pub struct VNode {
|
||||||
|
// for internal use only
|
||||||
|
relative_path: String,
|
||||||
pub flags: u16,
|
pub flags: u16,
|
||||||
pub ref_count: u16,
|
pub ref_count: u16,
|
||||||
pub shared_lock_count: u16,
|
pub shared_lock_count: u16,
|
||||||
pub exclusive_lock_count: u16,
|
pub exclusive_lock_count: u16,
|
||||||
pub ops: Box<dyn VNodeOperations>,
|
ops: NonNull<dyn VNodeOperations>,
|
||||||
pub node_data: Option<NodeData>,
|
pub node_data: Option<NodeData>,
|
||||||
pub parent: *const Vfs,
|
pub parent_vfs: *const Vfs,
|
||||||
pub typ: VNodeType,
|
pub typ: VNodeType,
|
||||||
pub data: *mut u8,
|
pub data: *mut u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VNode {
|
impl VNode {
|
||||||
|
pub fn new(ops: Box<dyn VNodeOperations>, file_typ: VNodeType, parent_vfs: *const Vfs) -> Self {
|
||||||
|
return Self {
|
||||||
|
relative_path: "".to_string(),
|
||||||
|
flags: 0,
|
||||||
|
ref_count: 0,
|
||||||
|
shared_lock_count: 0,
|
||||||
|
exclusive_lock_count: 0,
|
||||||
|
ops: unsafe { NonNull::new_unchecked(Box::into_raw(ops)) },
|
||||||
|
node_data: None,
|
||||||
|
parent_vfs,
|
||||||
|
typ: file_typ,
|
||||||
|
data: core::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_ptr(&self) -> *const VNode {
|
pub fn as_ptr(&self) -> *const VNode {
|
||||||
core::ptr::addr_of!(*self)
|
core::ptr::addr_of!(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trait functions
|
||||||
|
pub fn open(&mut self, f: u32, c: UserCred) -> Result<Arc<[u8]>, ()> {
|
||||||
|
unsafe { self.ops.as_mut().open(f, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(&mut self, f: u32, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().close(f, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rdwr(&mut self, uiop: *const UIO, direction: IODirection, f: u32, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().rdwr(uiop, direction, f, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ioctl(&mut self, com: u32, d: *mut u8, f: u32, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().ioctl(com, d, f, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select(&mut self, w: IODirection, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().select(w, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getattr(&mut self, c: UserCred) -> VAttr {
|
||||||
|
unsafe { self.ops.as_mut().getattr(c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setattr(&mut self, va: VAttr, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().setattr(va, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn access(&mut self, m: u32, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().access(m, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup(&mut self, nm: &str, c: UserCred) -> Result<VNode, ()> {
|
||||||
|
let mut vnode = unsafe { self.ops.as_mut().lookup(nm, c, self.as_ptr()) }?;
|
||||||
|
|
||||||
|
// TODO: the memory cost of this is pretty bad
|
||||||
|
vnode.relative_path = self.relative_path.clone() + "/" + nm;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if let Some(mut new_vfs) = vfs_has_mount_point(
|
||||||
|
&((*self.parent_vfs).mount_point.clone().unwrap() + &vnode.relative_path),
|
||||||
|
) {
|
||||||
|
return Ok(new_vfs.as_mut().root());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(vnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(
|
||||||
|
&mut self,
|
||||||
|
nm: &str,
|
||||||
|
va: VAttr,
|
||||||
|
e: u32,
|
||||||
|
m: u32,
|
||||||
|
c: UserCred,
|
||||||
|
) -> Result<VNode, ()> {
|
||||||
|
unsafe { self.ops.as_mut().create(nm, va, e, m, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn link(&mut self, target_dir: *mut VNode, target_name: &str, c: UserCred) {
|
||||||
|
unsafe {
|
||||||
|
self.ops
|
||||||
|
.as_mut()
|
||||||
|
.link(target_dir, target_name, c, self.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rename(&mut self, nm: &str, target_dir: *mut VNode, target_name: &str, c: UserCred) {
|
||||||
|
unsafe {
|
||||||
|
self.ops
|
||||||
|
.as_mut()
|
||||||
|
.rename(nm, target_dir, target_name, c, self.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mkdir(&mut self, nm: &str, va: VAttr, c: UserCred) -> Result<VNode, ()> {
|
||||||
|
unsafe { self.ops.as_mut().mkdir(nm, va, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readdir(&mut self, uiop: *const UIO, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().readdir(uiop, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symlink(&mut self, link_name: &str, va: VAttr, target_name: &str, c: UserCred) {
|
||||||
|
unsafe {
|
||||||
|
self.ops
|
||||||
|
.as_mut()
|
||||||
|
.symlink(link_name, va, target_name, c, self.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readlink(&mut self, uiop: *const UIO, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().readlink(uiop, c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fsync(&mut self, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().fsync(c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inactive(&mut self, c: UserCred) {
|
||||||
|
unsafe { self.ops.as_mut().inactive(c, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bmap(&mut self, block_number: u32, bnp: ()) -> VNode {
|
||||||
|
unsafe { self.ops.as_mut().bmap(block_number, bnp, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn strategy(&mut self, bp: ()) {
|
||||||
|
unsafe { self.ops.as_mut().strategy(bp, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bread(&mut self, block_number: u32) -> Arc<[u8]> {
|
||||||
|
unsafe { self.ops.as_mut().bread(block_number, self.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VNode {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let vnode_ops = unsafe { Box::from_raw(self.ops.as_ptr()) };
|
||||||
|
drop(vnode_ops)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for VNode {
|
impl Debug for VNode {
|
||||||
@@ -222,49 +419,21 @@ pub struct VAttr {
|
|||||||
used_blocks: u32,
|
used_blocks: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn find_mount_point(file_path: &str) -> Option<NonNull<Vfs>> {
|
unsafe fn vfs_has_mount_point(mount_point: &str) -> Option<NonNull<Vfs>> {
|
||||||
// TODO: refactor
|
|
||||||
let mut mount_point: Option<NonNull<Vfs>> = None;
|
|
||||||
let mut current = ROOT_VFS.next;
|
let mut current = ROOT_VFS.next;
|
||||||
|
|
||||||
while let Some(node) = current {
|
while let Some(node) = current {
|
||||||
if node
|
if node.as_ref().mount_point.as_ref().unwrap() == mount_point {
|
||||||
.as_ref()
|
return Some(node);
|
||||||
.mount_point
|
|
||||||
.as_ref()
|
|
||||||
.expect("Null mount point")
|
|
||||||
== "/"
|
|
||||||
&& mount_point.is_none()
|
|
||||||
{
|
|
||||||
mount_point = Some(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mount_point_str = node
|
|
||||||
.as_ref()
|
|
||||||
.mount_point
|
|
||||||
.as_ref()
|
|
||||||
.expect("Null mount point");
|
|
||||||
if file_path.starts_with(mount_point_str)
|
|
||||||
&& mount_point_str.len()
|
|
||||||
> (mount_point.unwrap().as_ref())
|
|
||||||
.mount_point
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.len()
|
|
||||||
{
|
|
||||||
mount_point = Some(node);
|
|
||||||
}
|
|
||||||
current = unsafe { (*node.as_ptr()).next };
|
current = unsafe { (*node.as_ptr()).next };
|
||||||
}
|
}
|
||||||
|
|
||||||
mount_point
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_vfs(mut mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
|
pub fn add_vfs(mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
|
||||||
if mount_point != "/" {
|
|
||||||
mount_point = mount_point.trim_end_matches('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// Consumes vfs
|
/// Consumes vfs
|
||||||
unsafe fn deallocate_vfs(vfs: NonNull<Vfs>) {
|
unsafe fn deallocate_vfs(vfs: NonNull<Vfs>) {
|
||||||
@@ -277,8 +446,6 @@ pub fn add_vfs(mut mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()>
|
|||||||
}
|
}
|
||||||
|
|
||||||
let layout = alloc::alloc::Layout::new::<Vfs>();
|
let layout = alloc::alloc::Layout::new::<Vfs>();
|
||||||
// TODO: its fucking broken again
|
|
||||||
// let vfs_ptr = PHYSICAL_MEMORY_MANAGER.alloc(1).cast::<Vfs>();
|
|
||||||
let vfs_ptr = unsafe { alloc(layout).cast::<Vfs>() };
|
let vfs_ptr = unsafe { alloc(layout).cast::<Vfs>() };
|
||||||
|
|
||||||
if vfs_ptr.is_null() {
|
if vfs_ptr.is_null() {
|
||||||
@@ -289,8 +456,9 @@ pub fn add_vfs(mut mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()>
|
|||||||
unsafe {
|
unsafe {
|
||||||
let mut vfs = Vfs::null();
|
let mut vfs = Vfs::null();
|
||||||
vfs.ops = Some(NonNull::new_unchecked(Box::into_raw(fs_ops)));
|
vfs.ops = Some(NonNull::new_unchecked(Box::into_raw(fs_ops)));
|
||||||
vfs.mount_point = Some(mount_point.to_string());
|
// 'normalize' the path (yes, making "/" == "" is intentional)
|
||||||
*vfs_ptr = vfs;
|
vfs.mount_point = Some(mount_point.trim_end_matches('/').to_string());
|
||||||
|
vfs_ptr.write(vfs);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Safety: We know vfs_ptr is not null
|
// Safety: We know vfs_ptr is not null
|
||||||
@@ -300,35 +468,29 @@ pub fn add_vfs(mut mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()>
|
|||||||
|
|
||||||
log_info!("Adding vfs at {mount_point}");
|
log_info!("Adding vfs at {mount_point}");
|
||||||
|
|
||||||
// TODO: dont give / special treatment
|
|
||||||
if mount_point == "/" {
|
if mount_point == "/" {
|
||||||
if unsafe { ROOT_VFS.next.is_some() } {
|
if unsafe { ROOT_VFS.next.is_some() } {
|
||||||
unsafe {
|
unsafe {
|
||||||
deallocate_vfs(vfs_ptr);
|
deallocate_vfs(vfs_ptr);
|
||||||
};
|
};
|
||||||
// PHYSICAL_MEMORY_MANAGER.dealloc(vfs_ptr.cast::<u8>(), 1);
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
vfs.mount(mount_point);
|
||||||
vfs.ops
|
|
||||||
.unwrap()
|
|
||||||
.as_mut()
|
|
||||||
.mount(mount_point, &mut vfs.data, vfs_ptr.as_ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { ROOT_VFS.next = Some(vfs_ptr) };
|
unsafe { ROOT_VFS.next = Some(vfs_ptr) };
|
||||||
} else {
|
} else {
|
||||||
// TODO: technically this allows you to mount file systems at nonexistent mount point
|
|
||||||
if unsafe { ROOT_VFS.next.is_none() } {
|
if unsafe { ROOT_VFS.next.is_none() } {
|
||||||
unsafe {
|
unsafe {
|
||||||
deallocate_vfs(vfs_ptr);
|
deallocate_vfs(vfs_ptr);
|
||||||
};
|
};
|
||||||
// PHYSICAL_MEMORY_MANAGER.dealloc(vfs_ptr.cast::<u8>(), 1);
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// let target_vfs = unsafe { ROOT_VFS.next.unwrap() };
|
if vfs_open(mount_point).is_err() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
let mut next_vfs = unsafe { ROOT_VFS.next };
|
let mut next_vfs = unsafe { ROOT_VFS.next };
|
||||||
|
|
||||||
@@ -337,7 +499,6 @@ pub fn add_vfs(mut mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()>
|
|||||||
unsafe {
|
unsafe {
|
||||||
deallocate_vfs(vfs_ptr);
|
deallocate_vfs(vfs_ptr);
|
||||||
};
|
};
|
||||||
// PHYSICAL_MEMORY_MANAGER.dealloc(vfs_ptr.cast::<u8>(), 1);
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,16 +513,10 @@ pub fn add_vfs(mut mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()>
|
|||||||
unsafe {
|
unsafe {
|
||||||
deallocate_vfs(vfs_ptr);
|
deallocate_vfs(vfs_ptr);
|
||||||
};
|
};
|
||||||
// PHYSICAL_MEMORY_MANAGER.dealloc(vfs_ptr.cast::<u8>(), 1);
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
vfs.mount(mount_point);
|
||||||
vfs.ops
|
|
||||||
.unwrap()
|
|
||||||
.as_mut()
|
|
||||||
.mount(mount_point, &mut vfs.data, vfs_ptr.as_ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { (next_vfs.unwrap()).as_mut().next = Some(vfs_ptr) };
|
unsafe { (next_vfs.unwrap()).as_mut().next = Some(vfs_ptr) };
|
||||||
}
|
}
|
||||||
@@ -376,23 +531,7 @@ pub fn vfs_open(path: &str) -> Result<VNode, ()> {
|
|||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let root_vfs = unsafe { find_mount_point(path) };
|
let mut cur_vnode = unsafe { ROOT_VFS.next.unwrap().as_mut().root() };
|
||||||
|
|
||||||
if root_vfs.is_none() {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut cur_vnode = unsafe {
|
|
||||||
root_vfs
|
|
||||||
.unwrap()
|
|
||||||
.as_mut()
|
|
||||||
.ops
|
|
||||||
.unwrap()
|
|
||||||
.as_mut()
|
|
||||||
.root(root_vfs.unwrap().as_ptr())
|
|
||||||
};
|
|
||||||
|
|
||||||
let path = &path[unsafe { root_vfs.unwrap().as_ref().mount_point.as_ref().unwrap() }.len()..];
|
|
||||||
|
|
||||||
let parts = path.split('/').collect::<Vec<&str>>();
|
let parts = path.split('/').collect::<Vec<&str>>();
|
||||||
|
|
||||||
@@ -401,11 +540,7 @@ pub fn vfs_open(path: &str) -> Result<VNode, ()> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(vnode) =
|
if let Ok(vnode) = cur_vnode.lookup(part, UserCred { uid: 0, gid: 0 }) {
|
||||||
cur_vnode
|
|
||||||
.ops
|
|
||||||
.lookup(part, UserCred { uid: 0, gid: 0 }, cur_vnode.as_ptr())
|
|
||||||
{
|
|
||||||
cur_vnode = vnode;
|
cur_vnode = vnode;
|
||||||
} else {
|
} else {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
|||||||
use crate::{
|
use crate::{
|
||||||
arch::io::{inb, insw, inw, outb, outsw},
|
arch::io::{inb, insw, inw, outb, outsw},
|
||||||
drivers::{
|
drivers::{
|
||||||
fs::{devfs::DeviceOperations, fat, vfs::add_vfs},
|
fs::{fat, vfs::add_vfs},
|
||||||
storage::{GPTHeader, GPTPartitionEntry, Partition, MBR},
|
storage::{GPTHeader, GPTPartitionEntry, Partition, MBR},
|
||||||
},
|
},
|
||||||
libs::{sync::Mutex, uuid::Uuid},
|
libs::{sync::Mutex, uuid::Uuid},
|
||||||
@@ -296,7 +296,7 @@ impl ATABus {
|
|||||||
sector_count: usize,
|
sector_count: usize,
|
||||||
) -> Result<Arc<[u8]>, ()> {
|
) -> Result<Arc<[u8]>, ()> {
|
||||||
let mut buffer: Vec<u8> = Vec::with_capacity(ATA_SECTOR_SIZE * sector_count);
|
let mut buffer: Vec<u8> = Vec::with_capacity(ATA_SECTOR_SIZE * sector_count);
|
||||||
unsafe { buffer.set_len(buffer.capacity()) };
|
buffer.resize(buffer.capacity(), 0);
|
||||||
|
|
||||||
self.ide_access(
|
self.ide_access(
|
||||||
drive,
|
drive,
|
||||||
|
|||||||
@@ -126,9 +126,7 @@ struct HuffRing {
|
|||||||
impl HuffRing {
|
impl HuffRing {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let mut data = Vec::with_capacity(32 * 1024);
|
let mut data = Vec::with_capacity(32 * 1024);
|
||||||
unsafe {
|
data.resize(data.capacity(), 0);
|
||||||
data.set_len(32 * 1024);
|
|
||||||
};
|
|
||||||
|
|
||||||
return Self { pointer: 0, data };
|
return Self { pointer: 0, data };
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/main.rs
49
src/main.rs
@@ -7,7 +7,6 @@ use core::ffi::CStr;
|
|||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use limine::KernelFileRequest;
|
use limine::KernelFileRequest;
|
||||||
use mem::HHDM_OFFSET;
|
|
||||||
|
|
||||||
use crate::drivers::fs::{
|
use crate::drivers::fs::{
|
||||||
initramfs,
|
initramfs,
|
||||||
@@ -35,6 +34,8 @@ pub extern "C" fn _start() -> ! {
|
|||||||
mem::init_allocator();
|
mem::init_allocator();
|
||||||
drivers::acpi::init_acpi();
|
drivers::acpi::init_acpi();
|
||||||
|
|
||||||
|
parse_kernel_cmdline();
|
||||||
|
|
||||||
kmain()
|
kmain()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,23 +47,34 @@ pub fn kmain() -> ! {
|
|||||||
|
|
||||||
let mut file = vfs_open("/firstdir/seconddirbutlonger/yeah.txt").unwrap();
|
let mut file = vfs_open("/firstdir/seconddirbutlonger/yeah.txt").unwrap();
|
||||||
|
|
||||||
crate::println!(
|
crate::println!("YEAH.TXT: {:X?}", file.open(0, UserCred { uid: 0, gid: 0 }));
|
||||||
"YEAH.TXT: {:X?}",
|
|
||||||
&file
|
|
||||||
.ops
|
|
||||||
.open(0, UserCred { uid: 0, gid: 0 }, file.as_ptr())
|
|
||||||
.unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
drivers::storage::ide::init();
|
drivers::storage::ide::init();
|
||||||
|
|
||||||
let mut nested_file = vfs_open("/mnt/boot/limine/limine.cfg").unwrap();
|
let mut limine_dir = vfs_open("/mnt/boot/limine").unwrap();
|
||||||
|
|
||||||
crate::println!(
|
crate::println!(
|
||||||
"LIMINE BOOT: {:X?}",
|
"LIMINE BOOT: {:X?}",
|
||||||
nested_file
|
limine_dir
|
||||||
.ops
|
.lookup("limine.cfg", UserCred { uid: 0, gid: 0 })
|
||||||
.open(0, UserCred { uid: 0, gid: 0 }, nested_file.as_ptr())
|
.unwrap()
|
||||||
|
.open(0, UserCred { uid: 0, gid: 0 })
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut root_dir = vfs_open("/").unwrap();
|
||||||
|
|
||||||
|
crate::println!(
|
||||||
|
"LIMINE BOOT THROUGH LOOKUP: {:X?}",
|
||||||
|
root_dir
|
||||||
|
.lookup("mnt", UserCred { uid: 0, gid: 0 })
|
||||||
|
.unwrap()
|
||||||
|
.lookup("boot", UserCred { uid: 0, gid: 0 })
|
||||||
|
.unwrap()
|
||||||
|
.lookup("limine", UserCred { uid: 0, gid: 0 })
|
||||||
|
.unwrap()
|
||||||
|
.lookup("limine.cfg", UserCred { uid: 0, gid: 0 })
|
||||||
|
.unwrap()
|
||||||
|
.open(0, UserCred { uid: 0, gid: 0 })
|
||||||
);
|
);
|
||||||
|
|
||||||
// let file = vfs_open("/example.txt").unwrap();
|
// let file = vfs_open("/example.txt").unwrap();
|
||||||
@@ -178,15 +190,15 @@ impl KernelFeatures {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Do this vastly differently
|
// TODO: Do this vastly differently
|
||||||
pub static KERNEL_FEATURES: libs::cell::LazyCell<KernelFeatures> =
|
pub static KERNEL_FEATURES: libs::cell::OnceCell<KernelFeatures> = libs::cell::OnceCell::new();
|
||||||
libs::cell::LazyCell::new(parse_kernel_cmdline);
|
|
||||||
|
|
||||||
fn parse_kernel_cmdline() -> KernelFeatures {
|
fn parse_kernel_cmdline() {
|
||||||
let mut kernel_features: KernelFeatures = KernelFeatures { fat_in_mem: true };
|
let mut kernel_features: KernelFeatures = KernelFeatures { fat_in_mem: true };
|
||||||
|
|
||||||
let kernel_file_response = KERNEL_REQUEST.get_response().get();
|
let kernel_file_response = KERNEL_REQUEST.get_response().get();
|
||||||
if kernel_file_response.is_none() {
|
if kernel_file_response.is_none() {
|
||||||
return kernel_features;
|
KERNEL_FEATURES.set(kernel_features);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmdline_ptr = kernel_file_response
|
let cmdline_ptr = kernel_file_response
|
||||||
@@ -198,7 +210,8 @@ fn parse_kernel_cmdline() -> KernelFeatures {
|
|||||||
.as_ptr();
|
.as_ptr();
|
||||||
|
|
||||||
if cmdline_ptr.is_none() {
|
if cmdline_ptr.is_none() {
|
||||||
return kernel_features;
|
KERNEL_FEATURES.set(kernel_features);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmdline = unsafe { CStr::from_ptr(cmdline_ptr.unwrap()) };
|
let cmdline = unsafe { CStr::from_ptr(cmdline_ptr.unwrap()) };
|
||||||
@@ -220,7 +233,7 @@ fn parse_kernel_cmdline() -> KernelFeatures {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return kernel_features;
|
KERNEL_FEATURES.set(kernel_features);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
|
|||||||
@@ -70,15 +70,15 @@ impl LinkedListAllocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_from_node(node: &MemNode, layout: Layout) -> *mut u8 {
|
fn alloc_from_node(node: &MemNode, layout: Layout) -> *mut u8 {
|
||||||
let start = align_up(node.addr() as usize, layout.align());
|
let start = align_up(node.addr(), layout.align());
|
||||||
let end = start + layout.size();
|
let end = start + layout.size();
|
||||||
|
|
||||||
if end > node.end_addr() as usize {
|
if end > node.end_addr() {
|
||||||
// aligned address goes outside the bounds of the node
|
// aligned address goes outside the bounds of the node
|
||||||
return core::ptr::null_mut();
|
return core::ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
let extra = node.end_addr() as usize - end;
|
let extra = node.end_addr() - end;
|
||||||
if extra > 0 && extra < core::mem::size_of::<MemNode>() {
|
if extra > 0 && extra < core::mem::size_of::<MemNode>() {
|
||||||
// Node size minus allocation size is less than the minimum size needed for a node,
|
// Node size minus allocation size is less than the minimum size needed for a node,
|
||||||
// thus, if we let the allocation to happen in this node, we lose track of the extra memory
|
// thus, if we let the allocation to happen in this node, we lose track of the extra memory
|
||||||
|
|||||||
Reference in New Issue
Block a user