From 0369e2b419e9a09525a5d097964b25bc6f78bf7b Mon Sep 17 00:00:00 2001 From: jeebuscrossaint Date: Fri, 5 Jul 2024 21:06:49 -0400 Subject: [PATCH] implement serial and serial println with better qemu --- Cargo.lock | 20 +++++++++++++++++++- Cargo.toml | 6 +++++- src/main.rs | 19 ++++++++++++++++--- src/serial.rs | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 src/serial.rs diff --git a/Cargo.lock b/Cargo.lock index c21bbbf..705b12a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.6.0" @@ -36,6 +42,7 @@ dependencies = [ "bootloader", "lazy_static", "spin 0.5.2", + "uart_16550", "volatile 0.2.7", "x86_64", ] @@ -58,6 +65,17 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "uart_16550" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614ff2a87880d4bd4374722268598a970bbad05ced8bf630439417347254ab2e" +dependencies = [ + "bitflags 1.3.2", + "rustversion", + "x86_64", +] + [[package]] name = "volatile" version = "0.2.7" @@ -77,7 +95,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96cb6fd45bfeab6a5055c5bffdb08768bd0c069f1d946debe585bbb380a7c062" dependencies = [ "bit_field", - "bitflags", + "bitflags 2.6.0", "rustversion", "volatile 0.4.6", ] diff --git a/Cargo.toml b/Cargo.toml index 4747565..01ce126 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ bootloader = "0.9" volatile = "0.2.6" spin = "0.5.2" x86_64 = "0.14.2" +uart_16550 = "0.2.0" #// DO NOTE THAT IN CARGO AS OF TO MY KNOWLEDGE 2019 AND EVEN NOW IN 2024 #// THERE IS A BUG IN CARGO WHERE THERE ARE "duplicate lang item" ERRORS @@ -26,5 +27,8 @@ version = "1.0" features = ["spin_no_std"] [package.metadata.bootimage] -test-args = ["-device", "isa-debug-exit,iobase=0xf4,iosize=0x04"] +test-args = [ + "-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "stdio", + "-display", "none" +] test-success-exit-code = 33 # (0x10 << 1) | 1 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 41e0ae1..7703c80 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,15 +6,27 @@ #![reexport_test_harness_main = "test_main"] mod vga_buffer; +mod serial; use core::panic::PanicInfo; /// This function is called on panic. +#[cfg(not(test))] // new attribute dropped ayyy #[panic_handler] fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } +// panic handler in test mode +#[cfg(test)] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + serial_println!("[failed]\n"); + serial_println!("Error: {}\n", info); + exit_qemu(QemuExitCode::Failed); + loop {} +} + // from old vga implementation // static VGA_BUF: &[u8] = b"Hello, world!"; @@ -58,6 +70,7 @@ pub extern "C" fn _start() -> ! { // FOR A PROFILE IN THE CARGO.TOML FILE #[cfg(test)] fn test_runner(tests: &[&dyn Fn()]) { + serial_println!("Running {} tests", tests.len()); println!("Running {} tests", tests.len()); for test in tests { test(); @@ -68,9 +81,9 @@ fn test_runner(tests: &[&dyn Fn()]) { #[test_case] fn trivial_assertion() { - print!("trivial assertion... "); - assert_eq!(1, 1); - println!("[ok]"); + serial_print!("trivial assertion... "); + assert_eq!(0, 1); + serial_println!("[ok]"); } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/src/serial.rs b/src/serial.rs new file mode 100644 index 0000000..07129bb --- /dev/null +++ b/src/serial.rs @@ -0,0 +1,34 @@ +use uart_16550::SerialPort; +use spin::Mutex; +use lazy_static::lazy_static; + +lazy_static! { + pub static ref SERIAL1: Mutex = { + 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