| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #![no_std]
- #![no_main]
- #![feature(allocator_api)]
- #![feature(c_size_t)]
- #![feature(coerce_unsized)]
- #![feature(arbitrary_self_types)]
- #![feature(get_mut_unchecked)]
- #![feature(macro_metavar_expr)]
- #![feature(unsize)]
- extern crate alloc;
- #[macro_use]
- extern crate static_assertions;
- mod driver;
- mod fs;
- mod hash;
- mod io;
- mod kernel;
- mod kernel_init;
- mod net;
- mod panic;
- mod path;
- mod prelude;
- mod rcu;
- mod sync;
- use alloc::ffi::CString;
- use core::hint::spin_loop;
- use core::sync::atomic::{AtomicBool, Ordering};
- use eonix_hal::processor::CPU;
- use eonix_hal::symbol_addr;
- use eonix_hal::traits::trap::{IrqState, RawTrapContext, TrapReturn};
- use eonix_hal::trap::{disable_irqs_save, TrapContext};
- use eonix_mm::address::PRange;
- use eonix_runtime::scheduler::RUNTIME;
- use kernel::mem::GlobalPageAlloc;
- use kernel::task::{KernelStack, ProcessList, ProgramLoader};
- use kernel::vfs::dentry::Dentry;
- use kernel::vfs::mount::{
- do_mount, MS_NOATIME, MS_NODEV, MS_NOSUID, MS_RDONLY,
- };
- use kernel::vfs::types::Permission;
- use kernel::vfs::FsContext;
- use kernel::{shutdown_system, CharDevice};
- use kernel_init::setup_memory;
- use path::Path;
- use prelude::*;
- static BSP_OK: AtomicBool = AtomicBool::new(false);
- #[eonix_hal::main]
- fn kernel_init(mut data: eonix_hal::bootstrap::BootStrapData) -> ! {
- setup_memory(&mut data);
- #[cfg(target_arch = "riscv64")]
- {
- driver::sbi_console::init_console();
- }
- BSP_OK.store(true, Ordering::Release);
- RUNTIME.spawn(init_process(data.get_early_stack()));
- drop(data);
- let mut ctx = TrapContext::new();
- let stack = KernelStack::new();
- ctx.set_interrupt_enabled(true);
- ctx.set_user_mode(false);
- ctx.set_kernel_call_frame(symbol_addr!(standard_main), &stack, None, &[]);
- core::mem::forget(stack);
- unsafe {
- ctx.trap_return_noreturn();
- }
- }
- #[eonix_hal::ap_main]
- fn kernel_ap_main(_stack_range: PRange) -> ! {
- while BSP_OK.load(Ordering::Acquire) == false {
- // Wait for BSP to finish initializing.
- spin_loop();
- }
- println_debug!("AP{} started", CPU::local().cpuid());
- let mut ctx = TrapContext::new();
- let stack = KernelStack::new();
- ctx.set_interrupt_enabled(true);
- ctx.set_user_mode(false);
- ctx.set_kernel_call_frame(symbol_addr!(standard_main), &stack, None, &[]);
- core::mem::forget(stack);
- unsafe {
- ctx.trap_return_noreturn();
- }
- }
- fn standard_main() -> ! {
- RUNTIME.enter();
- shutdown_system();
- }
- async fn init_process(early_kstack: PRange) {
- unsafe {
- let irq_ctx = disable_irqs_save();
- // SAFETY: IRQ is disabled.
- GlobalPageAlloc::add_pages(early_kstack);
- irq_ctx.restore();
- }
- kernel::pcie::init_pcie().expect("Unable to initialize PCIe bus");
- CharDevice::init().unwrap();
- #[cfg(target_arch = "x86_64")]
- {
- // We might want the serial initialized as soon as possible.
- driver::serial::init().unwrap();
- driver::e1000e::register_e1000e_driver().await;
- driver::ahci::register_ahci_driver().await;
- }
- #[cfg(target_arch = "riscv64")]
- {
- driver::serial::init().unwrap();
- driver::virtio::init_virtio_devices();
- driver::e1000e::register_e1000e_driver().await;
- driver::ahci::register_ahci_driver().await;
- driver::goldfish_rtc::probe();
- }
- #[cfg(target_arch = "loongarch64")]
- {
- driver::serial::init().unwrap();
- driver::virtio::init_virtio_devices();
- driver::e1000e::register_e1000e_driver().await;
- driver::ahci::register_ahci_driver().await;
- }
- fs::tmpfs::init();
- fs::procfs::init().await;
- fs::fat32::init();
- // fs::ext4::init();
- let load_info = {
- // mount fat32 /mnt directory
- let fs_context = FsContext::global();
- let mnt_dir =
- Dentry::open(fs_context, Path::new(b"/mnt/").unwrap(), true)
- .await
- .unwrap();
- mnt_dir
- .mkdir(Permission::new(0o755))
- .await
- .expect("Failed to create /mnt directory");
- do_mount(
- &mnt_dir,
- "/dev/sda",
- "/mnt",
- "fat32",
- MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
- )
- .await
- .unwrap();
- let init_names =
- [&b"/init"[..], &b"/sbin/init"[..], &b"/mnt/initsh"[..]];
- let mut init_name = None;
- let mut init = None;
- for name in init_names {
- if let Ok(dentry) =
- Dentry::open(fs_context, Path::new(name).unwrap(), true).await
- {
- if dentry.is_valid() {
- init_name = Some(CString::new(name).unwrap());
- init = Some(dentry);
- break;
- }
- }
- }
- let init = init.expect("No init binary found in the system.");
- let init_name = init_name.unwrap();
- let argv = vec![init_name.clone()];
- let envp = vec![
- CString::new("LANG=C").unwrap(),
- CString::new("HOME=/root").unwrap(),
- CString::new("PATH=/mnt").unwrap(),
- CString::new("PWD=/").unwrap(),
- ];
- ProgramLoader::parse(fs_context, init_name, init.clone(), argv, envp)
- .await
- .expect("Failed to parse init program")
- .load()
- .await
- .expect("Failed to load init program")
- };
- ProcessList::sys_init(load_info).await;
- }
|