| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- #![no_std]
- #![no_main]
- #![feature(c_size_t)]
- #![feature(concat_idents)]
- #![feature(arbitrary_self_types)]
- #![feature(get_mut_unchecked)]
- #![feature(macro_metavar_expr)]
- #![feature(naked_functions)]
- extern crate alloc;
- #[allow(warnings)]
- mod bindings;
- mod driver;
- mod elf;
- mod fs;
- mod hash;
- mod intrusive_list;
- mod io;
- mod kernel;
- mod net;
- mod path;
- mod prelude;
- mod rcu;
- mod sync;
- use alloc::{ffi::CString, sync::Arc};
- use core::alloc::{GlobalAlloc, Layout};
- use elf::ParsedElf32;
- use eonix_runtime::{run::FutureRun, scheduler::Scheduler};
- use kernel::{
- cpu::init_thiscpu,
- mem::Page,
- task::{KernelStack, ProcessBuilder, ProcessList, ThreadBuilder, ThreadRunnable},
- vfs::{
- dentry::Dentry,
- mount::{do_mount, MS_NOATIME, MS_NODEV, MS_NOSUID, MS_RDONLY},
- FsContext,
- },
- CharDevice,
- };
- use path::Path;
- use prelude::*;
- #[panic_handler]
- fn panic(info: &core::panic::PanicInfo) -> ! {
- if let Some(location) = info.location() {
- println_fatal!(
- "panicked at {}:{}:{}",
- location.file(),
- location.line(),
- location.column()
- );
- } else {
- println_fatal!("panicked at <UNKNOWN>");
- }
- println_fatal!();
- println_fatal!("{}", info.message());
- arch::freeze()
- }
- extern "C" {
- fn _do_allocate(size: usize) -> *mut core::ffi::c_void;
- fn _do_deallocate(ptr: *mut core::ffi::c_void, size: core::ffi::c_size_t) -> i32;
- fn init_pci();
- }
- struct Allocator {}
- unsafe impl GlobalAlloc for Allocator {
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- let result = _do_allocate(layout.size());
- if result.is_null() {
- core::ptr::null_mut()
- } else {
- result as *mut u8
- }
- }
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- match _do_deallocate(ptr as *mut core::ffi::c_void, layout.size()) {
- 0 => (),
- _ => panic!("Failed to deallocate memory"),
- }
- }
- }
- #[global_allocator]
- static ALLOCATOR: Allocator = Allocator {};
- extern "C" {
- fn init_allocator();
- }
- #[no_mangle]
- pub extern "C" fn rust_kinit(early_kstack_pfn: usize) -> ! {
- // We don't call global constructors.
- // Rust doesn't need that, and we're not going to use global variables in C++.
- unsafe { init_thiscpu() };
- unsafe { init_allocator() };
- kernel::interrupt::init().unwrap();
- // TODO: Move this to rust.
- unsafe { init_pci() };
- kernel::vfs::mount::init_vfs().unwrap();
- // To satisfy the `Scheduler` "preempt count == 0" assertion.
- eonix_preempt::disable();
- // We need root dentry to be present in constructor of `FsContext`.
- // So call `init_vfs` first, then `init_multitasking`.
- Scheduler::init_local_scheduler::<KernelStack>();
- Scheduler::get().spawn::<KernelStack, _>(FutureRun::new(init_process(early_kstack_pfn)));
- unsafe {
- // SAFETY: `preempt::count()` == 1.
- Scheduler::goto_scheduler_noreturn()
- }
- }
- async fn init_process(early_kstack_pfn: usize) {
- unsafe { Page::take_pfn(early_kstack_pfn, 9) };
- kernel::syscall::register_syscalls();
- CharDevice::init().unwrap();
- // We might want the serial initialized as soon as possible.
- driver::serial::init().unwrap();
- driver::e1000e::register_e1000e_driver();
- driver::ahci::register_ahci_driver();
- fs::procfs::init();
- fs::fat32::init();
- unsafe { kernel::smp::bootstrap_smp() };
- let (ip, sp, mm_list) = {
- // mount fat32 /mnt directory
- let fs_context = FsContext::global();
- let mnt_dir = Dentry::open(fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
- mnt_dir.mkdir(0o755).unwrap();
- do_mount(
- &mnt_dir,
- "/dev/sda",
- "/mnt",
- "fat32",
- MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
- )
- .unwrap();
- let init = Dentry::open(fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
- .expect("busybox should be present in /mnt");
- let argv = vec![
- CString::new("/mnt/busybox").unwrap(),
- CString::new("sh").unwrap(),
- CString::new("/mnt/initsh").unwrap(),
- ];
- let envp = vec![
- CString::new("LANG=C").unwrap(),
- CString::new("HOME=/root").unwrap(),
- CString::new("PATH=/mnt").unwrap(),
- CString::new("PWD=/").unwrap(),
- ];
- let elf = ParsedElf32::parse(init.clone()).unwrap();
- elf.load(argv, envp).unwrap()
- };
- let thread_builder = ThreadBuilder::new().name(Arc::from(*b"busybox"));
- let mut process_list = ProcessList::get().write();
- let (thread, process) = ProcessBuilder::new()
- .mm_list(mm_list)
- .thread_builder(thread_builder)
- .build(&mut process_list);
- process_list.set_init_process(process);
- // TODO!!!: Remove this.
- thread.files.open_console();
- Scheduler::get().spawn::<KernelStack, _>(ThreadRunnable::new(thread, ip, sp));
- }
|