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