From d0ecdbef0073a5516c9b7ec56d346cf9f1febd14 Mon Sep 17 00:00:00 2001 From: natrixaeria Date: Sat, 9 Nov 2019 01:00:09 +0100 Subject: Create panic screen module with text buffer --- kernel/src/io/mod.rs | 1 + kernel/src/io/panic_screen.rs | 57 +++++++++++++++++++++++++++++++++++++++++++ kernel/src/io/vga_text.rs | 34 ++++++++------------------ kernel/src/lib.rs | 28 ++------------------- 4 files changed, 70 insertions(+), 50 deletions(-) create mode 100644 kernel/src/io/panic_screen.rs diff --git a/kernel/src/io/mod.rs b/kernel/src/io/mod.rs index 9ac924a..e5dc66f 100644 --- a/kernel/src/io/mod.rs +++ b/kernel/src/io/mod.rs @@ -1,3 +1,4 @@ pub mod qemu; pub mod serial; pub mod vga_text; +pub mod panic_screen; diff --git a/kernel/src/io/panic_screen.rs b/kernel/src/io/panic_screen.rs new file mode 100644 index 0000000..ce2c118 --- /dev/null +++ b/kernel/src/io/panic_screen.rs @@ -0,0 +1,57 @@ +use core::fmt::Write; +use crate::io::vga_text::{OStream, CharState, Color}; + +const PANIC_SCREEN_MESSAGE_BUFFER_SIZE: usize = 2048; + +struct TextBuffer<'a> { + dst: &'a mut [u8], + len: usize +} + +impl<'a> TextBuffer<'a> { + fn new(dst: &'a mut [u8]) -> Self { + Self { dst, len: 0 } + } + fn get(&'a mut self) -> &'a mut [u8] { + &mut self.dst[..self.len] + } +} + +impl<'a> core::fmt::Write for TextBuffer<'a> { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + if s.len() + self.len > self.dst.len() { + Err(core::fmt::Error) + } else { + let s = s.as_bytes(); + (&mut self.dst[self.len..self.len+s.len()]).clone_from_slice(s); + Ok(self.len += s.len()) + } + } +} + +pub fn show(args: Option<&core::fmt::Arguments>) { + let mut stderr = OStream::new(); + stderr.set_state(CharState::from_colors( + Color::LightRed, + Color::Red, + )); + stderr.clear(); + stderr.print(b"uff-os"); + stderr.set_row(10); + stderr.set_state(CharState::from_colors( + Color::White, + Color::Red, + )); + stderr.print_centered(b""); + stderr.set_row(14); + stderr.set_state(CharState::from_colors( + Color::Cyan, + Color::Red, + )); + stderr.set_centered(true); + let buffer: &mut [u8] = &mut [b' '; PANIC_SCREEN_MESSAGE_BUFFER_SIZE]; + let mut tbuffer = TextBuffer::new(buffer); + let _ = core::fmt::write(&mut tbuffer, *args.unwrap_or(&format_args!("no panic information obtainable"))); + stderr.print(tbuffer.get()); + stderr.set_centered(false); +} diff --git a/kernel/src/io/vga_text.rs b/kernel/src/io/vga_text.rs index 281a40a..eef56bf 100644 --- a/kernel/src/io/vga_text.rs +++ b/kernel/src/io/vga_text.rs @@ -103,7 +103,7 @@ impl OStream { pub fn put_char(&mut self, c: VgaChar) { if c.byte == b'\n' { self.new_line(); - } else if self.pos.0 >= WIDTH - 1 { + } else if self.pos.0 >= WIDTH { self.new_line(); self.put_char(c); } else { @@ -158,31 +158,17 @@ impl OStream { } pub fn print_centered(&mut self, s: &[u8]) { - let mut line = &s[..]; - let mut n = 0; - if s.len() == 0 { return; } - let slast = s.len() - 1; - for (i, &b) in s.iter().enumerate() { - if n >= WIDTH { - self.set_col(0); - self.put_bytes(&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 usize); - self.put_bytes(&line[..n]); + let mut line_start = 0; + let mut line_len = 0; + for (n, &c) in s.iter().enumerate() { + if line_len >= WIDTH || c == b'\n' || n == s.len() - 1 { + self.set_col((WIDTH - line_len) >> 1); + self.put_bytes(&s[line_start..(line_start+line_len+1)]); self.new_line(); - if i == slast { - return; - } - line = &line[(n + 1)..]; - n = 0; + line_start += line_len; + line_len = 0; } - n += 1; + line_len += 1; } } } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 15f027b..623f2bc 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -57,32 +57,8 @@ pub extern "C" fn _start() -> ! { #[panic_handler] #[no_mangle] pub extern "C" fn panic_handler(info: &core::panic::PanicInfo) -> ! { - let mut stderr = OStream::new(); - stderr.set_state(vga_text::CharState::from_colors( - vga_text::Color::LightRed, - vga_text::Color::Red, - )); - stderr.clear(); - stderr.print(b"uff-os"); - stderr.set_row(10); - stderr.set_state(vga_text::CharState::from_colors( - vga_text::Color::White, - vga_text::Color::Red, - )); - stderr.print_centered(b""); - stderr.set_row(14); - stderr.set_state(vga_text::CharState::from_colors( - vga_text::Color::Cyan, - vga_text::Color::Red, - )); - stderr.set_centered(true); - write!( - &mut stderr, - "{:?}", - info.message() - .unwrap_or(&format_args!("no panic information obtainable")) - ); - stderr.set_centered(false); + io::panic_screen::show(info.message()); + if cfg!(test) { write!(serial::SerialStream::new(), "Testing failed\n").unwrap(); qemu::exit_qemu(qemu::QemuExitCode::Failed); -- cgit v1.2.3-54-g00ecf From 3a3c7fa4cd0babe23a51fd1e50114612d2f53228 Mon Sep 17 00:00:00 2001 From: natrixaeria Date: Sat, 9 Nov 2019 01:26:48 +0100 Subject: Rewrite print_centered in a more pretty way --- kernel/src/io/vga_text.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/kernel/src/io/vga_text.rs b/kernel/src/io/vga_text.rs index eef56bf..833c191 100644 --- a/kernel/src/io/vga_text.rs +++ b/kernel/src/io/vga_text.rs @@ -160,15 +160,12 @@ impl OStream { pub fn print_centered(&mut self, s: &[u8]) { let mut line_start = 0; let mut line_len = 0; - for (n, &c) in s.iter().enumerate() { - if line_len >= WIDTH || c == b'\n' || n == s.len() - 1 { - self.set_col((WIDTH - line_len) >> 1); - self.put_bytes(&s[line_start..(line_start+line_len+1)]); - self.new_line(); - line_start += line_len; - line_len = 0; + for chunk in s.chunks(WIDTH) { + for line in chunk.split(|&c| c == b'\n') { + self.set_col((WIDTH - line.len()) >> 1); + self.put_bytes(line); + self.new_line() } - line_len += 1; } } } -- cgit v1.2.3-54-g00ecf From 405b2a3ed380931225095c65c80eba7f11f0faa4 Mon Sep 17 00:00:00 2001 From: natrixaeria Date: Sat, 9 Nov 2019 01:50:51 +0100 Subject: Adapt exception messages --- kernel/src/interrupts/exceptions.rs | 22 +++++++++++++++------- kernel/src/io/vga_text.rs | 9 +++++---- kernel/src/lib.rs | 11 +++++++++++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/kernel/src/interrupts/exceptions.rs b/kernel/src/interrupts/exceptions.rs index b6fb5a6..88c78a7 100644 --- a/kernel/src/interrupts/exceptions.rs +++ b/kernel/src/interrupts/exceptions.rs @@ -1,11 +1,19 @@ use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode}; +macro_rules! exception_default { + ($stack_frame: expr) => { + format_args!("instruction addr: 0x{:08x}\nstack addr: 0x{:08x}\nflags: 0x{:x}", + $stack_frame.instruction_pointer.as_u64(), + $stack_frame.cpu_flags, + $stack_frame.stack_pointer.as_u64() + ) + } +} + pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut InterruptStackFrame) { panic!( - "BREAKPOINT at {:x} Flags: {:b} Stack: {:x}", - stack_frame.instruction_pointer.as_u64(), - stack_frame.cpu_flags, - stack_frame.stack_pointer.as_u64() + "BREAKPOINT exception thrown\n\n{}", + exception_default!(stack_frame) ); } @@ -16,11 +24,11 @@ pub extern "x86-interrupt" fn page_fault_handler( use x86_64::registers::control::Cr2; panic!( - "PAGE FAULT while accessing address: {:x}{:?}Flags: {:b} Stack: {:x}", + "PAGE FAULT while accessing address: 0x{:08x}\nerror code: {:?}(0x{:x})\n{}", Cr2::read().as_u64(), error_code, - stack_frame.cpu_flags, - stack_frame.stack_pointer.as_u64() + error_code.bits(), + exception_default!(stack_frame) ); } diff --git a/kernel/src/io/vga_text.rs b/kernel/src/io/vga_text.rs index 833c191..277db73 100644 --- a/kernel/src/io/vga_text.rs +++ b/kernel/src/io/vga_text.rs @@ -160,10 +160,11 @@ impl OStream { pub fn print_centered(&mut self, s: &[u8]) { let mut line_start = 0; let mut line_len = 0; - for chunk in s.chunks(WIDTH) { - for line in chunk.split(|&c| c == b'\n') { - self.set_col((WIDTH - line.len()) >> 1); - self.put_bytes(line); + for line in s.split(|&c| c == b'\n') { + if line.is_empty() { self.new_line() } + for chunk in line.chunks(WIDTH) { + self.set_col((WIDTH - chunk.len()) >> 1); + self.put_bytes(chunk); self.new_line() } } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index d18ca6f..e18c22c 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -33,6 +33,17 @@ pub extern "C" fn _start() -> ! { test_main(); qemu::exit_qemu(qemu::QemuExitCode::Success); } + + fn _loop(i: u64) -> u64 { + if i > 0b1010101001101101 { + return i; + } + let n = i; + let mut stdout = OStream::new(); + write!(&mut stdout, "{:x}", &n as *const u64 as u64).unwrap(); + _loop(i + 1) + } + _loop(0); x86_64::instructions::interrupts::int3(); let stdout = OStream::new(); -- cgit v1.2.3-54-g00ecf From fdb9cbebc5eefbb89886eef86ab71dfac70cc39a Mon Sep 17 00:00:00 2001 From: natrixaeria Date: Sat, 9 Nov 2019 02:00:29 +0100 Subject: Add error messages --- kernel/src/interrupts/exceptions.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/kernel/src/interrupts/exceptions.rs b/kernel/src/interrupts/exceptions.rs index 88c78a7..057adbc 100644 --- a/kernel/src/interrupts/exceptions.rs +++ b/kernel/src/interrupts/exceptions.rs @@ -37,10 +37,9 @@ pub extern "x86-interrupt" fn segment_not_present_handler( error_code: u64, ) { panic!( - "SEGMENT NOT PRESENT: {:?}Flags: {:b} Stack: {:x}", + "SEGMENT NOT PRESENT exception\nerror code: 0x{:x}\n{}", error_code, - stack_frame.cpu_flags, - stack_frame.stack_pointer.as_u64() + exception_default!(stack_frame) ); } @@ -49,8 +48,7 @@ pub extern "x86-interrupt" fn double_fault_handler( _error_code: u64, // code is always zero ) { panic!( - "DOUBLE FAULT Flags: {:b} Stack: {:x}", - stack_frame.cpu_flags, - stack_frame.stack_pointer.as_u64() + "DOUBLE FAULT\nthis is a fatal exception\n{}", + exception_default!(stack_frame) ); } -- cgit v1.2.3-54-g00ecf From d7ca45f9986f1aef6cee256a581a38f824e21585 Mon Sep 17 00:00:00 2001 From: natrixaeria Date: Sat, 9 Nov 2019 02:03:23 +0100 Subject: Remove garbage code --- kernel/src/lib.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index e18c22c..d8b49b4 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -34,22 +34,8 @@ pub extern "C" fn _start() -> ! { qemu::exit_qemu(qemu::QemuExitCode::Success); } - fn _loop(i: u64) -> u64 { - if i > 0b1010101001101101 { - return i; - } - let n = i; - let mut stdout = OStream::new(); - write!(&mut stdout, "{:x}", &n as *const u64 as u64).unwrap(); - _loop(i + 1) - } - _loop(0); x86_64::instructions::interrupts::int3(); - let stdout = OStream::new(); - stdout.clear(); - panic!("panic! at the disco"); - /// TODO: write test ///fn _loop(i: u64) -> u64 { /// if i > 0b1010101001101101 { -- cgit v1.2.3-54-g00ecf