From 403c53fd6c7059c159db1604eb178251239fc4bf Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Mon, 4 Nov 2019 03:25:16 +0100 Subject: Implement serial connection and basic testing --- kernel/src/io/mod.rs | 2 +- kernel/src/io/qemu.rs | 15 ++++++++++++++ kernel/src/io/serial.rs | 53 +++++++++++++++++++++++++++++++---------------- kernel/src/io/vga_text.rs | 1 + kernel/src/lib.rs | 16 ++++++++------ 5 files changed, 62 insertions(+), 25 deletions(-) create mode 100644 kernel/src/io/qemu.rs (limited to 'kernel/src') diff --git a/kernel/src/io/mod.rs b/kernel/src/io/mod.rs index 8a0652e..9ac924a 100644 --- a/kernel/src/io/mod.rs +++ b/kernel/src/io/mod.rs @@ -1,3 +1,3 @@ +pub mod qemu; pub mod serial; pub mod vga_text; - diff --git a/kernel/src/io/qemu.rs b/kernel/src/io/qemu.rs new file mode 100644 index 0000000..8b01885 --- /dev/null +++ b/kernel/src/io/qemu.rs @@ -0,0 +1,15 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum QemuExitCode { + Success = 0x10, // The actual exit code is (value << 1) | 1. + 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); + } +} diff --git a/kernel/src/io/serial.rs b/kernel/src/io/serial.rs index e1d4660..2a3bae8 100644 --- a/kernel/src/io/serial.rs +++ b/kernel/src/io/serial.rs @@ -1,25 +1,42 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u32)] -pub enum QemuExitCode { - Success = 0x10, // The actual exit code is (value << 1) | 1. - Failed = 0x11, +use spin::Mutex; +use uart_16550::SerialPort; + +/*lazy_static! { + pub static ref SERIAL1: Mutex = { + let mut serial_port = unsafe { SerialPort::new(0x3F8) }; + serial_port.init(); + Mutex::new(serial_port) + }; +}*/ +const SERIAL_IO_PORT: u16 = 0x3F8; + +static CONNECTION: Mutex = Mutex::new(Serial { + initialized: false, + port: unsafe { SerialPort::new(SERIAL_IO_PORT) }, +}); + +struct Serial { + pub initialized: bool, + pub port: SerialPort, } -pub fn exit_qemu(exit_code: QemuExitCode) { - use x86_64::instructions::port::Port; +pub struct SerialStream {} - unsafe { - let mut port = Port::new(0xf4); - port.write(exit_code as u32); +impl SerialStream { + pub fn new() -> Self { + SerialStream {} } } -fn trivial_assertion() { - use crate::io::vga_text::OStream; - let mut stdout = OStream::new(); - stdout.clear(); - - stdout.print(b"trivial assertion... "); - assert_eq!(0, 1); - stdout.print(b"[ok]"); +impl core::fmt::Write for SerialStream { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + let mut guard = CONNECTION.lock(); + if !guard.initialized { + unsafe { + guard.port.init(); + } + guard.initialized = true; + } + guard.port.write_str(s) + } } diff --git a/kernel/src/io/vga_text.rs b/kernel/src/io/vga_text.rs index 34f13a8..fddb3e1 100644 --- a/kernel/src/io/vga_text.rs +++ b/kernel/src/io/vga_text.rs @@ -1,3 +1,4 @@ +#[allow(dead_code)] #[repr(u8)] pub enum Color { Black = 0, diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 74daa8a..8d967ad 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -10,8 +10,8 @@ extern crate compiler_builtins; mod io; use core::fmt::Write; -use io::vga_text; use io::vga_text::OStream; +use io::{qemu, serial, vga_text}; #[cfg(test)] pub fn test_runner(tests: &[&dyn Fn(&mut OStream)]) { @@ -26,6 +26,8 @@ pub fn test_runner(tests: &[&dyn Fn(&mut OStream)]) { #[test_case] fn test01(stdout: &mut OStream) { write!(stdout, "running test01 . . . OK"); + write!(serial::SerialStream::new(), "running test01 . . . OK\n"); + assert_eq!(0, 1); } #[no_mangle] @@ -33,16 +35,14 @@ pub extern "C" fn _start() -> ! { if cfg!(test) { #[cfg(test)] test_main(); - loop {} + qemu::exit_qemu(qemu::QemuExitCode::Success); } - let mut stdout = vga_text::OStream::new(); + let mut stdout = OStream::new(); stdout.clear(); write!(&mut stdout, "hello world!"); - // panic!("i has panicing"); - core::iter::successors(Some(0), |n| Some(n + 1)) .for_each(|n| write!(&mut stdout, "hello world {}!", n).unwrap()); @@ -52,7 +52,7 @@ pub extern "C" fn _start() -> ! { #[panic_handler] #[no_mangle] pub extern "C" fn panic_handler(_info: &core::panic::PanicInfo) -> ! { - let mut stderr = vga_text::OStream::new(); + let mut stderr = OStream::new(); stderr.set_state(vga_text::CharState::from_colors( vga_text::Color::LightRed, vga_text::Color::Red, @@ -75,5 +75,9 @@ pub extern "C" fn panic_handler(_info: &core::panic::PanicInfo) -> ! { vga_text::Color::Red, )); stderr.print_centered(text.as_bytes()); + if cfg!(test) { + write!(serial::SerialStream::new(), "Testing failed\n"); + qemu::exit_qemu(qemu::QemuExitCode::Failed); + } loop {} } -- cgit v1.2.3-54-g00ecf