mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-19 12:58:13 +00:00
refactor(core): improve and simplify error handling
[no changelog]
This commit is contained in:
parent
ac1a25fc21
commit
5fc3c6e617
@ -68,6 +68,7 @@ CPPPATH_MOD += [
|
|||||||
SOURCE_MOD += [
|
SOURCE_MOD += [
|
||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/gfx_color.c',
|
'embed/lib/gfx_color.c',
|
||||||
|
@ -107,6 +107,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/buffers.c',
|
'embed/lib/buffers.c',
|
||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/gfx_color.c',
|
'embed/lib/gfx_color.c',
|
||||||
|
@ -98,6 +98,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_draw.c',
|
'embed/lib/display_draw.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/image.c',
|
'embed/lib/image.c',
|
||||||
|
@ -102,6 +102,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/buffers.c',
|
'embed/lib/buffers.c',
|
||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/gfx_color.c',
|
'embed/lib/gfx_color.c',
|
||||||
@ -109,6 +110,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/gfx_bitblt_rgb565.c',
|
'embed/lib/gfx_bitblt_rgb565.c',
|
||||||
'embed/lib/gfx_bitblt_rgba8888.c',
|
'embed/lib/gfx_bitblt_rgba8888.c',
|
||||||
'embed/lib/image.c',
|
'embed/lib/image.c',
|
||||||
|
'embed/lib/mini_printf.c',
|
||||||
'embed/lib/terminal.c',
|
'embed/lib/terminal.c',
|
||||||
'embed/lib/touch.c',
|
'embed/lib/touch.c',
|
||||||
'embed/lib/unit_variant.c',
|
'embed/lib/unit_variant.c',
|
||||||
@ -144,10 +146,10 @@ SOURCE_BOOTLOADER = [
|
|||||||
|
|
||||||
SOURCE_TREZORHAL = [
|
SOURCE_TREZORHAL = [
|
||||||
'embed/trezorhal/unix/boot_args.c',
|
'embed/trezorhal/unix/boot_args.c',
|
||||||
|
'embed/trezorhal/unix/common.c',
|
||||||
'embed/trezorhal/unix/fault_handlers.c',
|
'embed/trezorhal/unix/fault_handlers.c',
|
||||||
'embed/trezorhal/unix/flash.c',
|
'embed/trezorhal/unix/flash.c',
|
||||||
'embed/trezorhal/unix/flash_otp.c',
|
'embed/trezorhal/unix/flash_otp.c',
|
||||||
'embed/trezorhal/unix/common.c',
|
|
||||||
'embed/trezorhal/unix/touch/touch.c',
|
'embed/trezorhal/unix/touch/touch.c',
|
||||||
'embed/trezorhal/unix/rng.c',
|
'embed/trezorhal/unix/rng.c',
|
||||||
'embed/trezorhal/unix/usb.c',
|
'embed/trezorhal/unix/usb.c',
|
||||||
|
@ -226,6 +226,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/buffers.c',
|
'embed/lib/buffers.c',
|
||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/gfx_color.c',
|
'embed/lib/gfx_color.c',
|
||||||
|
@ -102,6 +102,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_draw.c',
|
'embed/lib/display_draw.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/image.c',
|
'embed/lib/image.c',
|
||||||
|
@ -74,6 +74,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_draw.c',
|
'embed/lib/display_draw.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/image.c',
|
'embed/lib/image.c',
|
||||||
|
@ -232,6 +232,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/buffers.c',
|
'embed/lib/buffers.c',
|
||||||
'embed/lib/colors.c',
|
'embed/lib/colors.c',
|
||||||
'embed/lib/display_utils.c',
|
'embed/lib/display_utils.c',
|
||||||
|
'embed/lib/error_handling.c',
|
||||||
'embed/lib/fonts/font_bitmap.c',
|
'embed/lib/fonts/font_bitmap.c',
|
||||||
'embed/lib/fonts/fonts.c',
|
'embed/lib/fonts/fonts.c',
|
||||||
'embed/lib/gfx_color.c',
|
'embed/lib/gfx_color.c',
|
||||||
@ -239,6 +240,7 @@ SOURCE_MOD += [
|
|||||||
'embed/lib/gfx_bitblt_rgba8888.c',
|
'embed/lib/gfx_bitblt_rgba8888.c',
|
||||||
'embed/lib/gfx_bitblt_mono8.c',
|
'embed/lib/gfx_bitblt_mono8.c',
|
||||||
'embed/lib/image.c',
|
'embed/lib/image.c',
|
||||||
|
'embed/lib/mini_printf.c',
|
||||||
'embed/lib/terminal.c',
|
'embed/lib/terminal.c',
|
||||||
'embed/lib/translations.c',
|
'embed/lib/translations.c',
|
||||||
'embed/lib/unit_variant.c',
|
'embed/lib/unit_variant.c',
|
||||||
|
@ -88,27 +88,6 @@ bool load_firmware(const char *filename, uint8_t *hash) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noreturn)) void display_error_and_die(const char *message,
|
|
||||||
const char *title,
|
|
||||||
const char *footer) {
|
|
||||||
if (footer == NULL) {
|
|
||||||
footer = "PLEASE VISIT\nTREZOR.IO/RSOD";
|
|
||||||
}
|
|
||||||
if (title == NULL) {
|
|
||||||
title = "INTERNAL ERROR";
|
|
||||||
}
|
|
||||||
display_init();
|
|
||||||
display_backlight(180);
|
|
||||||
screen_fatal_error_rust(title, message, footer);
|
|
||||||
#if USE_TOUCH
|
|
||||||
printf("Click screen to exit.\n");
|
|
||||||
#elif USE_BUTTON
|
|
||||||
printf("Press both buttons to exit.\n");
|
|
||||||
#endif
|
|
||||||
ui_click();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((noreturn)) int main(int argc, char **argv) {
|
__attribute__((noreturn)) int main(int argc, char **argv) {
|
||||||
display_init();
|
display_init();
|
||||||
flash_init();
|
flash_init();
|
||||||
@ -175,7 +154,7 @@ __attribute__((noreturn)) int main(int argc, char **argv) {
|
|||||||
} else {
|
} else {
|
||||||
message = "No message specified";
|
message = "No message specified";
|
||||||
}
|
}
|
||||||
display_error_and_die(message, title, footer);
|
error_shutdown_ex(title, message, footer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// write variant to OTP
|
// write variant to OTP
|
||||||
@ -198,18 +177,13 @@ __attribute__((noreturn)) void jump_to(void *addr) {
|
|||||||
|
|
||||||
if (storage_is_erased) {
|
if (storage_is_erased) {
|
||||||
printf("STORAGE WAS ERASED\n");
|
printf("STORAGE WAS ERASED\n");
|
||||||
screen_fatal_error_rust("BOOTLOADER EXIT", "Jumped to firmware",
|
error_shutdown_ex("BOOTLOADER EXIT", "Jumped to firmware",
|
||||||
"STORAGE WAS ERASED");
|
"STORAGE WAS ERASED");
|
||||||
} else {
|
} else {
|
||||||
printf("storage was retained\n");
|
printf("storage was retained\n");
|
||||||
screen_fatal_error_rust("BOOTLOADER EXIT", "Jumped to firmware",
|
error_shutdown_ex("BOOTLOADER EXIT", "Jumped to firmware",
|
||||||
"STORAGE WAS RETAINED");
|
"STORAGE WAS RETAINED");
|
||||||
}
|
}
|
||||||
display_backlight(180);
|
|
||||||
hal_delay(3000);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensure_compatible_settings(void) {}
|
void ensure_compatible_settings(void) {}
|
||||||
|
|
||||||
void main_clean_exit(int code) { exit(code); }
|
|
||||||
|
@ -192,7 +192,8 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
|
|||||||
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
|
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
|
||||||
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
|
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
|
||||||
if (r == UPLOAD_ERR_BOOTLOADER_LOCKED) {
|
if (r == UPLOAD_ERR_BOOTLOADER_LOCKED) {
|
||||||
secret_show_install_restricted_screen();
|
// This function does not return
|
||||||
|
show_install_restricted_screen();
|
||||||
} else {
|
} else {
|
||||||
ui_screen_fail();
|
ui_screen_fail();
|
||||||
}
|
}
|
||||||
@ -291,9 +292,7 @@ static void check_bootloader_version(void) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void failed_jump_to_firmware(void) {
|
void failed_jump_to_firmware(void) { error_shutdown("(glitch)"); }
|
||||||
error_shutdown("INTERNAL ERROR", "(glitch)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void real_jump_to_firmware(void) {
|
void real_jump_to_firmware(void) {
|
||||||
const image_header *hdr = NULL;
|
const image_header *hdr = NULL;
|
||||||
|
@ -213,8 +213,9 @@ static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) {
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// error
|
// error
|
||||||
error_shutdown("USB ERROR",
|
error_shutdown_ex("USB ERROR",
|
||||||
"Error reading from USB. Try different USB cable.");
|
"Error reading from USB. Try different USB cable.",
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return; // success
|
return; // success
|
||||||
|
@ -200,8 +200,9 @@ static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) {
|
|||||||
// only timeout => let's try again
|
// only timeout => let's try again
|
||||||
} else {
|
} else {
|
||||||
// error
|
// error
|
||||||
error_shutdown("USB ERROR",
|
error_shutdown_ex("USB ERROR",
|
||||||
"Error reading from USB. Try different USB cable.");
|
"Error reading from USB. Try different USB cable.",
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return; // success
|
return; // success
|
||||||
|
@ -161,8 +161,7 @@ void secp256k1_default_illegal_callback_fn(const char *str, void *data) {
|
|||||||
|
|
||||||
void secp256k1_default_error_callback_fn(const char *str, void *data) {
|
void secp256k1_default_error_callback_fn(const char *str, void *data) {
|
||||||
(void)data;
|
(void)data;
|
||||||
__fatal_error(NULL, str, __FILE__, __LINE__, __func__);
|
error_shutdown(str);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ int main(void) {
|
|||||||
mp_deinit();
|
mp_deinit();
|
||||||
|
|
||||||
// Python code shouldn't ever exit, avoid black screen if it does
|
// Python code shouldn't ever exit, avoid black screen if it does
|
||||||
error_shutdown("INTERNAL ERROR", "(PE)");
|
error_shutdown("(PE)");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -282,7 +282,7 @@ int main(void) {
|
|||||||
// MicroPython default exception handler
|
// MicroPython default exception handler
|
||||||
|
|
||||||
void __attribute__((noreturn)) nlr_jump_fail(void *val) {
|
void __attribute__((noreturn)) nlr_jump_fail(void *val) {
|
||||||
error_shutdown("INTERNAL ERROR", "(UE)");
|
error_shutdown("(UE)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// MicroPython builtin stubs
|
// MicroPython builtin stubs
|
||||||
|
123
core/embed/lib/error_handling.c
Normal file
123
core/embed/lib/error_handling.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "error_handling.h"
|
||||||
|
#include "mini_printf.h"
|
||||||
|
#ifdef FANCY_FATAL_ERROR
|
||||||
|
#include "rust_ui.h"
|
||||||
|
#else
|
||||||
|
#include "terminal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RGB16
|
||||||
|
#define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00)
|
||||||
|
#else
|
||||||
|
#define COLOR_FATAL_ERROR COLOR_BLACK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void __attribute__((noreturn))
|
||||||
|
error_shutdown_ex(const char *title, const char *message, const char *footer) {
|
||||||
|
if (title == NULL) {
|
||||||
|
title = "INTERNAL ERROR";
|
||||||
|
}
|
||||||
|
if (footer == NULL) {
|
||||||
|
footer = "PLEASE VISIT\nTREZOR.IO/RSOD";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FANCY_FATAL_ERROR
|
||||||
|
error_shutdown_rust(title, message, footer);
|
||||||
|
#else
|
||||||
|
display_orientation(0);
|
||||||
|
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
||||||
|
term_printf("%s\n", title);
|
||||||
|
if (message) {
|
||||||
|
term_printf("%s\n", message);
|
||||||
|
}
|
||||||
|
term_printf("\n%s\n", footer);
|
||||||
|
display_backlight(255);
|
||||||
|
trezor_shutdown();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((noreturn)) error_shutdown(const char *message) {
|
||||||
|
error_shutdown_ex(NULL, message, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((noreturn))
|
||||||
|
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
||||||
|
const char *func) {
|
||||||
|
#ifdef FANCY_FATAL_ERROR
|
||||||
|
char buf[256] = {0};
|
||||||
|
mini_snprintf(buf, sizeof(buf), "%s: %d", file, line);
|
||||||
|
error_shutdown(msg != NULL ? msg : buf);
|
||||||
|
#else
|
||||||
|
display_orientation(0);
|
||||||
|
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
||||||
|
term_printf("\nINTERNAL ERROR:\n");
|
||||||
|
if (expr) {
|
||||||
|
term_printf("expr: %s\n", expr);
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
term_printf("msg : %s\n", msg);
|
||||||
|
}
|
||||||
|
if (file) {
|
||||||
|
term_printf("file: %s:%d\n", file, line);
|
||||||
|
}
|
||||||
|
if (func) {
|
||||||
|
term_printf("func: %s\n", func);
|
||||||
|
}
|
||||||
|
#ifdef SCM_REVISION
|
||||||
|
const uint8_t *rev = (const uint8_t *)SCM_REVISION;
|
||||||
|
term_printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3],
|
||||||
|
rev[4]);
|
||||||
|
#endif
|
||||||
|
term_printf("\nPlease contact Trezor support.\n");
|
||||||
|
display_backlight(255);
|
||||||
|
trezor_shutdown();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void __assert_func(const char *file, int line, const char *func,
|
||||||
|
const char *expr) {
|
||||||
|
__fatal_error(expr, "assert failed", file, line, func);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void __attribute__((noreturn)) show_wipe_code_screen(void) {
|
||||||
|
error_shutdown_ex("WIPE CODE ENTERED",
|
||||||
|
"All data has been erased from the device",
|
||||||
|
"PLEASE RECONNECT\nTHE DEVICE");
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((noreturn)) show_pin_too_many_screen(void) {
|
||||||
|
error_shutdown_ex("TOO MANY PIN ATTEMPTS",
|
||||||
|
"All data has been erased from the device",
|
||||||
|
"PLEASE RECONNECT\nTHE DEVICE");
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((noreturn)) show_install_restricted_screen(void) {
|
||||||
|
error_shutdown_ex("INSTALL RESTRICTED",
|
||||||
|
"Installation of custom firmware is currently restricted.",
|
||||||
|
"Please visit\ntrezor.io/bootloader");
|
||||||
|
}
|
57
core/embed/lib/error_handling.h
Normal file
57
core/embed/lib/error_handling.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIB_ERROR_HANDLING_H
|
||||||
|
#define LIB_ERROR_HANDLING_H
|
||||||
|
|
||||||
|
// Shows an error message and shuts down the device.
|
||||||
|
//
|
||||||
|
// If the title is NULL, it will be set to "INTERNAL ERROR".
|
||||||
|
// If the message is NULL, it will be ignored.
|
||||||
|
// If the footer is NULL, it will be set to "PLEASE VISIT TREZOR.IO/RSOD".
|
||||||
|
void __attribute__((noreturn))
|
||||||
|
error_shutdown_ex(const char *title, const char *message, const char *footer);
|
||||||
|
|
||||||
|
// Shows an error message and shuts down the device.
|
||||||
|
//
|
||||||
|
// Same as `error_shutdown_ex()` but with a default header and footer.
|
||||||
|
void __attribute__((noreturn)) error_shutdown(const char *message);
|
||||||
|
|
||||||
|
// Do not use this function directly, use the `ensure()` macro instead.
|
||||||
|
void __attribute__((noreturn))
|
||||||
|
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
||||||
|
const char *func);
|
||||||
|
|
||||||
|
// Checks for an expression and if it is false, shows an error message
|
||||||
|
// and shuts down the device.
|
||||||
|
#define ensure(expr, msg) \
|
||||||
|
(((expr) == sectrue) \
|
||||||
|
? (void)0 \
|
||||||
|
: __fatal_error(#expr, msg, __FILE__, __LINE__, __func__))
|
||||||
|
|
||||||
|
// Shows WIPE CODE ENTERED screeen and shuts down the device.
|
||||||
|
void __attribute__((noreturn)) show_wipe_code_screen(void);
|
||||||
|
|
||||||
|
// Shows TOO MANY PIN ATTEMPTS screen and shuts down the device.
|
||||||
|
void __attribute__((noreturn)) show_pin_too_many_screen(void);
|
||||||
|
|
||||||
|
// Shows INSTALL RESTRICTED screen and shuts down the device.
|
||||||
|
void __attribute__((noreturn)) show_install_restricted_screen(void);
|
||||||
|
|
||||||
|
#endif // LIB_ERRORS_H
|
@ -180,12 +180,18 @@ void term_print(const char *text, int textlen) {
|
|||||||
void term_printf(const char *fmt, ...) {
|
void term_printf(const char *fmt, ...) {
|
||||||
if (!strchr(fmt, '%')) {
|
if (!strchr(fmt, '%')) {
|
||||||
term_print(fmt, strlen(fmt));
|
term_print(fmt, strlen(fmt));
|
||||||
|
#ifdef TREZOR_EMULATOR
|
||||||
|
printf("%s", fmt);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
char buf[256] = {0};
|
char buf[256] = {0};
|
||||||
int len = mini_vsnprintf(buf, sizeof(buf), fmt, va);
|
int len = mini_vsnprintf(buf, sizeof(buf), fmt, va);
|
||||||
term_print(buf, len);
|
term_print(buf, len);
|
||||||
|
#ifdef TREZOR_EMULATOR
|
||||||
|
vprintf(fmt, va);
|
||||||
|
#endif
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
void screen_fatal_error_rust(const char* title, const char* msg,
|
__attribute__((noreturn)) void error_shutdown_rust(const char* title,
|
||||||
const char* footer);
|
const char* msg,
|
||||||
|
const char* footer);
|
||||||
|
|
||||||
void screen_boot_stage_2(void);
|
void screen_boot_stage_2(void);
|
||||||
|
|
||||||
|
@ -5,24 +5,34 @@ mod ffi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::ui::ui_features::{ModelUI, UIFeaturesCommon};
|
use crate::ui::{
|
||||||
|
shape,
|
||||||
|
ui_features::{ModelUI, UIFeaturesCommon},
|
||||||
|
};
|
||||||
|
|
||||||
fn shutdown() -> ! {
|
fn shutdown() -> ! {
|
||||||
unsafe { ffi::trezor_shutdown() }
|
unsafe { ffi::trezor_shutdown() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "bootloader")]
|
/// Shows an error message and shuts down the device.
|
||||||
pub fn __fatal_error(_expr: &str, _msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
|
pub fn error_shutdown(title: &str, msg: &str, footer: &str) -> ! {
|
||||||
ModelUI::screen_fatal_error("BL.rs", "BL.rs", "PLEASE VISIT\nTREZOR.IO/RSOD");
|
// SAFETY:
|
||||||
|
// This is the only situation we are allowed use this function
|
||||||
|
// to allow nested calls to `run_with_bumps`/`render_on_display`,
|
||||||
|
// because after the error message is displayed, the application will
|
||||||
|
// shut down.
|
||||||
|
unsafe { shape::unlock_bumps_on_failure() };
|
||||||
|
|
||||||
|
ModelUI::screen_fatal_error(title, msg, footer);
|
||||||
ModelUI::backlight_on();
|
ModelUI::backlight_on();
|
||||||
shutdown()
|
shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "bootloader"))]
|
/// Shows an error message on the screen and shuts down the device.
|
||||||
|
/// 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) -> ! {
|
pub fn __fatal_error(_expr: &str, msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
|
||||||
ModelUI::screen_fatal_error("INTERNAL_ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
|
error_shutdown("INTERNAL_ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
|
||||||
ModelUI::backlight_on();
|
|
||||||
shutdown()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UnwrapOrFatalError<T> {
|
pub trait UnwrapOrFatalError<T> {
|
||||||
|
@ -10,19 +10,19 @@ use crate::ui::{
|
|||||||
geometry::{Alignment2D, Point},
|
geometry::{Alignment2D, Point},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ui::util::from_c_str;
|
use crate::{trezorhal::fatal_error, ui::util::from_c_str};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn screen_fatal_error_rust(
|
extern "C" fn error_shutdown_rust(
|
||||||
title: *const cty::c_char,
|
title: *const cty::c_char,
|
||||||
msg: *const cty::c_char,
|
msg: *const cty::c_char,
|
||||||
footer: *const cty::c_char,
|
footer: *const cty::c_char,
|
||||||
) {
|
) -> ! {
|
||||||
let title = unsafe { from_c_str(title) }.unwrap_or("");
|
let title = unsafe { from_c_str(title) }.unwrap_or("");
|
||||||
let msg = unsafe { from_c_str(msg) }.unwrap_or("");
|
let msg = unsafe { from_c_str(msg) }.unwrap_or("");
|
||||||
let footer = unsafe { from_c_str(footer) }.unwrap_or("");
|
let footer = unsafe { from_c_str(footer) }.unwrap_or("");
|
||||||
|
|
||||||
ModelUI::screen_fatal_error(title, msg, footer);
|
fatal_error::error_shutdown(title, msg, footer)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -22,6 +22,9 @@ pub const BUMP_A_SIZE: usize = DrawingCache::get_bump_a_size() + SHAPE_MEM_SIZE;
|
|||||||
/// Size of `bump_b` memory that must be accessible by DMA
|
/// Size of `bump_b` memory that must be accessible by DMA
|
||||||
pub const BUMP_B_SIZE: usize = DrawingCache::get_bump_b_size();
|
pub const BUMP_B_SIZE: usize = DrawingCache::get_bump_b_size();
|
||||||
|
|
||||||
|
//
|
||||||
|
static mut LOCKED: bool = false;
|
||||||
|
|
||||||
/// Runs a user-defined function with two bump allocators.
|
/// Runs a user-defined function with two bump allocators.
|
||||||
///
|
///
|
||||||
/// The function is passed two bump allocators, `bump_a` and `bump_b`, which
|
/// The function is passed two bump allocators, `bump_a` and `bump_b`, which
|
||||||
@ -32,8 +35,6 @@ pub fn run_with_bumps<F>(func: F)
|
|||||||
where
|
where
|
||||||
F: for<'a> FnOnce(&'a mut Bump<[u8; BUMP_A_SIZE]>, &'a mut Bump<[u8; BUMP_B_SIZE]>),
|
F: for<'a> FnOnce(&'a mut Bump<[u8; BUMP_A_SIZE]>, &'a mut Bump<[u8; BUMP_B_SIZE]>),
|
||||||
{
|
{
|
||||||
static mut LOCKED: bool = false;
|
|
||||||
|
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The application is single-threaded, so we can safely use a
|
// The application is single-threaded, so we can safely use a
|
||||||
// static variable as a lock against nested calls.
|
// static variable as a lock against nested calls.
|
||||||
@ -64,3 +65,20 @@ where
|
|||||||
LOCKED = false;
|
LOCKED = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
unsafe {
|
||||||
|
LOCKED = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -49,3 +49,5 @@ mod _new_rendering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub use _new_rendering::render_on_display;
|
pub use _new_rendering::render_on_display;
|
||||||
|
|
||||||
|
pub use bumps::unlock_bumps_on_failure;
|
||||||
|
@ -28,7 +28,7 @@ pub use canvas::{
|
|||||||
};
|
};
|
||||||
pub use circle::Circle;
|
pub use circle::Circle;
|
||||||
pub use corner_highlight::CornerHighlight;
|
pub use corner_highlight::CornerHighlight;
|
||||||
pub use display::{render_on_canvas, render_on_display};
|
pub use display::{render_on_canvas, render_on_display, unlock_bumps_on_failure};
|
||||||
#[cfg(feature = "ui_jpeg_decoder")]
|
#[cfg(feature = "ui_jpeg_decoder")]
|
||||||
pub use jpeg::JpegImage;
|
pub use jpeg::JpegImage;
|
||||||
pub use qrcode::QrImage;
|
pub use qrcode::QrImage;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "secbool.h"
|
#include "secbool.h"
|
||||||
|
|
||||||
|
#include "error_handling.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#ifndef MIN_8bits
|
#ifndef MIN_8bits
|
||||||
@ -53,20 +54,6 @@
|
|||||||
|
|
||||||
void __attribute__((noreturn)) trezor_shutdown(void);
|
void __attribute__((noreturn)) trezor_shutdown(void);
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
|
||||||
const char *func);
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
error_shutdown(const char *label, const char *msg);
|
|
||||||
|
|
||||||
void show_wipe_code_screen(void);
|
|
||||||
void show_pin_too_many_screen(void);
|
|
||||||
|
|
||||||
#define ensure(expr, msg) \
|
|
||||||
(((expr) == sectrue) \
|
|
||||||
? (void)0 \
|
|
||||||
: __fatal_error(#expr, msg, __FILE__, __LINE__, __func__))
|
|
||||||
|
|
||||||
void hal_delay(uint32_t ms);
|
void hal_delay(uint32_t ms);
|
||||||
uint32_t hal_ticks_ms();
|
uint32_t hal_ticks_ms();
|
||||||
void hal_delay_us(uint16_t delay_us);
|
void hal_delay_us(uint16_t delay_us);
|
||||||
|
@ -60,7 +60,3 @@ void secret_bhk_regenerate(void);
|
|||||||
// Disables access to the secret storage until next reset, if possible
|
// Disables access to the secret storage until next reset, if possible
|
||||||
// This function is called by the bootloader before starting the firmware
|
// This function is called by the bootloader before starting the firmware
|
||||||
void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all);
|
void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all);
|
||||||
|
|
||||||
// Shows a screen informing the user that installation of custom firmware is
|
|
||||||
// currently restricted
|
|
||||||
void secret_show_install_restricted_screen(void);
|
|
||||||
|
@ -22,9 +22,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
|
||||||
#define handle_fault(msg) \
|
|
||||||
(__fatal_error("Fault detected", msg, __FILE__, __LINE__, __func__))
|
|
||||||
|
|
||||||
static uint32_t board_name = 0;
|
static uint32_t board_name = 0;
|
||||||
|
|
||||||
static struct BoardloaderVersion boardloader_version;
|
static struct BoardloaderVersion boardloader_version;
|
||||||
@ -53,7 +50,7 @@ void parse_boardloader_capabilities() {
|
|||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
if (pos + length > end) {
|
if (pos + length > end) {
|
||||||
handle_fault("Bad capabilities format.");
|
error_shutdown("Bad capabilities format");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
|
@ -24,29 +24,18 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "terminal.h"
|
|
||||||
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
#include "rust_ui.h"
|
|
||||||
#endif
|
|
||||||
#include "flash_otp.h"
|
#include "flash_otp.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "rand.h"
|
#include "rand.h"
|
||||||
#include "supervise.h"
|
#include "supervise.h"
|
||||||
|
|
||||||
#include "mini_printf.h"
|
|
||||||
#include "stm32f4xx_ll_utils.h"
|
#include "stm32f4xx_ll_utils.h"
|
||||||
|
|
||||||
#ifdef TREZOR_MODEL_T
|
#ifdef TREZOR_MODEL_T
|
||||||
#include "backlight_pwm.h"
|
#include "backlight_pwm.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RGB16
|
|
||||||
#define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00)
|
|
||||||
#else
|
|
||||||
#define COLOR_FATAL_ERROR COLOR_BLACK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t systick_val_copy = 0;
|
uint32_t systick_val_copy = 0;
|
||||||
|
|
||||||
// from util.s
|
// from util.s
|
||||||
@ -65,92 +54,6 @@ 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");
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
if (label) {
|
|
||||||
term_printf("%s\n", label);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("%s\n", msg);
|
|
||||||
}
|
|
||||||
if (footer) {
|
|
||||||
term_printf("\n%s\n", footer);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
display_backlight(255);
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
|
||||||
const char *func) {
|
|
||||||
display_orientation(0);
|
|
||||||
display_backlight(255);
|
|
||||||
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
char buf[256] = {0};
|
|
||||||
mini_snprintf(buf, sizeof(buf), "%s: %d", file, line);
|
|
||||||
screen_fatal_error_rust("INTERNAL ERROR", msg != NULL ? msg : buf,
|
|
||||||
"PLEASE VISIT\nTREZOR.IO/RSOD");
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
term_printf("\nINTERNAL ERROR:\n");
|
|
||||||
if (expr) {
|
|
||||||
term_printf("expr: %s\n", expr);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("msg : %s\n", msg);
|
|
||||||
}
|
|
||||||
if (file) {
|
|
||||||
term_printf("file: %s:%d\n", file, line);
|
|
||||||
}
|
|
||||||
if (func) {
|
|
||||||
term_printf("func: %s\n", func);
|
|
||||||
}
|
|
||||||
#ifdef SCM_REVISION
|
|
||||||
const uint8_t *rev = (const uint8_t *)SCM_REVISION;
|
|
||||||
term_printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3],
|
|
||||||
rev[4]);
|
|
||||||
#endif
|
|
||||||
term_printf("\nPlease contact Trezor support.\n");
|
|
||||||
#endif
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
error_shutdown(const char *label, const char *msg) {
|
|
||||||
display_orientation(0);
|
|
||||||
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
|
|
||||||
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
if (label) {
|
|
||||||
term_printf("%s\n", label);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("%s\n", msg);
|
|
||||||
}
|
|
||||||
term_printf("\nPLEASE VISIT TREZOR.IO/RSOD\n");
|
|
||||||
#endif
|
|
||||||
display_backlight(255);
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
void __assert_func(const char *file, int line, const char *func,
|
|
||||||
const char *expr) {
|
|
||||||
__fatal_error(expr, "assert failed", file, line, func);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void hal_delay(uint32_t ms) { HAL_Delay(ms); }
|
void hal_delay(uint32_t ms) { HAL_Delay(ms); }
|
||||||
uint32_t hal_ticks_ms() { return HAL_GetTick(); }
|
uint32_t hal_ticks_ms() { return HAL_GetTick(); }
|
||||||
void hal_delay_us(uint16_t delay_us) {
|
void hal_delay_us(uint16_t delay_us) {
|
||||||
@ -185,7 +88,7 @@ void clear_otg_hs_memory(void) {
|
|||||||
uint32_t __stack_chk_guard = 0;
|
uint32_t __stack_chk_guard = 0;
|
||||||
|
|
||||||
void __attribute__((noreturn)) __stack_chk_fail(void) {
|
void __attribute__((noreturn)) __stack_chk_fail(void) {
|
||||||
error_shutdown("INTERNAL ERROR", "(SS)");
|
error_shutdown("(SS)");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
|
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
|
||||||
@ -230,15 +133,6 @@ void ensure_compatible_settings(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_wipe_code_screen(void) {
|
|
||||||
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_uni("TOO MANY PIN ATTEMPTS", "All data has been erased from the device",
|
|
||||||
"PLEASE RECONNECT\nTHE DEVICE");
|
|
||||||
}
|
|
||||||
|
|
||||||
void invalidate_firmware(void) {
|
void invalidate_firmware(void) {
|
||||||
// erase start of the firmware (metadata) -> invalidate FW
|
// erase start of the firmware (metadata) -> invalidate FW
|
||||||
ensure(flash_unlock_write(), NULL);
|
ensure(flash_unlock_write(), NULL);
|
||||||
|
@ -5,19 +5,19 @@ void fault_handlers_init(void) {
|
|||||||
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
|
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
|
void HardFault_Handler(void) { error_shutdown("(HF)"); }
|
||||||
|
|
||||||
void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
|
void MemManage_Handler_MM(void) { error_shutdown("(MM)"); }
|
||||||
|
|
||||||
void MemManage_Handler_SO(void) { error_shutdown("INTERNAL ERROR", "(SO)"); }
|
void MemManage_Handler_SO(void) { error_shutdown("(SO)"); }
|
||||||
|
|
||||||
void BusFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(BF)"); }
|
void BusFault_Handler(void) { error_shutdown("(BF)"); }
|
||||||
|
|
||||||
void UsageFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(UF)"); }
|
void UsageFault_Handler(void) { error_shutdown("(UF)"); }
|
||||||
|
|
||||||
void NMI_Handler(void) {
|
void NMI_Handler(void) {
|
||||||
// Clock Security System triggered NMI
|
// Clock Security System triggered NMI
|
||||||
if ((RCC->CIR & RCC_CIR_CSSF) != 0) {
|
if ((RCC->CIR & RCC_CIR_CSSF) != 0) {
|
||||||
error_shutdown("INTERNAL ERROR", "(CS)");
|
error_shutdown("(CS)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,21 +98,11 @@ secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) {
|
|||||||
return secret_read(dest, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
return secret_read(dest, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void secret_show_install_restricted_screen(void) {
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
display_clear();
|
|
||||||
screen_fatal_error_rust(
|
|
||||||
"INSTALL RESTRICTED",
|
|
||||||
"Installation of custom firmware is currently restricted.",
|
|
||||||
"Please visit\ntrezor.io/bootloader");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void secret_prepare_fw(secbool allow_run_with_secret, secbool _trust_all) {
|
void secret_prepare_fw(secbool allow_run_with_secret, secbool _trust_all) {
|
||||||
#ifdef USE_OPTIGA
|
#ifdef USE_OPTIGA
|
||||||
if (sectrue != allow_run_with_secret && sectrue != secret_wiped()) {
|
if (sectrue != allow_run_with_secret && sectrue != secret_wiped()) {
|
||||||
secret_show_install_restricted_screen();
|
// This function does not return
|
||||||
trezor_shutdown();
|
show_install_restricted_screen();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -23,26 +23,15 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "secret.h"
|
|
||||||
#include "terminal.h"
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
#include "rust_ui.h"
|
|
||||||
#endif
|
|
||||||
#include "flash_otp.h"
|
#include "flash_otp.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "rand.h"
|
#include "rand.h"
|
||||||
|
#include "secret.h"
|
||||||
#include "supervise.h"
|
#include "supervise.h"
|
||||||
|
|
||||||
#include "mini_printf.h"
|
|
||||||
#include "stm32u5xx_ll_utils.h"
|
#include "stm32u5xx_ll_utils.h"
|
||||||
|
|
||||||
#ifdef RGB16
|
|
||||||
#define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00)
|
|
||||||
#else
|
|
||||||
#define COLOR_FATAL_ERROR COLOR_BLACK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t systick_val_copy = 0;
|
uint32_t systick_val_copy = 0;
|
||||||
|
|
||||||
// from util.s
|
// from util.s
|
||||||
@ -66,91 +55,6 @@ 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");
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
if (label) {
|
|
||||||
term_printf("%s\n", label);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("%s\n", msg);
|
|
||||||
}
|
|
||||||
if (footer) {
|
|
||||||
term_printf("\n%s\n", footer);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
display_backlight(255);
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
|
||||||
const char *func) {
|
|
||||||
display_orientation(0);
|
|
||||||
display_backlight(255);
|
|
||||||
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
char buf[256] = {0};
|
|
||||||
mini_snprintf(buf, sizeof(buf), "%s: %d", file, line);
|
|
||||||
screen_fatal_error_rust("INTERNAL ERROR", msg != NULL ? msg : buf,
|
|
||||||
"PLEASE VISIT\nTREZOR.IO/RSOD");
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
term_printf("\nINTERNAL ERROR:\n");
|
|
||||||
if (expr) {
|
|
||||||
term_printf("expr: %s\n", expr);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("msg : %s\n", msg);
|
|
||||||
}
|
|
||||||
if (file) {
|
|
||||||
term_printf("file: %s:%d\n", file, line);
|
|
||||||
}
|
|
||||||
if (func) {
|
|
||||||
term_printf("func: %s\n", func);
|
|
||||||
}
|
|
||||||
#ifdef SCM_REVISION
|
|
||||||
const uint8_t *rev = (const uint8_t *)SCM_REVISION;
|
|
||||||
term_printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3],
|
|
||||||
rev[4]);
|
|
||||||
#endif
|
|
||||||
term_printf("\nPlease contact Trezor support.\n");
|
|
||||||
#endif
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
error_shutdown(const char *label, const char *msg) {
|
|
||||||
display_orientation(0);
|
|
||||||
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
if (label) {
|
|
||||||
term_printf("%s\n", label);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("%s\n", msg);
|
|
||||||
}
|
|
||||||
term_printf("\nPLEASE VISIT TREZOR.IO/RSOD\n");
|
|
||||||
#endif
|
|
||||||
display_backlight(255);
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
void __assert_func(const char *file, int line, const char *func,
|
|
||||||
const char *expr) {
|
|
||||||
__fatal_error(expr, "assert failed", file, line, func);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void hal_delay(uint32_t ms) { HAL_Delay(ms); }
|
void hal_delay(uint32_t ms) { HAL_Delay(ms); }
|
||||||
uint32_t hal_ticks_ms() { return HAL_GetTick(); }
|
uint32_t hal_ticks_ms() { return HAL_GetTick(); }
|
||||||
void hal_delay_us(uint16_t delay_us) {
|
void hal_delay_us(uint16_t delay_us) {
|
||||||
@ -168,7 +72,7 @@ void hal_delay_us(uint16_t delay_us) {
|
|||||||
uint32_t __stack_chk_guard = 0;
|
uint32_t __stack_chk_guard = 0;
|
||||||
|
|
||||||
void __attribute__((noreturn)) __stack_chk_fail(void) {
|
void __attribute__((noreturn)) __stack_chk_fail(void) {
|
||||||
error_shutdown("INTERNAL ERROR", "(SS)");
|
error_shutdown("(SS)");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
|
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
|
||||||
@ -202,15 +106,6 @@ void collect_hw_entropy(void) {
|
|||||||
// where this setting might be unknown
|
// where this setting might be unknown
|
||||||
void ensure_compatible_settings(void) {}
|
void ensure_compatible_settings(void) {}
|
||||||
|
|
||||||
void show_wipe_code_screen(void) {
|
|
||||||
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_uni("TOO MANY PIN ATTEMPTS", "All data has been erased from the device",
|
|
||||||
"PLEASE RECONNECT\nTHE DEVICE");
|
|
||||||
}
|
|
||||||
|
|
||||||
void invalidate_firmware(void) {
|
void invalidate_firmware(void) {
|
||||||
// on stm32u5, we need to disable the instruction cache before erasing the
|
// on stm32u5, we need to disable the instruction cache before erasing the
|
||||||
// firmware - otherwise, the write check will fail
|
// firmware - otherwise, the write check will fail
|
||||||
|
@ -5,11 +5,11 @@ void fault_handlers_init(void) {
|
|||||||
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
|
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
|
void HardFault_Handler(void) { error_shutdown("(HF)"); }
|
||||||
|
|
||||||
void MemManage_Handler(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
|
void MemManage_Handler(void) { error_shutdown("(MM)"); }
|
||||||
|
|
||||||
void BusFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(BF)"); }
|
void BusFault_Handler(void) { error_shutdown("(BF)"); }
|
||||||
|
|
||||||
void UsageFault_Handler(void) {
|
void UsageFault_Handler(void) {
|
||||||
if (SCB->CFSR & SCB_CFSR_STKOF_Msk) {
|
if (SCB->CFSR & SCB_CFSR_STKOF_Msk) {
|
||||||
@ -17,20 +17,20 @@ void UsageFault_Handler(void) {
|
|||||||
extern uint8_t _estack; // linker script symbol
|
extern uint8_t _estack; // linker script symbol
|
||||||
// Fix stack pointer
|
// Fix stack pointer
|
||||||
__set_MSP((uint32_t)&_estack);
|
__set_MSP((uint32_t)&_estack);
|
||||||
error_shutdown("INTERNAL ERROR", "(SO)");
|
error_shutdown("(SO)");
|
||||||
} else {
|
} else {
|
||||||
// Other error
|
// Other error
|
||||||
error_shutdown("INTERNAL ERROR", "(UF)");
|
error_shutdown("(UF)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecureFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(SF)"); }
|
void SecureFault_Handler(void) { error_shutdown("(SF)"); }
|
||||||
|
|
||||||
void GTZC_IRQHandler(void) { error_shutdown("INTERNAL ERROR", "(IA)"); }
|
void GTZC_IRQHandler(void) { error_shutdown("(IA)"); }
|
||||||
|
|
||||||
void NMI_Handler(void) {
|
void NMI_Handler(void) {
|
||||||
// Clock Security System triggered NMI
|
// Clock Security System triggered NMI
|
||||||
if ((RCC->CIFR & RCC_CIFR_CSSF) != 0) {
|
if ((RCC->CIFR & RCC_CIFR_CSSF) != 0) {
|
||||||
error_shutdown("INTERNAL ERROR", "(CS)");
|
error_shutdown("(CS)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,12 +239,6 @@ void secret_erase(void) {
|
|||||||
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
|
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
|
||||||
}
|
}
|
||||||
|
|
||||||
void secret_show_install_restricted_screen(void) {
|
|
||||||
// this should never happen on U5
|
|
||||||
__fatal_error("INTERNAL ERROR", "Install restricted", __FILE__, __LINE__,
|
|
||||||
__func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all) {
|
void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all) {
|
||||||
/**
|
/**
|
||||||
* The BHK is copied to the backup registers, which are accessible by the SAES
|
* The BHK is copied to the backup registers, which are accessible by the SAES
|
||||||
|
@ -238,7 +238,7 @@ void TAMP_IRQHandler(void) {
|
|||||||
TAMP->SCR = sr;
|
TAMP->SCR = sr;
|
||||||
|
|
||||||
#ifdef BOARDLOADER
|
#ifdef BOARDLOADER
|
||||||
error_shutdown("INTERNAL TAMPER", "");
|
error_shutdown_ex("INTERNAL TAMPER", NULL, NULL);
|
||||||
#else
|
#else
|
||||||
const char* reason = "UNKNOWN";
|
const char* reason = "UNKNOWN";
|
||||||
if (sr & TAMP_SR_TAMP1F) {
|
if (sr & TAMP_SR_TAMP1F) {
|
||||||
@ -268,6 +268,6 @@ void TAMP_IRQHandler(void) {
|
|||||||
} else if (sr & TAMP_SR_ITAMP13F) {
|
} else if (sr & TAMP_SR_ITAMP13F) {
|
||||||
reason = "ANALOG WDG3";
|
reason = "ANALOG WDG3";
|
||||||
}
|
}
|
||||||
error_shutdown("INTERNAL TAMPER", reason);
|
error_shutdown_ex("INTERNAL TAMPER", reason, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -26,128 +26,16 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
#include "rust_ui.h"
|
|
||||||
#endif
|
|
||||||
#include "memzero.h"
|
#include "memzero.h"
|
||||||
|
|
||||||
extern void main_clean_exit(int);
|
|
||||||
|
|
||||||
void __attribute__((noreturn)) trezor_shutdown(void) {
|
void __attribute__((noreturn)) trezor_shutdown(void) {
|
||||||
display_finish_actions();
|
|
||||||
printf("SHUTDOWN\n");
|
printf("SHUTDOWN\n");
|
||||||
main_clean_exit(3);
|
|
||||||
for (;;)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef RGB16
|
// Wait some time to let the user see the displayed
|
||||||
#define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00)
|
// message before shutting down
|
||||||
#else
|
|
||||||
// black on monochromatic displays
|
|
||||||
#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");
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
if (label) {
|
|
||||||
term_printf("%s\n", label);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("%s\n", msg);
|
|
||||||
}
|
|
||||||
if (footer) {
|
|
||||||
term_printf("\n%s\n", footer);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
display_backlight(255);
|
|
||||||
hal_delay(3000);
|
hal_delay(3000);
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
exit(3);
|
||||||
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
|
||||||
const char *func) {
|
|
||||||
display_orientation(0);
|
|
||||||
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_rust("INTERNAL ERROR", buf,
|
|
||||||
"PLEASE VISIT\nTREZOR.IO/RSOD");
|
|
||||||
} else {
|
|
||||||
screen_fatal_error_rust("INTERNAL ERROR", msg,
|
|
||||||
"PLEASE VISIT\nTREZOR.IO/RSOD");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
term_printf("\nINTERNAL ERROR:\n");
|
|
||||||
printf("\nINTERNAL ERROR:\n");
|
|
||||||
if (expr) {
|
|
||||||
term_printf("expr: %s\n", expr);
|
|
||||||
printf("expr: %s\n", expr);
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
term_printf("msg : %s\n", msg);
|
|
||||||
printf("msg : %s\n", msg);
|
|
||||||
}
|
|
||||||
if (file) {
|
|
||||||
term_printf("file: %s:%d\n", file, line);
|
|
||||||
printf("file: %s:%d\n", file, line);
|
|
||||||
}
|
|
||||||
if (func) {
|
|
||||||
term_printf("func: %s\n", func);
|
|
||||||
printf("func: %s\n", func);
|
|
||||||
}
|
|
||||||
#ifdef SCM_REVISION
|
|
||||||
const uint8_t *rev = (const uint8_t *)SCM_REVISION;
|
|
||||||
term_printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3],
|
|
||||||
rev[4]);
|
|
||||||
printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3],
|
|
||||||
rev[4]);
|
|
||||||
#endif
|
|
||||||
term_printf("\n\n\nHint:\nIsn't the emulator already running?\n");
|
|
||||||
printf("Hint:\nIsn't the emulator already running?\n");
|
|
||||||
#endif
|
|
||||||
hal_delay(3000);
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
error_shutdown(const char *label, const char *msg) {
|
|
||||||
#ifdef FANCY_FATAL_ERROR
|
|
||||||
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
|
|
||||||
#else
|
|
||||||
display_clear();
|
|
||||||
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_FATAL_ERROR);
|
|
||||||
int y = 32;
|
|
||||||
if (label) {
|
|
||||||
display_text(8, y, label, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
printf("%s\n", label);
|
|
||||||
y += 32;
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
display_text(8, y, msg, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR);
|
|
||||||
printf("%s\n", msg);
|
|
||||||
y += 32;
|
|
||||||
}
|
|
||||||
y += 32;
|
|
||||||
display_text(8, y, "Please unplug the device.", -1, FONT_NORMAL, COLOR_WHITE,
|
|
||||||
COLOR_FATAL_ERROR);
|
|
||||||
printf("\nPlease unplug the device.\n");
|
|
||||||
#endif
|
|
||||||
display_backlight(255);
|
|
||||||
hal_delay(5000);
|
|
||||||
exit(4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hal_delay(uint32_t ms) { usleep(1000 * ms); }
|
void hal_delay(uint32_t ms) { usleep(1000 * ms); }
|
||||||
@ -161,7 +49,7 @@ uint32_t hal_ticks_ms() {
|
|||||||
static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) {
|
static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) {
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
trezor_shutdown();
|
exit(3);
|
||||||
return 0;
|
return 0;
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
if (event->key.repeat) {
|
if (event->key.repeat) {
|
||||||
@ -169,7 +57,7 @@ static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) {
|
|||||||
}
|
}
|
||||||
switch (event->key.keysym.sym) {
|
switch (event->key.keysym.sym) {
|
||||||
case SDLK_ESCAPE:
|
case SDLK_ESCAPE:
|
||||||
trezor_shutdown();
|
exit(3);
|
||||||
return 0;
|
return 0;
|
||||||
case SDLK_p:
|
case SDLK_p:
|
||||||
display_save("emu");
|
display_save("emu");
|
||||||
@ -188,12 +76,3 @@ void emulator_poll_events(void) {
|
|||||||
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
|
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
|
||||||
|
|
||||||
void collect_hw_entropy(void) { memzero(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_uni("WIPE CODE ENTERED", "All data has been erased from the device",
|
|
||||||
"PLEASE RECONNECT\nTHE DEVICE");
|
|
||||||
}
|
|
||||||
void show_pin_too_many_screen(void) {
|
|
||||||
error_uni("TOO MANY PIN ATTEMPTS", "All data has been erased from the device",
|
|
||||||
"PLEASE RECONNECT\nTHE DEVICE");
|
|
||||||
}
|
|
||||||
|
@ -27,20 +27,12 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "error_handling.h"
|
||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
#include "memzero.h"
|
#include "memzero.h"
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
|
||||||
const char *func);
|
|
||||||
|
|
||||||
#define ensure(expr, msg) \
|
|
||||||
(((expr) == sectrue) \
|
|
||||||
? (void)0 \
|
|
||||||
: __fatal_error(#expr, msg, __FILE__, __LINE__, __func__))
|
|
||||||
|
|
||||||
// emulator opens UDP server and emulates HID/WebUSB interfaces
|
// emulator opens UDP server and emulates HID/WebUSB interfaces
|
||||||
// gracefully ignores all other USB interfaces
|
// gracefully ignores all other USB interfaces
|
||||||
|
|
||||||
|
@ -407,16 +407,6 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_clean_exit(int status) {
|
|
||||||
fflush(stdout);
|
|
||||||
fflush(stderr);
|
|
||||||
// sys.exit is disabled, so raise a SystemExit exception directly
|
|
||||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_SystemExit,
|
|
||||||
MP_OBJ_NEW_SMALL_INT(status)));
|
|
||||||
// the above shouldn't return, but make sure we exit just in case
|
|
||||||
exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define PATHLIST_SEP_CHAR ';'
|
#define PATHLIST_SEP_CHAR ';'
|
||||||
#else
|
#else
|
||||||
|
Loading…
Reference in New Issue
Block a user