lib.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #![no_std]
  2. #![no_main]
  3. #![feature(c_size_t)]
  4. #![feature(concat_idents)]
  5. #![feature(arbitrary_self_types)]
  6. #![feature(get_mut_unchecked)]
  7. #![feature(macro_metavar_expr)]
  8. extern crate alloc;
  9. mod driver;
  10. mod fs;
  11. mod hash;
  12. mod io;
  13. mod kernel;
  14. mod kernel_init;
  15. mod net;
  16. mod path;
  17. mod prelude;
  18. mod rcu;
  19. mod sync;
  20. use crate::kernel::task::alloc_pid;
  21. use alloc::{ffi::CString, sync::Arc};
  22. use core::{
  23. hint::spin_loop,
  24. sync::atomic::{AtomicBool, Ordering},
  25. };
  26. use eonix_hal::{processor::CPU, traits::trap::IrqState, trap::disable_irqs_save};
  27. use eonix_mm::address::PRange;
  28. use eonix_runtime::{run::FutureRun, scheduler::Scheduler, task::Task};
  29. use kernel::{
  30. mem::GlobalPageAlloc,
  31. pcie::init_pcie,
  32. task::{
  33. new_thread_runnable, KernelStack, ProcessBuilder, ProcessList, ProgramLoader, ThreadBuilder,
  34. },
  35. vfs::{
  36. dentry::Dentry,
  37. mount::{do_mount, MS_NOATIME, MS_NODEV, MS_NOSUID, MS_RDONLY},
  38. FsContext,
  39. },
  40. CharDevice,
  41. };
  42. use kernel_init::setup_memory;
  43. use path::Path;
  44. use prelude::*;
  45. #[panic_handler]
  46. fn panic(info: &core::panic::PanicInfo) -> ! {
  47. if let Some(location) = info.location() {
  48. println_fatal!(
  49. "panicked at {}:{}:{}",
  50. location.file(),
  51. location.line(),
  52. location.column()
  53. );
  54. } else {
  55. println_fatal!("panicked at <UNKNOWN>");
  56. }
  57. println_fatal!();
  58. println_fatal!("{}", info.message());
  59. loop {}
  60. }
  61. static BSP_OK: AtomicBool = AtomicBool::new(false);
  62. #[eonix_hal::main]
  63. fn kernel_init(mut data: eonix_hal::bootstrap::BootStrapData) -> ! {
  64. setup_memory(&mut data);
  65. BSP_OK.store(true, Ordering::Release);
  66. init_pcie().expect("Unable to initialize PCIe bus");
  67. // To satisfy the `Scheduler` "preempt count == 0" assertion.
  68. eonix_preempt::disable();
  69. // We need root dentry to be present in constructor of `FsContext`.
  70. // So call `init_vfs` first, then `init_multitasking`.
  71. Scheduler::init_local_scheduler::<KernelStack>();
  72. Scheduler::get().spawn::<KernelStack, _>(FutureRun::new(init_process(data.get_early_stack())));
  73. drop(data);
  74. unsafe {
  75. // SAFETY: `preempt::count()` == 1.
  76. Scheduler::goto_scheduler_noreturn()
  77. }
  78. }
  79. #[eonix_hal::ap_main]
  80. fn kernel_ap_main(_stack_range: PRange) -> ! {
  81. while BSP_OK.load(Ordering::Acquire) == false {
  82. // Wait for BSP to finish initializing.
  83. spin_loop();
  84. }
  85. Scheduler::init_local_scheduler::<KernelStack>();
  86. println_debug!("AP{} started", CPU::local().cpuid());
  87. eonix_preempt::disable();
  88. // TODO!!!!!: Free the stack after having switched to idle task.
  89. unsafe {
  90. // SAFETY: `preempt::count()` == 1.
  91. Scheduler::goto_scheduler_noreturn()
  92. }
  93. }
  94. async fn init_process(early_kstack: PRange) {
  95. unsafe {
  96. let irq_ctx = disable_irqs_save();
  97. // SAFETY: IRQ is disabled.
  98. GlobalPageAlloc::add_pages(early_kstack);
  99. irq_ctx.restore();
  100. }
  101. CharDevice::init().unwrap();
  102. // We might want the serial initialized as soon as possible.
  103. driver::serial::init().unwrap();
  104. driver::e1000e::register_e1000e_driver();
  105. driver::ahci::register_ahci_driver();
  106. fs::tmpfs::init();
  107. fs::procfs::init();
  108. fs::fat32::init();
  109. let load_info = {
  110. // mount fat32 /mnt directory
  111. let fs_context = FsContext::global();
  112. let mnt_dir = Dentry::open(fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
  113. mnt_dir.mkdir(0o755).unwrap();
  114. do_mount(
  115. &mnt_dir,
  116. "/dev/sda",
  117. "/mnt",
  118. "fat32",
  119. MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
  120. )
  121. .unwrap();
  122. let init = Dentry::open(fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
  123. .expect("busybox should be present in /mnt");
  124. let argv = vec![
  125. CString::new("/mnt/busybox").unwrap(),
  126. CString::new("sh").unwrap(),
  127. CString::new("/mnt/initsh").unwrap(),
  128. ];
  129. let envp = vec![
  130. CString::new("LANG=C").unwrap(),
  131. CString::new("HOME=/root").unwrap(),
  132. CString::new("PATH=/mnt").unwrap(),
  133. CString::new("PWD=/").unwrap(),
  134. ];
  135. ProgramLoader::parse(init.clone())
  136. .unwrap()
  137. .load(argv, envp)
  138. .unwrap()
  139. };
  140. let thread_builder = ThreadBuilder::new()
  141. .name(Arc::from(&b"busybox"[..]))
  142. .entry(load_info.entry_ip, load_info.sp);
  143. let mut process_list = Task::block_on(ProcessList::get().write());
  144. let (thread, process) = ProcessBuilder::new()
  145. .pid(alloc_pid())
  146. .mm_list(load_info.mm_list)
  147. .thread_builder(thread_builder)
  148. .build(&mut process_list);
  149. process_list.set_init_process(process);
  150. // TODO!!!: Remove this.
  151. thread.files.open_console();
  152. Scheduler::get().spawn::<KernelStack, _>(new_thread_runnable(thread));
  153. }