mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-07 05:02:38 +00:00
refactor(core): rewrite startup code in C
[no changelog]
This commit is contained in:
parent
70c577b67b
commit
95afa34f27
@ -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',
|
||||
]
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
]
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "ports/stm32/gccollect.h"
|
||||
#include "ports/stm32/pendsv.h"
|
||||
|
||||
#include <sys/linker_utils.h>
|
||||
#include <sys/systask.h>
|
||||
#include <sys/system.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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
95
core/embed/sys/linker/inc/sys/linker_utils.h
Normal file
95
core/embed/sys/linker/inc/sys/linker_utils.h
Normal 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, §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); \
|
||||
}
|
195
core/embed/sys/linker/linker_utils.c
Normal file
195
core/embed/sys/linker/linker_utils.c
Normal 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 = ®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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -43,6 +43,12 @@ typedef union {
|
||||
|
||||
} 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.
|
||||
// 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);
|
||||
|
@ -81,6 +81,15 @@ void bootargs_get_args(boot_args_t* dest) {
|
||||
|
||||
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
|
||||
|
||||
// Deletes all secrets and SRAM2 where stack is located
|
||||
|
@ -21,7 +21,10 @@
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <sec/rng.h>
|
||||
#include <sys/bootargs.h>
|
||||
#include <sys/bootutils.h>
|
||||
#include <sys/linker_utils.h>
|
||||
#include <sys/system.h>
|
||||
#include <sys/systick.h>
|
||||
#include "startup_init.h"
|
||||
|
||||
@ -250,4 +253,65 @@ __attribute((used)) void clear_otg_hs_memory(void) {
|
||||
// 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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -21,6 +21,9 @@
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <sec/rng.h>
|
||||
#include <sys/bootargs.h>
|
||||
#include <sys/linker_utils.h>
|
||||
#include <sys/system.h>
|
||||
|
||||
#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,61 @@ void SystemInit(void) {
|
||||
__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(®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
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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,6 +67,7 @@ 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",
|
||||
|
@ -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,6 +85,7 @@ 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",
|
||||
|
Loading…
Reference in New Issue
Block a user