1use crate::raw::DirEntry;
2
3use super::errors::ErrorStatus;
4
5#[cfg(not(feature = "rustc-dep-of-std"))]
6extern crate alloc;
7use super::raw::FileAttr;
8use super::raw::{RawSlice, RawSliceMut};
9use alloc::vec::Vec;
10use core::arch::asm;
11use core::{ops, ptr};
12use safa_abi::errors::SysResult;
13pub use safa_abi::syscalls::SyscallTable as SyscallNum;
14
15macro_rules! err_from_u16 {
16 ($result:expr) => {
17 unsafe {
18 Into::<Result<(), ErrorStatus>>::into(
19 TryInto::<SysResult>::try_into($result).unwrap_unchecked(),
20 )
21 }
22 };
23 ($result:expr, $ok:expr) => {
24 err_from_u16!($result).map(|()| $ok)
25 };
26}
27
28#[inline(always)]
29fn syscall0(num: SyscallNum) -> u16 {
30 let result: u16;
31 unsafe {
32 asm!(
33 "int 0x80",
34 in("rax") num as usize,
35 lateout("rax") result,
36 );
37 result
38 }
39}
40
41#[inline(always)]
42fn syscall1(num: SyscallNum, arg1: usize) -> u16 {
43 let result: u16;
44 unsafe {
45 asm!(
46 "int 0x80",
47 in("rax") num as usize,
48 in("rdi") arg1,
49 lateout("rax") result,
50 );
51 result
52 }
53}
54
55#[inline(always)]
56fn syscall2(num: SyscallNum, arg1: usize, arg2: usize) -> u16 {
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 result
67 }
68}
69
70#[inline(always)]
71fn syscall3(num: SyscallNum, arg1: usize, arg2: usize, arg3: usize) -> u16 {
72 let result: u16;
73 unsafe {
74 asm!(
75 "int 0x80",
76 in("rax") num as usize,
77 in("rdi") arg1,
78 in("rsi") arg2,
79 in("rdx") arg3,
80 lateout("rax") result,
81 );
82 result
83 }
84}
85
86#[inline(always)]
87fn syscall5(
88 num: SyscallNum,
89 arg1: usize,
90 arg2: usize,
91 arg3: usize,
92 arg4: usize,
93 arg5: usize,
94) -> u16 {
95 let result: u16;
96 unsafe {
97 asm!(
98 "int 0x80",
99 in("rax") num as usize,
100 in("rdi") arg1,
101 in("rsi") arg2,
102 in("rdx") arg3,
103 in("rcx") arg4,
104 in("r8") arg5,
105 lateout("rax") result,
106 );
107 result
108 }
109}
110
111#[inline(always)]
112fn syscall4(num: SyscallNum, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> u16 {
113 let result: u16;
114 unsafe {
115 asm!(
116 "int 0x80",
117 in("rax") num as usize,
118 in("rdi") arg1,
119 in("rsi") arg2,
120 in("rdx") arg3,
121 in("rcx") arg4,
122 lateout("rax") result,
123 );
124 result
125 }
126}
127
128#[cfg_attr(
129 not(any(feature = "std", feature = "rustc-dep-of-std")),
130 unsafe(no_mangle)
131)]
132#[inline(always)]
133extern "C" fn sysgetdirentry(
134 path_ptr: *const u8,
135 path_len: usize,
136 dest_direntry: *mut DirEntry,
137) -> u16 {
138 syscall3(
139 SyscallNum::SysGetDirEntry,
140 path_ptr as usize,
141 path_len,
142 dest_direntry as usize,
143 )
144}
145
146#[inline]
147pub fn getdirentry(path: &str) -> Result<DirEntry, ErrorStatus> {
148 let mut dest_direntry: DirEntry = unsafe { core::mem::zeroed() };
149 err_from_u16!(
150 sysgetdirentry(path.as_ptr(), path.len(), &raw mut dest_direntry),
151 dest_direntry
152 )
153}
154
155#[cfg_attr(
156 not(any(feature = "std", feature = "rustc-dep-of-std")),
157 unsafe(no_mangle)
158)]
159#[inline(always)]
160extern "C" fn sysopen(path_ptr: *const u8, path_len: usize, dest_fd: *mut usize) -> u16 {
161 syscall3(
162 SyscallNum::SysOpen,
163 path_ptr as usize,
164 path_len,
165 dest_fd as usize,
166 )
167}
168
169#[cfg_attr(
170 not(any(feature = "std", feature = "rustc-dep-of-std")),
171 unsafe(no_mangle)
172)]
173#[inline(always)]
174extern "C" fn syscreate_file(path_ptr: *const u8, path_len: usize) -> u16 {
175 syscall2(SyscallNum::SysCreate, path_ptr as usize, path_len)
176}
177
178#[inline]
179pub fn create(path: &str) -> Result<(), ErrorStatus> {
180 err_from_u16!(syscreate_file(path.as_ptr(), path.len()))
181}
182
183#[cfg_attr(
184 not(any(feature = "std", feature = "rustc-dep-of-std")),
185 unsafe(no_mangle)
186)]
187#[inline(always)]
188extern "C" fn syscreate_dir(path_ptr: *const u8, path_len: usize) -> u16 {
189 syscall2(SyscallNum::SysCreateDir, path_ptr as usize, path_len)
190}
191
192#[inline]
193pub fn createdir(path: &str) -> Result<(), ErrorStatus> {
194 err_from_u16!(syscreate_dir(path.as_ptr(), path.len()))
195}
196
197#[inline]
198pub fn open(path: &str) -> Result<usize, ErrorStatus> {
199 let mut dest_fd = 0xAAAAAAAAAAAAAAAAusize;
200 err_from_u16!(
201 sysopen(path.as_ptr(), path.len(), &raw mut dest_fd),
202 dest_fd
203 )
204}
205
206#[cfg_attr(
207 not(any(feature = "std", feature = "rustc-dep-of-std")),
208 unsafe(no_mangle)
209)]
210#[inline(always)]
211extern "C" fn sysclose(fd: usize) -> u16 {
212 syscall1(SyscallNum::SysClose, fd)
213}
214
215#[inline]
216pub fn close(fd: usize) -> Result<(), ErrorStatus> {
217 err_from_u16!(sysclose(fd))
218}
219
220#[cfg_attr(
221 not(any(feature = "std", feature = "rustc-dep-of-std")),
222 unsafe(no_mangle)
223)]
224#[inline(always)]
225extern "C" fn sysdiriter_close(fd: usize) -> u16 {
226 syscall1(SyscallNum::SysDirIterClose, fd)
227}
228
229#[inline]
230pub fn diriter_close(fd: usize) -> Result<(), ErrorStatus> {
231 err_from_u16!(sysdiriter_close(fd))
232}
233
234#[cfg_attr(
235 not(any(feature = "std", feature = "rustc-dep-of-std")),
236 unsafe(no_mangle)
237)]
238#[inline(always)]
239extern "C" fn sysdiriter_open(dir_ri: usize, dest_ri: *mut usize) -> u16 {
240 syscall2(SyscallNum::SysDirIterOpen, dir_ri, dest_ri as usize)
241}
242
243#[inline]
244pub fn diriter_open(dir_ri: usize) -> Result<usize, ErrorStatus> {
245 let mut dest_fd: usize = 0xAAAAAAAAAAAAAAAAusize;
246 err_from_u16!(sysdiriter_open(dir_ri, &raw mut dest_fd), dest_fd)
247}
248
249#[cfg_attr(
250 not(any(feature = "std", feature = "rustc-dep-of-std")),
251 unsafe(no_mangle)
252)]
253#[inline(always)]
254extern "C" fn sysdiriter_next(dir_ri: usize, dest_direntry: *mut DirEntry) -> u16 {
255 syscall2(SyscallNum::SysDirIterNext, dir_ri, dest_direntry as usize)
256}
257
258#[inline]
259pub fn diriter_next(dir_ri: usize) -> Result<DirEntry, ErrorStatus> {
260 let mut dest_direntry: DirEntry = unsafe { core::mem::zeroed() };
261 err_from_u16!(
262 sysdiriter_next(dir_ri, &raw mut dest_direntry),
263 dest_direntry
264 )
265}
266
267#[cfg_attr(
268 not(any(feature = "std", feature = "rustc-dep-of-std")),
269 unsafe(no_mangle)
270)]
271#[inline(always)]
272extern "C" fn syswrite(
273 fd: usize,
274 offset: isize,
275 buf: *const u8,
276 len: usize,
277 dest_wrote: &mut usize,
278) -> u16 {
279 syscall5(
280 SyscallNum::SysWrite,
281 fd,
282 offset as usize,
283 buf as usize,
284 len,
285 dest_wrote as *mut _ as usize,
286 )
287}
288
289#[inline]
290pub fn write(fd: usize, offset: isize, buf: &[u8]) -> Result<usize, ErrorStatus> {
291 let mut dest_wrote = 0;
292 err_from_u16!(
293 syswrite(fd, offset, buf.as_ptr(), buf.len(), &mut dest_wrote),
294 dest_wrote
295 )
296}
297
298#[cfg_attr(
299 not(any(feature = "std", feature = "rustc-dep-of-std")),
300 unsafe(no_mangle)
301)]
302#[inline(always)]
303extern "C" fn systruncate(fd: usize, len: usize) -> u16 {
304 syscall2(SyscallNum::SysTruncate, fd, len)
305}
306
307#[inline]
308pub fn truncate(fd: usize, len: usize) -> Result<(), ErrorStatus> {
309 err_from_u16!(systruncate(fd, len))
310}
311
312#[cfg_attr(
313 not(any(feature = "std", feature = "rustc-dep-of-std")),
314 unsafe(no_mangle)
315)]
316#[inline(always)]
317pub fn sysfsize(fd: usize, dest_size: *mut usize) -> u16 {
318 syscall2(SyscallNum::SysFSize, fd, dest_size as usize)
319}
320
321#[inline]
322pub fn fsize(fd: usize) -> Result<usize, ErrorStatus> {
323 let mut dest_size = 0;
324 err_from_u16!(sysfsize(fd, &raw mut dest_size), dest_size)
325}
326
327#[cfg_attr(
328 not(any(feature = "std", feature = "rustc-dep-of-std")),
329 unsafe(no_mangle)
330)]
331#[inline(always)]
332extern "C" fn sysfattrs(fd: usize, dest_attrs: *mut FileAttr) -> u16 {
333 syscall2(SyscallNum::SysFAttrs, fd, dest_attrs as usize)
334}
335
336#[inline]
337pub fn fattrs(fd: usize) -> Result<FileAttr, ErrorStatus> {
338 let mut attrs: FileAttr = unsafe { core::mem::zeroed() };
339 err_from_u16!(sysfattrs(fd, &raw mut attrs), attrs)
340}
341
342#[cfg_attr(
343 not(any(feature = "std", feature = "rustc-dep-of-std")),
344 unsafe(no_mangle)
345)]
346#[inline(always)]
347extern "C" fn sysread(
348 fd: usize,
349 offset: isize,
350 buf: *mut u8,
351 len: usize,
352 dest_read: &mut usize,
353) -> u16 {
354 syscall5(
355 SyscallNum::SysRead,
356 fd,
357 offset as usize,
358 buf as usize,
359 len,
360 dest_read as *mut _ as usize,
361 )
362}
363
364#[inline]
365pub fn read(fd: usize, offset: isize, buf: &mut [u8]) -> Result<usize, ErrorStatus> {
366 let mut dest_read = 0;
367 err_from_u16!(
368 sysread(fd, offset, buf.as_mut_ptr(), buf.len(), &mut dest_read),
369 dest_read
370 )
371}
372
373#[cfg_attr(
374 not(any(feature = "std", feature = "rustc-dep-of-std")),
375 unsafe(no_mangle)
376)]
377#[inline(always)]
378extern "C" fn syssync(fd: usize) -> u16 {
379 syscall1(SyscallNum::SysSync, fd)
380}
381
382#[inline]
383pub fn sync(fd: usize) -> Result<(), ErrorStatus> {
384 err_from_u16!(syssync(fd))
385}
386#[cfg_attr(
387 not(any(feature = "std", feature = "rustc-dep-of-std")),
388 unsafe(no_mangle)
389)]
390#[inline(always)]
391extern "C" fn syssbrk(size: isize, target_ptr: &mut *mut u8) -> u16 {
392 syscall2(
393 SyscallNum::SysSbrk,
394 size as usize,
395 target_ptr as *mut _ as usize,
396 )
397}
398
399#[inline]
400pub fn sbrk(size: isize) -> Result<*mut u8, ErrorStatus> {
401 let mut target_ptr: *mut u8 = core::ptr::null_mut();
402 err_from_u16!(syssbrk(size, &mut target_ptr), target_ptr)
403}
404
405#[cfg_attr(
406 not(any(feature = "std", feature = "rustc-dep-of-std")),
407 unsafe(no_mangle)
408)]
409#[inline(always)]
410extern "C" fn sysexit(code: usize) -> ! {
411 syscall1(SyscallNum::SysExit, code);
412 unreachable!()
413}
414
415#[cfg_attr(
416 not(any(feature = "std", feature = "rustc-dep-of-std")),
417 unsafe(no_mangle)
418)]
419#[inline(always)]
420extern "C" fn sysyield() -> u16 {
421 syscall0(SyscallNum::SysYield)
422}
423
424#[inline]
425pub fn yield_now() {
426 debug_assert!(sysyield() == 0)
427}
428
429#[cfg_attr(
430 not(any(feature = "std", feature = "rustc-dep-of-std")),
431 unsafe(no_mangle)
432)]
433#[inline(always)]
434extern "C" fn sysshutdown() -> ! {
435 syscall0(SyscallNum::SysShutdown);
436 unreachable!()
437}
438
439#[inline]
440pub fn shutdown() -> ! {
441 sysshutdown()
442}
443
444#[cfg_attr(
445 not(any(feature = "std", feature = "rustc-dep-of-std")),
446 unsafe(no_mangle)
447)]
448#[inline(always)]
449extern "C" fn sysreboot() -> ! {
450 syscall0(SyscallNum::SysReboot);
451 unreachable!()
452}
453
454#[inline]
455pub fn reboot() -> ! {
456 sysreboot()
457}
458
459#[inline]
460pub fn exit(code: usize) -> ! {
461 sysexit(code)
462}
463#[cfg_attr(
464 not(any(feature = "std", feature = "rustc-dep-of-std")),
465 unsafe(no_mangle)
466)]
467#[inline(always)]
468extern "C" fn syschdir(buf_ptr: *const u8, buf_len: usize) -> u16 {
469 syscall2(SyscallNum::SysCHDir, buf_ptr as usize, buf_len)
470}
471
472#[inline]
473pub fn chdir(path: &str) -> Result<(), ErrorStatus> {
474 let path = path.as_bytes();
475 err_from_u16!(syschdir(path.as_ptr(), path.len()))
476}
477
478#[cfg_attr(
479 not(any(feature = "std", feature = "rustc-dep-of-std")),
480 unsafe(no_mangle)
481)]
482#[inline(always)]
485extern "C" fn sysgetcwd(cwd_buf_ptr: *mut u8, cwd_buf_len: usize, dest_len: &mut usize) -> u16 {
486 syscall3(
487 SyscallNum::SysGetCWD,
488 cwd_buf_ptr as usize,
489 cwd_buf_len,
490 dest_len as *mut _ as usize,
491 )
492}
493
494#[inline]
495pub fn getcwd() -> Result<Vec<u8>, ErrorStatus> {
496 let do_syscall = |cwd_buf: &mut [u8]| {
497 let mut dest_len = 0;
498 err_from_u16!(
499 sysgetcwd(cwd_buf.as_mut_ptr(), cwd_buf.len(), &mut dest_len),
500 dest_len
501 )
502 };
503
504 let extend = |cwd_buf: &mut Vec<u8>| unsafe {
505 cwd_buf.reserve(128);
506 cwd_buf.set_len(cwd_buf.capacity());
507 };
508
509 let mut cwd_buf = Vec::new();
510 extend(&mut cwd_buf);
511
512 loop {
513 match do_syscall(&mut cwd_buf) {
514 Ok(len) => unsafe {
515 cwd_buf.set_len(len);
516 return Ok(cwd_buf);
517 },
518 Err(err) => {
519 if err == ErrorStatus::Generic {
520 extend(&mut cwd_buf);
521 } else {
522 return Err(err);
523 }
524 }
525 }
526 }
527}
528
529#[derive(Debug, Clone, Copy)]
530#[repr(C)]
531pub struct SpawnFlags(u8);
532impl SpawnFlags {
533 pub const CLONE_RESOURCES: Self = Self(1 << 0);
534 pub const CLONE_CWD: Self = Self(1 << 1);
535}
536
537impl ops::BitOr for SpawnFlags {
538 type Output = Self;
539 fn bitor(self, rhs: Self) -> Self::Output {
540 Self(self.0 | rhs.0)
541 }
542}
543#[cfg_attr(
544 not(any(feature = "std", feature = "rustc-dep-of-std")),
545 unsafe(no_mangle)
546)]
547#[inline(always)]
548extern "C" fn syspspawn(
549 name_ptr: *const u8,
550 name_len: usize,
551 path_ptr: *const u8,
552 path_len: usize,
553 argv_ptr: *const RawSlice<u8>,
554 argv_len: usize,
555 flags: SpawnFlags,
556 dest_pid: &mut usize,
557) -> u16 {
558 #[repr(C)]
562 struct SpawnConfig {
563 name: RawSlice<u8>,
564 argv: RawSlice<RawSlice<u8>>,
565 flags: SpawnFlags,
566 }
567
568 let config = SpawnConfig {
569 name: unsafe { RawSlice::from_raw_parts(name_ptr, name_len) },
570 argv: unsafe { RawSlice::from_raw_parts(argv_ptr, argv_len) },
571 flags,
572 };
573 syscall4(
574 SyscallNum::SysPSpawn,
575 path_ptr as usize,
576 path_len,
577 (&raw const config) as usize,
578 dest_pid as *mut _ as usize,
579 )
580}
581
582#[inline]
587pub unsafe fn unsafe_pspawn(
588 name: Option<&str>,
589 path: &str,
590 argv: *mut [&str],
591 flags: SpawnFlags,
592) -> Result<usize, ErrorStatus> {
593 let mut pid = 0;
594
595 let name = name.map(|s| s.as_bytes());
596 let name_ptr = name.map(|s| s.as_ptr()).unwrap_or(ptr::null());
597 let name_len = name.map(|s| s.len()).unwrap_or(0);
598
599 let argv: *mut [&[u8]] = argv as *mut [&[u8]];
600 let argv = unsafe { RawSliceMut::from_slices(argv) };
601 err_from_u16!(
602 syspspawn(
603 name_ptr,
604 name_len,
605 path.as_ptr(),
606 path.len(),
607 argv.as_ptr(),
608 argv.len(),
609 flags,
610 &mut pid,
611 ),
612 pid
613 )
614}
615
616#[inline]
618pub fn pspawn(
619 name: Option<&str>,
620 path: &str,
621 mut argv: Vec<&str>,
622 flags: SpawnFlags,
623) -> Result<usize, ErrorStatus> {
624 let argv: &mut [&str] = &mut argv;
625 unsafe { unsafe_pspawn(name, path, argv as *mut _, flags) }
626}
627#[cfg_attr(
628 not(any(feature = "std", feature = "rustc-dep-of-std")),
629 unsafe(no_mangle)
630)]
631#[inline(always)]
632extern "C" fn syswait(pid: usize, exit_code: &mut usize) -> u16 {
633 syscall2(SyscallNum::SysWait, pid, exit_code as *mut _ as usize)
634}
635
636#[inline]
637pub fn wait(pid: usize) -> Result<usize, ErrorStatus> {
638 let mut dest_exit_code = 0;
639 err_from_u16!(syswait(pid, &mut dest_exit_code), dest_exit_code)
640}