1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 06:48:16 +00:00

refactor(core): unify error screens

[no changelog]
This commit is contained in:
tychovrahe 2023-03-13 18:56:16 +01:00 committed by matejcik
parent 64bc94cbc9
commit 9b8984896e
13 changed files with 302 additions and 228 deletions

View File

@ -191,11 +191,11 @@ void ui_screen_done(int restart_seconds, secbool full_redraw) {
const char *str;
char count_str[24];
if (restart_seconds >= 1) {
mini_snprintf(count_str, sizeof(count_str), "DONE! RESTARTING IN %d",
mini_snprintf(count_str, sizeof(count_str), "RESTARTING IN %d",
restart_seconds);
str = count_str;
} else {
str = "DONE! RECONNECT THE DEVICE";
str = "RECONNECT THE DEVICE";
}
screen_install_success(str, initial_setup, full_redraw);

View File

@ -17,8 +17,8 @@ uint32_t screen_intro(const char* bld_version_str, const char* vendor_str,
uint8_t vendor_str_len, const char* version_str);
uint32_t screen_menu(const char* bld_version_str);
void screen_connect(void);
void screen_fatal_error_c(const char* msg, const char* file);
void screen_error_shutdown_c(const char* label, const char* msg);
void screen_fatal_error_rust(const char* title, const char* msg,
const char* footer);
void screen_wipe_success(void);
void screen_wipe_fail(void);
uint32_t screen_install_success(const char* reboot_msg, bool initial_setup,

View File

@ -6,11 +6,6 @@ mod ffi {
}
use crate::ui::screens::screen_fatal_error;
#[cfg(not(feature = "bootloader"))]
use heapless::String;
#[cfg(not(feature = "bootloader"))]
use crate::ui::util::u32_to_str;
fn shutdown() -> ! {
unsafe { ffi::trezor_shutdown() }
@ -18,22 +13,13 @@ fn shutdown() -> ! {
#[cfg(feature = "bootloader")]
pub fn __fatal_error(_expr: &str, _msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
screen_fatal_error(Some("BL.rs"), "BL.rs");
screen_fatal_error("BL.rs", "BL.rs", "PLEASE VISIT\nTREZOR.IO/RSOD");
shutdown()
}
#[cfg(not(feature = "bootloader"))]
pub fn __fatal_error(_expr: &str, msg: &str, file: &str, line: u32, _func: &str) -> ! {
let mut buf: String<256> = String::new();
let _ = buf.push_str(file); // Nothing we can do if this fails
let _ = buf.push_str(": ");
let mut line_buf = [0u8; 10];
if let Some(text) = u32_to_str(line, &mut line_buf) {
let _ = buf.push_str(text);
}
screen_fatal_error(Some(msg), buf.as_str());
pub fn __fatal_error(_expr: &str, msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
screen_fatal_error("FATAL ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
shutdown()
}

View File

@ -26,32 +26,23 @@ unsafe fn get_str(text: &str) -> StrBuffer {
unsafe { StrBuffer::from_ptr_and_len(text.as_ptr(), text.len()) }
}
pub fn screen_fatal_error(msg: Option<&str>, file: &str) {
pub fn screen_fatal_error(title: &str, msg: &str, footer: &str) {
// SAFETY: these will get placed into `frame` which does not outlive this
// function
let msg = msg.map(|s| unsafe { get_str(s) });
let file = unsafe { get_str(file) };
let title = unsafe { get_str(title) };
let msg = unsafe { get_str(msg) };
let footer = unsafe { get_str(footer) };
let m_top = if let Some(msg) = msg {
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_BOLD, "FATAL ERROR!".into()).centered());
messages.add(Paragraph::new(&TEXT_BOLD, title).centered());
messages.add(Paragraph::new(&TEXT_NORMAL, msg).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
} else {
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_BOLD, "FATAL ERROR!".into()).centered());
messages.add(Paragraph::new(&TEXT_NORMAL, file).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
};
let m_top =
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_BOLD, "PLEASE CONTACT".into()).centered());
messages.add(Paragraph::new(&TEXT_BOLD, "TREZOR SUPPORT".into()).centered());
messages.add(Paragraph::new(&TEXT_BOLD, footer).centered());
let m_bottom =
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
@ -60,34 +51,3 @@ pub fn screen_fatal_error(msg: Option<&str>, file: &str) {
frame.place(constant::screen());
frame.paint();
}
pub fn screen_error_shutdown(msg: Option<&str>, label: &str) {
// SAFETY: these will get placed into `frame` which does not outlive this
// function
let msg = msg.map(|s| unsafe { get_str(s) });
let label = unsafe { get_str(label) };
let m_top = if let Some(msg) = msg {
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_BOLD, label).centered());
messages.add(Paragraph::new(&TEXT_NORMAL, msg).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
} else {
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_BOLD, label).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
};
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_BOLD, "PLEASE UNPLUG".into()).centered());
messages.add(Paragraph::new(&TEXT_BOLD, "THE DEVICE".into()).centered());
let m_bottom =
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
let mut frame = ResultScreen::new(WHITE, BLACK, Icon::new(ICON_FAIL), m_top, m_bottom, true);
frame.place(constant::screen());
frame.paint();
}

View File

@ -355,7 +355,7 @@ extern "C" fn screen_wipe_success() {
BLD_WIPE_CANCEL_BTN_COLOR,
Icon::new(CHECK40),
m_top,
m_bottom,
Some(m_bottom),
true,
);
show(&mut frame, true);
@ -383,7 +383,7 @@ extern "C" fn screen_wipe_fail() {
BLD_WIPE_CANCEL_BTN_COLOR,
Icon::new(WARNING40),
m_top,
m_bottom,
Some(m_bottom),
true,
);
show(&mut frame, true);
@ -433,7 +433,7 @@ extern "C" fn screen_install_fail() {
BLD_BTN_COLOR,
Icon::new(WARNING40),
m_top,
m_bottom,
Some(m_bottom),
true,
);
show(&mut frame, true);
@ -457,7 +457,7 @@ fn screen_install_success_bld(msg: &'static str, complete_draw: bool) {
BLD_BTN_COLOR,
Icon::new(CHECK40),
m_top,
m_bottom,
Some(m_bottom),
complete_draw,
);
show(&mut frame, complete_draw);
@ -483,7 +483,7 @@ fn screen_install_success_initial(msg: &'static str, complete_draw: bool) {
WELCOME_HIGHLIGHT_COLOR,
Icon::new(CHECK40),
m_top,
m_bottom,
Some(m_bottom),
complete_draw,
);
show(&mut frame, complete_draw);

View File

@ -0,0 +1,105 @@
use crate::ui::{
component::{
text::paragraphs::{ParagraphStrType, ParagraphVecShort, Paragraphs},
Child, Component, Event, EventCtx, Label, Never, Pad,
},
constant::screen,
display::{self, Icon},
geometry::{Alignment::Center, Point, Rect, TOP_CENTER},
};
use crate::ui::model_tt::{
constant::WIDTH,
theme::{
FATAL_ERROR_COLOR, FATAL_ERROR_HIGHLIGHT_COLOR, ICON_WARNING40, RESULT_FOOTER_HEIGHT,
RESULT_FOOTER_START, RESULT_PADDING, TEXT_ERROR_BOLD, WHITE,
},
};
const TITLE_AREA_START: i16 = 70;
const ICON_TOP: i16 = 27;
pub struct ErrorScreen<T> {
bg: Pad,
title: Child<Label<T>>,
message: Child<Paragraphs<ParagraphVecShort<T>>>,
footer: Child<Paragraphs<ParagraphVecShort<T>>>,
}
impl<T: ParagraphStrType> ErrorScreen<T> {
pub fn new(
title: T,
message: Paragraphs<ParagraphVecShort<T>>,
footer: Paragraphs<ParagraphVecShort<T>>,
) -> Self {
let title = Label::new(title, Center, TEXT_ERROR_BOLD);
Self {
bg: Pad::with_background(FATAL_ERROR_COLOR).with_clear(),
title: Child::new(title),
message: Child::new(message),
footer: Child::new(footer),
}
}
}
impl<T: ParagraphStrType> Component for ErrorScreen<T> {
type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect {
self.bg.place(screen());
let title_area = Rect::new(
Point::new(RESULT_PADDING, TITLE_AREA_START),
Point::new(WIDTH - RESULT_PADDING, RESULT_FOOTER_START),
);
self.title.place(title_area);
let (_, message_area) = title_area.split_top(self.title.inner().area().height());
self.message.place(message_area);
let bottom_area = Rect::new(
Point::new(RESULT_PADDING, RESULT_FOOTER_START),
Point::new(
WIDTH - RESULT_PADDING,
RESULT_FOOTER_START + RESULT_FOOTER_HEIGHT,
),
);
self.footer.place(bottom_area);
bounds
}
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
None
}
fn paint(&mut self) {
self.bg.paint();
let icon = Icon::new(ICON_WARNING40);
icon.draw(
Point::new(screen().center().x, ICON_TOP),
TOP_CENTER,
WHITE,
FATAL_ERROR_COLOR,
);
self.title.paint();
self.message.paint();
display::rect_fill_rounded(
Rect::new(
Point::new(RESULT_PADDING, RESULT_FOOTER_START),
Point::new(
WIDTH - RESULT_PADDING,
RESULT_FOOTER_START + RESULT_FOOTER_HEIGHT,
),
),
FATAL_ERROR_HIGHLIGHT_COLOR,
FATAL_ERROR_COLOR,
2,
);
self.footer.paint();
}
}

