1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-03 05:12:34 +00:00

feat(core): allow passing postmortem info in bootargs

[no changelog]
This commit is contained in:
cepetr 2025-05-09 10:25:13 +02:00 committed by cepetr
parent cafed0d02b
commit 1a372b5019
12 changed files with 84 additions and 31 deletions

View File

@ -390,6 +390,16 @@ int bootloader_main(void) {
drivers_init(manufacturing_mode, &touch_initialized);
#ifdef USE_BOOTARGS_RSOD
if (bootargs_get_command() == BOOT_COMMAND_SHOW_RSOD) {
// post mortem info was left in bootargs
boot_args_t args;
bootargs_get_args(&args);
rsod_gui(&args.pminfo);
reboot_or_halt_after_rsod();
}
#endif // USE_BOOTARGS_RSOD
ui_screen_boot_stage_1(false);
#ifdef TREZOR_EMULATOR

View File

@ -194,6 +194,16 @@ int main(void) {
drivers_init();
#ifdef USE_BOOTARGS_RSOD
if (bootargs_get_command() == BOOT_COMMAND_SHOW_RSOD) {
// post mortem info was left in bootargs
boot_args_t args;
bootargs_get_args(&args);
rsod_terminal(&args.pminfo);
reboot_or_halt_after_rsod();
}
#endif // USE_BOOTARGS_RSOD
#if PRODUCTION && !defined STM32U5
// for STM32U5, this check is moved to boardloader
ensure_bootloader_min_version();

View File

@ -238,6 +238,8 @@ static void coreapp_init(applet_t *applet) {
applet_init(applet, coreapp_header, &coreapp_layout, &coreapp_privileges);
}
#ifndef USE_BOOTARGS_RSOD
// Shows RSOD (Red Screen of Death)
static void show_rsod(const systask_postmortem_t *pminfo) {
#ifdef RSOD_IN_COREAPP
@ -281,13 +283,19 @@ static void init_and_show_rsod(const systask_postmortem_t *pminfo) {
reboot_or_halt_after_rsod();
}
#endif // USE_BOOTARGS_RSOD
// Kernel panic handler
// (may be called from interrupt context)
static void kernel_panic(const systask_postmortem_t *pminfo) {
// Since the system state is unreliable, enter emergency mode
// and show the RSOD.
#ifndef USE_BOOTARGS_RSOD
system_emergency_rescue(&init_and_show_rsod, pminfo);
// The previous function call never returns
#else
reboot_with_rsod(pminfo);
#endif // USE_BOOTARGS_RSOD
// We never get here
}
int main(void) {
@ -318,11 +326,14 @@ int main(void) {
// Release the coreapp resources
applet_stop(&coreapp);
#ifndef USE_BOOTARGS_RSOD
// Coreapp crashed, show RSOD
show_rsod(&coreapp.task.pminfo);
// Reboots or halts (if RSOD_INFINITE_LOOP is defined)
reboot_or_halt_after_rsod();
#else
reboot_with_rsod(&coreapp.task.pminfo);
#endif // USE_BOOTARGS_RSOD
return 0;
}

View File

@ -69,10 +69,4 @@ boot_command_t bootargs_get_command();
// Copies the boot arguments to the destination buffer
void bootargs_get_args(boot_args_t* dest);
// Returns a pointer to the boot arguments structure.
//
// This function is intended to be used only in rescue mode, when the MPU
// is disabled and the caller has full access to the boot arguments area.
boot_args_t* bootargs_ptr(void);
#endif // TREZORHAL_BOOTARGS_H

View File

@ -17,10 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TREZORHAL_BOOTUTILS_H
#define TREZORHAL_BOOTUTILS_H
#pragma once
#include <trezor_types.h>
#include <sys/systask.h>
// Immediately resets the device and initiates the normal boot sequence as if
// the device was powered on
@ -42,6 +41,13 @@ void __attribute__((noreturn)) reboot_to_bootloader(void);
// with the firmware installation.
void __attribute__((noreturn)) reboot_and_upgrade(const uint8_t hash[32]);
#ifdef USE_BOOTARGS_RSOD
// Resets the device with post-mortem information in bootargs
// so that the bootloader can display it.
void __attribute__((noreturn))
reboot_with_rsod(const systask_postmortem_t *pminfo);
#endif
// Allows the user to read the displayed error message and then
// reboots the device or waits for power-off.
//
@ -57,5 +63,3 @@ void __attribute__((noreturn)) reboot_or_halt_after_rsod(void);
// Before jumping, the function disables all interrupts and clears the
// memory and registers that could contain sensitive information.
void __attribute__((noreturn)) jump_to_next_stage(uint32_t vectbl_address);
#endif // TREZORHAL_BOOTUTILS_H

View File

@ -79,14 +79,6 @@ void bootargs_set(boot_command_t command, const void* args, size_t args_size) {
mpu_restore(mode);
}
boot_args_t* bootargs_ptr(void) { return &g_boot_args; }
#ifdef BOOTLOADER
// Contains the current boot command saved during bootloader startup.
boot_command_t g_boot_command_saved;
boot_command_t bootargs_get_command() { return g_boot_command_saved; }
void bootargs_get_args(boot_args_t* dest) {
mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTARGS);
@ -95,6 +87,12 @@ void bootargs_get_args(boot_args_t* dest) {
mpu_restore(mode);
}
#ifdef BOOTLOADER
// Contains the current boot command saved during bootloader startup.
boot_command_t g_boot_command_saved;
boot_command_t bootargs_get_command() { return g_boot_command_saved; }
void bootargs_init(uint32_t r11_register) {
#ifdef STM32U5
g_boot_command_saved = g_boot_command;
@ -220,6 +218,12 @@ __attribute__((noreturn)) void reboot_to_off(void) {
reboot_with_args(BOOT_COMMAND_POWER_OFF, NULL, 0);
}
__attribute__((noreturn)) void reboot_with_rsod(
const systask_postmortem_t* pminfo) {
// Set bootargs area to the new command and arguments
reboot_with_args(BOOT_COMMAND_SHOW_RSOD, pminfo, sizeof(*pminfo));
}
__attribute__((noreturn)) void reboot_or_halt_after_rsod(void) {
#ifndef RSOD_INFINITE_LOOP
systick_delay_ms(10 * 1000);

View File

@ -47,6 +47,11 @@ void system_deinit(void);
//
// The system will be in a state similar to a reset when `main()` is called
// (but with some hardware peripherals still initialized and running).
//
// If `error_handler` is NULL the system will be reset immediately after
// clearing the memory. If `USE_BOOTARGS_RSOD` is defined, the system will
// leave the postmortem information in the bootargs allowing the bootloader
// to display the RSOD.
__attribute__((noreturn)) void system_emergency_rescue(
systask_error_handler_t error_handler, const systask_postmortem_t* pminfo);

View File

@ -85,9 +85,12 @@ system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
// Reset peripherals (so we are sure that no DMA is pending)
reset_peripherals_and_interrupts();
// Copy pminfo from to our stack
// MPU is now disable, we have full access to bootargs.
systask_postmortem_t pminfo = bootargs_ptr()->pminfo;
// Althought MPU is disabled, we need to change MPU driver state
mpu_reconfig(MPU_MODE_DISABLED);
// Copy bootargs to our stack
boot_args_t bootargs;
bootargs_get_args(&bootargs);
// Clear unused part of our stack
clear_unused_stack();
@ -97,10 +100,13 @@ system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
uint32_t stack_chk_guard = __stack_chk_guard;
// Clear all memory except our stack.
// NOTE: This also clear bootargs, so we don't pass pminfo structure
// to the bootloader for now.
// NOTE: This also clear bootargs, if the model doesn't support
// showing RSOD in the bootloader startup.
memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM;
MEMREGION_DEL_SECTION(&region, _stack_section);
#ifdef USE_BOOTARGS_RSOD
MEMREGION_DEL_SECTION(&region, _bootargs_ram);
#endif
memregion_fill(&region, 0);
// Reinitialize .bss, .data, ...
@ -119,12 +125,16 @@ system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
// in C code
if (error_handler != NULL) {
error_handler(&pminfo);
error_handler(&bootargs.pminfo);
// We reach this point only if error_handler returns that's
// not expected to happen. We clear the memory again and reboot.
reboot_device();
}
// We reach this point only if error_handler is NULL or
// if it returns. Neither is expected to happen.
reboot_device();
// We reach this point only if error_handler is NULL
// (if USE_BOOTARGS_RSOD is defined we leave postmortem info
// in bootargs, so it can be used by the bootloader)
NVIC_SystemReset();
}
__attribute((naked, noreturn, no_stack_protector)) void system_emergency_rescue(

View File

@ -139,7 +139,9 @@ const char* system_fault_message(const system_fault_t* fault) {
void system_emergency_rescue(systask_error_handler_t error_handler,
const systask_postmortem_t* pminfo) {
if (error_handler != NULL) {
error_handler(pminfo);
}
// We should never reach this point
reboot_device();

View File

@ -39,6 +39,7 @@ def configure(
("USE_LSE", "1"),
("FIXED_HW_DEINIT", "1"),
("LOCKABLE_BOOTLOADER", "1"),
("USE_BOOTARGS_RSOD", "1"),
("TERMINAL_FONT_SCALE", "2"),
("TERMINAL_X_PADDING", "4"),
("TERMINAL_Y_PADDING", "12"),

View File

@ -39,6 +39,7 @@ def configure(
("USE_LSE", "1"),
("FIXED_HW_DEINIT", "1"),
("LOCKABLE_BOOTLOADER", "1"),
("USE_BOOTARGS_RSOD", "1"),
("TERMINAL_FONT_SCALE", "2"),
("TERMINAL_X_PADDING", "4"),
("TERMINAL_Y_PADDING", "12"),

View File

@ -39,6 +39,7 @@ def configure(
("USE_LSE", "1"),
("FIXED_HW_DEINIT", "1"),
("LOCKABLE_BOOTLOADER", "1"),
("USE_BOOTARGS_RSOD", "1"),
("TERMINAL_FONT_SCALE", "2"),
("TERMINAL_X_PADDING", "4"),
("TERMINAL_Y_PADDING", "12"),