1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#![no_std]
#![cfg_attr(test, no_main)]
#![feature(abi_x86_interrupt)]
#![feature(alloc_error_handler)]
#![feature(asm_sym)]
#![feature(naked_functions)]
#![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]
extern crate alloc;
#[macro_use]
pub mod api;
pub mod sys;
pub mod usr;
use bootloader::BootInfo;
const KERNEL_SIZE: usize = 2 << 20;
pub fn init(boot_info: &'static BootInfo) {
sys::vga::init();
sys::gdt::init();
sys::idt::init();
sys::pic::init();
sys::serial::init();
sys::keyboard::init();
sys::time::init();
log!("MOROS v{}\n", env!("CARGO_PKG_VERSION"));
sys::mem::init(boot_info);
sys::cpu::init();
sys::pci::init();
sys::net::init();
sys::ata::init();
sys::fs::init();
sys::clock::init();
}
#[alloc_error_handler]
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
panic!("allocation error: {:?}", layout)
}
pub trait Testable {
fn run(&self);
}
impl<T> Testable for T where T: Fn() {
fn run(&self) {
print!("test {} ... ", core::any::type_name::<T>());
self();
let csi_color = api::console::Style::color("LightGreen");
let csi_reset = api::console::Style::reset();
println!("{}ok{}", csi_color, csi_reset);
}
}
pub fn test_runner(tests: &[&dyn Testable]) {
let n = tests.len();
println!("\nrunning {} test{}", n, if n == 1 { "" } else { "s" });
for test in tests {
test.run();
}
exit_qemu(QemuExitCode::Success);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum QemuExitCode {
Success = 0x10,
Failed = 0x11,
}
pub fn exit_qemu(exit_code: QemuExitCode) {
use x86_64::instructions::port::Port;
unsafe {
let mut port = Port::new(0xf4);
port.write(exit_code as u32);
}
}
pub fn hlt_loop() -> ! {
loop {
x86_64::instructions::hlt();
}
}
#[cfg(test)]
use bootloader::entry_point;
#[cfg(test)]
use core::panic::PanicInfo;
#[cfg(test)]
entry_point!(test_kernel_main);
#[cfg(test)]
fn test_kernel_main(boot_info: &'static BootInfo) -> ! {
init(boot_info);
test_main();
hlt_loop();
}
#[cfg(test)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let csi_color = api::console::Style::color("LightRed");
let csi_reset = api::console::Style::reset();
println!("{}failed{}\n", csi_color, csi_reset);
println!("{}\n", info);
exit_qemu(QemuExitCode::Failed);
hlt_loop();
}
#[test_case]
fn trivial_assertion() {
assert_eq!(1, 1);
}