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:
parent
64bc94cbc9
commit
9b8984896e
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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 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_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 title = unsafe { get_str(title) };
|
||||
let msg = unsafe { get_str(msg) };
|
||||
let footer = unsafe { get_str(footer) };
|
||||
|
||||
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, title).centered());
|
||||
messages.add(Paragraph::new(&TEXT_NORMAL, msg).centered());
|
||||
let m_top =
|
||||
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||
|
||||
let mut messages = ParagraphVecShort::new();
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
105
core/embed/rust/src/ui/model_tt/component/error.rs
Normal file
105
core/embed/rust/src/ui/model_tt/component/error.rs
Normal 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();
|
||||
}
|
||||
}
|
@ -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};
|
||||
|
@ -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();
|
||||
display::rect_fill_rounded(
|
||||
Rect::new(Point::new(6, 176), Point::new(WIDTH - 6, 176 + 56)),
|
||||
self.msg_area_color,
|
||||
self.bg_color,
|
||||
2,
|
||||
);
|
||||
self.message_bottom.paint();
|
||||
self.message.paint();
|
||||
|
||||
if let Some(bottom) = &mut self.footer {
|
||||
display::rect_fill_rounded(
|
||||
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,
|
||||
);
|
||||
bottom.paint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 mut messages = ParagraphVecShort::new();
|
||||
|
||||
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "FATAL ERROR!".into()).centered());
|
||||
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, file).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(),
|
||||
);
|
||||
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, msg).centered());
|
||||
|
||||
let m_top =
|
||||
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||
|
||||
let mut messages = ParagraphVecShort::new();
|
||||
|
||||
messages.add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, footer).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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) }
|
||||
macro_rules! convert_str {
|
||||
($str:expr) => {
|
||||
if ($str).is_null() {
|
||||
""
|
||||
} else {
|
||||
unwrap!(unsafe { from_c_str($str) })
|
||||
}
|
||||
};
|
||||
let file = if file.is_null() {
|
||||
""
|
||||
} else {
|
||||
unwrap!(unsafe { from_c_str(file) })
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
char buf[256] = {0};
|
||||
snprintf(buf, sizeof(buf), "%s: %d", file, line);
|
||||
screen_fatal_error_c(msg, buf);
|
||||
if (msg == NULL) {
|
||||
msg = "Unknown error";
|
||||
char buf[256] = {0};
|
||||
snprintf(buf, sizeof(buf), "%s: %d", file, line);
|
||||
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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user