Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
Graham Kelly | 4e2819f025 | ||
Graham Kelly | 2a7f15239e | ||
Graham Kelly | 4f1e82e70a | ||
Graham Kelly | 4c2e52c9bb | ||
Graham Kelly | 2b5076baa7 | ||
Graham Kelly | 9975d08054 |
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -2,6 +2,10 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ablewasi"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
|
|
|
@ -2,4 +2,4 @@ resolver = "2"
|
||||||
|
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["kernel", "repbuild"]
|
members = ["kernel", "repbuild", "user/ablewasi"]
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
use crate::arch::hardware_random_u64;
|
use spin::Lazy;
|
||||||
use alloc::vec::Vec;
|
|
||||||
use core::fmt::{self, Formatter};
|
use spin::{Mutex};
|
||||||
|
|
||||||
|
use crate::interp::objects::{Object,HandleTarget, TARGETS};
|
||||||
|
|
||||||
|
use {
|
||||||
|
crate::arch::hardware_random_u64,
|
||||||
|
alloc::vec::Vec,
|
||||||
|
core::fmt::{self, Formatter},
|
||||||
|
};
|
||||||
|
|
||||||
|
use alloc::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
};
|
||||||
#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)]
|
||||||
pub struct OSHandle {
|
pub struct OSHandle {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
|
@ -19,21 +31,30 @@ impl OSHandle {
|
||||||
|
|
||||||
#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)]
|
||||||
pub struct Handle {
|
pub struct Handle {
|
||||||
id: OSHandle,
|
pub id: OSHandle,
|
||||||
perms: Permissions,
|
pub perms: Permissions,
|
||||||
|
pub r#ref: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handle {
|
impl Handle {
|
||||||
pub fn new() -> Handle {
|
pub fn new(r#ref: usize) -> Handle {
|
||||||
Handle {
|
Handle {
|
||||||
id: OSHandle::random_new(),
|
id: OSHandle::random_new(),
|
||||||
perms: Permissions::new(),
|
perms: Permissions::new(),
|
||||||
|
r#ref,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_u64(&self) -> u64 {
|
pub fn as_u64(&self) -> u64 {
|
||||||
self.id.id
|
self.id.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get<R, F: for<'a> FnOnce(Option<&'a mut HandleTarget>) -> R>(&self, f: F) -> R {
|
||||||
|
let l = TARGETS;
|
||||||
|
let mut olock = l.lock();
|
||||||
|
let a = olock.get_mut(self.r#ref).and_then(|a| a.as_mut());
|
||||||
|
return f(a);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Handle {
|
impl fmt::Display for Handle {
|
||||||
|
@ -57,3 +78,8 @@ impl Permissions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const GLOBALS: Lazy<Mutex<BTreeMap<[u64; 4], Handle>>> = Lazy::new(|| {
|
||||||
|
let mut globals = BTreeMap::new();
|
||||||
|
Mutex::new(globals)
|
||||||
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use {
|
use {
|
||||||
crate::interp::{HFIDT, OBJECTS},
|
crate::interp::{HFIDT, TARGETS},
|
||||||
alloc::string::String,
|
alloc::string::String,
|
||||||
log::trace,
|
log::trace,
|
||||||
wasmi::{Caller, TypedFunc},
|
wasmi::{Caller, TypedFunc},
|
||||||
|
@ -34,7 +34,14 @@ pub fn host_register_idt_handler(
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::interp::Handle;
|
use crate::{
|
||||||
|
arch::hardware_random_u64,
|
||||||
|
handle::GLOBALS,
|
||||||
|
interp::{
|
||||||
|
objects::{HandleTarget, Object},
|
||||||
|
Handle,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn host_make_object(
|
pub fn host_make_object(
|
||||||
mut caller: Caller<'_, HostState>,
|
mut caller: Caller<'_, HostState>,
|
||||||
|
@ -54,17 +61,13 @@ pub fn host_make_object(
|
||||||
name.push(ch);
|
name.push(ch);
|
||||||
}
|
}
|
||||||
trace!("Object Name {}", name);
|
trace!("Object Name {}", name);
|
||||||
let hand = Handle::new();
|
let binding = TARGETS;
|
||||||
{
|
let mut olock = binding.lock();
|
||||||
let binding = OBJECTS;
|
let hand = Handle::new(olock.len());
|
||||||
let mut olock = binding.lock();
|
let obj = xml::XMLElement::new(name);
|
||||||
let obj = xml::XMLElement::new(name);
|
|
||||||
|
|
||||||
olock.push(Some(obj))
|
olock.push(Some(HandleTarget::Object(Object { xml: obj })));
|
||||||
}
|
caller.data_mut().add_handle(hand).try_into().unwrap()
|
||||||
caller.data_mut().handles.push(hand);
|
|
||||||
// hand.into()
|
|
||||||
hand.as_u64().try_into().unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type WFIDT = TypedFunc<(), ()>;
|
pub type WFIDT = TypedFunc<(), ()>;
|
||||||
|
@ -74,3 +77,33 @@ fn get_fn_from_wc(wc: WasmContext, function_name: String) -> WFIDT {
|
||||||
.get_typed_func(wc.store, &function_name)
|
.get_typed_func(wc.store, &function_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn host_make_global(mut caller: Caller<'_, HostState>, h: i64) -> (u64, u64, u64, u64) {
|
||||||
|
let binding = GLOBALS;
|
||||||
|
let Some(hand): Option<&mut Option<Handle>> = caller.data_mut().handles.get_mut(h as usize) else {
|
||||||
|
return (0,0,0,0);
|
||||||
|
};
|
||||||
|
let Some(t) = hand.take() else {
|
||||||
|
return (0,0,0,0);
|
||||||
|
};
|
||||||
|
let a = [hardware_random_u64(); 4];
|
||||||
|
let mut l = binding.lock();
|
||||||
|
l.insert(a, t);
|
||||||
|
return (a[0], a[1], a[2], a[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn host_take_global(mut caller: Caller<'_, HostState>, a: u64, b: u64, c: u64, d: u64) -> i64 {
|
||||||
|
let binding = GLOBALS;
|
||||||
|
let mut l = binding.lock();
|
||||||
|
let mut j: [u64; 4] = [0u64; 4];
|
||||||
|
j[0] = a;
|
||||||
|
j[1] = b;
|
||||||
|
j[2] = c;
|
||||||
|
j[3] = d;
|
||||||
|
let Some(m) = l.remove::<[u64; 4]>({
|
||||||
|
&j
|
||||||
|
}) else{
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
caller.data_mut().add_handle(m) as i64
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
mod host_functions;
|
mod host_functions;
|
||||||
mod objects;
|
pub mod objects;
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
handle::{self, Handle},
|
handle::{self, Handle},
|
||||||
interp::{host_functions::host_make_object, objects::OBJECTS},
|
interp::{host_functions::host_make_object, objects::TARGETS},
|
||||||
},
|
},
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
hashbrown::HashMap,
|
hashbrown::HashMap,
|
||||||
|
@ -13,7 +13,12 @@ use {
|
||||||
xml::XMLElement,
|
xml::XMLElement,
|
||||||
};
|
};
|
||||||
// Seperate use statement
|
// Seperate use statement
|
||||||
use alloc::vec;
|
use {
|
||||||
|
alloc::{fmt::format, format, vec},
|
||||||
|
wasmi::Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
use self::objects::HandleTarget;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
||||||
|
@ -94,7 +99,20 @@ pub fn wasm() -> Result<(), wasmi::Error> {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct HostState {
|
pub struct HostState {
|
||||||
handles: Vec<Handle>,
|
handles: Vec<Option<Handle>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HostState {
|
||||||
|
pub fn add_handle(&mut self, hand: Handle) -> usize {
|
||||||
|
for (i, h) in self.handles.iter_mut().enumerate() {
|
||||||
|
if let None = h {
|
||||||
|
*h = Some(hand);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.handles.push(Some(hand));
|
||||||
|
return (self.handles.len() - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_memory_address(caller: Caller<'_, HostState>, address: i32) -> i32 {
|
pub fn read_memory_address(caller: Caller<'_, HostState>, address: i32) -> i32 {
|
||||||
|
@ -104,27 +122,60 @@ pub fn read_memory_address(caller: Caller<'_, HostState>, address: i32) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn host_read_object_attribute(
|
pub fn host_read_object_attribute(
|
||||||
caller: Caller<'_, HostState>,
|
mut caller: Caller<'_, HostState>,
|
||||||
handle: i64,
|
handle: i64,
|
||||||
address_start: i32,
|
address_start: i32,
|
||||||
length_of_string: i32,
|
length_of_string: i32,
|
||||||
) -> (i32, i32) {
|
) -> (i32, i32) {
|
||||||
{
|
let binding = TARGETS;
|
||||||
let binding = OBJECTS;
|
let mut olock = binding.lock();
|
||||||
let mut olock = binding.lock();
|
|
||||||
|
|
||||||
// olock.get(&handle);
|
// olock.get(&handle);
|
||||||
}
|
|
||||||
|
|
||||||
let mem = caller.get_export("memory").unwrap().into_memory().unwrap();
|
let mem = caller.get_export("memory").unwrap().into_memory().unwrap();
|
||||||
let mem_array = mem.data(&caller);
|
let mem_array = mem.data_mut(&mut caller);
|
||||||
let mut name = String::new();
|
let mut name = String::new();
|
||||||
for i in address_start..(address_start + length_of_string) {
|
for i in address_start..(address_start + length_of_string) {
|
||||||
let ch = mem_array[i as usize] as char;
|
let ch = mem_array[i as usize] as char;
|
||||||
name.push(ch);
|
name.push(ch);
|
||||||
}
|
}
|
||||||
|
let Some(Some(a)) = caller.data().handles.get(handle as usize) else {
|
||||||
|
return (0,0);
|
||||||
|
};
|
||||||
|
let Some(Some(HandleTarget::Object(o))) = olock.get(a.r#ref) else{
|
||||||
|
return (0,0);
|
||||||
|
};
|
||||||
|
let Some(r) = o.xml.attributes.iter().find(|a|{
|
||||||
|
let f = format!("{:?}",a);
|
||||||
|
f.contains(&format!("Attribute{{ name: \"{}",name))
|
||||||
|
})else{
|
||||||
|
return (0,0);
|
||||||
|
};
|
||||||
|
let f = format!("{:?}", r);
|
||||||
|
let p = format!("Attribute{{ name: \"{}\", value: \"", name);
|
||||||
|
let s = format!("\" }}");
|
||||||
|
let h = f.replace(&p, "").replace(&s, "");
|
||||||
|
|
||||||
(0, 0)
|
let i = vec![Value::I32(h.len().try_into().unwrap())];
|
||||||
|
let mut o = vec![Value::I32(0)];
|
||||||
|
|
||||||
|
let a = caller
|
||||||
|
.get_export("malloc")
|
||||||
|
.unwrap()
|
||||||
|
.into_func()
|
||||||
|
.unwrap()
|
||||||
|
.call(&mut caller, &i, &mut o);
|
||||||
|
let mem_array = mem.data_mut(&mut caller);
|
||||||
|
|
||||||
|
let Value::I32(a) = o[0] else{
|
||||||
|
panic!("invalid malloc");
|
||||||
|
};
|
||||||
|
|
||||||
|
for (s, b) in h.clone().into_bytes().iter().enumerate() {
|
||||||
|
mem_array[(a as usize) + s] = *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
(a, h.len().try_into().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_wasm_context(bytes: Vec<u8>) -> Result<WasmContext, wasmi::Error> {
|
pub fn build_wasm_context(bytes: Vec<u8>) -> Result<WasmContext, wasmi::Error> {
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
use alloc::vec;
|
use alloc::{vec, vec::Vec, collections::BTreeMap};
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
use spin::{Lazy, Mutex};
|
use spin::{Lazy, Mutex};
|
||||||
|
|
||||||
pub type HostObjects = Vec<Option<xml::XMLElement>>;
|
use crate::handle::Handle;
|
||||||
|
|
||||||
pub const OBJECTS: Lazy<Mutex<HostObjects>> = Lazy::new(|| {
|
pub struct Object{
|
||||||
|
pub xml: xml::XMLElement
|
||||||
|
}
|
||||||
|
pub enum HandleTarget{
|
||||||
|
Object(Object)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type HostTargets = Vec<Option<HandleTarget>>;
|
||||||
|
|
||||||
|
pub const TARGETS: Lazy<Mutex<HostTargets>> = Lazy::new(|| {
|
||||||
let mut obj = vec![];
|
let mut obj = vec![];
|
||||||
Mutex::new(obj)
|
Mutex::new(obj)
|
||||||
});
|
});
|
||||||
|
|
8
user/ablewasi/Cargo.toml
Normal file
8
user/ablewasi/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "ablewasi"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
36
user/ablewasi/src/api.rs
Normal file
36
user/ablewasi/src/api.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use crate::sys;
|
||||||
|
|
||||||
|
pub struct Object{
|
||||||
|
pub id: i64
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Object{
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe{
|
||||||
|
sys::drop_object(self.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object{
|
||||||
|
pub fn to_global(self) -> [u64; 4]{
|
||||||
|
let b = unsafe {
|
||||||
|
sys::make_global(self.id).into()
|
||||||
|
};
|
||||||
|
core::mem::forget(self);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_global(a: [u64; 4]) -> Object{
|
||||||
|
return Object{id: unsafe {
|
||||||
|
sys::take_global(a.into())
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(name: &str) -> Object{
|
||||||
|
return Object{id: unsafe {
|
||||||
|
let a = name.as_ptr();
|
||||||
|
sys::create_object(a, name.len() as i32)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
}
|
8
user/ablewasi/src/lib.rs
Normal file
8
user/ablewasi/src/lib.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
pub mod sys;
|
||||||
|
pub mod api;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
}
|
29
user/ablewasi/src/sys.rs
Normal file
29
user/ablewasi/src/sys.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ROAResult(*const u8,i32);
|
||||||
|
|
||||||
|
pub type LocalObject = i64;
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct GlobalObject(u64,u64,u64,u64);
|
||||||
|
|
||||||
|
impl From<[u64;4]> for GlobalObject {
|
||||||
|
fn from(value: [u64;4]) -> Self {
|
||||||
|
GlobalObject(value[0], value[1], value[2], value[3])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<GlobalObject> for [u64; 4]{
|
||||||
|
fn from(value: GlobalObject) -> Self {
|
||||||
|
let GlobalObject(a,b,c,d) = value;
|
||||||
|
[a,b,c,d]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"{
|
||||||
|
pub fn create_object(a: *const u8, b: i32) -> LocalObject;
|
||||||
|
pub fn read_object_attribute(a: LocalObject, b: *const i8, c: i32) -> ROAResult;
|
||||||
|
pub fn take_global(a: GlobalObject) -> LocalObject;
|
||||||
|
pub fn make_global(a: LocalObject) -> GlobalObject;
|
||||||
|
pub fn drop_object(a: LocalObject);
|
||||||
|
}
|
Loading…
Reference in a new issue