Skip to content

Commit

Permalink
Add emergency_console
Browse files Browse the repository at this point in the history
  • Loading branch information
gifnksm committed May 18, 2021
1 parent 457490e commit 159f253
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 30 deletions.
47 changes: 47 additions & 0 deletions src/emergency_console.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::{
font,
framebuffer::{self, Drawer, ScreenInfo},
graphics::{Color, Draw, Point, Rectangle},
};
use core::fmt;

pub(crate) fn with_console(f: impl FnOnce(&mut EmergencyConsole<'_>)) -> ! {
let screen_info = *framebuffer::info();
let mut drawer = unsafe { framebuffer::emergency_lock_drawer() };
let mut console = EmergencyConsole {
screen_info,
pos: Point::new(0, 0),
drawer: &mut *drawer,
};

f(&mut console);

crate::hlt_loop();
}

pub(crate) struct EmergencyConsole<'a> {
screen_info: ScreenInfo,
pos: Point<i32>,
drawer: &'a mut Drawer,
}

impl fmt::Write for EmergencyConsole<'_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
for ch in s.chars() {
if ch != '\n' {
self.drawer.fill_rect(
Rectangle::new(self.pos, font::FONT_PIXEL_SIZE),
Color::WHITE,
);
font::draw_char(self.drawer, self.pos, ch, Color::RED);
self.pos.x += font::FONT_PIXEL_SIZE.x;
}

if ch == '\n' || self.pos.x + font::FONT_PIXEL_SIZE.x > self.screen_info.width {
self.pos.y += font::FONT_PIXEL_SIZE.y;
self.pos.x = 0;
}
}
Ok(())
}
}
14 changes: 7 additions & 7 deletions src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ pub(crate) fn char_to_byte(ch: char) -> u8 {
u8::try_from(codepoint).unwrap_or(b'?')
}

// pub(crate) fn draw_char<D>(drawer: &mut D, pos: Point<i32>, ch: char, color: Color)
// where
// D: Draw,
// {
// let byte = char_to_byte(ch);
// draw_byte(drawer, pos, byte, color)
// }
pub(crate) fn draw_char<D>(drawer: &mut D, pos: Point<i32>, ch: char, color: Color)
where
D: Draw,
{
let byte = char_to_byte(ch);
draw_byte(drawer, pos, byte, color)
}

// pub(crate) fn draw_str<D>(drawer: &mut D, pos: Point<i32>, s: &str, color: Color)
// where
Expand Down
9 changes: 9 additions & 0 deletions src/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ pub(crate) fn lock_drawer() -> MutexGuard<'static, Drawer> {
DRAWER.get().lock()
}

pub(crate) unsafe fn emergency_lock_drawer() -> MutexGuard<'static, Drawer> {
let drawer = DRAWER.get();
if let Ok(drawer) = drawer.try_lock() {
return drawer;
}
unsafe { drawer.force_unlock() };
drawer.lock()
}

#[derive(Debug, Clone, Copy)]
pub(crate) struct ScreenInfo {
pub(crate) width: i32,
Expand Down
44 changes: 23 additions & 21 deletions src/interrupt.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{println, sync::once_cell::OnceCell, xhc};
use crate::{emergency_console, println, sync::once_cell::OnceCell, xhc};
use core::fmt::Write as _;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -50,42 +51,43 @@ extern "x86-interrupt" fn page_fault_handler(
) {
use x86_64::registers::control::Cr2;

println!("EXCEPTION: PAGE FAULT");
println!("Accessed Address: {:?}", Cr2::read());
println!("Error Code: {:x}", error_code);
println!("{:#?}", stack_frame);

crate::hlt_loop();
emergency_console::with_console(|console| {
let _ = writeln!(console, "EXCEPTION: PAGE FAULT");
let _ = writeln!(console, "Accessed Address: {:?}", Cr2::read());
let _ = writeln!(console, "Error Code: {:x}", error_code);
let _ = writeln!(console, "{:#?}", stack_frame);
});
}

extern "x86-interrupt" fn general_protection_fault_handler(
stack_frame: InterruptStackFrame,
error_code: u64,
) {
println!("EXCEPTION: GENERAL PROTECTION FAULT");
println!("Error Code: {:x}", error_code);
println!("{:#?}", stack_frame);

crate::hlt_loop();
emergency_console::with_console(|console| {
let _ = writeln!(console, "EXCEPTION: GENERAL PROTECTION FAULT");
let _ = writeln!(console, "Error Code: {:x}", error_code);
let _ = writeln!(console, "{:#?}", stack_frame);
});
}

extern "x86-interrupt" fn segment_not_present_handler(
stack_frame: InterruptStackFrame,
error_code: u64,
) {
println!("EXCEPTION: STACK NOT PRESENT");
println!("Error Code: {:x}", error_code);
println!("{:#?}", stack_frame);

crate::hlt_loop();
emergency_console::with_console(|console| {
let _ = writeln!(console, "EXCEPTION: STACK NOT PRESENT");
let _ = writeln!(console, "Error Code: {:x}", error_code);
let _ = writeln!(console, "{:#?}", stack_frame);
});
}

extern "x86-interrupt" fn double_fault_handler(
stack_frame: InterruptStackFrame,
error_code: u64,
) -> ! {
panic!(
"EXCEPTION: DOUBLE FAULT\nError Code: {:x}\n{:#?}",
error_code, stack_frame
);
emergency_console::with_console(|console| {
let _ = writeln!(console, "EXCEPTION: DOUBLE FAULT",);
let _ = writeln!(console, "Error Code: {:x}", error_code);
let _ = writeln!(console, "{:#?}", stack_frame);
});
}
7 changes: 5 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod co_task;
mod console;
mod cxx_support;
mod desktop;
mod emergency_console;
mod error;
mod font;
mod framebuffer;
Expand Down Expand Up @@ -117,6 +118,8 @@ fn hlt_loop() -> ! {
#[cfg(not(test))]
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
error!("{}", info);
hlt_loop();
use core::fmt::Write as _;
emergency_console::with_console(|console| {
let _ = write!(console, "{}", info);
});
}
4 changes: 4 additions & 0 deletions src/sync/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ where
pub(crate) fn try_lock(&self) -> Result<MutexGuard<'_, T>> {
Ok(self.0.try_lock().ok_or(ErrorKind::Deadlock)?)
}

pub(crate) unsafe fn force_unlock(&self) {
unsafe { self.0.force_unlock() }
}
}

0 comments on commit 159f253

Please sign in to comment.