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

feat(core): reset peripherals during handovers

[no changelog]
This commit is contained in:
cepetr 2025-01-29 21:36:01 +01:00 committed by cepetr
parent 236c377e20
commit f99030938e
5 changed files with 117 additions and 102 deletions

View File

@ -413,6 +413,10 @@
#endif /* USE_FULL_ASSERT */ #endif /* USE_FULL_ASSERT */
#ifndef HardFault_IRQn
#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32f429xx.h
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -49,8 +49,17 @@ void ensure_thread_mode(void);
void ensure_compatible_settings(void); void ensure_compatible_settings(void);
// Clears USB peripheral fifo memory // Clears USB peripheral fifo memory
//
// Used to wipe sensitive data from USB peripheral memory.
void clear_otg_hs_memory(void); void clear_otg_hs_memory(void);
// Resets critical peripherals, disables all interrupts, and clears
// pending interrupts in the NVIC controller.
//
// This function is used to stop pending DMA transfers and interrupts,
// ensuring it is safe to jump to the next stage or initiate rescue mode.
void reset_peripherals_and_interrupts(void);
// Jumps to the binary using its vector table. // Jumps to the binary using its vector table.
// //
// The target binary is called with interrupts disabled, and all registers // The target binary is called with interrupts disabled, and all registers

View File

@ -104,6 +104,10 @@ static void reboot_with_args_phase_2(uint32_t arg1, uint32_t arg2) {
// any variables in the .bss and .data sections, so we must // any variables in the .bss and .data sections, so we must
// be careful and avoid using them altogether. // be careful and avoid using them altogether.
// Reset peripherals (so we are sure that no DMA is pending)
// and disable all interrupts and clear all pending ones
reset_peripherals_and_interrupts();
// Clear unused part of stack // Clear unused part of stack
clear_unused_stack(); clear_unused_stack();
@ -174,6 +178,10 @@ static void jump_to_next_stage_phase_2(uint32_t arg1, uint32_t arg2) {
// any variables in the .bss and .data sections, so we must // any variables in the .bss and .data sections, so we must
// be careful and avoid using them altogether. // be careful and avoid using them altogether.
// Reset peripherals (so we are sure that no DMA is pending)
// and disable all interrupts and clear all pending ones
reset_peripherals_and_interrupts();
// Clear unused part of stack // Clear unused part of stack
clear_unused_stack(); clear_unused_stack();

View File

@ -260,4 +260,99 @@ __attribute((naked, noreturn, no_stack_protector)) void jump_to_vectbl(
); );
} }
void reset_peripherals_and_interrupts(void) {
#ifdef __HAL_RCC_DMA2D_FORCE_RESET
__HAL_RCC_DMA2D_CLK_DISABLE();
__HAL_RCC_DMA2D_FORCE_RESET();
__HAL_RCC_DMA2D_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_DSI_FORCE_RESET
__HAL_RCC_DSI_CLK_DISABLE();
__HAL_RCC_DSI_FORCE_RESET();
__HAL_RCC_DSI_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_GFXMMU_FORCE_RESET
__HAL_RCC_GFXMMU_CLK_DISABLE();
__HAL_RCC_GFXMMU_FORCE_RESET();
__HAL_RCC_GFXMMU_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_LTDC_FORCE_RESET
__HAL_RCC_LTDC_CLK_DISABLE();
__HAL_RCC_LTDC_FORCE_RESET();
__HAL_RCC_LTDC_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_GPDMA1_FORCE_RESET
__HAL_RCC_GPDMA1_CLK_DISABLE();
__HAL_RCC_GPDMA1_FORCE_RESET();
__HAL_RCC_GPDMA1_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_DMA1_FORCE_RESET
__HAL_RCC_DMA1_CLK_DISABLE();
__HAL_RCC_DMA1_FORCE_RESET();
__HAL_RCC_DMA1_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_DMA2_FORCE_RESET
__HAL_RCC_DMA2_CLK_DISABLE();
__HAL_RCC_DMA2_FORCE_RESET();
__HAL_RCC_DMA2_RELEASE_RESET();
#endif
// Disable all NVIC interrupts and clear pending flags
// so later the global interrupt can be re-enabled without
// firing any pending interrupt
for (int irqn = 0; irqn < 255; irqn++) {
NVIC_DisableIRQ(irqn);
NVIC_ClearPendingIRQ(irqn);
}
// Disable SysTick
SysTick->CTRL = 0;
// Clear PENDSV flag to prevent the PendSV_Handler call
SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk;
// Clear SCB->SHCSR exception flags so we can return back
// to thread mode without any exception active
uint32_t preserved_flag = 0;
switch ((__get_IPSR() & IPSR_ISR_Msk) - 16) {
case MemoryManagement_IRQn:
preserved_flag = SCB_SHCSR_MEMFAULTACT_Msk;
break;
case BusFault_IRQn:
preserved_flag = SCB_SHCSR_BUSFAULTACT_Msk;
break;
case UsageFault_IRQn:
preserved_flag = SCB_SHCSR_USGFAULTACT_Msk;
break;
case PendSV_IRQn:
preserved_flag = SCB_SHCSR_PENDSVACT_Msk;
break;
case SysTick_IRQn:
preserved_flag = SCB_SHCSR_SYSTICKACT_Msk;
break;
case SVCall_IRQn:
preserved_flag = SCB_SHCSR_SVCALLACT_Msk;
break;
case HardFault_IRQn:
default:
break;
}
const uint32_t cleared_flags =
SCB_SHCSR_MEMFAULTACT_Msk | SCB_SHCSR_BUSFAULTACT_Msk |
SCB_SHCSR_USGFAULTACT_Msk | SCB_SHCSR_SVCALLACT_Msk |
SCB_SHCSR_MONITORACT_Msk | SCB_SHCSR_PENDSVACT_Msk |
SCB_SHCSR_SYSTICKACT_Msk;
SCB->SHCSR &= ~(cleared_flags & ~preserved_flag);
}
#endif // KERNEL_MODE #endif // KERNEL_MODE

