obkrnl/
main.rs

1#![no_std]
2#![cfg_attr(not(test), no_main)]
3
4use self::config::Config;
5use self::context::{ContextSetup, current_procmgr};
6use self::imgact::Ps4Abi;
7use self::malloc::KernelHeap;
8use self::proc::{Fork, Proc, ProcAbi, ProcMgr, Thread};
9use self::sched::sleep;
10use self::uma::Uma;
11use self::vm::Vm;
12use alloc::sync::Arc;
13use core::mem::zeroed;
14use humansize::{DECIMAL, SizeFormatter};
15use krt::info;
16
17#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
18#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
19mod arch;
20mod config;
21mod context;
22mod event;
23mod imgact;
24mod imgfmt;
25mod lock;
26mod malloc;
27mod proc;
28mod sched;
29mod signal;
30mod subsystem;
31mod trap;
32mod uma;
33mod vm;
34
35extern crate alloc;
36
37/// This will be called by [`krt`] crate.
38///
39/// See Orbis kernel entry point for a reference.
40#[cfg_attr(target_os = "none", unsafe(no_mangle))]
41fn main(config: &'static ::config::Config) -> ! {
42    // SAFETY: This function has a lot of restrictions. See Context documentation for more details.
43    info!("Starting Obliteration Kernel.");
44
45    // Setup the CPU after the first print to let the bootloader developer know (some of) their code
46    // are working.
47    let config = Config::new(config);
48    let arch = unsafe { self::arch::setup_main_cpu() };
49
50    // Setup proc0 to represent the kernel.
51    let proc0 = Proc::new_bare(Arc::new(Proc0Abi));
52
53    // Setup thread0 to represent this thread.
54    let proc0 = Arc::new(proc0);
55    let thread0 = Thread::new_bare(proc0);
56
57    // Activate CPU context.
58    let thread0 = Arc::new(thread0);
59
60    unsafe { self::context::run_with_context(config, arch, 0, thread0, setup, run) };
61}
62
63fn setup() -> ContextSetup {
64    // Run sysinit vector for subsystem. The Orbis use linker to put all sysinit functions in a list
65    // then loop the list to execute all of it. We manually execute those functions instead for
66    // readability. This also allow us to pass data from one function to another function. See
67    // mi_startup function on the Orbis for a reference.
68    let procs = ProcMgr::new();
69    let uma = init_vm(); // 161 on PS4 11.00.
70
71    ContextSetup { uma, pmgr: procs }
72}
73
74fn run() -> ! {
75    // Activate stage 2 heap.
76    info!("Activating stage 2 heap.");
77
78    unsafe { KERNEL_HEAP.activate_stage2() };
79
80    // Run remaining sysinit vector.
81    create_init(); // 659 on PS4 11.00.
82    swapper(); // 1119 on PS4 11.00.
83}
84
85/// See `vm_mem_init` function on the Orbis for a reference.
86///
87/// # Reference offsets
88/// | Version | Offset |
89/// |---------|--------|
90/// |PS4 11.00|0x39A390|
91fn init_vm() -> Arc<Uma> {
92    // Initialize VM.
93    let vm = Vm::new().unwrap();
94
95    info!(
96        concat!(
97            "Initial memory size: {} ({})\n",
98            "Boot area          : {:#x}"
99        ),
100        vm.initial_memory_size(),
101        SizeFormatter::new(vm.initial_memory_size(), DECIMAL),
102        vm.boot_area()
103    );
104
105    // Initialize UMA.
106    Uma::new(vm)
107}
108
109/// See `create_init` function on the Orbis for a reference.
110///
111/// # Reference offsets
112/// | Version | Offset |
113/// |---------|--------|
114/// |PS4 11.00|0x2BEF30|
115fn create_init() {
116    let pmgr = current_procmgr().unwrap();
117    let abi = Arc::new(Ps4Abi);
118    let flags = Fork::CopyFd | Fork::CreateProcess;
119
120    pmgr.fork(abi, flags).unwrap();
121
122    todo!()
123}
124
125/// See `scheduler` function on the PS4 for a reference.
126fn swapper() -> ! {
127    // TODO: Subscribe to "system_suspend_phase2_pre_sync" and "system_resume_phase2" event.
128    let procs = current_procmgr().unwrap();
129
130    loop {
131        // TODO: Implement a call to vm_page_count_min().
132        let procs = procs.list();
133
134        if procs.len() == 0 {
135            // TODO: The PS4 check for some value for non-zero but it seems like that value always
136            // zero.
137            sleep();
138            continue;
139        }
140
141        todo!();
142    }
143}
144
145/// Implementation of [`ProcAbi`] for kernel process.
146///
147/// See `null_sysvec` on the PS4 for a reference.
148struct Proc0Abi;
149
150impl ProcAbi for Proc0Abi {
151    /// See `null_fetch_syscall_args` on the PS4 for a reference.
152    fn syscall_handler(&self) {
153        unimplemented!()
154    }
155}
156
157// SAFETY: PRIMITIVE_HEAP is a mutable static so it valid for reads and writes. This will be safe as
158// long as no one access PRIMITIVE_HEAP.
159#[allow(dead_code)]
160#[cfg_attr(target_os = "none", global_allocator)]
161static KERNEL_HEAP: KernelHeap = unsafe { KernelHeap::new(&raw mut PRIMITIVE_HEAP) };
162static mut PRIMITIVE_HEAP: [u8; 1024 * 1024] = unsafe { zeroed() };