1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-07 13:12:41 +00:00

refactor(core): rewrite startup code in C

[no changelog]
This commit is contained in:
cepetr 2025-01-29 21:34:20 +01:00 committed by cepetr
parent 70c577b67b
commit 95afa34f27
24 changed files with 453 additions and 456 deletions

View File

@ -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) 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 = [ SOURCE_BOARDLOADER = [
f"embed/sys/startup/{FILE_SUFFIX}/startup_stage_0.s",
'embed/projects/boardloader/main.c', 'embed/projects/boardloader/main.c',
] ]

View File

@ -101,10 +101,7 @@ env = Environment(
FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) 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 = [ SOURCE_BOOTLOADER = [
f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_1.s',
'embed/projects/bootloader/header.S', 'embed/projects/bootloader/header.S',
'embed/projects/bootloader/bootui.c', 'embed/projects/bootloader/bootui.c',
'embed/projects/bootloader/main.c', 'embed/projects/bootloader/main.c',

View File

@ -95,10 +95,7 @@ env = Environment(
FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) 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 = [ SOURCE_BOOTLOADER = [
f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_1.s',
'embed/projects/bootloader_ci/header.S', 'embed/projects/bootloader_ci/header.S',
'embed/projects/bootloader_ci/bootui.c', 'embed/projects/bootloader_ci/bootui.c',
'embed/projects/bootloader_ci/main.c', 'embed/projects/bootloader_ci/main.c',

View File

@ -397,14 +397,11 @@ env = Environment(
FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) 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 = [ SOURCE_FIRMWARE = [
'embed/projects/firmware/header.S', 'embed/projects/firmware/header.S',
'embed/projects/firmware/main.c', 'embed/projects/firmware/main.c',
'embed/projects/firmware/mphalport.c', 'embed/projects/firmware/mphalport.c',
'embed/projects/firmware/nlrthumb.c', 'embed/projects/firmware/nlrthumb.c',
f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_4.s',
] ]
if 'sd_card' in FEATURES_AVAILABLE: if 'sd_card' in FEATURES_AVAILABLE:

View File

@ -258,11 +258,8 @@ env = Environment(
FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) 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 = [ SOURCE_FIRMWARE = [
'embed/projects/kernel/main.c', 'embed/projects/kernel/main.c',
f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_2.s',
] ]
if 'sd_card' in FEATURES_AVAILABLE: if 'sd_card' in FEATURES_AVAILABLE:

View File

@ -95,11 +95,7 @@ env = Environment(
FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) 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 = [ SOURCE_PRODTEST = [
f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_2.s',
'embed/projects/prodtest/header.S', 'embed/projects/prodtest/header.S',
'embed/projects/prodtest/main.c', 'embed/projects/prodtest/main.c',
'embed/projects/prodtest/prodtest_common.c', 'embed/projects/prodtest/prodtest_common.c',

View File

@ -81,10 +81,7 @@ env = Environment(
FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) 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 = [ SOURCE_REFLASH = [
f'embed/sys/startup/{FILE_SUFFIX}/startup_stage_2.s',
'embed/projects/reflash/header.S', 'embed/projects/reflash/header.S',
'embed/projects/reflash/main.c', 'embed/projects/reflash/main.c',
] ]

View File

@ -32,6 +32,7 @@
#include "ports/stm32/gccollect.h" #include "ports/stm32/gccollect.h"
#include "ports/stm32/pendsv.h" #include "ports/stm32/pendsv.h"
#include <sys/linker_utils.h>
#include <sys/systask.h> #include <sys/systask.h>
#include <sys/system.h> #include <sys/system.h>
#include <util/rsod.h> #include <util/rsod.h>
@ -111,3 +112,22 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); 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);
}

View File

@ -0,0 +1,95 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
// 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, &section_name##_start, &section_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, &section_name##_start, &section_name##_end); \
}

View File

@ -0,0 +1,195 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <trezor_rtl.h>
#include <sys/linker_utils.h>
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) {
extern uint32_t _stack_section_start;
__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 = &region->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 = &region->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 = &region->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 = &region->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;
}
}
}
}

View File

