safa_api/process/
init.rs

1//! contains api initialization functions, that should be called before using the api
2use core::ptr::NonNull;
3
4use crate::{
5    alloc::GLOBAL_SYSTEM_ALLOCATOR,
6    syscalls::{self},
7};
8use safa_abi::raw::{processes::AbiStructures, NonNullSlice, RawSliceMut};
9
10use super::{
11    args::{RawArgs, RAW_ARGS},
12    env::RAW_ENV,
13    stdio::init_meta,
14};
15
16// Initialization
17
18fn init_args(args: RawSliceMut<NonNullSlice<u8>>) {
19    unsafe {
20        let slice = args
21            .into_slice_mut()
22            .map(|inner| RawArgs::new(NonNull::new_unchecked(inner as *mut _)));
23        RAW_ARGS.init(slice)
24    }
25}
26
27fn init_env(env: RawSliceMut<NonNullSlice<u8>>) {
28    unsafe {
29        let slice = env
30            .into_slice_mut()
31            .map(|inner| RawArgs::new(NonNull::new_unchecked(inner as *mut _)));
32        RAW_ENV.init(slice)
33    }
34}
35
36/// Initializes the safa-api
37/// if your programs are designed as C main function,
38///
39/// use [`_c_api_init`] instead
40#[cfg_attr(
41    not(any(feature = "std", feature = "rustc-dep-of-std")),
42    unsafe(no_mangle)
43)]
44#[inline(always)]
45pub extern "C" fn sysapi_init(
46    args: RawSliceMut<NonNullSlice<u8>>,
47    env: RawSliceMut<NonNullSlice<u8>>,
48    task_abi_structures: AbiStructures,
49) {
50    init_args(args);
51    init_env(env);
52    init_meta(task_abi_structures);
53}
54
55/// Initializes the safa-api, converts arguments to C-style arguments, calls `main`, and exits with the result
56/// main are designed as C main function,
57///
58/// this function is designed to be called from C code at _start before main,
59/// main should be passed as a parameter
60#[cfg_attr(
61    not(any(feature = "std", feature = "rustc-dep-of-std")),
62    unsafe(no_mangle)
63)]
64pub unsafe extern "C" fn _c_api_init(
65    args: RawSliceMut<NonNullSlice<u8>>,
66    env: RawSliceMut<NonNullSlice<u8>>,
67    task_abi_structures: *const AbiStructures,
68    main: extern "C" fn(argc: i32, argv: *const NonNull<u8>) -> i32,
69) -> ! {
70    sysapi_init(args, env, *task_abi_structures);
71
72    // Convert SafaOS `_start` arguments to `main` arguments
73    fn c_main_args(args: RawSliceMut<NonNullSlice<u8>>) -> (i32, *const NonNull<u8>) {
74        let argv_slice = unsafe { args.into_slice_mut().unwrap_or_default() };
75        if argv_slice.is_empty() {
76            return (0, core::ptr::null());
77        }
78
79        let bytes = args.len() * size_of::<usize>();
80
81        let c_argv_bytes = GLOBAL_SYSTEM_ALLOCATOR.allocate(bytes).unwrap();
82        let c_argv_slice = unsafe {
83            core::slice::from_raw_parts_mut(c_argv_bytes.as_ptr() as *mut NonNull<u8>, args.len())
84        };
85
86        for (i, arg) in argv_slice.iter().enumerate() {
87            c_argv_slice[i] = arg.as_non_null();
88        }
89
90        (args.len() as i32, c_argv_slice.as_ptr())
91    }
92
93    let (argc, argv) = c_main_args(args);
94    let result = main(argc, argv);
95    syscalls::exit(result as usize)
96}