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(path_ptr: *const u8, path_len: usize, dest_fd: *mut usize) -> u16 {
240 syscall3(
241 SyscallNum::SysDirIterOpen,
242 path_ptr as usize,
243 path_len,
244 dest_fd as usize,
245 )
246}
247
248#[inline]
249pub fn diriter_open(path: &str) -> Result<usize, ErrorStatus> {
250 let mut dest_fd: usize = 0xAAAAAAAAAAAAAAAAusize;
251 err_from_u16!(
252 sysdiriter_open(path.as_ptr(), path.len(), &raw mut dest_fd),
253 dest_fd
254 )
255}
256
257#[cfg_attr(
258 not(any(feature = "std", feature = "rustc-dep-of-std")),
259 unsafe(no_mangle)
260)]
261#[inline(always)]
262extern "C" fn sysdiriter_next(dir_ri: usize, dest_direntry: *mut DirEntry) -> u16 {
263 syscall2(SyscallNum::SysDirIterNext, dir_ri, dest_direntry as usize)
264}
265
266#[inline]
267pub fn diriter_next(dir_ri: usize) -> Result<DirEntry, ErrorStatus> {
268 let mut dest_direntry: DirEntry = unsafe { core::mem::zeroed() };
269 err_from_u16!(
270 sysdiriter_next(dir_ri, &raw mut dest_direntry),
271 dest_direntry
272 )
273}
274
275#[cfg_attr(
276 not(any(feature = "std", feature = "rustc-dep-of-std")),
277 unsafe(no_mangle)
278)]
279#[inline(always)]
280extern "C" fn syswrite(
281 fd: usize,
282 offset: isize,
283 buf: *const u8,
284 len: usize,
285 dest_wrote: &mut usize,
286) -> u16 {
287 syscall5(
288 SyscallNum::SysWrite,
289 fd,
290 offset as usize,
291 buf as usize,
292 len,
293 dest_wrote as *mut _ as usize,
294 )
295}
296
297#[inline]
298pub fn write(fd: usize, offset: isize, buf: &[u8]) -> Result<usize, ErrorStatus> {
299 let mut dest_wrote = 0;
300 err_from_u16!(
301 syswrite(fd, offset, buf.as_ptr(), buf.len(), &mut dest_wrote),
302 dest_wrote
303 )
304}
305
306#[cfg_attr(
307 not(any(feature = "std", feature = "rustc-dep-of-std")),
308 unsafe(no_mangle)
309)]
310#[inline(always)]
311extern "C" fn systruncate(fd: usize, len: usize) -> u16 {
312 syscall2(SyscallNum::SysTruncate, fd, len)
313}
314
315#[inline]
316pub fn truncate(fd: usize, len: usize) -> Result<(), ErrorStatus> {
317 err_from_u16!(systruncate(fd, len))
318}
319
320#[cfg_attr(
321 not(any(feature = "std", feature = "rustc-dep-of-std")),
322 unsafe(no_mangle)
323)]
324#[inline(always)]
325pub fn sysfsize(fd: usize, dest_size: *mut usize) -> u16 {
326 syscall2(SyscallNum::SysFSize, fd, dest_size as usize)
327}
328
329#[inline]
330pub fn fsize(fd: usize) -> Result<usize, ErrorStatus> {
331 let mut dest_size = 0;
332 err_from_u16!(sysfsize(fd, &raw mut dest_size), dest_size)
333}
334
335#[cfg_attr(
336 not(any(feature = "std", feature = "rustc-dep-of-std")),
337 unsafe(no_mangle)
338)]
339#[inline(always)]
340extern "C" fn sysfattrs(fd: usize, dest_attrs: *mut FileAttr) -> u16 {
341 syscall2(SyscallNum::SysFAttrs, fd, dest_attrs as usize)
342}
343
344#[inline]
345pub fn fattrs(fd: usize) -> Result<FileAttr, ErrorStatus> {
346 let mut attrs: FileAttr = unsafe { core::mem::zeroed() };
347 err_from_u16!(sysfattrs(fd, &raw mut attrs), attrs)
348}
349
350#[cfg_attr(
351 not(any(feature = "std", feature = "rustc-dep-of-std")),
352 unsafe(no_mangle)
353)]
354#[inline(always)]
355extern "C" fn sysread(
356 fd: usize,
357 offset: isize,
358 buf: *mut u8,
359 len: usize,
360 dest_read: &mut usize,
361) -> u16 {
362 syscall5(
363 SyscallNum::SysRead,
364 fd,
365 offset as usize,
366 buf as usize,
367 len,
368 dest_read as *mut _ as usize,
369 )
370}
371
372#[inline]
373pub fn read(fd: usize, offset: isize, buf: &mut [u8]) -> Result<usize, ErrorStatus> {
374 let mut dest_read = 0;
375 err_from_u16!(
376 sysread(fd, offset, buf.as_mut_ptr(), buf.len(), &mut dest_read),
377 dest_read
378 )
379}
380
381#[cfg_attr(
382 not(any(feature = "std", feature = "rustc-dep-of-std")),
383 unsafe(no_mangle)
384)]
385#[inline(always)]
386extern "C" fn syssync(fd: usize) -> u16 {
387 syscall1(SyscallNum::SysSync, fd)
388}
389
390#[inline]
391pub fn sync(fd: usize) -> Result<(), ErrorStatus> {
392 err_from_u16!(syssync(fd))
393}
394#[cfg_attr(
395 not(any(feature = "std", feature = "rustc-dep-of-std")),
396 unsafe(no_mangle)
397)]
398#[inline(always)]
399extern "C" fn syssbrk(size: isize, target_ptr: &mut *mut u8) -> u16 {
400 syscall2(
401 SyscallNum::SysSbrk,
402 size as usize,
403 target_ptr as *mut _ as usize,
404 )
405}
406
407#[inline]
408pub fn sbrk(size: isize) -> Result<*mut u8, ErrorStatus> {
409 let mut target_ptr: *mut u8 = core::ptr::null_mut();
410 err_from_u16!(syssbrk(size, &mut target_ptr), target_ptr)
411}
412
413#[cfg_attr(
414 not(any(feature = "std", feature = "rustc-dep-of-std")),
415 unsafe(no_mangle)
416)]
417#[inline(always)]
418extern "C" fn sysexit(code: usize) -> ! {
419 syscall1(SyscallNum::SysExit, code);
420 unreachable!()
421}
422
423#[cfg_attr(
424 not(any(feature = "std", feature = "rustc-dep-of-std")),
425 unsafe(no_mangle)
426)]
427#[inline(always)]
428extern "C" fn sysyield() -> u16 {
429 syscall0(SyscallNum::SysYield)
430}
431
432#[inline]
433pub fn yield_now() {
434 debug_assert!(sysyield() == 0)
435}
436
437#[cfg_attr(
438 not(any(feature = "std", feature = "rustc-dep-of-std")),
439 unsafe(no_mangle)
440)]
441#[inline(always)]
442extern "C" fn sysshutdown() -> ! {
443 syscall0(SyscallNum::SysShutdown);
444 unreachable!()
445}
446
447#[inline]
448pub fn shutdown() -> ! {
449 sysshutdown()
450}
451
452#[cfg_attr(
453 not(any(feature = "std", feature = "rustc-dep-of-std")),
454 unsafe(no_mangle)
455)]
456#[inline(always)]
457extern "C" fn sysreboot() -> ! {
458 syscall0(SyscallNum::SysReboot);
459 unreachable!()
460}
461
462#[inline]
463pub fn reboot() -> ! {
464 sysreboot()
465}
466
467#[inline]
468pub fn exit(code: usize) -> ! {
469 sysexit(code)
470}
471#[cfg_attr(
472 not(any(feature = "std", feature = "rustc-dep-of-std")),
473 unsafe(no_mangle)
474)]
475#[inline(always)]
476extern "C" fn syschdir(buf_ptr: *const u8, buf_len: usize) -> u16 {
477 syscall2(SyscallNum::SysCHDir, buf_ptr as usize, buf_len)
478}
479
480#[inline]
481pub fn chdir(path: &str) -> Result<(), ErrorStatus> {
482 let path = path.as_bytes();
483 err_from_u16!(syschdir(path.as_ptr(), path.len()))
484}
485
486#[cfg_attr(
487 not(any(feature = "std", feature = "rustc-dep-of-std")),
488 unsafe(no_mangle)
489)]
490#[inline(always)]
493extern "C" fn sysgetcwd(cwd_buf_ptr: *mut u8, cwd_buf_len: usize, dest_len: &mut usize) -> u16 {
494 syscall3(
495 SyscallNum::SysGetCWD,
496 cwd_buf_ptr as usize,
497 cwd_buf_len,
498 dest_len as *mut _ as usize,
499 )
500}
501
502#[inline]
503pub fn getcwd() -> Result<Vec<u8>, ErrorStatus> {
504 let do_syscall = |cwd_buf: &mut [u8]| {
505 let mut dest_len = 0;
506 err_from_u16!(
507 sysgetcwd(cwd_buf.as_mut_ptr(), cwd_buf.len(), &mut dest_len),
508 dest_len
509 )
510 };
511
512 let extend = |cwd_buf: &mut Vec<u8>| unsafe {
513 cwd_buf.reserve(128);
514 cwd_buf.set_len(cwd_buf.capacity());
515 };
516
517 let mut cwd_buf = Vec::new();
518 extend(&mut cwd_buf);
519
520 loop {
521 match do_syscall(&mut cwd_buf) {
522 Ok(len) => unsafe {
523 cwd_buf.set_len(len);
524 return Ok(cwd_buf);
525 },
526 Err(err) => {
527 if err == ErrorStatus::Generic {
528 extend(&mut cwd_buf);
529 } else {
530 return Err(err);
531 }
532 }
533 }
534 }
535}
536
537#[derive(Debug, Clone, Copy)]
538#[repr(C)]
539pub struct SpawnFlags(u8);
540impl SpawnFlags {
541 pub const CLONE_RESOURCES: Self = Self(1 << 0);
542 pub const CLONE_CWD: Self = Self(1 << 1);
543}
544
545impl ops::BitOr for SpawnFlags {
546 type Output = Self;
547 fn bitor(self, rhs: Self) -> Self::Output {
548 Self(self.0 | rhs.0)
549 }
550}
551#[cfg_attr(
552 not(any(feature = "std", feature = "rustc-dep-of-std")),
553 unsafe(no_mangle)
554)]
555#[inline(always)]
556extern "C" fn syspspawn(
557 name_ptr: *const u8,
558 name_len: usize,
559 path_ptr: *const u8,
560 path_len: usize,
561 argv_ptr: *const RawSlice<u8>,
562 argv_len: usize,
563 flags: SpawnFlags,
564 dest_pid: &mut usize,
565) -> u16 {
566 #[repr(C)]
570 struct SpawnConfig {
571 name: RawSlice<u8>,
572 argv: RawSlice<RawSlice<u8>>,
573 flags: SpawnFlags,
574 }
575
576 let config = SpawnConfig {
577 name: unsafe { RawSlice::from_raw_parts(name_ptr, name_len) },
578 argv: unsafe { RawSlice::from_raw_parts(argv_ptr, argv_len) },
579 flags,
580 };
581 syscall4(
582 SyscallNum::SysPSpawn,
583 path_ptr as usize,
584 path_len,
585 (&raw const config) as usize,
586 dest_pid as *mut _ as usize,
587 )
588}
589
590#[inline]
595pub unsafe fn unsafe_pspawn(
596 name: Option<&str>,
597 path: &str,
598 argv: *mut [&str],
599 flags: SpawnFlags,
600) -> Result<usize, ErrorStatus> {
601 let mut pid = 0;
602
603 let name = name.map(|s| s.as_bytes());
604 let name_ptr = name.map(|s| s.as_ptr()).unwrap_or(ptr::null());
605 let name_len = name.map(|s| s.len()).unwrap_or(0);
606
607 let argv: *mut [&[u8]] = argv as *mut [&[u8]];
608 let argv = unsafe { RawSliceMut::from_slices(argv) };
609 err_from_u16!(
610 syspspawn(
611 name_ptr,
612 name_len,
613 path.as_ptr(),
614 path.len(),
615 argv.as_ptr(),
616 argv.len(),
617 flags,
618 &mut pid,
619 ),
620 pid
621 )
622}
623
624#[inline]
626pub fn pspawn(
627 name: Option<&str>,
628 path: &str,
629 mut argv: Vec<&str>,
630 flags: SpawnFlags,
631) -> Result<usize, ErrorStatus> {
632 let argv: &mut [&str] = &mut argv;
633 unsafe { unsafe_pspawn(name, path, argv as *mut _, flags) }
634}
635#[cfg_attr(
636 not(any(feature = "std", feature = "rustc-dep-of-std")),
637 unsafe(no_mangle)
638)]
639#[inline(always)]
640extern "C" fn syswait(pid: usize, exit_code: &mut usize) -> u16 {
641 syscall2(SyscallNum::SysWait, pid, exit_code as *mut _ as usize)
642}
643
644#[inline]
645pub fn wait(pid: usize) -> Result<usize, ErrorStatus> {
646 let mut dest_exit_code = 0;
647 err_from_u16!(syswait(pid, &mut dest_exit_code), dest_exit_code)
648}