Add fsync. Add env scheme, currently hardcoded to get ion to launch. Make serial IRQ send data to debug scheme
This commit is contained in:
parent
1b056395bb
commit
483d466b1a
|
@ -102,7 +102,12 @@ impl SerialPort {
|
||||||
|
|
||||||
pub fn on_receive(&mut self) {
|
pub fn on_receive(&mut self) {
|
||||||
let data = self.data.read();
|
let data = self.data.read();
|
||||||
self.write_translate(data);
|
|
||||||
|
extern {
|
||||||
|
fn debug_input(byte: u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { debug_input(data) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,25 @@
|
||||||
|
use collections::VecDeque;
|
||||||
use core::str;
|
use core::str;
|
||||||
|
use spin::{Mutex, MutexGuard, Once};
|
||||||
|
|
||||||
|
use context;
|
||||||
use syscall::Result;
|
use syscall::Result;
|
||||||
use super::Scheme;
|
use super::Scheme;
|
||||||
|
|
||||||
|
/// Input
|
||||||
|
static INPUT: Once<Mutex<VecDeque<u8>>> = Once::new();
|
||||||
|
|
||||||
|
/// Initialize contexts, called if needed
|
||||||
|
fn init_input() -> Mutex<VecDeque<u8>> {
|
||||||
|
Mutex::new(VecDeque::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the global schemes list, const
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn debug_input(b: u8) {
|
||||||
|
INPUT.call_once(init_input).lock().push_back(b)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DebugScheme;
|
pub struct DebugScheme;
|
||||||
|
|
||||||
impl Scheme for DebugScheme {
|
impl Scheme for DebugScheme {
|
||||||
|
@ -17,8 +34,23 @@ impl Scheme for DebugScheme {
|
||||||
/// Read the file `number` into the `buffer`
|
/// Read the file `number` into the `buffer`
|
||||||
///
|
///
|
||||||
/// Returns the number of bytes read
|
/// Returns the number of bytes read
|
||||||
fn read(&mut self, _file: usize, _buffer: &mut [u8]) -> Result<usize> {
|
fn read(&mut self, _file: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
Ok(0)
|
loop {
|
||||||
|
let mut i = 0;
|
||||||
|
{
|
||||||
|
let mut input = INPUT.call_once(init_input).lock();
|
||||||
|
while i < buf.len() && ! input.is_empty() {
|
||||||
|
buf[i] = input.pop_front().expect("debug_input lost byte");
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > 0 {
|
||||||
|
return Ok(i);
|
||||||
|
} else {
|
||||||
|
unsafe { context::switch(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the `buffer` to the `file`
|
/// Write the `buffer` to the `file`
|
||||||
|
@ -30,6 +62,10 @@ impl Scheme for DebugScheme {
|
||||||
Ok(buffer.len())
|
Ok(buffer.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fsync(&mut self, file: usize) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Close the file `number`
|
/// Close the file `number`
|
||||||
fn close(&mut self, _file: usize) -> Result<()> {
|
fn close(&mut self, _file: usize) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
88
kernel/scheme/env.rs
Normal file
88
kernel/scheme/env.rs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
use collections::BTreeMap;
|
||||||
|
|
||||||
|
use syscall::{Error, Result};
|
||||||
|
use super::Scheme;
|
||||||
|
|
||||||
|
struct Handle {
|
||||||
|
data: &'static [u8],
|
||||||
|
seek: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EnvScheme {
|
||||||
|
next_id: usize,
|
||||||
|
files: BTreeMap<&'static [u8], &'static [u8]>,
|
||||||
|
handles: BTreeMap<usize, Handle>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnvScheme {
|
||||||
|
pub fn new() -> EnvScheme {
|
||||||
|
let mut files: BTreeMap<&'static [u8], &'static [u8]> = BTreeMap::new();
|
||||||
|
|
||||||
|
files.insert(b"HOME", b"initfs:");
|
||||||
|
files.insert(b"PWD", b"initfs:");
|
||||||
|
files.insert(b"COLUMNS", b"80");
|
||||||
|
files.insert(b"LINES", b"30");
|
||||||
|
|
||||||
|
EnvScheme {
|
||||||
|
next_id: 0,
|
||||||
|
files: files,
|
||||||
|
handles: BTreeMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scheme for EnvScheme {
|
||||||
|
fn open(&mut self, path: &[u8], _flags: usize) -> Result<usize> {
|
||||||
|
let data = self.files.get(path).ok_or(Error::NoEntry)?;
|
||||||
|
|
||||||
|
let id = self.next_id;
|
||||||
|
self.next_id += 1;
|
||||||
|
self.handles.insert(id, Handle {
|
||||||
|
data: data,
|
||||||
|
seek: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dup(&mut self, file: usize) -> Result<usize> {
|
||||||
|
let (data, seek) = {
|
||||||
|
let handle = self.handles.get(&file).ok_or(Error::BadFile)?;
|
||||||
|
(handle.data, handle.seek)
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = self.next_id;
|
||||||
|
self.next_id += 1;
|
||||||
|
self.handles.insert(id, Handle {
|
||||||
|
data: data,
|
||||||
|
seek: seek
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result<usize> {
|
||||||
|
let mut handle = self.handles.get_mut(&file).ok_or(Error::BadFile)?;
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
while i < buffer.len() && handle.seek < handle.data.len() {
|
||||||
|
buffer[i] = handle.data[handle.seek];
|
||||||
|
i += 1;
|
||||||
|
handle.seek += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, _file: usize, _buffer: &[u8]) -> Result<usize> {
|
||||||
|
Err(Error::NotPermitted)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fsync(&mut self, file: usize) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&mut self, file: usize) -> Result<()> {
|
||||||
|
self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(()))
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,6 +78,10 @@ impl Scheme for InitFsScheme {
|
||||||
Err(Error::NotPermitted)
|
Err(Error::NotPermitted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fsync(&mut self, file: usize) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn close(&mut self, file: usize) -> Result<()> {
|
fn close(&mut self, file: usize) -> Result<()> {
|
||||||
self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(()))
|
self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,15 @@ use spin::{Once, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
use syscall::{Error, Result};
|
use syscall::{Error, Result};
|
||||||
|
|
||||||
use self::debug::DebugScheme;
|
use self::debug::DebugScheme;
|
||||||
|
use self::env::EnvScheme;
|
||||||
use self::initfs::InitFsScheme;
|
use self::initfs::InitFsScheme;
|
||||||
|
|
||||||
/// Debug scheme
|
/// Debug scheme
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
|
|
||||||
|
/// Environmental variables
|
||||||
|
pub mod env;
|
||||||
|
|
||||||
/// InitFS scheme
|
/// InitFS scheme
|
||||||
pub mod initfs;
|
pub mod initfs;
|
||||||
|
|
||||||
|
@ -57,7 +61,7 @@ impl SchemeList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new context.
|
/// Create a new scheme.
|
||||||
pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Mutex<Box<Scheme + Send>>>) -> Result<&Arc<Mutex<Box<Scheme + Send>>>> {
|
pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Mutex<Box<Scheme + Send>>>) -> Result<&Arc<Mutex<Box<Scheme + Send>>>> {
|
||||||
if self.names.contains_key(&name) {
|
if self.names.contains_key(&name) {
|
||||||
return Err(Error::FileExists);
|
return Err(Error::FileExists);
|
||||||
|
@ -92,6 +96,7 @@ static SCHEMES: Once<RwLock<SchemeList>> = Once::new();
|
||||||
fn init_schemes() -> RwLock<SchemeList> {
|
fn init_schemes() -> RwLock<SchemeList> {
|
||||||
let mut list: SchemeList = SchemeList::new();
|
let mut list: SchemeList = SchemeList::new();
|
||||||
list.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme)))).expect("failed to insert debug: scheme");
|
list.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme)))).expect("failed to insert debug: scheme");
|
||||||
|
list.insert(Box::new(*b"env"), Arc::new(Mutex::new(Box::new(EnvScheme::new())))).expect("failed to insert env: scheme");
|
||||||
list.insert(Box::new(*b"initfs"), Arc::new(Mutex::new(Box::new(InitFsScheme::new())))).expect("failed to insert initfs: scheme");
|
list.insert(Box::new(*b"initfs"), Arc::new(Mutex::new(Box::new(InitFsScheme::new())))).expect("failed to insert initfs: scheme");
|
||||||
RwLock::new(list)
|
RwLock::new(list)
|
||||||
}
|
}
|
||||||
|
@ -128,6 +133,9 @@ pub trait Scheme {
|
||||||
/// Returns the number of bytes written
|
/// Returns the number of bytes written
|
||||||
fn write(&mut self, file: usize, buffer: &[u8]) -> Result<usize>;
|
fn write(&mut self, file: usize, buffer: &[u8]) -> Result<usize>;
|
||||||
|
|
||||||
|
/// Sync the file descriptor
|
||||||
|
fn fsync(&mut self, file: usize) -> Result<()>;
|
||||||
|
|
||||||
/// Close the file descriptor
|
/// Close the file descriptor
|
||||||
fn close(&mut self, file: usize) -> Result<()>;
|
fn close(&mut self, file: usize) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ pub enum Call {
|
||||||
Brk = 45,
|
Brk = 45,
|
||||||
/// Set process I/O privilege level
|
/// Set process I/O privilege level
|
||||||
Iopl = 110,
|
Iopl = 110,
|
||||||
|
/// Sync file descriptor
|
||||||
|
FSync = 118,
|
||||||
/// Clone process
|
/// Clone process
|
||||||
Clone = 120,
|
Clone = 120,
|
||||||
/// Yield to scheduler
|
/// Yield to scheduler
|
||||||
|
@ -55,6 +57,7 @@ impl Call {
|
||||||
41 => Ok(Call::Dup),
|
41 => Ok(Call::Dup),
|
||||||
45 => Ok(Call::Brk),
|
45 => Ok(Call::Brk),
|
||||||
110 => Ok(Call::Iopl),
|
110 => Ok(Call::Iopl),
|
||||||
|
118 => Ok(Call::FSync),
|
||||||
120 => Ok(Call::Clone),
|
120 => Ok(Call::Clone),
|
||||||
158 => Ok(Call::SchedYield),
|
158 => Ok(Call::SchedYield),
|
||||||
183 => Ok(Call::GetCwd),
|
183 => Ok(Call::GetCwd),
|
||||||
|
|
|
@ -120,3 +120,18 @@ pub fn dup(fd: usize) -> Result<usize> {
|
||||||
let result = scheme_mutex.lock().dup(file.number);
|
let result = scheme_mutex.lock().dup(file.number);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fsync(fd: usize) -> Result<usize> {
|
||||||
|
let file = {
|
||||||
|
let contexts = context::contexts();
|
||||||
|
let context_lock = contexts.current().ok_or(Error::NoProcess)?;
|
||||||
|
let context = context_lock.read();
|
||||||
|
let file = context.get_file(fd).ok_or(Error::BadFile)?;
|
||||||
|
file
|
||||||
|
};
|
||||||
|
|
||||||
|
let schemes = scheme::schemes();
|
||||||
|
let scheme_mutex = schemes.get(file.scheme).ok_or(Error::BadFile)?;
|
||||||
|
let result = scheme_mutex.lock().fsync(file.number).and(Ok(0));
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
|
||||||
Call::Dup => dup(b),
|
Call::Dup => dup(b),
|
||||||
Call::Brk => brk(b),
|
Call::Brk => brk(b),
|
||||||
Call::Iopl => iopl(b),
|
Call::Iopl => iopl(b),
|
||||||
|
Call::FSync => fsync(b),
|
||||||
Call::Clone => clone(b, stack),
|
Call::Clone => clone(b, stack),
|
||||||
Call::SchedYield => sched_yield(),
|
Call::SchedYield => sched_yield(),
|
||||||
Call::GetCwd => getcwd(validate_slice_mut(b as *mut u8, c)?)
|
Call::GetCwd => getcwd(validate_slice_mut(b as *mut u8, c)?)
|
||||||
|
|
Loading…
Reference in a new issue