feature: simple sysfs
This commit is contained in:
parent
b4b99915ef
commit
fcbe412732
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -93,6 +93,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"cortex-a",
|
||||
"fdt-rs",
|
||||
"fs-macros",
|
||||
"kernel-macros",
|
||||
"libsys",
|
||||
"memfs",
|
||||
|
5
Makefile
5
Makefile
@ -92,10 +92,11 @@ initrd:
|
||||
--target=../etc/$(ARCH)-osdev5.json \
|
||||
-Z build-std=core,alloc,compiler_builtins \
|
||||
$(CARGO_COMMON_OPTS)
|
||||
mkdir -p $(O)/rootfs/bin $(O)/rootfs/sbin $(O)/rootfs/dev $(O)/rootfs/etc
|
||||
mkdir -p $(O)/rootfs/bin $(O)/rootfs/sbin $(O)/rootfs/dev $(O)/rootfs/etc $(O)/rootfs/sys
|
||||
cp etc/initrd/passwd $(O)/rootfs/etc
|
||||
cp etc/initrd/shadow $(O)/rootfs/etc
|
||||
touch $(O)/rootfs/dev/.do_no_remove
|
||||
touch $(O)/rootfs/dev/.do_not_remove
|
||||
touch $(O)/rootfs/sys/.do_not_remove
|
||||
cp target/$(ARCH)-osdev5/$(PROFILE)/init $(O)/rootfs/init
|
||||
cp target/$(ARCH)-osdev5/$(PROFILE)/shell $(O)/rootfs/bin
|
||||
cp target/$(ARCH)-osdev5/$(PROFILE)/fuzzy $(O)/rootfs/bin
|
||||
|
@ -18,6 +18,7 @@ tock-registers = "0.7.x"
|
||||
fdt-rs = { version = "0.x.x", default-features = false }
|
||||
bitflags = "^1.3.0"
|
||||
kernel-macros = { path = "macros" }
|
||||
fs-macros = { path = "../fs/macros" }
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||
cortex-a = { version = "6.x.x" }
|
||||
|
@ -10,7 +10,7 @@ use crate::dev::{
|
||||
irq::IntSource,
|
||||
Device,
|
||||
};
|
||||
use crate::fs::devfs;
|
||||
use crate::fs::{devfs, sysfs};
|
||||
use crate::dev::pseudo;
|
||||
use libsys::error::Errno;
|
||||
//use crate::debug::Level;
|
||||
@ -97,6 +97,7 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! {
|
||||
}
|
||||
|
||||
devfs::init();
|
||||
sysfs::init();
|
||||
|
||||
machine::init_board().unwrap();
|
||||
|
||||
|
@ -12,20 +12,39 @@
|
||||
//! * [errorln!]
|
||||
|
||||
use crate::dev::serial::SerialDevice;
|
||||
use libsys::debug::TraceLevel;
|
||||
use libsys::{debug::TraceLevel, error::Errno};
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
|
||||
pub static LEVEL: Level = Level::Debug;
|
||||
|
||||
/// Kernel logging levels
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum Level {
|
||||
/// Debugging information
|
||||
Debug,
|
||||
Debug = 1,
|
||||
/// General informational messages
|
||||
Info,
|
||||
Info = 2,
|
||||
/// Non-critical warnings
|
||||
Warn,
|
||||
Warn = 3,
|
||||
/// Critical errors
|
||||
Error,
|
||||
Error = 4,
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for Level {
|
||||
type Error = Errno;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_from(l: u32) -> Result<Level, Errno> {
|
||||
match l {
|
||||
1 => Ok(Level::Debug),
|
||||
2 => Ok(Level::Info),
|
||||
3 => Ok(Level::Warn),
|
||||
4 => Ok(Level::Error),
|
||||
_ => Err(Errno::InvalidArgument)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TraceLevel> for Level {
|
||||
@ -114,13 +133,15 @@ macro_rules! errorln {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn _debug(_level: Level, args: fmt::Arguments) {
|
||||
pub fn _debug(level: Level, args: fmt::Arguments) {
|
||||
use crate::arch::machine;
|
||||
use fmt::Write;
|
||||
|
||||
SerialOutput {
|
||||
inner: machine::console(),
|
||||
if level >= LEVEL {
|
||||
SerialOutput {
|
||||
inner: machine::console(),
|
||||
}
|
||||
.write_fmt(args)
|
||||
.ok();
|
||||
}
|
||||
.write_fmt(args)
|
||||
.ok();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use vfs::VnodeRef;
|
||||
use memfs::BlockAllocator;
|
||||
|
||||
pub mod devfs;
|
||||
pub mod sysfs;
|
||||
|
||||
/// Allocator implementation for memfs
|
||||
#[derive(Clone, Copy)]
|
||||
@ -32,9 +33,9 @@ unsafe impl BlockAllocator for MemfsBlockAlloc {
|
||||
pub fn create_filesystem(options: &MountOptions) -> Result<VnodeRef, Errno> {
|
||||
let fs_name = options.fs.unwrap();
|
||||
|
||||
if fs_name == "devfs" {
|
||||
Ok(devfs::root().clone())
|
||||
} else {
|
||||
todo!();
|
||||
match fs_name {
|
||||
"devfs" => Ok(devfs::root().clone()),
|
||||
"sysfs" => Ok(sysfs::root().clone()),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
|
169
kernel/src/fs/sysfs.rs
Normal file
169
kernel/src/fs/sysfs.rs
Normal file
@ -0,0 +1,169 @@
|
||||
use crate::util::InitOnce;
|
||||
use alloc::boxed::Box;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use fs_macros::auto_inode;
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
stat::{FileMode, OpenFlags, Stat},
|
||||
};
|
||||
use vfs::{CharDevice, CharDeviceWrapper, Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
||||
use core::fmt::{self, Write};
|
||||
use core::str::FromStr;
|
||||
use crate::debug::{self, Level};
|
||||
|
||||
struct NodeData<
|
||||
R: Fn(&mut [u8]) -> Result<usize, Errno>,
|
||||
W: Fn(&[u8]) -> Result<usize, Errno>,
|
||||
> {
|
||||
read_func: R,
|
||||
write_func: W,
|
||||
}
|
||||
|
||||
struct BufferWriter<'a> {
|
||||
dst: &'a mut [u8],
|
||||
pos: usize
|
||||
}
|
||||
|
||||
impl<'a> fmt::Write for BufferWriter<'a> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for byte in s.bytes() {
|
||||
if self.pos == self.dst.len() {
|
||||
todo!();
|
||||
}
|
||||
self.dst[self.pos] = byte;
|
||||
self.pos += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BufferWriter<'a> {
|
||||
pub const fn new(dst: &'a mut [u8]) -> Self {
|
||||
Self { dst, pos: 0 }
|
||||
}
|
||||
|
||||
pub const fn count(&self) -> usize {
|
||||
self.pos
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_inode]
|
||||
impl<
|
||||
R: Fn(&mut [u8]) -> Result<usize, Errno>,
|
||||
W: Fn(&[u8]) -> Result<usize, Errno>,
|
||||
> VnodeImpl for NodeData<R, W>
|
||||
{
|
||||
fn open(&mut self, _node: VnodeRef, _mode: OpenFlags) -> Result<usize, Errno> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), Errno> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read(&mut self, _node: VnodeRef, pos: usize, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
if pos != 0 {
|
||||
// TODO handle this
|
||||
Ok(0)
|
||||
} else {
|
||||
(self.read_func)(data)
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, _node: VnodeRef, pos: usize, data: &[u8]) -> Result<usize, Errno> {
|
||||
if pos != 0 {
|
||||
todo!();
|
||||
}
|
||||
(self.write_func)(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
R: Fn(&mut [u8]) -> Result<usize, Errno>,
|
||||
W: Fn(&[u8]) -> Result<usize, Errno>,
|
||||
> NodeData<R, W>
|
||||
{
|
||||
pub const fn new(read_func: R, write_func: W) -> Self {
|
||||
Self {
|
||||
read_func,
|
||||
write_func,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SYSFS_ROOT: InitOnce<VnodeRef> = InitOnce::new();
|
||||
static TEST_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
// TODO subdirs
|
||||
fn add_generic_node<R, W>(parent: Option<VnodeRef>, name: &str, mode: FileMode, read: R, write: W)
|
||||
where
|
||||
R: Fn(&mut [u8]) -> Result<usize, Errno> + 'static,
|
||||
W: Fn(&[u8]) -> Result<usize, Errno> + 'static,
|
||||
{
|
||||
let node = Vnode::new(name, VnodeKind::Regular, Vnode::CACHE_STAT);
|
||||
node.props_mut().mode = mode | FileMode::S_IFREG;
|
||||
node.set_data(Box::new(NodeData::new(read, write)));
|
||||
|
||||
if let Some(parent) = parent {
|
||||
parent.attach(node);
|
||||
} else {
|
||||
SYSFS_ROOT.get().attach(node);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_read_write_node<R, W>(parent: Option<VnodeRef>, name: &str, read: R, write: W)
|
||||
where
|
||||
R: Fn(&mut [u8]) -> Result<usize, Errno> + 'static,
|
||||
W: Fn(&[u8]) -> Result<usize, Errno> + 'static,
|
||||
{
|
||||
add_generic_node(parent, name, FileMode::from_bits(0o600).unwrap(), read, write)
|
||||
}
|
||||
|
||||
pub fn add_read_node<R>(parent: Option<VnodeRef>, name: &str, read: R) where R: Fn(&mut [u8]) -> Result<usize, Errno> + 'static {
|
||||
add_generic_node(parent, name, FileMode::from_bits(0o400).unwrap(), read, |_| Err(Errno::ReadOnly))
|
||||
}
|
||||
|
||||
pub fn add_directory(parent: Option<VnodeRef>, name: &str) -> Result<VnodeRef, Errno> {
|
||||
let node = Vnode::new(name, VnodeKind::Directory, Vnode::CACHE_READDIR | Vnode::CACHE_STAT);
|
||||
node.props_mut().mode = FileMode::from_bits(0o500).unwrap() | FileMode::S_IFDIR;
|
||||
|
||||
if let Some(parent) = parent {
|
||||
parent.attach(node.clone());
|
||||
} else {
|
||||
SYSFS_ROOT.get().attach(node.clone());
|
||||
}
|
||||
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
pub fn root() -> &'static VnodeRef {
|
||||
SYSFS_ROOT.get()
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
let node = Vnode::new("", VnodeKind::Directory, 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_node(None, "uptime", |buf| {
|
||||
use crate::arch::machine;
|
||||
use crate::dev::timer::TimestampSource;
|
||||
|
||||
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)?;
|
||||
Ok(writer.count())
|
||||
});
|
||||
}
|
@ -12,7 +12,8 @@
|
||||
panic_info_message,
|
||||
alloc_error_handler,
|
||||
linked_list_cursors,
|
||||
const_btree_new
|
||||
const_btree_new,
|
||||
const_generics_defaults,
|
||||
)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -17,6 +17,14 @@ fn main() -> i32 {
|
||||
},
|
||||
)
|
||||
.expect("Failed to mount devfs");
|
||||
sys_mount(
|
||||
"/sys",
|
||||
&MountOptions {
|
||||
device: None,
|
||||
fs: Some("sysfs"),
|
||||
},
|
||||
)
|
||||
.expect("Failed to mount sysfs");
|
||||
|
||||
if let Some(pid) = unsafe { sys_fork().unwrap() } {
|
||||
let mut status = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user