From 8b5be6ebc014fed9e82553cf25c14d06aa60007d Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 12 Jun 2018 19:25:53 +0200 Subject: [PATCH] Implement code for integration test post --- Cargo.toml | 2 ++ src/bin/test-basic-boot.rs | 37 +++++++++++++++++++++++++++++++++++++ src/bin/test-panic.rs | 27 +++++++++++++++++++++++++++ src/lib.rs | 24 ++++++++++++++++++++++++ src/main.rs | 14 ++------------ src/serial.rs | 31 +++++++++++++++++++++++++++++++ src/vga_buffer.rs | 2 ++ 7 files changed, 125 insertions(+), 12 deletions(-) create mode 100644 src/bin/test-basic-boot.rs create mode 100644 src/bin/test-panic.rs create mode 100644 src/lib.rs create mode 100644 src/serial.rs diff --git a/Cargo.toml b/Cargo.toml index 880c1297..bd1ff4be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,8 @@ version = "0.2.0" [dependencies] spin = "0.4.6" volatile = "0.2.3" +uart_16550 = "0.1.0" +x86_64 = "0.2.0" [dependencies.lazy_static] version = "1.0" diff --git a/src/bin/test-basic-boot.rs b/src/bin/test-basic-boot.rs new file mode 100644 index 00000000..93655ff6 --- /dev/null +++ b/src/bin/test-basic-boot.rs @@ -0,0 +1,37 @@ +#![feature(panic_implementation)] // required for defining the panic handler +#![feature(const_fn)] +#![no_std] // don't link the Rust standard library +#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points + +// add the library as dependency (same crate name as executable) +#[macro_use] +extern crate blog_os; + +#[cfg(not(test))] +use core::panic::PanicInfo; +use blog_os::exit_qemu; + +/// This function is the entry point, since the linker looks for a function +/// named `_start_` by default. +#[cfg(not(test))] +#[no_mangle] // don't mangle the name of this function +pub extern "C" fn _start() -> ! { + serial_println!("ok"); + + unsafe { exit_qemu(); } + loop {} +} + + +/// This function is called on panic. +#[cfg(not(test))] +#[panic_implementation] +#[no_mangle] +pub fn panic(info: &PanicInfo) -> ! { + serial_println!("failed"); + + serial_println!("{}", info); + + unsafe { exit_qemu(); } + loop {} +} \ No newline at end of file diff --git a/src/bin/test-panic.rs b/src/bin/test-panic.rs new file mode 100644 index 00000000..a3ac10e3 --- /dev/null +++ b/src/bin/test-panic.rs @@ -0,0 +1,27 @@ +#![feature(panic_implementation)] +#![feature(const_fn)] +#![no_std] +#![cfg_attr(not(test), no_main)] + +#[macro_use] +extern crate blog_os; + +#[cfg(not(test))] +use core::panic::PanicInfo; +use blog_os::exit_qemu; + +#[cfg(not(test))] +#[no_mangle] +pub extern "C" fn _start() -> ! { + panic!(); +} + +#[cfg(not(test))] +#[panic_implementation] +#[no_mangle] +pub fn panic(_info: &PanicInfo) -> ! { + serial_println!("ok"); + + unsafe { exit_qemu(); } + loop {} +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..0c1b49e0 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,24 @@ +#![feature(const_fn)] +#![no_std] // don't link the Rust standard library + +extern crate spin; +extern crate volatile; +#[macro_use] +extern crate lazy_static; +extern crate uart_16550; +extern crate x86_64; + +#[cfg(test)] +extern crate array_init; +#[cfg(test)] +extern crate std; + +pub mod vga_buffer; +pub mod serial; + +pub unsafe fn exit_qemu() { + use x86_64::instructions::port::Port; + + let mut port = Port::::new(0xf4); + port.write(0); +} diff --git a/src/main.rs b/src/main.rs index f4efc5bf..7a96e4d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,22 +3,12 @@ #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(test, allow(dead_code, unused_macros))] // allow unused code in test mode -extern crate spin; -extern crate volatile; #[macro_use] -extern crate lazy_static; - -#[cfg(test)] -extern crate array_init; -#[cfg(test)] -extern crate std; +extern crate blog_os; #[cfg(not(test))] use core::panic::PanicInfo; -#[macro_use] -mod vga_buffer; - /// This function is the entry point, since the linker looks for a function /// named `_start_` by default. #[cfg(not(test))] @@ -36,4 +26,4 @@ pub extern "C" fn _start() -> ! { pub fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} -} +} \ No newline at end of file diff --git a/src/serial.rs b/src/serial.rs new file mode 100644 index 00000000..0ce097c1 --- /dev/null +++ b/src/serial.rs @@ -0,0 +1,31 @@ +use uart_16550::SerialPort; +use spin::Mutex; + +lazy_static! { + pub static ref SERIAL1: Mutex = { + let mut serial_port = SerialPort::new(0x3F8); + serial_port.init(); + Mutex::new(serial_port) + }; +} + +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 { + () => (serial_print!("\n")); + ($fmt:expr) => (serial_print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (serial_print!(concat!($fmt, "\n"), $($arg)*)); +} \ No newline at end of file diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs index 4033a276..8c956365 100644 --- a/src/vga_buffer.rs +++ b/src/vga_buffer.rs @@ -148,11 +148,13 @@ impl fmt::Write for Writer { } /// Like the `print!` macro in the standard library, but prints to the VGA text buffer. +#[macro_export] macro_rules! print { ($($arg:tt)*) => ($crate::vga_buffer::print(format_args!($($arg)*))); } /// Like the `print!` macro in the standard library, but prints to the VGA text buffer. +#[macro_export] macro_rules! println { () => (print!("\n")); ($fmt:expr) => (print!(concat!($fmt, "\n")));