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(num: SyscallNum) -> SyscallResult {
28    let result: u16;
29    unsafe {
30        asm!(
31            "int 0x80",
32            in("rax") num as usize,
33            lateout("rax") result,
34        );
35        core::mem::transmute(result)
36    }
37}
38
39#[doc(hidden)]
40#[inline(always)]
41pub fn syscall1(num: SyscallNum, arg1: usize) -> SyscallResult {
42    let result: u16;
43    unsafe {
44        asm!(
45            "int 0x80",
46            in("rax") num as usize,
47            in("rdi") arg1,
48            lateout("rax") result,
49        );
50        core::mem::transmute(result)
51    }
52}
53
54#[doc(hidden)]
55#[inline(always)]
56pub fn syscall2(num: SyscallNum, arg1: usize, arg2: usize) -> SyscallResult {
57    let result: u16;
58    unsafe {
59        asm!(
60            "int 0x80",
61            in("rax") num as usize,
62            in("rdi") arg1,
63            in("rsi") arg2,
64            lateout("rax") result,
65        );
66        core::mem::transmute(result)
67    }
68}
69
70#[doc(hidden)]
71#[inline(always)]
72pub fn syscall3(num: SyscallNum, arg1: usize, arg2: usize, arg3: usize) -> SyscallResult {
73    let result: u16;
74    unsafe {
75        asm!(
76            "int 0x80",
77            in("rax") num as usize,
78            in("rdi") arg1,
79            in("rsi") arg2,
80            in("rdx") arg3,
81            lateout("rax") result,
82        );
83        core::mem::transmute(result)
84    }
85}
86
87#[doc(hidden)]
88#[inline(always)]
89pub fn syscall5(
90    num: SyscallNum,
91    arg1: usize,
92    arg2: usize,
93    arg3: usize,
94    arg4: usize,
95    arg5: usize,
96) -> SyscallResult {
97    let result: u16;
98    unsafe {
99        asm!(
100            "int 0x80",
101            in("rax") num as usize,
102            in("rdi") arg1,
103            in("rsi") arg2,
104            in("rdx") arg3,
105            in("rcx") arg4,
106            in("r8") arg5,
107            lateout("rax") result,
108        );
109        core::mem::transmute(result)
110    }
111}
112
113#[doc(hidden)]
114#[inline(always)]
115pub fn syscall4(
116    num: SyscallNum,
117    arg1: usize,
118    arg2: usize,
119    arg3: usize,
120    arg4: usize,
121) -> SyscallResult {
122    let result: u16;
123    unsafe {
124        asm!(
125            "int 0x80",
126            in("rax") num as usize,
127            in("rdi") arg1,
128            in("rsi") arg2,
129            in("rdx") arg3,
130            in("rcx") arg4,
131            lateout("rax") result,
132        );
133        core::mem::transmute(result)
134    }
135}
136
137/// Invokes a syscall with the given number and arguments
138/// Number must be of type [`SyscallNum`]
139/// Arguments must be of type [`usize`]
140/// returns a [`SyscallResult`]
141macro_rules! syscall {
142    ($num: path $(,)?) => {
143        $crate::syscalls::syscall0($num)
144    };
145    ($num: path, $arg1: expr $(,)?) => {
146        $crate::syscalls::syscall1($num, $arg1)
147    };
148    ($num: path, $arg1: expr, $arg2: expr $(,)?) => {
149        $crate::syscalls::syscall2($num, $arg1, $arg2)
150    };
151    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr $(,)?) => {
152        $crate::syscalls::syscall3($num, $arg1, $arg2, $arg3)
153    };
154    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr, $arg4: expr $(,)?) => {
155        $crate::syscalls::syscall4($num, $arg1, $arg2, $arg3, $arg4)
156    };
157    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr, $arg4: expr, $arg5: expr $(,)?) => {
158        $crate::syscalls::syscall5($num, $arg1, $arg2, $arg3, $arg4, $arg5)
159    };
160}
161
162pub(crate) use syscall;
163
164macro_rules! define_syscall {
165    ($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident : $ty:ty),*) unreachable }) => {
166        $(#[$attrss])*
167        #[cfg_attr(
168            not(any(feature = "std", feature = "rustc-dep-of-std")),
169            unsafe(no_mangle)
170        )]
171        #[inline(always)]
172        pub extern "C" fn $name($($arg: $ty),*) -> ! {
173            #[allow(unused_imports)]
174            use $crate::syscalls::types::IntoSyscallArg;
175            _ = $crate::syscalls::syscall!($num, $( $arg.into_syscall_arg() ),*);
176            unreachable!()
177        }
178    };
179    ($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident : $ty:ty),*) }) => {
180        $(#[$attrss])*
181        #[cfg_attr(
182            not(any(feature = "std", feature = "rustc-dep-of-std")),
183            unsafe(no_mangle)
184        )]
185        #[inline(always)]
186        pub extern "C" fn $name($($arg: $ty),*) -> SyscallResult {
187            #[allow(unused_imports)]
188            use $crate::syscalls::types::IntoSyscallArg;
189            let result = $crate::syscalls::syscall!($num, $( $arg.into_syscall_arg() ),*);
190            result
191        }
192    };
193    {$($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident: $ty:ty),*) $($modifier:tt)* }),*} => {
194        $(define_syscall!($num => { $(#[$attrss])* $name($($arg: $ty),*) $($modifier)* });)*
195    };
196}
197
198pub(crate) use define_syscall;
199
200mod raw;
201pub use raw::*;
202use types::SyscallResult;
203/// Contains documentation-only types for syscall arguments
204pub mod types;