//! Kernel main process implementation: filesystem initialization and userspace init start use abi::error::Error; use libk::{ device::display::console, fs::devfs, random, task::{binary::LoadOptions, process::Process, runtime, thread::Thread}, vfs::{impls::fn_hardlink, IoContext, NodeRef, OwnedFilename}, }; use memfs::MemoryFilesystem; use crate::{ fs::{FileBlockAllocator, INITRD_DATA}, proc, }; fn setup_root() -> Result { let initrd_data = INITRD_DATA.try_get().ok_or(Error::DoesNotExist)?; let fs = MemoryFilesystem::::from_slice(initrd_data.data)?; fs.root() } /// Kernel's "main" process function. /// /// # Note /// /// This function is meant to be used as a kernel-space process after all the platform-specific /// initialization has finished. pub fn kinit() -> Result<(), Error> { log::info!("In main"); runtime::spawn(ygg_driver_usb::bus::bus_handler())?; runtime::spawn(console::flush_consoles_task()).ok(); devfs::root() .add_child( OwnedFilename::new("tty").unwrap(), fn_hardlink(|| { let thread = Thread::current(); let process = thread.process(); process.session_terminal().ok_or(Error::InvalidOperation) }), ) .ok(); ygg_driver_net_loopback::init(); ygg_driver_net_core::start_network_tasks()?; random::init(); let root = setup_root().inspect_err(|error| { log::error!("Cannot setup root filesystem: {error:?}"); })?; let mut ioctx = IoContext::new(root); // TODO move this to userspace so it doesn't block the init process, maybe lazy-load on first // attempt to load a module? #[cfg(all(not(target_arch = "aarch64"), not(target_arch = "riscv64")))] { use libk::module::load_kernel_symbol_table; load_kernel_symbol_table(&mut ioctx, "/kernel.sym")?; } { let group_id = Process::create_group(); let options = LoadOptions { group_id, parent: None, path: "/init", args: &["/init", "xxx"], envs: &[], single_step: false, disable_aslr: false, }; let (user_init, user_init_main) = proc::load_binary(&mut ioctx, &options)?; let mut io = user_init.io.lock(); io.set_ioctx(ioctx); drop(io); user_init_main.enqueue(); } Ok(()) }