From 6c09097e5441eafc971c8d5d414963a4e66a892f Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Thu, 31 Oct 2019 21:06:46 +0100 Subject: Add testing to build --- kernel/build.sh | 27 +++++-- kernel/src/io/mod.rs | 3 + kernel/src/io/serial.rs | 26 +++++++ kernel/src/io/text_buffer.rs | 0 kernel/src/io/vga_text.rs | 170 +++++++++++++++++++++++++++++++++++++++++++ kernel/src/vga_text.rs | 167 ------------------------------------------ 6 files changed, 219 insertions(+), 174 deletions(-) create mode 100644 kernel/src/io/mod.rs create mode 100644 kernel/src/io/serial.rs create mode 100644 kernel/src/io/text_buffer.rs create mode 100644 kernel/src/io/vga_text.rs delete mode 100644 kernel/src/vga_text.rs diff --git a/kernel/build.sh b/kernel/build.sh index d8086b6..86842b1 100755 --- a/kernel/build.sh +++ b/kernel/build.sh @@ -9,10 +9,13 @@ GRUB_CFG_PATH="src/grub.cfg" ARCH="x86_64" TARGET="$ARCH-uff" RUST_BIN="$TARGET_PATH/$TARGET/debug/libkernel.a" +QUEMU="qemu-system-x86_64 -cdrom $TARGET_PATH/uff.iso" -remove_target() { - rm -rf $TMP_PATH/* &> /dev/null +cleanup_target() { rm -f $TARGET_PATH/uff.iso &> /dev/null + rm -rf $TARGET_PATH/kernel.bin + + cleanup_temp } create_target() { @@ -54,7 +57,11 @@ build_init() { } build_launch() { - qemu-system-x86_64 -cdrom $TARGET_PATH/uff.iso + $QUEMU +} + +build_launch_serial() { + $QEMU -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio #-display none } build_run() { @@ -65,16 +72,20 @@ build_run() { } build_clean() { - remove_target + cleanup_target } build_build() { cargo xbuild - rm -rf $TARGET_PATH/sysroot - rm -rf $TARGET_PATH/kernel.bin - rm -rf $TARGET_PATH/uff.iso + cleanup_target build_run } +build_build() { + cargo xbuild --features testing + cleanup_target + build_kernel_iso + build_launch_serial +} build_all() { build_kernel_elf @@ -91,6 +102,7 @@ for arg in "$@"; do "run") build_run;; "clean") build_clean;; "build") build_build;; + "test") build_tests;; "all") build_all;; *) echo "warn: ignoring unknown option '$arg'" @@ -107,6 +119,7 @@ print_help() { echo " clean cleanup binaries" echo " launch launch iso in qemu" echo " run creates iso if necessary and runs it in qemu" + echo " test runs tests in qemu" echo echo " kernel-elf build the kernel-elf" echo " kernel-iso build the kernel-elf if necessary and the kernel-iso" diff --git a/kernel/src/io/mod.rs b/kernel/src/io/mod.rs new file mode 100644 index 0000000..8a0652e --- /dev/null +++ b/kernel/src/io/mod.rs @@ -0,0 +1,3 @@ +pub mod serial; +pub mod vga_text; + diff --git a/kernel/src/io/serial.rs b/kernel/src/io/serial.rs new file mode 100644 index 0000000..bab770d --- /dev/null +++ b/kernel/src/io/serial.rs @@ -0,0 +1,26 @@ +#[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); + } +} + +#[test_case] +fn trivial_assertion() { + use crate::vga_text::OStream; + let mut stdout = OStream::new(); + stdout.clear(); + + stdout.print(b"trivial assertion... "); + assert_eq!(0, 1); + stdout.print(b"[ok]"); +} diff --git a/kernel/src/io/text_buffer.rs b/kernel/src/io/text_buffer.rs new file mode 100644 index 0000000..e69de29 diff --git a/kernel/src/io/vga_text.rs b/kernel/src/io/vga_text.rs new file mode 100644 index 0000000..f60e6e1 --- /dev/null +++ b/kernel/src/io/vga_text.rs @@ -0,0 +1,170 @@ +#[repr(u8)] +pub enum Color { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + Pink = 13, + Yellow = 14, + White = 15, +} + +pub const WIDTH = 80; +pub const HEIGHT = 25; + +#[derive(Clone, Copy)] +pub struct CharState(pub u8); + +impl CharState { + pub fn from_colors(fg: Color, bg: Color) -> Self { + Self((fg as u8) | ((bg as u8) << 4)) + } + + pub fn set_fg(&mut self, fg: Color) { + self.0 = (self.0 & HEIGHT - 10) | (fg as u8) + } + + pub fn set_bg(&mut self, bg: Color) { + self.0 = (self.0 & 15) | ((bg as u8) << 4) + } +} + +#[no_mangle] +#[derive(Clone, Copy)] +pub struct VgaChar { + pub byte: u8, + pub state: CharState, +} + +impl VgaChar { + pub fn from_state_and_byte(state: CharState, byte: u8) -> Self { + Self{ state, byte } + } +} + +pub struct OStream { + pos: (u8, u8), + cursor: *mut VgaChar, + state: CharState, +} + +impl OStream { + pub fn new() -> Self { + Self { + pos: (0, 0), + cursor: Self::at(0), + state: CharState::from_colors(Color::White, Color::Black) + } + } + + fn at(n: usize) -> *mut VgaChar { + (0xbWIDTH00 + (n << 1)) as *mut VgaChar + } + + fn compute_cursor(&mut self) { + self.cursor = Self::at(self.pos.0 as usize + self.pos.1 as usize * WIDTH) + } + + pub fn set_col(&mut self, col: u8) { + self.pos.0 = core::cmp::min(col, WIDTH - 1); + self.compute_cursor() + } + + pub fn set_row(&mut self, row: u8) { + self.pos.1 = core::cmp::min(row, HEIGHT - 1); + self.compute_cursor() + } + + pub fn set_cursor(&mut self, col: u8, row: u8) { + self.pos = (core::cmp::min(col, WIDTH - 1), core::cmp::min(row, HEIGHT - 1)); + self.compute_cursor() + } + + pub fn set_char(&mut self, c: VgaChar) { + unsafe {self.cursor.write_volatile(c)} + } + + pub fn put_char(&mut self, c: VgaChar) { + if c.byte == b'\n' { + self.new_line(); + } else if self.pos.0 >= WIDTH - 1 { + self.new_line(); + self.put_char(c); + } else { + self.set_char(c); + self.cursor = self.cursor.wrapping_offset(1); + self.pos.0 += 1; + } + } + + pub fn put_byte(&mut self, b: u8) { + self.put_char(VgaChar::from_state_and_byte(self.state, b)) + } + + pub fn clear(&self) { + let c = VgaChar::from_state_and_byte(self.state, b' '); + for i in 0..(WIDTH * HEIGHT) { + unsafe {Self::at(i).write_volatile(c)} + } + } + + pub fn new_line(&mut self) { + if self.pos.1 >= HEIGHT - 1 { + self.set_col(0); + for i in 0..1920 { + unsafe {Self::at(i).write_volatile(*Self::at(i + WIDTH))} + } + } else { + self.set_cursor(0, self.pos.1 + 1); + } + } + + pub fn set_state(&mut self, state: CharState) { + self.state = state + } + + pub fn print(&mut self, s: &[u8]) { + for &b in s { + self.put_byte(b) + } + } + + pub fn print_centered(&mut self, s: &[u8]) { + let mut line = &s[..]; + let mut n = 0; + let slast = s.len() - 1; + for (i, &b) in s.iter().enumerate() { + if n >= WIDTH { + self.set_col(0); + self.print(&line[..WIDTH]); + line = &line[WIDTH..]; + n = 0; + } + if b == b'\n' || i == slast { + if b != b'\n' { n += 1 } + self.set_col(((WIDTH - n) / 2) as u8); + self.print(&line[..n]); + self.new_line(); + if i == slast { return; } + line = &line[(n+1)..]; + n = 0; + } + n += 1; + } + } +} + +impl core::fmt::Write for OStream { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + Ok(self.print(s.as_bytes())) + } +} diff --git a/kernel/src/vga_text.rs b/kernel/src/vga_text.rs deleted file mode 100644 index a292c8c..0000000 --- a/kernel/src/vga_text.rs +++ /dev/null @@ -1,167 +0,0 @@ -#[repr(u8)] -pub enum Color { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Magenta = 5, - Brown = 6, - LightGray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - Pink = 13, - Yellow = 14, - White = 15, -} - -#[derive(Clone, Copy)] -pub struct CharState(pub u8); - -impl CharState { - pub fn from_colors(fg: Color, bg: Color) -> Self { - Self((fg as u8) | ((bg as u8) << 4)) - } - - pub fn set_fg(&mut self, fg: Color) { - self.0 = (self.0 & 240) | (fg as u8) - } - - pub fn set_bg(&mut self, bg: Color) { - self.0 = (self.0 & 15) | ((bg as u8) << 4) - } -} - -#[no_mangle] -#[derive(Clone, Copy)] -pub struct VgaChar { - pub byte: u8, - pub state: CharState, -} - -impl VgaChar { - pub fn from_state_and_byte(state: CharState, byte: u8) -> Self { - Self{ state, byte } - } -} - -pub struct OStream { - pos: (u8, u8), - cursor: *mut VgaChar, - state: CharState, -} - -impl OStream { - pub fn new() -> Self { - Self { - pos: (0, 0), - cursor: Self::at(0), - state: CharState::from_colors(Color::White, Color::Black) - } - } - - fn at(n: usize) -> *mut VgaChar { - (0xb8000 + (n << 1)) as *mut VgaChar - } - - fn compute_cursor(&mut self) { - self.cursor = Self::at(self.pos.0 as usize + self.pos.1 as usize * 80) - } - - pub fn set_col(&mut self, col: u8) { - self.pos.0 = core::cmp::min(col, 79); - self.compute_cursor() - } - - pub fn set_row(&mut self, row: u8) { - self.pos.1 = core::cmp::min(row, 24); - self.compute_cursor() - } - - pub fn set_cursor(&mut self, col: u8, row: u8) { - self.pos = (core::cmp::min(col, 79), core::cmp::min(row, 24)); - self.compute_cursor() - } - - pub fn set_char(&mut self, c: VgaChar) { - unsafe {self.cursor.write_volatile(c)} - } - - pub fn put_char(&mut self, c: VgaChar) { - if c.byte == b'\n' { - self.new_line(); - } else if self.pos.0 >= 79 { - self.new_line(); - self.put_char(c); - } else { - self.set_char(c); - self.cursor = self.cursor.wrapping_offset(1); - self.pos.0 += 1; - } - } - - pub fn put_byte(&mut self, b: u8) { - self.put_char(VgaChar::from_state_and_byte(self.state, b)) - } - - pub fn clear(&self) { - let c = VgaChar::from_state_and_byte(self.state, b' '); - for i in 0..2000 { - unsafe {Self::at(i).write_volatile(c)} - } - } - - pub fn new_line(&mut self) { - if self.pos.1 >= 24 { - self.set_col(0); - for i in 0..1920 { - unsafe {Self::at(i).write_volatile(*Self::at(i + 80))} - } - } else { - self.set_cursor(0, self.pos.1 + 1); - } - } - - pub fn set_state(&mut self, state: CharState) { - self.state = state - } - - pub fn print(&mut self, s: &[u8]) { - for &b in s { - self.put_byte(b) - } - } - - pub fn print_centered(&mut self, s: &[u8]) { - let mut line = &s[..]; - let mut n = 0; - let slast = s.len() - 1; - for (i, &b) in s.iter().enumerate() { - if n >= 80 { - self.set_col(0); - self.print(&line[..80]); - line = &line[80..]; - n = 0; - } - if b == b'\n' || i == slast { - if b != b'\n' { n += 1 } - self.set_col(((80 - n) / 2) as u8); - self.print(&line[..n]); - self.new_line(); - if i == slast { return; } - line = &line[(n+1)..]; - n = 0; - } - n += 1; - } - } -} - -impl core::fmt::Write for OStream { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - Ok(self.print(s.as_bytes())) - } -} -- cgit v1.2.3-70-g09d2