safa_api/process/
init.rs

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