View File

@ -38,10 +38,6 @@
#include "../stm32f4/startup_init.h" #include "../stm32f4/startup_init.h"
#endif #endif
#ifndef HardFault_IRQn
#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32429xx.h
#endif
#ifdef KERNEL_MODE #ifdef KERNEL_MODE
void system_init(systask_error_handler_t error_handler) { void system_init(systask_error_handler_t error_handler) {
@ -81,109 +77,12 @@ void system_exit_fatal_ex(const char* message, size_t message_len,
systask_exit_fatal(NULL, message, message_len, file, file_len, line); systask_exit_fatal(NULL, message, message_len, file, file_len, line);
} }
__attribute__((used)) static void emergency_reset(void) {
// Reset peripherals
#ifdef __HAL_RCC_DMA2D_FORCE_RESET
__HAL_RCC_DMA2D_CLK_DISABLE();
__HAL_RCC_DMA2D_FORCE_RESET();
__HAL_RCC_DMA2D_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_DSI_FORCE_RESET
__HAL_RCC_DSI_CLK_DISABLE();
__HAL_RCC_DSI_FORCE_RESET();
__HAL_RCC_DSI_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_GFXMMU_FORCE_RESET
__HAL_RCC_GFXMMU_CLK_DISABLE();
__HAL_RCC_GFXMMU_FORCE_RESET();
__HAL_RCC_GFXMMU_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_LTDC_FORCE_RESET
__HAL_RCC_LTDC_CLK_DISABLE();
__HAL_RCC_LTDC_FORCE_RESET();
__HAL_RCC_LTDC_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_GPDMA1_FORCE_RESET
__HAL_RCC_GPDMA1_CLK_DISABLE();
__HAL_RCC_GPDMA1_FORCE_RESET();
__HAL_RCC_GPDMA1_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_DMA1_FORCE_RESET
__HAL_RCC_DMA1_CLK_DISABLE();
__HAL_RCC_DMA1_FORCE_RESET();
__HAL_RCC_DMA1_RELEASE_RESET();
#endif
#ifdef __HAL_RCC_DMA2_FORCE_RESET
__HAL_RCC_DMA2_CLK_DISABLE();
__HAL_RCC_DMA2_FORCE_RESET();
__HAL_RCC_DMA2_RELEASE_RESET();
#endif
// Disable all NVIC interrupts and clear pending flags
// so later the global interrupt can be re-enabled without
// firing any pending interrupt
for (int irqn = 0; irqn < 255; irqn++) {
NVIC_DisableIRQ(irqn);
NVIC_ClearPendingIRQ(irqn);
}
// Disable SysTick
SysTick->CTRL = 0;
// Clear PENDSV flag to prevent the PendSV_Handler call
SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk;
// Clear SCB->SHCSR exception flags so we can return back
// to thread mode without any exception active
uint32_t preserved_flag = 0;
switch ((__get_IPSR() & IPSR_ISR_Msk) - 16) {
case MemoryManagement_IRQn:
preserved_flag = SCB_SHCSR_MEMFAULTACT_Msk;
break;
case BusFault_IRQn:
preserved_flag = SCB_SHCSR_BUSFAULTACT_Msk;
break;
case UsageFault_IRQn:
preserved_flag = SCB_SHCSR_USGFAULTACT_Msk;
break;
case PendSV_IRQn:
preserved_flag = SCB_SHCSR_PENDSVACT_Msk;
break;
case SysTick_IRQn:
preserved_flag = SCB_SHCSR_SYSTICKACT_Msk;
break;
case SVCall_IRQn:
preserved_flag = SCB_SHCSR_SVCALLACT_Msk;
break;
case HardFault_IRQn:
default:
break;
}
const uint32_t cleared_flags =
SCB_SHCSR_MEMFAULTACT_Msk | SCB_SHCSR_BUSFAULTACT_Msk |
SCB_SHCSR_USGFAULTACT_Msk | SCB_SHCSR_SVCALLACT_Msk |
SCB_SHCSR_MONITORACT_Msk | SCB_SHCSR_PENDSVACT_Msk |
SCB_SHCSR_SYSTICKACT_Msk;
SCB->SHCSR &= ~(cleared_flags & ~preserved_flag);
}
__attribute((noreturn, no_stack_protector)) static void __attribute((noreturn, no_stack_protector)) static void
system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) { system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
systask_error_handler_t error_handler = (systask_error_handler_t)arg1; systask_error_handler_t error_handler = (systask_error_handler_t)arg1;
// Reset peripherals (so we are sure that no DMA is pending) // Reset peripherals (so we are sure that no DMA is pending)
emergency_reset(); reset_peripherals_and_interrupts();
// Copy pminfo from to our stack // Copy pminfo from to our stack
// MPU is now disable, we have full access to bootargs. // MPU is now disable, we have full access to bootargs.