diff --git a/fs/macros/src/lib.rs b/fs/macros/src/lib.rs index 91d79e9..db86c8d 100644 --- a/fs/macros/src/lib.rs +++ b/fs/macros/src/lib.rs @@ -1,162 +1,162 @@ -extern crate proc_macro; -extern crate syn; -#[macro_use] -extern crate quote; +// extern crate proc_macro; +// extern crate syn; +// #[macro_use] +// extern crate quote; +// +// use proc_macro::TokenStream; +// use quote::ToTokens; +// use std::collections::HashSet; +// use syn::{parse_macro_input, ImplItem, ItemImpl, Ident}; -use proc_macro::TokenStream; -use quote::ToTokens; -use std::collections::HashSet; -use syn::{parse_macro_input, ImplItem, ItemImpl, Ident}; - -fn impl_inode_fn(name: &str, behavior: T) -> ImplItem { - // TODO somehow know if current crate is vfs or not? - ImplItem::Verbatim(match name { - "create" => quote! { - fn create(&mut self, _at: VnodeRef, _name: &str, kind: VnodeKind) -> - Result - { - #behavior - } - }, - "remove" => quote! { - fn remove(&mut self, _at: VnodeRef, _name: &str) -> Result<(), libsys::error::Errno> { - #behavior - } - }, - "lookup" => quote! { - fn lookup(&mut self, _at: VnodeRef, _name: &str) -> - Result - { - #behavior - } - }, - "stat" => quote! { - fn stat(&mut self, _at: VnodeRef) -> - Result - { - #behavior - } - }, - "truncate" => quote! { - fn truncate(&mut self, _node: VnodeRef, _size: usize) -> - Result<(), libsys::error::Errno> - { - #behavior - } - }, - "size" => quote! { - fn size(&mut self, _node: VnodeRef) -> Result { - #behavior - } - }, - "read" => quote! { - fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) -> - Result - { - #behavior - } - }, - "write" => quote! { - fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> - Result - { - #behavior - } - }, - "open" => quote! { - fn open(&mut self, _node: VnodeRef, _flags: libsys::stat::OpenFlags) -> - Result - { - #behavior - } - }, - "close" => quote! { - fn close(&mut self, _node: VnodeRef) -> Result<(), libsys::error::Errno> { - #behavior - } - }, - "ioctl" => quote! { - fn ioctl( - &mut self, - _node: VnodeRef, - _cmd: libsys::ioctl::IoctlCmd, - _ptr: usize, - _len: usize) -> - Result - { - #behavior - } - }, - "is_ready" => quote! { - fn is_ready(&mut self, _node: VnodeRef, _write: bool) -> - Result - { - #behavior - } - }, - "readdir" => quote! { - fn readdir( - &mut self, - _node: VnodeRef, - _pos: usize, - _entries: &mut [libsys::stat::DirectoryEntry] - ) -> - Result - { - #behavior - } - }, - _ => panic!("TODO implement {:?}", name), - }) -} - -#[proc_macro_attribute] -pub fn auto_inode(attr: TokenStream, input: TokenStream) -> TokenStream { - let mut impl_item = parse_macro_input!(input as ItemImpl); - let mut missing = HashSet::::new(); - let behavior = if attr.is_empty() { - "unimplemented".to_string() - } else { - parse_macro_input!(attr as Ident).to_string() - }; - let behavior = match behavior.as_str() { - "unimplemented" => quote! { unimplemented!() }, - "panic" => quote! { panic!() }, - "error" => quote! { Err(libsys::error::Errno::NotImplemented) }, - _ => panic!("Unknown #[auto_inode] behavior: {:?}", behavior) - }; - - missing.insert("create".to_string()); - missing.insert("remove".to_string()); - missing.insert("lookup".to_string()); - missing.insert("open".to_string()); - missing.insert("close".to_string()); - missing.insert("truncate".to_string()); - missing.insert("read".to_string()); - missing.insert("write".to_string()); - missing.insert("stat".to_string()); - missing.insert("size".to_string()); - missing.insert("ioctl".to_string()); - missing.insert("is_ready".to_string()); - missing.insert("readdir".to_string()); - - for item in &impl_item.items { - match item { - ImplItem::Method(method) => { - let name = &method.sig.ident.to_string(); - if missing.contains(name) { - missing.remove(name); - } - } - _ => panic!("Unexpected impl item"), - } - } - - for item in &missing { - impl_item - .items - .push(impl_inode_fn(item, behavior.clone())); - } - - impl_item.to_token_stream().into() -} +//fn impl_inode_fn(name: &str, behavior: T) -> ImplItem { +// // TODO somehow know if current crate is vfs or not? +// ImplItem::Verbatim(match name { +// "create" => quote! { +// fn create(&mut self, _at: VnodeRef, _name: &str, kind: VnodeKind) -> +// Result +// { +// #behavior +// } +// }, +// "remove" => quote! { +// fn remove(&mut self, _at: VnodeRef, _name: &str) -> Result<(), libsys::error::Errno> { +// #behavior +// } +// }, +// "lookup" => quote! { +// fn lookup(&mut self, _at: VnodeRef, _name: &str) -> +// Result +// { +// #behavior +// } +// }, +// "stat" => quote! { +// fn stat(&mut self, _at: VnodeRef) -> +// Result +// { +// #behavior +// } +// }, +// "truncate" => quote! { +// fn truncate(&mut self, _node: VnodeRef, _size: usize) -> +// Result<(), libsys::error::Errno> +// { +// #behavior +// } +// }, +// "size" => quote! { +// fn size(&mut self, _node: VnodeRef) -> Result { +// #behavior +// } +// }, +// "read" => quote! { +// fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) -> +// Result +// { +// #behavior +// } +// }, +// "write" => quote! { +// fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> +// Result +// { +// #behavior +// } +// }, +// "open" => quote! { +// fn open(&mut self, _node: VnodeRef, _flags: libsys::stat::OpenFlags) -> +// Result +// { +// #behavior +// } +// }, +// "close" => quote! { +// fn close(&mut self, _node: VnodeRef) -> Result<(), libsys::error::Errno> { +// #behavior +// } +// }, +// "ioctl" => quote! { +// fn ioctl( +// &mut self, +// _node: VnodeRef, +// _cmd: libsys::ioctl::IoctlCmd, +// _ptr: usize, +// _len: usize) -> +// Result +// { +// #behavior +// } +// }, +// "is_ready" => quote! { +// fn is_ready(&mut self, _node: VnodeRef, _write: bool) -> +// Result +// { +// #behavior +// } +// }, +// "readdir" => quote! { +// fn readdir( +// &mut self, +// _node: VnodeRef, +// _pos: usize, +// _entries: &mut [libsys::stat::DirectoryEntry] +// ) -> +// Result +// { +// #behavior +// } +// }, +// _ => panic!("TODO implement {:?}", name), +// }) +//} +// +//#[proc_macro_attribute] +//pub fn auto_inode(attr: TokenStream, input: TokenStream) -> TokenStream { +// let mut impl_item = parse_macro_input!(input as ItemImpl); +// let mut missing = HashSet::::new(); +// let behavior = if attr.is_empty() { +// "unimplemented".to_string() +// } else { +// parse_macro_input!(attr as Ident).to_string() +// }; +// let behavior = match behavior.as_str() { +// "unimplemented" => quote! { unimplemented!() }, +// "panic" => quote! { panic!() }, +// "error" => quote! { Err(libsys::error::Errno::NotImplemented) }, +// _ => panic!("Unknown #[auto_inode] behavior: {:?}", behavior) +// }; +// +// missing.insert("create".to_string()); +// missing.insert("remove".to_string()); +// missing.insert("lookup".to_string()); +// missing.insert("open".to_string()); +// missing.insert("close".to_string()); +// missing.insert("truncate".to_string()); +// missing.insert("read".to_string()); +// missing.insert("write".to_string()); +// missing.insert("stat".to_string()); +// missing.insert("size".to_string()); +// missing.insert("ioctl".to_string()); +// missing.insert("is_ready".to_string()); +// missing.insert("readdir".to_string()); +// +// for item in &impl_item.items { +// match item { +// ImplItem::Method(method) => { +// let name = &method.sig.ident.to_string(); +// if missing.contains(name) { +// missing.remove(name); +// } +// } +// _ => panic!("Unexpected impl item"), +// } +// } +// +// for item in &missing { +// impl_item +// .items +// .push(impl_inode_fn(item, behavior.clone())); +// } +// +// impl_item.to_token_stream().into() +//} diff --git a/fs/memfs/src/block.rs b/fs/memfs/src/block.rs index 64241c9..9d4182f 100644 --- a/fs/memfs/src/block.rs +++ b/fs/memfs/src/block.rs @@ -11,6 +11,9 @@ pub struct BlockRef<'a, A: BlockAllocator + Copy> { alloc: MaybeUninit, } +/// # Safety +/// +/// This trait is unsafe to implement due to its direct memory management pub unsafe trait BlockAllocator { fn alloc(&self) -> *mut u8; /// # Safety diff --git a/fs/memfs/src/dir.rs b/fs/memfs/src/dir.rs index 84f1ef5..90f6aa3 100644 --- a/fs/memfs/src/dir.rs +++ b/fs/memfs/src/dir.rs @@ -18,7 +18,6 @@ impl VnodeDirectory for DirInode { let data = match kind { VnodeCreateKind::Directory => VnodeData::Directory(RefCell::new(Some(Box::new(DirInode { alloc: self.alloc })))), VnodeCreateKind::File => VnodeData::File(RefCell::new(Some(Box::new(FileInode::new(Bvec::new(self.alloc)))))), - _ => todo!() }; Ok(Vnode::new(name, data, Vnode::SEEKABLE | Vnode::CACHE_READDIR)) // match kind { @@ -38,9 +37,9 @@ impl VnodeDirectory for DirInode { /// Read directory entries into target buffer fn readdir( &mut self, - node: VnodeRef, - pos: usize, - data: &mut [DirectoryEntry], + _node: VnodeRef, + _pos: usize, + _data: &mut [DirectoryEntry], ) -> Result { todo!() } @@ -59,21 +58,21 @@ impl VnodeCommon for DirInode { /// Performs filetype-specific request fn ioctl( &mut self, - node: VnodeRef, - cmd: IoctlCmd, - ptr: usize, - len: usize, + _node: VnodeRef, + _cmd: IoctlCmd, + _ptr: usize, + _len: usize, ) -> Result { todo!() } /// Reports the size of this filesystem object in bytes - fn size(&mut self, node: VnodeRef) -> Result { + fn size(&mut self, _node: VnodeRef) -> Result { todo!() } /// Returns `true` if node is ready for an operation - fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result { + fn ready(&mut self, _node: VnodeRef, _write: bool) -> Result { todo!() } diff --git a/fs/memfs/src/file.rs b/fs/memfs/src/file.rs index fc5e7d8..a78cf85 100644 --- a/fs/memfs/src/file.rs +++ b/fs/memfs/src/file.rs @@ -35,16 +35,16 @@ impl<'a, A: BlockAllocator + Copy + 'static> VnodeCommon for FileInode<'a, A> { /// Performs filetype-specific request fn ioctl( &mut self, - node: VnodeRef, - cmd: IoctlCmd, - ptr: usize, - len: usize, + _node: VnodeRef, + _cmd: IoctlCmd, + _ptr: usize, + _len: usize, ) -> Result { todo!() } /// Returns `true` if node is ready for an operation - fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result { + fn ready(&mut self, _node: VnodeRef, _write: bool) -> Result { todo!() } } diff --git a/fs/memfs/src/lib.rs b/fs/memfs/src/lib.rs index 6bca71f..91af6c6 100644 --- a/fs/memfs/src/lib.rs +++ b/fs/memfs/src/lib.rs @@ -6,9 +6,6 @@ extern crate alloc; #[macro_use] extern crate std; -#[macro_use] -extern crate fs_macros; - use alloc::{boxed::Box, rc::Rc}; use core::any::Any; use core::cell::{Ref, RefCell}; @@ -69,11 +66,10 @@ impl Ramfs { VnodeData::Directory(RefCell::new(Some(Box::new(DirInode::new(self.alloc))))) } VnodeCreateKind::File => VnodeData::File(RefCell::new(None)), - _ => todo!(), }; let node = Vnode::new(name, data, Vnode::SEEKABLE | Vnode::CACHE_READDIR); node.props_mut().mode = tar.mode(); - node.set_fs(self.clone()); + node.set_fs(self); node } diff --git a/fs/memfs/src/tar.rs b/fs/memfs/src/tar.rs index 92399d9..435aa58 100644 --- a/fs/memfs/src/tar.rs +++ b/fs/memfs/src/tar.rs @@ -1,5 +1,5 @@ use libsys::{error::Errno, stat::FileMode}; -use vfs::{VnodeData, VnodeCreateKind}; +use vfs::VnodeCreateKind; #[repr(packed)] #[allow(dead_code)] @@ -85,7 +85,6 @@ impl Tar { let t = match self.node_create_kind() { VnodeCreateKind::File => FileMode::S_IFREG, VnodeCreateKind::Directory => FileMode::S_IFDIR, - _ => todo!() }; FileMode::from_bits(from_octal(&self.mode) as u32).unwrap() | t } diff --git a/fs/vfs/src/ioctx.rs b/fs/vfs/src/ioctx.rs index 38d7cd4..905bae4 100644 --- a/fs/vfs/src/ioctx.rs +++ b/fs/vfs/src/ioctx.rs @@ -128,13 +128,10 @@ impl Ioctx { /// Changes current working directory of the process pub fn chdir(&mut self, path: &str) -> Result<(), Errno> { - todo!() - // let node = self.find(None, path, true)?; - // if !node.is_directory() { - // return Err(Errno::NotADirectory); - // } - // self.cwd = node; - // Ok(()) + let node = self.find(None, path, true)?; + let _dir = node.as_directory()?; + self.cwd = node; + Ok(()) } } diff --git a/fs/vfs/src/node.rs b/fs/vfs/src/node.rs index fcfced0..6dc96ec 100644 --- a/fs/vfs/src/node.rs +++ b/fs/vfs/src/node.rs @@ -13,6 +13,7 @@ use libsys::{ pub type VnodeRef = Rc; pub type VnodeKind = Discriminant; +/// Trait implemented by both regular files and directories pub trait VnodeCommon { /// Performs filetype-specific request fn ioctl( @@ -30,7 +31,7 @@ pub trait VnodeCommon { fn size(&mut self, node: VnodeRef) -> Result; /// Returns `true` if node is ready for an operation - fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result; + fn ready(&mut self, node: VnodeRef, write: bool) -> Result; /// Opens a vnode for access. Returns initial file position. fn open(&mut self, node: VnodeRef, opts: OpenFlags) -> Result; @@ -38,6 +39,7 @@ pub trait VnodeCommon { fn close(&mut self, node: VnodeRef) -> Result<(), Errno>; } +/// Regular file access interface pub trait VnodeFile: VnodeCommon { /// Changes file's underlying storage size fn truncate(&mut self, node: VnodeRef, size: usize) -> Result<(), Errno>; @@ -48,14 +50,18 @@ pub trait VnodeFile: VnodeCommon { fn write(&mut self, node: VnodeRef, pos: usize, data: &[u8]) -> Result; } +/// Directory access interface pub trait VnodeDirectory: VnodeCommon { + /// Creates entry `name` of type `kind` in directory `at` fn create( &mut self, at: VnodeRef, name: &str, kind: VnodeCreateKind, ) -> Result; + /// Removes entry `name` for directory `at` fn remove(&mut self, at: VnodeRef, name: &str) -> Result<(), Errno>; + /// Loads an entry `name` in directory `at` from filesystem fn lookup(&mut self, at: VnodeRef, name: &str) -> Result; /// Read directory entries into target buffer @@ -91,15 +97,22 @@ pub struct VnodeProps { pub mode: FileMode, } +/// Specific node implementation data pub enum VnodeData { + /// Directory node Directory(RefCell>>), + /// Regular file node File(RefCell>>), + /// Character device node Char(&'static dyn CharDevice) } +/// Node types for create() calls #[derive(Debug, Clone, Copy)] pub enum VnodeCreateKind { + /// Directory node Directory, + /// Regular file node File, } @@ -173,6 +186,7 @@ impl Vnode { *self.fs.borrow_mut() = Some(fs); } + /// Returns node's directory implementation data pub fn as_directory(&self) -> Result<&RefCell>>, Errno> { match &self.data { VnodeData::Directory(data) => Ok(data), @@ -180,6 +194,7 @@ impl Vnode { } } + /// Returns node's regular file implementation data pub fn as_file(&self) -> Result<&RefCell>>, Errno> { match &self.data { VnodeData::File(data) => Ok(data), diff --git a/kernel/src/arch/aarch64/boot/mod.rs b/kernel/src/arch/aarch64/boot/mod.rs index 754d132..b748641 100644 --- a/kernel/src/arch/aarch64/boot/mod.rs +++ b/kernel/src/arch/aarch64/boot/mod.rs @@ -83,7 +83,7 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! { // Enable MMU virt::enable().expect("Failed to initialize virtual memory"); - let fdt = init_device_tree(fdt_base).expect("Device tree init failed"); + let _fdt = init_device_tree(fdt_base).expect("Device tree init failed"); // Most basic machine init: initialize proper debug output // physical memory diff --git a/kernel/src/arch/aarch64/exception.rs b/kernel/src/arch/aarch64/exception.rs index 00d09fd..10a659b 100644 --- a/kernel/src/arch/aarch64/exception.rs +++ b/kernel/src/arch/aarch64/exception.rs @@ -4,7 +4,7 @@ use crate::arch::{machine, intrin}; use crate::debug::Level; use crate::dev::irq::{IntController, IrqContext}; use crate::mem; -use crate::proc::{sched, Process, Thread}; +use crate::proc::{sched, Thread}; use crate::syscall; use cortex_a::registers::{ESR_EL1, FAR_EL1}; use libsys::{abi::SystemCall, signal::Signal, error::Errno}; diff --git a/kernel/src/arch/aarch64/intrin.rs b/kernel/src/arch/aarch64/intrin.rs index b8f0c34..4ba7a58 100644 --- a/kernel/src/arch/aarch64/intrin.rs +++ b/kernel/src/arch/aarch64/intrin.rs @@ -1,14 +1,31 @@ +//! AArch64-specific assembly functions use core::arch::asm; +/// Disables delievery of IRQs +/// +/// # Safety +/// +/// Unsafe: requires EL0 #[inline(always)] pub unsafe fn irq_disable() { asm!("msr daifset, {bits}", bits = const 2, options(nomem, nostack, preserves_flags)); } +/// Discards an entry related to `addr` from TLB cache +/// +/// # Safety +/// +/// Unsafe: requires EL0 #[inline(always)] -pub unsafe fn flush_tlb_virt(addr: usize) { +pub unsafe fn flush_tlb_virt(_addr: usize) { + todo!() } +/// Discards all entries related to `asid` from TLB cache +/// +/// # Safety +/// +/// Only safe to use for known [Process]es and their ASIDs // TODO non-portable #[inline(always)] pub unsafe fn flush_tlb_asid(asid: usize) { diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 01ebded..e0ea0dc 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -1,6 +1,5 @@ //! aarch64 architecture implementation -use core::arch::asm; use cortex_a::registers::DAIF; use tock_registers::interfaces::{Readable, Writeable}; diff --git a/kernel/src/arch/aarch64/reg/mod.rs b/kernel/src/arch/aarch64/reg/mod.rs index 05c01b6..d01c4f1 100644 --- a/kernel/src/arch/aarch64/reg/mod.rs +++ b/kernel/src/arch/aarch64/reg/mod.rs @@ -8,13 +8,15 @@ use tock_registers::{ macro_rules! wrap_msr { ($struct_name:ident, $name:ident, $reg:literal, $fields:tt) => { + #[allow(missing_docs)] + pub struct $struct_name; + register_bitfields! { u64, + #[allow(missing_docs)] pub $name $fields } - pub struct $struct_name; - impl Readable for $struct_name { type T = u64; type R = $name::Register; @@ -41,11 +43,11 @@ macro_rules! wrap_msr { } } + #[allow(missing_docs)] pub const $name: $struct_name = $struct_name; }; } -/// EL1 Architectural Feature Access Control Register wrap_msr!(CpacrEl1, CPACR_EL1, "cpacr_el1", [ /// Enable EL0 and EL1 SIMD/FP accesses to EL1 FPEN OFFSET(20) NUMBITS(2) [ diff --git a/kernel/src/debug.rs b/kernel/src/debug.rs index 8f5a205..61548bc 100644 --- a/kernel/src/debug.rs +++ b/kernel/src/debug.rs @@ -16,6 +16,7 @@ use libsys::{debug::TraceLevel, error::Errno}; use core::convert::TryFrom; use core::fmt; +/// Currently active print level pub static LEVEL: Level = Level::Debug; /// Kernel logging levels diff --git a/kernel/src/dev/pseudo.rs b/kernel/src/dev/pseudo.rs index 2115cb8..3ad5ffd 100644 --- a/kernel/src/dev/pseudo.rs +++ b/kernel/src/dev/pseudo.rs @@ -1,25 +1,14 @@ -use crate::arch::machine::{self, IrqNumber}; -use crate::dev::{ - irq::{IntController, IntSource}, - serial::SerialDevice, - tty::{CharRing, TtyDevice}, - Device, -}; -use crate::mem::virt::DeviceMemoryIo; -use crate::sync::IrqSafeSpinLock; -use crate::util::InitOnce; -use libsys::{error::Errno, ioctl::IoctlCmd}; +//! Virtual (pseudo) device implemetation +use crate::dev::Device; use core::sync::atomic::{AtomicU32, Ordering}; -use tock_registers::{ - interfaces::{ReadWriteable, Readable, Writeable}, - register_bitfields, register_structs, - registers::{ReadOnly, ReadWrite, WriteOnly}, -}; +use libsys::{error::Errno, ioctl::IoctlCmd}; use vfs::CharDevice; +/// Pseudorandom number generator device pub struct Random { - state: AtomicU32 + state: AtomicU32, } +/// Zero device pub struct Zero; impl Device for Random { @@ -53,7 +42,6 @@ impl CharDevice for Random { } } - impl Device for Zero { fn name(&self) -> &'static str { "Zero device" @@ -84,10 +72,12 @@ impl CharDevice for Zero { } impl Random { + /// Initializes PRNG with a seed value pub fn set_state(&self, state: u32) { self.state.store(state, Ordering::Release); } + /// Returns a single pseudo-random value pub fn read_single(&self) -> u32 { let mut x = self.state.load(Ordering::Acquire); x ^= x << 13; @@ -98,5 +88,9 @@ impl Random { } } -pub static RANDOM: Random = Random { state: AtomicU32::new(0) }; +/// Pseudorandom number generator device +pub static RANDOM: Random = Random { + state: AtomicU32::new(0), +}; +/// Zero device pub static ZERO: Zero = Zero; diff --git a/kernel/src/fs/devfs.rs b/kernel/src/fs/devfs.rs index 1198a7c..c2cdb17 100644 --- a/kernel/src/fs/devfs.rs +++ b/kernel/src/fs/devfs.rs @@ -1,10 +1,10 @@ //! Device list pseudo-filesystem use crate::util::InitOnce; -use alloc::boxed::Box; -use core::sync::atomic::{AtomicUsize, Ordering}; -use libsys::{stat::FileMode, error::Errno}; -use vfs::{CharDevice, Vnode, VnodeData, VnodeRef}; use core::cell::RefCell; +use vfs::CharDevice; +use core::sync::atomic::{AtomicUsize, Ordering}; +use libsys::{error::Errno, stat::FileMode}; +use vfs::{Vnode, VnodeData, VnodeRef}; /// Possible character device kinds #[derive(Debug)] @@ -17,7 +17,11 @@ static DEVFS_ROOT: InitOnce = InitOnce::new(); /// Initializes devfs pub fn init() { - let node = Vnode::new("", VnodeData::Directory(RefCell::new(None)), Vnode::CACHE_READDIR | Vnode::CACHE_STAT); + let node = Vnode::new( + "", + VnodeData::Directory(RefCell::new(None)), + Vnode::CACHE_READDIR | Vnode::CACHE_STAT, + ); // let node = Vnode::new("", VnodeKind::Directory, Vnode::CACHE_READDIR | Vnode::CACHE_STAT); node.props_mut().mode = FileMode::default_dir(); DEVFS_ROOT.init(node); @@ -28,13 +32,14 @@ pub fn root() -> &'static VnodeRef { DEVFS_ROOT.get() } +/// Adds device `dev` to devfs with `name` pub fn add_named_char_device(dev: &'static dyn CharDevice, name: &str) -> Result<(), Errno> { infoln!("Add char device: {}", name); let node = Vnode::new(name, VnodeData::Char(dev), Vnode::CACHE_STAT); // let node = Vnode::new(name, VnodeKind::Char, Vnode::CACHE_STAT); // node.set_data(Box::new(CharDeviceWrapper::new(dev))); - node.props_mut().mode = FileMode::from_bits(0o600).unwrap() | FileMode::S_IFCHR; + node.props_mut().mode = FileMode::from_bits(0o600).unwrap() | FileMode::S_IFCHR; DEVFS_ROOT.get().attach(node); diff --git a/kernel/src/fs/sysfs.rs b/kernel/src/fs/sysfs.rs index 10c286f..c5072de 100644 --- a/kernel/src/fs/sysfs.rs +++ b/kernel/src/fs/sysfs.rs @@ -1,17 +1,16 @@ +//! System control/info virtual filesystem use crate::debug::{self, Level}; use crate::util::InitOnce; use alloc::boxed::Box; use core::cell::RefCell; use core::fmt::{self, Write}; use core::str::FromStr; -use core::sync::atomic::{AtomicUsize, Ordering}; -use fs_macros::auto_inode; use libsys::{ error::Errno, - stat::{FileMode, OpenFlags, Stat}, ioctl::IoctlCmd, + stat::{FileMode, OpenFlags, Stat}, }; -use vfs::{CharDevice, Vnode, VnodeCommon, VnodeData, VnodeFile, VnodeRef}; +use vfs::{Vnode, VnodeCommon, VnodeData, VnodeFile, VnodeRef}; struct NodeData Result, W: Fn(&[u8]) -> Result> { read_func: R, @@ -59,32 +58,33 @@ impl Result, W: Fn(&[u8]) -> Result Result { todo!() } /// Retrieves file status - fn stat(&mut self, node: VnodeRef) -> Result { + fn stat(&mut self, _node: VnodeRef) -> Result { todo!() } /// Reports the size of this filesystem object in bytes - fn size(&mut self, node: VnodeRef) -> Result { + fn size(&mut self, _node: VnodeRef) -> Result { todo!() } /// Returns `true` if node is ready for an operation - fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result { + fn ready(&mut self, _node: VnodeRef, _write: bool) -> Result { todo!() } } impl Result, W: Fn(&[u8]) -> Result> VnodeFile - for NodeData { + for NodeData +{ fn read(&mut self, _node: VnodeRef, pos: usize, data: &mut [u8]) -> Result { if pos != 0 { // TODO handle this @@ -101,10 +101,10 @@ impl Result, W: Fn(&[u8]) -> Result Result<(), Errno> { + fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> { todo!() } - } +} impl Result, W: Fn(&[u8]) -> Result> NodeData { @@ -117,7 +117,6 @@ impl Result, W: Fn(&[u8]) -> Result = InitOnce::new(); -static TEST_COUNTER: AtomicUsize = AtomicUsize::new(0); // TODO subdirs fn add_generic_node(parent: Option, name: &str, mode: FileMode, read: R, write: W) @@ -139,6 +138,7 @@ where } } +/// Adds a node with and `read` and `write` operations pub fn add_read_write_node(parent: Option, name: &str, read: R, write: W) where R: Fn(&mut [u8]) -> Result + 'static, @@ -153,6 +153,7 @@ where ) } +/// Adds `read`-only node pub fn add_read_node(parent: Option, name: &str, read: R) where R: Fn(&mut [u8]) -> Result + 'static, @@ -166,8 +167,13 @@ where ) } +/// Creates a directory in sysfs structure pub fn add_directory(parent: Option, name: &str) -> Result { - let node = Vnode::new(name, VnodeData::Directory(RefCell::new(None)), Vnode::CACHE_READDIR | Vnode::CACHE_STAT); + let node = Vnode::new( + name, + VnodeData::Directory(RefCell::new(None)), + Vnode::CACHE_READDIR | Vnode::CACHE_STAT, + ); node.props_mut().mode = FileMode::from_bits(0o500).unwrap() | FileMode::S_IFDIR; if let Some(parent) = parent { @@ -179,26 +185,39 @@ pub fn add_directory(parent: Option, name: &str) -> Result &'static VnodeRef { SYSFS_ROOT.get() } +/// Sets up the sysfs tree pub fn init() { - let node = Vnode::new("", VnodeData::Directory(RefCell::new(None)), Vnode::CACHE_READDIR | Vnode::CACHE_STAT); + let node = Vnode::new( + "", + VnodeData::Directory(RefCell::new(None)), + Vnode::CACHE_READDIR | Vnode::CACHE_STAT, + ); node.props_mut().mode = FileMode::default_dir(); SYSFS_ROOT.init(node); let debug_dir = add_directory(None, "debug").unwrap(); - add_read_write_node(Some(debug_dir.clone()), "level", |buf| { - let mut writer = BufferWriter::new(buf); - write!(&mut writer, "{}\n", debug::LEVEL as u32).map_err(|_| Errno::InvalidArgument)?; - Ok(writer.count()) - }, |buf| { - let s = core::str::from_utf8(buf).map_err(|_| Errno::InvalidArgument)?; - let value = u32::from_str(s).map_err(|_| Errno::InvalidArgument).and_then(Level::try_from)?; - todo!() - }); + add_read_write_node( + Some(debug_dir), + "level", + |buf| { + let mut writer = BufferWriter::new(buf); + writeln!(&mut writer, "{}", debug::LEVEL as u32).map_err(|_| Errno::InvalidArgument)?; + Ok(writer.count()) + }, + |buf| { + let s = core::str::from_utf8(buf).map_err(|_| Errno::InvalidArgument)?; + let _value = u32::from_str(s) + .map_err(|_| Errno::InvalidArgument) + .and_then(Level::try_from)?; + todo!() + }, + ); add_read_node(None, "uptime", |buf| { use crate::arch::machine; @@ -206,7 +225,8 @@ pub fn init() { let mut writer = BufferWriter::new(buf); let time = machine::local_timer().timestamp()?; - write!(&mut writer, "{} {}\n", time.as_secs(), time.subsec_nanos()).map_err(|_| Errno::InvalidArgument)?; + writeln!(&mut writer, "{} {}", time.as_secs(), time.subsec_nanos()) + .map_err(|_| Errno::InvalidArgument)?; Ok(writer.count()) }); } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 2426870..9b17fd3 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -37,8 +37,6 @@ pub mod sync; pub mod syscall; pub mod util; -use core::arch::asm; - #[panic_handler] fn panic_handler(pi: &core::panic::PanicInfo) -> ! { unsafe { diff --git a/kernel/src/mem/mod.rs b/kernel/src/mem/mod.rs index 34df055..0df95a2 100644 --- a/kernel/src/mem/mod.rs +++ b/kernel/src/mem/mod.rs @@ -28,6 +28,7 @@ pub fn kernel_end_phys() -> usize { } // TODO cross-platform variant +/// Returns `true` if `virt` address is accessible for requested operation #[inline(always)] pub fn is_el0_accessible(virt: usize, write: bool) -> bool { use core::arch::asm; diff --git a/kernel/src/mem/phys/manager.rs b/kernel/src/mem/phys/manager.rs index de4ba15..9a5e49a 100644 --- a/kernel/src/mem/phys/manager.rs +++ b/kernel/src/mem/phys/manager.rs @@ -4,6 +4,9 @@ use crate::sync::IrqSafeSpinLock; use core::mem; use libsys::{error::Errno, mem::memcpy}; +/// # Safety +/// +/// Unsafe to implement because of direct memory manipulation pub unsafe trait Manager { fn alloc_page(&mut self, pu: PageUsage) -> Result; fn alloc_contiguous_pages(&mut self, pu: PageUsage, count: usize) -> Result; diff --git a/kernel/src/proc/io.rs b/kernel/src/proc/io.rs index 275a130..3ee1ee1 100644 --- a/kernel/src/proc/io.rs +++ b/kernel/src/proc/io.rs @@ -1,7 +1,10 @@ //! Process file descriptors and I/O context use alloc::collections::BTreeMap; -use libsys::{error::Errno, stat::{FileDescriptor, UserId, GroupId}}; -use vfs::{FileRef, Ioctx, VnodeRef, VnodeData}; +use libsys::{ + error::Errno, + stat::{FileDescriptor, GroupId, UserId}, +}; +use vfs::{FileRef, Ioctx, VnodeRef}; /// Process I/O context. Contains file tables, root/cwd info etc. pub struct ProcessIo { @@ -74,7 +77,11 @@ impl ProcessIo { } /// Clones a file descriptor into an available slot or, if specified, requested one - pub fn duplicate_file(&mut self, src: FileDescriptor, dst: Option) -> Result { + pub fn duplicate_file( + &mut self, + src: FileDescriptor, + dst: Option, + ) -> Result { let file_ref = self.file(src)?; if let Some(dst) = dst { let idx = u32::from(dst); @@ -91,7 +98,10 @@ impl ProcessIo { /// Returns [File] struct referred to by file descriptor `idx` pub fn file(&mut self, fd: FileDescriptor) -> Result { - self.files.get(&u32::from(fd)).cloned().ok_or(Errno::InvalidFile) + self.files + .get(&u32::from(fd)) + .cloned() + .ok_or(Errno::InvalidFile) } /// Returns [Ioctx] structure reference of this I/O context diff --git a/kernel/src/proc/process.rs b/kernel/src/proc/process.rs index 27092f6..3190632 100644 --- a/kernel/src/proc/process.rs +++ b/kernel/src/proc/process.rs @@ -10,7 +10,6 @@ use crate::proc::{ }; use crate::sync::IrqSafeSpinLock; use alloc::{rc::Rc, vec::Vec}; -use core::arch::asm; use core::sync::atomic::{AtomicU32, Ordering}; use libsys::{ error::Errno, @@ -463,10 +462,12 @@ impl Process { Ok(base + offset) } + /// Returns the process's address space ID pub fn asid(&self) -> usize { (self.id().asid() as usize) << 48 } + /// Flushes TLB cache for the process address space pub fn invalidate_tlb(&self) { unsafe { intrin::flush_tlb_asid(self.asid()); diff --git a/kernel/src/syscall/arg.rs b/kernel/src/syscall/arg.rs index bdda7c0..30e0cb6 100644 --- a/kernel/src/syscall/arg.rs +++ b/kernel/src/syscall/arg.rs @@ -5,7 +5,6 @@ use crate::arch::intrin; use core::alloc::Layout; use libsys::error::Errno; use crate::proc::Process; -use core::arch::asm; // TODO _mut() versions checking whether pages are actually writable diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index efd9113..1590725 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -251,7 +251,8 @@ fn _syscall(num: SystemCall, args: &[usize]) -> Result { let at_fd = FileDescriptor::from_i32(args[0] as i32)?; let path = arg::str_ref(args[1], args[2])?; let mode = FileMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?; - let flags = args[4] as u32; + // TODO honor this option + let _flags = args[4] as u32; let proc = Process::current(); let mut io = proc.io.lock(); diff --git a/libusr/src/allocator.rs b/libusr/src/allocator.rs index 1f4f455..91a433b 100644 --- a/libusr/src/allocator.rs +++ b/libusr/src/allocator.rs @@ -198,9 +198,9 @@ unsafe impl GlobalAlloc for Allocator { } } - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { #[cfg(feature = "verbose")] - trace_debug!("free({:p}, {:?})", ptr, layout); + trace_debug!("free({:p}, {:?})", ptr, _layout); assert!(!ptr.is_null()); let mut block = ptr.sub(size_of::()) as *mut Block; let mut block_ref = &mut *block; diff --git a/libusr/src/env/mod.rs b/libusr/src/env/mod.rs index 625f1cc..97a7f0c 100644 --- a/libusr/src/env/mod.rs +++ b/libusr/src/env/mod.rs @@ -1,7 +1,9 @@ +#[cfg(feature = "verbose")] use crate::trace; use alloc::vec::Vec; +#[cfg(feature = "verbose")] +use libsys::debug::TraceLevel; use libsys::{ - debug::TraceLevel, ProgramArgs, }; diff --git a/libusr/src/env/passwd.rs b/libusr/src/env/passwd.rs index 92f50c3..7b50a15 100644 --- a/libusr/src/env/passwd.rs +++ b/libusr/src/env/passwd.rs @@ -1,9 +1,11 @@ -use crate::io::{Read, read_line}; -use core::str::FromStr; -use core::fmt; -use crate::trace_debug; use crate::file::File; -use libsys::{FixedStr, stat::{UserId, GroupId}}; +use crate::io::{self, read_line}; +use core::str::FromStr; +use libsys::{ + stat::{GroupId, UserId}, + error::Errno, + FixedStr, +}; #[derive(Debug, Clone, Copy)] pub struct UserInfo { @@ -35,11 +37,11 @@ impl UserInfo { self.gid } - pub fn find bool>(pred: F) -> Result { - let mut file = File::open("/etc/passwd").map_err(|_| ())?; + pub fn find bool>(pred: F) -> Result { + let mut file = File::open("/etc/passwd")?; let mut buf = [0; 128]; loop { - let line = read_line(&mut file, &mut buf).map_err(|_| ())?; + let line = read_line(&mut file, &mut buf)?; if let Some(line) = line { let ent = UserInfo::from_str(line)?; if pred(&ent) { @@ -49,37 +51,37 @@ impl UserInfo { break; } } - Err(()) + Err(io::Error::from(Errno::InvalidArgument)) } - pub fn by_name(name: &str) -> Result { + pub fn by_name(name: &str) -> Result { Self::find(|ent| ent.name() == name) } } impl FromStr for UserInfo { - type Err = (); + type Err = io::Error; - fn from_str(s: &str) -> Result { - let mut iter = s.split(":"); + fn from_str(s: &str) -> Result { + let mut iter = s.split(':'); - let name = iter.next().ok_or(())?; + let name = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?; let uid = iter .next() - .ok_or(()) - .and_then(|e| u32::from_str(e).map_err(|_| ())) + .ok_or_else(|| io::Error::from(Errno::InvalidArgument)) + .and_then(|e| u32::from_str(e).map_err(|_| io::Error::from(Errno::InvalidArgument))) .map(UserId::from)?; let gid = iter .next() - .ok_or(()) - .and_then(|e| u32::from_str(e).map_err(|_| ())) + .ok_or_else(|| io::Error::from(Errno::InvalidArgument)) + .and_then(|e| u32::from_str(e).map_err(|_| io::Error::from(Errno::InvalidArgument))) .map(GroupId::from)?; - let comment = iter.next().ok_or(())?; - let home = iter.next().ok_or(())?; - let shell = iter.next().ok_or(())?; + let _comment = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?; + let home = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?; + let shell = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?; if iter.next().is_some() { - return Err(()); + return Err(io::Error::from(Errno::InvalidArgument)); } let mut res = Self { @@ -90,9 +92,9 @@ impl FromStr for UserInfo { shell: FixedStr::empty(), }; - res.name.copy_from_str(&name); - res.home.copy_from_str(&home); - res.shell.copy_from_str(&shell); + res.name.copy_from_str(name); + res.home.copy_from_str(home); + res.shell.copy_from_str(shell); Ok(res) } diff --git a/libusr/src/env/shadow.rs b/libusr/src/env/shadow.rs index 4691090..4b44751 100644 --- a/libusr/src/env/shadow.rs +++ b/libusr/src/env/shadow.rs @@ -1,7 +1,7 @@ use crate::file::File; -use crate::io::{Read, read_line}; +use crate::io::{self, read_line}; use core::str::FromStr; -use libsys::FixedStr; +use libsys::{FixedStr, error::Errno}; #[derive(Debug, Clone, Copy)] pub struct UserShadow { @@ -18,12 +18,11 @@ impl UserShadow { self.password.as_str() } - - pub fn find bool>(pred: F) -> Result { - let mut file = File::open("/etc/shadow").map_err(|_| ())?; + pub fn find bool>(pred: F) -> Result { + let mut file = File::open("/etc/shadow")?; let mut buf = [0; 128]; loop { - let line = read_line(&mut file, &mut buf).map_err(|_| ())?; + let line = read_line(&mut file, &mut buf)?; if let Some(line) = line { let ent = UserShadow::from_str(line)?; if pred(&ent) { @@ -33,25 +32,25 @@ impl UserShadow { break; } } - Err(()) + Err(io::Error::from(Errno::DoesNotExist)) } - pub fn by_name(name: &str) -> Result { + pub fn by_name(name: &str) -> Result { Self::find(|ent| ent.name() == name) } } impl FromStr for UserShadow { - type Err = (); + type Err = io::Error; - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { let mut iter = s.split(':'); - let name = iter.next().ok_or(())?; - let password = iter.next().ok_or(())?; + let name = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?; + let password = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?; if iter.next().is_some() { - return Err(()); + return Err(io::Error::from(Errno::InvalidArgument)); } let mut res = Self { diff --git a/libusr/src/io/mod.rs b/libusr/src/io/mod.rs index 907f2ef..ea07315 100644 --- a/libusr/src/io/mod.rs +++ b/libusr/src/io/mod.rs @@ -44,14 +44,14 @@ pub fn stat(pathname: &str) -> Result { } // TODO use BufRead instead once it's implemented -pub(crate) fn read_line<'a, F: Read>(f: &mut F, buf: &'a mut [u8]) -> Result, ()> { +pub(crate) fn read_line<'a, F: Read>(f: &mut F, buf: &'a mut [u8]) -> Result, Error> { let mut pos = 0; loop { if pos == buf.len() { - return Err(()); + return Err(Error::from(Errno::OutOfMemory)); } - let count = f.read(&mut buf[pos..=pos]).map_err(|_| ())?; + let count = f.read(&mut buf[pos..=pos])?; if count == 0 { if pos == 0 { return Ok(None); @@ -64,5 +64,5 @@ pub(crate) fn read_line<'a, F: Read>(f: &mut F, buf: &'a mut [u8]) -> Result i32 { } } - login_as(username); + login_as(username).ok(); } }