diff --git a/ableos/src/rhai_shell/mod.rs b/ableos/src/rhai_shell/mod.rs index 20421428..aae557bc 100644 --- a/ableos/src/rhai_shell/mod.rs +++ b/ableos/src/rhai_shell/mod.rs @@ -13,6 +13,8 @@ use rhai::Engine; use spin::Lazy; use x86_64::instructions::interrupts::{disable, enable}; +pub const RHAISHELL_VERSION: &str = "0.1.0"; + pub static KEYBUFF: spin::Mutex> = spin::Mutex::new(Vec::new()); pub static CURRENT_DIR: Lazy> = Lazy::new(|| spin::Mutex::new("/".to_string())); @@ -25,12 +27,19 @@ pub fn shell() { let engine = engine_construction(); let mut scope = rhai::Scope::new(); + println!("Rhaishell v{}", RHAISHELL_VERSION); + let mut buf = String::new(); print!("> "); loop { match x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()) { Some('\n') => { + if buf == "quit" { + println!("Bye!"); + break; + } + match engine.eval_with_scope::(&mut scope, &buf) { Ok(o) => println!("{o}"), @@ -201,16 +210,12 @@ fn engine_construction() -> Engine { debug!("{} at {:?}: {}", src, pos, x); }); - engine.register_fn("ls", ls); - engine.register_fn("cat", echo_file); - engine.register_fn("cd", change_directory); engine.register_fn("afetch", afetch); engine.register_fn("set_hostname", set_hostname); engine.register_fn("shutdown", shutdown); engine.register_fn("peek", peek_memory); engine.register_fn("poke", poke_memory); engine.register_fn("sloop", sloop); - engine.register_fn("wasm", interp); engine.register_fn("log_dump", log_dump); engine diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs index aa1dd42e..21646344 100644 --- a/ableos/src/scratchpad.rs +++ b/ableos/src/scratchpad.rs @@ -1,7 +1,10 @@ use core::alloc::Layout; +use crate::encoding::bin; use crate::rhai_shell::shell; +use crate::wasm_jumploader::run_program; use acpi::{AcpiTables, PlatformInfo}; +use genfs::Fs; /// Experimental scratchpad for testing. pub fn scratchpad() { @@ -17,7 +20,7 @@ pub fn scratchpad() { info!("{:?}", node); } // acpi(); - shell(); + real_shell(); } pub fn pci_fun() {} @@ -61,3 +64,115 @@ impl acpi::AcpiHandler for AcpiStruct { todo!("unmap_physical_region"); } } + +pub fn real_shell() { + let _current_dir = "/".to_string(); + let current_user = "able".to_string(); + + let mut buf = String::new(); + print!("> "); + + loop { + match x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()) { + Some('\n') => { + // match engine.eval_with_scope::(&mut scope, &buf) { + // Ok(o) => println!("{o}"), + + // Err(e) => println!("Eval error: {e}"), + // }; + if !buf.is_empty() { + command_parser(current_user.clone(), buf.clone()); + } + + buf.clear(); + print!("> "); + } + Some('\u{0008}') => { + buf.pop(); + } + + Some('\u{0009}') => { + buf.push(' '); + buf.push(' '); + buf.push(' '); + buf.push(' '); + } + + Some(chr) => buf.push(chr), + None => (), + } + } +} +use crate::rhai_shell::KEYBUFF; + +pub fn command_parser(user: String, command: String) { + let fs = &*FILE_SYSTEM.lock(); + let mut iter = command.split_whitespace(); + + let bin_name = iter.next().unwrap(); + + if bin_name == "rhai" { + drop(fs); + shell(); + return; + } + + let home_exec_path = format!("/home/{}/bins/{}.wasm", user, bin_name); + let shared_exec_path = format!("/shared/bins/{}.wasm", bin_name); + let system_exec_path = format!("/system/bins/{}.wasm", bin_name); + + let home_exec_file = fs.open(&home_exec_path.as_bytes(), OpenOptions::new().read(true)); + let shared_exec_file = fs.open(&shared_exec_path.as_bytes(), OpenOptions::new().read(true)); + let system_exec_file = fs.open(&system_exec_path.as_bytes(), OpenOptions::new().read(true)); + + let mut in_home = false; + let mut in_shared = false; + let mut in_system = false; + + let mut binary_prog: Vec = vec![]; + + match home_exec_file { + Ok(file) => { + let ret = file.read_to_end(&mut binary_prog).unwrap(); + in_home = true; + } + + Err(error) => { + trace!("{:?}", error); + in_home = false; + } + } + match shared_exec_file { + Ok(file) => { + let ret = file.read_to_end(&mut binary_prog).unwrap(); + in_shared = true; + } + Err(error) => { + trace!("{:?}", error); + in_shared = false; + } + } + match system_exec_file { + Ok(file) => { + let ret = file.read_to_end(&mut binary_prog).unwrap(); + in_system = true; + } + + Err(error) => { + trace!("{:?}", error); + in_system = false; + } + } + + let args = iter.collect::>(); + println!("{:?}", args); + if in_home || in_shared || in_system { + run_program(binary_prog); + } else { + println!("No such binary: {}", bin_name); + error!("No such binary: {}", bin_name); + } +} + +use crate::filesystem::FILE_SYSTEM; +use genfs::OpenOptions; diff --git a/ableos/src/wasm_jumploader/mod.rs b/ableos/src/wasm_jumploader/mod.rs index 50b1fd85..00dcff39 100644 --- a/ableos/src/wasm_jumploader/mod.rs +++ b/ableos/src/wasm_jumploader/mod.rs @@ -98,4 +98,84 @@ pub fn interp() { } } -pub fn run_program() {} +pub fn run_program(program: Vec) { + // Load wasm binary and prepare it for instantiation. + let module = wasmi::Module::from_buffer(&program).expect("failed to load wasm"); + trace!("Loaded wasm binary"); + let imports = ImportsBuilder::new().with_resolver("env", &host_functions::HostExternals {}); + trace!("Created imports"); + + // Instantiate a module with empty imports and + // assert that there is no `start` function. + let instance = ModuleInstance::new(&module, &imports); // .expect("failed to instantiate wasm module") + + match instance { + Ok(inst) => { + let instance = inst.assert_no_start(); + let mut is_driver = false; + let _is_program = false; + let mut has_driver_entry = false; + let mut has_driver_exit = false; + let mut has_start = false; + + if let Some(_val) = instance.export_by_name("driver_entry") { + has_driver_entry = true; + } + + if let Some(_val) = instance.export_by_name("driver_exit") { + has_driver_exit = true; + } + + match instance.export_by_name("start") { + Some(_val) => { + trace!("Program start function found"); + has_start = true; + } + None => debug!("No start function found"), + } + + match instance.export_by_name("main") { + Some(_val) => { + trace!("Program main function found"); + has_start = false; + } + None => debug!("No main function found"), + } + + match (has_driver_entry, has_driver_exit) { + (true, true) => { + trace!("Valid driver entry and exit functions found"); + is_driver = true; + } + (true, false) => error!("Driver entry function found but no driver exit function"), + (false, true) => error!("Driver exit function found but no driver entry function"), + (false, false) => { + trace!("No driver entry or exit functions found"); + } + } + + if has_start && has_driver_entry { + error!( + "A program should not have both a start function and a driver entry function. It Will be treated as a program." + ); + } + + if has_start { + let ret = instance + .invoke_export("start", &[], &mut HostExternals {}) + .expect("failed to execute export"); + + println!("collected wasm return value: {:?}", ret); + } else if is_driver { + let ret = instance + .invoke_export("driver_entry", &[], &mut HostExternals {}) + .expect("failed to execute export"); + + println!("collected wasm return value: {:?}", ret); + } else { + println!("ERROR: No start or driver entry function found, invalid program"); + } + } + Err(err) => error!("{}", err), + } +} diff --git a/userland/root_fs/ext2.img b/userland/root_fs/ext2.img index 41ff01da..12e42077 100644 Binary files a/userland/root_fs/ext2.img and b/userland/root_fs/ext2.img differ