diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 183f93901..f6f032bfa 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -49,6 +49,9 @@ #include "supervise.h" #include "touch.h" +// from util.s +extern void shutdown_privileged(void); + int main(void) { random_delays_init(); @@ -180,6 +183,11 @@ void SVC_C_Handler(uint32_t *stack) { cyccnt_cycles = *DWT_CYCCNT_ADDR; break; #endif + case SVC_SHUTDOWN: + shutdown_privileged(); + for (;;) + ; + break; default: stack[0] = 0xffffffff; break; diff --git a/core/embed/trezorhal/supervise.h b/core/embed/trezorhal/supervise.h index e1ca2dc9b..9fc5fba8c 100644 --- a/core/embed/trezorhal/supervise.h +++ b/core/embed/trezorhal/supervise.h @@ -3,6 +3,10 @@ #define SVC_ENABLE_IRQ 0 #define SVC_DISABLE_IRQ 1 #define SVC_SET_PRIORITY 2 +#define SVC_SHUTDOWN 4 + +// from util.s +extern void shutdown_privileged(void); static inline uint32_t is_mode_unprivileged(void) { uint32_t r0; @@ -38,3 +42,11 @@ static inline void svc_setpriority(uint32_t IRQn, uint32_t priority) { NVIC_SetPriority(IRQn, priority); } } + +static inline void svc_shutdown(void) { + if (is_mode_unprivileged()) { + __asm__ __volatile__("svc %0" ::"i"(SVC_SHUTDOWN) : "memory"); + } else { + shutdown_privileged(); + } +}