View File

@ -5,6 +5,7 @@ mod dialog;
mod fido;
#[rustfmt::skip]
mod fido_icons;
mod error;
mod frame;
mod hold_to_confirm;
#[cfg(feature = "dma2d")]
@ -27,6 +28,7 @@ pub use button::{
};
pub use coinjoin_progress::CoinJoinProgress;
pub use dialog::{Dialog, DialogMsg, IconDialog};
pub use error::ErrorScreen;
pub use fido::{FidoConfirm, FidoMsg};
pub use frame::{Frame, FrameMsg, NotificationFrame};
pub use hold_to_confirm::{HoldToConfirm, HoldToConfirmMsg};

View File

@ -8,17 +8,23 @@ use crate::ui::{
geometry::{Point, Rect, CENTER},
};
use crate::ui::model_tt::constant::{HEIGHT, WIDTH};
use crate::ui::model_tt::{
constant::WIDTH,
theme::{RESULT_FOOTER_HEIGHT, RESULT_FOOTER_START, RESULT_PADDING},
};
const MESSAGE_AREA_START: i16 = 82;
const ICON_CENTER_Y: i16 = 62;
pub struct ResultScreen<T> {
bg: Pad,
small_pad: Pad,
footer_pad: Pad,
fg_color: Color,
bg_color: Color,
msg_area_color: Color,
icon: Icon,
message_top: Child<Paragraphs<ParagraphVecShort<T>>>,
message_bottom: Child<Paragraphs<ParagraphVecShort<T>>>,
message: Child<Paragraphs<ParagraphVecShort<T>>>,
footer: Option<Child<Paragraphs<ParagraphVecShort<T>>>>,
}
impl<T: ParagraphStrType> ResultScreen<T> {
@ -27,25 +33,25 @@ impl<T: ParagraphStrType> ResultScreen<T> {
bg_color: Color,
msg_area_color: Color,
icon: Icon,
message_top: Paragraphs<ParagraphVecShort<T>>,
message_bottom: Paragraphs<ParagraphVecShort<T>>,
message: Paragraphs<ParagraphVecShort<T>>,
footer: Option<Paragraphs<ParagraphVecShort<T>>>,
complete_draw: bool,
) -> Self {
let mut instance = Self {
bg: Pad::with_background(bg_color),
small_pad: Pad::with_background(bg_color),
footer_pad: Pad::with_background(bg_color),
fg_color,
bg_color,
msg_area_color,
icon,
message_top: Child::new(message_top),
message_bottom: Child::new(message_bottom),
message: Child::new(message),
footer: footer.map(Child::new),
};
if complete_draw {
instance.bg.clear();
} else {
instance.small_pad.clear();
instance.footer_pad.clear();
}
instance
}
@ -55,16 +61,33 @@ impl<T: ParagraphStrType> Component for ResultScreen<T> {
type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect {
self.bg
.place(Rect::new(Point::new(0, 0), Point::new(WIDTH, HEIGHT)));
self.bg.place(screen());
self.message_top
.place(Rect::new(Point::new(15, 59), Point::new(WIDTH - 15, 176)));
let message_arae = if let Some(footer) = &mut self.footer {
let footer_area = Rect::new(
Point::new(RESULT_PADDING, RESULT_FOOTER_START),
Point::new(
WIDTH - RESULT_PADDING,
RESULT_FOOTER_START + RESULT_FOOTER_HEIGHT,
),
);
self.footer_pad.place(footer_area);
footer.place(footer_area);
Rect::new(
Point::new(RESULT_PADDING, MESSAGE_AREA_START),
Point::new(WIDTH - RESULT_PADDING, RESULT_FOOTER_START),
)
} else {
Rect::new(
Point::new(RESULT_PADDING, MESSAGE_AREA_START),
Point::new(
WIDTH - RESULT_PADDING,
RESULT_FOOTER_START + RESULT_FOOTER_HEIGHT,
),
)
};
let bottom_area = Rect::new(Point::new(6, 176), Point::new(WIDTH - 6, 176 + 56));
self.small_pad.place(bottom_area);
self.message_bottom.place(bottom_area);
self.message.place(message_arae);
bounds
}
@ -75,21 +98,30 @@ impl<T: ParagraphStrType> Component for ResultScreen<T> {
fn paint(&mut self) {
self.bg.paint();
self.small_pad.paint();
self.footer_pad.paint();
self.icon.draw(
Point::new(screen().center().x, 45),
Point::new(screen().center().x, ICON_CENTER_Y),
CENTER,
self.fg_color,
self.bg_color,
);
self.message_top.paint();
self.message.paint();
if let Some(bottom) = &mut self.footer {
display::rect_fill_rounded(
Rect::new(Point::new(6, 176), Point::new(WIDTH - 6, 176 + 56)),
Rect::new(
Point::new(RESULT_PADDING, RESULT_FOOTER_START),
Point::new(
WIDTH - RESULT_PADDING,
RESULT_FOOTER_START + RESULT_FOOTER_HEIGHT,
),
),
self.msg_area_color,
self.bg_color,
2,
);
self.message_bottom.paint();
bottom.paint();
}
}
}

View File

@ -5,15 +5,11 @@ use crate::ui::{
text::paragraphs::{Paragraph, ParagraphVecShort, Paragraphs, VecExt},
Component,
},
display::Icon,
geometry::LinearPlacement,
model_tt::{
component::ResultScreen,
component::ErrorScreen,
constant,
theme::{
FATAL_ERROR_COLOR, FATAL_ERROR_HIGHLIGHT_COLOR, ICON_WARNING40, TEXT_ERROR_BOLD,
TEXT_ERROR_HIGHLIGHT, TEXT_ERROR_NORMAL, WHITE,
},
theme::{TEXT_ERROR_HIGHLIGHT, TEXT_ERROR_NORMAL},
},
};
@ -29,87 +25,28 @@ unsafe fn get_str(text: &str) -> StrBuffer {
unsafe { StrBuffer::from_ptr_and_len(text.as_ptr(), text.len()) }
}
pub fn screen_fatal_error(msg: Option<&str>, file: &str) {
pub fn screen_fatal_error(title: &str, msg: &str, footer: &str) {
// SAFETY: these will get placed into `frame` which does not outlive this
// function
let msg = msg.map(|s| unsafe { get_str(s) });
let file = unsafe { get_str(file) };
let title = unsafe { get_str(title) };
let msg = unsafe { get_str(msg) };
let footer = unsafe { get_str(footer) };
let m_top = if let Some(msg) = msg {
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "FATAL ERROR!".into()).centered());
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, msg).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
} else {
let m_top =
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "FATAL ERROR!".into()).centered());
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, file).centered());
messages.add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, footer).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
};
let mut messages = ParagraphVecShort::new();
messages.add(
Paragraph::new(
&TEXT_ERROR_HIGHLIGHT,
"PLEASE CONTACT\nTREZOR SUPPORT".into(),
)
.centered(),
);
let m_bottom =
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
let mut frame = ResultScreen::new(
WHITE,
FATAL_ERROR_COLOR,
FATAL_ERROR_HIGHLIGHT_COLOR,
Icon::new(ICON_WARNING40),
m_top,
m_bottom,
true,
);
frame.place(constant::screen());
frame.paint();
}
pub fn screen_error_shutdown(label: &str, msg: Option<&str>) {
// SAFETY: these will get placed into `frame` which does not outlive this
// function
let msg = msg.map(|s| unsafe { get_str(s) });
let label = unsafe { get_str(label) };
let m_top = if let Some(msg) = msg {
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, label).centered());
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, msg).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
} else {
let mut messages = ParagraphVecShort::new();
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, label).centered());
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
};
let mut messages = ParagraphVecShort::new();
messages
.add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, "PLEASE UNPLUG\nTHE DEVICE".into()).centered());
let m_bottom =
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
let mut frame = ResultScreen::new(
WHITE,
FATAL_ERROR_COLOR,
FATAL_ERROR_HIGHLIGHT_COLOR,
Icon::new(ICON_WARNING40),
m_top,
m_bottom,
true,
);
let mut frame = ErrorScreen::new(title, m_top, m_bottom);
frame.place(constant::screen());
frame.paint();
}

