diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu
index b479a256a..3a2e11f78 100644
--- a/core/SConscript.bootloader_emu
+++ b/core/SConscript.bootloader_emu
@@ -129,6 +129,7 @@ SOURCE_BOOTLOADER = [
SOURCE_TREZORHAL = [
'embed/trezorhal/unix/boot_args.c',
'embed/trezorhal/unix/display-unix.c',
+ 'embed/trezorhal/unix/fault_handlers.c',
'embed/trezorhal/unix/flash.c',
'embed/trezorhal/unix/common.c',
'embed/trezorhal/unix/touch/touch.c',
diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c
index 21abe992f..24fbbc832 100644
--- a/core/embed/boardloader/main.c
+++ b/core/embed/boardloader/main.c
@@ -24,6 +24,7 @@
#include "common.h"
#include "compiler_traits.h"
#include "display.h"
+#include "fault_handlers.h"
#include "flash.h"
#include "image.h"
#include "model.h"
@@ -257,6 +258,8 @@ int main(void) {
mpu_config_boardloader();
+ fault_handlers_init();
+
#ifdef USE_SDRAM
sdram_init();
#endif
diff --git a/core/embed/boardloader/memory_stm32u5a.ld b/core/embed/boardloader/memory_stm32u5a.ld
index f5947dca9..0900bb9e5 100644
--- a/core/embed/boardloader/memory_stm32u5a.ld
+++ b/core/embed/boardloader/memory_stm32u5a.ld
@@ -14,7 +14,7 @@ MEMORY {
}
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
-_sstack = ORIGIN(SRAM2) + 0x100;
+_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@@ -80,7 +80,7 @@ SECTIONS {
} >SRAM1
.stack : ALIGN(8) {
- . = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
+ . = 16K; /* Overflow causes UsageFault */
} >SRAM2
.sensitive : ALIGN(8) {
diff --git a/core/embed/boardloader/startup_stm32u5.s b/core/embed/boardloader/startup_stm32u5.s
index fa61c0cc5..991af48e5 100644
--- a/core/embed/boardloader/startup_stm32u5.s
+++ b/core/embed/boardloader/startup_stm32u5.s
@@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
+ // set the stack protection
+ ldr r0, =_sstack
+ add r0, r0, #16 // padding
+ msr MSPLIM, r0
+
bl SystemInit
// read the first rng data and save it
diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c
index e03e2f6a0..d068ee3ee 100644
--- a/core/embed/bootloader/main.c
+++ b/core/embed/bootloader/main.c
@@ -24,6 +24,7 @@
#include "common.h"
#include "display.h"
#include "display_utils.h"
+#include "fault_handlers.h"
#include "flash.h"
#include "image.h"
#include "lowlevel.h"
@@ -424,6 +425,8 @@ int bootloader_main(void) {
mpu_config_bootloader();
+ fault_handlers_init();
+
#ifdef TREZOR_EMULATOR
// wait a bit so that the empty lock icon is visible
// (on a real device, we are waiting for touch init which takes longer)
diff --git a/core/embed/bootloader/memory_stm32u5a.ld b/core/embed/bootloader/memory_stm32u5a.ld
index 5a8302696..ad08bdd67 100644
--- a/core/embed/bootloader/memory_stm32u5a.ld
+++ b/core/embed/bootloader/memory_stm32u5a.ld
@@ -14,7 +14,7 @@ MEMORY {
}
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
-_sstack = ORIGIN(SRAM2) + 0x100;
+_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@@ -81,7 +81,7 @@ SECTIONS {
} >SRAM1
.stack : ALIGN(8) {
- . = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
+ . = 16K; /* Overflow causes UsageFault */
} >SRAM2
.sensitive : ALIGN(512) {
diff --git a/core/embed/bootloader/startup_stm32u5.s b/core/embed/bootloader/startup_stm32u5.s
index f31dabc52..ee50183b0 100644
--- a/core/embed/bootloader/startup_stm32u5.s
+++ b/core/embed/bootloader/startup_stm32u5.s
@@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
+ // set the stack protection
+ ldr r0, =_sstack
+ add r0, r0, #16 // padding
+ msr MSPLIM, r0
+
// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written
diff --git a/core/embed/bootloader_ci/memory_stm32u5a.ld b/core/embed/bootloader_ci/memory_stm32u5a.ld
index 5a8302696..ad08bdd67 100644
--- a/core/embed/bootloader_ci/memory_stm32u5a.ld
+++ b/core/embed/bootloader_ci/memory_stm32u5a.ld
@@ -14,7 +14,7 @@ MEMORY {
}
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
-_sstack = ORIGIN(SRAM2) + 0x100;
+_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@@ -81,7 +81,7 @@ SECTIONS {
} >SRAM1
.stack : ALIGN(8) {
- . = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
+ . = 16K; /* Overflow causes UsageFault */
} >SRAM2
.sensitive : ALIGN(512) {
diff --git a/core/embed/bootloader_ci/startup_stm32u5.s b/core/embed/bootloader_ci/startup_stm32u5.s
index ef0bb95a5..e8c04834e 100644
--- a/core/embed/bootloader_ci/startup_stm32u5.s
+++ b/core/embed/bootloader_ci/startup_stm32u5.s
@@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
+ // set the stack protection
+ ldr r0, =_sstack
+ add r0, r0, #16 // padding
+ msr MSPLIM, r0
+
// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written
diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c
index d4ae27b80..df934b809 100644
--- a/core/embed/firmware/main.c
+++ b/core/embed/firmware/main.c
@@ -41,6 +41,7 @@
#include "common.h"
#include "compiler_traits.h"
#include "display.h"
+#include "fault_handlers.h"
#include "flash.h"
#include "image.h"
#include "memzero.h"
@@ -146,10 +147,7 @@ int main(void) {
// Init peripherals
pendsv_init();
-#if !PRODUCTION
- // enable BUS fault and USAGE fault handlers
- SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
-#endif
+ fault_handlers_init();
#if defined TREZOR_MODEL_T
set_core_clock(CLOCK_180_MHZ);
diff --git a/core/embed/firmware/memory_DISC2.ld b/core/embed/firmware/memory_DISC2.ld
index e28dd7941..450579b4e 100644
--- a/core/embed/firmware/memory_DISC2.ld
+++ b/core/embed/firmware/memory_DISC2.ld
@@ -14,7 +14,7 @@ MEMORY {
}
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
-_sstack = ORIGIN(SRAM2) + 0x100;
+_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@@ -97,7 +97,7 @@ SECTIONS {
} >SRAM1
.stack : ALIGN(8) {
- . = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
+ . = 16K; /* Overflow causes UsageFault */
} >SRAM2
.sensitive : ALIGN(512) {
diff --git a/core/embed/firmware/startup_stm32u5.S b/core/embed/firmware/startup_stm32u5.S
index 3c1023596..19e183adc 100644
--- a/core/embed/firmware/startup_stm32u5.S
+++ b/core/embed/firmware/startup_stm32u5.S
@@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
+ // set the stack protection
+ ldr r0, =_sstack
+ add r0, r0, #16 // padding
+ msr MSPLIM, r0
+
// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written
diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c
index 97cdc80bb..033e6edbb 100644
--- a/core/embed/prodtest/main.c
+++ b/core/embed/prodtest/main.c
@@ -27,6 +27,7 @@
#include "common.h"
#include "display.h"
#include "display_utils.h"
+#include "fault_handlers.h"
#include "flash.h"
#include "i2c.h"
#include "model.h"
@@ -570,6 +571,8 @@ int main(void) {
#endif
mpu_config_prodtest();
+ fault_handlers_init();
+
drop_privileges();
display_clear();
diff --git a/core/embed/prodtest/memory_stm32u5a.ld b/core/embed/prodtest/memory_stm32u5a.ld
index 0b487d350..f5aee9ae3 100644
--- a/core/embed/prodtest/memory_stm32u5a.ld
+++ b/core/embed/prodtest/memory_stm32u5a.ld
@@ -14,7 +14,7 @@ MEMORY {
}
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
-_sstack = ORIGIN(SRAM2) + 0x100;
+_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@@ -96,7 +96,7 @@ SECTIONS {
} >SRAM1
.stack : ALIGN(8) {
- . = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
+ . = 16K; /* Overflow causes UsageFault */
} >SRAM2
.sensitive : ALIGN(512) {
diff --git a/core/embed/prodtest/startup_stm32u5.s b/core/embed/prodtest/startup_stm32u5.s
index 3c1023596..19e183adc 100644
--- a/core/embed/prodtest/startup_stm32u5.s
+++ b/core/embed/prodtest/startup_stm32u5.s
@@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
+ // set the stack protection
+ ldr r0, =_sstack
+ add r0, r0, #16 // padding
+ msr MSPLIM, r0
+
// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written
diff --git a/core/embed/reflash/memory_stm32u5a.ld b/core/embed/reflash/memory_stm32u5a.ld
index 55bda2ff3..bcd7458cc 100644
--- a/core/embed/reflash/memory_stm32u5a.ld
+++ b/core/embed/reflash/memory_stm32u5a.ld
@@ -14,7 +14,7 @@ MEMORY {
}
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
-_sstack = ORIGIN(SRAM2) + 0x100;
+_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@@ -97,7 +97,7 @@ SECTIONS {
} >SRAM1
.stack : ALIGN(8) {
- . = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
+ . = 16K + 0x100; /* Overflow causes UsageFault */
} >SRAM2
.sensitive : ALIGN(512) {
diff --git a/core/embed/reflash/startup_stm32u5.s b/core/embed/reflash/startup_stm32u5.s
index 3c1023596..19e183adc 100644
--- a/core/embed/reflash/startup_stm32u5.s
+++ b/core/embed/reflash/startup_stm32u5.s
@@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
+ // set the stack protection
+ ldr r0, =_sstack
+ add r0, r0, #16 // padding
+ msr MSPLIM, r0
+
// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written
diff --git a/core/embed/trezorhal/fault_handlers.h b/core/embed/trezorhal/fault_handlers.h
new file mode 100644
index 000000000..8372135f3
--- /dev/null
+++ b/core/embed/trezorhal/fault_handlers.h
@@ -0,0 +1,7 @@
+#ifndef TREZORHAL_FAULT_HANDLERS_H
+#define TREZORHAL_FAULT_HANDLERS_H
+
+// Initializes and enables fault handlers
+void fault_handlers_init(void);
+
+#endif // TREZORHAL_FAULT_HANDLERS_H
diff --git a/core/embed/trezorhal/stm32f4/fault_handlers.c b/core/embed/trezorhal/stm32f4/fault_handlers.c
index ae2f0bb09..ea8b8b471 100644
--- a/core/embed/trezorhal/stm32f4/fault_handlers.c
+++ b/core/embed/trezorhal/stm32f4/fault_handlers.c
@@ -1,5 +1,10 @@
#include "common.h"
+void fault_handlers_init(void) {
+ // Enable BUS fault and USAGE fault handlers
+ SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
+}
+
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
diff --git a/core/embed/trezorhal/stm32u5/fault_handlers.c b/core/embed/trezorhal/stm32u5/fault_handlers.c
index 94f9609da..3da1a1657 100644
--- a/core/embed/trezorhal/stm32u5/fault_handlers.c
+++ b/core/embed/trezorhal/stm32u5/fault_handlers.c
@@ -1,14 +1,28 @@
#include "common.h"
-void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
+void fault_handlers_init(void) {
+ // Enable BUS fault and USAGE fault handlers
+ SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
+}
-void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
+void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
-void MemManage_Handler_SO(void) { error_shutdown("INTERNAL ERROR", "(SO)"); }
+void MemManage_Handler(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
void BusFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(BF)"); }
-void UsageFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(UF)"); }
+void UsageFault_Handler(void) {
+ if (SCB->CFSR & SCB_CFSR_STKOF_Msk) {
+ // Stack overflow
+ extern uint8_t _estack; // linker script symbol
+ // Fix stack pointer
+ __set_MSP((uint32_t)&_estack);
+ error_shutdown("INTERNAL ERROR", "(SO)");
+ } else {
+ // Other error
+ error_shutdown("INTERNAL ERROR", "(UF)");
+ }
+}
void SecureFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(SF)"); }
diff --git a/core/embed/trezorhal/stm32u5/limited_util.s b/core/embed/trezorhal/stm32u5/limited_util.s
index 65adcd63f..b5dc918ae 100644
--- a/core/embed/trezorhal/stm32u5/limited_util.s
+++ b/core/embed/trezorhal/stm32u5/limited_util.s
@@ -130,16 +130,4 @@ shutdown_privileged:
ldr r0, =0
b . // loop forever
- .global MemManage_Handler
- .type MemManage_Handler, STT_FUNC
-MemManage_Handler:
- ldr r2, =_sstack
- mrs r1, msp
- ldr r0, =_estack
- msr msp, r0
- cmp r1, r2
- IT lt
- bllt MemManage_Handler_SO
- bl MemManage_Handler_MM
-
.end
diff --git a/core/embed/trezorhal/stm32u5/mpu.c b/core/embed/trezorhal/stm32u5/mpu.c
index 1cffe7dbb..51f3b0d42 100644
--- a/core/embed/trezorhal/stm32u5/mpu.c
+++ b/core/embed/trezorhal/stm32u5/mpu.c
@@ -114,8 +114,7 @@ static void mpu_set_attributes() {
#define SIZE_128K (128 * 1024)
#define SIZE_192K (192 * 1024)
#define SIZE_320K (320 * 1024)
-#define SIZE_768K (768 * 1024)
-#define SIZE_1728K ((832 * 2 + 64) * 1024)
+#define SIZE_2496K (2496 * 1024)
#define SIZE_3776K ((4096 - 320) * 1024)
#define SIZE_3904K ((4096 - 192) * 1024)
#define SIZE_4032K ((4096 - 64) * 1024)
@@ -131,10 +130,10 @@ void mpu_config_boardloader() {
SET_REGION( 0, FLASH_BASE_S, SIZE_16K, FLASH_DATA, YES, NO ); // Secret
SET_REGION( 1, FLASH_BASE_S + SIZE_16K, SIZE_48K, FLASH_CODE, NO, NO ); // Boardloader code
SET_REGION( 2, FLASH_BASE_S + SIZE_64K, SIZE_4032K, FLASH_DATA, YES, NO ); // Bootloader + Storage + Firmware
- SET_REGION( 3, SRAM1_BASE_S, SIZE_768K, SRAM, YES, NO ); // SRAM1
- SET_REGION( 4, SRAM2_BASE_S + 0x100, SIZE_1728K - 0x100, SRAM, YES, NO ); // SRAM2/3/5 + stack guard
- SET_REGION( 5, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
- SET_REGION( 6, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
+ SET_REGION( 3, SRAM1_BASE_S, SIZE_2496K, SRAM, YES, NO ); // SRAM1/2/3/5
+ SET_REGION( 4, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
+ SET_REGION( 5, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
+ DIS_REGION( 6 );
DIS_REGION( 7 );
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
@@ -148,11 +147,11 @@ void mpu_config_bootloader() {
SET_REGION( 0, FLASH_BASE_S, SIZE_64K, FLASH_DATA, YES, NO ); // Secret + Boardloader
SET_REGION( 1, FLASH_BASE_S + SIZE_64K, SIZE_128K, FLASH_CODE, NO, NO ); // Bootloader code
SET_REGION( 2, FLASH_BASE_S + SIZE_192K, SIZE_3904K, FLASH_DATA, YES, NO ); // Storage + Firmware
- SET_REGION( 3, SRAM1_BASE_S, SIZE_768K, SRAM, YES, NO ); // SRAM1
- SET_REGION( 4, SRAM2_BASE_S + 0x100, SIZE_1728K - 0x100, SRAM, YES, NO ); // SRAM2/3/5 + stack guard
- SET_REGION( 5, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
- SET_REGION( 6, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
- SET_REGION( 7, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, NO ); // OTP
+ SET_REGION( 3, SRAM1_BASE_S, SIZE_2496K, SRAM, YES, NO ); // SRAM1/2/3/5
+ SET_REGION( 4, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
+ SET_REGION( 5, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
+ SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, NO ); // OTP
+ DIS_REGION( 7 );
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
}
@@ -164,11 +163,11 @@ void mpu_config_firmware() {
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, FLASH_BASE_S + SIZE_192K, SIZE_128K, FLASH_DATA, YES, YES ); // Storage
SET_REGION( 1, FLASH_BASE_S + SIZE_320K, SIZE_3776K, FLASH_CODE, NO, YES ); // Firmware
- SET_REGION( 2, SRAM1_BASE_S, SIZE_768K, SRAM, YES, YES ); // SRAM1
- SET_REGION( 3, SRAM2_BASE_S + 0x100, SIZE_1728K - 0x100, SRAM, YES, YES ); // SRAM2/3/5 + stack guard
- SET_REGION( 4, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, YES ); // Frame buffer
- SET_REGION( 5, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, YES ); // Peripherals
- SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP
+ SET_REGION( 2, SRAM1_BASE_S, SIZE_2496K, SRAM, YES, YES ); // SRAM1/2/3/5
+ SET_REGION( 3, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, YES ); // Frame buffer
+ SET_REGION( 4, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, YES ); // Peripherals
+ SET_REGION( 5, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP
+ DIS_REGION( 6 );
DIS_REGION( 7 );
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
diff --git a/core/embed/trezorhal/unix/fault_handlers.c b/core/embed/trezorhal/unix/fault_handlers.c
new file mode 100644
index 000000000..1e7754849
--- /dev/null
+++ b/core/embed/trezorhal/unix/fault_handlers.c
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+void fault_handlers_init(void) {}