1use alloc::{
2 string::{String, ToString},
3 sync::Arc,
4};
5
6use ax_fs::FS_CONTEXT;
7use ax_hal::uspace::UserContext;
8use ax_sync::Mutex;
9use ax_task::{AxTaskExt, spawn_task};
10use starry_process::{Pid, Process};
11
12use crate::{
13 file::FD_TABLE,
14 mm::{copy_from_kernel, load_user_app, new_user_aspace_empty},
15 pseudofs::{self, dev::tty::N_TTY},
16 task::{ProcessData, Thread, add_task_to_table, new_user_task, spawn_alarm_task},
17};
18
19pub fn init(args: &[String], envs: &[String]) {
21 static_keys::global_init();
22 pseudofs::mount_all().expect("Failed to mount pseudofs");
23 spawn_alarm_task();
24
25 let loc = FS_CONTEXT
26 .lock()
27 .resolve(&args[0])
28 .expect("Failed to resolve executable path");
29 let path = loc
30 .absolute_path()
31 .expect("Failed to get executable absolute path");
32 let name = loc.name().into_owned();
33
34 let mut uspace = new_user_aspace_empty()
35 .and_then(|mut it| {
36 copy_from_kernel(&mut it)?;
37 Ok(it)
38 })
39 .expect("Failed to create user address space");
40
41 let (entry_vaddr, ustack_top) = load_user_app(&mut uspace, None, args, envs)
42 .unwrap_or_else(|e| panic!("Failed to load user app: {}", e));
43
44 let uctx = UserContext::new(entry_vaddr.into(), ustack_top, 0);
45 let mut task = new_user_task(&name, uctx, 0);
46 task.ctx_mut().set_page_table_root(uspace.page_table_root());
47
48 let pid = task.id().as_u64() as Pid;
49 let proc = Process::new_init(pid);
50 proc.add_thread(pid);
51
52 N_TTY.bind_to(&proc).expect("Failed to bind ntty");
53
54 let proc = ProcessData::new(
55 proc,
56 path.to_string(),
57 Arc::new(args.to_vec()),
58 Arc::new(Mutex::new(uspace)),
59 Arc::default(),
60 None,
61 );
62
63 {
64 let mut scope = proc.scope.write();
65 crate::file::add_stdio(&mut FD_TABLE.scope_mut(&mut scope).write())
66 .expect("Failed to add stdio");
67 }
68
69 let thr = Thread::new(pid, proc, None);
70 *task.task_ext_mut() = Some(AxTaskExt::from_impl(thr));
71
72 let task = spawn_task(task);
73 add_task_to_table(&task);
74
75 let exit_code = task.join();
77 info!("Init process exited with code: {exit_code:?}");
78
79 let cx = FS_CONTEXT.lock();
80 cx.root_dir()
81 .unmount_all()
82 .expect("Failed to unmount all filesystems");
83 cx.root_dir()
84 .filesystem()
85 .flush()
86 .expect("Failed to flush rootfs");
87}