mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-04 13:52:35 +00:00
feat(core): allow passing postmortem info in bootargs
[no changelog]
This commit is contained in:
parent
cafed0d02b
commit
1a372b5019
@ -390,6 +390,16 @@ int bootloader_main(void) {
|
|||||||
|
|
||||||
drivers_init(manufacturing_mode, &touch_initialized);
|
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);
|
ui_screen_boot_stage_1(false);
|
||||||
|
|
||||||
#ifdef TREZOR_EMULATOR
|
#ifdef TREZOR_EMULATOR
|
||||||
|
@ -194,6 +194,16 @@ int main(void) {
|
|||||||
|
|
||||||
drivers_init();
|
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
|
#if PRODUCTION && !defined STM32U5
|
||||||
// for STM32U5, this check is moved to boardloader
|
// for STM32U5, this check is moved to boardloader
|
||||||
ensure_bootloader_min_version();
|
ensure_bootloader_min_version();
|
||||||
|
@ -238,6 +238,8 @@ static void coreapp_init(applet_t *applet) {
|
|||||||
applet_init(applet, coreapp_header, &coreapp_layout, &coreapp_privileges);
|
applet_init(applet, coreapp_header, &coreapp_layout, &coreapp_privileges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_BOOTARGS_RSOD
|
||||||
|
|
||||||
// Shows RSOD (Red Screen of Death)
|
// Shows RSOD (Red Screen of Death)
|
||||||
static void show_rsod(const systask_postmortem_t *pminfo) {
|
static void show_rsod(const systask_postmortem_t *pminfo) {
|
||||||
#ifdef RSOD_IN_COREAPP
|
#ifdef RSOD_IN_COREAPP
|
||||||
@ -281,13 +283,19 @@ static void init_and_show_rsod(const systask_postmortem_t *pminfo) {
|
|||||||
reboot_or_halt_after_rsod();
|
reboot_or_halt_after_rsod();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // USE_BOOTARGS_RSOD
|
||||||
|
|
||||||
// Kernel panic handler
|
// Kernel panic handler
|
||||||
// (may be called from interrupt context)
|
// (may be called from interrupt context)
|
||||||
static void kernel_panic(const systask_postmortem_t *pminfo) {
|
static void kernel_panic(const systask_postmortem_t *pminfo) {
|
||||||
// Since the system state is unreliable, enter emergency mode
|
// Since the system state is unreliable, enter emergency mode
|
||||||
// and show the RSOD.
|
// and show the RSOD.
|
||||||
|
#ifndef USE_BOOTARGS_RSOD
|
||||||
system_emergency_rescue(&init_and_show_rsod, pminfo);
|
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) {
|
int main(void) {
|
||||||
@ -318,11 +326,14 @@ int main(void) {
|
|||||||
// Release the coreapp resources
|
// Release the coreapp resources
|
||||||
applet_stop(&coreapp);
|
applet_stop(&coreapp);
|
||||||
|
|
||||||
|
#ifndef USE_BOOTARGS_RSOD
|
||||||
// Coreapp crashed, show RSOD
|
// Coreapp crashed, show RSOD
|
||||||
show_rsod(&coreapp.task.pminfo);
|
show_rsod(&coreapp.task.pminfo);
|
||||||
|
|
||||||
// Reboots or halts (if RSOD_INFINITE_LOOP is defined)
|
// Reboots or halts (if RSOD_INFINITE_LOOP is defined)
|
||||||
reboot_or_halt_after_rsod();
|
reboot_or_halt_after_rsod();
|
||||||
|
#else
|
||||||
|
reboot_with_rsod(&coreapp.task.pminfo);
|
||||||
|
#endif // USE_BOOTARGS_RSOD
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -69,10 +69,4 @@ boot_command_t bootargs_get_command();
|
|||||||
// Copies the boot arguments to the destination buffer
|
// Copies the boot arguments to the destination buffer
|
||||||
void bootargs_get_args(boot_args_t* dest);
|
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
|
#endif // TREZORHAL_BOOTARGS_H
|
||||||
|
@ -17,10 +17,9 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TREZORHAL_BOOTUTILS_H
|
#pragma once
|
||||||
#define TREZORHAL_BOOTUTILS_H
|
|
||||||
|
|
||||||
#include <trezor_types.h>
|
#include <sys/systask.h>
|
||||||
|
|
||||||
// Immediately resets the device and initiates the normal boot sequence as if
|
// Immediately resets the device and initiates the normal boot sequence as if
|
||||||
// the device was powered on
|
// the device was powered on
|
||||||
@ -42,6 +41,13 @@ void __attribute__((noreturn)) reboot_to_bootloader(void);
|
|||||||
// with the firmware installation.
|
// with the firmware installation.
|
||||||
void __attribute__((noreturn)) reboot_and_upgrade(const uint8_t hash[32]);
|
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
|
// Allows the user to read the displayed error message and then
|
||||||
// reboots the device or waits for power-off.
|
// 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
|
// Before jumping, the function disables all interrupts and clears the
|
||||||
// memory and registers that could contain sensitive information.
|
// memory and registers that could contain sensitive information.
|
||||||
void __attribute__((noreturn)) jump_to_next_stage(uint32_t vectbl_address);
|
void __attribute__((noreturn)) jump_to_next_stage(uint32_t vectbl_address);
|
||||||
|
|
||||||
#endif // TREZORHAL_BOOTUTILS_H
|
|
||||||
|
@ -79,14 +79,6 @@ void bootargs_set(boot_command_t command, const void* args, size_t args_size) {
|
|||||||
mpu_restore(mode);
|
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) {
|
void bootargs_get_args(boot_args_t* dest) {
|
||||||
mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTARGS);
|
mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTARGS);
|
||||||
|
|
||||||
@ -95,6 +87,12 @@ void bootargs_get_args(boot_args_t* dest) {
|
|||||||
mpu_restore(mode);
|
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) {
|
void bootargs_init(uint32_t r11_register) {
|
||||||
#ifdef STM32U5
|
#ifdef STM32U5
|
||||||
g_boot_command_saved = g_boot_command;
|
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);
|
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) {
|
__attribute__((noreturn)) void reboot_or_halt_after_rsod(void) {
|
||||||
#ifndef RSOD_INFINITE_LOOP
|
#ifndef RSOD_INFINITE_LOOP
|
||||||
systick_delay_ms(10 * 1000);
|
systick_delay_ms(10 * 1000);
|
||||||
|
@ -47,6 +47,11 @@ void system_deinit(void);
|
|||||||
//
|
//
|
||||||
// The system will be in a state similar to a reset when `main()` is called
|
// The system will be in a state similar to a reset when `main()` is called
|
||||||
// (but with some hardware peripherals still initialized and running).
|
// (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(
|
__attribute__((noreturn)) void system_emergency_rescue(
|
||||||
systask_error_handler_t error_handler, const systask_postmortem_t* pminfo);
|
systask_error_handler_t error_handler, const systask_postmortem_t* pminfo);
|
||||||
|
|
||||||
|
@ -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 (so we are sure that no DMA is pending)
|
||||||
reset_peripherals_and_interrupts();
|
reset_peripherals_and_interrupts();
|
||||||
|
|
||||||
// Copy pminfo from to our stack
|
// Althought MPU is disabled, we need to change MPU driver state
|
||||||
// MPU is now disable, we have full access to bootargs.
|
mpu_reconfig(MPU_MODE_DISABLED);
|
||||||
systask_postmortem_t pminfo = bootargs_ptr()->pminfo;
|
|
||||||
|
// Copy bootargs to our stack
|
||||||
|
boot_args_t bootargs;
|
||||||
|
bootargs_get_args(&bootargs);
|
||||||
|
|
||||||
// Clear unused part of our stack
|
// Clear unused part of our stack
|
||||||
clear_unused_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;
|
uint32_t stack_chk_guard = __stack_chk_guard;
|
||||||
|
|
||||||
// Clear all memory except our stack.
|
// Clear all memory except our stack.
|
||||||
// NOTE: This also clear bootargs, so we don't pass pminfo structure
|
// NOTE: This also clear bootargs, if the model doesn't support
|
||||||
// to the bootloader for now.
|
// showing RSOD in the bootloader startup.
|
||||||
memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM;
|
memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM;
|
||||||
MEMREGION_DEL_SECTION(®ion, _stack_section);
|
MEMREGION_DEL_SECTION(®ion, _stack_section);
|
||||||
|
#ifdef USE_BOOTARGS_RSOD
|
||||||
|
MEMREGION_DEL_SECTION(®ion, _bootargs_ram);
|
||||||
|
#endif
|
||||||
memregion_fill(®ion, 0);
|
memregion_fill(®ion, 0);
|
||||||
|
|
||||||
// Reinitialize .bss, .data, ...
|
// Reinitialize .bss, .data, ...
|
||||||
@ -119,12 +125,16 @@ system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
|
|||||||
// in C code
|
// in C code
|
||||||
|
|
||||||
if (error_handler != NULL) {
|
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
|
// We reach this point only if error_handler is NULL
|
||||||
// if it returns. Neither is expected to happen.
|
// (if USE_BOOTARGS_RSOD is defined we leave postmortem info
|
||||||
reboot_device();
|
// in bootargs, so it can be used by the bootloader)
|
||||||
|
NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute((naked, noreturn, no_stack_protector)) void system_emergency_rescue(
|
__attribute((naked, noreturn, no_stack_protector)) void system_emergency_rescue(
|
||||||
|
@ -139,7 +139,9 @@ const char* system_fault_message(const system_fault_t* fault) {
|
|||||||
|
|
||||||
void system_emergency_rescue(systask_error_handler_t error_handler,
|
void system_emergency_rescue(systask_error_handler_t error_handler,
|
||||||
const systask_postmortem_t* pminfo) {
|
const systask_postmortem_t* pminfo) {
|
||||||
error_handler(pminfo);
|
if (error_handler != NULL) {
|
||||||
|
error_handler(pminfo);
|
||||||
|
}
|
||||||
|
|
||||||
// We should never reach this point
|
// We should never reach this point
|
||||||
reboot_device();
|
reboot_device();
|
||||||
|
@ -39,6 +39,7 @@ def configure(
|
|||||||
("USE_LSE", "1"),
|
("USE_LSE", "1"),
|
||||||
("FIXED_HW_DEINIT", "1"),
|
("FIXED_HW_DEINIT", "1"),
|
||||||
("LOCKABLE_BOOTLOADER", "1"),
|
("LOCKABLE_BOOTLOADER", "1"),
|
||||||
|
("USE_BOOTARGS_RSOD", "1"),
|
||||||
("TERMINAL_FONT_SCALE", "2"),
|
("TERMINAL_FONT_SCALE", "2"),
|
||||||
("TERMINAL_X_PADDING", "4"),
|
("TERMINAL_X_PADDING", "4"),
|
||||||
("TERMINAL_Y_PADDING", "12"),
|
("TERMINAL_Y_PADDING", "12"),
|
||||||
|
@ -39,6 +39,7 @@ def configure(
|
|||||||
("USE_LSE", "1"),
|
("USE_LSE", "1"),
|
||||||
("FIXED_HW_DEINIT", "1"),
|
("FIXED_HW_DEINIT", "1"),
|
||||||
("LOCKABLE_BOOTLOADER", "1"),
|
("LOCKABLE_BOOTLOADER", "1"),
|
||||||
|
("USE_BOOTARGS_RSOD", "1"),
|
||||||
("TERMINAL_FONT_SCALE", "2"),
|
("TERMINAL_FONT_SCALE", "2"),
|
||||||
("TERMINAL_X_PADDING", "4"),
|
("TERMINAL_X_PADDING", "4"),
|
||||||
("TERMINAL_Y_PADDING", "12"),
|
("TERMINAL_Y_PADDING", "12"),
|
||||||
|
@ -39,6 +39,7 @@ def configure(
|
|||||||
("USE_LSE", "1"),
|
("USE_LSE", "1"),
|
||||||
("FIXED_HW_DEINIT", "1"),
|
("FIXED_HW_DEINIT", "1"),
|
||||||
("LOCKABLE_BOOTLOADER", "1"),
|
("LOCKABLE_BOOTLOADER", "1"),
|
||||||
|
("USE_BOOTARGS_RSOD", "1"),
|
||||||
("TERMINAL_FONT_SCALE", "2"),
|
("TERMINAL_FONT_SCALE", "2"),
|
||||||
("TERMINAL_X_PADDING", "4"),
|
("TERMINAL_X_PADDING", "4"),
|
||||||
("TERMINAL_Y_PADDING", "12"),
|
("TERMINAL_Y_PADDING", "12"),
|
||||||
|
Loading…
Reference in New Issue
Block a user