Skip to content

Commit

Permalink
fixup! refactor(core): rewrite rescue code in C
Browse files Browse the repository at this point in the history
  • Loading branch information
cepetr committed Jan 17, 2025
1 parent 046d9ca commit 3e9c6ed
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 8 deletions.
16 changes: 14 additions & 2 deletions core/embed/sys/startup/inc/sys/bootargs.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#ifndef TREZORHAL_BOOTARGS_H
#define TREZORHAL_BOOTARGS_H

#include <sys/systask.h>
#include <trezor_types.h>

// Defines boot command processed in bootloader on next reboot
Expand All @@ -30,19 +31,24 @@ typedef enum {
BOOT_COMMAND_STOP_AND_WAIT = 0x0FC35A96,
// Do not ask anything, install an upgrade
BOOT_COMMAND_INSTALL_UPGRADE = 0xFA4A5C8D,
// Show RSOD and wait for user input
BOOT_COMMAND_SHOW_RSOD = 0x7CD945A0,
} boot_command_t;

// Maximum size boot_args array
#define BOOT_ARGS_MAX_SIZE (256 - 8)

typedef union {
uint8_t raw[BOOT_ARGS_MAX_SIZE];

// firmware header hash, BOOT_COMMAND_INSTALL_UPGRADE
uint8_t hash[32];

// error information, BOOT_COMMAND_SHOW_RSOD
systask_postmortem_t pminfo;
} boot_args_t;

_Static_assert(sizeof(boot_args_t) == BOOT_ARGS_MAX_SIZE,
"boot_args_t structure is too long");

// Initialize bootargs module after bootloader startup
//
// r11_register is the value of the r11 register at bootloader entry.
Expand All @@ -59,4 +65,10 @@ 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
2 changes: 2 additions & 0 deletions core/embed/sys/startup/stm32/bootutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ 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;
Expand Down
17 changes: 11 additions & 6 deletions core/embed/sys/task/stm32/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <trezor_bsp.h>
#include <trezor_rtl.h>

#include <sys/bootargs.h>
#include <sys/bootutils.h>
#include <sys/linker_utils.h>
#include <sys/mpu.h>
Expand Down Expand Up @@ -83,14 +84,13 @@ void system_exit_fatal_ex(const char* message, size_t message_len,
__attribute((noreturn, no_stack_protector)) static void
system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
systask_error_handler_t error_handler = (systask_error_handler_t)arg1;
systask_postmortem_t* _pminfo = (systask_postmortem_t*)arg2;

// Reset peripherals (so we are sure that no DMA is pending)
reset_peripherals_and_interrupts();

// Copy pminfo to our stack (_pminfo will be rewritten soon)
systask_postmortem_t pminfo;
memcpy(&pminfo, _pminfo, sizeof(pminfo));
// Copy pminfo from to our stack
// MPU is now disable, we have full access to bootargs.
systask_postmortem_t pminfo = bootargs_ptr()->pminfo;

// Clear unused part of our stack
clear_unused_stack();
Expand All @@ -99,7 +99,9 @@ system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
extern uint32_t __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
// to the bootloader for now.
memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM;
MEMREGION_DEL_SECTION(&region, _stack_section);
memregion_fill(&region, 0);
Expand Down Expand Up @@ -130,7 +132,10 @@ system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {

__attribute((naked, noreturn, no_stack_protector)) void system_emergency_rescue(
systask_error_handler_t error_handler, const systask_postmortem_t* pminfo) {
call_with_new_stack((uint32_t)error_handler, (uint32_t)pminfo,
// Save `pminfo` to bootargs so it isn't overwritten by succesive call
bootargs_set(BOOT_COMMAND_SHOW_RSOD, pminfo, sizeof(*pminfo));

call_with_new_stack((uint32_t)error_handler, 0,
system_emergency_rescue_phase_2);
}

Expand Down

0 comments on commit 3e9c6ed

Please sign in to comment.