the correctest way (mostly) to do vfs
This commit is contained in:
4
Makefile
4
Makefile
@@ -106,6 +106,8 @@ copy-iso-files:
|
||||
mkdir -p ${ISO_PATH}/boot/limine
|
||||
mkdir -p ${ISO_PATH}/EFI/BOOT
|
||||
|
||||
mkdir -p ${ISO_PATH}/mnt
|
||||
|
||||
cp -v limine.cfg limine/limine-bios.sys ${ISO_PATH}/boot/limine
|
||||
cp -v limine/BOOT${LIMINE_BOOT_VARIATION}.EFI ${ISO_PATH}/EFI/BOOT/
|
||||
|
||||
@@ -158,8 +160,6 @@ compile-bootloader:
|
||||
@if [ ! -d "limine" ]; then \
|
||||
echo "Cloning Limine into limine/..."; \
|
||||
git clone https://github.com/limine-bootloader/limine.git --branch=${LIMINE_BRANCH} --depth=1; \
|
||||
else \
|
||||
echo "Folder limine already exists. Skipping clone."; \
|
||||
fi
|
||||
make -C limine
|
||||
|
||||
|
||||
@@ -103,7 +103,6 @@ exception_function!(0x00, div_error);
|
||||
exception_function!(0x06, invalid_opcode);
|
||||
exception_function!(0x08, double_fault);
|
||||
exception_function!(0x0D, general_protection_fault);
|
||||
// TODO: fix the page fault then gracefully return.
|
||||
exception_function!(0x0E, page_fault);
|
||||
exception_function!(0xFF, generic_handler);
|
||||
|
||||
|
||||
@@ -95,7 +95,11 @@ pub fn idt_init() {
|
||||
let mut idt_lock = IDT.lock();
|
||||
IDT_PTR.base = idt_lock.as_ptr() as u64;
|
||||
|
||||
core::ptr::write_bytes(idt_lock.as_mut_ptr() as *mut core::ffi::c_void, 0, idt_size);
|
||||
core::ptr::write_bytes(
|
||||
idt_lock.as_mut_ptr().cast::<core::ffi::c_void>(),
|
||||
0,
|
||||
idt_size,
|
||||
);
|
||||
}
|
||||
|
||||
// Set every interrupt to the "null" interrupt handler (it does nothing)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use core::ptr::NonNull;
|
||||
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
@@ -265,45 +267,6 @@ impl FatFs {
|
||||
_ => bpb.sectors_per_fat as usize,
|
||||
};
|
||||
|
||||
let bytes_per_fat = 512 * sectors_per_fat;
|
||||
|
||||
let mut fat: Option<Arc<[u32]>> = None;
|
||||
|
||||
if crate::KERNEL_FEATURES.fat_in_mem {
|
||||
let cluster_bytes = match fat_type {
|
||||
FatType::Fat32(_) => 4,
|
||||
_ => 2,
|
||||
};
|
||||
|
||||
let mut fat_vec: Vec<u32> = Vec::with_capacity(bytes_per_fat / cluster_bytes);
|
||||
|
||||
for i in 0..sectors_per_fat {
|
||||
let sector = partition
|
||||
.read(fat_start + i as u64, 1)
|
||||
.expect("Failed to read FAT");
|
||||
for j in 0..(512 / cluster_bytes) {
|
||||
match fat_type {
|
||||
FatType::Fat32(_) => fat_vec.push(u32::from_le_bytes(
|
||||
sector[j * cluster_bytes..(j * cluster_bytes + cluster_bytes)]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)),
|
||||
_ => fat_vec.push(u16::from_le_bytes(
|
||||
sector[j * cluster_bytes..(j * cluster_bytes + cluster_bytes)]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
) as u32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fat = Some(Arc::from(fat_vec));
|
||||
} else {
|
||||
crate::log_info!(
|
||||
"\x1B[33mWARNING\x1B[0m: FAT is not being stored in memory, this feature is experimental and file reads are expected to be slower."
|
||||
)
|
||||
}
|
||||
|
||||
crate::println!("Found {fat_type:?} FS");
|
||||
|
||||
let cluster_size = bpb.sectors_per_cluster as usize * 512;
|
||||
@@ -311,7 +274,7 @@ impl FatFs {
|
||||
return Ok(Self {
|
||||
partition,
|
||||
fs_info,
|
||||
fat,
|
||||
fat: None,
|
||||
bpb,
|
||||
fat_start,
|
||||
fat_type,
|
||||
@@ -511,17 +474,57 @@ impl FatFs {
|
||||
}
|
||||
|
||||
impl FsOps for FatFs {
|
||||
fn mount(&mut self, _path: &str, data: &mut *mut u8, _vfsp: *const super::vfs::Vfs) {
|
||||
// TODO: load the FAT into memory here
|
||||
fn mount(&mut self, _path: &str, data: &mut *mut u8, _vfsp: NonNull<super::vfs::Vfs>) {
|
||||
let bytes_per_fat = 512 * self.sectors_per_fat;
|
||||
|
||||
let mut fat: Option<Arc<[u32]>> = None;
|
||||
|
||||
if crate::KERNEL_FEATURES.fat_in_mem {
|
||||
let cluster_bytes = match self.fat_type {
|
||||
FatType::Fat32(_) => 4,
|
||||
_ => 2,
|
||||
};
|
||||
|
||||
let mut fat_vec: Vec<u32> = Vec::with_capacity(bytes_per_fat / cluster_bytes);
|
||||
|
||||
for i in 0..self.sectors_per_fat {
|
||||
let sector = self
|
||||
.partition
|
||||
.read(self.fat_start + i as u64, 1)
|
||||
.expect("Failed to read FAT");
|
||||
for j in 0..(512 / cluster_bytes) {
|
||||
match self.fat_type {
|
||||
FatType::Fat32(_) => fat_vec.push(u32::from_le_bytes(
|
||||
sector[j * cluster_bytes..(j * cluster_bytes + cluster_bytes)]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)),
|
||||
_ => fat_vec.push(u16::from_le_bytes(
|
||||
sector[j * cluster_bytes..(j * cluster_bytes + cluster_bytes)]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
) as u32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fat = Some(Arc::from(fat_vec));
|
||||
} else {
|
||||
crate::log_info!(
|
||||
"\x1B[33mWARNING\x1B[0m: FAT is not being stored in memory, this feature is experimental and file reads are expected to be slower."
|
||||
)
|
||||
}
|
||||
|
||||
self.fat = fat;
|
||||
|
||||
*data = core::ptr::addr_of!(*self) as *mut u8;
|
||||
}
|
||||
|
||||
fn unmount(&mut self, _vfsp: *const super::vfs::Vfs) {
|
||||
// TODO: unload the FAT form memory
|
||||
fn unmount(&mut self, _vfsp: NonNull<super::vfs::Vfs>) {
|
||||
self.fat = None;
|
||||
}
|
||||
|
||||
fn root(&mut self, vfsp: *const super::vfs::Vfs) -> super::vfs::VNode {
|
||||
fn root(&mut self, vfsp: NonNull<super::vfs::Vfs>) -> super::vfs::VNode {
|
||||
let root_cluster = match self.fat_type {
|
||||
FatType::Fat32(ebpb) => ebpb.root_dir_cluster as usize,
|
||||
_ => self.sector_to_cluster(
|
||||
@@ -537,22 +540,22 @@ impl FsOps for FatFs {
|
||||
return VNode::new(Box::new(file), super::vfs::VNodeType::Directory, vfsp);
|
||||
}
|
||||
|
||||
fn fid(&mut self, _path: &str, _vfsp: *const super::vfs::Vfs) -> Option<super::vfs::FileId> {
|
||||
fn fid(&mut self, _path: &str, _vfsp: NonNull<super::vfs::Vfs>) -> Option<super::vfs::FileId> {
|
||||
todo!("FAT FID");
|
||||
}
|
||||
|
||||
fn statfs(&mut self, _vfsp: *const super::vfs::Vfs) -> super::vfs::StatFs {
|
||||
fn statfs(&mut self, _vfsp: NonNull<super::vfs::Vfs>) -> super::vfs::StatFs {
|
||||
todo!("FAT STATFS");
|
||||
}
|
||||
|
||||
fn sync(&mut self, _vfsp: *const super::vfs::Vfs) {
|
||||
fn sync(&mut self, _vfsp: NonNull<super::vfs::Vfs>) {
|
||||
todo!("FAT SYNC");
|
||||
}
|
||||
|
||||
fn vget(
|
||||
&mut self,
|
||||
_fid: super::vfs::FileId,
|
||||
_vfsp: *const super::vfs::Vfs,
|
||||
_vfsp: NonNull<super::vfs::Vfs>,
|
||||
) -> super::vfs::VNode {
|
||||
todo!("FAT VGET");
|
||||
}
|
||||
@@ -564,19 +567,19 @@ enum 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: NonNull<VNode>) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn bmap(&mut self, _block_number: u32, _bnp: (), _vp: *const VNode) -> super::vfs::VNode {
|
||||
fn bmap(&mut self, _block_number: u32, _bnp: (), _vp: NonNull<VNode>) -> super::vfs::VNode {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn bread(&mut self, _block_number: u32, _vp: *const VNode) -> Arc<[u8]> {
|
||||
fn bread(&mut self, _block_number: u32, _vp: NonNull<VNode>) -> Arc<[u8]> {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn close(&mut self, _f: u32, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn close(&mut self, _f: u32, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
@@ -587,20 +590,20 @@ impl VNodeOperations for File {
|
||||
_e: u32,
|
||||
_m: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) -> Result<super::vfs::VNode, ()> {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn fsync(&mut self, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn fsync(&mut self, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn getattr(&mut self, _c: super::vfs::UserCred, _vp: *const VNode) -> super::vfs::VAttr {
|
||||
fn getattr(&mut self, _c: super::vfs::UserCred, _vp: NonNull<VNode>) -> super::vfs::VAttr {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn inactive(&mut self, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn inactive(&mut self, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
@@ -610,7 +613,7 @@ impl VNodeOperations for File {
|
||||
_d: *mut u8,
|
||||
_f: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
@@ -620,7 +623,7 @@ impl VNodeOperations for File {
|
||||
_target_dir: *mut super::vfs::VNode,
|
||||
_target_name: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
@@ -629,9 +632,9 @@ impl VNodeOperations for File {
|
||||
&mut self,
|
||||
nm: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
vp: *const VNode,
|
||||
vp: NonNull<VNode>,
|
||||
) -> Result<super::vfs::VNode, ()> {
|
||||
let fat_fs = unsafe { (*(*vp).parent_vfs).data.cast::<FatFs>() };
|
||||
let fat_fs = unsafe { (*vp.as_ptr()).parent_vfs.as_mut().data.cast::<FatFs>() };
|
||||
|
||||
match self {
|
||||
File::Dir(directory) => unsafe {
|
||||
@@ -652,7 +655,7 @@ impl VNodeOperations for File {
|
||||
File::Archive(FatFile { file_entry })
|
||||
};
|
||||
|
||||
let vnode = VNode::new(Box::new(file), file_typ, (*vp).parent_vfs);
|
||||
let vnode = VNode::new(Box::new(file), file_typ, (*vp.as_ptr()).parent_vfs);
|
||||
|
||||
Ok(vnode)
|
||||
},
|
||||
@@ -665,7 +668,7 @@ impl VNodeOperations for File {
|
||||
_nm: &str,
|
||||
_va: super::vfs::VAttr,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) -> Result<super::vfs::VNode, ()> {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
@@ -674,11 +677,11 @@ impl VNodeOperations for File {
|
||||
&mut self,
|
||||
_f: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
vp: *const VNode,
|
||||
vp: NonNull<VNode>,
|
||||
) -> Result<Arc<[u8]>, ()> {
|
||||
match self {
|
||||
File::Archive(archive) => {
|
||||
let fat_fs = unsafe { (*(*vp).parent_vfs).data.cast::<FatFs>() };
|
||||
let fat_fs = unsafe { (*vp.as_ptr()).parent_vfs.as_mut().data.cast::<FatFs>() };
|
||||
|
||||
let mut file: Vec<u8> = Vec::with_capacity(archive.file_entry.file_size as usize);
|
||||
let mut file_ptr_index = 0;
|
||||
@@ -746,8 +749,8 @@ impl VNodeOperations for File {
|
||||
_direction: super::vfs::IODirection,
|
||||
_f: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
) {
|
||||
_vp: NonNull<VNode>,
|
||||
) -> Result<Arc<[u8]>, ()> {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
@@ -755,7 +758,7 @@ impl VNodeOperations for File {
|
||||
&mut self,
|
||||
_uiop: *const super::vfs::UIO,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
@@ -764,7 +767,7 @@ impl VNodeOperations for File {
|
||||
&mut self,
|
||||
_uiop: *const super::vfs::UIO,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
@@ -775,20 +778,25 @@ impl VNodeOperations for File {
|
||||
_target_dir: *mut super::vfs::VNode,
|
||||
_target_name: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn select(&mut self, _w: super::vfs::IODirection, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn select(
|
||||
&mut self,
|
||||
_w: super::vfs::IODirection,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn setattr(&mut self, _va: super::vfs::VAttr, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn setattr(&mut self, _va: super::vfs::VAttr, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
fn strategy(&mut self, _bp: (), _vp: *const VNode) {
|
||||
fn strategy(&mut self, _bp: (), _vp: NonNull<VNode>) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
@@ -798,7 +806,7 @@ impl VNodeOperations for File {
|
||||
_va: super::vfs::VAttr,
|
||||
_target_name: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!("VNODE OPERATIONS");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod chunk_reader;
|
||||
mod superblock;
|
||||
|
||||
use core::{fmt::Debug, mem::MaybeUninit};
|
||||
use core::{fmt::Debug, mem::MaybeUninit, ptr::NonNull};
|
||||
|
||||
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
||||
use limine::ModuleRequest;
|
||||
@@ -82,7 +82,7 @@ impl Squashfs<'_> {
|
||||
// crate::log_info!("Parsing initramfs at {:p}", ptr);
|
||||
|
||||
// 40 is the offset for bytes used by the archive in the superblock
|
||||
let length = unsafe { u64::from_le(*(ptr.add(40) as *const u64)) as usize };
|
||||
let length = unsafe { u64::from_le(*(ptr.add(40).cast::<u64>())) as usize };
|
||||
|
||||
let squashfs_data: &[u8] = unsafe { core::slice::from_raw_parts(ptr, length) };
|
||||
|
||||
@@ -345,39 +345,39 @@ impl Squashfs<'_> {
|
||||
}
|
||||
|
||||
impl<'a> FsOps for Squashfs<'a> {
|
||||
fn mount(&mut self, _path: &str, data: &mut *mut u8, _vfspp: *const super::vfs::Vfs) {
|
||||
fn mount(&mut self, _path: &str, data: &mut *mut u8, _vfsp: NonNull<super::vfs::Vfs>) {
|
||||
// STUB
|
||||
|
||||
// not recommended:tm:
|
||||
*data = core::ptr::addr_of!(*self) as *mut u8;
|
||||
}
|
||||
|
||||
fn unmount(&mut self, _vfsp: *const super::vfs::Vfs) {
|
||||
fn unmount(&mut self, _vfsp: NonNull<super::vfs::Vfs>) {
|
||||
// STUB
|
||||
}
|
||||
|
||||
fn root(&mut self, vfsp: *const super::vfs::Vfs) -> super::vfs::VNode {
|
||||
fn root(&mut self, vfsp: NonNull<super::vfs::Vfs>) -> super::vfs::VNode {
|
||||
let root_dir = self.read_root_dir();
|
||||
|
||||
return VNode::new(Box::new(root_dir), VNodeType::Directory, vfsp);
|
||||
}
|
||||
|
||||
fn fid(&mut self, _path: &str, _vfspp: *const super::vfs::Vfs) -> Option<super::vfs::FileId> {
|
||||
fn fid(&mut self, _path: &str, _vfsp: NonNull<super::vfs::Vfs>) -> Option<super::vfs::FileId> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn statfs(&mut self, _vfsp: *const super::vfs::Vfs) -> super::vfs::StatFs {
|
||||
fn statfs(&mut self, _vfsp: NonNull<super::vfs::Vfs>) -> super::vfs::StatFs {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn sync(&mut self, _vfsp: *const super::vfs::Vfs) {
|
||||
fn sync(&mut self, _vfsp: NonNull<super::vfs::Vfs>) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn vget(
|
||||
&mut self,
|
||||
_fid: super::vfs::FileId,
|
||||
_vfsp: *const super::vfs::Vfs,
|
||||
_vfsp: NonNull<super::vfs::Vfs>,
|
||||
) -> super::vfs::VNode {
|
||||
todo!();
|
||||
}
|
||||
@@ -412,9 +412,9 @@ impl VNodeOperations for Inode {
|
||||
&mut self,
|
||||
_f: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
vp: *const VNode,
|
||||
vp: NonNull<VNode>,
|
||||
) -> Result<Arc<[u8]>, ()> {
|
||||
let squashfs = unsafe { (*(*vp).parent_vfs).data.cast::<Squashfs>() };
|
||||
let squashfs = unsafe { (*vp.as_ptr()).parent_vfs.as_mut().data.cast::<Squashfs>() };
|
||||
|
||||
match self {
|
||||
Inode::BasicFile(file) => unsafe {
|
||||
@@ -456,7 +456,7 @@ impl VNodeOperations for Inode {
|
||||
// And since we are building the array due to unaligned pointer shenanigans we need to
|
||||
// include the header bytes otherwise we are short by two bytes
|
||||
let fragment_block_size =
|
||||
(u16::from_le(core::ptr::read_unaligned(fragment_pointer as *mut u16))
|
||||
(u16::from_le(core::ptr::read_unaligned(fragment_pointer.cast::<u16>()))
|
||||
& 0x7FFF)
|
||||
+ 2;
|
||||
|
||||
@@ -498,7 +498,7 @@ impl VNodeOperations for Inode {
|
||||
}
|
||||
}
|
||||
|
||||
fn close(&mut self, _f: u32, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn close(&mut self, _f: u32, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -508,8 +508,8 @@ impl VNodeOperations for Inode {
|
||||
_direction: super::vfs::IODirection,
|
||||
_f: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
) {
|
||||
_vp: NonNull<VNode>,
|
||||
) -> Result<Arc<[u8]>, ()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -519,24 +519,29 @@ impl VNodeOperations for Inode {
|
||||
_d: *mut u8,
|
||||
_f: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn select(&mut self, _w: super::vfs::IODirection, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn select(
|
||||
&mut self,
|
||||
_w: super::vfs::IODirection,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn getattr(&mut self, _c: super::vfs::UserCred, _vp: *const VNode) -> super::vfs::VAttr {
|
||||
fn getattr(&mut self, _c: super::vfs::UserCred, _vp: NonNull<VNode>) -> super::vfs::VAttr {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn setattr(&mut self, _va: super::vfs::VAttr, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn setattr(&mut self, _va: super::vfs::VAttr, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn access(&mut self, _m: u32, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn access(&mut self, _m: u32, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -544,9 +549,11 @@ impl VNodeOperations for Inode {
|
||||
&mut self,
|
||||
nm: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
vp: *const VNode,
|
||||
vp: NonNull<VNode>,
|
||||
) -> Result<super::vfs::VNode, ()> {
|
||||
let squashfs = unsafe { (*(*vp).parent_vfs).data.cast::<Squashfs>() };
|
||||
let squashfs = unsafe { (*vp.as_ptr()).parent_vfs.as_mut().data.cast::<Squashfs>() };
|
||||
|
||||
crate::println!("wawawaw");
|
||||
|
||||
match self {
|
||||
Inode::BasicDirectory(_) | Inode::ExtendedDirectory(_) => unsafe {
|
||||
@@ -556,7 +563,7 @@ impl VNodeOperations for Inode {
|
||||
Inode::BasicFile(_) => VNodeType::Regular,
|
||||
};
|
||||
|
||||
let vnode = VNode::new(Box::new(inode), vnode_type, (*vp).parent_vfs);
|
||||
let vnode = VNode::new(Box::new(inode), vnode_type, (*vp.as_ptr()).parent_vfs);
|
||||
|
||||
return Ok(vnode);
|
||||
},
|
||||
@@ -571,7 +578,7 @@ impl VNodeOperations for Inode {
|
||||
_e: u32,
|
||||
_m: u32,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) -> Result<super::vfs::VNode, ()> {
|
||||
todo!()
|
||||
}
|
||||
@@ -581,7 +588,7 @@ impl VNodeOperations for Inode {
|
||||
_target_dir: *mut super::vfs::VNode,
|
||||
_target_name: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
@@ -592,7 +599,7 @@ impl VNodeOperations for Inode {
|
||||
_target_dir: *mut super::vfs::VNode,
|
||||
_target_name: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
@@ -602,7 +609,7 @@ impl VNodeOperations for Inode {
|
||||
_nm: &str,
|
||||
_va: super::vfs::VAttr,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) -> Result<super::vfs::VNode, ()> {
|
||||
todo!()
|
||||
}
|
||||
@@ -611,7 +618,7 @@ impl VNodeOperations for Inode {
|
||||
&mut self,
|
||||
_uiop: *const super::vfs::UIO,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
@@ -622,7 +629,7 @@ impl VNodeOperations for Inode {
|
||||
_va: super::vfs::VAttr,
|
||||
_target_name: &str,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
@@ -631,28 +638,28 @@ impl VNodeOperations for Inode {
|
||||
&mut self,
|
||||
_uiop: *const super::vfs::UIO,
|
||||
_c: super::vfs::UserCred,
|
||||
_vp: *const VNode,
|
||||
_vp: NonNull<VNode>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn fsync(&mut self, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn fsync(&mut self, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn inactive(&mut self, _c: super::vfs::UserCred, _vp: *const VNode) {
|
||||
fn inactive(&mut self, _c: super::vfs::UserCred, _vp: NonNull<VNode>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bmap(&mut self, _block_number: u32, _bnp: (), _vp: *const VNode) -> super::vfs::VNode {
|
||||
fn bmap(&mut self, _block_number: u32, _bnp: (), _vp: NonNull<VNode>) -> super::vfs::VNode {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn strategy(&mut self, _bp: (), _vp: *const VNode) {
|
||||
fn strategy(&mut self, _bp: (), _vp: NonNull<VNode>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bread(&mut self, _block_number: u32, _vp: *const VNode) -> Arc<[u8]> {
|
||||
fn bread(&mut self, _block_number: u32, _vp: NonNull<VNode>) -> Arc<[u8]> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// is this terrible? God yes, but it works
|
||||
|
||||
use core::{fmt::Debug, ptr::NonNull};
|
||||
|
||||
use alloc::{
|
||||
alloc::{alloc, dealloc, handle_alloc_error},
|
||||
boxed::Box,
|
||||
collections::BTreeMap,
|
||||
rc::Rc,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
@@ -12,108 +11,196 @@ use alloc::{
|
||||
|
||||
use crate::{log_info, log_ok};
|
||||
|
||||
// TODO: probably keeps excess memory but whatever
|
||||
struct TreeNode {
|
||||
vnode: Rc<VNode>,
|
||||
parent: Option<NonNull<Self>>,
|
||||
children: BTreeMap<String, Self>,
|
||||
}
|
||||
|
||||
impl TreeNode {
|
||||
fn new(vnode: VNode) -> Self {
|
||||
return Self {
|
||||
vnode: Rc::new(vnode),
|
||||
parent: None,
|
||||
children: BTreeMap::new(),
|
||||
};
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> NonNull<Self> {
|
||||
return NonNull::from(self);
|
||||
}
|
||||
|
||||
fn get_vnode(&mut self) -> &mut VNode {
|
||||
Rc::get_mut(&mut self.vnode).unwrap()
|
||||
}
|
||||
|
||||
fn lookup(&mut self, name: &str) -> Result<&mut Self, ()> {
|
||||
let parent = Some(self.as_ptr());
|
||||
|
||||
crate::println!("looking up {name} in node_tree");
|
||||
|
||||
if !self.children.contains_key(name) {
|
||||
crate::println!("not found in node tree");
|
||||
|
||||
let vnode: VNode;
|
||||
|
||||
if let Some(mut vfs) = self.vnode.vfs_mounted_here {
|
||||
crate::println!("using VFS root");
|
||||
|
||||
unsafe {
|
||||
vnode = vfs
|
||||
.as_mut()
|
||||
.root()
|
||||
.lookup(name, UserCred { uid: 0, gid: 0 })?
|
||||
};
|
||||
} else {
|
||||
vnode = Rc::get_mut(&mut self.vnode)
|
||||
.unwrap()
|
||||
.lookup(name, UserCred { uid: 0, gid: 0 })?;
|
||||
}
|
||||
|
||||
let child_node = TreeNode {
|
||||
vnode: Rc::new(vnode),
|
||||
parent,
|
||||
children: BTreeMap::new(),
|
||||
};
|
||||
|
||||
self.children.insert(name.to_string(), child_node);
|
||||
let child = self.children.get_mut(name).unwrap();
|
||||
return Ok(child);
|
||||
}
|
||||
|
||||
return Ok(self.children.get_mut(name).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
static mut NODE_TREE: Option<TreeNode> = None;
|
||||
static mut ROOT_VFS: Vfs = Vfs::null();
|
||||
|
||||
// TODO: everything being Option to accomodate the stupid null root vfs is getting annoying
|
||||
#[allow(unused)]
|
||||
pub struct Vfs {
|
||||
mount_point: Option<String>,
|
||||
next: Option<NonNull<Vfs>>,
|
||||
ops: Option<NonNull<dyn FsOps>>,
|
||||
// vnode_covered: Option<*const VNode>,
|
||||
next: Option<Box<Vfs>>,
|
||||
pub fs: Option<Box<dyn FsOps>>,
|
||||
vnode_covered: Option<NonNull<VNode>>,
|
||||
flags: u32,
|
||||
block_size: u32,
|
||||
pub data: *mut u8,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Vfs {}
|
||||
impl !Sync for Vfs {}
|
||||
|
||||
impl Vfs {
|
||||
const fn null() -> Self {
|
||||
return Vfs {
|
||||
mount_point: None,
|
||||
next: None,
|
||||
ops: None,
|
||||
// vnode_covered: None,
|
||||
fs: None,
|
||||
vnode_covered: None,
|
||||
flags: 0,
|
||||
block_size: 0,
|
||||
data: core::ptr::null_mut(),
|
||||
};
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const Self {
|
||||
core::ptr::addr_of!(*self)
|
||||
fn add_vfs(&mut self, vfs: Box<Self>) {
|
||||
let mut current = self;
|
||||
while let Some(ref mut next_vfs) = current.next {
|
||||
current = next_vfs;
|
||||
}
|
||||
current.next = Some(vfs);
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> NonNull<Self> {
|
||||
unsafe { NonNull::new_unchecked(core::ptr::addr_of!(*self) as *mut Self) }
|
||||
}
|
||||
|
||||
pub fn mount(&mut self, path: &str) {
|
||||
if self.ops.is_none() {
|
||||
if self.fs.is_none() {
|
||||
panic!("FsOps is null");
|
||||
}
|
||||
|
||||
let vfsp = self.as_ptr();
|
||||
|
||||
unsafe { self.ops.unwrap().as_mut().mount(path, &mut self.data, vfsp) };
|
||||
self.fs
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.mount(path, &mut self.data, vfsp);
|
||||
}
|
||||
|
||||
pub fn unmount(&mut self) {
|
||||
if self.ops.is_none() {
|
||||
if self.fs.is_none() {
|
||||
panic!("FsOps is null");
|
||||
}
|
||||
|
||||
unsafe { self.ops.unwrap().as_mut().unmount(self.as_ptr()) };
|
||||
let vfsp = self.as_ptr();
|
||||
|
||||
self.fs.as_mut().unwrap().as_mut().unmount(vfsp);
|
||||
}
|
||||
|
||||
pub fn root(&mut self) -> VNode {
|
||||
if self.ops.is_none() {
|
||||
if self.fs.is_none() {
|
||||
panic!("FsOps is null");
|
||||
}
|
||||
|
||||
unsafe { self.ops.unwrap().as_mut().root(self.as_ptr()) }
|
||||
let vfsp = self.as_ptr();
|
||||
|
||||
self.fs.as_mut().unwrap().as_mut().root(vfsp)
|
||||
}
|
||||
|
||||
pub fn statfs(&mut self) -> StatFs {
|
||||
if self.ops.is_none() {
|
||||
if self.fs.is_none() {
|
||||
panic!("FsOps is null");
|
||||
}
|
||||
|
||||
unsafe { self.ops.unwrap().as_mut().statfs(self.as_ptr()) }
|
||||
let vfsp = self.as_ptr();
|
||||
|
||||
self.fs.as_mut().unwrap().as_mut().statfs(vfsp)
|
||||
}
|
||||
|
||||
pub fn sync(&mut self) {
|
||||
if self.ops.is_none() {
|
||||
if self.fs.is_none() {
|
||||
panic!("FsOps is null");
|
||||
}
|
||||
|
||||
unsafe { self.ops.unwrap().as_mut().sync(self.as_ptr()) };
|
||||
let vfsp = self.as_ptr();
|
||||
|
||||
self.fs.as_mut().unwrap().as_mut().sync(vfsp);
|
||||
}
|
||||
|
||||
pub fn fid(&mut self, path: &str) -> Option<FileId> {
|
||||
if self.ops.is_none() {
|
||||
if self.fs.is_none() {
|
||||
panic!("FsOps is null");
|
||||
}
|
||||
|
||||
unsafe { self.ops.unwrap().as_mut().fid(path, self.as_ptr()) }
|
||||
let vfsp = self.as_ptr();
|
||||
|
||||
self.fs.as_mut().unwrap().as_mut().fid(path, vfsp)
|
||||
}
|
||||
|
||||
pub fn vget(&mut self, fid: FileId) -> VNode {
|
||||
if self.ops.is_none() {
|
||||
if self.fs.is_none() {
|
||||
panic!("FsOps is null");
|
||||
}
|
||||
|
||||
unsafe { self.ops.unwrap().as_mut().vget(fid, self.as_ptr()) }
|
||||
let vfsp = self.as_ptr();
|
||||
|
||||
self.fs.as_mut().unwrap().as_mut().vget(fid, vfsp)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FsOps {
|
||||
// yes, the vfsp was the best solution I could come up with
|
||||
fn mount(&mut self, path: &str, data: &mut *mut u8, vfsp: *const Vfs);
|
||||
fn unmount(&mut self, vfsp: *const Vfs);
|
||||
fn root(&mut self, vfsp: *const Vfs) -> VNode;
|
||||
fn statfs(&mut self, vfsp: *const Vfs) -> StatFs;
|
||||
fn sync(&mut self, vfsp: *const Vfs);
|
||||
fn fid(&mut self, path: &str, vfsp: *const Vfs) -> Option<FileId>;
|
||||
fn mount(&mut self, path: &str, data: &mut *mut u8, vfsp: NonNull<Vfs>);
|
||||
fn unmount(&mut self, vfsp: NonNull<Vfs>);
|
||||
fn root(&mut self, vfsp: NonNull<Vfs>) -> VNode;
|
||||
fn statfs(&mut self, vfsp: NonNull<Vfs>) -> StatFs;
|
||||
fn sync(&mut self, vfsp: NonNull<Vfs>);
|
||||
fn fid(&mut self, path: &str, vfsp: NonNull<Vfs>) -> Option<FileId>;
|
||||
// idk how the fuck you're supposed to accomplish this
|
||||
// good luck I guess.
|
||||
fn vget(&mut self, fid: FileId, vfsp: *const Vfs) -> VNode;
|
||||
fn vget(&mut self, fid: FileId, vfsp: NonNull<Vfs>) -> VNode;
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
@@ -136,6 +223,7 @@ pub struct StatFs {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(PartialEq)]
|
||||
pub enum VNodeType {
|
||||
// Jury is out on this one
|
||||
NON = 0,
|
||||
@@ -149,87 +237,95 @@ pub enum VNodeType {
|
||||
}
|
||||
|
||||
pub struct VNode {
|
||||
// for internal use only
|
||||
relative_path: String,
|
||||
pub flags: u16,
|
||||
pub ref_count: u16,
|
||||
pub shared_lock_count: u16,
|
||||
pub exclusive_lock_count: u16,
|
||||
ops: NonNull<dyn VNodeOperations>,
|
||||
inode: Box<dyn VNodeOperations>,
|
||||
pub node_data: Option<NodeData>,
|
||||
pub parent_vfs: *const Vfs,
|
||||
pub typ: VNodeType,
|
||||
pub vfs_mounted_here: Option<NonNull<Vfs>>,
|
||||
pub parent_vfs: NonNull<Vfs>,
|
||||
pub file_typ: VNodeType,
|
||||
pub data: *mut u8,
|
||||
}
|
||||
|
||||
impl VNode {
|
||||
pub fn new(ops: Box<dyn VNodeOperations>, file_typ: VNodeType, parent_vfs: *const Vfs) -> Self {
|
||||
pub fn new(
|
||||
inode: Box<dyn VNodeOperations>,
|
||||
file_typ: VNodeType,
|
||||
parent_vfs: NonNull<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)) },
|
||||
inode,
|
||||
node_data: None,
|
||||
vfs_mounted_here: None,
|
||||
parent_vfs,
|
||||
typ: file_typ,
|
||||
file_typ,
|
||||
data: core::ptr::null_mut(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const VNode {
|
||||
core::ptr::addr_of!(*self)
|
||||
pub fn as_ptr(&self) -> NonNull<VNode> {
|
||||
unsafe { NonNull::new_unchecked(core::ptr::addr_of!(*self) as *mut 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()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().open(f, c, vp)
|
||||
}
|
||||
|
||||
pub fn close(&mut self, f: u32, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().close(f, c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().close(f, c, vp)
|
||||
}
|
||||
|
||||
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 rdwr(
|
||||
&mut self,
|
||||
uiop: *const UIO,
|
||||
direction: IODirection,
|
||||
f: u32,
|
||||
c: UserCred,
|
||||
) -> Result<Arc<[u8]>, ()> {
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().rdwr(uiop, direction, f, c, vp)
|
||||
}
|
||||
|
||||
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()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().ioctl(com, d, f, c, vp)
|
||||
}
|
||||
|
||||
pub fn select(&mut self, w: IODirection, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().select(w, c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().select(w, c, vp)
|
||||
}
|
||||
|
||||
pub fn getattr(&mut self, c: UserCred) -> VAttr {
|
||||
unsafe { self.ops.as_mut().getattr(c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().getattr(c, vp)
|
||||
}
|
||||
|
||||
pub fn setattr(&mut self, va: VAttr, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().setattr(va, c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().setattr(va, c, vp)
|
||||
}
|
||||
|
||||
pub fn access(&mut self, m: u32, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().access(m, c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().access(m, c, vp)
|
||||
}
|
||||
|
||||
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()) }?;
|
||||
let vp = 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);
|
||||
self.inode.as_mut().lookup(nm, c, vp)
|
||||
}
|
||||
|
||||
pub fn create(
|
||||
@@ -240,70 +336,79 @@ impl VNode {
|
||||
m: u32,
|
||||
c: UserCred,
|
||||
) -> Result<VNode, ()> {
|
||||
unsafe { self.ops.as_mut().create(nm, va, e, m, c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().create(nm, va, e, m, c, vp)
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().link(target_dir, target_name, c, vp)
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode
|
||||
.as_mut()
|
||||
.rename(nm, target_dir, target_name, c, vp)
|
||||
}
|
||||
|
||||
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()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().mkdir(nm, va, c, vp)
|
||||
}
|
||||
|
||||
pub fn readdir(&mut self, uiop: *const UIO, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().readdir(uiop, c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().readdir(uiop, c, vp)
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode
|
||||
.as_mut()
|
||||
.symlink(link_name, va, target_name, c, vp)
|
||||
}
|
||||
|
||||
pub fn readlink(&mut self, uiop: *const UIO, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().readlink(uiop, c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().readlink(uiop, c, vp)
|
||||
}
|
||||
|
||||
pub fn fsync(&mut self, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().fsync(c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().fsync(c, vp)
|
||||
}
|
||||
|
||||
pub fn inactive(&mut self, c: UserCred) {
|
||||
unsafe { self.ops.as_mut().inactive(c, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().inactive(c, vp)
|
||||
}
|
||||
|
||||
pub fn bmap(&mut self, block_number: u32, bnp: ()) -> VNode {
|
||||
unsafe { self.ops.as_mut().bmap(block_number, bnp, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().bmap(block_number, bnp, vp)
|
||||
}
|
||||
|
||||
pub fn strategy(&mut self, bp: ()) {
|
||||
unsafe { self.ops.as_mut().strategy(bp, self.as_ptr()) }
|
||||
let vp = self.as_ptr();
|
||||
|
||||
self.inode.as_mut().strategy(bp, vp)
|
||||
}
|
||||
|
||||
pub fn bread(&mut self, block_number: u32) -> Arc<[u8]> {
|
||||
unsafe { self.ops.as_mut().bread(block_number, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
let vp = 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)
|
||||
self.inode.as_mut().bread(block_number, vp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,22 +452,22 @@ pub struct UIO {
|
||||
}
|
||||
|
||||
pub trait VNodeOperations {
|
||||
fn open(&mut self, f: u32, c: UserCred, vp: *const VNode) -> Result<Arc<[u8]>, ()>;
|
||||
fn close(&mut self, f: u32, c: UserCred, vp: *const VNode);
|
||||
fn open(&mut self, f: u32, c: UserCred, vp: NonNull<VNode>) -> Result<Arc<[u8]>, ()>;
|
||||
fn close(&mut self, f: u32, c: UserCred, vp: NonNull<VNode>);
|
||||
fn rdwr(
|
||||
&mut self,
|
||||
uiop: *const UIO,
|
||||
direction: IODirection,
|
||||
f: u32,
|
||||
c: UserCred,
|
||||
vp: *const VNode,
|
||||
);
|
||||
fn ioctl(&mut self, com: u32, d: *mut u8, f: u32, c: UserCred, vp: *const VNode);
|
||||
fn select(&mut self, w: IODirection, c: UserCred, vp: *const VNode);
|
||||
fn getattr(&mut self, c: UserCred, vp: *const VNode) -> VAttr;
|
||||
fn setattr(&mut self, va: VAttr, c: UserCred, vp: *const VNode);
|
||||
fn access(&mut self, m: u32, c: UserCred, vp: *const VNode);
|
||||
fn lookup(&mut self, nm: &str, c: UserCred, vp: *const VNode) -> Result<VNode, ()>;
|
||||
vp: NonNull<VNode>,
|
||||
) -> Result<Arc<[u8]>, ()>;
|
||||
fn ioctl(&mut self, com: u32, d: *mut u8, f: u32, c: UserCred, vp: NonNull<VNode>);
|
||||
fn select(&mut self, w: IODirection, c: UserCred, vp: NonNull<VNode>);
|
||||
fn getattr(&mut self, c: UserCred, vp: NonNull<VNode>) -> VAttr;
|
||||
fn setattr(&mut self, va: VAttr, c: UserCred, vp: NonNull<VNode>);
|
||||
fn access(&mut self, m: u32, c: UserCred, vp: NonNull<VNode>);
|
||||
fn lookup(&mut self, nm: &str, c: UserCred, vp: NonNull<VNode>) -> Result<VNode, ()>;
|
||||
fn create(
|
||||
&mut self,
|
||||
nm: &str,
|
||||
@@ -370,33 +475,33 @@ pub trait VNodeOperations {
|
||||
e: u32,
|
||||
m: u32,
|
||||
c: UserCred,
|
||||
vp: *const VNode,
|
||||
vp: NonNull<VNode>,
|
||||
) -> Result<VNode, ()>;
|
||||
fn link(&mut self, target_dir: *mut VNode, target_name: &str, c: UserCred, vp: *const VNode);
|
||||
fn link(&mut self, target_dir: *mut VNode, target_name: &str, c: UserCred, vp: NonNull<VNode>);
|
||||
fn rename(
|
||||
&mut self,
|
||||
nm: &str,
|
||||
target_dir: *mut VNode,
|
||||
target_name: &str,
|
||||
c: UserCred,
|
||||
vp: *const VNode,
|
||||
vp: NonNull<VNode>,
|
||||
);
|
||||
fn mkdir(&mut self, nm: &str, va: VAttr, c: UserCred, vp: *const VNode) -> Result<VNode, ()>;
|
||||
fn readdir(&mut self, uiop: *const UIO, c: UserCred, vp: *const VNode);
|
||||
fn mkdir(&mut self, nm: &str, va: VAttr, c: UserCred, vp: NonNull<VNode>) -> Result<VNode, ()>;
|
||||
fn readdir(&mut self, uiop: *const UIO, c: UserCred, vp: NonNull<VNode>);
|
||||
fn symlink(
|
||||
&mut self,
|
||||
link_name: &str,
|
||||
va: VAttr,
|
||||
target_name: &str,
|
||||
c: UserCred,
|
||||
vp: *const VNode,
|
||||
vp: NonNull<VNode>,
|
||||
);
|
||||
fn readlink(&mut self, uiop: *const UIO, c: UserCred, vp: *const VNode);
|
||||
fn fsync(&mut self, c: UserCred, vp: *const VNode);
|
||||
fn inactive(&mut self, c: UserCred, vp: *const VNode);
|
||||
fn bmap(&mut self, block_number: u32, bnp: (), vp: *const VNode) -> VNode;
|
||||
fn strategy(&mut self, bp: (), vp: *const VNode);
|
||||
fn bread(&mut self, block_number: u32, vp: *const VNode) -> Arc<[u8]>;
|
||||
fn readlink(&mut self, uiop: *const UIO, c: UserCred, vp: NonNull<VNode>);
|
||||
fn fsync(&mut self, c: UserCred, vp: NonNull<VNode>);
|
||||
fn inactive(&mut self, c: UserCred, vp: NonNull<VNode>);
|
||||
fn bmap(&mut self, block_number: u32, bnp: (), vp: NonNull<VNode>) -> VNode;
|
||||
fn strategy(&mut self, bp: (), vp: NonNull<VNode>);
|
||||
fn bread(&mut self, block_number: u32, vp: NonNull<VNode>) -> Arc<[u8]>;
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
@@ -419,72 +524,24 @@ pub struct VAttr {
|
||||
used_blocks: u32,
|
||||
}
|
||||
|
||||
unsafe fn vfs_has_mount_point(mount_point: &str) -> Option<NonNull<Vfs>> {
|
||||
let mut current = ROOT_VFS.next;
|
||||
|
||||
while let Some(node) = current {
|
||||
if node.as_ref().mount_point.as_ref().unwrap() == mount_point {
|
||||
return Some(node);
|
||||
}
|
||||
|
||||
current = unsafe { (*node.as_ptr()).next };
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn add_vfs(mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
|
||||
/// # Safety
|
||||
/// Consumes vfs
|
||||
unsafe fn deallocate_vfs(vfs: NonNull<Vfs>) {
|
||||
let fs_ops_box = Box::from_raw(vfs.as_ref().ops.unwrap().as_ptr());
|
||||
drop(fs_ops_box);
|
||||
dealloc(
|
||||
vfs.as_ptr().cast::<u8>(),
|
||||
alloc::alloc::Layout::new::<Vfs>(),
|
||||
);
|
||||
}
|
||||
|
||||
let layout = alloc::alloc::Layout::new::<Vfs>();
|
||||
let vfs_ptr = unsafe { alloc(layout).cast::<Vfs>() };
|
||||
|
||||
if vfs_ptr.is_null() {
|
||||
handle_alloc_error(layout)
|
||||
}
|
||||
|
||||
// Initialize the data so we can use the nonnull helpers
|
||||
unsafe {
|
||||
let mut vfs = Vfs::null();
|
||||
vfs.ops = Some(NonNull::new_unchecked(Box::into_raw(fs_ops)));
|
||||
// 'normalize' the path (yes, making "/" == "" is intentional)
|
||||
vfs.mount_point = Some(mount_point.trim_end_matches('/').to_string());
|
||||
vfs_ptr.write(vfs);
|
||||
};
|
||||
let mut new_vfs = Vfs::null();
|
||||
new_vfs.fs = Some(fs_ops);
|
||||
let mut vfs = Box::new(new_vfs);
|
||||
|
||||
// Safety: We know vfs_ptr is not null
|
||||
let mut vfs_ptr = unsafe { NonNull::new_unchecked(vfs_ptr) };
|
||||
|
||||
let vfs = unsafe { vfs_ptr.as_mut() };
|
||||
let vfsp = vfs.as_ptr();
|
||||
|
||||
log_info!("Adding vfs at {mount_point}");
|
||||
|
||||
if mount_point == "/" {
|
||||
if unsafe { ROOT_VFS.next.is_some() } {
|
||||
unsafe {
|
||||
deallocate_vfs(vfs_ptr);
|
||||
};
|
||||
|
||||
return Err(());
|
||||
}
|
||||
|
||||
vfs.mount(mount_point);
|
||||
|
||||
unsafe { ROOT_VFS.next = Some(vfs_ptr) };
|
||||
unsafe { NODE_TREE = Some(TreeNode::new(vfs.fs.as_mut().unwrap().as_mut().root(vfsp))) }
|
||||
} else {
|
||||
if unsafe { ROOT_VFS.next.is_none() } {
|
||||
unsafe {
|
||||
deallocate_vfs(vfs_ptr);
|
||||
};
|
||||
return Err(());
|
||||
}
|
||||
|
||||
@@ -492,46 +549,26 @@ pub fn add_vfs(mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut next_vfs = unsafe { ROOT_VFS.next };
|
||||
let vnode = vfs_open(mount_point)?;
|
||||
|
||||
while let Some(target_vfs) = next_vfs {
|
||||
if unsafe { target_vfs.as_ref().mount_point.as_ref().unwrap() == mount_point } {
|
||||
unsafe {
|
||||
deallocate_vfs(vfs_ptr);
|
||||
};
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if unsafe { target_vfs.as_ref().next }.is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
next_vfs = unsafe { target_vfs.as_ref().next };
|
||||
}
|
||||
|
||||
if next_vfs.is_none() {
|
||||
unsafe {
|
||||
deallocate_vfs(vfs_ptr);
|
||||
};
|
||||
return Err(());
|
||||
}
|
||||
|
||||
vfs.mount(mount_point);
|
||||
|
||||
unsafe { (next_vfs.unwrap()).as_mut().next = Some(vfs_ptr) };
|
||||
vnode.vfs_mounted_here = Some(vfsp);
|
||||
}
|
||||
|
||||
vfs.mount(mount_point);
|
||||
|
||||
unsafe { ROOT_VFS.add_vfs(vfs) };
|
||||
|
||||
log_ok!("Added vfs at {mount_point}");
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn vfs_open(path: &str) -> Result<VNode, ()> {
|
||||
if unsafe { ROOT_VFS.next.is_none() } {
|
||||
pub fn vfs_open(path: &str) -> Result<&mut VNode, ()> {
|
||||
if unsafe { ROOT_VFS.next.is_none() || NODE_TREE.is_none() } {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut cur_vnode = unsafe { ROOT_VFS.next.unwrap().as_mut().root() };
|
||||
let mut cur_node = unsafe { NODE_TREE.as_mut().unwrap() };
|
||||
|
||||
let parts = path.split('/').collect::<Vec<&str>>();
|
||||
|
||||
@@ -540,12 +577,12 @@ pub fn vfs_open(path: &str) -> Result<VNode, ()> {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(vnode) = cur_vnode.lookup(part, UserCred { uid: 0, gid: 0 }) {
|
||||
cur_vnode = vnode;
|
||||
if let Ok(new_node) = cur_node.lookup(part) {
|
||||
cur_node = new_node;
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(cur_vnode);
|
||||
return Ok(cur_node.get_vnode());
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ pub fn is_transmit_empty() -> bool {
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
pub fn write_serial(character: u8) {
|
||||
unsafe {
|
||||
*UART = character;
|
||||
UART.write(character);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -432,14 +432,14 @@ impl ATABus {
|
||||
ATADriveDirection::Read => unsafe {
|
||||
insw(
|
||||
self.io_bar + ATADriveDataRegister::Data as u16,
|
||||
(buffer.as_mut_ptr() as *mut u16).add(buffer_offset),
|
||||
(buffer.as_mut_ptr().cast::<u16>()).add(buffer_offset),
|
||||
ATA_SECTOR_SIZE / size_of::<u16>(),
|
||||
);
|
||||
},
|
||||
ATADriveDirection::Write => unsafe {
|
||||
outsw(
|
||||
self.io_bar + ATADriveDataRegister::Data as u16,
|
||||
(buffer.as_mut_ptr() as *mut u16).add(buffer_offset),
|
||||
(buffer.as_mut_ptr().cast::<u16>()).add(buffer_offset),
|
||||
ATA_SECTOR_SIZE / size_of::<u16>(),
|
||||
)
|
||||
},
|
||||
@@ -502,7 +502,7 @@ impl ATADrive {
|
||||
fn sector_count(&self) -> u64 {
|
||||
let sectors = self.identify_data[120..].as_ptr();
|
||||
|
||||
return unsafe { *(sectors as *const u32) } as u64;
|
||||
return unsafe { *(sectors.cast::<u32>()) } as u64;
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const ATADrive {
|
||||
@@ -524,7 +524,7 @@ impl BlockDevice for ATADrive {
|
||||
fn sector_count(&self) -> u64 {
|
||||
let sectors = self.identify_data[120..].as_ptr();
|
||||
|
||||
return unsafe { *(sectors as *const u32) } as u64;
|
||||
return unsafe { *(sectors.cast::<u32>()) } as u64;
|
||||
}
|
||||
|
||||
fn write(&self, sector: u64, buffer: &[u8]) -> Result<(), ()> {
|
||||
@@ -542,7 +542,6 @@ static DRIVES: Mutex<Vec<ATADrive>> = Mutex::new(Vec::new());
|
||||
|
||||
// TODO: This code is pretty much just the C from @Moldytzu's mOS
|
||||
// This code could probably be made better and more device agnostic
|
||||
// But that's TODO obviously
|
||||
fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
|
||||
let mut drives_lock = DRIVES.lock();
|
||||
let io_port_base = bar0 as u16;
|
||||
|
||||
@@ -32,7 +32,7 @@ impl Framebuffer {
|
||||
let pixel_offset = (y * self.pitch as u32 + (x * (self.bpp / 8) as u32)) as isize;
|
||||
|
||||
unsafe {
|
||||
*(self.pointer.offset(pixel_offset) as *mut u32) = color;
|
||||
*(self.pointer.offset(pixel_offset).cast::<u32>()) = color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,21 +43,25 @@ impl Framebuffer {
|
||||
|
||||
unsafe {
|
||||
if let Some(mirror_buffer) = mirror_buffer {
|
||||
crate::mem::memset32(mirror_buffer.pointer as *mut u32, color, buffer_size);
|
||||
crate::mem::memset32(mirror_buffer.pointer.cast::<u32>(), color, buffer_size);
|
||||
}
|
||||
|
||||
crate::mem::memset32(self.pointer as *mut u32, color, buffer_size);
|
||||
crate::mem::memset32(self.pointer.cast::<u32>(), color, buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blit_screen(&self, buffer: &mut [u32], mirror_buffer: Option<Self>) {
|
||||
unsafe {
|
||||
core::ptr::copy_nonoverlapping(buffer.as_ptr(), self.pointer as *mut u32, buffer.len());
|
||||
core::ptr::copy_nonoverlapping(
|
||||
buffer.as_ptr(),
|
||||
self.pointer.cast::<u32>(),
|
||||
buffer.len(),
|
||||
);
|
||||
|
||||
if let Some(mirror_buffer) = mirror_buffer {
|
||||
core::ptr::copy_nonoverlapping(
|
||||
buffer.as_ptr(),
|
||||
mirror_buffer.pointer as *mut u32,
|
||||
mirror_buffer.pointer.cast::<u32>(),
|
||||
buffer.len(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ pub struct Cell<T: ?Sized> {
|
||||
value: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> !Sync for Cell<T> {}
|
||||
|
||||
impl<T> Cell<T> {
|
||||
pub const fn new(value: T) -> Cell<T> {
|
||||
return Self {
|
||||
|
||||
54
src/main.rs
54
src/main.rs
@@ -1,4 +1,10 @@
|
||||
#![feature(allocator_api, abi_x86_interrupt, naked_functions, const_mut_refs)]
|
||||
#![feature(
|
||||
allocator_api,
|
||||
abi_x86_interrupt,
|
||||
naked_functions,
|
||||
const_mut_refs,
|
||||
negative_impls
|
||||
)]
|
||||
#![allow(clippy::needless_return)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@@ -45,13 +51,12 @@ pub fn kmain() -> ! {
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
drivers::pci::enumerate_pci_bus();
|
||||
|
||||
let mut file = vfs_open("/firstdir/seconddirbutlonger/yeah.txt").unwrap();
|
||||
let file = vfs_open("/firstdir/seconddirbutlonger/yeah.txt").unwrap();
|
||||
|
||||
crate::println!("YEAH.TXT: {:X?}", file.open(0, UserCred { uid: 0, gid: 0 }));
|
||||
|
||||
drivers::storage::ide::init();
|
||||
|
||||
let mut limine_dir = vfs_open("/mnt/boot/limine").unwrap();
|
||||
let limine_dir = vfs_open("/mnt/boot/limine").unwrap();
|
||||
|
||||
crate::println!(
|
||||
"LIMINE BOOT: {:X?}",
|
||||
@@ -61,21 +66,22 @@ pub fn kmain() -> ! {
|
||||
.open(0, UserCred { uid: 0, gid: 0 })
|
||||
);
|
||||
|
||||
let mut root_dir = vfs_open("/").unwrap();
|
||||
// TODO: figure out whether this should or shouldnt work in the first place
|
||||
// let 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 })
|
||||
);
|
||||
// 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();
|
||||
|
||||
@@ -83,20 +89,20 @@ pub fn kmain() -> ! {
|
||||
draw_gradient();
|
||||
|
||||
// loop {
|
||||
// let ch = read_serial();
|
||||
// let ch = crate::drivers::serial::read_serial();
|
||||
|
||||
// if ch == b'\x00' {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// if ch == b'\x08' {
|
||||
// write_serial(b'\x08');
|
||||
// write_serial(b' ');
|
||||
// write_serial(b'\x08');
|
||||
// crate::drivers::serial::write_serial(b'\x08');
|
||||
// crate::drivers::serial::write_serial(b' ');
|
||||
// crate::drivers::serial::write_serial(b'\x08');
|
||||
// }
|
||||
|
||||
// if ch > 0x20 && ch < 0x7F {
|
||||
// write_serial(ch);
|
||||
// if ch > 0x1F && ch < 0x7F {
|
||||
// crate::drivers::serial::write_serial(ch);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user