Testing, remove cursor, print logo

This commit is contained in:
Piotr Siuszko 2021-09-26 20:50:57 +02:00
parent 692e770cf2
commit 172c967095
7 changed files with 138 additions and 86 deletions

View File

@ -7,7 +7,8 @@ edition = "2018"
[dependencies]
bootloader = "0.9.19"
x86_64 = "0.14.6"
spin = "0.5.2"
spin = "0.9.2"
uart_16550 = "0.2.0"
[dependencies.lazy_static]
version = "1.0"
@ -15,7 +16,9 @@ features = ["spin_no_std"]
[package.metadata.bootimage]
build-command = ["build"]
test-args = ["-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "stdio",
"-display", "none"]
run-command = [
"qemu-system-x86_64", "-drive", "format=raw,file={}"
]
test-success-exit-code = 33 # (0x10 << 1) | 1

View File

@ -1,54 +0,0 @@
use crate::color::Color;
use core::fmt;
pub struct Cursor {
pub position: isize,
pub foreground: Color,
pub background: Color,
}
impl Cursor {
pub fn color(&self) -> u8 {
let fg = self.foreground as u8;
let bg = (self.background as u8) << 4;
fg | bg
}
pub fn print(&mut self, text: &[u8]) {
let color = self.color();
let framebuffer = 0xb8000 as *mut u8;
for &character in text {
unsafe {
framebuffer.offset(self.position).write_volatile(character);
framebuffer.offset(self.position + 1).write_volatile(color);
}
self.position += 2;
}
}
pub fn clr(&mut self) {
self.position = 0;
for _ in 0..(80 * 25) {
self.print(b" ");
}
self.position = 0;
}
}
impl Default for Cursor {
fn default() -> Self {
Cursor {
position: 0,
foreground: Color::Green,
background: Color::DarkGray,
}
}
}
impl fmt::Write for Cursor {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.print(s.as_bytes());
Ok(())
}
}

View File

@ -1,48 +1,62 @@
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]
#![no_std]
#![no_main]
use core::fmt::Write;
use core::panic::PanicInfo;
use x86_64::instructions::hlt;
mod color;
mod cursor;
mod serial;
mod vga_buffer;
use color::{Color, ColorCode};
use cursor::Cursor;
use vga_buffer::*;
mod testable;
mod utils;
pub fn print_something() {
let mut writer = Writer {
column_position: 0,
color_code: ColorCode::new(Color::Yellow, Color::Black),
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
};
writer.write_byte(b'H');
writer.write_string("ello ");
writer.write_string("Wörld!\n");
writer.write_string("Awruk!\n");
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
serial_println!("Running {} tests", tests.len());
for test in tests {
use testable::Testable;
test.run();
}
utils::exit_qemu(utils::QemuExitCode::Success);
}
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info);
#[test_case]
fn trivial_assertion() {
assert_eq!(1, 1);
}
loop {
hlt();
}
#[cfg(not(test))]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
println!("{}", info);
loop {}
}
#[cfg(test)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
serial_println!("[failed]\n");
serial_println!("Error: {}\n", info);
utils::exit_qemu(utils::QemuExitCode::Failed);
loop {}
}
#[no_mangle]
pub extern "C" fn _start() -> ! {
print_something();
println!("DSADSA");
println!("Test {}", 5132.31);
utils::print_logo();
println!("");
println!("Welcome!");
println!("Awruk!");
println!("Test value: {}\n", 5132.31);
#[cfg(test)]
test_main();
// panic!("help!");
loop {
hlt();

37
src/serial.rs Normal file
View File

@ -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)*));
}

16
src/testable.rs Normal file
View File

@ -0,0 +1,16 @@
use crate::{serial_print,serial_println};
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]");
}
}

29
src/utils.rs Normal file
View File

@ -0,0 +1,29 @@
use crate::println;
#[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 print_logo() {
let text = r###"
_ _ __
_ |_ |_) _ _|_/ \(_
(_ | || \|_|_> |_\_/__)
"###;
crate::vga_buffer::change_color(crate::color::Color::BrightRed);
println!("{}", text);
crate::vga_buffer::reset_color();
}

View File

@ -6,7 +6,7 @@ use spin::Mutex;
lazy_static! {
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer {
column_position: 0,
color_code: ColorCode::new(Color::Yellow, Color::Black),
color_code: ColorCode::new(Color::White, Color::Black),
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
});
}
@ -44,10 +44,9 @@ impl Writer {
let row = BUFFER_HEIGHT - 1;
let col = self.column_position;
let color_code = self.color_code;
let screen_char = ScreenChar {
ascii_character: byte,
color_code,
color_code: self.color_code,
};
unsafe {
core::ptr::write_volatile(&mut self.buffer.chars[row][col], screen_char);
@ -101,6 +100,14 @@ impl fmt::Write for Writer {
}
}
pub fn change_color(color : Color) {
WRITER.lock().color_code = ColorCode::new(color, Color::Black);
}
pub fn reset_color() {
WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black);
}
#[macro_export]
macro_rules! print {
($($arg:tt)*) => ($crate::vga_buffer::_print(format_args!($($arg)*)));