diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader index 02ff3258117..c067a83db81 100644 --- a/core/SConscript.boardloader +++ b/core/SConscript.boardloader @@ -79,10 +79,7 @@ env = Environment(ENV=os.environ, FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) -FILE_SUFFIX= env.get('ENV')['SUFFIX'] - SOURCE_BOARDLOADER = [ - f"embed/sys/startup/{FILE_SUFFIX}/startup_stage_0.s", 'embed/projects/boardloader/main.c', ] diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 2d7b1338564..95c9cffec55 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -101,10 +101,7 @@ env = Environment( FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) -FILE_SUFFIX= env.get('ENV')['SUFFIX'] - SOURCE_BOOTLOADER = [ - f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_1.s', 'embed/projects/bootloader/header.S', 'embed/projects/bootloader/bootui.c', 'embed/projects/bootloader/main.c', diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci index 7df885fdfb3..2c8bb2f661e 100644 --- a/core/SConscript.bootloader_ci +++ b/core/SConscript.bootloader_ci @@ -95,10 +95,7 @@ env = Environment( FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) -FILE_SUFFIX= env.get('ENV')['SUFFIX'] - SOURCE_BOOTLOADER = [ - f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_1.s', 'embed/projects/bootloader_ci/header.S', 'embed/projects/bootloader_ci/bootui.c', 'embed/projects/bootloader_ci/main.c', diff --git a/core/SConscript.firmware b/core/SConscript.firmware index c2d36dea190..e5dcc6a4111 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -397,14 +397,11 @@ env = Environment( FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) -FILE_SUFFIX= env.get('ENV')['SUFFIX'] - SOURCE_FIRMWARE = [ 'embed/projects/firmware/header.S', 'embed/projects/firmware/main.c', 'embed/projects/firmware/mphalport.c', 'embed/projects/firmware/nlrthumb.c', - f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_4.s', ] if 'sd_card' in FEATURES_AVAILABLE: diff --git a/core/SConscript.kernel b/core/SConscript.kernel index 6cdf868ec91..626904922e8 100644 --- a/core/SConscript.kernel +++ b/core/SConscript.kernel @@ -258,11 +258,8 @@ env = Environment( FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) -FILE_SUFFIX= env.get('ENV')['SUFFIX'] - SOURCE_FIRMWARE = [ 'embed/projects/kernel/main.c', - f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_2.s', ] if 'sd_card' in FEATURES_AVAILABLE: diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index ddce05f1528..558062bd42b 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -95,11 +95,7 @@ env = Environment( FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) -FILE_SUFFIX= env.get('ENV')['SUFFIX'] - - SOURCE_PRODTEST = [ - f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_2.s', 'embed/projects/prodtest/header.S', 'embed/projects/prodtest/main.c', 'embed/projects/prodtest/prodtest_common.c', diff --git a/core/SConscript.reflash b/core/SConscript.reflash index 464bf186505..b72201a74f8 100644 --- a/core/SConscript.reflash +++ b/core/SConscript.reflash @@ -81,10 +81,7 @@ env = Environment( FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) -FILE_SUFFIX= env.get('ENV')['SUFFIX'] - SOURCE_REFLASH = [ - f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_2.s', 'embed/projects/reflash/header.S', 'embed/projects/reflash/main.c', ] diff --git a/core/embed/io/display/ltdc_dsi/display_driver.c b/core/embed/io/display/ltdc_dsi/display_driver.c index f1439ccbcf1..717ecd0fdb0 100644 --- a/core/embed/io/display/ltdc_dsi/display_driver.c +++ b/core/embed/io/display/ltdc_dsi/display_driver.c @@ -427,15 +427,6 @@ bool display_init(display_content_mode_t mode) { void display_deinit(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; - if (mode == DISPLAY_RETAIN_CONTENT) { - // This is a temporary workaround for T3W1 to avoid clearing - // the display after drawing RSOD screen in `secure_shutdown()` - // function. The workaround should be removed once we have - // proper replacement for `secure_shutdown()` that resets the - // device instead of waiting for manual power off. - return; - } - GPIO_InitTypeDef GPIO_InitStructure = {0}; gfx_bitblt_deinit(); diff --git a/core/embed/projects/boardloader/main.c b/core/embed/projects/boardloader/main.c index 2eab5d052fa..bcfa3446cb9 100644 --- a/core/embed/projects/boardloader/main.c +++ b/core/embed/projects/boardloader/main.c @@ -106,7 +106,6 @@ static void drivers_deinit(void) { #ifdef USE_POWERCTL powerctl_deinit(); #endif - ensure_compatible_settings(); } static uint8_t get_bootloader_min_version(void) { @@ -323,7 +322,7 @@ int main(void) { system_deinit(); // g_boot_command is preserved on STM32U5 - jump_to(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE)); + jump_to_next_stage(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE)); return 0; } diff --git a/core/embed/projects/bootloader/emulator.c b/core/embed/projects/bootloader/emulator.c index b2bd30a452f..8f46770f5a1 100644 --- a/core/embed/projects/bootloader/emulator.c +++ b/core/embed/projects/bootloader/emulator.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -111,7 +112,7 @@ static int sdl_event_filter(void *userdata, SDL_Event *event) { return 1; } -__attribute__((noreturn)) int main(int argc, char **argv) { +int main(int argc, char **argv) { SDL_SetEventFilter(sdl_event_filter, NULL); display_init(DISPLAY_RESET_CONTENT); @@ -189,10 +190,12 @@ __attribute__((noreturn)) int main(int argc, char **argv) { bootloader_main(); hal_delay(3000); - jump_to(0); + jump_to_next_stage(0); + + return 0; } -void jump_to(uint32_t address) { +void jump_to_next_stage(uint32_t address) { bool storage_is_erased = storage_empty(&STORAGE_AREAS[0]) && storage_empty(&STORAGE_AREAS[1]); diff --git a/core/embed/projects/bootloader/emulator.h b/core/embed/projects/bootloader/emulator.h index aa90a93f823..721490e912a 100644 --- a/core/embed/projects/bootloader/emulator.h +++ b/core/embed/projects/bootloader/emulator.h @@ -7,6 +7,4 @@ extern uint8_t *FIRMWARE_START; -__attribute__((noreturn)) void jump_to(uint32_t address); - #endif diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c index 6878e926c46..1a65b6796fb 100644 --- a/core/embed/projects/bootloader/main.c +++ b/core/embed/projects/bootloader/main.c @@ -141,7 +141,6 @@ static void drivers_deinit(void) { #endif #endif display_deinit(DISPLAY_JUMP_BEHAVIOR); - ensure_compatible_settings(); } static void usb_init_all(secbool usb21_landing) { @@ -382,7 +381,8 @@ void real_jump_to_firmware(void) { system_deinit(); - jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); + jump_to_next_stage( + IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); } #ifdef USE_RESET_TO_BOOT diff --git a/core/embed/projects/bootloader_ci/main.c b/core/embed/projects/bootloader_ci/main.c index cc790e4ff32..634ee0864a3 100644 --- a/core/embed/projects/bootloader_ci/main.c +++ b/core/embed/projects/bootloader_ci/main.c @@ -276,7 +276,8 @@ int main(void) { system_deinit(); - jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); + jump_to_next_stage( + IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); return 0; } diff --git a/core/embed/projects/firmware/main.c b/core/embed/projects/firmware/main.c index 3f2094ea61f..39435894500 100644 --- a/core/embed/projects/firmware/main.c +++ b/core/embed/projects/firmware/main.c @@ -32,6 +32,7 @@ #include "ports/stm32/gccollect.h" #include "ports/stm32/pendsv.h" +#include #include #include #include @@ -57,8 +58,9 @@ int main(uint32_t cmd, void *arg) { printf("CORE: Preparing stack\n"); // Stack limit should be less than real stack size, so we have a chance // to recover from limit hit. - mp_stack_set_top(&_estack); - mp_stack_set_limit((char *)&_estack - (char *)&_sstack - 1024); + mp_stack_set_top(&_stack_section_end); + mp_stack_set_limit((char *)&_stack_section_end - + (char *)&_stack_section_start - 1024); #if MICROPY_ENABLE_PYSTACK static mp_obj_t pystack[1024]; @@ -106,3 +108,22 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); + +// `reset_handler` is the application entry point (first routine called +// from kernel) +__attribute((no_stack_protector)) void reset_handler(uint32_t cmd, void *arg, + uint32_t random_value) { + // Initialize linker script defined sections (.bss, .data, ...) + init_linker_sections(); + + // Initialize stack protector + extern uint32_t __stack_chk_guard; + __stack_chk_guard = random_value; + + // Now everything is perfectly initialized and we can do anything + // in C code + + int main_result = main(cmd, arg); + + system_exit(main_result); +} diff --git a/core/embed/projects/kernel/main.c b/core/embed/projects/kernel/main.c index cf241746b6a..146652b240f 100644 --- a/core/embed/projects/kernel/main.c +++ b/core/embed/projects/kernel/main.c @@ -220,8 +220,8 @@ static void show_rsod(const systask_postmortem_t *pminfo) { applet_run(&coreapp); if (coreapp.task.pminfo.reason == TASK_TERM_REASON_EXIT) { - // If the RSOD was shown successfully, proceed to shutdown - secure_shutdown(); + // RSOD was shown successfully + return; } } #endif @@ -243,8 +243,8 @@ static void init_and_show_rsod(const systask_postmortem_t *pminfo) { // Show RSOD show_rsod(pminfo); - // Wait for the user to manually power off the device - secure_shutdown(); + // Reboots or halts (if RSOD_INFINITE_LOOP is defined) + reboot_or_halt_after_rsod(); } // Kernel panic handler @@ -283,8 +283,8 @@ int main(void) { // Coreapp crashed, show RSOD show_rsod(&coreapp.task.pminfo); - // Wait for the user to manually power off the device - secure_shutdown(); + // Reboots or halts (if RSOD_INFINITE_LOOP is defined) + reboot_or_halt_after_rsod(); return 0; } diff --git a/core/embed/sec/random_delays/stm32/random_delays.c b/core/embed/sec/random_delays/stm32/random_delays.c index 1078a458e6c..79790b7fcc4 100644 --- a/core/embed/sec/random_delays/stm32/random_delays.c +++ b/core/embed/sec/random_delays/stm32/random_delays.c @@ -29,9 +29,6 @@ #ifdef KERNEL_MODE -// from util.s -extern void shutdown_privileged(void); - #define DRBG_RESEED_INTERVAL_CALLS 1000 #define DRBG_TRNG_ENTROPY_LENGTH 50 _Static_assert(CHACHA_DRBG_OPTIMAL_RESEED_LENGTH(1) == DRBG_TRNG_ENTROPY_LENGTH, @@ -192,14 +189,14 @@ void wait_random(void) { volatile int j = wait; while (i < wait) { if (i + j != wait) { - shutdown_privileged(); + error_shutdown("(glitch)"); } ++i; --j; } // Double-check loop completion. if (i != wait || j != 0) { - shutdown_privileged(); + error_shutdown("(glitch)"); } #endif } diff --git a/core/embed/sys/bsp/stm32f4/stm32f4xx_hal_conf.h b/core/embed/sys/bsp/stm32f4/stm32f4xx_hal_conf.h index 467d575be65..ebd2e3ea696 100644 --- a/core/embed/sys/bsp/stm32f4/stm32f4xx_hal_conf.h +++ b/core/embed/sys/bsp/stm32f4/stm32f4xx_hal_conf.h @@ -413,6 +413,10 @@ #endif /* USE_FULL_ASSERT */ +#ifndef HardFault_IRQn +#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32f429xx.h +#endif + #ifdef __cplusplus } #endif diff --git a/core/embed/sys/linker/inc/sys/linker_utils.h b/core/embed/sys/linker/inc/sys/linker_utils.h new file mode 100644 index 00000000000..9975fc83725 --- /dev/null +++ b/core/embed/sys/linker/inc/sys/linker_utils.h @@ -0,0 +1,99 @@ + +/* + * 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 . + */ + +#pragma once + +// symbols defined in the linker script +extern uint8_t _stack_section_start; +extern uint8_t _stack_section_end; + +// Initialize linker script-defined sections (.bss, .data, etc.) +// +// This function must be called only during the startup sequence, +// before executing any other code. In special cases, it can be used +// to reinitialize these sections if necessary. +void init_linker_sections(void); + +// Clears the unused portion of the stack. +// +// This includes memory between the start of the stack +// and the current stack pointer (SP). +// +// It's safe to call this function at any time, but it's +// recommended to call it only during the startup sequence. +void clear_unused_stack(void); + +// Maximum number of memory blocks in a memory region +#define MEMREGION_MAX_BLOCKS 8 + +typedef struct { + // block start address (inclusive) + void* start; + // block end address (exclusive) + void* end; +} memregion_block_t; + +typedef struct { + // non-overlapping memory blocks ordered by start address + memregion_block_t block[MEMREGION_MAX_BLOCKS]; +} memregion_t; + +#define MEMREGION_ALL_ACCESSIBLE_RAM \ + ({ \ + extern uint8_t _accessible_ram_0_start; \ + extern uint8_t _accessible_ram_0_end; \ + extern uint8_t _accessible_ram_1_start; \ + extern uint8_t _accessible_ram_1_end; \ + (memregion_t){.block = { \ + {&_accessible_ram_0_start, &_accessible_ram_0_end}, \ + {&_accessible_ram_1_start, &_accessible_ram_1_end}, \ + }}; \ + }) + +// Adds a new address range to the memory region. +// +// The start and end pointers must be aligned to 4-byte boundaries. +// +// The current implementation does not merge overlapping or adjacent blocks. +// This behavior is not required for the current use case and, in the +// worst case, will result in a few additional blocks in the region. +void memregion_add_range(memregion_t* region, void* start, void* end); + +// Deletes an address range from the memory region +// +// The range start and end pointers must be aligned to the 4 bytes. +void memregion_del_range(memregion_t* region, void* start, void* end); + +// Fill memory region with a value 32-bit value +void memregion_fill(memregion_t* region, uint32_t value); + +#define MEMREGION_ADD_SECTION(region, section_name) \ + { \ + extern uint8_t section_name##_start; \ + extern uint8_t section_name##_end; \ + memregion_add_range(region, §ion_name##_start, §ion_name##_end); \ + } + +#define MEMREGION_DEL_SECTION(region, section_name) \ + { \ + extern uint8_t section_name##_start; \ + extern uint8_t section_name##_end; \ + memregion_del_range(region, §ion_name##_start, §ion_name##_end); \ + } diff --git a/core/embed/sys/linker/linker_utils.c b/core/embed/sys/linker/linker_utils.c new file mode 100644 index 00000000000..84419ed12b9 --- /dev/null +++ b/core/embed/sys/linker/linker_utils.c @@ -0,0 +1,193 @@ +/* + * 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 + +#include + +void init_linker_sections(void) { + extern uint32_t _bss_section_start; + extern uint32_t _bss_section_end; + extern uint32_t _data_section_start; + extern uint32_t _data_section_end; + extern uint32_t _data_section_loadaddr; + extern uint32_t _confidential_section_start; + extern uint32_t _confidential_section_end; + extern uint32_t _confidential_section_loadaddr; + + // Pointer are intentionally volatile to prevent optimization + // (otherwise the compiler may optimize loops to memset/memcpy) + volatile uint32_t* dst; + volatile uint32_t* src; + + dst = &_bss_section_start; + while (dst < &_bss_section_end) { + *dst++ = 0; + } + + dst = &_data_section_start; + src = &_data_section_loadaddr; + while (dst < &_data_section_end) { + *dst++ = *src++; + } + + dst = &_confidential_section_start; + src = &_confidential_section_loadaddr; + while (dst < &_confidential_section_end) { + *dst++ = *src++; + } +} + +__attribute((naked, no_stack_protector)) void clear_unused_stack(void) { + __asm__ volatile( + " MOV R0, #0 \n" + " LDR R1, =%[sstack] \n" + "1: \n" + " STR R0, [R1], #4 \n" + " CMP R1, SP \n" + " BNE 1b \n" + " BX LR \n" + : // no output + : [sstack] "i"((uint32_t)&_stack_section_start) + : // no clobber + ); +} + +static void memregion_remove_block(memregion_t* region, int idx) { + if (idx < 0 || idx >= MEMREGION_MAX_BLOCKS) { + return; + } + + for (int i = idx; i < MEMREGION_MAX_BLOCKS - 1; i++) { + region->block[i] = region->block[i + 1]; + } + + memregion_block_t* last = ®ion->block[MEMREGION_MAX_BLOCKS - 1]; + last->start = NULL; + last->end = NULL; +} + +static void memregion_insert_block(memregion_t* region, int idx, void* start, + void* end) { + if (idx < 0 || idx >= MEMREGION_MAX_BLOCKS) { + return; + } + + for (int i = MEMREGION_MAX_BLOCKS - 1; i > idx; i--) { + region->block[i] = region->block[i - 1]; + } + + region->block[idx].start = start; + region->block[idx].end = end; +} + +void memregion_add_range(memregion_t* region, void* start, void* end) { + int idx = 0; + + while ((start < end) && (idx < MEMREGION_MAX_BLOCKS)) { + memregion_block_t* b = ®ion->block[idx]; + if (b->start >= b->end) { + // The added range is completely after the last block + // in the region. Just add it as a block at the end. + b->start = start; + b->end = end; + break; + } else if (end < b->start) { + // The added range is completely before `b`. + // Shift all blocks after the inserted block + // Insert the new block + memregion_insert_block(region, idx, start, end); + break; + } else if (start < b->end) { + // The inserted range overlaps with `b`. + // Extend the block 'b'. + b->start = MIN(start, b->start); + // Shorten the added range + start = MAX(start, b->end); + } else { + // The added range is behind 'b' + // Move to the next block + idx += 1; + } + } +} + +void memregion_del_range(memregion_t* region, void* start, void* end) { + int idx = 0; + + while ((start < end) && (idx < MEMREGION_MAX_BLOCKS)) { + memregion_block_t* b = ®ion->block[idx]; + if (b->start >= b->end) { + // Deleted range is completely after the last block + break; + } else if (end < b->start) { + // Deleted range is completely before `b`. + break; + } else if (start < b->end) { + // Deleted range overlaps with `b`. + + if (start <= b->start) { + // Deleted range overlaps beginning of 'b'. + // Cut the beginning of the block 'b'. + b->start = MIN(end, b->end); + start = b->start; + + // If the block is empty, remove it + if (b->start >= b->end) { + memregion_remove_block(region, idx); + } + } else if (end >= b->end) { + // Deleted range overlaps end of 'b'. + // Cut the end of the block 'b' + b->end = start; + } else { + // Deleted range is inside 'b'. + // Split the block 'b' into two blocks. + void* new_start = end; + void* new_end = b->end; + + // Cut the end of the block 'b' + b->end = start; + + // Insert a new block, if there is a free space + memregion_insert_block(region, idx + 1, new_start, new_end); + break; + } + } else { + // The deleted range is behind 'b' + // Move to the next block + idx += 1; + } + } +} + +__attribute((no_stack_protector)) void memregion_fill(memregion_t* region, + uint32_t value) { + for (int i = 0; i < MEMREGION_MAX_BLOCKS; i++) { + memregion_block_t* block = ®ion->block[i]; + if (block->start < block->end) { + // Pointer is intentionally volatile to prevent optimization + // (otherwise the compiler may optimize loop to memset) + volatile uint32_t* ptr = block->start; + while ((void*)ptr < block->end) { + *ptr++ = value; + } + } + } +} diff --git a/core/embed/sys/linker/stm32f4/boardloader.ld b/core/embed/sys/linker/stm32f4/boardloader.ld index fbdaf5ed8c8..776a18fdd15 100644 --- a/core/embed/sys/linker/stm32f4/boardloader.ld +++ b/core/embed/sys/linker/stm32f4/boardloader.ld @@ -11,34 +11,27 @@ MEMORY { AUX1_RAM (wal) : ORIGIN = AUX1_RAM_START, LENGTH = AUX1_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_CCMRAM; -_startup_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_startup_clear_ram_1_start = MCU_SRAM; -_startup_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the startup/jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_CCMRAM; -_handoff_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM; -_handoff_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_CCMRAM; -_shutdown_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM; -_shutdown_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = 0; +_confidential_section_start = 0; +_confidential_section_end = 0; + +_accessible_ram_0_start = MCU_CCMRAM; +_accessible_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; +_accessible_ram_1_start = MCU_SRAM; +_accessible_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; SECTIONS { .vector_table : ALIGN(CODE_ALIGNMENT) { diff --git a/core/embed/sys/linker/stm32f4/bootloader.ld b/core/embed/sys/linker/stm32f4/bootloader.ld index 41b96dae5c6..a207b32d685 100644 --- a/core/embed/sys/linker/stm32f4/bootloader.ld +++ b/core/embed/sys/linker/stm32f4/bootloader.ld @@ -11,38 +11,27 @@ MEMORY { AUX1_RAM (wal) : ORIGIN = AUX1_RAM_START, LENGTH = AUX1_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_CCMRAM; -_startup_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE; -_startup_clear_ram_1_start = MCU_SRAM; -_startup_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_CCMRAM; -_handoff_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM; -_handoff_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_CCMRAM; -_shutdown_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM; -_shutdown_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = 0; +_confidential_section_start = 0; +_confidential_section_end = 0; + +_accessible_ram_0_start = MCU_CCMRAM; +_accessible_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; +_accessible_ram_1_start = MCU_SRAM; +_accessible_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.flash) + SIZEOF(.data); diff --git a/core/embed/sys/linker/stm32f4/firmware.ld b/core/embed/sys/linker/stm32f4/firmware.ld index d2c909ada70..46da6431e9c 100644 --- a/core/embed/sys/linker/stm32f4/firmware.ld +++ b/core/embed/sys/linker/stm32f4/firmware.ld @@ -9,18 +9,20 @@ MEMORY { AUX2_RAM (wal) : ORIGIN = K_AUX2_RAM_START, LENGTH = K_AUX2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; -_stack_size = SIZEOF(.stack); - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); - -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); +_stack_section_size = SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = 0; +_confidential_section_start = 0; +_confidential_section_end = 0; _codelen = LENGTH(FLASH) - SIZEOF(.vendorheader) - SIZEOF(.header) + SIZEOF(.flash2); _heap_start = ADDR(.heap); diff --git a/core/embed/sys/linker/stm32f4/kernel.ld b/core/embed/sys/linker/stm32f4/kernel.ld index dd87d0e1ea1..8ce21d3a7db 100644 --- a/core/embed/sys/linker/stm32f4/kernel.ld +++ b/core/embed/sys/linker/stm32f4/kernel.ld @@ -11,34 +11,27 @@ MEMORY { DMABUF (wal) : ORIGIN = DMABUF_RAM_START, LENGTH = DMABUF_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_CCMRAM; -_startup_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_startup_clear_ram_1_start = MCU_SRAM; -_startup_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_CCMRAM; -_handoff_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM; -_handoff_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_CCMRAM; -_shutdown_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM; -_shutdown_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = 0; +_confidential_section_start = 0; +_confidential_section_end = 0; + +_accessible_ram_0_start = MCU_CCMRAM; +_accessible_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; +_accessible_ram_1_start = MCU_SRAM; +_accessible_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.vendorheader) + SIZEOF(.header) + SIZEOF(.flash) + SIZEOF(.data) ; diff --git a/core/embed/sys/linker/stm32f4/prodtest.ld b/core/embed/sys/linker/stm32f4/prodtest.ld index 0a1d4598f7d..dd2e6b3b6bd 100644 --- a/core/embed/sys/linker/stm32f4/prodtest.ld +++ b/core/embed/sys/linker/stm32f4/prodtest.ld @@ -11,38 +11,27 @@ MEMORY { AUX1_RAM (wal) : ORIGIN = AUX1_RAM_START, LENGTH = AUX1_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_CCMRAM; -_startup_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_startup_clear_ram_1_start = MCU_SRAM; -_startup_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the startup/jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_CCMRAM; -_handoff_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM; -_handoff_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_CCMRAM; -_shutdown_clear_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM; -_shutdown_clear_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = 0; +_confidential_section_start = 0; +_confidential_section_end = 0; + +_accessible_ram_0_start = MCU_CCMRAM; +_accessible_ram_0_end = MCU_CCMRAM + MCU_CCMRAM_SIZE; +_accessible_ram_1_start = MCU_SRAM; +_accessible_ram_1_end = MCU_SRAM + MCU_SRAM_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.flash) + SIZEOF(.data); _flash_start = ORIGIN(FLASH); diff --git a/core/embed/sys/linker/stm32u58/boardloader.ld b/core/embed/sys/linker/stm32u58/boardloader.ld index e048d11bd04..d900b1399cc 100644 --- a/core/embed/sys/linker/stm32u58/boardloader.ld +++ b/core/embed/sys/linker/stm32u58/boardloader.ld @@ -14,48 +14,27 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE - BOOTARGS_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE - BOOTARGS_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM4; -_shutdown_clear_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; -_shutdown_clear_ram_2_start = 0; -_shutdown_clear_ram_2_end = 0; -_shutdown_clear_ram_3_start = 0; -_shutdown_clear_ram_3_end = 0; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; SECTIONS { .vector_table : ALIGN(CODE_ALIGNMENT) { diff --git a/core/embed/sys/linker/stm32u58/bootloader.ld b/core/embed/sys/linker/stm32u58/bootloader.ld index b2e4bb27a31..692c19a394f 100644 --- a/core/embed/sys/linker/stm32u58/bootloader.ld +++ b/core/embed/sys/linker/stm32u58/bootloader.ld @@ -13,47 +13,27 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE - BOOTARGS_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM4; -_shutdown_clear_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; -_shutdown_clear_ram_2_start = 0; -_shutdown_clear_ram_2_end = 0; -_shutdown_clear_ram_3_start = 0; -_shutdown_clear_ram_3_end = 0; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); diff --git a/core/embed/sys/linker/stm32u58/firmware.ld b/core/embed/sys/linker/stm32u58/firmware.ld index 6c09d9364b3..6f6223fc2be 100644 --- a/core/embed/sys/linker/stm32u58/firmware.ld +++ b/core/embed/sys/linker/stm32u58/firmware.ld @@ -8,22 +8,20 @@ MEMORY { AUX2_RAM (wal) : ORIGIN = AUX2_RAM_START, LENGTH = AUX2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; -_stack_size = SIZEOF(.stack); - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); +_stack_section_size = SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); diff --git a/core/embed/sys/linker/stm32u58/kernel.ld b/core/embed/sys/linker/stm32u58/kernel.ld index 88cc18beda2..21213c24080 100644 --- a/core/embed/sys/linker/stm32u58/kernel.ld +++ b/core/embed/sys/linker/stm32u58/kernel.ld @@ -12,51 +12,31 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); ustack_base = ADDR(.udata) + 512; _sustack = ADDR(.udata) + 256; _eustack = ustack_base; -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE - 512; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM4; -_shutdown_clear_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; -_shutdown_clear_ram_2_start = 0; -_shutdown_clear_ram_2_end = 0; -_shutdown_clear_ram_3_start = 0; -_shutdown_clear_ram_3_end = 0; +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.vendorheader) + SIZEOF(.header) + SIZEOF(.flash) + SIZEOF(.uflash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); diff --git a/core/embed/sys/linker/stm32u58/prodtest.ld b/core/embed/sys/linker/stm32u58/prodtest.ld index 33e1479da1b..5af5eaa071a 100644 --- a/core/embed/sys/linker/stm32u58/prodtest.ld +++ b/core/embed/sys/linker/stm32u58/prodtest.ld @@ -13,47 +13,27 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE - BOOTARGS_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; -_shutdown_clear_ram_1_start = MCU_SRAM4; -_shutdown_clear_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; -_shutdown_clear_ram_2_start = 0; -_shutdown_clear_ram_2_end = 0; -_shutdown_clear_ram_3_start = 0; -_shutdown_clear_ram_3_end = 0; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM3 + MCU_SRAM3_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); diff --git a/core/embed/sys/linker/stm32u5g/boardloader.ld b/core/embed/sys/linker/stm32u5g/boardloader.ld index f9ec3c16108..df63d1203b4 100644 --- a/core/embed/sys/linker/stm32u5g/boardloader.ld +++ b/core/embed/sys/linker/stm32u5g/boardloader.ld @@ -14,47 +14,28 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1 + BOOTARGS_SIZE; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1 + BOOTARGS_SIZE; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = ADDR(.fb1); -_shutdown_clear_ram_1_start = ADDR(.fb1) + SIZEOF(.fb1); -_shutdown_clear_ram_1_end = ADDR(.fb2); -_shutdown_clear_ram_2_start = ADDR(.fb2) + SIZEOF(.fb2); -_shutdown_clear_ram_2_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_shutdown_clear_ram_3_start = MCU_SRAM4; -_shutdown_clear_ram_3_end = MCU_SRAM4 + MCU_SRAM4_SIZE; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM6 + MCU_SRAM6_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; + SECTIONS { .vector_table : ALIGN(CODE_ALIGNMENT) { diff --git a/core/embed/sys/linker/stm32u5g/bootloader.ld b/core/embed/sys/linker/stm32u5g/bootloader.ld index 75bfeb458e1..ce1557ce7ee 100644 --- a/core/embed/sys/linker/stm32u5g/bootloader.ld +++ b/core/embed/sys/linker/stm32u5g/bootloader.ld @@ -13,47 +13,27 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1 + BOOTARGS_SIZE; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = ADDR(.fb1); -_shutdown_clear_ram_1_start = ADDR(.fb1) + SIZEOF(.fb1); -_shutdown_clear_ram_1_end = ADDR(.fb2); -_shutdown_clear_ram_2_start = ADDR(.fb2) + SIZEOF(.fb2); -_shutdown_clear_ram_2_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_shutdown_clear_ram_3_start = MCU_SRAM4; -_shutdown_clear_ram_3_end = MCU_SRAM4 + MCU_SRAM4_SIZE; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM6 + MCU_SRAM6_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.padding) + SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); diff --git a/core/embed/sys/linker/stm32u5g/firmware.ld b/core/embed/sys/linker/stm32u5g/firmware.ld index 499be37ac9b..de559d22e09 100644 --- a/core/embed/sys/linker/stm32u5g/firmware.ld +++ b/core/embed/sys/linker/stm32u5g/firmware.ld @@ -7,22 +7,20 @@ MEMORY { AUX1_RAM (wal) : ORIGIN = AUX1_RAM_START, LENGTH = AUX1_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; -_stack_size = SIZEOF(.stack); - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); +_stack_section_size = SIZEOF(.stack); + +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); _codelen = SIZEOF(.padding) + SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); diff --git a/core/embed/sys/linker/stm32u5g/kernel.ld b/core/embed/sys/linker/stm32u5g/kernel.ld index 6ed802c8747..9ae4b177dc9 100644 --- a/core/embed/sys/linker/stm32u5g/kernel.ld +++ b/core/embed/sys/linker/stm32u5g/kernel.ld @@ -12,51 +12,32 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); + ustack_base = ADDR(.udata) + 512; _sustack = ADDR(.udata) + 256; _eustack = ustack_base; -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1 + BOOTARGS_SIZE; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = ADDR(.fb1); -_shutdown_clear_ram_1_start = ADDR(.fb1) + SIZEOF(.fb1); -_shutdown_clear_ram_1_end = ADDR(.fb2); -_shutdown_clear_ram_2_start = ADDR(.fb2) + SIZEOF(.fb2); -_shutdown_clear_ram_2_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_shutdown_clear_ram_3_start = MCU_SRAM4; -_shutdown_clear_ram_3_end = MCU_SRAM4 + MCU_SRAM4_SIZE; +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM6 + MCU_SRAM6_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.vendorheader) + SIZEOF(.header) + SIZEOF(.flash) + SIZEOF(.uflash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); diff --git a/core/embed/sys/linker/stm32u5g/prodtest.ld b/core/embed/sys/linker/stm32u5g/prodtest.ld index eb721427ed1..141b11ee451 100644 --- a/core/embed/sys/linker/stm32u5g/prodtest.ld +++ b/core/embed/sys/linker/stm32u5g/prodtest.ld @@ -13,50 +13,30 @@ MEMORY { FB2_RAM (wal) : ORIGIN = FB2_RAM_START, LENGTH = FB2_RAM_SIZE } -main_stack_base = ADDR(.stack) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ADDR(.stack); -_estack = main_stack_base; - -/* used by the startup code to populate variables used by the C code */ -data_lma = LOADADDR(.data); -data_vma = ADDR(.data); -data_size = SIZEOF(.data); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* used by the startup code to populate variables used by the C code */ -confidential_lma = LOADADDR(.confidential); -confidential_vma = ADDR(.confidential); -confidential_size = SIZEOF(.confidential); - -/* used by the startup code to wipe memory */ -_startup_clear_ram_0_start = MCU_SRAM1; -_startup_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_startup_clear_ram_1_start = MCU_SRAM2; -_startup_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_startup_clear_ram_2_start = MCU_SRAM4; -_startup_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the jump code to wipe memory */ -_handoff_clear_ram_0_start = MCU_SRAM1 + BOOTARGS_SIZE; -_handoff_clear_ram_0_end = MCU_SRAM1 + MCU_SRAM1_SIZE; -_handoff_clear_ram_1_start = MCU_SRAM2; -_handoff_clear_ram_1_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_handoff_clear_ram_2_start = MCU_SRAM4; -_handoff_clear_ram_2_end = MCU_SRAM4 + MCU_SRAM4_SIZE; - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = MCU_SRAM1; -_shutdown_clear_ram_0_end = ADDR(.fb1); -_shutdown_clear_ram_1_start = ADDR(.fb1) + SIZEOF(.fb1); -_shutdown_clear_ram_1_end = ADDR(.fb2); -_shutdown_clear_ram_2_start = ADDR(.fb2) + SIZEOF(.fb2); -_shutdown_clear_ram_2_end = MCU_SRAM6 + MCU_SRAM6_SIZE; -_shutdown_clear_ram_3_start = MCU_SRAM4; -_shutdown_clear_ram_3_end = MCU_SRAM4 + MCU_SRAM4_SIZE; +_stack_section_start = ADDR(.stack); +_stack_section_end = ADDR(.stack) + SIZEOF(.stack); +_data_section_loadaddr = LOADADDR(.data); +_data_section_start = ADDR(.data); +_data_section_end = ADDR(.data) + SIZEOF(.data); + +_bss_section_start = ADDR(.bss); +_bss_section_end = ADDR(.bss) + SIZEOF(.bss); + +_confidential_section_loadaddr = LOADADDR(.confidential); +_confidential_section_start = ADDR(.confidential); +_confidential_section_end = ADDR(.confidential) + SIZEOF(.confidential); + +_accessible_ram_0_start = MCU_SRAM1; +_accessible_ram_0_end = MCU_SRAM6 + MCU_SRAM6_SIZE; +_accessible_ram_1_start = MCU_SRAM4; +_accessible_ram_1_end = MCU_SRAM4 + MCU_SRAM4_SIZE; + +_bootargs_ram_start = BOOTARGS_START; +_bootargs_ram_end = BOOTARGS_START + BOOTARGS_SIZE; _codelen = SIZEOF(.padding) + SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); + _flash_start = ORIGIN(FLASH); _flash_end = ORIGIN(FLASH) + LENGTH(FLASH); diff --git a/core/embed/sys/pvd/stm32/pvd.c b/core/embed/sys/pvd/stm32/pvd.c index cd94df5321d..bc6581a88e6 100644 --- a/core/embed/sys/pvd/stm32/pvd.c +++ b/core/embed/sys/pvd/stm32/pvd.c @@ -56,9 +56,7 @@ void PVD_IRQHandler(void) { // Turn off display backlight BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; #endif - // from util.s - extern void shutdown_privileged(void); - shutdown_privileged(); + error_shutdown("PVD IRQ"); } #endif // defined(KERNEL_MODE) && defined(USE_PVD) diff --git a/core/embed/sys/startup/inc/sys/bootargs.h b/core/embed/sys/startup/inc/sys/bootargs.h index 92fc79d2bc8..051040404c5 100644 --- a/core/embed/sys/startup/inc/sys/bootargs.h +++ b/core/embed/sys/startup/inc/sys/bootargs.h @@ -20,6 +20,7 @@ #ifndef TREZORHAL_BOOTARGS_H #define TREZORHAL_BOOTARGS_H +#include #include // Defines boot command processed in bootloader on next reboot @@ -30,6 +31,8 @@ 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 @@ -37,12 +40,21 @@ typedef enum { 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. +// This value is used only on STM32F4 platform. On STM32U5, it is ignored. +void bootargs_init(uint32_t r11_register); + // Configures the boot command and associated arguments for the next reboot. // The arguments must adhere to the boot_args_t structure layout. void bootargs_set(boot_command_t command, const void* args, size_t args_size); @@ -53,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 diff --git a/core/embed/sys/startup/inc/sys/bootutils.h b/core/embed/sys/startup/inc/sys/bootutils.h index 10b069e9137..a32abe1ad43 100644 --- a/core/embed/sys/startup/inc/sys/bootutils.h +++ b/core/embed/sys/startup/inc/sys/bootutils.h @@ -38,33 +38,20 @@ void __attribute__((noreturn)) reboot_to_bootloader(void); // with the firmware installation. void __attribute__((noreturn)) reboot_and_upgrade(const uint8_t hash[32]); -// Allows the user to see the displayed error message and then -// safely shuts down the device (clears secrets, memory, etc.). +// Allows the user to read the displayed error message and then +// reboots the device or waits for power-off. // -// This function is called when the device enters an -// unrecoverable error state. -void __attribute__((noreturn)) secure_shutdown(void); - -// Alternative memset with slightly different arguments -// -// This function writes a 32-bit value to a range of memory addresses. -// The range is defined by the start and stop pointers and must -// be aligned to 4 bytes. -void memset_reg(volatile void *start, volatile void *stop, uint32_t val); +// The function's behavior depends on the `RSOD_INFINITE_LOOP` macro: +// 1) If `RSOD_INFINITE_LOOP` is defined, the function enters an infinite loop. +// 2) If `RSOD_INFINITE_LOOP` is not defined, the function waits for a +// specified duration and then resets the device. +void __attribute__((noreturn)) reboot_or_halt_after_rsod(void); // Jumps to the next booting stage (e.g. bootloader to firmware). -// `address` points to the flash at the vector table of the next stage. +// `vectbl_address` points to the flash at the vector table of the next stage. // // Before jumping, the function disables all interrupts and clears the // memory and registers that could contain sensitive information. -void jump_to(uint32_t address); - -// Ensure compatible hardware settings before jumping to -// the different booting stage. This function is used to -// ensure backward compatibility with older versions of -// released bootloaders and firmware. -// -// Does nothing on almost all platforms. -void ensure_compatible_settings(void); +void __attribute__((noreturn)) jump_to_next_stage(uint32_t vectbl_address); #endif // TREZORHAL_BOOTUTILS_H diff --git a/core/embed/sys/startup/inc/sys/sysutils.h b/core/embed/sys/startup/inc/sys/sysutils.h new file mode 100644 index 00000000000..7508610226c --- /dev/null +++ b/core/embed/sys/startup/inc/sys/sysutils.h @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +#pragma once + +#ifdef KERNEL_MODE + +#include + +typedef void (*new_stack_callback_t)(uint32_t arg1, uint32_t arg2); + +// Disables interrupts, disables the MPU, clears +// all registers, sets up a new stack and calls the given callback. +// +// The function is intended to be used in special cases, like +// emergency situations, where the current stack may be corrupted. +__attribute((noreturn)) void call_with_new_stack(uint32_t arg1, uint32_t arg2, + new_stack_callback_t callback); + +// Ensure that we are running in privileged thread mode. +// +// This function is used only on STM32F4, where a direct jump to the +// bootloader is performed. It checks if we are in handler mode, and +// if so, it switches to privileged thread mode. +void ensure_thread_mode(void); + +// Ensure compatible hardware settings before jumping to +// the different booting stage. This function is used to +// ensure backward compatibility with older versions of +// released bootloaders and firmware. +// +// Does nothing on almost all platforms. +void ensure_compatible_settings(void); + +// Clears USB peripheral fifo memory +// +// Used to wipe sensitive data from USB peripheral memory. +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. +// +// The target binary is called with interrupts disabled, and all registers +// are cleared except R11, which is set to the specified value. +__attribute((noreturn)) void jump_to_vectbl(uint32_t vectbl_addr, uint32_t r11); + +#endif // KERNEL_MODE diff --git a/core/embed/sys/startup/stm32/bootutils.c b/core/embed/sys/startup/stm32/bootutils.c index 1b69858749c..1522ac658a3 100644 --- a/core/embed/sys/startup/stm32/bootutils.c +++ b/core/embed/sys/startup/stm32/bootutils.c @@ -25,15 +25,20 @@ #include #include #include +#include #include +#include +#include #include -#ifdef TREZOR_MODEL_T2T1 -#include "../stm32f4/startup_init.h" -#endif - #ifdef KERNEL_MODE +// Battery powered devices (USE_POWERCTL) should not stall +// after showing RSOD, as it would drain the battery. +#ifndef USE_POWERCTL +#define RSOD_INFINITE_LOOP +#endif + #ifdef STM32U5 // Persistent variable that holds the 'command' for the next reboot. boot_command_t __attribute__((section(".boot_command"))) g_boot_command; @@ -68,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; @@ -81,142 +88,125 @@ void bootargs_get_args(boot_args_t* dest) { mpu_restore(mode); } -#endif -// Deletes all secrets and SRAM2 where stack is located -// to prevent stack smashing error, do not return from function calling this +void bootargs_init(uint32_t r11_register) { #ifdef STM32U5 -static inline void __attribute__((always_inline)) delete_secrets(void) { - __disable_irq(); + g_boot_command_saved = g_boot_command; + g_boot_command = BOOT_COMMAND_NONE; +#else + g_boot_command_saved = r11_register; +#endif +} +#endif - // Disable SAES peripheral clock, so that we don't get tamper events - __HAL_RCC_SAES_CLK_DISABLE(); +static void reboot_with_args_phase_2(uint32_t arg1, uint32_t arg2) { + // We are now running on a new stack. We cannot be sure about + // any variables in the .bss and .data sections, so we must + // be careful and avoid using them altogether. - TAMP->CR2 |= TAMP_CR2_BKERASE; -} -#endif // STM32U5 + // Reset peripherals (so we are sure that no DMA is pending) + // and disable all interrupts and clear all pending ones + reset_peripherals_and_interrupts(); -#ifdef STM32F4 -// Ensure that we are running in privileged thread mode. -// -// This function is used only on STM32F4, where a direct jump to the -// bootloader is performed. It checks if we are in handler mode, and -// if so, it switches to privileged thread mode. -__attribute((naked, no_stack_protector)) static void ensure_thread_mode(void) { - __asm__ volatile( - // -------------------------------------------------------------- - // Check if we are in handler mode - // -------------------------------------------------------------- - - "LDR R1, =0x1FF \n" // Get lower 9 bits of IPSR - "MRS R0, IPSR \n" - "ANDS R0, R0, R1 \n" - "CMP R0, #0 \n" // == 0 if in thread mode - "IT EQ \n" - "BXEQ LR \n" // return if in thread mode - - // -------------------------------------------------------------- - // Disable FP registers lazy stacking - // -------------------------------------------------------------- - - "LDR R1, = 0xE000EF34 \n" // FPU->FPCCR - "LDR R0, [R1] \n" - "BIC R0, R0, #1 \n" // Clear LSPACT to suppress lazy - // stacking - "STR R0, [R1] \n" - - // -------------------------------------------------------------- - // Exit handler mode, enter thread mode - // -------------------------------------------------------------- - - "MOV R0, SP \n" // Align stack pointer to 8 bytes - "AND R0, R0, #~7 \n" - "MOV SP, R0 \n" - "SUB SP, SP, #32 \n" // Allocate space for the stack frame - - "MOV R0, #0 \n" - "STR R0, [SP, #0] \n" // future R0 = 0 - "STR R0, [SP, #4] \n" // future R1 = 0 - "STR R0, [SP, #8] \n" // future R2 = 0 - "STR R0, [SP, #12] \n" // future R3 = 0 - "STR R12, [SP, #16] \n" // future R12 = R12 - "STR LR, [SP, #20] \n" // future LR = LR - "BIC LR, LR, #1 \n" - "STR LR, [SP, #24] \n" // return address = LR - "LDR R0, = 0x01000000 \n" // THUMB bit set - "STR R0, [SP, #28] \n" // future xPSR - - "MRS R0, CONTROL \n" // Clear SPSEL to use MSP for thread - "BIC R0, R0, #3 \n" // Clear nPRIV to run in privileged mode - "MSR CONTROL, R0 \n" - - "LDR LR, = 0xFFFFFFF9 \n" // Return to Secure Thread mode, use MSP - "BX LR \n"); + // Clear unused part of stack + clear_unused_stack(); + + // Clear all memory except stack and bootargs + memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM; + MEMREGION_DEL_SECTION(®ion, _stack_section); + MEMREGION_DEL_SECTION(®ion, _bootargs_ram); + memregion_fill(®ion, 0); + +#if defined STM32U5 + NVIC_SystemReset(); +#elif defined STM32F4 + clear_otg_hs_memory(); + jump_to_vectbl(BOOTLOADER_START + IMAGE_HEADER_SIZE, arg1); +#else +#error Unsupported platform +#endif } -#endif // STM32F4 // Reboots the device with the given boot command and arguments -static void __attribute__((noreturn)) -reboot_with_args(boot_command_t command, const void* args, size_t args_size) { +__attribute__((noreturn)) static void reboot_with_args(boot_command_t command, + const void* args, + size_t args_size) { + // Set bootargs area to the new command and arguments bootargs_set(command, args, args_size); -#ifdef STM32U5 - delete_secrets(); - NVIC_SystemReset(); -#else +#ifdef STM32F4 + // We are going to jump directly to the bootloader, so we need to + // ensure that the device is in a compatible state. Following lines + // ensure the display is properly deinitialized, CPU frequency is + // properly set and we are running in privileged thread mode. display_deinit(DISPLAY_RESET_CONTENT); ensure_compatible_settings(); - - mpu_reconfig(MPU_MODE_DISABLED); - ensure_thread_mode(); - - // from util.s - extern void jump_to_with_flag(uint32_t address, uint32_t reset_flag); - jump_to_with_flag(BOOTLOADER_START + IMAGE_HEADER_SIZE, g_boot_command); - for (;;) - ; #endif + + // Disable interrupts, MPU, clear all registers and set up a new stack + // (on STM32U5 it also clear all CPU secrets and SRAM2). + call_with_new_stack(command, 0, reboot_with_args_phase_2); } -void reboot_to_bootloader(void) { +__attribute__((noreturn)) void reboot_to_bootloader(void) { reboot_with_args(BOOT_COMMAND_STOP_AND_WAIT, NULL, 0); } -void reboot_and_upgrade(const uint8_t hash[32]) { +__attribute__((noreturn)) void reboot_and_upgrade(const uint8_t hash[32]) { reboot_with_args(BOOT_COMMAND_INSTALL_UPGRADE, hash, 32); } -void reboot_device(void) { - bootargs_set(BOOT_COMMAND_NONE, NULL, 0); +__attribute__((noreturn)) void reboot_device(void) { + reboot_with_args(BOOT_COMMAND_NONE, NULL, 0); +} -#ifdef STM32U5 - delete_secrets(); +__attribute__((noreturn)) void reboot_or_halt_after_rsod(void) { +#ifndef RSOD_INFINITE_LOOP + systick_delay_ms(10 * 1000); +#endif +#ifdef RSOD_INFINITE_LOOP + while (true) + ; +#else + reboot_device(); #endif - - NVIC_SystemReset(); } -void __attribute__((noreturn)) secure_shutdown(void) { - display_deinit(DISPLAY_RETAIN_CONTENT); +static void jump_to_next_stage_phase_2(uint32_t arg1, uint32_t arg2) { + // We are now running on a new stack. We cannot be sure about + // any variables in the .bss and .data sections, so we must + // be careful and avoid using them altogether. -#ifdef STM32U5 - delete_secrets(); -#endif - // from util.s - extern void shutdown_privileged(void); - shutdown_privileged(); + // Reset peripherals (so we are sure that no DMA is pending) + // and disable all interrupts and clear all pending ones + reset_peripherals_and_interrupts(); - for (;;) - ; + // Clear unused part of stack + clear_unused_stack(); + + // Clear all memory except stack and bootargs + memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM; + MEMREGION_DEL_SECTION(®ion, _stack_section); + MEMREGION_DEL_SECTION(®ion, _bootargs_ram); + memregion_fill(®ion, 0); + + // Jump to reset vector of the next stage + jump_to_vectbl(arg1, 0); } -void ensure_compatible_settings(void) { -#ifdef TREZOR_MODEL_T2T1 - // Early version of bootloader on T2T1 expects 168 MHz core clock. - // So we need to set it here before handover to the bootloader. - set_core_clock(CLOCK_168_MHZ); +void __attribute__((noreturn)) jump_to_next_stage(uint32_t vectbl_address) { +#ifdef STM32F4 + // Ensure the display is properly deinitialized, CPU frequency is + // properly set. It's needed for backward compatibility with the older + // firmware. + display_deinit(DISPLAY_JUMP_BEHAVIOR); + ensure_compatible_settings(); #endif + + // Disable interrupts, MPU, clear all registers and set up a new stack + // (on STM32U5 it also clear all CPU secrets and SRAM2). + call_with_new_stack(vectbl_address, 0, jump_to_next_stage_phase_2); } #endif // KERNEL_MODE diff --git a/core/embed/sys/startup/stm32/sysutils.c b/core/embed/sys/startup/stm32/sysutils.c new file mode 100644 index 00000000000..8ef51dbc954 --- /dev/null +++ b/core/embed/sys/startup/stm32/sysutils.c @@ -0,0 +1,358 @@ +/* + * 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 + +#include +#include + +#ifdef KERNEL_MODE + +#ifdef TREZOR_MODEL_T2T1 +#include "../stm32f4/startup_init.h" +#endif + +__attribute((naked, noreturn, no_stack_protector)) void call_with_new_stack( + uint32_t arg1, uint32_t arg2, new_stack_callback_t callback) { + __asm__ volatile( + + // R0, R1, R2 are used for arguments + + "CPSID F \n" // Disable interrupts/faults + + // -------------------------------------------------------------- + // Disable MPU + // -------------------------------------------------------------- + + "DMB 0xF \n" // Data memory barrier + "LDR R4, =0xE000ED94 \n" // MPU->CTRL + "MOV R5, #0 \n" + "STR R5, [R4] \n" // Disable MPU + ); + +#ifdef STM32U5 + __asm__ volatile( + // -------------------------------------------------------------- + // Delete all secrets and SRAM2 where stack is located. + // SAES peripheral need to be disabled, so that we don't get + // tamper events. + // -------------------------------------------------------------- + + // RCC->AHBENR1 &= ~RCC_AHBENR1_SAESEN; + "LDR R4, =%[_RCC_AHB2ENR1] \n" + "LDR R5, =%[_RCC_AHB2ENR1_SAESEN] \n" + "LDR R6, [R4] \n" + "BIC R6, R6, R5 \n" + "STR R6, [R4] \n" + + // TAMP->CR2 |= TAMP_CR2_BKERASE; + "LDR R4, =%[_TAMP_CR2] \n" + "LDR R5, =%[_TAMP_CR2_BKERASE] \n" + "LDR R6, [R4] \n" + "ORR R6, R6, R5 \n" + "STR R6, [R4] \n" + + : // no output + : [_RCC_AHB2ENR1] "i"(&RCC->AHB2ENR1), + [_RCC_AHB2ENR1_SAESEN] "i"(RCC_AHB2ENR1_SAESEN), + [_TAMP_CR2] "i"(&TAMP->CR2), + [_TAMP_CR2_BKERASE] "i"(TAMP_CR2_BKERASE) + + : // no clobber + ); +#endif // STM32U5 + + __asm__ volatile( + // -------------------------------------------------------------- + // Setup new stack + // -------------------------------------------------------------- + + "LDR R4, =%[estack] \n" // Setup new stack + "MSR MSP, R4 \n" // Set MSP +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + "LDR R4, =%[sstack] \n" + "ADD R4, R4, #256 \n" // Add safety margin + "MSR MSPLIM, R4 \n" // Set MSPLIM +#endif + + // -------------------------------------------------------------- + // Clear all VFP registers + // -------------------------------------------------------------- + + "LDR R4, = 0xE000EF34 \n" // FPU->FPCCR + "LDR R5, [R4] \n" + "BIC R5, R5, #1 \n" // Clear LSPACT to suppress lazy + // stacking + "STR R5, [R4] \n" + + // TODO: clear VFP registers (maybe for ARMV7-M only) + + // -------------------------------------------------------------- + // Clear all unused registers + // -------------------------------------------------------------- + + "MOV R3, #0 \n" + "MOV R4, R3 \n" + "MOV R5, R3 \n" + "MOV R6, R3 \n" + "MOV R7, R3 \n" + "MOV R8, R3 \n" + "MOV R9, R3 \n" + "MOV R10, R3 \n" + "MOV R11, R3 \n" + "MOV R12, R3 \n" + + // -------------------------------------------------------------- + // Invoke phase 2 function + // -------------------------------------------------------------- + + // R0 = arg1 + // R1 = arg2 + + "BX R2 \n" + + : // no output + : [estack] "i"(&_stack_section_end), + [sstack] "i"(&_stack_section_start) + : // no clobber + ); +} + +// Ensure that we are running in privileged thread mode. +// +// This function is used only on STM32F4, where a direct jump to the +// bootloader is performed. It checks if we are in handler mode, and +// if so, it switches to privileged thread mode. +__attribute((naked, no_stack_protector)) void ensure_thread_mode(void) { + __asm__ volatile( + // -------------------------------------------------------------- + // Check if we are in handler mode + // -------------------------------------------------------------- + + "LDR R1, =0x1FF \n" // Get lower 9 bits of IPSR + "MRS R0, IPSR \n" + "ANDS R0, R0, R1 \n" + "CMP R0, #0 \n" // == 0 if in thread mode + "IT EQ \n" + "BXEQ LR \n" // return if in thread mode + + // -------------------------------------------------------------- + // Disable FP registers lazy stacking + // -------------------------------------------------------------- + + "LDR R1, = 0xE000EF34 \n" // FPU->FPCCR + "LDR R0, [R1] \n" + "BIC R0, R0, #1 \n" // Clear LSPACT to suppress lazy + // stacking + "STR R0, [R1] \n" + + // -------------------------------------------------------------- + // Exit handler mode, enter thread mode + // -------------------------------------------------------------- + + "MOV R0, SP \n" // Align stack pointer to 8 bytes + "AND R0, R0, #~7 \n" + "MOV SP, R0 \n" + "SUB SP, SP, #32 \n" // Allocate space for the stack frame + + "MOV R0, #0 \n" + "STR R0, [SP, #0] \n" // future R0 = 0 + "STR R0, [SP, #4] \n" // future R1 = 0 + "STR R0, [SP, #8] \n" // future R2 = 0 + "STR R0, [SP, #12] \n" // future R3 = 0 + "STR R12, [SP, #16] \n" // future R12 = R12 + "STR LR, [SP, #20] \n" // future LR = LR + "BIC LR, LR, #1 \n" + "STR LR, [SP, #24] \n" // return address = LR + "LDR R0, = 0x01000000 \n" // THUMB bit set + "STR R0, [SP, #28] \n" // future xPSR + + "MRS R0, CONTROL \n" // Clear SPSEL to use MSP for thread + "BIC R0, R0, #3 \n" // Clear nPRIV to run in privileged mode + "MSR CONTROL, R0 \n" + + "LDR LR, = 0xFFFFFFF9 \n" // Return to Secure Thread mode, use MSP + "BX LR \n"); +} + +// Clears USB FIFO memory to prevent data leakage of sensitive information +__attribute((used)) void clear_otg_hs_memory(void) { +#ifdef STM32F4 + +// reference RM0090 section 35.12.1 Figure 413 +#define USB_OTG_HS_DATA_FIFO_RAM (USB_OTG_HS_PERIPH_BASE + 0x20000U) +#define USB_OTG_HS_DATA_FIFO_SIZE (4096U) + + // use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); // enable USB_OTG_HS peripheral clock so + // that the peripheral memory is + // accessible + __IO uint32_t* usb_fifo_ram = (__IO uint32_t*)USB_OTG_HS_DATA_FIFO_RAM; + + for (uint32_t i = 0; i < USB_OTG_HS_DATA_FIFO_SIZE / 4; i++) { + usb_fifo_ram[i] = 0; + } + + __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as + // the peripheral is not needed right now +#endif +} + +void ensure_compatible_settings(void) { +#ifdef TREZOR_MODEL_T2T1 + // Early version of bootloader on T2T1 expects 168 MHz core clock. + // So we need to set it here before handover to the bootloader. + set_core_clock(CLOCK_168_MHZ); +#endif +} + +__attribute((naked, noreturn, no_stack_protector)) void jump_to_vectbl( + uint32_t vectbl_addr, uint32_t r11) { + __asm__ volatile( + "CPSID F \n" + + "MOV R11, R1 \n" + "MOV LR, R0 \n" + + "LDR R0, =0 \n" + "MOV R1, R0 \n" + "MOV R2, R0 \n" + "MOV R3, R0 \n" + "MOV R4, R0 \n" + "MOV R5, R0 \n" + "MOV R6, R0 \n" + "MOV R7, R0 \n" + "MOV R8, R0 \n" + "MOV R9, R0 \n" + "MOV R10, R0 \n" // R11 is set to r11 argument + "MOV R12, R0 \n" + + "LDR R0, [LR] \n" // Initial MSP value + "MSR MSP, R0 \n" // Set MSP + + "LDR R0, =%[_SCB_VTOR] \n" // Reset handler + "STR LR, [R0] \n" // Set SCB->VTOR = vectb_addr + + "MOV R0, R1 \n" // Zero out R0 + + "LDR LR, [LR, #4] \n" // Reset handler + "BX LR \n" // Go to reset handler + + : // no output + : [_SCB_VTOR] "i"(&SCB->VTOR) + : // no clobber + ); +} + +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 diff --git a/core/embed/sys/startup/stm32f4/limited_util.S b/core/embed/sys/startup/stm32f4/limited_util.S deleted file mode 100644 index ba510710b0d..00000000000 --- a/core/embed/sys/startup/stm32f4/limited_util.S +++ /dev/null @@ -1,105 +0,0 @@ - .syntax unified - - .text - - .global memset_reg - .type memset_reg, STT_FUNC -memset_reg: - // call with the following (note that the arguments are not validated prior to use): - // r0 - address of first word to write (inclusive) - // r1 - address of first word following the address in r0 to NOT write (exclusive) - // r2 - word value to be written - // both addresses in r0 and r1 needs to be divisible by 4! - cmp r0, r1 - beq .L_loop_end - .L_loop_begin: - str r2, [r0], 4 // store the word in r2 to the address in r0, post-indexed - cmp r0, r1 - bne .L_loop_begin - .L_loop_end: - bx lr - - .global jump_to - .type jump_to, STT_FUNC -jump_to: - mov r4, r0 // save input argument r0 (the address of the next stage's vector table) (r4 is callee save) - // this subroutine re-points the exception handlers before the C code - // that comprises them has been given a good environment to run. - // therefore, this code needs to disable interrupts before the VTOR - // update. then, the reset_handler of the next stage needs to re-enable interrupts. - // the following prevents activation of all exceptions except Non-Maskable Interrupt (NMI). - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.8: - // "there is no requirement to insert memory barrier instructions after CPSID". - cpsid f - // wipe memory at the end of the current stage of code - bl clear_otg_hs_memory - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_handoff_clear_ram_0_start - ldr r1, =_handoff_clear_ram_0_end - bl memset_reg - ldr r0, =_handoff_clear_ram_1_start - ldr r1, =_handoff_clear_ram_1_end - bl memset_reg - mov lr, r4 - // clear out the general purpose registers before the next stage's code can run (even the NMI exception handler) - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r11, r0 - mov r12, r0 - // give the next stage a fresh main stack pointer - ldr r0, [lr] // set r0 to the main stack pointer in the next stage's vector table - msr msp, r0 // give the next stage its main stack pointer - // point to the next stage's exception handlers - // AN321, section 4.11: "a memory barrier is not required after a VTOR update" - .set SCB_VTOR, 0xE000ED08 // reference "Cortex-M4 Devices Generic User Guide" section 4.3 - ldr r0, =SCB_VTOR - str lr, [r0] - mov r0, r1 // zero out r0 - // go on to the next stage - ldr lr, [lr, 4] // set lr to the next stage's reset_handler - bx lr - - .global shutdown_privileged - .type shutdown_privileged, STT_FUNC - // The function must be called from the privileged mode -shutdown_privileged: - cpsid f // disable all exceptions (except for NMI), the instruction is ignored in unprivileged mode - // if the exceptions weren't disabled, an exception handler (for example systick handler) - // could be called after the memory is erased, which would lead to another exception - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r11, r0 - mov r12, r0 - ldr lr, =0xffffffff - - ldr r0, =_shutdown_clear_ram_0_start - ldr r1, =_shutdown_clear_ram_0_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_1_start - ldr r1, =_shutdown_clear_ram_1_end - bl memset_reg - bl clear_otg_hs_memory - ldr r0, =1 - msr control, r0 // jump to unprivileged mode - ldr r0, =0 - b . // loop forever - - .end diff --git a/core/embed/sys/startup/stm32f4/startup_init.c b/core/embed/sys/startup/stm32f4/startup_init.c index 52634a030f0..b6429a76c0f 100644 --- a/core/embed/sys/startup/stm32f4/startup_init.c +++ b/core/embed/sys/startup/stm32f4/startup_init.c @@ -21,8 +21,13 @@ #include #include +#include #include +#include +#include #include +#include + #include "startup_init.h" #ifdef KERNEL_MODE @@ -230,23 +235,65 @@ void set_core_clock(clock_settings_t settings) { } #endif -// reference RM0090 section 35.12.1 Figure 413 -#define USB_OTG_HS_DATA_FIFO_RAM (USB_OTG_HS_PERIPH_BASE + 0x20000U) -#define USB_OTG_HS_DATA_FIFO_SIZE (4096U) - -// Clears USB FIFO memory to prevent data leakage of sensitive information -__attribute((used)) void clear_otg_hs_memory(void) { - // use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet - __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); // enable USB_OTG_HS peripheral clock so - // that the peripheral memory is - // accessible - memset_reg( - (volatile void *)USB_OTG_HS_DATA_FIFO_RAM, - (volatile void *)(USB_OTG_HS_DATA_FIFO_RAM + USB_OTG_HS_DATA_FIFO_SIZE), - 0); - - __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as - // the peripheral is not needed right now +__attribute((no_stack_protector)) void reset_handler(void) { +#ifdef BOOTLOADER + uint32_t r11_value; + // Copy the value of R11 to the local variable r11_value + __asm__ volatile("MOV %0, R11" : "=r"(r11_value)); +#endif + + // Now .bss, .data are not initialized yet - we need to be + // careful with global variables. They are not initialized, + // contain random values and will be rewritten in the succesive + // code + + // Initialize system clocks + SystemInit(); + + // Clear unused part of stack + clear_unused_stack(); + + // Initialize random number generator + rng_init(); + + // Clear all memory except stack. + // Keep also bootargs in bootloader and boardloader. + memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM; + + MEMREGION_DEL_SECTION(®ion, _stack_section); +#ifdef BOOTLOADER + MEMREGION_DEL_SECTION(®ion, _bootargs_ram); +#endif + +#ifdef BOARDLOADER + memregion_fill(®ion, rng_get()); +#endif + memregion_fill(®ion, 0); + + // Initialize .bss, .data, ... + init_linker_sections(); + + // Initialize stack protector guard value + extern uint32_t __stack_chk_guard; + __stack_chk_guard = rng_get(); + + // Now everything is perfectly initialized and we can do anything + // in C code + + clear_otg_hs_memory(); + +#ifdef BOOTLOADER + bootargs_init(r11_value); +#endif + + // Enable interrupts and fault handlers + __enable_fault_irq(); + + // Run application + extern int main(void); + int main_result = main(); + + system_exit(main_result); } #endif // KERNEL_MODE diff --git a/core/embed/sys/startup/stm32f4/startup_stage_0.s b/core/embed/sys/startup/stm32f4/startup_stage_0.s deleted file mode 100644 index cbb9e921d4e..00000000000 --- a/core/embed/sys/startup/stm32f4/startup_stage_0.s +++ /dev/null @@ -1,61 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - bl SystemInit - - // read the first rng data and save it - ldr r0, =0 // r0 - previous value - ldr r1, =0 // r1 - whether to compare the previous value - bl rng_read - - // read the next rng data and make sure it is different than previous - // r0 - value returned from previous call - ldr r1, =1 // r1 - whether to compare the previous value - bl rng_read - mov r4, r0 // save TRNG output in r4 - - // wipe memory to remove any possible vestiges of sensitive data - // use unpredictable value as a defense against side-channels - mov r2, r4 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - - // setup environment for subsequent stage of code - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - - // copy data in from flash - ldr r0, =data_vma // dst addr - ldr r1, =data_lma // src addr - ldr r2, =data_size // size in bytes - bl memcpy - - // setup the stack protector (see build script "-fstack-protector-all") - // with an unpredictable value - bl rng_get - ldr r1, = __stack_chk_guard - str r0, [r1] - - // Clear the USB FIFO memory to prevent data leakage of sensitive information. - // This peripheral memory is not cleared by a device reset. - bl clear_otg_hs_memory - - // enter the application code - bl main - - b shutdown_privileged - - .end diff --git a/core/embed/sys/startup/stm32f4/startup_stage_1.s b/core/embed/sys/startup/stm32f4/startup_stage_1.s deleted file mode 100644 index 72a4cc8fab0..00000000000 --- a/core/embed/sys/startup/stm32f4/startup_stage_1.s +++ /dev/null @@ -1,45 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - // setup environment for subsequent stage of code - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - - // copy data in from flash - ldr r0, =data_vma // dst addr - ldr r1, =data_lma // src addr - ldr r2, =data_size // size in bytes - bl memcpy - - // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value - bl rng_get - ldr r1, = __stack_chk_guard - str r0, [r1] - - // re-enable exceptions - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.7: - // "If it is not necessary to ensure that a pended interrupt is recognized immediately before - // subsequent operations, it is not necessary to insert a memory barrier instruction." - cpsie f - - // r11 contains the command passed to bootargs_set() - // function called when the firmware rebooted to the bootloader - ldr r0, =g_boot_command_saved - str r11, [r0] - - // enter the application code - bl main - - b shutdown_privileged - - .end - diff --git a/core/embed/sys/startup/stm32f4/startup_stage_2.s b/core/embed/sys/startup/stm32f4/startup_stage_2.s deleted file mode 100644 index e08f0de48c3..00000000000 --- a/core/embed/sys/startup/stm32f4/startup_stage_2.s +++ /dev/null @@ -1,39 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - // setup environment for subsequent stage of code - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - - // copy data in from flash - ldr r0, =data_vma // dst addr - ldr r1, =data_lma // src addr - ldr r2, =data_size // size in bytes - bl memcpy - - // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value - bl rng_get - ldr r1, = __stack_chk_guard - str r0, [r1] - - // re-enable exceptions - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.7: - // "If it is not necessary to ensure that a pended interrupt is recognized immediately before - // subsequent operations, it is not necessary to insert a memory barrier instruction." - cpsie f - - // enter the application code - bl main - - b shutdown_privileged - - .end diff --git a/core/embed/sys/startup/stm32f4/startup_stage_4.s b/core/embed/sys/startup/stm32f4/startup_stage_4.s deleted file mode 100644 index d1a921abb34..00000000000 --- a/core/embed/sys/startup/stm32f4/startup_stage_4.s +++ /dev/null @@ -1,37 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - - push {r0, r1} - - // setup the stack protector with provided random value - ldr r0, = __stack_chk_guard - str r2, [r0] - - ldr r0, =bss_start - ldr r1, =0 - ldr r2, =bss_end - sub r2, r2, r0 - bl memset - - // copy data in from flash - ldr r0, =data_vma // dst addr - ldr r1, =data_lma // src addr - ldr r2, =data_size // size in bytes - bl memcpy - - pop {r0, r1} - - // enter the application code - // returns exit code in r0 - bl main - - // terminate the application - // pass exit code in r0 - b system_exit - - .end diff --git a/core/embed/sys/startup/stm32f4/util.S b/core/embed/sys/startup/stm32f4/util.S deleted file mode 100644 index b01f5ee1a07..00000000000 --- a/core/embed/sys/startup/stm32f4/util.S +++ /dev/null @@ -1,120 +0,0 @@ - .syntax unified - - .text - -#ifdef KERNEL_MODE - - .global memset_reg - .type memset_reg, STT_FUNC -memset_reg: - // call with the following (note that the arguments are not validated prior to use): - // r0 - address of first word to write (inclusive) - // r1 - address of first word following the address in r0 to NOT write (exclusive) - // r2 - word value to be written - // both addresses in r0 and r1 needs to be divisible by 4! - cmp r0, r1 - beq .L_loop_end - .L_loop_begin: - str r2, [r0], 4 // store the word in r2 to the address in r0, post-indexed - cmp r0, r1 - bne .L_loop_begin - .L_loop_end: - bx lr - - // Jump to address given in first argument R0 that points to next's stage's VTOR - // Clear memory and all registers before jump - .global jump_to - .type jump_to, STT_FUNC -jump_to: - ldr r1, =0 - bl jump_to_with_flag - - // Jump to address given in first argument R0 that points to next's stage's VTOR - // Clear memory and all registers before jump. Second argument R1 is copied to R11 - // and kept after jump. - .global jump_to_with_flag - .type jump_to_with_flag, STT_FUNC -jump_to_with_flag: - mov r4, r0 // save input argument r0 (the address of the next stage's vector table) (r4 is callee save) - mov r11, r1 // save second argument in "flag" register because we'll be cleaning RAM - // this subroutine re-points the exception handlers before the C code - // that comprises them has been given a good environment to run. - // therefore, this code needs to disable interrupts before the VTOR - // update. then, the reset_handler of the next stage needs to re-enable interrupts. - // the following prevents activation of all exceptions except Non-Maskable Interrupt (NMI). - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.8: - // "there is no requirement to insert memory barrier instructions after CPSID". - cpsid f - // wipe memory at the end of the current stage of code - bl clear_otg_hs_memory - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_handoff_clear_ram_0_start - ldr r1, =_handoff_clear_ram_0_end - bl memset_reg - ldr r0, =_handoff_clear_ram_1_start - ldr r1, =_handoff_clear_ram_1_end - bl memset_reg - mov lr, r4 - // clear out the general purpose registers before the next stage's except the register with flag R11 - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r12, r0 - // give the next stage a fresh main stack pointer - ldr r0, [lr] // set r0 to the main stack pointer in the next stage's vector table - msr msp, r0 // give the next stage its main stack pointer - // point to the next stage's exception handlers - // AN321, section 4.11: "a memory barrier is not required after a VTOR update" - .set SCB_VTOR, 0xE000ED08 // reference "Cortex-M4 Devices Generic User Guide" section 4.3 - ldr r0, =SCB_VTOR - str lr, [r0] - mov r0, r1 // zero out r0 - // go on to the next stage - ldr lr, [lr, 4] // set lr to the next stage's reset_handler - bx lr - - .global shutdown_privileged - .type shutdown_privileged, STT_FUNC - // The function must be called from the privileged mode -shutdown_privileged: - cpsid f // disable all exceptions (except for NMI), the instruction is ignored in unprivileged mode - // if the exceptions weren't disabled, an exception handler (for example systick handler) - // could be called after the memory is erased, which would lead to another exception - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r11, r0 - mov r12, r0 - ldr lr, =0xffffffff - - ldr r0, =_shutdown_clear_ram_0_start - ldr r1, =_shutdown_clear_ram_0_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_1_start - ldr r1, =_shutdown_clear_ram_1_end - bl memset_reg - bl clear_otg_hs_memory - ldr r0, =1 - msr control, r0 // jump to unprivileged mode - ldr r0, =0 - b . // loop forever - -#endif - - .end diff --git a/core/embed/sys/startup/stm32f4/vectortable.S b/core/embed/sys/startup/stm32f4/vectortable.S index 2f07d34fd11..1dd7c4082c8 100644 --- a/core/embed/sys/startup/stm32f4/vectortable.S +++ b/core/embed/sys/startup/stm32f4/vectortable.S @@ -7,7 +7,7 @@ .global default_handler .type default_handler, STT_FUNC default_handler: - b shutdown_privileged + b Default_IRQHandler .macro add_handler symbol_name:req .word \symbol_name @@ -20,7 +20,7 @@ default_handler: // Section B1.5 - ARMv7-M Architecture Reference Manual .section .vector_table, "a" vector_table: - .word main_stack_base // defined in linker script + .word _stack_section_end // defined in linker script add_handler reset_handler add_handler NMI_Handler add_handler HardFault_Handler @@ -132,8 +132,8 @@ vector_table: .section .vector_table, "a" vector_table: - .word _sstack - .word _stack_size + .word _stack_section_start + .word _stack_section_size .word reset_handler diff --git a/core/embed/sys/startup/stm32u5/limited_util.S b/core/embed/sys/startup/stm32u5/limited_util.S deleted file mode 100644 index 0c7cc3c2efb..00000000000 --- a/core/embed/sys/startup/stm32u5/limited_util.S +++ /dev/null @@ -1,116 +0,0 @@ - .syntax unified - - .text - - .global memset_reg - .type memset_reg, STT_FUNC -memset_reg: - // call with the following (note that the arguments are not validated prior to use): - // r0 - address of first word to write (inclusive) - // r1 - address of first word following the address in r0 to NOT write (exclusive) - // r2 - word value to be written - // both addresses in r0 and r1 needs to be divisible by 4! - cmp r0, r1 - beq .L_loop_end - .L_loop_begin: - str r2, [r0], 4 // store the word in r2 to the address in r0, post-indexed - cmp r0, r1 - bne .L_loop_begin - .L_loop_end: - bx lr - - // Jump to address given in first argument R0 that points to next's stage's VTOR - // Clear memory and all registers before jump - .global jump_to - .type jump_to, STT_FUNC -jump_to: - mov r4, r0 // save input argument r0 (the address of the next stage's vector table) (r4 is callee save) - // this subroutine re-points the exception handlers before the C code - // that comprises them has been given a good environment to run. - // therefore, this code needs to disable interrupts before the VTOR - // update. then, the reset_handler of the next stage needs to re-enable interrupts. - // the following prevents activation of all exceptions except Non-Maskable Interrupt (NMI). - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.8: - // "there is no requirement to insert memory barrier instructions after CPSID". - cpsid f - // wipe memory at the end of the current stage of code - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_handoff_clear_ram_0_start - ldr r1, =_handoff_clear_ram_0_end - bl memset_reg - ldr r0, =_handoff_clear_ram_1_start - ldr r1, =_handoff_clear_ram_1_end - bl memset_reg - ldr r0, =_handoff_clear_ram_2_start - ldr r1, =_handoff_clear_ram_2_end - bl memset_reg - - mov lr, r4 - // clear out the general purpose registers before the next stage's code can run - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r11, r0 - mov r12, r0 - // give the next stage a fresh main stack pointer - ldr r0, [lr] // set r0 to the main stack pointer in the next stage's vector table - msr msp, r0 // give the next stage its main stack pointer - // point to the next stage's exception handlers - // AN321, section 4.11: "a memory barrier is not required after a VTOR update" - .set SCB_VTOR, 0xE000ED08 // reference "Cortex-M4 Devices Generic User Guide" section 4.3 - ldr r0, =SCB_VTOR - str lr, [r0] - mov r0, r1 // zero out r0 - // go on to the next stage - ldr lr, [lr, 4] // set lr to the next stage's reset_handler - bx lr - - .global shutdown_privileged - .type shutdown_privileged, STT_FUNC - // The function must be called from the privileged mode -shutdown_privileged: - cpsid f // disable all exceptions (except for NMI), the instruction is ignored in unprivileged mode - // if the exceptions weren't disabled, an exception handler (for example systick handler) - // could be called after the memory is erased, which would lead to another exception - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r11, r0 - mov r12, r0 - ldr lr, =0xffffffff - - ldr r0, =_shutdown_clear_ram_0_start - ldr r1, =_shutdown_clear_ram_0_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_1_start - ldr r1, =_shutdown_clear_ram_1_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_2_start - ldr r1, =_shutdown_clear_ram_2_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_3_start - ldr r1, =_shutdown_clear_ram_3_end - bl memset_reg - - ldr r0, =1 - msr control, r0 // jump to unprivileged mode - ldr r0, =0 - b . // loop forever - - .end diff --git a/core/embed/sys/startup/stm32u5/startup_init.c b/core/embed/sys/startup/stm32u5/startup_init.c index dd4d6818b62..524c8baffce 100644 --- a/core/embed/sys/startup/stm32u5/startup_init.c +++ b/core/embed/sys/startup/stm32u5/startup_init.c @@ -21,6 +21,9 @@ #include #include +#include +#include +#include #ifdef KERNEL_MODE @@ -186,9 +189,6 @@ void SystemInit(void) { // TODO turn off MSI? - // init the TRNG peripheral - rng_init(); - // set CP10 and CP11 to enable full access to the fpu coprocessor; SCB->CPACR |= ((3UL << 20U) | (3UL << 22U)); /* set CP10 and CP11 Full Access */ @@ -220,4 +220,60 @@ void SystemInit(void) { __HAL_RCC_GPIOD_CLK_ENABLE(); } +__attribute((no_stack_protector)) void reset_handler(void) { + // Set stack pointer limit for checking stack overflow + __set_MSPLIM((uintptr_t)&_stack_section_start + 128); + + // Now .bss, .data are not initialized yet - we need to be + // careful with global variables. They are not initialized, + // contain random values and will be rewritten in the succesive + // code + + // Initialize system clocks + SystemInit(); + + // Clear unused part of stack + clear_unused_stack(); + + // Initialize random number generator + rng_init(); + + // Clear all memory except stack. + // Keep also bootargs in bootloader and boardloader. + memregion_t region = MEMREGION_ALL_ACCESSIBLE_RAM; + + MEMREGION_DEL_SECTION(®ion, _stack_section); +#if defined BOARDLOADER || defined BOOTLOADER + MEMREGION_DEL_SECTION(®ion, _bootargs_ram); +#endif + +#ifdef BOARDLOADER + memregion_fill(®ion, rng_get()); +#endif + memregion_fill(®ion, 0); + + // Initialize .bss, .data, ... + init_linker_sections(); + + // Initialize stack protector guard value + extern uint32_t __stack_chk_guard; + __stack_chk_guard = rng_get(); + + // Now everything is perfectly initialized and we can do anything + // in C code + +#ifdef BOOTLOADER + bootargs_init(0); +#endif + + // Enable interrupts and fault handlers + __enable_fault_irq(); + + // Run application + extern int main(void); + int main_result = main(); + + system_exit(main_result); +} + #endif // #ifdef KERNEL_MODE diff --git a/core/embed/sys/startup/stm32u5/startup_stage_0.s b/core/embed/sys/startup/stm32u5/startup_stage_0.s deleted file mode 100644 index e237fe57e9b..00000000000 --- a/core/embed/sys/startup/stm32u5/startup_stage_0.s +++ /dev/null @@ -1,79 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - // set the stack protection - ldr r0, =_sstack - add r0, r0, #128 // safety margin for the exception frame - msr MSPLIM, r0 - - bl SystemInit - - // read the first rng data and save it - ldr r0, =0 // r0 - previous value - ldr r1, =0 // r1 - whether to compare the previous value - bl rng_read - - // read the next rng data and make sure it is different than previous - // r0 - value returned from previous call - ldr r1, =1 // r1 - whether to compare the previous value - bl rng_read - mov r4, r0 // save TRNG output in r4 - - // wipe memory to remove any possible vestiges of confidential data - - -fill_ram: - - mov r2, r4 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - ldr r0, =_startup_clear_ram_2_start - ldr r1, =_startup_clear_ram_2_end - bl memset_reg - - // setup environment for subsequent stage of code - - -clear_ram: - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - ldr r0, =_startup_clear_ram_2_start - ldr r1, =_startup_clear_ram_2_end - bl memset_reg - - // copy data in from flash - ldr r0, =data_vma // dst addr - ldr r1, =data_lma // src addr - ldr r2, =data_size // size in bytes - bl memcpy - - // copy confidential data in from flash - ldr r0, =confidential_vma // dst addr - ldr r1, =confidential_lma // src addr - ldr r2, =confidential_size // size in bytes - bl memcpy - - // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value - bl rng_get - ldr r1, = __stack_chk_guard - str r0, [r1] - - // enter the application code - bl main - - b shutdown_privileged - - .end diff --git a/core/embed/sys/startup/stm32u5/startup_stage_1.s b/core/embed/sys/startup/stm32u5/startup_stage_1.s deleted file mode 100644 index 53ba794d391..00000000000 --- a/core/embed/sys/startup/stm32u5/startup_stage_1.s +++ /dev/null @@ -1,62 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - // set the stack protection - ldr r0, =_sstack - add r0, r0, #128 // safety margin for the exception frame - msr MSPLIM, r0 - - // setup environment for subsequent stage of code - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - ldr r0, =_startup_clear_ram_2_start - ldr r1, =_startup_clear_ram_2_end - bl memset_reg - - // copy data in from flash - ldr r0, =data_vma // dst addr - ldr r1, =data_lma // src addr - ldr r2, =data_size // size in bytes - bl memcpy - - // copy confidential data in from flash - ldr r0, =confidential_vma // dst addr - ldr r1, =confidential_lma // src addr - ldr r2, =confidential_size // size in bytes - bl memcpy - - // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value - bl rng_get - ldr r1, = __stack_chk_guard - str r0, [r1] - - // copy & clear g_boot_command - ldr r0, =g_boot_command - ldr r1, [r0] - ldr r0, =g_boot_command_saved - str r1, [r0] - ldr r0, =g_boot_command - mov r1, #0 - str r1, [r0] - - // re-enable exceptions - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.7: - // "If it is not necessary to ensure that a pended interrupt is recognized immediately before - // subsequent operations, it is not necessary to insert a memory barrier instruction." - cpsie f - - // enter the application code - bl main - - b shutdown_privileged - - .end diff --git a/core/embed/sys/startup/stm32u5/startup_stage_2.s b/core/embed/sys/startup/stm32u5/startup_stage_2.s deleted file mode 100644 index 7813166f8ce..00000000000 --- a/core/embed/sys/startup/stm32u5/startup_stage_2.s +++ /dev/null @@ -1,53 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - // set the stack protection - ldr r0, =_sstack - add r0, r0, #128 // safety margin for the exception frame - msr MSPLIM, r0 - - // setup environment for subsequent stage of code - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_startup_clear_ram_0_start - ldr r1, =_startup_clear_ram_0_end - bl memset_reg - ldr r0, =_startup_clear_ram_1_start - ldr r1, =_startup_clear_ram_1_end - bl memset_reg - ldr r0, =_startup_clear_ram_2_start - ldr r1, =_startup_clear_ram_2_end - bl memset_reg - - // copy data in from flash - ldr r0, =data_vma // dst addr - ldr r1, =data_lma // src addr - ldr r2, =data_size // size in bytes - bl memcpy - - // copy confidential data in from flash - ldr r0, =confidential_vma // dst addr - ldr r1, =confidential_lma // src addr - ldr r2, =confidential_size // size in bytes - bl memcpy - - // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value - bl rng_get - ldr r1, = __stack_chk_guard - str r0, [r1] - - // re-enable exceptions - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.7: - // "If it is not necessary to ensure that a pended interrupt is recognized immediately before - // subsequent operations, it is not necessary to insert a memory barrier instruction." - cpsie f - - // enter the application code - bl main - - b shutdown_privileged - - .end diff --git a/core/embed/sys/startup/stm32u5/startup_stage_4.s b/core/embed/sys/startup/stm32u5/startup_stage_4.s deleted file mode 100644 index cc26b7470b8..00000000000 --- a/core/embed/sys/startup/stm32u5/startup_stage_4.s +++ /dev/null @@ -1,43 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - - push {r0, r1} - - // setup the stack protector with provided random value - ldr r0, = __stack_chk_guard - str r2, [r0] - - ldr r0, =bss_start - ldr r1, =0 - ldr r2, =bss_end - sub r2, r2, r0 - bl memset - - // copy data in from flash - ldr r0, =data_vma - ldr r1, =data_lma - ldr r2, =data_size - bl memcpy - - // copy confidential data in from flash - ldr r0, =confidential_vma - ldr r1, =confidential_lma - ldr r2, =confidential_size - bl memcpy - - pop {r0, r1} - - // enter the application code - // returns exit code in r0 - bl main - - // terminate the application - // pass exit code in r0 - b system_exit - - .end diff --git a/core/embed/sys/startup/stm32u5/util.S b/core/embed/sys/startup/stm32u5/util.S deleted file mode 100644 index 65fe4f94d0b..00000000000 --- a/core/embed/sys/startup/stm32u5/util.S +++ /dev/null @@ -1,120 +0,0 @@ - .syntax unified - - .text - -#ifdef KERNEL_MODE - - .global memset_reg - .type memset_reg, STT_FUNC -memset_reg: - // call with the following (note that the arguments are not validated prior to use): - // r0 - address of first word to write (inclusive) - // r1 - address of first word following the address in r0 to NOT write (exclusive) - // r2 - word value to be written - // both addresses in r0 and r1 needs to be divisible by 4! - cmp r0, r1 - beq .L_loop_end - .L_loop_begin: - str r2, [r0], 4 // store the word in r2 to the address in r0, post-indexed - cmp r0, r1 - bne .L_loop_begin - .L_loop_end: - bx lr - - // Jump to address given in first argument R0 that points to next's stage's VTOR - // Clear memory and all registers before jump - .global jump_to - .type jump_to, STT_FUNC -jump_to: - mov r4, r0 // save input argument r0 (the address of the next stage's vector table) (r4 is callee save) - // this subroutine re-points the exception handlers before the C code - // that comprises them has been given a good environment to run. - // therefore, this code needs to disable interrupts before the VTOR - // update. then, the reset_handler of the next stage needs to re-enable interrupts. - // the following prevents activation of all exceptions except Non-Maskable Interrupt (NMI). - // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.8: - // "there is no requirement to insert memory barrier instructions after CPSID". - cpsid f - // wipe memory at the end of the current stage of code - ldr r2, =0 // r2 - the word-sized value to be written - ldr r0, =_handoff_clear_ram_0_start - ldr r1, =_handoff_clear_ram_0_end - bl memset_reg - ldr r0, =_handoff_clear_ram_1_start - ldr r1, =_handoff_clear_ram_1_end - bl memset_reg - ldr r0, =_handoff_clear_ram_2_start - ldr r1, =_handoff_clear_ram_2_end - bl memset_reg - - mov lr, r4 - // clear out the general purpose registers before the next stage's code can run - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r11, r0 - mov r12, r0 - // give the next stage a fresh main stack pointer - ldr r0, [lr] // set r0 to the main stack pointer in the next stage's vector table - msr msp, r0 // give the next stage its main stack pointer - // point to the next stage's exception handlers - // AN321, section 4.11: "a memory barrier is not required after a VTOR update" - .set SCB_VTOR, 0xE000ED08 // reference "Cortex-M4 Devices Generic User Guide" section 4.3 - ldr r0, =SCB_VTOR - str lr, [r0] - mov r0, r1 // zero out r0 - // go on to the next stage - ldr lr, [lr, 4] // set lr to the next stage's reset_handler - bx lr - - .global shutdown_privileged - .type shutdown_privileged, STT_FUNC - // The function must be called from the privileged mode -shutdown_privileged: - cpsid f // disable all exceptions (except for NMI), the instruction is ignored in unprivileged mode - // if the exceptions weren't disabled, an exception handler (for example systick handler) - // could be called after the memory is erased, which would lead to another exception - ldr r0, =0 - mov r1, r0 - mov r2, r0 - mov r3, r0 - mov r4, r0 - mov r5, r0 - mov r6, r0 - mov r7, r0 - mov r8, r0 - mov r9, r0 - mov r10, r0 - mov r11, r0 - mov r12, r0 - ldr lr, =0xffffffff - - ldr r0, =_shutdown_clear_ram_0_start - ldr r1, =_shutdown_clear_ram_0_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_1_start - ldr r1, =_shutdown_clear_ram_1_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_2_start - ldr r1, =_shutdown_clear_ram_2_end - bl memset_reg - ldr r0, =_shutdown_clear_ram_3_start - ldr r1, =_shutdown_clear_ram_3_end - bl memset_reg - - ldr r0, =1 - msr control, r0 // jump to unprivileged mode - ldr r0, =0 - b . // loop forever - -#endif - - .end diff --git a/core/embed/sys/startup/stm32u5/vectortable.S b/core/embed/sys/startup/stm32u5/vectortable.S index d4f79d19503..a7059829a6c 100644 --- a/core/embed/sys/startup/stm32u5/vectortable.S +++ b/core/embed/sys/startup/stm32u5/vectortable.S @@ -7,7 +7,7 @@ .global default_handler .type default_handler, STT_FUNC default_handler: - b shutdown_privileged + b Default_IRQHandler .macro add_handler symbol_name:req .word \symbol_name @@ -20,7 +20,7 @@ default_handler: // Section B1.5 - ARMv7-M Architecture Reference Manual .section .vector_table, "a" vector_table: - .word main_stack_base // defined in linker script + .word _stack_section_end // defined in linker script add_handler reset_handler add_handler NMI_Handler add_handler HardFault_Handler @@ -180,8 +180,8 @@ vector_table: .section .vector_table, "a" vector_table: - .word _sstack - .word _stack_size + .word _stack_section_start + .word _stack_section_size .word reset_handler #endif diff --git a/core/embed/sys/startup/unix/bootutils.c b/core/embed/sys/startup/unix/bootutils.c index 12824d0c00a..347335ce257 100644 --- a/core/embed/sys/startup/unix/bootutils.c +++ b/core/embed/sys/startup/unix/bootutils.c @@ -55,16 +55,18 @@ void bootargs_get_args(boot_args_t* dest) { memcpy(dest, &g_boot_args, sizeof(boot_args_t)); } -void __attribute__((noreturn)) secure_shutdown(void) { - printf("SHUTDOWN\n"); +__attribute__((noreturn)) void reboot_device(void) { + printf("reboot (normal)\n"); + + exit(3); +} + +__attribute__((noreturn)) void reboot_or_halt_after_rsod(void) { + printf("reboot (with timeout)\n"); // Wait some time to let the user see the displayed // message before shutting down - hal_delay(3000); + systick_delay_ms(3000); exit(3); } - -void ensure_compatible_settings(void) { - // Left empty -} diff --git a/core/embed/sys/syscall/stm32/syscall_dispatch.c b/core/embed/sys/syscall/stm32/syscall_dispatch.c index 58b9f62806e..b8f94450550 100644 --- a/core/embed/sys/syscall/stm32/syscall_dispatch.c +++ b/core/embed/sys/syscall/stm32/syscall_dispatch.c @@ -141,10 +141,6 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args, args[1] = cycles >> 32; } break; - case SYSCALL_SECURE_SHUTDOWN: { - secure_shutdown(); - } break; - case SYSCALL_REBOOT_DEVICE: { reboot_device(); } break; diff --git a/core/embed/sys/syscall/stm32/syscall_numbers.h b/core/embed/sys/syscall/stm32/syscall_numbers.h index 3c283365b7a..2edef3d3f3c 100644 --- a/core/embed/sys/syscall/stm32/syscall_numbers.h +++ b/core/embed/sys/syscall/stm32/syscall_numbers.h @@ -32,7 +32,6 @@ typedef enum { SYSCALL_SYSTICK_US, SYSCALL_SYSTICK_US_TO_CYCLES, - SYSCALL_SECURE_SHUTDOWN, SYSCALL_REBOOT_DEVICE, SYSCALL_REBOOT_TO_BOOTLOADER, SYSCALL_REBOOT_AND_UPGRADE, diff --git a/core/embed/sys/syscall/stm32/syscall_probe.c b/core/embed/sys/syscall/stm32/syscall_probe.c index df1172d34f2..a8f8bfa1301 100644 --- a/core/embed/sys/syscall/stm32/syscall_probe.c +++ b/core/embed/sys/syscall/stm32/syscall_probe.c @@ -26,7 +26,7 @@ #ifdef SYSCALL_DISPATCH static inline bool inside_area(const void *addr, size_t len, - const memory_area_t *area) { + const applet_memory_t *area) { return ((uintptr_t)addr >= area->start) && ((uintptr_t)addr + len <= area->start + area->size); } @@ -63,7 +63,7 @@ bool probe_read_access(const void *addr, size_t len) { return true; } - static const memory_area_t assets = { + static const applet_memory_t assets = { .start = ASSETS_START, .size = ASSETS_MAXSIZE, }; diff --git a/core/embed/sys/syscall/stm32/syscall_stubs.c b/core/embed/sys/syscall/stm32/syscall_stubs.c index 4bfe2f11615..f7048cacf69 100644 --- a/core/embed/sys/syscall/stm32/syscall_stubs.c +++ b/core/embed/sys/syscall/stm32/syscall_stubs.c @@ -76,12 +76,6 @@ uint64_t systick_us_to_cycles(uint64_t us) { #include -void secure_shutdown(void) { - syscall_invoke0(SYSCALL_SECURE_SHUTDOWN); - while (1) - ; -} - void reboot_to_bootloader(void) { syscall_invoke0(SYSCALL_REBOOT_TO_BOOTLOADER); while (1) diff --git a/core/embed/sys/task/inc/sys/applet.h b/core/embed/sys/task/inc/sys/applet.h index ef03e95e7cd..aef2cc81dc1 100644 --- a/core/embed/sys/task/inc/sys/applet.h +++ b/core/embed/sys/task/inc/sys/applet.h @@ -32,12 +32,12 @@ typedef void (*applet_startup_t)(const char* args, uint32_t random); typedef struct { uint32_t start; uint32_t size; -} memory_area_t; +} applet_memory_t; // Applet header found at the beginning of the applet binary typedef struct { // Stack area - memory_area_t stack; + applet_memory_t stack; // Applet entry point applet_startup_t startup; } applet_header_t; @@ -45,13 +45,13 @@ typedef struct { // Applet memory layout typedef struct { // Read/write data area #1 - memory_area_t data1; + applet_memory_t data1; // Read/write data area #2 - memory_area_t data2; + applet_memory_t data2; // Read-only code area #1 - memory_area_t code1; + applet_memory_t code1; // Read-only code area #2 - memory_area_t code2; + applet_memory_t code2; } applet_layout_t; diff --git a/core/embed/sys/task/stm32/systask.c b/core/embed/sys/task/stm32/systask.c index a6bb7a0bf81..852b53a415e 100644 --- a/core/embed/sys/task/stm32/systask.c +++ b/core/embed/sys/task/stm32/systask.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -54,10 +55,6 @@ typedef struct { systask_t* waiting_task; } systask_scheduler_t; -// Kernel stack base pointer defined in linker script -extern uint8_t _sstack; -extern uint8_t _estack; - // Global task manager state static systask_scheduler_t g_systask_scheduler = { // This static initialization is required for exception handling @@ -65,7 +62,7 @@ static systask_scheduler_t g_systask_scheduler = { .active_task = &g_systask_scheduler.kernel_task, .waiting_task = &g_systask_scheduler.kernel_task, .kernel_task = { - .sp_lim = (uint32_t)&_sstack, + .sp_lim = (uint32_t)&_stack_section_start, }}; void systask_scheduler_init(systask_error_handler_t error_handler) { @@ -77,7 +74,7 @@ void systask_scheduler_init(systask_error_handler_t error_handler) { scheduler->active_task = &scheduler->kernel_task; scheduler->waiting_task = scheduler->active_task; - scheduler->kernel_task.sp_lim = (uint32_t)&_sstack; + scheduler->kernel_task.sp_lim = (uint32_t)&_stack_section_start; // SVCall priority should be the lowest since it is // generally a blocking operation @@ -209,7 +206,10 @@ static void systask_kill(systask_t* task) { if (scheduler->error_handler != NULL) { scheduler->error_handler(&task->pminfo); } - secure_shutdown(); + + // We reach this point only if error_handler is NULL or + // if it returns. Neither is expected to happen. + reboot_device(); } else if (task == scheduler->active_task) { // Switch to the kernel task systask_yield_to(&scheduler->kernel_task); @@ -541,7 +541,7 @@ __attribute__((naked, no_stack_protector)) void HardFault_Handler(void) { "MOV R0, #1 \n" // R0 = 1 (Privileged) "B systask_exit_fault \n" // Exit task with fault : - : [estack] "i"(&_estack) + : [estack] "i"(&_stack_section_end) : "memory"); } @@ -565,7 +565,9 @@ __attribute__((naked, no_stack_protector)) void MemManage_Handler(void) { #endif "B systask_exit_fault \n" // Exit task with fault : - : [estack] "i"(&_estack), [sstack] "i"((uint32_t)&_sstack + 256) + : [estack] "i"(&_stack_section_end), [sstack] "i"( + (uint32_t)&_stack_section_start + + 256) : "memory"); } @@ -600,7 +602,7 @@ __attribute__((naked, no_stack_protector)) void UsageFault_Handler(void) { "MOV R0, #1 \n" // R0 = 1 (Privileged) "B systask_exit_fault \n" // Exit task with fault : - : [estack] "i"(&_estack) + : [estack] "i"(&_stack_section_end) : "memory"); } @@ -635,4 +637,6 @@ void NMI_Handler(void) { mpu_restore(mpu_mode); } +void Default_IRQHandler(void) { error_shutdown("Unhandled IRQ"); } + #endif // KERNEL_MODE diff --git a/core/embed/sys/task/stm32/system.c b/core/embed/sys/task/stm32/system.c index d21866b8480..6af3531231c 100644 --- a/core/embed/sys/task/stm32/system.c +++ b/core/embed/sys/task/stm32/system.c @@ -20,12 +20,15 @@ #include #include +#include #include +#include #include #include #include #include #include +#include #ifdef USE_SDRAM #include @@ -35,10 +38,6 @@ #include "../stm32f4/startup_init.h" #endif -#ifndef HardFault_IRQn -#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32429xx.h -#endif - #ifdef KERNEL_MODE void system_init(systask_error_handler_t error_handler) { @@ -78,262 +77,62 @@ void system_exit_fatal_ex(const char* message, size_t message_len, 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 +__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; -#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 + // Reset peripherals (so we are sure that no DMA is pending) + reset_peripherals_and_interrupts(); -#ifdef __HAL_RCC_LTDC_FORCE_RESET - __HAL_RCC_LTDC_CLK_DISABLE(); - __HAL_RCC_LTDC_FORCE_RESET(); - __HAL_RCC_LTDC_RELEASE_RESET(); -#endif + // Copy pminfo from to our stack + // MPU is now disable, we have full access to bootargs. + systask_postmortem_t pminfo = bootargs_ptr()->pminfo; -#ifdef __HAL_RCC_GPDMA1_FORCE_RESET - __HAL_RCC_GPDMA1_CLK_DISABLE(); - __HAL_RCC_GPDMA1_FORCE_RESET(); - __HAL_RCC_GPDMA1_RELEASE_RESET(); -#endif + // Clear unused part of our stack + clear_unused_stack(); -#ifdef __HAL_RCC_DMA1_FORCE_RESET - __HAL_RCC_DMA1_CLK_DISABLE(); - __HAL_RCC_DMA1_FORCE_RESET(); - __HAL_RCC_DMA1_RELEASE_RESET(); -#endif + // Save stack protector guard for later + extern uint32_t __stack_chk_guard; + uint32_t stack_chk_guard = __stack_chk_guard; -#ifdef __HAL_RCC_DMA2_FORCE_RESET - __HAL_RCC_DMA2_CLK_DISABLE(); - __HAL_RCC_DMA2_FORCE_RESET(); - __HAL_RCC_DMA2_RELEASE_RESET(); -#endif + // 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(®ion, _stack_section); + memregion_fill(®ion, 0); - // 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); - } + // Reinitialize .bss, .data, ... + init_linker_sections(); - // Disable SysTick - SysTick->CTRL = 0; + // Reinitialize stack protector guard + __stack_chk_guard = stack_chk_guard; - // Clear PENDSV flag to prevent the PendSV_Handler call - SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk; + // Now we can safely enable interrupts again + __enable_fault_irq(); - // Clear SCB->SHCSR exception flags so we can return back - // to thread mode without any exception active + // Ensure we are in thread mode + ensure_thread_mode(); - uint32_t preserved_flag = 0; + // Now everything is perfectly initialized and we can do anything + // in C code - 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; + if (error_handler != NULL) { + error_handler(&pminfo); } - 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); + // We reach this point only if error_handler is NULL or + // if it returns. Neither is expected to happen. + reboot_device(); } -__attribute((naked, no_stack_protector)) void system_emergency_rescue( +__attribute((naked, noreturn, no_stack_protector)) void system_emergency_rescue( systask_error_handler_t error_handler, const systask_postmortem_t* pminfo) { - extern uint32_t __stack_chk_guard; - - __asm__ volatile( - "MOV R5, R1 \n" // R5 = pminfo - "MOV R6, R0 \n" // R6 = error_handler - - "CPSID I \n" // Disable interrupts - - // -------------------------------------------------------------- - // Disable MPU - // -------------------------------------------------------------- - - "DMB 0xF \n" // Data memory barrier - "LDR R0, =0xE000ED94 \n" // MPU->CTRL - "MOV R1, #0 \n" - "STR R1, [R0] \n" // Disable MPU - - // -------------------------------------------------------------- - // Setup new stack - // -------------------------------------------------------------- - - "LDR R0, =_estack \n" // Setup new stack - "MSR MSP, R0 \n" // Set MSP -#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) - "LDR R0, =_sstack \n" - "ADD R0, R0, #256 \n" // Add safety margin - "MSR MSPLIM, R0 \n" // Set MSPLIM -#endif - - // -------------------------------------------------------------- - // Copy pminfo to new stack - // -------------------------------------------------------------- - - "LDR R2, =%[PMINFO_SIZE] \n" // Copy pminfo to new stack - "SUB SP, R2 \n" // Allocate space for pminfo - "MOV R0, SP \n" // Destination - "MOV R1, R5 \n" // Source - "MOV R5, R0 \n" // R5 = pminfo on the new stack - "BL memcpy \n" - - // -------------------------------------------------------------- - // Save stack protector guard - // -------------------------------------------------------------- - - "LDR R0, =%[STK_GUARD] \n" // Save stack protector guard - "LDR R7, [R0] \n" // R7 = __stack_chk_guard - - // -------------------------------------------------------------- - // Clear .bss, initialize .data, ... - // -------------------------------------------------------------- - - "LDR R0, =bss_start \n" // Clear .bss - "MOV R1, #0 \n" - "LDR R2, =bss_end \n" - "SUB R2, R2, R0 \n" - "BL memset \n" - - "LDR R0, =data_vma \n" // Initialize .data - "LDR R1, =data_lma \n" - "LDR R2, =data_size \n" - "BL memcpy \n" - -#ifdef STM32U5 - "LDR R0, =confidential_vma \n" // Initialize .confidental - "LDR R1, =confidential_lma \n" - "LDR R2, =confidential_size \n" - "BL memcpy \n" -#endif - - // -------------------------------------------------------------- - // Restore stack protector guard - // -------------------------------------------------------------- - - "LDR R0, =%[STK_GUARD] \n" // Restore stack protector guard - "STR R7, [R0] \n" - - // -------------------------------------------------------------- - // Reset critical hardware so we can safely enable interrupts - // -------------------------------------------------------------- - - "BL emergency_reset \n" - - "CPSIE I \n" // Re-enable interrupts - - // -------------------------------------------------------------- - // Clear all VFP registers - // -------------------------------------------------------------- - - "LDR R1, = 0xE000EF34 \n" // FPU->FPCCR - "LDR R0, [R1] \n" - "BIC R0, R0, #1 \n" // Clear LSPACT to suppress lazy - // stacking - "STR R0, [R1] \n" - - // TODO: clear VFP registers (maybe for ARMV7-M only) - - // -------------------------------------------------------------- - // Clear R7-R11 registers - // -------------------------------------------------------------- - - "MOV R0, #0 \n" - "MOV R7, R0 \n" - "MOV R8, R0 \n" - "MOV R9, R0 \n" - "MOV R10, R0 \n" - "MOV R11, R0 \n" - - // -------------------------------------------------------------- - // Check if we are in thread mode and if yes, jump to error_handler - // -------------------------------------------------------------- - - "LDR R1, =0x1FF \n" // Get lower 9 bits of IPSR - "MRS R0, IPSR \n" - "ANDS R0, R0, R1 \n" - "CMP R0, #0 \n" // == 0 if in thread mode - "ITTT EQ \n" - "MOVEQ R0, R5 \n" // R0 = pminfo - "LDREQ LR, =secure_shutdown\n" - "BXEQ R6 \n" // jump to error_handler directly - - // -------------------------------------------------------------- - // Return from exception to thread mode - // -------------------------------------------------------------- - - "MOV R0, SP \n" // Align stack pointer to 8 bytes - "AND R0, R0, #~7 \n" - "MOV SP, R0 \n" - "SUB SP, SP, #32 \n" // Allocate space for the stack frame - - "MOV R0, #0 \n" - "STR R5, [SP, #0] \n" // future R0 = pminfo - "STR R0, [SP, #4] \n" // future R1 = 0 - "STR R0, [SP, #8] \n" // future R2 = 0 - "STR R0, [SP, #12] \n" // future R3 = 0 - "STR R0, [SP, #16] \n" // future R12 = 0 - "LDR R0, =secure_shutdown\n" - "STR R0, [SP, #20] \n" // future LR = secure_shutdown() - "BIC R6, R6, #1 \n" - "STR R6, [SP, #24] \n" // return address = error_handler() - "LDR R1, = 0x01000000 \n" // THUMB bit set - "STR R1, [SP, #28] \n" // future xPSR - - "MOV R4, R0 \n" // Clear registers R4-R6 - "MOV R5, R0 \n" // (R7-R11 are already cleared) - "MOV R6, R0 \n" - - "MRS R0, CONTROL \n" // Clear SPSEL to use MSP for thread - "BIC R0, R0, #3 \n" // Clear nPRIV to run in privileged mode - "MSR CONTROL, R1 \n" + // Save `pminfo` to bootargs so it isn't overwritten by succesive call + bootargs_set(BOOT_COMMAND_SHOW_RSOD, pminfo, sizeof(*pminfo)); - "LDR LR, = 0xFFFFFFF9 \n" // Return to Secure Thread mode, use MSP - "BX LR \n" - : // no output - : [PMINFO_SIZE] "i"(sizeof(systask_postmortem_t)), - [STK_GUARD] "i"(&__stack_chk_guard) - : // no clobber - ); + call_with_new_stack((uint32_t)error_handler, 0, + system_emergency_rescue_phase_2); } #endif // KERNEL_MODE diff --git a/core/embed/sys/task/unix/system.c b/core/embed/sys/task/unix/system.c index 48157962e9c..451505fa091 100644 --- a/core/embed/sys/task/unix/system.c +++ b/core/embed/sys/task/unix/system.c @@ -48,7 +48,9 @@ void system_exit(int exitcode) { } } - secure_shutdown(); + // We reach this point only if g_error_handler is NULL or + // if it returns. Neither is expected to happen. + reboot_device(); } void system_exit_error_ex(const char* title, size_t title_len, @@ -77,7 +79,9 @@ void system_exit_error_ex(const char* title, size_t title_len, } } - secure_shutdown(); + // We reach this point only if g_error_handler is NULL or + // if it returns. Neither is expected to happen. + reboot_device(); } void system_exit_error(const char* title, const char* message, @@ -117,7 +121,9 @@ void system_exit_fatal_ex(const char* message, size_t message_len, } } - secure_shutdown(); + // We reach this point only if g_error_handler is NULL or + // if it returns. Neither is expected to happen. + reboot_device(); } void system_exit_fatal(const char* message, const char* file, int line) { @@ -136,5 +142,5 @@ void system_emergency_rescue(systask_error_handler_t error_handler, error_handler(pminfo); // We should never reach this point - exit(0); + reboot_device(); } diff --git a/core/embed/util/rsod/rsod.c b/core/embed/util/rsod/rsod.c index c23a91744b5..1d9e9df702d 100644 --- a/core/embed/util/rsod/rsod.c +++ b/core/embed/util/rsod/rsod.c @@ -177,8 +177,8 @@ static void init_and_show_rsod(const systask_postmortem_t* pminfo) { rsod_terminal(pminfo); #endif - // Wait for the user to manually power off the device - secure_shutdown(); + // Reboots or halts (if RSOD_INFINITE_LOOP is defined) + reboot_or_halt_after_rsod(); } // Universal panic handler diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index ba37025165e..498803b1d1f 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -18,6 +18,7 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/sec/time_estimate/inc", "embed/sys/bsp/stm32f4", "embed/sys/irq/inc", + "embed/sys/linker/inc", "embed/sys/mpu/inc", "embed/sys/pvd/inc", "embed/sec/secret/inc", @@ -66,9 +67,11 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/sec/rng/stm32/rng.c", "embed/sec/secret/stm32f4/secret.c", "embed/sec/time_estimate/stm32/time_estimate.c", + "embed/sys/linker/linker_utils.c", "embed/sys/mpu/stm32f4/mpu.c", "embed/sys/pvd/stm32/pvd.c", "embed/sys/startup/stm32/bootutils.c", + "embed/sys/startup/stm32/sysutils.c", "embed/sys/startup/stm32f4/reset_flags.c", "embed/sys/startup/stm32f4/startup_init.c", "embed/sys/startup/stm32f4/vectortable.S", @@ -92,17 +95,5 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/util/unit_properties/stm32/unit_properties.c", ] - # boardloader needs separate assembler for some function unencumbered by various FW+bootloader hacks - # this helps to prevent making a bug in boardloader which may be hard to fix since it's locked with write-protect - env_constraints = env.get("CONSTRAINTS") - if env_constraints and "limited_util_s" in env_constraints: - sources += [ - "embed/sys/startup/stm32f4/limited_util.S", - ] - else: - sources += [ - "embed/sys/startup/stm32f4/util.S", - ] - env.get("ENV")["SUFFIX"] = "stm32f4" env.get("ENV")["LINKER_SCRIPT"] = """embed/sys/linker/stm32f4/{target}.ld""" diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index 736d0626961..dbf1ac3801f 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -20,6 +20,7 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/sec/time_estimate/inc", "embed/sys/irq/inc", "embed/sys/bsp/stm32u5", + "embed/sys/linker/inc", "embed/sys/mpu/inc", "embed/sys/pvd/inc", "embed/sys/startup/inc", @@ -84,9 +85,11 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/sec/secret/stm32u5/secret.c", "embed/sec/secure_aes/stm32u5/secure_aes.c", "embed/sec/time_estimate/stm32/time_estimate.c", + "embed/sys/linker/linker_utils.c", "embed/sys/mpu/stm32u5/mpu.c", "embed/sys/pvd/stm32/pvd.c", "embed/sys/startup/stm32/bootutils.c", + "embed/sys/startup/stm32/sysutils.c", "embed/sys/startup/stm32u5/reset_flags.c", "embed/sys/startup/stm32u5/startup_init.c", "embed/sys/startup/stm32u5/vectortable.S", @@ -112,16 +115,4 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/util/unit_properties/stm32/unit_properties.c", ] - # boardloader needs separate assembler for some function unencumbered by various FW+bootloader hacks - # this helps to prevent making a bug in boardloader which may be hard to fix since it's locked with write-protect - env_constraints = env.get("CONSTRAINTS") - if env_constraints and "limited_util_s" in env_constraints: - sources += [ - "embed/sys/startup/stm32u5/limited_util.S", - ] - else: - sources += [ - "embed/sys/startup/stm32u5/util.S", - ] - env.get("ENV")["SUFFIX"] = "stm32u5"