Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Executable loading #349

Merged
merged 6 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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/{}
Expand Down
3 changes: 1 addition & 2 deletions src/api/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
9 changes: 7 additions & 2 deletions src/api/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
1 change: 1 addition & 0 deletions src/sys/allocator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::sys;

use alloc::slice::SliceIndex;
use alloc::sync::Arc;
use alloc::vec;
Expand Down
4 changes: 4 additions & 0 deletions src/sys/fs/dir_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 12 additions & 5 deletions src/sys/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -242,26 +243,29 @@ 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(())
}
}

fn create(bin: &[u8]) -> Result<usize, ()> {
// 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;
Expand All @@ -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();
Expand Down
3 changes: 1 addition & 2 deletions src/sys/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions src/sys/syscall/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 26 additions & 7 deletions src/usr/shell.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -304,11 +306,28 @@ pub fn exec(cmd: &str, env: &mut BTreeMap<String, String>) -> 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
}
}
}
};
Expand Down