137 lines
3.6 KiB
Rust
137 lines
3.6 KiB
Rust
//! The std library of jinux
|
|
#![no_std]
|
|
#![forbid(unsafe_code)]
|
|
#![allow(dead_code)]
|
|
#![allow(incomplete_features)]
|
|
#![allow(unused_variables)]
|
|
#![feature(cstr_from_bytes_until_nul)]
|
|
#![feature(exclusive_range_pattern)]
|
|
#![feature(btree_drain_filter)]
|
|
#![feature(const_option)]
|
|
#![feature(extend_one)]
|
|
#![feature(let_chains)]
|
|
// FIXME: This feature is used to support vm capbility now as a work around.
|
|
// Since this is an incomplete feature, use this feature is unsafe.
|
|
// We should find a proper method to replace this feature with min_specialization, which is a sound feature.
|
|
#![feature(specialization)]
|
|
#![feature(fn_traits)]
|
|
#![feature(linked_list_remove)]
|
|
#![feature(trait_alias)]
|
|
#![feature(register_tool)]
|
|
#![feature(trait_upcasting)]
|
|
#![register_tool(component_access_control)]
|
|
|
|
use crate::{
|
|
prelude::*,
|
|
process::status::ProcessStatus,
|
|
thread::{kernel_thread::KernelThreadExt, Thread},
|
|
};
|
|
use jinux_frame::exit_qemu;
|
|
use process::Process;
|
|
|
|
extern crate alloc;
|
|
extern crate lru;
|
|
#[macro_use]
|
|
extern crate controlled;
|
|
|
|
pub mod device;
|
|
pub mod driver;
|
|
pub mod error;
|
|
pub mod events;
|
|
pub mod fs;
|
|
pub mod net;
|
|
pub mod prelude;
|
|
mod process;
|
|
pub mod syscall;
|
|
pub mod thread;
|
|
pub mod time;
|
|
mod util;
|
|
pub mod vm;
|
|
|
|
pub fn init(ramdisk: &[u8]) {
|
|
driver::init();
|
|
net::init();
|
|
process::fifo_scheduler::init();
|
|
fs::initramfs::init(ramdisk).unwrap();
|
|
device::init().unwrap();
|
|
}
|
|
|
|
fn init_thread() {
|
|
println!(
|
|
"[kernel] Spawn init thread, tid = {}",
|
|
current_thread!().tid()
|
|
);
|
|
net::lazy_init();
|
|
// driver::pci::virtio::block::block_device_test();
|
|
let thread = Thread::spawn_kernel_thread(|| {
|
|
println!("[kernel] Hello world from kernel!");
|
|
let current = current_thread!();
|
|
let tid = current.tid();
|
|
debug!("current tid = {}", tid);
|
|
});
|
|
thread.join();
|
|
info!(
|
|
"[jinux-std/lib.rs] spawn kernel thread, tid = {}",
|
|
thread.tid()
|
|
);
|
|
|
|
print_banner();
|
|
let busybox = run_busybox().expect("run busybox fails");
|
|
|
|
loop {
|
|
// If busybox becomes zombie, then exit qemu.
|
|
if *busybox.status().lock() == ProcessStatus::Zombie {
|
|
println!("Exit jinux.");
|
|
exit_qemu(jinux_frame::QemuExitCode::Success);
|
|
}
|
|
// We don't have preemptive scheduler now.
|
|
// The long running init thread should yield its own execution to allow other tasks to go on.
|
|
Thread::yield_now();
|
|
}
|
|
}
|
|
|
|
/// first process never return
|
|
#[controlled]
|
|
pub fn run_first_process() -> ! {
|
|
Thread::spawn_kernel_thread(init_thread);
|
|
unreachable!()
|
|
}
|
|
|
|
fn run_busybox() -> Result<Arc<Process>> {
|
|
let executable_path = "/busybox/busybox";
|
|
let argv = ["sh", "-l"];
|
|
let envp = [
|
|
"SHELL=/bin/sh",
|
|
"LOGNAME=root",
|
|
"HOME=/",
|
|
"USER=root",
|
|
"PATH=/bin",
|
|
];
|
|
let argv = argv
|
|
.into_iter()
|
|
.map(|arg| CString::new(arg).unwrap())
|
|
.collect();
|
|
let envp = envp
|
|
.into_iter()
|
|
.map(|env| CString::new(env).unwrap())
|
|
.collect();
|
|
println!("");
|
|
println!("BusyBox v1.35.0 built-in shell (ash)\n");
|
|
Process::spawn_user_process(executable_path, argv, envp)
|
|
}
|
|
|
|
fn print_banner() {
|
|
println!("\x1B[36m");
|
|
println!(
|
|
r"
|
|
__ __ .__ __. __ __ ___ ___
|
|
| | | | | \ | | | | | | \ \ / /
|
|
| | | | | \| | | | | | \ V /
|
|
.--. | | | | | . ` | | | | | > <
|
|
| `--' | | | | |\ | | `--' | / . \
|
|
\______/ |__| |__| \__| \______/ /__/ \__\
|
|
"
|
|
);
|
|
println!("\x1B[0m");
|
|
}
|