diff --git a/Makefile b/Makefile index b90f836af..d4dd066ca 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,10 @@ export MOROS_KEYBOARD = $(keyboard) # Build userspace binaries user-nasm: basename -s .s dsk/src/bin/*.s | xargs -I {} \ - nasm dsk/src/bin/{}.s -o dsk/bin/{} + nasm dsk/src/bin/{}.s -o dsk/bin/{}.tmp + basename -s .s dsk/src/bin/*.s | xargs -I {} \ + sh -c "printf '\x7FBIN' | cat - dsk/bin/{}.tmp > dsk/bin/{}" + rm dsk/bin/*.tmp user-rust: basename -s .rs src/bin/*.rs | xargs -I {} \ touch dsk/bin/{} diff --git a/src/api/process.rs b/src/api/process.rs index 7a168e3d7..641f3f538 100644 --- a/src/api/process.rs +++ b/src/api/process.rs @@ -2,8 +2,7 @@ use crate::api::syscall; pub fn spawn(path: &str) -> Result<(), ()> { if syscall::info(path).is_some() { - syscall::spawn(path); - return Ok(()); + return syscall::spawn(path); } Err(()) } diff --git a/src/api/syscall.rs b/src/api/syscall.rs index 89a08df87..708341bb7 100644 --- a/src/api/syscall.rs +++ b/src/api/syscall.rs @@ -80,10 +80,15 @@ pub fn close(handle: usize) { unsafe { syscall!(CLOSE, handle as usize) }; } -pub fn spawn(path: &str) { +pub fn spawn(path: &str) -> Result<(), ()> { let ptr = path.as_ptr() as usize; let len = path.len() as usize; - unsafe { syscall!(SPAWN, ptr, len) }; + let res = unsafe { syscall!(SPAWN, ptr, len) } as isize; + if res.is_negative() { + Err(()) + } else { + Ok(()) + } } pub fn reboot() { diff --git a/src/sys/allocator.rs b/src/sys/allocator.rs index 4043100f4..ce474e5f1 100644 --- a/src/sys/allocator.rs +++ b/src/sys/allocator.rs @@ -1,4 +1,5 @@ use crate::sys; + use alloc::slice::SliceIndex; use alloc::sync::Arc; use alloc::vec; diff --git a/src/sys/fs/dir_entry.rs b/src/sys/fs/dir_entry.rs index a146ce180..cac941b48 100644 --- a/src/sys/fs/dir_entry.rs +++ b/src/sys/fs/dir_entry.rs @@ -117,6 +117,10 @@ impl FileInfo { self.name.clone() } + pub fn kind(&self) -> FileType { + self.kind + } + // TODO: Duplicated from dir entry pub fn is_dir(&self) -> bool { self.kind == FileType::Dir diff --git a/src/sys/process.rs b/src/sys/process.rs index 0a50fd6b4..6746045e5 100644 --- a/src/sys/process.rs +++ b/src/sys/process.rs @@ -209,7 +209,8 @@ pub struct Registers { pub rax: usize, } -const ELF_MAGIC: [u8; 4] = [0x74, b'E', b'L', b'F']; +const ELF_MAGIC: [u8; 4] = [0x7F, b'E', b'L', b'F']; +const BIN_MAGIC: [u8; 4] = [0x7F, b'B', b'I', b'N']; #[derive(Clone, Debug)] pub struct Process { @@ -242,13 +243,16 @@ impl Process { } } - pub fn spawn(bin: &[u8]) { + pub fn spawn(bin: &[u8]) -> Result<(), ()> { if let Ok(pid) = Self::create(bin) { let proc = { let table = PROCESS_TABLE.read(); table[pid].clone() }; proc.exec(); + Ok(()) + } else { + Err(()) } } @@ -256,12 +260,12 @@ impl Process { // Allocate some memory for the code and the stack of the program let code_size = 1 * PAGE_SIZE; let code_addr = CODE_ADDR.fetch_add(code_size, Ordering::SeqCst); - sys::allocator::alloc_pages(code_addr, code_size); let mut entry_point = 0; let code_ptr = code_addr as *mut u8; if bin[0..4] == ELF_MAGIC { // ELF binary if let Ok(obj) = object::File::parse(bin) { + sys::allocator::alloc_pages(code_addr, code_size); entry_point = obj.entry(); for segment in obj.segments() { let addr = segment.address() as usize; @@ -275,13 +279,16 @@ impl Process { } } } - } else { // Raw binary - for (i, op) in bin.iter().enumerate() { + } else if bin[0..4] == BIN_MAGIC { // Flat binary + sys::allocator::alloc_pages(code_addr, code_size); + for (i, op) in bin.iter().skip(4).enumerate() { unsafe { let ptr = code_ptr.add(i); core::ptr::write(ptr, *op); } } + } else { + return Err(()); } let mut table = PROCESS_TABLE.write(); diff --git a/src/sys/syscall/mod.rs b/src/sys/syscall/mod.rs index 754813d49..3dc6a6b28 100644 --- a/src/sys/syscall/mod.rs +++ b/src/sys/syscall/mod.rs @@ -67,8 +67,7 @@ pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { let ptr = sys::process::ptr_from_addr(arg1 as u64); let len = arg2; let path = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(ptr, len)) }; - service::spawn(path); - 0 + service::spawn(path) as usize } number::STOP => { service::stop(arg1) diff --git a/src/sys/syscall/service.rs b/src/sys/syscall/service.rs index ba97bb80a..ecbfb52e1 100644 --- a/src/sys/syscall/service.rs +++ b/src/sys/syscall/service.rs @@ -89,8 +89,9 @@ pub fn spawn(path: &str) -> isize { let mut buf = vec![0; file.size()]; if let Ok(bytes) = file.read(&mut buf) { buf.resize(bytes, 0); - Process::spawn(&buf); - return 0; + if Process::spawn(&buf).is_ok() { + return 0; + } } } -1 diff --git a/src/usr/shell.rs b/src/usr/shell.rs index 5e6f2ee12..fa3fbf3f0 100644 --- a/src/usr/shell.rs +++ b/src/usr/shell.rs @@ -1,8 +1,10 @@ use crate::{api, sys, usr}; +use crate::api::console::Style; use crate::api::fs; -use crate::api::regex::Regex; use crate::api::prompt::Prompt; -use crate::api::console::Style; +use crate::api::regex::Regex; +use crate::api::syscall; +use crate::sys::fs::FileType; use alloc::collections::btree_map::BTreeMap; use alloc::format; @@ -304,11 +306,28 @@ pub fn exec(cmd: &str, env: &mut BTreeMap) -> ExitCode { "2048" => usr::pow::main(&args), "time" => usr::time::main(&args), "proc" => proc(&args), - cmd => { - if api::process::spawn(cmd).is_ok() { - ExitCode::CommandSuccessful - } else { - ExitCode::CommandUnknown + _ => { + let mut path = fs::realpath(args[0]); + if path.len() > 1 { + path = path.trim_end_matches('/').into(); + } + match syscall::info(&path).map(|info| info.kind()) { + Some(FileType::Dir) => { + sys::process::set_dir(&path); + ExitCode::CommandSuccessful + } + Some(FileType::File) => { + if api::process::spawn(&path).is_ok() { + ExitCode::CommandSuccessful + } else { + error!("'{}' is not executable", path); + ExitCode::CommandError + } + } + _ => { + error!("Could not execute '{}'", cmd); + ExitCode::CommandUnknown + } } } };