use core::mem::MaybeUninit;
use moa_uapi::{
error::{ERR_FAULT, ERR_INVAL, ERR_NO_RESOURCE, ERR_NOT_FOUND, ERR_PERM},
mem::MemSource,
space::{MapFlags, MapPerms, SpaceFlags, SpaceHandle, SpaceId, Uaddr},
sysnr::{
SYSNR_SPACE_CLOSE, SYSNR_SPACE_CREATE, SYSNR_SPACE_GET_ID, SYSNR_SPACE_MAP,
SYSNR_SPACE_PROTECT, SYSNR_SPACE_READ, SYSNR_SPACE_UNMAP, SYSNR_SPACE_WRITE,
},
};
pub type Result<T> = core::result::Result<T, SpaceError>;
define_syscall_error! {
pub enum SpaceError {
Perm = ERR_PERM,
NotFound = ERR_NOT_FOUND,
Inval = ERR_INVAL,
NoResource = ERR_NO_RESOURCE,
Fault = ERR_FAULT,
}
}
pub fn space_create(max_pages: u32, flags: SpaceFlags) -> Result<(SpaceHandle, SpaceId)> {
let mut id = MaybeUninit::<SpaceId>::uninit();
let ret = unsafe {
super::arch::syscall3(
SYSNR_SPACE_CREATE,
max_pages as usize,
flags.bits() as usize,
id.as_mut_ptr() as usize,
)
};
if ret < 0 {
Err(SpaceError::from_raw(ret))
} else {
Ok((SpaceHandle::from_raw(ret as u32), unsafe { id.assume_init() }))
}
}
pub fn space_close(space: SpaceHandle) -> Result<()> {
let ret = unsafe { super::arch::syscall1(SYSNR_SPACE_CLOSE, space.raw() as usize) };
if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}
pub fn space_map(
space: SpaceHandle,
vaddr: Uaddr,
source: Option<&MemSource>,
size: usize,
perms: MapPerms,
flags: MapFlags,
) -> Result<Uaddr> {
let source_ptr = match source {
Some(s) => s as *const MemSource as usize,
None => 0,
};
let ret = unsafe {
super::arch::syscall6(
SYSNR_SPACE_MAP,
space.raw() as usize,
vaddr.raw(),
source_ptr,
size,
perms.bits() as usize,
flags.bits() as usize,
)
};
if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(Uaddr::from_raw(ret as usize)) }
}
pub fn space_unmap(space: SpaceHandle, vaddr: Uaddr, size: usize) -> Result<()> {
let ret = unsafe {
super::arch::syscall3(SYSNR_SPACE_UNMAP, space.raw() as usize, vaddr.raw(), size)
};
if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}
pub fn space_protect(space: SpaceHandle, vaddr: Uaddr, size: usize, perms: MapPerms) -> Result<()> {
let ret = unsafe {
super::arch::syscall4(
SYSNR_SPACE_PROTECT,
space.raw() as usize,
vaddr.raw(),
size,
perms.bits() as usize,
)
};
if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}
pub fn space_write(space: SpaceHandle, vaddr: Uaddr, data: &[u8]) -> Result<()> {
let ret = unsafe {
super::arch::syscall4(
SYSNR_SPACE_WRITE,
space.raw() as usize,
vaddr.raw(),
data.as_ptr() as usize,
data.len(),
)
};
if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}
pub fn space_read(space: SpaceHandle, vaddr: Uaddr, buf: &mut [u8]) -> Result<()> {
let ret = unsafe {
super::arch::syscall4(
SYSNR_SPACE_READ,
space.raw() as usize,
vaddr.raw(),
buf.as_mut_ptr() as usize,
buf.len(),
)
};
if ret < 0 { Err(SpaceError::from_raw(ret)) } else { Ok(()) }
}
pub fn space_get_id(space: SpaceHandle) -> Result<SpaceId> {
let ret = unsafe { super::arch::syscall1(SYSNR_SPACE_GET_ID, space.raw() as usize) };
if ret < 0 {
Err(SpaceError::from_raw(ret))
} else {
Ok(SpaceId::from_raw(ret as usize))
}
}