diff --git a/kernel/lib.rs b/kernel/lib.rs index 08c9944..836aa19 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -133,11 +133,23 @@ pub extern fn kmain() { let pid = syscall::getpid(); println!("BSP: {:?}", pid); - assert_eq!(syscall::open("debug:".as_bytes(), 0), Ok(0)); - assert_eq!(syscall::open("debug:".as_bytes(), 0), Ok(1)); - assert_eq!(syscall::open("debug:".as_bytes(), 0), Ok(2)); + assert_eq!(syscall::open(b"debug:", 0), Ok(0)); + assert_eq!(syscall::open(b"debug:", 0), Ok(1)); + assert_eq!(syscall::open(b"debug:", 0), Ok(2)); - let elf = elf::Elf::from(include_bytes!("../build/userspace/init")).expect("could not load elf"); + let init_file = syscall::open(b"initfs:init", 0).expect("failed to open initfs:init"); + let mut init_data = collections::Vec::new(); + loop { + let mut buf = [0; 65536]; + let count = syscall::read(init_file, &mut buf).expect("failed to read initfs:init"); + if count > 0 { + init_data.extend_from_slice(&buf[..count]); + } else { + break; + } + } + + let elf = elf::Elf::from(&init_data).expect("could not load elf"); elf.run(); /* @@ -163,12 +175,9 @@ pub extern fn kmain_ap(id: usize) { let pid = syscall::getpid(); println!("AP {}: {:?}", id, pid); - assert_eq!(syscall::open("debug:".as_bytes(), 0), Ok(0)); - assert_eq!(syscall::open("debug:".as_bytes(), 0), Ok(1)); - assert_eq!(syscall::open("debug:".as_bytes(), 0), Ok(2)); - - let elf = elf::Elf::from(include_bytes!("../build/userspace/init")).expect("could not load elf"); - elf.run(); + assert_eq!(syscall::open(b"debug:", 0), Ok(0)); + assert_eq!(syscall::open(b"debug:", 0), Ok(1)); + assert_eq!(syscall::open(b"debug:", 0), Ok(2)); loop { unsafe { interrupt::enable_and_halt() } diff --git a/kernel/scheme/initfs.rs b/kernel/scheme/initfs.rs new file mode 100644 index 0000000..145f7f6 --- /dev/null +++ b/kernel/scheme/initfs.rs @@ -0,0 +1,70 @@ +use collections::BTreeMap; + +use syscall::{Error, Result}; +use super::Scheme; + +struct Handle { + data: &'static [u8], + seek: usize +} + +pub struct InitFsScheme { + next_id: usize, + files: BTreeMap<&'static [u8], &'static [u8]>, + handles: BTreeMap +} + +impl InitFsScheme { + pub fn new() -> InitFsScheme { + let mut files: BTreeMap<&'static [u8], &'static [u8]> = BTreeMap::new(); + + files.insert(b"init", include_bytes!("../../build/userspace/init")); + + InitFsScheme { + next_id: 0, + files: files, + handles: BTreeMap::new() + } + } +} + +impl Scheme for InitFsScheme { + fn open(&mut self, path: &[u8], _flags: usize) -> Result { + 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) + } + + /// Read the file `number` into the `buffer` + /// + /// Returns the number of bytes read + fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result { + 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) + } + + /// Write the `buffer` to the `file` + /// + /// Returns the number of bytes written + fn write(&mut self, _file: usize, _buffer: &[u8]) -> Result { + Err(Error::NotPermitted) + } + + /// Close the file `number` + fn close(&mut self, file: usize) -> Result<()> { + self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(())) + } +} diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index 99a50a1..ef86570 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -16,10 +16,14 @@ use spin::{Once, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; use syscall::{Error, Result}; use self::debug::DebugScheme; +use self::initfs::InitFsScheme; /// Debug scheme pub mod debug; +/// InitFS scheme +pub mod initfs; + /// Limit on number of schemes pub const SCHEME_MAX_SCHEMES: usize = 65536; @@ -88,6 +92,7 @@ static SCHEMES: Once> = Once::new(); fn init_schemes() -> RwLock { 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"initfs"), Arc::new(Mutex::new(Box::new(InitFsScheme::new())))).expect("failed to insert initfs: scheme"); RwLock::new(list) }