lib.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. #![feature(naked_functions)]
  9. extern crate alloc;
  10. #[allow(warnings)]
  11. mod bindings;
  12. mod driver;
  13. mod elf;
  14. mod fs;
  15. mod hash;
  16. mod intrusive_list;
  17. mod io;
  18. mod kernel;
  19. mod net;
  20. mod path;
  21. mod prelude;
  22. mod rcu;
  23. mod sync;
  24. use alloc::{ffi::CString, sync::Arc};
  25. use core::alloc::{GlobalAlloc, Layout};
  26. use elf::ParsedElf32;
  27. use eonix_runtime::{run::FutureRun, scheduler::Scheduler};
  28. use kernel::{
  29. cpu::init_thiscpu,
  30. mem::Page,
  31. task::{KernelStack, ProcessBuilder, ProcessList, ThreadBuilder, ThreadRunnable},
  32. vfs::{
  33. dentry::Dentry,
  34. mount::{do_mount, MS_NOATIME, MS_NODEV, MS_NOSUID, MS_RDONLY},
  35. FsContext,
  36. },
  37. CharDevice,
  38. };
  39. use path::Path;
  40. use prelude::*;
  41. #[panic_handler]
  42. fn panic(info: &core::panic::PanicInfo) -> ! {
  43. if let Some(location) = info.location() {
  44. println_fatal!(
  45. "panicked at {}:{}:{}",
  46. location.file(),
  47. location.line(),
  48. location.column()
  49. );
  50. } else {
  51. println_fatal!("panicked at <UNKNOWN>");
  52. }
  53. println_fatal!();
  54. println_fatal!("{}", info.message());
  55. arch::freeze()
  56. }
  57. extern "C" {
  58. fn _do_allocate(size: usize) -> *mut core::ffi::c_void;
  59. fn _do_deallocate(ptr: *mut core::ffi::c_void, size: core::ffi::c_size_t) -> i32;
  60. fn init_pci();
  61. }
  62. struct Allocator {}
  63. unsafe impl GlobalAlloc for Allocator {
  64. unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
  65. let result = _do_allocate(layout.size());
  66. if result.is_null() {
  67. core::ptr::null_mut()
  68. } else {
  69. result as *mut u8
  70. }
  71. }
  72. unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
  73. match _do_deallocate(ptr as *mut core::ffi::c_void, layout.size()) {
  74. 0 => (),
  75. _ => panic!("Failed to deallocate memory"),
  76. }
  77. }
  78. }
  79. #[global_allocator]
  80. static ALLOCATOR: Allocator = Allocator {};
  81. extern "C" {
  82. fn init_allocator();
  83. }
  84. #[no_mangle]
  85. pub extern "C" fn rust_kinit(early_kstack_pfn: usize) -> ! {
  86. // We don't call global constructors.
  87. // Rust doesn't need that, and we're not going to use global variables in C++.
  88. unsafe { init_thiscpu() };
  89. unsafe { init_allocator() };
  90. kernel::interrupt::init().unwrap();
  91. // TODO: Move this to rust.
  92. unsafe { init_pci() };
  93. kernel::vfs::mount::init_vfs().unwrap();
  94. // To satisfy the `Scheduler` "preempt count == 0" assertion.
  95. eonix_preempt::disable();
  96. // We need root dentry to be present in constructor of `FsContext`.
  97. // So call `init_vfs` first, then `init_multitasking`.
  98. Scheduler::init_local_scheduler::<KernelStack>();
  99. Scheduler::get().spawn::<KernelStack, _>(FutureRun::new(init_process(early_kstack_pfn)));
  100. unsafe {
  101. // SAFETY: `preempt::count()` == 1.
  102. Scheduler::goto_scheduler_noreturn()
  103. }
  104. }
  105. async fn init_process(early_kstack_pfn: usize) {
  106. unsafe { Page::take_pfn(early_kstack_pfn, 9) };
  107. kernel::syscall::register_syscalls();
  108. CharDevice::init().unwrap();
  109. // We might want the serial initialized as soon as possible.
  110. driver::serial::init().unwrap();
  111. driver::e1000e::register_e1000e_driver();
  112. driver::ahci::register_ahci_driver();
  113. fs::procfs::init();
  114. fs::fat32::init();
  115. unsafe { kernel::smp::bootstrap_smp() };
  116. let (ip, sp, mm_list) = {
  117. // mount fat32 /mnt directory
  118. let fs_context = FsContext::global();
  119. let mnt_dir = Dentry::open(fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
  120. mnt_dir.mkdir(0o755).unwrap();
  121. do_mount(
  122. &mnt_dir,
  123. "/dev/sda",
  124. "/mnt",
  125. "fat32",
  126. MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
  127. )
  128. .unwrap();
  129. let init = Dentry::open(fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
  130. .expect("busybox should be present in /mnt");
  131. let argv = vec![
  132. CString::new("/mnt/busybox").unwrap(),
  133. CString::new("sh").unwrap(),
  134. CString::new("/mnt/initsh").unwrap(),
  135. ];
  136. let envp = vec![
  137. CString::new("LANG=C").unwrap(),
  138. CString::new("HOME=/root").unwrap(),
  139. CString::new("PATH=/mnt").unwrap(),
  140. CString::new("PWD=/").unwrap(),
  141. ];
  142. let elf = ParsedElf32::parse(init.clone()).unwrap();
  143. elf.load(argv, envp).unwrap()
  144. };
  145. let thread_builder = ThreadBuilder::new().name(Arc::from(*b"busybox"));
  146. let mut process_list = ProcessList::get().write();
  147. let (thread, process) = ProcessBuilder::new()
  148. .mm_list(mm_list)
  149. .thread_builder(thread_builder)
  150. .build(&mut process_list);
  151. process_list.set_init_process(process);
  152. // TODO!!!: Remove this.
  153. thread.files.open_console();
  154. Scheduler::get().spawn::<KernelStack, _>(ThreadRunnable::new(thread, ip, sp));
  155. }