lib.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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;
  25. use core::{
  26. alloc::{GlobalAlloc, Layout},
  27. arch::{asm, global_asm},
  28. };
  29. use elf::ParsedElf32;
  30. use kernel::{
  31. cpu::init_thiscpu,
  32. task::{init_multitasking, Scheduler, Thread},
  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. use sync::preempt;
  43. #[panic_handler]
  44. fn panic(info: &core::panic::PanicInfo) -> ! {
  45. if let Some(location) = info.location() {
  46. println_fatal!(
  47. "panicked at {}:{}:{}",
  48. location.file(),
  49. location.line(),
  50. location.column()
  51. );
  52. } else {
  53. println_fatal!("panicked at <UNKNOWN>");
  54. }
  55. println_fatal!();
  56. println_fatal!("{}", info.message());
  57. arch::freeze()
  58. }
  59. extern "C" {
  60. fn _do_allocate(size: usize) -> *mut core::ffi::c_void;
  61. fn _do_deallocate(ptr: *mut core::ffi::c_void, size: core::ffi::c_size_t) -> i32;
  62. fn init_pci();
  63. }
  64. struct Allocator {}
  65. unsafe impl GlobalAlloc for Allocator {
  66. unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
  67. let result = _do_allocate(layout.size());
  68. if result.is_null() {
  69. core::ptr::null_mut()
  70. } else {
  71. result as *mut u8
  72. }
  73. }
  74. unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
  75. match _do_deallocate(ptr as *mut core::ffi::c_void, layout.size()) {
  76. 0 => (),
  77. _ => panic!("Failed to deallocate memory"),
  78. }
  79. }
  80. }
  81. #[global_allocator]
  82. static ALLOCATOR: Allocator = Allocator {};
  83. global_asm!(
  84. r"
  85. .globl to_init_process
  86. to_init_process:
  87. push %rbp
  88. mov %rbx, %rdi
  89. jmp {}
  90. ",
  91. sym init_process,
  92. options(att_syntax)
  93. );
  94. extern "C" {
  95. fn to_init_process();
  96. }
  97. #[no_mangle]
  98. pub extern "C" fn rust_kinit(early_kstack_pfn: usize) -> ! {
  99. // We don't call global constructors.
  100. // Rust doesn't need that, and we're not going to use global variables in C++.
  101. unsafe { init_thiscpu() };
  102. kernel::interrupt::init().unwrap();
  103. // TODO: Move this to rust.
  104. unsafe { init_pci() };
  105. kernel::vfs::mount::init_vfs().unwrap();
  106. // To satisfy the `Scheduler` "preempt count == 0" assertion.
  107. preempt::disable();
  108. // We need root dentry to be present in constructor of `FsContext`.
  109. // So call `init_vfs` first, then `init_multitasking`.
  110. unsafe { init_multitasking(init_process) };
  111. let mut unuse_ctx = arch::TaskContext::new();
  112. // TODO: Temporary solution: we will never access this later on.
  113. unuse_ctx.init(
  114. to_init_process as usize,
  115. early_kstack_pfn + 0x1000 + 0xffffff0000000000,
  116. );
  117. unsafe {
  118. arch::TaskContext::switch_to(
  119. &mut unuse_ctx, // We will never come back
  120. &mut *Scheduler::idle_task().get_context_mut_ptr(),
  121. );
  122. }
  123. arch::freeze()
  124. }
  125. /// We enter this function with `preempt count == 0`
  126. extern "C" fn init_process(/* early_kstack_pfn: usize */) {
  127. // TODO!!! Should free pass eraly_kstack_pfn and free !!!
  128. // unsafe { Page::take_pfn(early_kstack_pfn, 9) };
  129. preempt::enable();
  130. kernel::syscall::register_syscalls();
  131. CharDevice::init().unwrap();
  132. // We might want the serial initialized as soon as possible.
  133. driver::serial::init().unwrap();
  134. driver::e1000e::register_e1000e_driver();
  135. driver::ahci::register_ahci_driver();
  136. fs::procfs::init();
  137. fs::fat32::init();
  138. unsafe { kernel::smp::bootstrap_smp() };
  139. let (ip, sp, mm_list) = {
  140. // mount fat32 /mnt directory
  141. let fs_context = FsContext::get_current();
  142. let mnt_dir = Dentry::open(&fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
  143. mnt_dir.mkdir(0o755).unwrap();
  144. do_mount(
  145. &mnt_dir,
  146. "/dev/sda",
  147. "/mnt",
  148. "fat32",
  149. MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
  150. )
  151. .unwrap();
  152. let init = Dentry::open(&fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
  153. .expect("busybox should be present in /mnt");
  154. let argv = vec![
  155. CString::new("/mnt/busybox").unwrap(),
  156. CString::new("sh").unwrap(),
  157. CString::new("/mnt/initsh").unwrap(),
  158. ];
  159. let envp = vec![
  160. CString::new("LANG=C").unwrap(),
  161. CString::new("HOME=/root").unwrap(),
  162. CString::new("PATH=/mnt").unwrap(),
  163. CString::new("PWD=/").unwrap(),
  164. ];
  165. let elf = ParsedElf32::parse(init.clone()).unwrap();
  166. elf.load(argv, envp).unwrap()
  167. };
  168. Thread::current().process.mm_list.replace(mm_list);
  169. Thread::current().files.open_console();
  170. unsafe {
  171. asm!(
  172. "swapgs",
  173. "mov ${ds}, %rax",
  174. "mov %ax, %ds",
  175. "mov %ax, %es",
  176. "push ${ds}",
  177. "push {sp}",
  178. "push $0x200",
  179. "push ${cs}",
  180. "push {ip}",
  181. "iretq",
  182. ds = const 0x33,
  183. cs = const 0x2b,
  184. in("rax") 0,
  185. ip = in(reg) ip.0,
  186. sp = in(reg) sp.0,
  187. options(att_syntax, noreturn),
  188. );
  189. }
  190. }