safa_api/syscalls/
mod.rs

1//! This module exposes SafaOS's syscalls and their rust counterparts
2
3use crate::raw::io::DirEntry;
4
5use super::errors::ErrorStatus;
6
7#[cfg(not(feature = "rustc-dep-of-std"))]
8extern crate alloc;
9use super::raw::io::FileAttr;
10use super::raw::{RawSlice, RawSliceMut};
11use core::arch::asm;
12pub use safa_abi::syscalls::SyscallTable as SyscallNum;
13
14macro_rules! err_from_u16 {
15    ($result:expr) => {
16        $result.into_result()
17    };
18    ($result:expr, $ok:expr) => {
19        err_from_u16!($result).map(|()| $ok)
20    };
21}
22
23pub(crate) use err_from_u16;
24
25#[doc(hidden)]
26#[inline(always)]
27pub fn syscall0<const NUM: u16>() -> SyscallResult {
28    let result: u16;
29    unsafe {
30        #[cfg(target_arch = "x86_64")]
31        asm!(
32            "int 0x80",
33            in("rax") NUM as usize,
34            lateout("rax") result,
35        );
36        #[cfg(target_arch = "aarch64")]
37        asm!(
38            "svc #{num}",
39            num = const NUM,
40            lateout("x0") result
41        );
42        core::mem::transmute(result)
43    }
44}
45
46#[doc(hidden)]
47#[inline(always)]
48pub fn syscall1<const NUM: u16>(arg1: usize) -> SyscallResult {
49    let result: u16;
50    unsafe {
51        #[cfg(target_arch = "x86_64")]
52        asm!(
53            "int 0x80",
54            in("rax") NUM as usize,
55            in("rdi") arg1,
56            lateout("rax") result,
57        );
58        #[cfg(target_arch = "aarch64")]
59        asm!(
60            "svc #{num}",
61            num = const NUM,
62            in("x0") arg1,
63            lateout("x0") result
64        );
65        core::mem::transmute(result)
66    }
67}
68
69#[doc(hidden)]
70#[inline(always)]
71pub fn syscall2<const NUM: u16>(arg1: usize, arg2: usize) -> SyscallResult {
72    let result: u16;
73    unsafe {
74        #[cfg(target_arch = "x86_64")]
75        asm!(
76            "int 0x80",
77            in("rax") NUM as usize,
78            in("rdi") arg1,
79            in("rsi") arg2,
80            lateout("rax") result,
81        );
82        #[cfg(target_arch = "aarch64")]
83        asm!(
84            "svc #{num}",
85            num = const NUM,
86            in("x0") arg1,
87            in("x1") arg2,
88            lateout("x0") result
89        );
90        core::mem::transmute(result)
91    }
92}
93
94#[doc(hidden)]
95#[inline(always)]
96pub fn syscall3<const NUM: u16>(arg1: usize, arg2: usize, arg3: usize) -> SyscallResult {
97    let result: u16;
98    unsafe {
99        #[cfg(target_arch = "x86_64")]
100        asm!(
101            "int 0x80",
102            in("rax") NUM as usize,
103            in("rdi") arg1,
104            in("rsi") arg2,
105            in("rdx") arg3,
106            lateout("rax") result,
107        );
108        #[cfg(target_arch = "aarch64")]
109        asm!(
110            "svc #{num}",
111            num = const NUM,
112            in("x0") arg1,
113            in("x1") arg2,
114            in("x2") arg3,
115            lateout("x0") result
116        );
117        core::mem::transmute(result)
118    }
119}
120
121#[doc(hidden)]
122#[inline(always)]
123pub fn syscall4<const NUM: u16>(
124    arg1: usize,
125    arg2: usize,
126    arg3: usize,
127    arg4: usize,
128) -> SyscallResult {
129    let result: u16;
130    unsafe {
131        #[cfg(target_arch = "x86_64")]
132        asm!(
133            "int 0x80",
134            in("rax") NUM as usize,
135            in("rdi") arg1,
136            in("rsi") arg2,
137            in("rdx") arg3,
138            in("rcx") arg4,
139            lateout("rax") result,
140        );
141
142        #[cfg(target_arch = "aarch64")]
143        asm!(
144            "svc #{num}",
145            num = const NUM,
146            in("x0") arg1,
147            in("x1") arg2,
148            in("x2") arg3,
149            in("x3") arg4,
150            lateout("x0") result
151        );
152        core::mem::transmute(result)
153    }
154}
155
156#[doc(hidden)]
157#[inline(always)]
158pub fn syscall5<const NUM: u16>(
159    arg1: usize,
160    arg2: usize,
161    arg3: usize,
162    arg4: usize,
163    arg5: usize,
164) -> SyscallResult {
165    let result: u16;
166    unsafe {
167        #[cfg(target_arch = "x86_64")]
168        asm!(
169            "int 0x80",
170            in("rax") NUM as usize,
171            in("rdi") arg1,
172            in("rsi") arg2,
173            in("rdx") arg3,
174            in("rcx") arg4,
175            in("r8") arg5,
176            lateout("rax") result,
177        );
178        #[cfg(target_arch = "aarch64")]
179        asm!(
180            "svc #{num}",
181            num = const NUM,
182            in("x0") arg1,
183            in("x1") arg2,
184            in("x2") arg3,
185            in("x3") arg4,
186            in("x4") arg5,
187            lateout("x0") result
188        );
189        core::mem::transmute(result)
190    }
191}
192
193/// Invokes a syscall with the given number and arguments
194/// Number must be of type [`SyscallNum`]
195/// Arguments must be of type [`usize`]
196/// returns a [`SyscallResult`]
197macro_rules! syscall {
198    ($num: path $(,)?) => {
199        $crate::syscalls::syscall0::<{ $num as u16 }>()
200    };
201    ($num: path, $arg1: expr $(,)?) => {
202        $crate::syscalls::syscall1::<{ $num as u16 }>($arg1)
203    };
204    ($num: path, $arg1: expr, $arg2: expr $(,)?) => {
205        $crate::syscalls::syscall2::<{ $num as u16 }>($arg1, $arg2)
206    };
207    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr $(,)?) => {
208        $crate::syscalls::syscall3::<{ $num as u16 }>($arg1, $arg2, $arg3)
209    };
210    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr, $arg4: expr $(,)?) => {
211        $crate::syscalls::syscall4::<{ $num as u16 }>($arg1, $arg2, $arg3, $arg4)
212    };
213    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr, $arg4: expr, $arg5: expr $(,)?) => {
214        $crate::syscalls::syscall5::<{ $num as u16 }>($arg1, $arg2, $arg3, $arg4, $arg5)
215    };
216}
217
218pub(crate) use syscall;
219
220macro_rules! define_syscall {
221    ($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident : $ty:ty),*) unreachable }) => {
222        $(#[$attrss])*
223        #[cfg_attr(
224            not(any(feature = "std", feature = "rustc-dep-of-std")),
225            unsafe(no_mangle)
226        )]
227        #[inline(always)]
228        pub extern "C" fn $name($($arg: $ty),*) -> ! {
229            #[allow(unused_imports)]
230            use $crate::syscalls::types::IntoSyscallArg;
231            _ = $crate::syscalls::syscall!($num, $( $arg.into_syscall_arg() ),*);
232            unreachable!()
233        }
234    };
235    ($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident : $ty:ty),*) }) => {
236        $(#[$attrss])*
237        #[cfg_attr(
238            not(any(feature = "std", feature = "rustc-dep-of-std")),
239            unsafe(no_mangle)
240        )]
241        #[inline(always)]
242        pub extern "C" fn $name($($arg: $ty),*) -> SyscallResult {
243            #[allow(unused_imports)]
244            use $crate::syscalls::types::IntoSyscallArg;
245            let result = $crate::syscalls::syscall!($num, $( $arg.into_syscall_arg() ),*);
246            result
247        }
248    };
249    {$($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident: $ty:ty),*) $($modifier:tt)* }),*} => {
250        $(define_syscall!($num => { $(#[$attrss])* $name($($arg: $ty),*) $($modifier)* });)*
251    };
252}
253
254pub(crate) use define_syscall;
255
256mod raw;
257pub use raw::*;
258use types::SyscallResult;
259/// Contains documentation-only types for syscall arguments
260pub mod types;