@ -43,6 +43,12 @@ typedef union {
} boot_args_t; } boot_args_t;
// 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. // Configures the boot command and associated arguments for the next reboot.
// The arguments must adhere to the boot_args_t structure layout. // 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); void bootargs_set(boot_command_t command, const void* args, size_t args_size);

View File

@ -81,6 +81,15 @@ void bootargs_get_args(boot_args_t* dest) {
mpu_restore(mode); mpu_restore(mode);
} }
void bootargs_init(uint32_t r11_register) {
#ifdef STM32U5
g_boot_command_saved = g_boot_command;
g_boot_command = BOOT_COMMAND_NONE;
#else
g_boot_command_saved = r11_register;
#endif
}
#endif #endif
// Deletes all secrets and SRAM2 where stack is located // Deletes all secrets and SRAM2 where stack is located

View File

@ -21,7 +21,10 @@
#include <trezor_rtl.h> #include <trezor_rtl.h>
#include <sec/rng.h> #include <sec/rng.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h> #include <sys/bootutils.h>
#include <sys/linker_utils.h>
#include <sys/system.h>
#include <sys/systick.h> #include <sys/systick.h>
#include "startup_init.h" #include "startup_init.h"
@ -250,4 +253,65 @@ __attribute((used)) void clear_otg_hs_memory(void) {
// the peripheral is not needed right now // 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(&region, _stack_section);
#ifdef BOOTLOADER
MEMREGION_DEL_SECTION(&region, _bootargs_ram);
#endif
#ifdef BOARDLOADER
memregion_fill(&region, rng_get());
#endif
memregion_fill(&region, 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 #endif // KERNEL_MODE

View File

@ -1,62 +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_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end // size in bytes
sub r2, r2, r0
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 system_exit
.end

View File

@ -1,46 +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_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end // size in bytes
sub r2, r2, r0
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 system_exit
.end

View File

@ -1,40 +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_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end // size in bytes
sub r2, r2, r0
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 system_exit
.end

View File

@ -1,38 +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_section_start
ldr r1, =0
ldr r2, =_bss_section_end
sub r2, r2, r0
bl memset
// copy data in from flash
ldr r0, =_data_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end
sub r2, r2, r0 // 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

View File

@ -21,6 +21,9 @@
#include <trezor_rtl.h> #include <trezor_rtl.h>
#include <sec/rng.h> #include <sec/rng.h>
#include <sys/bootargs.h>
#include <sys/linker_utils.h>
#include <sys/system.h>
#ifdef KERNEL_MODE #ifdef KERNEL_MODE
@ -186,9 +189,6 @@ void SystemInit(void) {
// TODO turn off MSI? // TODO turn off MSI?
// init the TRNG peripheral
rng_init();
// set CP10 and CP11 to enable full access to the fpu coprocessor; // set CP10 and CP11 to enable full access to the fpu coprocessor;
SCB->CPACR |= SCB->CPACR |=
((3UL << 20U) | (3UL << 22U)); /* set CP10 and CP11 Full Access */ ((3UL << 20U) | (3UL << 22U)); /* set CP10 and CP11 Full Access */
@ -220,4 +220,61 @@ void SystemInit(void) {
__HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE();
} }
__attribute((no_stack_protector)) void reset_handler(void) {
// Set stack pointer limit for checking stack overflow
extern uint8_t _stack_section_start;
__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(&region, _stack_section);
#if defined BOARDLOADER || defined BOOTLOADER
MEMREGION_DEL_SECTION(&region, _bootargs_ram);
#endif
#ifdef BOARDLOADER
memregion_fill(&region, rng_get());
#endif
memregion_fill(&region, 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 #endif // #ifdef KERNEL_MODE

View File

@ -1,81 +0,0 @@
.syntax unified
.text
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_stack_section_start
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_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end // size in bytes
sub r2, r2, r0
bl memcpy
// copy confidential data in from flash
ldr r0, =_confidential_section_start // dst addr
ldr r1, =_confidential_section_loadaddr // src addr
ldr r2, =_confidential_section_end // size in bytes
sub r2, r2, r0
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 system_exit
.end

View File

@ -1,64 +0,0 @@
.syntax unified
.text
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_stack_section_start
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_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end // size in bytes
sub r2, r2, r0
bl memcpy
// copy confidential data in from flash
ldr r0, =_confidential_section_start // dst addr
ldr r1, =_confidential_section_loadaddr // src addr
ldr r2, =_confidential_section_end // size in bytes
sub r2, r2, r0
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 system_exit
.end

View File

@ -1,55 +0,0 @@
.syntax unified
.text
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_stack_section_start
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_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end // size in bytes
sub r2, r2, r0
bl memcpy
// copy confidential data in from flash
ldr r0, =_confidential_section_start // dst addr
ldr r1, =_confidential_section_loadaddr // src addr
ldr r2, =_confidential_section_end // size in bytes
sub r2, r2, r0
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 system_exit
.end

View File

@ -1,45 +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_section_start
ldr r1, =0
ldr r2, =_bss_section_end
sub r2, r2, r0
bl memset
// copy data in from flash
ldr r0, =_data_section_start // dst addr
ldr r1, =_data_section_loadaddr // src addr
ldr r2, =_data_section_end // size in bytes
sub r2, r2, r0
bl memcpy
// copy confidential data in from flash
ldr r0, =_confidential_section_start // dst addr
ldr r1, =_confidential_section_loadaddr // src addr
ldr r2, =_confidential_section_end // size in bytes
sub r2, r2, r0
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

View File

@ -18,6 +18,7 @@ def stm32f4_common_files(env, defines, sources, paths):
"embed/sec/time_estimate/inc", "embed/sec/time_estimate/inc",
"embed/sys/bsp/stm32f4", "embed/sys/bsp/stm32f4",
"embed/sys/irq/inc", "embed/sys/irq/inc",
"embed/sys/linker/inc",
"embed/sys/mpu/inc", "embed/sys/mpu/inc",
"embed/sys/pvd/inc", "embed/sys/pvd/inc",
"embed/sec/secret/inc", "embed/sec/secret/inc",
@ -66,6 +67,7 @@ def stm32f4_common_files(env, defines, sources, paths):
"embed/sec/rng/stm32/rng.c", "embed/sec/rng/stm32/rng.c",
"embed/sec/secret/stm32f4/secret.c", "embed/sec/secret/stm32f4/secret.c",
"embed/sec/time_estimate/stm32/time_estimate.c", "embed/sec/time_estimate/stm32/time_estimate.c",
"embed/sys/linker/linker_utils.c",
"embed/sys/mpu/stm32f4/mpu.c", "embed/sys/mpu/stm32f4/mpu.c",
"embed/sys/pvd/stm32/pvd.c", "embed/sys/pvd/stm32/pvd.c",
"embed/sys/startup/stm32/bootutils.c", "embed/sys/startup/stm32/bootutils.c",

View File

@ -20,6 +20,7 @@ def stm32u5_common_files(env, defines, sources, paths):
"embed/sec/time_estimate/inc", "embed/sec/time_estimate/inc",
"embed/sys/irq/inc", "embed/sys/irq/inc",
"embed/sys/bsp/stm32u5", "embed/sys/bsp/stm32u5",
"embed/sys/linker/inc",
"embed/sys/mpu/inc", "embed/sys/mpu/inc",
"embed/sys/pvd/inc", "embed/sys/pvd/inc",
"embed/sys/startup/inc", "embed/sys/startup/inc",
@ -84,6 +85,7 @@ def stm32u5_common_files(env, defines, sources, paths):
"embed/sec/secret/stm32u5/secret.c", "embed/sec/secret/stm32u5/secret.c",
"embed/sec/secure_aes/stm32u5/secure_aes.c", "embed/sec/secure_aes/stm32u5/secure_aes.c",
"embed/sec/time_estimate/stm32/time_estimate.c", "embed/sec/time_estimate/stm32/time_estimate.c",
"embed/sys/linker/linker_utils.c",
"embed/sys/mpu/stm32u5/mpu.c", "embed/sys/mpu/stm32u5/mpu.c",
"embed/sys/pvd/stm32/pvd.c", "embed/sys/pvd/stm32/pvd.c",
"embed/sys/startup/stm32/bootutils.c", "embed/sys/startup/stm32/bootutils.c",