lib.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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 io;
  17. mod kernel;
  18. mod net;
  19. mod path;
  20. mod prelude;
  21. mod rcu;
  22. mod sync;
  23. use alloc::ffi::CString;
  24. use core::{
  25. alloc::{GlobalAlloc, Layout},
  26. arch::{asm, global_asm},
  27. };
  28. use elf::ParsedElf32;
  29. use kernel::{
  30. cpu::init_thiscpu,
  31. task::{init_multitasking, Scheduler, Thread},
  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. use sync::preempt;
  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. global_asm!(
  83. r"
  84. .globl to_init_process
  85. to_init_process:
  86. push %rbp
  87. mov %rbx, %rdi
  88. jmp {}
  89. ",
  90. sym init_process,
  91. options(att_syntax)
  92. );
  93. extern "C" {
  94. fn to_init_process();
  95. }
  96. #[no_mangle]
  97. pub extern "C" fn rust_kinit(early_kstack_pfn: usize) -> ! {
  98. // We don't call global constructors.
  99. // Rust doesn't need that, and we're not going to use global variables in C++.
  100. unsafe { init_thiscpu() };
  101. kernel::interrupt::init().unwrap();
  102. // TODO: Move this to rust.
  103. unsafe { init_pci() };
  104. kernel::vfs::mount::init_vfs().unwrap();
  105. // To satisfy the `Scheduler` "preempt count == 0" assertion.
  106. preempt::disable();
  107. // We need root dentry to be present in constructor of `FsContext`.
  108. // So call `init_vfs` first, then `init_multitasking`.
  109. unsafe { init_multitasking(init_process) };
  110. let mut unuse_ctx = arch::TaskContext::new();
  111. // TODO: Temporary solution: we will never access this later on.
  112. unuse_ctx.init(
  113. to_init_process as usize,
  114. early_kstack_pfn + 0x1000 + 0xffffff0000000000,
  115. );
  116. unsafe {
  117. arch::TaskContext::switch_to(
  118. &mut unuse_ctx, // We will never come back
  119. &mut *Scheduler::idle_task().get_context_mut_ptr(),
  120. );
  121. }
  122. arch::freeze()
  123. }
  124. /// We enter this function with `preempt count == 0`
  125. extern "C" fn init_process(/* early_kstack_pfn: usize */) {
  126. // TODO!!! Should free pass eraly_kstack_pfn and free !!!
  127. // unsafe { Page::take_pfn(early_kstack_pfn, 9) };
  128. preempt::enable();
  129. kernel::syscall::register_syscalls();
  130. CharDevice::init().unwrap();
  131. // We might want the serial initialized as soon as possible.
  132. driver::serial::init().unwrap();
  133. driver::e1000e::register_e1000e_driver();
  134. driver::ahci::register_ahci_driver();
  135. fs::procfs::init();
  136. fs::fat32::init();
  137. unsafe { kernel::smp::bootstrap_smp() };
  138. let (ip, sp) = {
  139. // mount fat32 /mnt directory
  140. let fs_context = FsContext::get_current();
  141. let mnt_dir = Dentry::open(&fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
  142. mnt_dir.mkdir(0o755).unwrap();
  143. do_mount(
  144. &mnt_dir,
  145. "/dev/sda",
  146. "/mnt",
  147. "fat32",
  148. MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
  149. )
  150. .unwrap();
  151. let init = Dentry::open(&fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
  152. .expect("busybox should be present in /mnt");
  153. let argv = vec![
  154. CString::new("/mnt/busybox").unwrap(),
  155. CString::new("sh").unwrap(),
  156. CString::new("/mnt/initsh").unwrap(),
  157. ];
  158. let envp = vec![
  159. CString::new("LANG=C").unwrap(),
  160. CString::new("HOME=/root").unwrap(),
  161. CString::new("PATH=/mnt").unwrap(),
  162. CString::new("PWD=/").unwrap(),
  163. ];
  164. let elf = ParsedElf32::parse(init.clone()).unwrap();
  165. elf.load(&Thread::current().process.mm_list, argv, envp)
  166. .unwrap()
  167. };
  168. Thread::current().files.open_console();
  169. unsafe {
  170. asm!(
  171. "swapgs",
  172. "mov ${ds}, %rax",
  173. "mov %ax, %ds",
  174. "mov %ax, %es",
  175. "push ${ds}",
  176. "push {sp}",
  177. "push $0x200",
  178. "push ${cs}",
  179. "push {ip}",
  180. "iretq",
  181. ds = const 0x33,
  182. cs = const 0x2b,
  183. in("rax") 0,
  184. ip = in(reg) ip.0,
  185. sp = in(reg) sp.0,
  186. options(att_syntax, noreturn),
  187. );
  188. }
  189. }