Merge branch 'master' into feat/signal
This commit is contained in:
commit
c584e1182f
60
Cargo.lock
generated
60
Cargo.lock
generated
@ -35,10 +35,6 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6419a5c75e40011b9fe0174db3fe24006ab122fbe1b7e9cc5974b338a755c76"
|
||||
|
||||
[[package]]
|
||||
name = "error"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
@ -49,8 +45,8 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
name = "fat32"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error",
|
||||
"libcommon",
|
||||
"fs-macros",
|
||||
"libsys",
|
||||
"vfs",
|
||||
]
|
||||
|
||||
@ -70,6 +66,14 @@ dependencies = [
|
||||
"unsafe_unwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel"
|
||||
version = "0.1.0"
|
||||
@ -77,35 +81,42 @@ dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cortex-a",
|
||||
"error",
|
||||
"fdt-rs",
|
||||
"libcommon",
|
||||
"kernel-macros",
|
||||
"libsys",
|
||||
"memfs",
|
||||
"syscall",
|
||||
"tock-registers",
|
||||
"vfs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libcommon"
|
||||
name = "kernel-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsys"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libusr"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"syscall",
|
||||
"libsys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memfs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error",
|
||||
"libcommon",
|
||||
"fs-macros",
|
||||
"libsys",
|
||||
"vfs",
|
||||
]
|
||||
|
||||
@ -144,9 +155,9 @@ version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.29"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
|
||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
@ -192,23 +203,15 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.80"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
||||
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syscall"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tock-registers"
|
||||
version = "0.7.0"
|
||||
@ -238,7 +241,6 @@ dependencies = [
|
||||
name = "vfs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error",
|
||||
"libcommon",
|
||||
"syscall",
|
||||
"fs-macros",
|
||||
"libsys",
|
||||
]
|
||||
|
10
Cargo.toml
10
Cargo.toml
@ -9,13 +9,13 @@ edition = "2018"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"fs/vfs",
|
||||
"fs/memfs",
|
||||
"fs/fat32",
|
||||
"syscall",
|
||||
"libcommon",
|
||||
"fs/macros",
|
||||
"fs/memfs",
|
||||
"fs/vfs",
|
||||
"kernel",
|
||||
"kernel/macros",
|
||||
"libsys",
|
||||
"libusr",
|
||||
"user",
|
||||
"error"
|
||||
]
|
||||
|
2
Makefile
2
Makefile
@ -124,7 +124,7 @@ doc-open:
|
||||
|
||||
clippy:
|
||||
cd kernel && cargo clippy $(CARGO_BUILD_OPTS)
|
||||
cd init && cargo clippy \
|
||||
cd user && cargo clippy \
|
||||
--target=../etc/$(ARCH)-osdev5.json \
|
||||
-Zbuild-std=core,alloc,compiler_builtins $(CARGO_COMMON_OPTS)
|
||||
|
||||
|
@ -7,5 +7,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
vfs = { path = "../vfs" }
|
||||
libcommon = { path = "../../libcommon" }
|
||||
error = { path = "../../error" }
|
||||
fs-macros = { path = "../macros" }
|
||||
libsys = { path = "../../libsys" }
|
||||
|
@ -1,4 +1,4 @@
|
||||
use libcommon::{read_le16, read_le32};
|
||||
use libsys::mem::{read_le16, read_le32};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bpb {
|
||||
|
@ -1,7 +1,11 @@
|
||||
use crate::{Bpb, FileInode};
|
||||
use alloc::{borrow::ToOwned, boxed::Box, string::String};
|
||||
use error::Errno;
|
||||
use libcommon::{read_le16, read_le32};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
ioctl::IoctlCmd,
|
||||
mem::{read_le16, read_le32},
|
||||
stat::{OpenFlags, Stat},
|
||||
};
|
||||
use vfs::{BlockDevice, Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
||||
|
||||
pub struct DirectoryInode {
|
||||
@ -26,20 +30,8 @@ pub struct Dirent {
|
||||
pub cluster: u32,
|
||||
}
|
||||
|
||||
#[auto_inode]
|
||||
impl VnodeImpl for DirectoryInode {
|
||||
fn create(
|
||||
&mut self,
|
||||
_parent: VnodeRef,
|
||||
_name: &str,
|
||||
_kind: VnodeKind,
|
||||
) -> Result<VnodeRef, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn remove(&mut self, _parent: VnodeRef, _name: &str) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn lookup(&mut self, parent: VnodeRef, name: &str) -> Result<VnodeRef, Errno> {
|
||||
let fs = parent.fs().unwrap();
|
||||
let dirent = {
|
||||
@ -72,30 +64,6 @@ impl VnodeImpl for DirectoryInode {
|
||||
}
|
||||
Ok(vnode)
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for FatIterator<'_> {
|
||||
|
@ -1,5 +1,9 @@
|
||||
use crate::Bpb;
|
||||
use error::Errno;
|
||||
use libsys::{
|
||||
stat::{Stat, OpenFlags},
|
||||
ioctl::IoctlCmd,
|
||||
error::Errno
|
||||
};
|
||||
use vfs::{VnodeImpl, VnodeKind, VnodeRef};
|
||||
|
||||
pub struct FileInode {
|
||||
@ -7,27 +11,15 @@ pub struct FileInode {
|
||||
pub size: u32,
|
||||
}
|
||||
|
||||
#[auto_inode]
|
||||
impl VnodeImpl for FileInode {
|
||||
fn create(&mut self, _at: VnodeRef, _name: &str, _kind: VnodeKind) -> Result<VnodeRef, Errno> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn remove(&mut self, _parent: VnodeRef, _name: &str) -> Result<(), Errno> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn lookup(&mut self, _parent: VnodeRef, _name: &str) -> Result<VnodeRef, Errno> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
fn open(&mut self, _node: VnodeRef, flags: OpenFlags) -> Result<usize, Errno> {
|
||||
if flags & OpenFlags::O_ACCESS != OpenFlags::O_RDONLY {
|
||||
return Err(Errno::ReadOnly);
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn read(&mut self, node: VnodeRef, pos: usize, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
let size = self.size as usize;
|
||||
if pos >= size {
|
||||
@ -60,16 +52,4 @@ impl VnodeImpl for FileInode {
|
||||
|
||||
Ok(off)
|
||||
}
|
||||
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,18 @@
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
|
||||
#[macro_use]
|
||||
extern crate fs_macros;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{boxed::Box, rc::Rc};
|
||||
use core::any::Any;
|
||||
use core::cell::{Ref, RefCell};
|
||||
use error::Errno;
|
||||
use libcommon::read_le32;
|
||||
use libsys::{
|
||||
mem::read_le32,
|
||||
error::Errno,
|
||||
};
|
||||
use vfs::{BlockDevice, Filesystem, Vnode, VnodeKind, VnodeRef};
|
||||
|
||||
pub mod dir;
|
||||
|
@ -1,8 +1,13 @@
|
||||
[package]
|
||||
name = "error"
|
||||
name = "fs-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "^1.0.81", features = ["full"] }
|
||||
quote = "^1.0.10"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
141
fs/macros/src/lib.rs
Normal file
141
fs/macros/src/lib.rs
Normal file
@ -0,0 +1,141 @@
|
||||
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};
|
||||
|
||||
fn impl_inode_fn<T: ToTokens>(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<VnodeRef, libsys::error::Errno>
|
||||
{
|
||||
#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<VnodeRef, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"stat" => quote! {
|
||||
fn stat(&mut self, _at: VnodeRef, _stat: &mut libsys::stat::Stat) ->
|
||||
Result<(), libsys::error::Errno>
|
||||
{
|
||||
#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<usize, libsys::error::Errno> {
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"read" => quote! {
|
||||
fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"write" => quote! {
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"open" => quote! {
|
||||
fn open(&mut self, _node: VnodeRef, _flags: libsys::stat::OpenFlags) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#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<usize, libsys::error::Errno>
|
||||
{
|
||||
#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::<String>::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());
|
||||
|
||||
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()
|
||||
}
|
@ -7,8 +7,8 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
vfs = { path = "../vfs" }
|
||||
error = { path = "../../error" }
|
||||
libcommon = { path = "../../libcommon" }
|
||||
fs-macros = { path = "../macros" }
|
||||
libsys = { path = "../../libsys" }
|
||||
|
||||
[features]
|
||||
cow = []
|
||||
|
@ -1,6 +1,6 @@
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
pub const SIZE: usize = 4096;
|
||||
pub const ENTRY_COUNT: usize = SIZE / size_of::<usize>();
|
||||
|
@ -2,7 +2,7 @@ use crate::{block, BlockAllocator, BlockRef};
|
||||
use core::cmp::min;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::ops::{Index, IndexMut};
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
const L0_BLOCKS: usize = 32; // 128K
|
||||
const L1_BLOCKS: usize = 8; // 16M
|
||||
|
@ -1,12 +1,13 @@
|
||||
use crate::{BlockAllocator, Bvec, FileInode};
|
||||
use alloc::boxed::Box;
|
||||
use error::Errno;
|
||||
use vfs::{OpenFlags, Stat, Vnode, VnodeImpl, VnodeKind, VnodeRef, IoctlCmd};
|
||||
use libsys::error::Errno;
|
||||
use vfs::{Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
||||
|
||||
pub struct DirInode<A: BlockAllocator + Copy + 'static> {
|
||||
alloc: A,
|
||||
}
|
||||
|
||||
#[auto_inode]
|
||||
impl<A: BlockAllocator + Copy + 'static> VnodeImpl for DirInode<A> {
|
||||
fn create(
|
||||
&mut self,
|
||||
@ -30,44 +31,6 @@ impl<A: BlockAllocator + Copy + 'static> VnodeImpl for DirInode<A> {
|
||||
fn remove(&mut self, _parent: VnodeRef, _name: &str) -> Result<(), Errno> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef, _flags: OpenFlags) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn stat(&mut self, _node: VnodeRef, _stat: &mut Stat) -> Result<(), Errno> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
node: VnodeRef,
|
||||
cmd: IoctlCmd,
|
||||
ptr: usize,
|
||||
len: usize,
|
||||
) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: BlockAllocator + Copy + 'static> DirInode<A> {
|
||||
|
@ -1,29 +1,16 @@
|
||||
use crate::{BlockAllocator, Bvec};
|
||||
use error::Errno;
|
||||
use vfs::{OpenFlags, Stat, VnodeImpl, VnodeKind, VnodeRef, IoctlCmd};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
stat::{OpenFlags, Stat},
|
||||
};
|
||||
use vfs::{VnodeImpl, VnodeKind, VnodeRef};
|
||||
|
||||
pub struct FileInode<'a, A: BlockAllocator + Copy + 'static> {
|
||||
data: Bvec<'a, A>,
|
||||
}
|
||||
|
||||
#[auto_inode]
|
||||
impl<'a, A: BlockAllocator + Copy + 'static> VnodeImpl for FileInode<'a, A> {
|
||||
fn create(
|
||||
&mut self,
|
||||
_parent: VnodeRef,
|
||||
_name: &str,
|
||||
_kind: VnodeKind,
|
||||
) -> Result<VnodeRef, Errno> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn lookup(&mut self, _parent: VnodeRef, _name: &str) -> Result<VnodeRef, Errno> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn remove(&mut self, _parent: VnodeRef, _name: &str) -> Result<(), Errno> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef, _mode: OpenFlags) -> Result<usize, Errno> {
|
||||
Ok(0)
|
||||
}
|
||||
@ -54,16 +41,6 @@ impl<'a, A: BlockAllocator + Copy + 'static> VnodeImpl for FileInode<'a, A> {
|
||||
stat.mode = 0o755;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
node: VnodeRef,
|
||||
cmd: IoctlCmd,
|
||||
ptr: usize,
|
||||
len: usize,
|
||||
) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: BlockAllocator + Copy + 'static> FileInode<'a, A> {
|
||||
|
@ -11,12 +11,18 @@ 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};
|
||||
use error::Errno;
|
||||
use libcommon::*;
|
||||
use vfs::{BlockDevice, FileMode, Filesystem, Vnode, VnodeKind, VnodeRef};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
path::{path_component_left, path_component_right},
|
||||
stat::FileMode,
|
||||
};
|
||||
use vfs::{BlockDevice, Filesystem, Vnode, VnodeKind, VnodeRef};
|
||||
|
||||
mod block;
|
||||
pub use block::{BlockAllocator, BlockRef};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use vfs::VnodeKind;
|
||||
|
||||
#[repr(packed)]
|
||||
|
@ -6,6 +6,5 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
error = { path = "../../error" }
|
||||
libcommon = { path = "../../libcommon" }
|
||||
syscall = { path = "../../syscall" }
|
||||
libsys = { path = "../../libsys" }
|
||||
fs-macros = { path = "../macros" }
|
||||
|
@ -1,4 +1,4 @@
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
/// Block device interface
|
||||
pub trait BlockDevice {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{OpenFlags, Stat, VnodeImpl, VnodeKind, VnodeRef, IoctlCmd};
|
||||
use error::Errno;
|
||||
use crate::{VnodeImpl, VnodeKind, VnodeRef};
|
||||
use libsys::{error::Errno, ioctl::IoctlCmd, stat::OpenFlags};
|
||||
|
||||
/// Generic character device trait
|
||||
pub trait CharDevice {
|
||||
@ -16,6 +16,7 @@ pub trait CharDevice {
|
||||
/// will immediately return an error.
|
||||
fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Errno>;
|
||||
|
||||
/// Performs a TTY control request
|
||||
fn ioctl(&self, cmd: IoctlCmd, ptr: usize, lim: usize) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
@ -25,19 +26,8 @@ pub struct CharDeviceWrapper {
|
||||
device: &'static dyn CharDevice,
|
||||
}
|
||||
|
||||
#[auto_inode(error)]
|
||||
impl VnodeImpl for CharDeviceWrapper {
|
||||
fn create(&mut self, _at: VnodeRef, _name: &str, _kind: VnodeKind) -> Result<VnodeRef, Errno> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn remove(&mut self, _at: VnodeRef, _name: &str) -> Result<(), Errno> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn lookup(&mut self, _at: VnodeRef, _name: &str) -> Result<VnodeRef, Errno> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef, _opts: OpenFlags) -> Result<usize, Errno> {
|
||||
Ok(0)
|
||||
}
|
||||
@ -54,19 +44,13 @@ impl VnodeImpl for CharDeviceWrapper {
|
||||
self.device.write(true, data)
|
||||
}
|
||||
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn stat(&mut self, _node: VnodeRef, _stat: &mut Stat) -> Result<(), Errno> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn ioctl(&mut self, _node: VnodeRef, cmd: IoctlCmd, ptr: usize, len: usize) -> Result<usize, Errno> {
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
_node: VnodeRef,
|
||||
cmd: IoctlCmd,
|
||||
ptr: usize,
|
||||
len: usize,
|
||||
) -> Result<usize, Errno> {
|
||||
self.device.ioctl(cmd, ptr, len)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ use crate::{VnodeKind, VnodeRef};
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
use core::cmp::min;
|
||||
use error::Errno;
|
||||
use libcommon::{Read, Seek, SeekDir, Write};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
traits::{Read, Seek, SeekDir, Write},
|
||||
};
|
||||
|
||||
struct NormalFile {
|
||||
vnode: VnodeRef,
|
||||
@ -133,11 +135,13 @@ impl Drop for File {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
||||
use libsys::{stat::OpenFlags, ioctl::IoctlCmd, stat::Stat};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
|
||||
struct DummyInode;
|
||||
|
||||
#[auto_inode]
|
||||
impl VnodeImpl for DummyInode {
|
||||
fn create(
|
||||
&mut self,
|
||||
@ -150,25 +154,17 @@ mod tests {
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn remove(&mut self, _at: VnodeRef, _name: &str) -> Result<(), Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn lookup(&mut self, _at: VnodeRef, _name: &str) -> Result<VnodeRef, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
fn open(&mut self, _node: VnodeRef, _flags: OpenFlags) -> Result<usize, Errno> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read(&mut self, _node: VnodeRef, pos: usize, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
#[cfg(test)]
|
||||
println!("read {}", pos);
|
||||
println!("read {} at {}", data.len(), pos);
|
||||
let len = 123;
|
||||
if pos >= len {
|
||||
return Ok(0);
|
||||
@ -183,41 +179,24 @@ mod tests {
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> Result<usize, Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_normal_read() {
|
||||
let node = Vnode::new("", VnodeKind::Regular, 0);
|
||||
node.set_data(Box::new(DummyInode {}));
|
||||
let mut file = node.open().unwrap();
|
||||
|
||||
match &file.inner {
|
||||
FileInner::Normal(inner) => {
|
||||
assert!(Rc::ptr_eq(&inner.vnode, &node));
|
||||
assert_eq!(inner.pos, 0);
|
||||
}
|
||||
_ => panic!("Invalid file.inner"),
|
||||
}
|
||||
|
||||
let mut file = node.open(OpenFlags::O_RDONLY).unwrap();
|
||||
let mut buf = [0u8; 4096];
|
||||
|
||||
assert_eq!(file.read(&mut buf[0..32]).unwrap(), 32);
|
||||
assert_eq!(file.borrow_mut().read(&mut buf[0..32]).unwrap(), 32);
|
||||
for i in 0..32 {
|
||||
assert_eq!((i & 0xFF) as u8, buf[i]);
|
||||
}
|
||||
assert_eq!(file.read(&mut buf[0..64]).unwrap(), 64);
|
||||
assert_eq!(file.borrow_mut().read(&mut buf[0..64]).unwrap(), 64);
|
||||
for i in 0..64 {
|
||||
assert_eq!(((i + 32) & 0xFF) as u8, buf[i]);
|
||||
}
|
||||
assert_eq!(file.read(&mut buf[0..64]).unwrap(), 27);
|
||||
assert_eq!(file.borrow_mut().read(&mut buf[0..64]).unwrap(), 27);
|
||||
for i in 0..27 {
|
||||
assert_eq!(((i + 96) & 0xFF) as u8, buf[i]);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::{BlockDevice, VnodeRef};
|
||||
use alloc::rc::Rc;
|
||||
use core::any::Any;
|
||||
use core::cell::Ref;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
/// General filesystem interface
|
||||
pub trait Filesystem {
|
||||
|
@ -1,6 +1,9 @@
|
||||
use crate::{FileMode, FileRef, OpenFlags, VnodeKind, VnodeRef};
|
||||
use error::Errno;
|
||||
use libcommon::{path_component_left, path_component_right};
|
||||
use crate::{FileRef, VnodeKind, VnodeRef};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
stat::{OpenFlags, FileMode},
|
||||
path::{path_component_left, path_component_right},
|
||||
};
|
||||
|
||||
/// I/O context structure
|
||||
#[derive(Clone)]
|
||||
@ -117,9 +120,11 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{Vnode, VnodeImpl, VnodeKind};
|
||||
use alloc::{boxed::Box, rc::Rc};
|
||||
use libsys::{ioctl::IoctlCmd, stat::OpenFlags, stat::Stat};
|
||||
|
||||
pub struct DummyInode;
|
||||
|
||||
#[auto_inode]
|
||||
impl VnodeImpl for DummyInode {
|
||||
fn create(
|
||||
&mut self,
|
||||
@ -132,37 +137,9 @@ mod tests {
|
||||
Ok(vnode)
|
||||
}
|
||||
|
||||
fn remove(&mut self, _at: VnodeRef, _name: &str) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn lookup(&mut self, _at: VnodeRef, _name: &str) -> Result<VnodeRef, Errno> {
|
||||
Err(Errno::DoesNotExist)
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -7,10 +7,13 @@
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
|
||||
#[macro_use]
|
||||
extern crate fs_macros;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub use syscall::stat::{FileMode, OpenFlags, Stat};
|
||||
pub use syscall::ioctl::IoctlCmd;
|
||||
// pub use libsys::stat::{FileMode, OpenFlags, Stat};
|
||||
// pub use libsys::ioctl::IoctlCmd;
|
||||
|
||||
mod block;
|
||||
pub use block::BlockDevice;
|
||||
|
@ -1,8 +1,12 @@
|
||||
use crate::{File, FileMode, FileRef, Filesystem, IoctlCmd, OpenFlags, Stat};
|
||||
use crate::{File, FileRef, Filesystem};
|
||||
use alloc::{borrow::ToOwned, boxed::Box, rc::Rc, string::String, vec::Vec};
|
||||
use core::cell::{RefCell, RefMut};
|
||||
use core::fmt;
|
||||
use error::Errno;
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
ioctl::IoctlCmd,
|
||||
stat::{FileMode, OpenFlags, Stat},
|
||||
};
|
||||
|
||||
/// Convenience type alias for [Rc<Vnode>]
|
||||
pub type VnodeRef = Rc<Vnode>;
|
||||
@ -76,6 +80,7 @@ pub trait VnodeImpl {
|
||||
/// Reports the size of this filesystem object in bytes
|
||||
fn size(&mut self, node: VnodeRef) -> Result<usize, Errno>;
|
||||
|
||||
/// Performs filetype-specific request
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
node: VnodeRef,
|
||||
@ -405,8 +410,10 @@ impl fmt::Debug for Vnode {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use libsys::{ioctl::IoctlCmd, stat::OpenFlags, stat::Stat};
|
||||
pub struct DummyInode;
|
||||
|
||||
#[auto_inode]
|
||||
impl VnodeImpl for DummyInode {
|
||||
fn create(
|
||||
&mut self,
|
||||
@ -426,30 +433,6 @@ mod tests {
|
||||
fn lookup(&mut self, _at: VnodeRef, _name: &str) -> Result<VnodeRef, Errno> {
|
||||
Err(Errno::DoesNotExist)
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) -> Result<usize, Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) -> Result<usize, Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
Err(Errno::NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -469,10 +452,13 @@ mod tests {
|
||||
|
||||
root.set_data(Box::new(DummyInode {}));
|
||||
|
||||
let node = root.mkdir("test", FileMode::default_dir()).unwrap();
|
||||
let node = root
|
||||
.create("test", FileMode::default_dir(), VnodeKind::Directory)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
root.mkdir("test", FileMode::default_dir()).unwrap_err(),
|
||||
root.create("test", FileMode::default_dir(), VnodeKind::Directory)
|
||||
.unwrap_err(),
|
||||
Errno::AlreadyExists
|
||||
);
|
||||
|
||||
|
@ -10,15 +10,14 @@ name = "kernel"
|
||||
test = false
|
||||
|
||||
[dependencies]
|
||||
error = { path = "../error" }
|
||||
vfs = { path = "../fs/vfs" }
|
||||
memfs = { path = "../fs/memfs" }
|
||||
libcommon = { path = "../libcommon" }
|
||||
syscall = { path = "../syscall" }
|
||||
libsys = { path = "../libsys" }
|
||||
cfg-if = "1.x.x"
|
||||
tock-registers = "0.7.x"
|
||||
fdt-rs = { version = "0.x.x", default-features = false }
|
||||
bitflags = "^1.3.0"
|
||||
kernel-macros = { path = "macros" }
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||
cortex-a = { version = "6.x.x" }
|
||||
|
@ -1,9 +1,13 @@
|
||||
[package]
|
||||
name = "libcommon"
|
||||
name = "kernel-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
error = { path = "../error" }
|
||||
syn = "^1.0.81"
|
||||
quote = "^1.0.10"
|
38
kernel/macros/src/lib.rs
Normal file
38
kernel/macros/src/lib.rs
Normal file
@ -0,0 +1,38 @@
|
||||
extern crate proc_macro;
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(TtyCharDevice)]
|
||||
pub fn derive_tty_char_device(input: TokenStream) -> TokenStream {
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
if !ast.generics.params.is_empty() {
|
||||
panic!(
|
||||
"Derived TtyCharDevice cannot have generic parameters: {:?}",
|
||||
ast.ident
|
||||
);
|
||||
}
|
||||
let ident = ast.ident;
|
||||
|
||||
quote! {
|
||||
impl vfs::CharDevice for #ident {
|
||||
fn read(&self, blocking: bool, data: &mut [u8]) -> Result<usize, libsys::error::Errno> {
|
||||
assert!(blocking);
|
||||
crate::dev::tty::TtyDevice::line_read(self, data)
|
||||
}
|
||||
fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, libsys::error::Errno> {
|
||||
assert!(blocking);
|
||||
crate::dev::tty::TtyDevice::line_write(self, data)
|
||||
}
|
||||
fn ioctl(&self, cmd: libsys::ioctl::IoctlCmd, ptr: usize, len: usize) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
crate::dev::tty::TtyDevice::tty_ioctl(self, cmd, ptr, len)
|
||||
}
|
||||
}
|
||||
}.into()
|
||||
}
|
@ -11,7 +11,7 @@ use crate::dev::{
|
||||
Device,
|
||||
};
|
||||
use crate::fs::devfs;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
//use crate::debug::Level;
|
||||
use crate::mem::{
|
||||
self, heap,
|
||||
|
@ -3,10 +3,10 @@
|
||||
use crate::arch::machine;
|
||||
use crate::debug::Level;
|
||||
use crate::dev::irq::{IntController, IrqContext};
|
||||
use crate::proc::{sched, Process};
|
||||
use crate::mem;
|
||||
use crate::proc::{sched, Process};
|
||||
use crate::syscall;
|
||||
use ::syscall::{abi, signal::Signal};
|
||||
use libsys::{abi, signal::Signal};
|
||||
use cortex_a::registers::{ESR_EL1, FAR_EL1};
|
||||
use tock_registers::interfaces::Readable;
|
||||
|
||||
|
@ -7,7 +7,7 @@ use crate::dev::{
|
||||
use crate::mem::virt::{DeviceMemory, DeviceMemoryIo};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
mod gicc;
|
||||
use gicc::Gicc;
|
||||
|
@ -12,7 +12,7 @@ use crate::dev::{
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::interfaces::{Readable, Writeable};
|
||||
use tock_registers::register_structs;
|
||||
use tock_registers::registers::ReadWrite;
|
||||
|
@ -13,7 +13,7 @@ use crate::dev::{
|
||||
};
|
||||
use crate::fs::devfs::{self, CharDeviceType};
|
||||
use crate::mem::phys;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
mod gpio;
|
||||
mod rtc;
|
||||
|
@ -7,7 +7,7 @@ use crate::dev::{
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::{
|
||||
interfaces::{Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
|
@ -8,11 +8,10 @@ use crate::dev::{
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||
use tock_registers::registers::{Aliased, ReadOnly, ReadWrite};
|
||||
use tock_registers::{register_bitfields, register_structs};
|
||||
use vfs::{CharDevice, IoctlCmd};
|
||||
|
||||
register_bitfields! [
|
||||
u32,
|
||||
@ -78,6 +77,7 @@ struct UartInner {
|
||||
regs: DeviceMemoryIo<Regs>,
|
||||
}
|
||||
|
||||
#[derive(TtyCharDevice)]
|
||||
pub(super) struct Uart {
|
||||
inner: InitOnce<IrqSafeSpinLock<UartInner>>,
|
||||
ring: CharRing<16>,
|
||||
@ -123,22 +123,6 @@ impl SerialDevice for Uart {
|
||||
}
|
||||
}
|
||||
|
||||
impl CharDevice for Uart {
|
||||
fn read(&self, blocking: bool, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
assert!(blocking);
|
||||
self.line_read(data)
|
||||
}
|
||||
|
||||
fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Errno> {
|
||||
assert!(blocking);
|
||||
self.line_write(data)
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: IoctlCmd, ptr: usize, len: usize) -> Result<usize, Errno> {
|
||||
self.tty_ioctl(cmd, ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
impl TtyDevice<16> for Uart {
|
||||
fn ring(&self) -> &CharRing<16> {
|
||||
&self.ring
|
||||
|
@ -2,7 +2,7 @@ use crate::dev::Device;
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::{
|
||||
interfaces::Writeable, register_bitfields, register_structs, registers::ReadWrite,
|
||||
};
|
||||
|
@ -13,7 +13,7 @@ use crate::dev::{
|
||||
};
|
||||
use crate::fs::devfs::{self, CharDeviceType};
|
||||
use crate::mem::phys;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
pub use gic::IrqNumber;
|
||||
|
||||
|
@ -7,7 +7,7 @@ use crate::dev::Device;
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||
use tock_registers::registers::{ReadOnly, ReadWrite};
|
||||
use tock_registers::{register_bitfields, register_structs};
|
||||
|
@ -7,7 +7,7 @@ use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use core::fmt;
|
||||
use cortex_a::registers::MPIDR_EL1;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
use tock_registers::interfaces::{Readable, Writeable};
|
||||
use tock_registers::register_structs;
|
||||
|
@ -2,7 +2,7 @@ use crate::dev::Device;
|
||||
use crate::mem::{self, virt::DeviceMemoryIo};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
use tock_registers::interfaces::{Readable, Writeable};
|
||||
use tock_registers::registers::{ReadOnly, WriteOnly};
|
||||
|
@ -5,7 +5,7 @@ use crate::dev::{
|
||||
Device,
|
||||
};
|
||||
use crate::mem::phys;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
pub mod irqchip;
|
||||
pub use irqchip::{Bcm283xIrqchip, IrqNumber};
|
||||
|
@ -8,7 +8,7 @@ use crate::dev::{
|
||||
};
|
||||
use core::time::Duration;
|
||||
use cortex_a::registers::{CNTFRQ_EL0, CNTPCT_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0};
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::interfaces::{Readable, Writeable};
|
||||
|
||||
/// Generic timer struct
|
||||
|
@ -1,12 +1,11 @@
|
||||
//! Device tree facilities
|
||||
use crate::debug::Level;
|
||||
use error::Errno;
|
||||
use fdt_rs::prelude::*;
|
||||
use fdt_rs::{
|
||||
base::DevTree,
|
||||
index::{DevTreeIndex, DevTreeIndexNode, DevTreeIndexProp},
|
||||
};
|
||||
use libcommon::path_component_left;
|
||||
use libsys::{error::Errno, path::path_component_left};
|
||||
|
||||
#[repr(align(16))]
|
||||
struct Wrap {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! GPIO and pin control interfaces
|
||||
|
||||
use crate::dev::Device;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
/// Pin function mode
|
||||
pub enum PinMode {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Interrupt controller and handler interfaces
|
||||
use crate::dev::Device;
|
||||
use core::marker::PhantomData;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
/// Token to indicate the local core is running in IRQ context
|
||||
pub struct IrqContext<'irq_context> {
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Module for device interfaces and drivers
|
||||
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
// Device classes
|
||||
pub mod fdt;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::dev::Device;
|
||||
use core::fmt;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
pub mod pcie;
|
||||
|
||||
|
@ -6,7 +6,7 @@ use crate::dev::{
|
||||
};
|
||||
use crate::mem::virt::DeviceMemory;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
/// GPEX host controller struct
|
||||
pub struct GenericPcieHost {
|
||||
|
@ -8,7 +8,7 @@ use crate::dev::{
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! SD host controller interface and card operation facilities
|
||||
use crate::dev::Device;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use vfs::BlockDevice;
|
||||
|
||||
/// Generic SD/MMC host controller interface
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Module for serial device drivers
|
||||
|
||||
use crate::dev::Device;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
#[cfg(feature = "pl011")]
|
||||
pub mod pl011;
|
||||
|
@ -10,14 +10,12 @@ use crate::dev::{
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use core::fmt;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
};
|
||||
use vfs::{CharDevice, IoctlCmd};
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
@ -78,6 +76,7 @@ struct Pl011Inner {
|
||||
}
|
||||
|
||||
/// Device struct for PL011
|
||||
#[derive(TtyCharDevice)]
|
||||
pub struct Pl011 {
|
||||
inner: InitOnce<IrqSafeSpinLock<Pl011Inner>>,
|
||||
ring: CharRing<16>,
|
||||
@ -117,16 +116,16 @@ impl Pl011Inner {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for Pl011Inner {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for &c in s.as_bytes() {
|
||||
unsafe {
|
||||
self.send(c);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
// impl fmt::Write for Pl011Inner {
|
||||
// fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
// for &c in s.as_bytes() {
|
||||
// unsafe {
|
||||
// self.send(c);
|
||||
// }
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl IntSource for Pl011 {
|
||||
fn handle_irq(&self) -> Result<(), Errno> {
|
||||
@ -168,21 +167,21 @@ impl SerialDevice for Pl011 {
|
||||
}
|
||||
}
|
||||
|
||||
impl CharDevice for Pl011 {
|
||||
fn read(&self, blocking: bool, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
assert!(blocking);
|
||||
self.line_read(data)
|
||||
}
|
||||
|
||||
fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Errno> {
|
||||
assert!(blocking);
|
||||
self.line_write(data)
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: IoctlCmd, ptr: usize, len: usize) -> Result<usize, Errno> {
|
||||
self.tty_ioctl(cmd, ptr, len)
|
||||
}
|
||||
}
|
||||
// impl CharDevice for Pl011 {
|
||||
// fn read(&self, blocking: bool, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
// assert!(blocking);
|
||||
// self.line_read(data)
|
||||
// }
|
||||
//
|
||||
// fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Errno> {
|
||||
// assert!(blocking);
|
||||
// self.line_write(data)
|
||||
// }
|
||||
//
|
||||
// fn ioctl(&self, cmd: IoctlCmd, ptr: usize, len: usize) -> Result<usize, Errno> {
|
||||
// self.tty_ioctl(cmd, ptr, len)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl TtyDevice<16> for Pl011 {
|
||||
fn ring(&self) -> &CharRing<16> {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::dev::Device;
|
||||
use core::time::Duration;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
/// Interface for generic timestamp source
|
||||
pub trait TimestampSource: Device {
|
||||
|
@ -2,14 +2,13 @@
|
||||
use crate::dev::serial::SerialDevice;
|
||||
use crate::proc::wait::Wait;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use error::Errno;
|
||||
use syscall::{
|
||||
use libsys::error::Errno;
|
||||
use libsys::{
|
||||
termios::{Termios, TermiosIflag, TermiosLflag, TermiosOflag},
|
||||
ioctl::IoctlCmd
|
||||
};
|
||||
use core::mem::size_of;
|
||||
use crate::syscall::arg::validate_user_ptr_struct;
|
||||
use vfs::CharDevice;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CharRingInner<const N: usize> {
|
||||
@ -27,10 +26,13 @@ pub struct CharRing<const N: usize> {
|
||||
inner: IrqSafeSpinLock<CharRingInner<N>>,
|
||||
}
|
||||
|
||||
/// Generic teletype device interface
|
||||
pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
/// Returns a reference to character device's ring buffer
|
||||
fn ring(&self) -> &CharRing<N>;
|
||||
|
||||
fn tty_ioctl(&self, cmd: IoctlCmd, ptr: usize, len: usize) -> Result<usize, Errno> {
|
||||
/// Performs a TTY control request
|
||||
fn tty_ioctl(&self, cmd: IoctlCmd, ptr: usize, _len: usize) -> Result<usize, Errno> {
|
||||
match cmd {
|
||||
IoctlCmd::TtyGetAttributes => {
|
||||
// TODO validate size
|
||||
@ -47,6 +49,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/// Processes and writes output an output byte
|
||||
fn line_send(&self, byte: u8) -> Result<(), Errno> {
|
||||
let config = self.ring().config.lock();
|
||||
|
||||
@ -57,6 +60,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
self.send(byte)
|
||||
}
|
||||
|
||||
/// Receives input bytes and processes them
|
||||
fn recv_byte(&self, mut byte: u8) {
|
||||
let ring = self.ring();
|
||||
let config = ring.config.lock();
|
||||
@ -105,7 +109,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
let ring = self.ring();
|
||||
let mut config = ring.config.lock();
|
||||
|
||||
if data.len() == 0 {
|
||||
if data.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
@ -113,7 +117,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
drop(config);
|
||||
let byte = ring.getc()?;
|
||||
data[0] = byte;
|
||||
return Ok(1);
|
||||
Ok(1)
|
||||
} else {
|
||||
let mut rem = data.len();
|
||||
let mut off = 0;
|
||||
@ -140,7 +144,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
let idx = data[..off].iter().rposition(|&ch| ch == b' ').unwrap_or(0);
|
||||
let len = off;
|
||||
|
||||
for i in idx..len {
|
||||
for _ in idx..len {
|
||||
self.raw_write(b"\x1B[D \x1B[D").ok();
|
||||
off -= 1;
|
||||
rem += 1;
|
||||
@ -173,6 +177,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/// Processes and writes string bytes
|
||||
fn line_write(&self, data: &[u8]) -> Result<usize, Errno> {
|
||||
for &byte in data.iter() {
|
||||
self.line_send(byte)?;
|
||||
@ -180,6 +185,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
Ok(data.len())
|
||||
}
|
||||
|
||||
/// Writes string bytes without any processing
|
||||
fn raw_write(&self, data: &[u8]) -> Result<usize, Errno> {
|
||||
for &byte in data.iter() {
|
||||
self.send(byte)?;
|
||||
|
@ -2,7 +2,7 @@
|
||||
use crate::util::InitOnce;
|
||||
use alloc::boxed::Box;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use vfs::{CharDevice, CharDeviceWrapper, Vnode, VnodeKind, VnodeRef};
|
||||
|
||||
/// Possible character device kinds
|
||||
|
@ -5,7 +5,8 @@ use crate::fs::{devfs, MemfsBlockAlloc};
|
||||
use crate::mem;
|
||||
use crate::proc::{elf, Process};
|
||||
use memfs::Ramfs;
|
||||
use vfs::{Filesystem, Ioctx, OpenFlags};
|
||||
use libsys::stat::OpenFlags;
|
||||
use vfs::{Filesystem, Ioctx};
|
||||
|
||||
/// Kernel init process function
|
||||
#[inline(never)]
|
||||
|
@ -18,6 +18,8 @@
|
||||
#![no_main]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate kernel_macros;
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
#[macro_use]
|
||||
|
@ -26,73 +26,3 @@ pub fn kernel_end_phys() -> usize {
|
||||
}
|
||||
unsafe { &__kernel_end as *const _ as usize - KERNEL_OFFSET }
|
||||
}
|
||||
|
||||
/// See memcpy(3p).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: writes to arbitrary memory locations, performs no pointer
|
||||
/// validation.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memcpy(dst: *mut u8, src: *mut u8, mut len: usize) -> *mut u8 {
|
||||
while len != 0 {
|
||||
len -= 1;
|
||||
*dst.add(len) = *src.add(len);
|
||||
}
|
||||
dst
|
||||
}
|
||||
|
||||
/// See memcmp(3p).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: performs reads from arbitrary memory locations, performs no
|
||||
/// pointer validation.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memcmp(a: *mut u8, b: *mut u8, mut len: usize) -> isize {
|
||||
while len != 0 {
|
||||
len -= 1;
|
||||
if *a.add(len) < *b.add(len) {
|
||||
return -1;
|
||||
}
|
||||
if *a.add(len) > *b.add(len) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
/// See memmove(3p)
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: writes to arbitrary memory locations, performs no pointer
|
||||
/// validation.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memmove(dst: *mut u8, src: *mut u8, len: usize) -> *mut u8 {
|
||||
if dst < src {
|
||||
for i in 0..len {
|
||||
*dst.add(i) = *src.add(i);
|
||||
}
|
||||
} else {
|
||||
for i in 0..len {
|
||||
*dst.add(len - (i + 1)) = *src.add(len - (i + 1));
|
||||
}
|
||||
}
|
||||
dst
|
||||
}
|
||||
|
||||
/// See memset(3p)
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: writes to arbitrary memory locations, performs no pointer
|
||||
/// validation.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memset(buf: *mut u8, val: u8, mut len: usize) -> *mut u8 {
|
||||
while len != 0 {
|
||||
len -= 1;
|
||||
*buf.add(len) = val;
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::{PageInfo, PageUsage, PageStatistics};
|
||||
use crate::mem::{memcpy, memset, virtualize, PAGE_SIZE};
|
||||
use crate::mem::{virtualize, PAGE_SIZE};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use core::mem;
|
||||
use error::Errno;
|
||||
use libsys::{error::Errno, mem::memcpy};
|
||||
|
||||
pub unsafe trait Manager {
|
||||
fn alloc_page(&mut self, pu: PageUsage) -> Result<usize, Errno>;
|
||||
@ -144,25 +144,28 @@ unsafe impl Manager for SimpleManager {
|
||||
|
||||
fn copy_cow_page(&mut self, src: usize) -> Result<usize, Errno> {
|
||||
let src_index = self.page_index(src);
|
||||
let page = &mut self.pages[src_index];
|
||||
let usage = page.usage;
|
||||
if usage != PageUsage::UserPrivate {
|
||||
panic!("CoW not available for non-UserPrivate pages: {:?}", usage);
|
||||
}
|
||||
let (usage, refcount) = {
|
||||
let page = &mut self.pages[src_index];
|
||||
let usage = page.usage;
|
||||
if usage != PageUsage::UserPrivate {
|
||||
panic!("CoW not available for non-UserPrivate pages: {:?}", usage);
|
||||
}
|
||||
let count = page.refcount;
|
||||
if count > 1 {
|
||||
page.refcount -= 1;
|
||||
}
|
||||
(usage, count)
|
||||
};
|
||||
|
||||
if page.refcount > 1 {
|
||||
page.refcount -= 1;
|
||||
drop(page);
|
||||
if refcount == 0 {
|
||||
Ok(src)
|
||||
} else {
|
||||
let dst_index = self.alloc_single_index(usage)?;
|
||||
let dst = (self.base_index + dst_index) * PAGE_SIZE;
|
||||
unsafe {
|
||||
memcpy(virtualize(dst) as *mut u8, virtualize(src) as *mut u8, 4096);
|
||||
}
|
||||
Ok(dst)
|
||||
} else {
|
||||
assert_eq!(page.refcount, 1);
|
||||
// No additional operations needed
|
||||
Ok(src)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::config::{ConfigKey, CONFIG};
|
||||
use crate::mem::PAGE_SIZE;
|
||||
use core::mem::size_of;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
mod manager;
|
||||
mod reserved;
|
||||
@ -147,6 +147,12 @@ pub fn statistics() -> PageStatistics {
|
||||
MANAGER.lock().as_ref().unwrap().statistics()
|
||||
}
|
||||
|
||||
/// Clones the source page.
|
||||
///
|
||||
/// If returned address is the same as `page`, this means
|
||||
/// `page`'s refcount has increased and the page is Copy-on-Write.
|
||||
/// This case has to be handled accordingly
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: accepts arbitrary `page` arguments
|
||||
@ -154,6 +160,12 @@ pub unsafe fn fork_page(page: usize) -> Result<usize, Errno> {
|
||||
MANAGER.lock().as_mut().unwrap().fork_page(page)
|
||||
}
|
||||
|
||||
/// Copies a Copy-on-Write page. If refcount is already 1,
|
||||
/// page does not need to be copied and the same address is returned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: accepts arbitrary `page` arguments
|
||||
pub unsafe fn copy_cow_page(page: usize) -> Result<usize, Errno> {
|
||||
MANAGER.lock().as_mut().unwrap().copy_cow_page(page)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::mem::{
|
||||
virt::{Entry, MapAttributes, Table},
|
||||
};
|
||||
use cortex_a::asm::barrier::{self, dsb, isb};
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
const DEVICE_MAP_OFFSET: usize = mem::KERNEL_OFFSET + (256usize << 30);
|
||||
|
||||
|
@ -4,7 +4,7 @@ use core::marker::PhantomData;
|
||||
use core::ops::Deref;
|
||||
use cortex_a::asm::barrier::{self, dsb, isb};
|
||||
use cortex_a::registers::TTBR0_EL1;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use tock_registers::interfaces::Writeable;
|
||||
|
||||
pub mod table;
|
||||
|
@ -5,7 +5,7 @@ use crate::mem::{
|
||||
phys::{self, PageUsage},
|
||||
};
|
||||
use core::ops::{Index, IndexMut};
|
||||
use error::Errno;
|
||||
use libsys::{error::Errno, mem::memset};
|
||||
|
||||
/// Transparent wrapper structure representing a single
|
||||
/// translation table entry
|
||||
@ -38,6 +38,7 @@ bitflags! {
|
||||
/// This page is used for device-MMIO mapping and uses MAIR attribute #1
|
||||
const DEVICE = 1 << 2;
|
||||
|
||||
/// Pages marked with this bit are Copy-on-Write
|
||||
const EX_COW = 1 << 55;
|
||||
|
||||
/// UXN bit -- if set, page may not be used for instruction fetching from EL0
|
||||
@ -209,6 +210,8 @@ impl Space {
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to resolve a page fault at `virt` address by copying the
|
||||
/// underlying Copy-on-Write mapping (if any is present)
|
||||
pub fn try_cow_copy(&mut self, virt: usize) -> Result<(), Errno> {
|
||||
let virt = virt & !0xFFF;
|
||||
let l0i = virt >> 30;
|
||||
@ -227,7 +230,11 @@ impl Space {
|
||||
|
||||
let src_phys = unsafe { entry.address_unchecked() };
|
||||
if !entry.is_cow() {
|
||||
warnln!("Entry is not marked as CoW: {:#x}, points to {:#x}", virt, src_phys);
|
||||
warnln!(
|
||||
"Entry is not marked as CoW: {:#x}, points to {:#x}",
|
||||
virt,
|
||||
src_phys
|
||||
);
|
||||
return Err(Errno::DoesNotExist);
|
||||
}
|
||||
|
||||
@ -270,7 +277,7 @@ impl Space {
|
||||
unsafe {
|
||||
asm!("tlbi vaae1, {}", in(reg) virt_addr);
|
||||
}
|
||||
res.map(virt_addr, dst_phys, flags);
|
||||
res.map(virt_addr, dst_phys, flags)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -280,6 +287,13 @@ impl Space {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Releases all the mappings from the address space. Frees all
|
||||
/// memory pages referenced by this space as well as those used for
|
||||
/// its paging tables.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: may invalidate currently active address space
|
||||
pub unsafe fn release(space: &mut Self) {
|
||||
for l0i in 0..512 {
|
||||
let l0_entry = space.0[l0i];
|
||||
@ -288,8 +302,7 @@ impl Space {
|
||||
}
|
||||
|
||||
assert!(l0_entry.is_table());
|
||||
let l1_table =
|
||||
unsafe { &mut *(mem::virtualize(l0_entry.address_unchecked()) as *mut Table) };
|
||||
let l1_table = &mut *(mem::virtualize(l0_entry.address_unchecked()) as *mut Table);
|
||||
|
||||
for l1i in 0..512 {
|
||||
let l1_entry = l1_table[l1i];
|
||||
@ -297,8 +310,7 @@ impl Space {
|
||||
continue;
|
||||
}
|
||||
assert!(l1_entry.is_table());
|
||||
let l2_table =
|
||||
unsafe { &mut *(mem::virtualize(l1_entry.address_unchecked()) as *mut Table) };
|
||||
let l2_table = &mut *(mem::virtualize(l1_entry.address_unchecked()) as *mut Table);
|
||||
|
||||
for l2i in 0..512 {
|
||||
let entry = l2_table[l2i];
|
||||
@ -307,21 +319,13 @@ impl Space {
|
||||
}
|
||||
|
||||
assert!(entry.is_table());
|
||||
unsafe {
|
||||
phys::free_page(unsafe { entry.address_unchecked() });
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
phys::free_page(unsafe { l1_entry.address_unchecked() });
|
||||
phys::free_page(entry.address_unchecked()).unwrap();
|
||||
}
|
||||
phys::free_page(l1_entry.address_unchecked()).unwrap();
|
||||
}
|
||||
unsafe {
|
||||
phys::free_page(unsafe { l0_entry.address_unchecked() });
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
mem::memset(space as *mut Space as *mut u8, 0, 4096);
|
||||
phys::free_page(l0_entry.address_unchecked()).unwrap();
|
||||
}
|
||||
memset(space as *mut Space as *mut u8, 0, 4096);
|
||||
}
|
||||
|
||||
pub fn address_phys(&mut self) -> usize {
|
||||
|
@ -5,8 +5,10 @@ use crate::mem::{
|
||||
virt::{MapAttributes, Space},
|
||||
};
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
use error::Errno;
|
||||
use libcommon::{Read, Seek, SeekDir};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
traits::{Read, Seek, SeekDir}
|
||||
};
|
||||
use vfs::FileRef;
|
||||
|
||||
trait Elf {
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Process file descriptors and I/O context
|
||||
use alloc::collections::BTreeMap;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
use vfs::{FileRef, Ioctx};
|
||||
|
||||
/// Process I/O context. Contains file tables, root/cwd info etc.
|
||||
|
@ -11,8 +11,7 @@ use alloc::rc::Rc;
|
||||
use core::cell::UnsafeCell;
|
||||
use core::fmt;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use error::Errno;
|
||||
use syscall::signal::Signal;
|
||||
use libsys::{error::Errno, signal::Signal};
|
||||
|
||||
pub use crate::arch::platform::context::{self, Context};
|
||||
|
||||
@ -131,6 +130,11 @@ impl Pid {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Constructs [Pid] from raw [u32] value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: does not check `num`
|
||||
pub const unsafe fn from_raw(num: u32) -> Self {
|
||||
Self(num)
|
||||
}
|
||||
@ -156,6 +160,7 @@ impl Process {
|
||||
SCHED.current_process()
|
||||
}
|
||||
|
||||
/// Returns process (if any) to which `pid` refers
|
||||
pub fn get(pid: Pid) -> Option<ProcessRef> {
|
||||
PROCESSES.lock().get(&pid).cloned()
|
||||
}
|
||||
@ -256,6 +261,7 @@ impl Process {
|
||||
proc.current_context().enter()
|
||||
}
|
||||
|
||||
/// Executes a function allowing mutation of the process address space
|
||||
#[inline]
|
||||
pub fn manipulate_space<F: FnOnce(&mut Space) -> Result<(), Errno>>(
|
||||
&self,
|
||||
|
@ -126,6 +126,7 @@ impl Scheduler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the scheduler has been initialized
|
||||
pub fn is_ready() -> bool {
|
||||
SCHED.inner.is_initialized()
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use crate::proc::{self, sched::SCHED, Pid, Process};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use alloc::collections::LinkedList;
|
||||
use core::time::Duration;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
/// Wait channel structure. Contains a queue of processes
|
||||
/// waiting for some event to happen.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::mem;
|
||||
use core::mem::size_of;
|
||||
use error::Errno;
|
||||
use libsys::error::Errno;
|
||||
|
||||
fn translate(virt: usize) -> Option<usize> {
|
||||
let mut res: usize;
|
||||
|
@ -6,14 +6,15 @@ use crate::proc::{elf, wait, Pid, Process, ProcessIo};
|
||||
use core::mem::size_of;
|
||||
use core::ops::DerefMut;
|
||||
use core::time::Duration;
|
||||
use error::Errno;
|
||||
use libcommon::{Read, Write};
|
||||
use syscall::{
|
||||
use libsys::{
|
||||
abi,
|
||||
signal::Signal,
|
||||
stat::{AT_EMPTY_PATH, AT_FDCWD},
|
||||
error::Errno,
|
||||
ioctl::IoctlCmd,
|
||||
stat::{FileMode, OpenFlags, Stat, AT_EMPTY_PATH, AT_FDCWD},
|
||||
traits::{Read, Write},
|
||||
};
|
||||
use vfs::{FileMode, IoctlCmd, OpenFlags, Stat, VnodeRef};
|
||||
use vfs::VnodeRef;
|
||||
|
||||
pub mod arg;
|
||||
pub use arg::*;
|
||||
|
@ -1,49 +0,0 @@
|
||||
#![no_std]
|
||||
|
||||
use error::Errno;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum SeekDir {
|
||||
Set,
|
||||
End,
|
||||
Current,
|
||||
}
|
||||
|
||||
pub trait Read {
|
||||
fn read(&mut self, data: &mut [u8]) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
pub trait Seek {
|
||||
fn seek(&mut self, off: isize, whence: SeekDir) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
pub trait Write {
|
||||
fn write(&mut self, data: &[u8]) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
pub fn path_component_left(path: &str) -> (&str, &str) {
|
||||
if let Some((left, right)) = path.split_once('/') {
|
||||
(left, right.trim_start_matches('/'))
|
||||
} else {
|
||||
(path, "")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_component_right(path: &str) -> (&str, &str) {
|
||||
if let Some((left, right)) = path.trim_end_matches('/').rsplit_once('/') {
|
||||
(left.trim_end_matches('/'), right)
|
||||
} else {
|
||||
("", path)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_le32(src: &[u8]) -> u32 {
|
||||
(src[0] as u32) | ((src[1] as u32) << 8) | ((src[2] as u32) << 16) | ((src[3] as u32) << 24)
|
||||
}
|
||||
|
||||
pub fn read_le16(src: &[u8]) -> u16 {
|
||||
(src[0] as u16) | ((src[1] as u16) << 8)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {}
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "syscall"
|
||||
name = "libsys"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
@ -7,7 +7,6 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "^1.3.0"
|
||||
error = { path = "../error" }
|
||||
|
||||
[features]
|
||||
user = []
|
@ -4,7 +4,6 @@ use crate::{
|
||||
signal::Signal,
|
||||
stat::{FileMode, OpenFlags, Stat},
|
||||
};
|
||||
use core::mem::size_of;
|
||||
|
||||
// TODO document the syscall ABI
|
||||
|
||||
@ -189,6 +188,9 @@ pub unsafe fn sys_waitpid(pid: u32, status: &mut i32) -> i32 {
|
||||
syscall!(abi::SYS_WAITPID, argn!(pid), argp!(status as *mut i32)) as i32
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ioctl(fd: u32, cmd: IoctlCmd, ptr: usize, len: usize) -> isize {
|
||||
syscall!(
|
@ -1,5 +1,3 @@
|
||||
#![no_std]
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum Errno {
|
||||
AlreadyExists,
|
@ -1,9 +1,9 @@
|
||||
use core::convert::TryFrom;
|
||||
use error::Errno;
|
||||
|
||||
use crate::error::Errno;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(u32)]
|
||||
#[non_exhaustive]
|
||||
pub enum IoctlCmd {
|
||||
TtySetAttributes = 1,
|
||||
TtyGetAttributes = 2,
|
@ -9,6 +9,10 @@ pub mod stat;
|
||||
pub mod ioctl;
|
||||
pub mod termios;
|
||||
pub mod signal;
|
||||
pub mod error;
|
||||
pub mod path;
|
||||
pub mod mem;
|
||||
pub mod traits;
|
||||
|
||||
#[cfg(feature = "user")]
|
||||
pub mod calls;
|
@ -1,3 +1,11 @@
|
||||
pub fn read_le32(src: &[u8]) -> u32 {
|
||||
(src[0] as u32) | ((src[1] as u32) << 8) | ((src[2] as u32) << 16) | ((src[3] as u32) << 24)
|
||||
}
|
||||
|
||||
pub fn read_le16(src: &[u8]) -> u16 {
|
||||
(src[0] as u16) | ((src[1] as u16) << 8)
|
||||
}
|
||||
|
||||
/// See memcpy(3p).
|
||||
///
|
||||
/// # Safety
|
15
libsys/src/path.rs
Normal file
15
libsys/src/path.rs
Normal file
@ -0,0 +1,15 @@
|
||||
pub fn path_component_left(path: &str) -> (&str, &str) {
|
||||
if let Some((left, right)) = path.split_once('/') {
|
||||
(left, right.trim_start_matches('/'))
|
||||
} else {
|
||||
(path, "")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_component_right(path: &str) -> (&str, &str) {
|
||||
if let Some((left, right)) = path.trim_end_matches('/').rsplit_once('/') {
|
||||
(left.trim_end_matches('/'), right)
|
||||
} else {
|
||||
("", path)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use error::Errno;
|
||||
use crate::error::Errno;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u32)]
|
28
libsys/src/traits.rs
Normal file
28
libsys/src/traits.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use crate::error::Errno;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum SeekDir {
|
||||
Set,
|
||||
End,
|
||||
Current,
|
||||
}
|
||||
|
||||
pub trait Read {
|
||||
fn read(&mut self, data: &mut [u8]) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
pub trait Seek {
|
||||
fn seek(&mut self, off: isize, whence: SeekDir) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
pub trait Write {
|
||||
fn write(&mut self, data: &[u8]) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
pub trait RandomRead {
|
||||
fn pread(&mut self, pos: usize, data: &mut [u8]) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
pub trait RandomWrite {
|
||||
fn pwrite(&mut self, pos: usize, data: &[u8]) -> Result<usize, Errno>;
|
||||
}
|
@ -6,4 +6,4 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
syscall = { path = "../syscall", features = ["user"] }
|
||||
libsys = { path = "../libsys", features = ["user"] }
|
||||
|
@ -1,13 +1,15 @@
|
||||
use crate::sys::{self, Stat};
|
||||
use core::fmt;
|
||||
use syscall::stat::AT_FDCWD;
|
||||
use libsys::{
|
||||
calls::{sys_fstatat, sys_write},
|
||||
stat::{Stat, AT_FDCWD},
|
||||
};
|
||||
|
||||
// TODO populate this type
|
||||
pub struct Error;
|
||||
|
||||
pub fn stat(pathname: &str) -> Result<Stat, Error> {
|
||||
let mut buf = Stat::default();
|
||||
let res = unsafe { sys::sys_fstatat(AT_FDCWD, pathname, &mut buf, 0) };
|
||||
let res = unsafe { sys_fstatat(AT_FDCWD, pathname, &mut buf, 0) };
|
||||
if res != 0 {
|
||||
todo!();
|
||||
}
|
||||
@ -60,6 +62,6 @@ pub fn _print(fd: i32, args: fmt::Arguments) {
|
||||
};
|
||||
writer.write_fmt(args).ok();
|
||||
unsafe {
|
||||
sys::sys_write(fd, &BUFFER[..writer.pos]);
|
||||
sys_write(fd, &BUFFER[..writer.pos]);
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,13 @@
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
pub mod io;
|
||||
pub mod mem;
|
||||
pub mod os;
|
||||
|
||||
pub mod sys {
|
||||
pub use syscall::calls::*;
|
||||
pub use syscall::stat::*;
|
||||
pub use syscall::signal::Signal;
|
||||
pub use syscall::termios;
|
||||
pub use libsys::signal::Signal;
|
||||
pub use libsys::termios;
|
||||
pub use libsys::calls::*;
|
||||
pub use libsys::stat::{self, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO};
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::sys;
|
||||
use core::fmt;
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
use syscall::{ioctl::IoctlCmd, termios::Termios};
|
||||
use libsys::{ioctl::IoctlCmd, termios::Termios};
|
||||
|
||||
pub fn get_tty_attrs(fd: u32) -> Result<Termios, &'static str> {
|
||||
let mut termios = MaybeUninit::<Termios>::uninit();
|
||||
|
@ -5,22 +5,31 @@
|
||||
#[macro_use]
|
||||
extern crate libusr;
|
||||
|
||||
use core::cmp::Ordering;
|
||||
|
||||
#[no_mangle]
|
||||
fn main() -> i32 {
|
||||
let pid = unsafe { libusr::sys::sys_fork() };
|
||||
if pid < 0 {
|
||||
eprintln!("fork() failed");
|
||||
return -1;
|
||||
} else if pid == 0 {
|
||||
return unsafe { libusr::sys::sys_execve("/bin/shell") };
|
||||
} else {
|
||||
let mut status = 0;
|
||||
let res = unsafe { libusr::sys::sys_waitpid(pid as u32, &mut status) };
|
||||
if res == 0 {
|
||||
println!("Process {} exited with status {}", pid, status);
|
||||
} else {
|
||||
eprintln!("waitpid() failed");
|
||||
match pid.cmp(&0) {
|
||||
Ordering::Less => {
|
||||
eprintln!("fork() failed");
|
||||
-1
|
||||
}
|
||||
Ordering::Equal => unsafe { libusr::sys::sys_execve("/bin/shell") },
|
||||
Ordering::Greater => {
|
||||
let mut status = 0;
|
||||
let res = unsafe { libusr::sys::sys_waitpid(pid as u32, &mut status) };
|
||||
if res == 0 {
|
||||
println!("Process {} exited with status {}", pid, status);
|
||||
} else {
|
||||
eprintln!("waitpid() failed");
|
||||
}
|
||||
|
||||
loop {
|
||||
unsafe {
|
||||
asm!("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
@ -41,5 +41,5 @@ fn main() -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
0
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user