lib.rs 5.0 KB

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