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 tracepoint::tracepoint_init,
18};
19
20pub fn init(args: &[String], envs: &[String]) {
22 static_keys::global_init();
23 tracepoint_init().expect("Failed to initialize tracepoints");
24
25 pseudofs::mount_all().expect("Failed to mount pseudofs");
26 spawn_alarm_task();
27
28 let loc = FS_CONTEXT
29 .lock()
30 .resolve(&args[0])
31 .expect("Failed to resolve executable path");
32 let path = loc
33 .absolute_path()
34 .expect("Failed to get executable absolute path");
35 let name = loc.name().into_owned();
36
37 let mut uspace = new_user_aspace_empty()
38 .and_then(|mut it| {
39 copy_from_kernel(&mut it)?;
40 Ok(it)
41 })
42 .expect("Failed to create user address space");
43
44 let (entry_vaddr, ustack_top) = load_user_app(&mut uspace, None, args, envs)
45 .unwrap_or_else(|e| panic!("Failed to load user app: {}", e));
46
47 let uctx = UserContext::new(entry_vaddr.into(), ustack_top, 0);
48 let mut task = new_user_task(&name, uctx, 0);
49 task.ctx_mut().set_page_table_root(uspace.page_table_root());
50
51 let pid = task.id().as_u64() as Pid;
52 let proc = Process::new_init(pid);
53 proc.add_thread(pid);
54
55 N_TTY.bind_to(&proc).expect("Failed to bind ntty");
56
57 let proc = ProcessData::new(
58 proc,
59 path.to_string(),
60 Arc::new(args.to_vec()),
61 Arc::new(Mutex::new(uspace)),
62 Arc::default(),
63 None,
64 false,
65 );
66
67 {
68 let mut scope = proc.scope.write();
69 crate::file::add_stdio(&mut FD_TABLE.scope_mut(&mut scope).write())
70 .expect("Failed to add stdio");
71 }
72
73 let thr = Thread::new(pid, proc, None);
74 *task.task_ext_mut() = Some(AxTaskExt::from_impl(thr));
75
76 let task = spawn_task(task);
77 add_task_to_table(&task);
78
79 let exit_code = task.join();
81 info!("Init process exited with code: {exit_code:?}");
82
83 let cx = FS_CONTEXT.lock();
84 cx.root_dir()
85 .unmount_all()
86 .expect("Failed to unmount all filesystems");
87 cx.root_dir()
88 .filesystem()
89 .flush()
90 .expect("Failed to flush rootfs");
91}