#![no_std] use turkos_os_syscall_abi::syscall_abi::Errno; pub const VERSION: u64 = 2; pub const EXIT: u64 = 3; pub const ALLOC: u64 = 4; pub const FREE: u64 = 5; pub const PANIC_EXIT: i32 = 127; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Request { Exit(i32), Alloc { bytes: usize, alignment: usize }, Free(u64), } pub fn compatible(required: u64, available: u64) -> Result<(), Errno> { if !matches!(required, 1 | 2) || !matches!(available, 1 | 2) || required > available { return Err(Errno::NoSys); } Ok(()) } /// This separately named v2 wire contract does not extend the frozen v1 /// Dispatcher. It grants no owner, allocation or native SVC service by itself. pub fn decode(version: u64, number: u64, arguments: [u64; 6]) -> Result { if version != VERSION { return Err(Errno::NoSys); } match number { EXIT => { let code = arguments[0] as i32; if code as i64 as u64 != arguments[0] { return Err(Errno::Overflow); } Ok(Request::Exit(code)) } ALLOC => { let bytes = usize::try_from(arguments[0]).map_err(|_| Errno::Overflow)?; let alignment = usize::try_from(arguments[1]).map_err(|_| Errno::Overflow)?; if bytes == 0 || bytes > 4096 || !alignment.is_power_of_two() || alignment > 4096 { return Err(Errno::Invalid); } Ok(Request::Alloc { bytes, alignment }) } FREE if arguments[0] != 0 => Ok(Request::Free(arguments[0])), FREE => Err(Errno::Invalid), _ => Err(Errno::NoSys), } }