aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNatasha Moongrave <natasha@256phi.eu>2026-02-17 20:49:06 +0100
committerNatasha Moongrave <natasha@256phi.eu>2026-02-17 20:49:06 +0100
commit85d391fb0d81186aac9917348c2fa400b789742b (patch)
tree9bd911d72d014811587b2401adda258885da30fc
parenta84b687bef49387cb622a81e27f9043fc1e5ee96 (diff)
configured tests, docs and macros
-rw-r--r--StrixKernel/src/lib.rs70
-rw-r--r--StrixKernel/src/serial.rs37
2 files changed, 107 insertions, 0 deletions
diff --git a/StrixKernel/src/lib.rs b/StrixKernel/src/lib.rs
new file mode 100644
index 0000000..0b659ea
--- /dev/null
+++ b/StrixKernel/src/lib.rs
@@ -0,0 +1,70 @@
+#![no_std]
+#![cfg_attr(test, no_main)]
+#![feature(custom_test_frameworks)]
+#![test_runner(crate::test_runner)]
+#![reexport_test_harness_main = "test_main"]
+
+use core::panic::PanicInfo;
+
+pub mod serial;
+pub mod vga_buffer;
+
+pub trait Testable {
+ fn run(&self) -> ();
+}
+
+impl<T> Testable for T
+where
+ T: Fn(),
+{
+ fn run(&self) {
+ serial_print!("{}...\t", core::any::type_name::<T>());
+ self();
+ serial_println!("[ok]");
+ }
+}
+
+pub fn test_runner(tests: &[&dyn Testable]) {
+ serial_println!("Running {} tests", tests.len());
+ for test in tests {
+ test.run();
+ }
+ exit_qemu(QemuExitCode::Success);
+}
+
+pub fn test_panic_handler(info: &PanicInfo) -> ! {
+ serial_println!("[failed]\n");
+ serial_println!("Error: {}\n", info);
+ exit_qemu(QemuExitCode::Failed);
+ loop {}
+}
+
+#[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);
+ }
+}
+
+/// Entry point for `cargo xtest`
+#[cfg(test)]
+#[unsafe(no_mangle)]
+pub extern "C" fn _start() -> ! {
+ test_main();
+ loop {}
+}
+
+#[cfg(test)]
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+ test_panic_handler(info)
+} \ No newline at end of file
diff --git a/StrixKernel/src/serial.rs b/StrixKernel/src/serial.rs
new file mode 100644
index 0000000..e8aeb33
--- /dev/null
+++ b/StrixKernel/src/serial.rs
@@ -0,0 +1,37 @@
+use lazy_static::lazy_static;
+use spin::Mutex;
+use uart_16550::SerialPort;
+
+lazy_static! {
+ pub static ref SERIAL1: Mutex<SerialPort> = {
+ let mut serial_port = unsafe { SerialPort::new(0x3F8) };
+ serial_port.init();
+ Mutex::new(serial_port)
+ };
+}
+
+#[doc(hidden)]
+pub fn _print(args: ::core::fmt::Arguments) {
+ use core::fmt::Write;
+ SERIAL1
+ .lock()
+ .write_fmt(args)
+ .expect("Printing to serial failed");
+}
+
+/// Prints to the host through the serial interface.
+#[macro_export]
+macro_rules! serial_print {
+ ($($arg:tt)*) => {
+ $crate::serial::_print(format_args!($($arg)*));
+ };
+}
+
+/// Prints to the host through the serial interface, appending a newline.
+#[macro_export]
+macro_rules! serial_println {
+ () => ($crate::serial_print!("\n"));
+ ($fmt:expr) => ($crate::serial_print!(concat!($fmt, "\n")));
+ ($fmt:expr, $($arg:tt)*) => ($crate::serial_print!(
+ concat!($fmt, "\n"), $($arg)*));
+} \ No newline at end of file