diff --git a/core/embed/rust/src/debug.rs b/core/embed/rust/src/debug.rs new file mode 100644 index 0000000000..17297b0313 --- /dev/null +++ b/core/embed/rust/src/debug.rs @@ -0,0 +1,33 @@ +use ufmt; + +#[cfg(feature = "micropython")] +use crate::micropython; + +pub struct DebugConsole; + +impl ufmt::uWrite for DebugConsole { + type Error = core::convert::Infallible; + + fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { + #[cfg(feature = "micropython")] + micropython::print::print(s); + + // TODO: add alternative if micropython is not available + + Ok(()) + } +} + +#[macro_export] +macro_rules! dbg_println { + ($($args:tt)*) => { + ufmt::uwriteln!($crate::debug::DebugConsole, $($args)*).ok(); + }; +} + +#[macro_export] +macro_rules! dbg_print { + ($($args:tt)*) => { + ufmt::uwrite!($crate::debug::DebugConsole, $($args)*).ok(); + }; +} diff --git a/core/embed/rust/src/lib.rs b/core/embed/rust/src/lib.rs index 3727d38d32..c51044faad 100644 --- a/core/embed/rust/src/lib.rs +++ b/core/embed/rust/src/lib.rs @@ -39,6 +39,10 @@ pub mod translations; pub mod ui; pub mod strutil; +#[cfg(feature = "debug")] +#[macro_use] +pub mod debug; + #[cfg(feature = "debug")] #[cfg(not(test))] #[panic_handler] @@ -48,13 +52,8 @@ pub mod strutil; fn panic_debug(panic_info: &core::panic::PanicInfo) -> ! { // Filling at least the file and line information, if available. // TODO: find out how to display message from panic_info.message() - if let Some(location) = panic_info.location() { - let file = location.file(); - print!(file); - print!(":"); - println!(inttostr!(location.line())); - trezorhal::fatal_error::__fatal_error("", "rs", file, location.line(), ""); + trezorhal::fatal_error::__fatal_error("", "rs", location.file(), location.line(), ""); } else { trezorhal::fatal_error::__fatal_error("", "rs", "", 0, ""); } diff --git a/core/embed/rust/src/trezorhal/fatal_error.rs b/core/embed/rust/src/trezorhal/fatal_error.rs index 64c8fbdc02..8f66c6bc47 100644 --- a/core/embed/rust/src/trezorhal/fatal_error.rs +++ b/core/embed/rust/src/trezorhal/fatal_error.rs @@ -10,6 +10,9 @@ use crate::ui::{ ui_features::{ModelUI, UIFeaturesCommon}, }; +#[cfg(feature = "debug")] +use crate::dbg_println; + fn shutdown() -> ! { unsafe { ffi::trezor_shutdown() } } @@ -32,6 +35,23 @@ pub fn error_shutdown(title: &str, msg: &str, footer: &str) -> ! { /// In debug mode, also prints the error message to the console. #[inline(never)] // saves few kilobytes of flash pub fn __fatal_error(_expr: &str, msg: &str, _file: &str, _line: u32, _func: &str) -> ! { + #[cfg(feature = "debug")] + { + dbg_println!("=== FATAL ERROR"); + + if _line != 0 { + dbg_println!("Location: {}:{}", _file, _line); + } + if !_expr.is_empty() { + dbg_println!("Expression: {}", _expr); + } + if !msg.is_empty() { + dbg_println!("Message: {}", msg); + } + + dbg_println!("==="); + } + error_shutdown("INTERNAL_ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD"); } diff --git a/core/embed/rust/src/ui/shape/display/bumps.rs b/core/embed/rust/src/ui/shape/display/bumps.rs index 70e0621347..c9af25872f 100644 --- a/core/embed/rust/src/ui/shape/display/bumps.rs +++ b/core/embed/rust/src/ui/shape/display/bumps.rs @@ -66,15 +66,15 @@ where }; } -// This function enables nested invocations of `run_with_bumps()`, -// which is necessary when the application needs to display a -// fatal error message and subsequently terminate. -// -// SAFETY: -// This function must be invoked exclusively in failure scenarios -// where the application is required to display a fatal error -// message and then shut down. It is safe to call this function -// only under these specific conditions. +/// This function enables nested invocations of `run_with_bumps()`, +/// which is necessary when the application needs to display a +/// fatal error message and subsequently terminate. +/// +/// # Safety +/// This function must be invoked exclusively in failure scenarios +/// where the application is required to display a fatal error +/// message and then shut down. It is safe to call this function +/// only under these specific conditions. pub unsafe fn unlock_bumps_on_failure() { // The application is single-threaded, so we can safely use a // static variable as a lock against nested calls.