From a490ff13ae8477f6387773317d294ff7f509bb5d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 14 Aug 2016 15:58:35 -0600 Subject: [PATCH] Add syscall module --- kernel/lib.rs | 6 +++ kernel/syscall/fs.rs | 27 +++++++++++ kernel/syscall/mod.rs | 95 +++++++++++++++++++++++++++++++++++++++ kernel/syscall/process.rs | 10 +++++ 4 files changed, 138 insertions(+) create mode 100644 kernel/syscall/fs.rs create mode 100644 kernel/syscall/mod.rs create mode 100644 kernel/syscall/process.rs diff --git a/kernel/lib.rs b/kernel/lib.rs index 5927692..1d0e884 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -65,6 +65,7 @@ //! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry. #![feature(lang_items)] +#![feature(question_mark)] #![no_std] #[macro_use] @@ -85,6 +86,9 @@ extern crate arch_x86_64 as arch; /// Intrinsics for panic handling pub mod panic; +/// Syscall handlers +pub mod syscall; + /// Tests #[cfg(test)] pub mod tests; @@ -93,6 +97,8 @@ pub mod tests; pub extern fn kmain() { println!("TEST"); + println!("{:?}", syscall::open(b"file:/test/file", 0)); + unsafe { set_interrupts() }; loop { unsafe { halt() }; diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs new file mode 100644 index 0000000..d3c6a15 --- /dev/null +++ b/kernel/syscall/fs.rs @@ -0,0 +1,27 @@ +//! Filesystem syscalls + +use super::Result; + +/// Read syscall +pub fn read(fd: usize, buf: &mut [u8]) -> Result { + println!("Read {}: {}", fd, buf.len()); + Ok(0) +} + +/// Write syscall +pub fn write(fd: usize, buf: &[u8]) -> Result { + println!("Write {}: {}", fd, buf.len()); + Ok(0) +} + +/// Open syscall +pub fn open(path: &[u8], flags: usize) -> Result { + println!("Open {:?}: {:X}", ::core::str::from_utf8(path), flags); + Ok(0) +} + +/// Close syscall +pub fn close(fd: usize) -> Result { + println!("Close {}", fd); + Ok(0) +} diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs new file mode 100644 index 0000000..cd71b76 --- /dev/null +++ b/kernel/syscall/mod.rs @@ -0,0 +1,95 @@ +///! Syscall handlers + +use core::slice; + +pub use self::fs::*; +pub use self::process::*; + +/// Filesystem syscalls +pub mod fs; + +/// Process syscalls +pub mod process; + +/// System call list +#[derive(Copy, Clone, Debug)] +pub enum Call { + /// Exit syscall + Exit, + /// Read syscall + Read, + /// Write syscall + Write, + /// Open syscall + Open, + /// Close syscall + Close, + /// Unknown syscall + Unknown +} + +/// Convert numbers to calls +/// See http://syscalls.kernelgrok.com/ +impl From for Call { + fn from(number: usize) -> Call { + match number { + 1 => Call::Exit, + 3 => Call::Read, + 4 => Call::Write, + 5 => Call::Open, + 6 => Call::Close, + _ => Call::Unknown + } + } +} + +/// The error number for an invalid value +#[derive(Copy, Clone, Debug)] +pub enum Error { + /// Operation not permitted + NotPermitted, + /// No such file or directory + NoEntry, + /// Invalid argument + InvalidValue, + /// Syscall not implemented + NoCall +} + +/// Convert errors to numbers +/// See http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html +impl From for usize { + fn from(err: Error) -> usize { + match err { + Error::NotPermitted => 1, + Error::NoEntry => 2, + Error::InvalidValue => 22, + Error::NoCall => 38 + } + } +} + +pub type Result = ::core::result::Result; + +/// Convert a pointer and length to slice, if valid +/// TODO: Check validity +pub fn convert_slice(ptr: usize, len: usize) -> Result<&'static [u8]> { + Ok(unsafe { slice::from_raw_parts(ptr as *const u8, len) }) +} + +/// Convert a pointer and length to slice, if valid +/// TODO: Check validity +pub fn convert_slice_mut(ptr: usize, len: usize) -> Result<&'static mut [u8]> { + Ok(unsafe { slice::from_raw_parts_mut(ptr as *mut u8, len) }) +} + +pub fn handle(a: usize, b: usize, c: usize, d: usize) -> ::core::result::Result { + match Call::from(a) { + Call::Exit => exit(b), + Call::Read => read(b, convert_slice_mut(c, d)?), + Call::Write => write(b, convert_slice(c, d)?), + Call::Open => open(convert_slice(b, c)?, d), + Call::Close => close(b), + Call::Unknown => Err(Error::NoCall) + }.map_err(|err| err.into()) +} diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs new file mode 100644 index 0000000..6cbe1ec --- /dev/null +++ b/kernel/syscall/process.rs @@ -0,0 +1,10 @@ +///! Process syscalls + +use arch::interrupt::halt; + +pub fn exit(status: usize) -> ! { + println!("Exit {}", status); + loop { + unsafe { halt() }; + } +}