diff --git a/Cargo.toml b/Cargo.toml index f98dd4c..3d9afb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,15 @@ name = "simple-filesystem" version = "0.0.1" authors = ["WangRunji "] +[lib] +crate-type = ["staticlib"] + +[profile.dev] +panic = 'abort' # prevent `_Unwind_Resume` link error + [dependencies] spin = "0.4" -bit-set = "0.5" +bit-set = { default-features = false, version = "0.5" } # default-features contains 'std' [features] ucore = [] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e08c0d0 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +ucore: + @RUST_TARGET_PATH=$(shell pwd) xargo build --target ucore --features ucore \ No newline at end of file diff --git a/Xargo.toml b/Xargo.toml new file mode 100644 index 0000000..10e8f71 --- /dev/null +++ b/Xargo.toml @@ -0,0 +1,2 @@ +[target.ucore.dependencies] +alloc = {} \ No newline at end of file diff --git a/src/c_interface.rs b/src/c_interface.rs index f9f01a9..822dd55 100644 --- a/src/c_interface.rs +++ b/src/c_interface.rs @@ -1,16 +1,92 @@ //! C Interfaces for ucore +use alloc::{rc::Rc, boxed::Box}; +use core::cell::RefCell; +use core::slice; + +/// Global allocator defined in root pub use self::allocator::UcoreAllocator; +/// Lang items for bare lib +mod lang { + use core; + + #[lang = "eh_personality"] + #[no_mangle] + extern fn eh_personality() { + } + + #[lang = "panic_fmt"] + #[no_mangle] + extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! { + eprintln!("\n\nPANIC in {} at line {}:", file, line); + eprintln!(" {}", fmt); + use super::ucore::__panic; + unsafe{ __panic() }; + unreachable!() + } +} + +/// Depends on ucore +mod ucore { + use super::*; + extern { + pub fn __alloc_inode(type_: i32) -> *mut INode; + pub fn inode_init(inode: &mut INode, ops: &INodeOps, fs: &mut Fs); + pub fn inode_kill(inode: &mut INode); + pub fn __alloc_fs(type_: i32) -> *mut Fs; + pub fn __panic(); + } + pub const SFS_TYPE: i32 = 0; // TODO +} + +// Exports for ucore + +static SFS_INODE_OPS: INodeOps = INodeOps::from_rust_inode::(); +//static SFS_FS: *mut Fs = 0 as *mut _; + #[no_mangle] -pub static SFS_INODE_OPS: INodeOps = INodeOps::from_rust_inode::(); +pub extern fn sfs_do_mount(dev: *mut Device, fs_store: &mut *mut Fs) -> ErrorCode { + use self::ucore::*; + let fs = unsafe{__alloc_fs(SFS_TYPE)}; + let device = unsafe{ Box::from_raw(dev) }; // TODO: fix unsafe + unsafe{&mut (*fs)}.fs = sfs::SimpleFileSystem::open(device).unwrap(); + *fs_store = fs; + ErrorCode::Ok +} + +// Structs defined in ucore /// Abstract low-level file. /// /// Match struct `inode` in ucore `kern/fs/vfs/inode.h` #[repr(C)] struct INode { - // TODO: full the struct + inode: Rc>, + // ... fields handled extern +} + +/// Abstract filesystem. (Or device accessible as a file.) +/// +/// Match struct `fs` in ucore `kern/fs/vfs/vfs.h` +#[repr(C)] +pub struct Fs { + fs: Rc, + // ... fields handled extern +} + +/// Filesystem-namespace-accessible device. +/// d_io is for both reads and writes; the iobuf will indicates the direction. +/// +/// Match struct `device` in ucore `kern/fs/devs/dev.h` +#[repr(C)] +pub struct Device { + blocks: usize, + blocksize: usize, + open: extern fn(&mut Device, flags: u32) -> ErrorCode, + close: extern fn(&mut Device) -> ErrorCode, + io: extern fn(&mut Device, buf: &mut IoBuf, is_write: bool) -> ErrorCode, + ioctl: extern fn(&mut Device, op: i32, data: *mut u8) -> ErrorCode, } /// A buffer Rd/Wr status record @@ -63,78 +139,164 @@ const S_IFBLK: u32 = 050000; #[repr(C)] pub struct INodeOps { magic: u64, - open: extern fn(*mut INode, flags: u32) -> ErrorCode, - close: extern fn(*mut INode) -> ErrorCode, - read: extern fn(*mut INode, *mut IoBuf) -> ErrorCode, - write: extern fn(*mut INode, *mut IoBuf) -> ErrorCode, - fstat: extern fn(*mut INode, *mut Stat) -> ErrorCode, - fsync: extern fn(*mut INode) -> ErrorCode, - namefile: extern fn(*mut INode, *mut IoBuf) -> ErrorCode, - getdirentry: extern fn(*mut INode, *mut IoBuf) -> ErrorCode, - reclaim: extern fn(*mut INode) -> ErrorCode, - gettype: extern fn(*mut INode, type_store: *mut u32) -> ErrorCode, - tryseek: extern fn(*mut INode, pos: i32) -> ErrorCode, - truncate: extern fn(*mut INode, len: i32) -> ErrorCode, - create: extern fn(*mut INode, name: *const u8, excl: bool, inode_store: *mut *mut INode) -> ErrorCode, - lookup: extern fn(*mut INode, path: *mut u8, inode_store: *mut *mut INode) -> ErrorCode, - ioctl: extern fn(*mut INode, op: i32, data: *mut u8) -> ErrorCode, + open: extern fn(&mut INode, flags: u32) -> ErrorCode, + close: extern fn(&mut INode) -> ErrorCode, + read: extern fn(&mut INode, &mut IoBuf) -> ErrorCode, + write: extern fn(&mut INode, &mut IoBuf) -> ErrorCode, + fstat: extern fn(&mut INode, &mut Stat) -> ErrorCode, + fsync: extern fn(&mut INode) -> ErrorCode, + namefile: extern fn(&mut INode, &mut IoBuf) -> ErrorCode, + getdirentry: extern fn(&mut INode, &mut IoBuf) -> ErrorCode, + reclaim: extern fn(&mut INode) -> ErrorCode, + gettype: extern fn(&mut INode, type_store: &mut u32) -> ErrorCode, + tryseek: extern fn(&mut INode, pos: i32) -> ErrorCode, + truncate: extern fn(&mut INode, len: i32) -> ErrorCode, + create: extern fn(&mut INode, name: *const u8, excl: bool, inode_store: &mut &mut INode) -> ErrorCode, + lookup: extern fn(&mut INode, path: &mut u8, inode_store: &mut &mut INode) -> ErrorCode, + ioctl: extern fn(&mut INode, op: i32, data: &mut u8) -> ErrorCode, } #[repr(i32)] -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub enum ErrorCode { Ok = 0, Unimplemented = -1, } +// Wrapper functions + use vfs; use sfs; +impl AsRef<[u8]> for IoBuf { + fn as_ref(&self) -> &[u8] { + unsafe{ slice::from_raw_parts(self.base, self.resident as usize) } + } +} +impl AsMut<[u8]> for IoBuf { + fn as_mut(&mut self) -> &mut [u8] { + unsafe{ slice::from_raw_parts_mut(self.base, self.resident as usize) } + } +} +impl IoBuf { + fn skip(&mut self, len: usize) { + assert!(len as u32 <= self.resident); + self.base = unsafe{ self.base.offset(len as isize) }; + self.offset += len as i32; + self.resident -= len as u32; + } +} + +impl sfs::Device for Device { + fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option { + let mut io_buf = IoBuf { + base: buf.as_mut_ptr(), + offset: offset as i32, + len: buf.len() as u32, + resident: buf.len() as u32, + }; + let ret = (self.io)(self, &mut io_buf, false); + assert_eq!(ret, ErrorCode::Ok); + Some(buf.len() - io_buf.resident as usize) + } + + fn write_at(&mut self, offset: usize, buf: &[u8]) -> Option { + let mut io_buf = IoBuf { + base: buf.as_ptr() as *mut u8, + offset: offset as i32, + len: buf.len() as u32, + resident: buf.len() as u32, + }; + let ret = (self.io)(self, &mut io_buf, true); + assert_eq!(ret, ErrorCode::Ok); + Some(buf.len() - io_buf.resident as usize) + } +} + +impl INode { + fn new() -> *mut Self { + use self::ucore::*; + let ptr = unsafe{ __alloc_inode(SFS_TYPE) }; + assert!(!ptr.is_null()); +// inode_init(ptr, &SFS_INODE_OPS as *const _, SFS_FS); + ptr + + } + fn drop(&mut self) { + use self::ucore::*; + unsafe{ inode_kill(self) }; + } +} + +impl From for Stat { + fn from(info: vfs::FileInfo) -> Self { + Stat { + mode: info.mode, + nlinks: 0, + blocks: info.blocks as u32, + size: info.size as u32, + } + } +} + impl INodeOps { const fn from_rust_inode() -> Self { - extern fn open(inode: *mut INode, flags: u32) -> ErrorCode { + extern fn open(inode: &mut INode, flags: u32) -> ErrorCode { ErrorCode::Unimplemented } - extern fn close(inode: *mut INode) -> ErrorCode { + extern fn close(inode: &mut INode) -> ErrorCode { ErrorCode::Unimplemented } - extern fn read(inode: *mut INode, buf: *mut IoBuf) -> ErrorCode { - ErrorCode::Unimplemented + extern fn read(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { + let inode = &inode.inode; + let len = inode.borrow().read_at(buf.offset as usize, buf.as_mut()).unwrap(); + buf.skip(len); + ErrorCode::Ok } - extern fn write(inode: *mut INode, buf: *mut IoBuf) -> ErrorCode { - ErrorCode::Unimplemented + extern fn write(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { + let inode = &inode.inode; + let len = inode.borrow().write_at(buf.offset as usize, buf.as_ref()).unwrap(); + buf.skip(len); + ErrorCode::Ok } - extern fn fstat(inode: *mut INode, stat: *mut Stat) -> ErrorCode { - ErrorCode::Unimplemented + extern fn fstat(inode: &mut INode, stat: &mut Stat) -> ErrorCode { + let inode = &inode.inode; + let info = inode.borrow().info().unwrap(); + *stat = Stat::from(info); + ErrorCode::Ok } - extern fn fsync(inode: *mut INode) -> ErrorCode { - ErrorCode::Unimplemented + extern fn fsync(inode: &mut INode) -> ErrorCode { + inode.inode.borrow_mut().sync().unwrap(); + ErrorCode::Ok } - extern fn namefile(inode: *mut INode, buf: *mut IoBuf) -> ErrorCode { + extern fn namefile(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { ErrorCode::Unimplemented } - extern fn getdirentry(inode: *mut INode, buf: *mut IoBuf) -> ErrorCode { + extern fn getdirentry(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { ErrorCode::Unimplemented } - extern fn reclaim(inode: *mut INode) -> ErrorCode { + extern fn reclaim(inode: &mut INode) -> ErrorCode { ErrorCode::Unimplemented } - extern fn gettype(inode: *mut INode, type_store: *mut u32) -> ErrorCode { - ErrorCode::Unimplemented + extern fn gettype(inode: &mut INode, type_store: &mut u32) -> ErrorCode { + let inode = &inode.inode; + let info = inode.borrow().info().unwrap(); + *type_store = info.type_ as u32; + ErrorCode::Ok } - extern fn tryseek(inode: *mut INode, pos: i32) -> ErrorCode { + extern fn tryseek(inode: &mut INode, pos: i32) -> ErrorCode { ErrorCode::Unimplemented } - extern fn truncate(inode: *mut INode, len: i32) -> ErrorCode { + extern fn truncate(inode: &mut INode, len: i32) -> ErrorCode { ErrorCode::Unimplemented } - extern fn create(inode: *mut INode, name: *const u8, excl: bool, inode_store: *mut *mut INode) -> ErrorCode { + extern fn create(inode: &mut INode, name: *const u8, excl: bool, inode_store: &mut &mut INode) -> ErrorCode { ErrorCode::Unimplemented } - extern fn lookup(inode: *mut INode, path: *mut u8, inode_store: *mut *mut INode) -> ErrorCode { + extern fn lookup(inode: &mut INode, path: &mut u8, inode_store: &mut &mut INode) -> ErrorCode { ErrorCode::Unimplemented } - extern fn ioctl(inode: *mut INode, op: i32, data: *mut u8) -> ErrorCode { + extern fn ioctl(inode: &mut INode, op: i32, data: &mut u8) -> ErrorCode { ErrorCode::Unimplemented } INodeOps { diff --git a/src/lib.rs b/src/lib.rs index 4e737d2..f67c072 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(alloc)] #![feature(const_fn)] -#![cfg_attr(feature = "ucore", feature(allocator_api, global_allocator))] +#![cfg_attr(feature = "ucore", feature(allocator_api, global_allocator, lang_items))] #![no_std] #[cfg(test)] diff --git a/src/sfs.rs b/src/sfs.rs index 7b19938..f394794 100644 --- a/src/sfs.rs +++ b/src/sfs.rs @@ -239,6 +239,7 @@ impl vfs::INode for INode { size: self.disk_inode.size as usize, mode: 0, type_: vfs::FileType::from(self.disk_inode.type_.clone()), + blocks: self.disk_inode.blocks as usize, }) } fn sync(&mut self) -> vfs::Result<()> { diff --git a/src/tests.rs b/src/tests.rs index dde7a15..eb52555 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -70,6 +70,7 @@ fn create_file() { size: 0, type_: FileType::File, mode: 0, + blocks: 0, }); sfs.sync().unwrap(); diff --git a/src/vfs.rs b/src/vfs.rs index 01d091e..9be6ef5 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -27,6 +27,7 @@ pub struct FileInfo { pub size: usize, pub mode: u32, pub type_: FileType, + pub blocks: usize, } #[derive(Debug, Eq, PartialEq)] diff --git a/ucore.json b/ucore.json new file mode 100644 index 0000000..9fccee8 --- /dev/null +++ b/ucore.json @@ -0,0 +1,16 @@ +{ + "cpu": "pentium4", + "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", + "llvm-target": "i686-unknown-none", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "features": "-mmx,-sse,+soft-float", + "os": "none", + "arch": "x86", + "linker-flavor": "ld", + "pre-link-args": ["-m32"], + "eliminate-frame-pointer": false, + "morestack": false, + "panic-strategy": "abort" +} \ No newline at end of file