Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Startup/shutdown refactoring #4499

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions core/SConscript.boardloader
Original file line number Diff line number Diff line change
Expand Up @@ -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',
]

Expand Down
3 changes: 0 additions & 3 deletions core/SConscript.bootloader
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 0 additions & 3 deletions core/SConscript.bootloader_ci
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 0 additions & 3 deletions core/SConscript.firmware
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 0 additions & 3 deletions core/SConscript.kernel
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 0 additions & 4 deletions core/SConscript.prodtest
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 0 additions & 3 deletions core/SConscript.reflash
Original file line number Diff line number Diff line change
Expand Up @@ -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',
]
Expand Down
9 changes: 0 additions & 9 deletions core/embed/io/display/ltdc_dsi/display_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
3 changes: 1 addition & 2 deletions core/embed/projects/boardloader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -330,7 +329,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;
}
9 changes: 6 additions & 3 deletions core/embed/projects/bootloader/emulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <io/display.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h>
#include <sys/systick.h>
#include <util/flash.h>
#include <util/flash_otp.h>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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]);

Expand Down
2 changes: 0 additions & 2 deletions core/embed/projects/bootloader/emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,4 @@

extern uint8_t *FIRMWARE_START;

__attribute__((noreturn)) void jump_to(uint32_t address);

#endif
4 changes: 2 additions & 2 deletions core/embed/projects/bootloader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ static void drivers_deinit(void) {
#endif
#endif
display_deinit(DISPLAY_JUMP_BEHAVIOR);
ensure_compatible_settings();
}

static void usb_init_all(secbool usb21_landing) {
Expand Down Expand Up @@ -379,7 +378,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
Expand Down
3 changes: 2 additions & 1 deletion core/embed/projects/bootloader_ci/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
25 changes: 23 additions & 2 deletions core/embed/projects/firmware/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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];
Expand Down Expand Up @@ -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);
}
12 changes: 6 additions & 6 deletions core/embed/projects/kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
7 changes: 2 additions & 5 deletions core/embed/sec/random_delays/stm32/random_delays.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
Expand Down
4 changes: 4 additions & 0 deletions core/embed/sys/bsp/stm32f4/stm32f4xx_hal_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
99 changes: 99 additions & 0 deletions core/embed/sys/linker/inc/sys/linker_utils.h
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

#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;
TychoVrahe marked this conversation as resolved.
Show resolved Hide resolved

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) \
TychoVrahe marked this conversation as resolved.
Show resolved Hide resolved
{ \
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); \
}
Loading
Loading