//! Environment call handling routines use { super::{mem::Memory, Vm}, crate::{arch, holeybytes::mem, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS}, alloc::string::String, log::{debug, error, info, trace, warn}, }; pub fn handler(vm: &mut Vm) { let r1 = vm.registers[1].cast::(); // debug!("Ecall number {:?}", r1); // trace!("Register dump: {:?}", vm.registers); match r1 { 0 => { // TODO: explode computer // hello world ecall for x in 0u64..=255 { vm.registers[x as usize] = x.into(); } } 1 => { // Make buffer let bounded = match vm.registers[2].cast::() { 0 => false, 1 => true, _ => { panic!("Bad"); } }; let length = vm.registers[3].cast::(); let mut buffs = IPC_BUFFERS.lock(); let abc; match bounded { false => { abc = IpcBuffer::new(false, 0); } true => { abc = IpcBuffer::new(true, length); } }; let buff_id = arch::hardware_random_u64(); buffs.insert(buff_id, abc); debug!("Buffer ID: {}", buff_id); vm.registers[1] = hbvm::value::Value(buff_id); } 2 => { // Delete buffer } 3 => { // Send a message to a buffer let r2 = vm.registers[2].cast::(); let r3 = vm.registers[3].cast::(); let r4 = vm.registers[4].cast::(); let buffer_id = r2; let mem_addr = r3; let length = r4 as usize; trace!("IPC address: {:?}", mem_addr); use alloc::vec::Vec; match buffer_id { 1 => match log_msg_handler(vm, mem_addr, length) { Ok(()) => {} Err(err) => log::error!("Improper log format"), }, 2 => match memory_msg_handler(vm, mem_addr, length) { Ok(()) => {} Err(err) => log::error!("Improper log format"), }, buffer_id => { let mut buffs = IPC_BUFFERS.lock(); match buffs.get_mut(&buffer_id) { Some(buff) => { let mut msg_vec = vec![]; for x in 0..(length as isize) { let xyz = mem_addr as *const u8; let value = unsafe { xyz.offset(x).read() }; msg_vec.push(value); } buff.push(msg_vec.clone()); info!( "Message {:?} has been sent to Buffer({})", msg_vec, buffer_id ); } None => { log::error!("Access of non-existent buffer {}", buffer_id) } } drop(buffs); } } } 4 => { let r2 = vm.registers[2].cast::(); let mut buffs = IPC_BUFFERS.lock(); let mut buff = buffs.get_mut(&r2).unwrap(); let msg = buff.pop(); info!("Recieve {:?} from Buffer({})", msg, r2); } 5 => { let r2 = vm.registers[2].cast::(); vm.registers[3] = hbvm::value::Value( unsafe { x86_in(r2 as u16) } as u64); } // 5 _ => { log::error!("Syscall unknown {:?}{:?}", r1, vm.registers); } } } unsafe fn x86_in(address: u16) -> u32{ x86_64::instructions::port::Port::new(address).read() } unsafe fn x86_out(address: u16, value: u32){ x86_64::instructions::port::Port::new(address).write(value); } fn log_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> { // let message_length = 8 + 8 + 8; // log::info!("Mem Addr 0x{:x?} length {}", mem_addr, length); let mut msg_vec = vec![]; for x in 0..(length as isize) { let xyz = mem_addr as *const u8; let value = unsafe { xyz.offset(x).read() }; // info!("{} - 0x{:x?} - {}", value, value, value as char); msg_vec.push(value); } let log_level = msg_vec.pop().unwrap(); match String::from_utf8(msg_vec) { Ok (strr) => { // use LogLevel::*; let ll = match log_level { 0 | 48 => error!("{}", strr), 1 | 49 => warn!("{}", strr), 2 | 50 => info!("{}", strr), 3 | 51 => debug!("{}", strr), 4 | 52 => trace!("{}", strr), _ => { return Err(LogError::InvalidLogFormat); } }; } Err(e) => { error!("{:?}", e); } } Ok(()) } #[derive(Debug)] pub enum LogError { InvalidLogFormat, } use {alloc::vec, log::Record}; fn memory_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> { let mut val = alloc::vec::Vec::new(); for _ in 0..4096 { val.push(0); } info!("Block address: {:?}", val.as_ptr()); vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64); vm.registers[2] = hbvm::value::Value(4096); Ok(()) }