safa_api/syscalls/
mem.rs

1use core::ptr::NonNull;
2
3use safa_abi::errors::ErrorStatus;
4use safa_abi::mem::{MemMapFlags, RawMemMapConfig};
5
6use crate::syscalls::types::{IntoSyscallArg, Ri};
7
8use super::types::{OptionalPtrMut, RequiredPtr};
9use super::SyscallNum;
10
11impl IntoSyscallArg for MemMapFlags {
12    type RegResults = (usize,);
13    fn into_syscall_arg(self) -> Self::RegResults {
14        (unsafe { core::mem::transmute::<_, u8>(self) } as usize,)
15    }
16}
17
18define_syscall! {
19    SyscallNum::SysMemMap => {
20        /// See [`SyscallNum::SysMemMap`]
21        sysmem_map(memmap_config: RequiredPtr<RawMemMapConfig>, flags: MemMapFlags, out_res_id: OptionalPtrMut<Ri>, out_start_addr: OptionalPtrMut<NonNull<u8>>)
22    }
23}
24
25/// See [`SyscallNum::SysMemMap`] and [`RawMemMapConfig`]
26///
27/// You don't have to provide the [`MemMapFlags::MAP_RESOURCE`] flag, it is automatically provided if `resource_to_map` is Some
28/// # Returns
29/// the resource ID of the Tracked Mapping and the slice of bytes in the mapping
30pub fn map(
31    addr_hint: *const (),
32    page_count: usize,
33    guard_pages_count: usize,
34    resource_to_map: Option<Ri>,
35    resource_off: Option<isize>,
36    mut flags: MemMapFlags,
37) -> Result<(Ri, NonNull<[u8]>), ErrorStatus> {
38    let (ri, off) = if let Some(ri) = resource_to_map {
39        let off = resource_off.unwrap_or_default();
40        flags = flags | MemMapFlags::MAP_RESOURCE;
41        (ri, off)
42    } else {
43        (0, 0)
44    };
45
46    let conf = RawMemMapConfig {
47        resource_off: off,
48        resource_to_map: ri,
49        guard_pages_count,
50        page_count,
51        addr_hint,
52    };
53
54    let mut res_id_results = 0xAAAAAAAAAAAAAAAAusize;
55    let mut start_addr_results =
56        unsafe { NonNull::new_unchecked(0xAAAAAAAAAAAAAAAAusize as *mut u8) };
57    let (result_ri, result_start_addr) = unsafe {
58        err_from_u16!(
59            sysmem_map(
60                RequiredPtr::new_unchecked(&raw const conf as *mut _),
61                flags,
62                RequiredPtr::new(&raw mut res_id_results).into(),
63                RequiredPtr::new(&raw mut start_addr_results).into()
64            ),
65            (res_id_results, start_addr_results)
66        )?
67    };
68
69    // each Page is 4096 bytes
70    let len = page_count * 4096;
71    let slice = unsafe { core::slice::from_raw_parts_mut(result_start_addr.as_ptr(), len) };
72
73    unsafe { Ok((result_ri, NonNull::new_unchecked(slice))) }
74}