View File

@ -556,6 +556,9 @@ pub const CORNER_BUTTON_SPACING: i16 = BUTTON_SPACING;
pub const INFO_BUTTON_HEIGHT: i16 = 44;
pub const PIN_BUTTON_HEIGHT: i16 = 40;
pub const MNEMONIC_BUTTON_HEIGHT: i16 = 52;
pub const RESULT_PADDING: i16 = 6;
pub const RESULT_FOOTER_START: i16 = 178;
pub const RESULT_FOOTER_HEIGHT: i16 = 56;
pub const fn button_bar<T>(inner: T) -> FixedHeightBar<T> {
FixedHeightBar::bottom(inner, BUTTON_HEIGHT)

View File

@ -7,34 +7,25 @@ pub use super::model_tr::screens::*;
pub use super::model_tt::screens::*;
use crate::ui::util::from_c_str;
#[no_mangle]
extern "C" fn screen_fatal_error_c(msg: *const cty::c_char, file: *const cty::c_char) {
let msg = if msg.is_null() {
None
} else {
unsafe { from_c_str(msg) }
};
let file = if file.is_null() {
macro_rules! convert_str {
($str:expr) => {
if ($str).is_null() {
""
} else {
unwrap!(unsafe { from_c_str(file) })
unwrap!(unsafe { from_c_str($str) })
}
};
screen_fatal_error(msg, file);
}
#[no_mangle]
extern "C" fn screen_error_shutdown_c(msg: *const cty::c_char, file: *const cty::c_char) {
let msg = if msg.is_null() {
None
} else {
unsafe { from_c_str(msg) }
};
let file = if file.is_null() {
""
} else {
unwrap!(unsafe { from_c_str(file) })
};
extern "C" fn screen_fatal_error_rust(
title: *const cty::c_char,
msg: *const cty::c_char,
footer: *const cty::c_char,
) {
let title = convert_str!(title);
let msg = convert_str!(msg);
let footer = convert_str!(footer);
screen_fatal_error(msg, file);
screen_fatal_error(title, msg, footer);
}

View File

@ -55,6 +55,31 @@ void __attribute__((noreturn)) trezor_shutdown(void) {
;
}
void __attribute__((noreturn))
error_uni(const char *label, const char *msg, const char *footer) {
display_orientation(0);
#ifdef FANCY_FATAL_ERROR
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
display_refresh();
#else
display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR);
if (label) {
display_printf("%s\n", label);
}
if (msg) {
display_printf("%s\n", msg);
}
if (footer) {
display_printf("\n%s\n", footer);
}
#endif
display_backlight(255);
display_refresh();
trezor_shutdown();
}
void __attribute__((noreturn))
__fatal_error(const char *expr, const char *msg, const char *file, int line,
const char *func) {
@ -64,7 +89,8 @@ __fatal_error(const char *expr, const char *msg, const char *file, int line,
#ifdef FANCY_FATAL_ERROR
char buf[256] = {0};
mini_snprintf(buf, sizeof(buf), "%s: %d", file, line);
screen_fatal_error_c(msg, buf);
screen_fatal_error_rust("FATAL ERROR", msg != NULL ? msg : buf,
"PLEASE VISIT\nTREZOR.IO/RSOD");
display_refresh();
#else
display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR);
@ -94,8 +120,10 @@ __fatal_error(const char *expr, const char *msg, const char *file, int line,
void __attribute__((noreturn))
error_shutdown(const char *label, const char *msg) {
display_orientation(0);
#ifdef FANCY_FATAL_ERROR
screen_error_shutdown_c(label, msg);
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
display_refresh();
#else
display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR);
@ -105,7 +133,7 @@ error_shutdown(const char *label, const char *msg) {
if (msg) {
display_printf("%s\n", msg);
}
display_printf("\nPlease unplug the device.\n");
display_printf("\nPLEASE VISIT TREZOR.IO/RSOD\n");
#endif
display_backlight(255);
trezor_shutdown();
@ -141,7 +169,7 @@ void clear_otg_hs_memory(void) {
uint32_t __stack_chk_guard = 0;
void __attribute__((noreturn)) __stack_chk_fail(void) {
error_shutdown("Internal error", "(SS)");
error_shutdown("INTERNAL ERROR", "(SS)");
}
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
@ -183,11 +211,10 @@ void ensure_compatible_settings(void) {
}
void show_wipe_code_screen(void) {
error_shutdown(
"DEVICE WIPED!",
"You have entered the wipe code. All private data has been erased.");
error_uni("WIPE CODE ENTERED", "All data has been erased from the device",
"PLEASE RECONNECT\nTHE DEVICE");
}
void show_pin_too_many_screen(void) {
error_shutdown("DEVICE WIPED!",
"Too many wrong PIN attempts. Storage has been wiped.");
error_uni("TOO MANY PIN ATTEMPTS", "All data has been erased from the device",
"PLEASE RECONNECT\nTHE DEVICE");
}

View File

@ -48,6 +48,32 @@ void __attribute__((noreturn)) trezor_shutdown(void) {
#define COLOR_FATAL_ERROR 0x0000
#endif
void __attribute__((noreturn))
error_uni(const char *label, const char *msg, const char *footer) {
display_orientation(0);
#ifdef FANCY_FATAL_ERROR
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
display_refresh();
#else
display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR);
if (label) {
display_printf("%s\n", label);
}
if (msg) {
display_printf("%s\n", msg);
}
if (footer) {
display_printf("\n%s\n", footer);
}
#endif
display_backlight(255);
display_refresh();
hal_delay(3000);
trezor_shutdown();
}
void __attribute__((noreturn))
__fatal_error(const char *expr, const char *msg, const char *file, int line,
const char *func) {
@ -55,9 +81,15 @@ __fatal_error(const char *expr, const char *msg, const char *file, int line,
display_backlight(255);
#ifdef FANCY_FATAL_ERROR
if (msg == NULL) {
msg = "Unknown error";
char buf[256] = {0};
snprintf(buf, sizeof(buf), "%s: %d", file, line);
screen_fatal_error_c(msg, buf);
screen_fatal_error_rust("FATAL ERROR", buf, "PLEASE VISIT\nTREZOR.IO/RSOD");
} else {
screen_fatal_error_rust("FATAL ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
}
display_refresh();
#else
display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR);
@ -96,7 +128,7 @@ __fatal_error(const char *expr, const char *msg, const char *file, int line,
void __attribute__((noreturn))
error_shutdown(const char *label, const char *msg) {
#ifdef FANCY_FATAL_ERROR
screen_error_shutdown_c(label, msg);
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
display_refresh();
#else
display_clear();
@ -176,11 +208,10 @@ uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
void collect_hw_entropy(void) { memzero(HW_ENTROPY_DATA, HW_ENTROPY_LEN); }
void show_wipe_code_screen(void) {
error_shutdown(
"DEVICE WIPED!",
"You have entered the wipe code. All private data has been erased.");
error_uni("WIPE CODE ENTERED", "All data has been erased from the device",
"PLEASE RECONNECT\nTHE DEVICE");
}
void show_pin_too_many_screen(void) {
error_shutdown("DEVICE WIPED!",
"Too many wrong PIN attempts. Storage has been wiped.");
error_uni("TOO MANY PIN ATTEMPTS", "All data has been erased from the device",
"PLEASE RECONNECT\nTHE DEVICE");
}