lib.rs 5.6 KB

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