From 6f762a05e9e8590730c9cdd3fe8f8908a3fae47f Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 20 Jun 2024 12:43:04 +0200 Subject: [PATCH 01/44] refactor(core/embed): remove unnecessary pendsv exception handling [no changelog] --- core/SConscript.firmware | 1 - core/embed/extmod/modtrezorio/modtrezorio-vcp.h | 4 +--- core/embed/firmware/main.c | 1 - core/embed/trezorhal/stm32f4/irq.h | 5 +---- core/embed/trezorhal/unix/usb.c | 2 -- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 2431309f022..b2a6abcc8a4 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -295,7 +295,6 @@ SOURCE_MICROPYTHON = [ 'vendor/micropython/shared/runtime/stdout_helpers.c', 'vendor/micropython/shared/timeutils/timeutils.c', 'vendor/micropython/ports/stm32/gccollect.c', - 'vendor/micropython/ports/stm32/pendsv.c', 'vendor/micropython/py/argcheck.c', 'vendor/micropython/py/asmarm.c', 'vendor/micropython/py/asmbase.c', diff --git a/core/embed/extmod/modtrezorio/modtrezorio-vcp.h b/core/embed/extmod/modtrezorio/modtrezorio-vcp.h index d063ba143d1..fc9ae5261fe 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-vcp.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-vcp.h @@ -17,8 +17,6 @@ * along with this program. If not, see . */ -void pendsv_kbd_intr(void); - /// package: trezorio.__init__ /// class VCP: @@ -93,7 +91,7 @@ STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type, o->info.rx_buffer = m_new(uint8_t, vcp_buffer_len); o->info.tx_buffer_len = vcp_buffer_len; o->info.rx_buffer_len = vcp_buffer_len; - o->info.rx_intr_fn = pendsv_kbd_intr; + o->info.rx_intr_fn = NULL; o->info.rx_intr_byte = 3; // Ctrl-C o->info.iface_num = (uint8_t)(iface_num); o->info.data_iface_num = (uint8_t)(data_iface_num); diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index fc59514d3c6..cd19d380997 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -187,7 +187,6 @@ int main(void) { #endif // Init peripherals - pendsv_init(); fault_handlers_init(); diff --git a/core/embed/trezorhal/stm32f4/irq.h b/core/embed/trezorhal/stm32f4/irq.h index 319755f1c5a..6d1fe0b0a40 100644 --- a/core/embed/trezorhal/stm32f4/irq.h +++ b/core/embed/trezorhal/stm32f4/irq.h @@ -155,10 +155,7 @@ static inline void restore_irq_pri(uint32_t state) { #define IRQ_PRI_EXTINT NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0) -// PENDSV should be at the lowst priority so that other interrupts complete -// before exception is raised. -#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) -#define IRQ_PRI_RTC_WKUP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) +//?#define IRQ_PRI_RTC_WKUP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) // !@# TAMPER interrupt priority should be probably much higher #define IRQ_PRI_TAMP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) diff --git a/core/embed/trezorhal/unix/usb.c b/core/embed/trezorhal/unix/usb.c index f5c1a00e754..e57f5120cb7 100644 --- a/core/embed/trezorhal/unix/usb.c +++ b/core/embed/trezorhal/unix/usb.c @@ -280,8 +280,6 @@ int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, return usb_webusb_write(iface_num, buf, len); } -void pendsv_kbd_intr(void) {} - void mp_hal_set_vcp_iface(int iface_num) {} secbool usb_configured(void) { From b7e2537d1738157125ef4913364704f408415cc0 Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 20 Jun 2024 12:48:48 +0200 Subject: [PATCH 02/44] refactor(core/embed): remove unnecessary sync from sdcard driver [no changelog] --- core/embed/trezorhal/stm32f4/sdcard.c | 10 ---------- core/embed/trezorhal/stm32u5/sdcard.c | 9 --------- 2 files changed, 19 deletions(-) diff --git a/core/embed/trezorhal/stm32f4/sdcard.c b/core/embed/trezorhal/stm32f4/sdcard.c index 75d46a9a818..443737abe61 100644 --- a/core/embed/trezorhal/stm32f4/sdcard.c +++ b/core/embed/trezorhal/stm32f4/sdcard.c @@ -298,9 +298,6 @@ secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, HAL_StatusTypeDef err = HAL_OK; - // we must disable USB irqs to prevent MSC contention with SD card - uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); - sd_dma.Instance = DMA2_Stream3; sd_dma.State = HAL_DMA_STATE_RESET; sd_dma.Init.Channel = DMA_CHANNEL_4; @@ -340,8 +337,6 @@ secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, HAL_DMA_DeInit(&sd_dma); sd_handle.hdmarx = NULL; - restore_irq_pri(basepri); - return sectrue * (err == HAL_OK); } @@ -359,9 +354,6 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, HAL_StatusTypeDef err = HAL_OK; - // we must disable USB irqs to prevent MSC contention with SD card - uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); - sd_dma.Instance = DMA2_Stream3; sd_dma.State = HAL_DMA_STATE_RESET; sd_dma.Init.Channel = DMA_CHANNEL_4; @@ -401,7 +393,5 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, HAL_DMA_DeInit(&sd_dma); sd_handle.hdmatx = NULL; - restore_irq_pri(basepri); - return sectrue * (err == HAL_OK); } diff --git a/core/embed/trezorhal/stm32u5/sdcard.c b/core/embed/trezorhal/stm32u5/sdcard.c index 1f8d22c57e0..c54e7ebaf17 100644 --- a/core/embed/trezorhal/stm32u5/sdcard.c +++ b/core/embed/trezorhal/stm32u5/sdcard.c @@ -301,16 +301,12 @@ secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, HAL_StatusTypeDef err = HAL_OK; - // we must disable USB irqs to prevent MSC contention with SD card - uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); - sdcard_reset_periph(); err = HAL_SD_ReadBlocks_DMA(&sd_handle, (uint8_t *)dest, block_num, num_blocks); if (err == HAL_OK) { err = sdcard_wait_finished(&sd_handle, 5000); } - restore_irq_pri(basepri); return sectrue * (err == HAL_OK); } @@ -329,9 +325,6 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, HAL_StatusTypeDef err = HAL_OK; - // we must disable USB irqs to prevent MSC contention with SD card - uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); - sdcard_reset_periph(); err = HAL_SD_WriteBlocks_DMA(&sd_handle, (uint8_t *)src, block_num, num_blocks); @@ -339,7 +332,5 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, err = sdcard_wait_finished(&sd_handle, 5000); } - restore_irq_pri(basepri); - return sectrue * (err == HAL_OK); } From 121eb955b4adaab50164113f8795e624f50668ae Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 20 Jun 2024 12:43:35 +0200 Subject: [PATCH 03/44] refactor(core/embed): simplify irq priorities [no changelog] --- core/embed/bootloader/main.c | 5 +- core/embed/firmware/delay.c | 6 +- core/embed/firmware/main.c | 2 + core/embed/prodtest/main.c | 1 + .../trezorhal/stm32f4/displays/st7789v.c | 4 +- core/embed/trezorhal/stm32f4/irq.h | 166 ++++-------------- core/embed/trezorhal/stm32f4/sdcard.c | 2 +- core/embed/trezorhal/stm32f4/sdram.c | 7 +- core/embed/trezorhal/stm32f4/supervise.c | 18 +- core/embed/trezorhal/stm32f4/supervise.h | 9 +- core/embed/trezorhal/stm32f4/usb/usbd_conf.c | 4 +- .../stm32f4/xdisplay/st-7789/display_fb.c | 4 +- .../stm32f4/xdisplay/st-7789/display_io.c | 4 +- core/embed/trezorhal/stm32u5/bg_copy.c | 8 +- core/embed/trezorhal/stm32u5/displays/dsi.c | 34 ++-- core/embed/trezorhal/stm32u5/hash_processor.c | 4 +- core/embed/trezorhal/stm32u5/sdcard.c | 2 +- .../trezorhal/stm32u5/stm32u5xx_hal_conf.h | 8 +- core/embed/trezorhal/stm32u5/tamper.c | 2 +- core/embed/trezorhal/stm32u5/touch/sitronix.c | 5 +- core/embed/trezorhal/stm32u5/trustzone.c | 5 +- .../xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c | 34 ++-- 22 files changed, 124 insertions(+), 210 deletions(-) diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 211916c682e..72374efea30 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -62,6 +62,9 @@ #ifdef USE_HASH_PROCESSOR #include "hash_processor.h" #endif +#ifdef STM32U5 +#include "irq.h" +#endif #include "model.h" #include "usb.h" @@ -339,7 +342,7 @@ __attribute__((noreturn)) void jump_to_fw_through_reset(void) { display_finish_actions(); display_fade(display_backlight(-1), 0, 200); - __disable_irq(); + disable_irq(); delete_secrets(); NVIC_SystemReset(); for (;;) diff --git a/core/embed/firmware/delay.c b/core/embed/firmware/delay.c index 0c4c267c322..a3d6da32a9c 100644 --- a/core/embed/firmware/delay.c +++ b/core/embed/firmware/delay.c @@ -55,7 +55,7 @@ extern __IO uint32_t uwTick; // and works when interrupts are disabled. This function is intended to be // used only by the ST HAL functions. void HAL_Delay(uint32_t Delay) { - if (query_irq() == IRQ_STATE_ENABLED) { + if (IS_IRQ_ENABLED(query_irq())) { // IRQs enabled, so can use systick counter to do the delay uint32_t start = uwTick; // Wraparound of tick is taken care of by 2's complement arithmetic. @@ -72,7 +72,7 @@ void HAL_Delay(uint32_t Delay) { // Core delay function that does an efficient sleep and may switch thread context. // If IRQs are enabled then we must have the GIL. void mp_hal_delay_ms(mp_uint_t Delay) { - if (query_irq() == IRQ_STATE_ENABLED) { + if (IS_IRQ_ENABLED(query_irq())) { // IRQs enabled, so can use systick counter to do the delay uint32_t start = uwTick; // Wraparound of tick is taken care of by 2's complement arithmetic. @@ -95,7 +95,7 @@ void mp_hal_delay_ms(mp_uint_t Delay) { // delay for given number of microseconds void mp_hal_delay_us(mp_uint_t usec) { - if (query_irq() == IRQ_STATE_ENABLED) { + if (IS_IRQ_ENABLED(query_irq())) { // IRQs enabled, so can use systick counter to do the delay uint32_t start = mp_hal_ticks_us(); while (mp_hal_ticks_us() - start < usec) { diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index cd19d380997..8c1c55525b9 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -130,6 +130,8 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data, #endif int main(void) { + svc_init(); + random_delays_init(); #ifdef RDI diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 2d35986e057..433c591a33b 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -776,6 +776,7 @@ void cpuid_read(void) { #define BACKLIGHT_NORMAL 150 int main(void) { + svc_init(); display_reinit(); display_orientation(0); random_delays_init(); diff --git a/core/embed/trezorhal/stm32f4/displays/st7789v.c b/core/embed/trezorhal/stm32f4/displays/st7789v.c index 35a68129148..5ab1adb0fa0 100644 --- a/core/embed/trezorhal/stm32f4/displays/st7789v.c +++ b/core/embed/trezorhal/stm32f4/displays/st7789v.c @@ -384,7 +384,7 @@ void display_setup_te_interrupt(void) { HAL_EXTI_SetConfigLine(&EXTI_Handle, &EXTI_Config); // setup interrupt for tearing effect pin - HAL_NVIC_SetPriority(DISPLAY_TE_INTERRUPT_NUM, IRQ_PRI_DMA, 0); + NVIC_SetPriority(DISPLAY_TE_INTERRUPT_NUM, IRQ_PRI_NORMAL); #endif } #endif @@ -564,7 +564,7 @@ void display_sync(void) {} #ifndef BOARDLOADER void DISPLAY_TE_INTERRUPT_HANDLER(void) { - HAL_NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM); + NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM); if (act_frame_buffer == 1) { bg_copy_start_const_out_8((uint8_t *)PhysFrameBuffer1, diff --git a/core/embed/trezorhal/stm32f4/irq.h b/core/embed/trezorhal/stm32f4/irq.h index 6d1fe0b0a40..b237d7b0882 100644 --- a/core/embed/trezorhal/stm32f4/irq.h +++ b/core/embed/trezorhal/stm32f4/irq.h @@ -1,50 +1,33 @@ -// clang-format off - /* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) + * This file is part of the Trezor project, https://trezor.io/ * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) SatoshiLabs * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * 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. * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * 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. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ -#ifndef MICROPY_INCLUDED_STM32_IRQ_H -#define MICROPY_INCLUDED_STM32_IRQ_H + +#ifndef TREZORHAL_IRQ_H +#define TREZORHAL_IRQ_H #include STM32_HAL_H #include -// Use this macro together with NVIC_SetPriority to indicate that an IRQn is non-negative, -// which helps the compiler optimise the resulting inline function. -#define IRQn_NONNEG(pri) ((pri) & 0x7f) - -// these states correspond to values from query_irq, enable_irq and disable_irq -#define IRQ_STATE_DISABLED (0x00000001) -#define IRQ_STATE_ENABLED (0x00000000) - -// Enable this to get a count for the number of times each irq handler is called, -// accessible via pyb.irq_stats(). +// Enables simple IRQ statistics for debugging #define IRQ_ENABLE_STATS (0) #if IRQ_ENABLE_STATS -#define IRQ_STATS_MAX (128) +#define IRQ_STATS_MAX (128) extern uint32_t irq_stats[IRQ_STATS_MAX]; #define IRQ_ENTER(irq) ++irq_stats[irq] #define IRQ_EXIT(irq) @@ -53,111 +36,34 @@ extern uint32_t irq_stats[IRQ_STATS_MAX]; #define IRQ_EXIT(irq) #endif -static inline uint32_t query_irq(void) { - return __get_PRIMASK(); -} +// Checks if interrupts are enabled +#define IS_IRQ_ENABLED(state) (((state) & 1) == 0) -static inline void enable_irq(uint32_t state) { - __set_PRIMASK(state); -} +// Get the current value of the CPU's exception mask register. +// The least significant bit indicates if interrupts are enabled or disabled. +static inline uint32_t query_irq(void) { return __get_PRIMASK(); } + +// Restore the CPU's exception mask register to a previous state +static inline void enable_irq(uint32_t state) { __set_PRIMASK(state); } +// Disable all interrupts and return the current state of the +// CPU's exception mask register static inline uint32_t disable_irq(void) { uint32_t state = __get_PRIMASK(); __disable_irq(); return state; } -// enable_irq and disable_irq are defined inline in mpconfigport.h - -#if __CORTEX_M >= 0x03 - -// irqs with a priority value greater or equal to "pri" will be disabled -// "pri" should be between 1 and 15 inclusive -static inline uint32_t raise_irq_pri(uint32_t pri) { - uint32_t basepri = __get_BASEPRI(); - // If non-zero, the processor does not process any exception with a - // priority value greater than or equal to BASEPRI. - // When writing to BASEPRI_MAX the write goes to BASEPRI only if either: - // - Rn is non-zero and the current BASEPRI value is 0 - // - Rn is non-zero and less than the current BASEPRI value - pri <<= (8 - __NVIC_PRIO_BITS); - __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); - return basepri; -} - -// "basepri" should be the value returned from raise_irq_pri -static inline void restore_irq_pri(uint32_t basepri) { - __set_BASEPRI(basepri); -} - -#else - -static inline uint32_t raise_irq_pri(uint32_t pri) { - return disable_irq(); -} - -// "state" should be the value returned from raise_irq_pri -static inline void restore_irq_pri(uint32_t state) { - enable_irq(state); -} - -#endif - -// IRQ priority definitions. -// -// Lower number implies higher interrupt priority. -// -// The default priority grouping is set to NVIC_PRIORITYGROUP_4 in the -// HAL_Init function. This corresponds to 4 bits for the priority field -// and 0 bits for the sub-priority field (which means that for all intensive -// purposes that the sub-priorities below are ignored). -// -// While a given interrupt is being processed, only higher priority (lower number) -// interrupts will preempt a given interrupt. If sub-priorities are active -// then the sub-priority determines the order that pending interrupts of -// a given priority are executed. This is only meaningful if 2 or more -// interrupts of the same priority are pending at the same time. -// -// The priority of the SysTick timer is determined from the TICK_INT_PRIORITY -// value which is normally set to 0 in the stm32f4xx_hal_conf.h file. -// -// The following interrupts are arranged from highest priority to lowest -// priority to make it a bit easier to figure out. - -//#def IRQ_PRI_SYSTICK NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 0, 0) - -// The UARTs have no FIFOs, so if they don't get serviced quickly then characters -// get dropped. The handling for each character only consumes about 0.5 usec -#define IRQ_PRI_UART NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 1, 0) - -// SDIO must be higher priority than DMA for SDIO DMA transfers to work. -#define IRQ_PRI_SDIO NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 4, 0) - -// DMA should be higher priority than USB, since USB Mass Storage calls -// into the sdcard driver which waits for the DMA to complete. -#define IRQ_PRI_DMA NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 5, 0) - -// Flash IRQ (used for flushing storage cache) must be at the same priority as -// the USB IRQs, so that the IRQ priority can be raised to this level to disable -// both the USB and cache flushing, when storage transfers are in progress. -#define IRQ_PRI_FLASH NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) - -#define IRQ_PRI_OTG_FS NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) -#define IRQ_PRI_OTG_HS NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) -#define IRQ_PRI_TIM5 NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) - -#define IRQ_PRI_CAN NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) - -#define IRQ_PRI_SPI NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 8, 0) - -// Interrupt priority for non-special timers. -#define IRQ_PRI_TIMX NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 13, 0) +// IRQ priority levels used throughout the system -#define IRQ_PRI_EXTINT NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0) +// Highest priority in the system (only RESET, NMI, and +// HardFault can preempt exceptions at this priority level) +#define IRQ_PRI_HIGHEST NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 0, 0) -//?#define IRQ_PRI_RTC_WKUP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) +// Standard priority for common interrupt handlers +#define IRQ_PRI_NORMAL NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 8, 0) -// !@# TAMPER interrupt priority should be probably much higher -#define IRQ_PRI_TAMP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) +// Lowest priority in the system used by SVC and PENDSV exception handlers +#define IRQ_PRI_LOWEST NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) -#endif // MICROPY_INCLUDED_STM32_IRQ_H +#endif // TREZORHAL_IRQ_H diff --git a/core/embed/trezorhal/stm32f4/sdcard.c b/core/embed/trezorhal/stm32f4/sdcard.c index 443737abe61..f308dd12652 100644 --- a/core/embed/trezorhal/stm32f4/sdcard.c +++ b/core/embed/trezorhal/stm32f4/sdcard.c @@ -134,7 +134,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { SDMMC_CLK_ENABLE(); // NVIC configuration for SDIO interrupts - svc_setpriority(SDMMC_IRQn, IRQ_PRI_SDIO); + svc_setpriority(SDMMC_IRQn, IRQ_PRI_NORMAL); svc_enableIRQ(SDMMC_IRQn); } diff --git a/core/embed/trezorhal/stm32f4/sdram.c b/core/embed/trezorhal/stm32f4/sdram.c index 0c9102d63c4..7c32bb1cf07 100644 --- a/core/embed/trezorhal/stm32f4/sdram.c +++ b/core/embed/trezorhal/stm32f4/sdram.c @@ -19,6 +19,7 @@ /* Includes ------------------------------------------------------------------*/ #include "sdram.h" +#include "irq.h" /** @addtogroup BSP * @{ @@ -397,8 +398,8 @@ void BSP_SDRAM_MspInit(SDRAM_HandleTypeDef *hsdram, void *Params) { HAL_DMA_Init(&dmaHandle); /* NVIC configuration for DMA transfer complete interrupt */ - HAL_NVIC_SetPriority(SDRAM_DMAx_IRQn, 0x0F, 0); - HAL_NVIC_EnableIRQ(SDRAM_DMAx_IRQn); + NVIC_SetPriority(SDRAM_DMAx_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(SDRAM_DMAx_IRQn); } /* of if(hsdram != (SDRAM_HandleTypeDef *)NULL) */ } @@ -413,7 +414,7 @@ void BSP_SDRAM_MspDeInit(SDRAM_HandleTypeDef *hsdram, void *Params) { if (hsdram != (SDRAM_HandleTypeDef *)NULL) { /* Disable NVIC configuration for DMA interrupt */ - HAL_NVIC_DisableIRQ(SDRAM_DMAx_IRQn); + NVIC_DisableIRQ(SDRAM_DMAx_IRQn); /* Deinitialize the stream for new transfer */ dma_handle.Instance = SDRAM_DMAx_STREAM; diff --git a/core/embed/trezorhal/stm32f4/supervise.c b/core/embed/trezorhal/stm32f4/supervise.c index 0ca4483062a..d34806d08f1 100644 --- a/core/embed/trezorhal/stm32f4/supervise.c +++ b/core/embed/trezorhal/stm32f4/supervise.c @@ -5,16 +5,26 @@ #include "../mpu.h" #include "common.h" #include "display.h" +#include "irq.h" #include "supervise.h" #ifdef ARM_USER_MODE +void svc_init(void) { + NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_HIGHEST); + + // We need to ensure that SysTick has the expected priority. + // The SysTick priority is configured in the boardloader, + // and some early versions didn't set this properly. + NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_HIGHEST); +} + #ifdef STM32U5 extern uint32_t g_boot_command; __attribute__((noreturn)) static void _reboot_to_bootloader( boot_command_t boot_command) { g_boot_command = boot_command; - __disable_irq(); + disable_irq(); delete_secrets(); NVIC_SystemReset(); } @@ -54,10 +64,10 @@ void SVC_C_Handler(uint32_t *stack) { uint8_t svc_number = ((uint8_t *)stack[6])[-2]; switch (svc_number) { case SVC_ENABLE_IRQ: - HAL_NVIC_EnableIRQ(stack[0]); + NVIC_EnableIRQ(stack[0]); break; case SVC_DISABLE_IRQ: - HAL_NVIC_DisableIRQ(stack[0]); + NVIC_DisableIRQ(stack[0]); break; case SVC_SET_PRIORITY: NVIC_SetPriority(stack[0], stack[1]); @@ -106,7 +116,7 @@ void SVC_C_Handler(uint32_t *stack) { __attribute__((naked)) void SVC_Handler(void) { __asm volatile( " tst lr, #4 \n" // Test Bit 3 to see which stack pointer we should - // use. + // use " ite eq \n" // Tell the assembler that the nest 2 instructions // are if-then-else " mrseq r0, msp \n" // Make R0 point to main stack pointer diff --git a/core/embed/trezorhal/stm32f4/supervise.h b/core/embed/trezorhal/stm32f4/supervise.h index 9affd8b770b..664939426cf 100644 --- a/core/embed/trezorhal/stm32f4/supervise.h +++ b/core/embed/trezorhal/stm32f4/supervise.h @@ -20,6 +20,11 @@ extern uint32_t systick_val_copy; extern void shutdown_privileged(void); extern void ensure_compatible_settings(void); +// Initializes the supervise module +// +// Must be called before invoking the first `svc_xxx` call +void svc_init(void); + static inline uint32_t is_mode_unprivileged(void) { uint32_t r0; __asm__ volatile("mrs %0, control" : "=r"(r0)); @@ -37,7 +42,7 @@ static inline void svc_enableIRQ(uint32_t IRQn) { register uint32_t r0 __asm__("r0") = IRQn; __asm__ __volatile__("svc %0" ::"i"(SVC_ENABLE_IRQ), "r"(r0) : "memory"); } else { - HAL_NVIC_EnableIRQ(IRQn); + NVIC_EnableIRQ(IRQn); } } @@ -46,7 +51,7 @@ static inline void svc_disableIRQ(uint32_t IRQn) { register uint32_t r0 __asm__("r0") = IRQn; __asm__ __volatile__("svc %0" ::"i"(SVC_DISABLE_IRQ), "r"(r0) : "memory"); } else { - HAL_NVIC_DisableIRQ(IRQn); + NVIC_DisableIRQ(IRQn); } } diff --git a/core/embed/trezorhal/stm32f4/usb/usbd_conf.c b/core/embed/trezorhal/stm32f4/usb/usbd_conf.c index 0434962d3a1..452adf4170d 100644 --- a/core/embed/trezorhal/stm32f4/usb/usbd_conf.c +++ b/core/embed/trezorhal/stm32f4/usb/usbd_conf.c @@ -147,7 +147,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) #endif /* Set USBFS Interrupt priority */ - svc_setpriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS); + svc_setpriority(OTG_FS_IRQn, IRQ_PRI_NORMAL); /* Enable USBFS Interrupt */ svc_enableIRQ(OTG_FS_IRQn); @@ -302,7 +302,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) #endif // !USE_USB_HS_IN_FS /* Set USBHS Interrupt to the lowest priority */ - svc_setpriority(OTG_HS_IRQn, IRQ_PRI_OTG_HS); + svc_setpriority(OTG_HS_IRQn, IRQ_PRI_NORMAL); /* Enable USBHS Interrupt */ svc_enableIRQ(OTG_HS_IRQn); diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c index a0e89d1bd22..fe3ae1d17f6 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c @@ -200,7 +200,7 @@ void display_refresh(void) { #ifndef BOARDLOADER if (is_mode_handler()) { // Disable scheduling of any new background copying - HAL_NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM); + NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM); // Wait for next TE signal. During this time the // display might be updated in the background wait_for_te_signal(); @@ -216,7 +216,7 @@ void display_refresh(void) { drv->queue.entry[i] = FB_STATE_EMPTY; } // Enable normal processing again - HAL_NVIC_EnableIRQ(DISPLAY_TE_INTERRUPT_NUM); + NVIC_EnableIRQ(DISPLAY_TE_INTERRUPT_NUM); } else { // Mark the buffer ready to switch to drv->queue.entry[drv->queue.wix] = FB_STATE_READY; diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c index edb12ef49c3..57d2baf88e7 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c @@ -142,7 +142,7 @@ void display_io_init_te_interrupt(void) { HAL_EXTI_SetConfigLine(&EXTI_Handle, &EXTI_Config); // setup interrupt for tearing effect pin - HAL_NVIC_SetPriority(DISPLAY_TE_INTERRUPT_NUM, IRQ_PRI_DMA, 0); - svc_enableIRQ(DISPLAY_TE_INTERRUPT_NUM); + NVIC_SetPriority(DISPLAY_TE_INTERRUPT_NUM, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(DISPLAY_TE_INTERRUPT_NUM); } #endif diff --git a/core/embed/trezorhal/stm32u5/bg_copy.c b/core/embed/trezorhal/stm32u5/bg_copy.c index 97c2b6b66e9..4a81f299639 100644 --- a/core/embed/trezorhal/stm32u5/bg_copy.c +++ b/core/embed/trezorhal/stm32u5/bg_copy.c @@ -44,7 +44,7 @@ void GPDMA1_Channel0_IRQHandler(void) { if (dma_transfer_remaining == 0) { // transfer finished, disable the channel HAL_DMA_DeInit(&DMA_Handle); - HAL_NVIC_DisableIRQ(GPDMA1_Channel0_IRQn); + NVIC_DisableIRQ(GPDMA1_Channel0_IRQn); data_src = NULL; data_dst = NULL; @@ -97,8 +97,8 @@ void bg_copy_start_const_out_8(const uint8_t *src, uint8_t *dst, size_t size, DMA_CHANNEL_SRC_SEC | DMA_CHANNEL_DEST_SEC); - HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, IRQ_PRI_DMA, 0); - HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn); + NVIC_SetPriority(GPDMA1_Channel0_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(GPDMA1_Channel0_IRQn); HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)src, (uint32_t)dst, data_to_send); } @@ -108,7 +108,7 @@ void bg_copy_abort(void) { dma_data_transferred = 0; HAL_DMA_Abort(&DMA_Handle); HAL_DMA_DeInit(&DMA_Handle); - HAL_NVIC_DisableIRQ(GPDMA1_Channel0_IRQn); + NVIC_DisableIRQ(GPDMA1_Channel0_IRQn); data_src = NULL; data_dst = NULL; } diff --git a/core/embed/trezorhal/stm32u5/displays/dsi.c b/core/embed/trezorhal/stm32u5/displays/dsi.c index 8e44fabb416..785f0567133 100644 --- a/core/embed/trezorhal/stm32u5/displays/dsi.c +++ b/core/embed/trezorhal/stm32u5/displays/dsi.c @@ -59,6 +59,7 @@ /* Includes ------------------------------------------------------------------*/ #include "colors.h" +#include "irq.h" #include "stdint.h" #include "string.h" #include STM32_HAL_H @@ -82,15 +83,6 @@ #define BSP_BUTTON_USER_IT_PRIORITY \ 0x0FUL /* Default is lowest priority level */ -/* LCD interrupt priorities */ -#define BSP_LCD_GFXMMU_IT_PRIORITY \ - 0x0FUL /* Default is lowest priority level \ - */ -#define BSP_LCD_LTDC_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ -#define BSP_LCD_DSI_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ - -/* HSPI RAM interrupt priority */ -#define BSP_HSPI_RAM_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ #define LCD_PIXEL_FORMAT_ARGB8888 \ 0x00000000U /*!< ARGB8888 LTDC pixel format \ */ @@ -1356,8 +1348,8 @@ static void GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu) { __HAL_RCC_GFXMMU_CLK_ENABLE(); /* Enable GFXMMU interrupt */ - HAL_NVIC_SetPriority(GFXMMU_IRQn, BSP_LCD_GFXMMU_IT_PRIORITY, 0); - HAL_NVIC_EnableIRQ(GFXMMU_IRQn); + NVIC_SetPriority(GFXMMU_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(GFXMMU_IRQn); } /** @@ -1370,7 +1362,7 @@ static void GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu) { UNUSED(hgfxmmu); /* Disable GFXMMU interrupt */ - HAL_NVIC_DisableIRQ(GFXMMU_IRQn); + NVIC_DisableIRQ(GFXMMU_IRQn); /* GFXMMU clock disable */ __HAL_RCC_GFXMMU_CLK_DISABLE(); @@ -1389,11 +1381,11 @@ static void LTDC_MspInit(LTDC_HandleTypeDef *hltdc) { __HAL_RCC_LTDC_CLK_ENABLE(); /* Enable LTDC interrupt */ - HAL_NVIC_SetPriority(LTDC_IRQn, BSP_LCD_LTDC_IT_PRIORITY, 0); - HAL_NVIC_EnableIRQ(LTDC_IRQn); + NVIC_SetPriority(LTDC_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(LTDC_IRQn); - HAL_NVIC_SetPriority(LTDC_ER_IRQn, BSP_LCD_LTDC_IT_PRIORITY, 0); - HAL_NVIC_EnableIRQ(LTDC_ER_IRQn); + NVIC_SetPriority(LTDC_ER_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(LTDC_ER_IRQn); } /** @@ -1406,8 +1398,8 @@ static void LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc) { UNUSED(hltdc); /* Disable LTDC interrupts */ - HAL_NVIC_DisableIRQ(LTDC_ER_IRQn); - HAL_NVIC_DisableIRQ(LTDC_IRQn); + NVIC_DisableIRQ(LTDC_ER_IRQn); + NVIC_DisableIRQ(LTDC_IRQn); /* LTDC clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); @@ -1514,8 +1506,8 @@ static void DSI_MspInit(DSI_HandleTypeDef *hdsi) { /* Enable DSI NVIC interrupt */ /* Default is lowest priority level */ - HAL_NVIC_SetPriority(DSI_IRQn, 0x0FUL, 0); - HAL_NVIC_EnableIRQ(DSI_IRQn); + NVIC_SetPriority(DSI_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(DSI_IRQn); } /** @@ -1550,7 +1542,7 @@ static void DSI_MspDeInit(DSI_HandleTypeDef *hdsi) { __HAL_RCC_DSI_RELEASE_RESET(); /* Disable DSI interrupts */ - HAL_NVIC_DisableIRQ(DSI_IRQn); + NVIC_DisableIRQ(DSI_IRQn); } void display_pixeldata(uint16_t c) { diff --git a/core/embed/trezorhal/stm32u5/hash_processor.c b/core/embed/trezorhal/stm32u5/hash_processor.c index 57993663af9..b9be38dbd97 100644 --- a/core/embed/trezorhal/stm32u5/hash_processor.c +++ b/core/embed/trezorhal/stm32u5/hash_processor.c @@ -40,8 +40,8 @@ void hash_processor_init(void) { DMA_Handle.Parent = &hhash; - HAL_NVIC_SetPriority(GPDMA1_Channel12_IRQn, IRQ_PRI_DMA, 0); - HAL_NVIC_EnableIRQ(GPDMA1_Channel12_IRQn); + NVIC_SetPriority(GPDMA1_Channel12_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(GPDMA1_Channel12_IRQn); } void GPDMA1_Channel12_IRQHandler(void) { HAL_DMA_IRQHandler(&DMA_Handle); } diff --git a/core/embed/trezorhal/stm32u5/sdcard.c b/core/embed/trezorhal/stm32u5/sdcard.c index c54e7ebaf17..1cfbc6522e2 100644 --- a/core/embed/trezorhal/stm32u5/sdcard.c +++ b/core/embed/trezorhal/stm32u5/sdcard.c @@ -138,7 +138,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { SDMMC_CLK_ENABLE(); // NVIC configuration for SDIO interrupts - svc_setpriority(SDMMC_IRQn, IRQ_PRI_SDIO); + svc_setpriority(SDMMC_IRQn, IRQ_PRI_NORMAL); svc_enableIRQ(SDMMC_IRQn); } diff --git a/core/embed/trezorhal/stm32u5/stm32u5xx_hal_conf.h b/core/embed/trezorhal/stm32u5/stm32u5xx_hal_conf.h index 203b2245c25..e5b411bd0f5 100644 --- a/core/embed/trezorhal/stm32u5/stm32u5xx_hal_conf.h +++ b/core/embed/trezorhal/stm32u5/stm32u5xx_hal_conf.h @@ -192,9 +192,8 @@ extern "C" { * @brief This is the HAL system configuration section */ -#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY \ - (15UL) /*!< tick interrupt priority (lowest by default) */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0UL /*!< tick interrupt priority */ #define USE_RTOS 0U #define PREFETCH_ENABLE 1U /*!< Enable prefetch */ @@ -554,7 +553,8 @@ extern "C" { */ #define assert_param(expr) \ ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ +/* Exported functions + ------------------------------------------------------- */ void assert_failed(uint8_t *file, uint32_t line); #else #define assert_param(expr) ((void)0U) diff --git a/core/embed/trezorhal/stm32u5/tamper.c b/core/embed/trezorhal/stm32u5/tamper.c index 6b74a54f483..9959aeaaa83 100644 --- a/core/embed/trezorhal/stm32u5/tamper.c +++ b/core/embed/trezorhal/stm32u5/tamper.c @@ -227,7 +227,7 @@ void tamper_init(void) { TAMP_IER_ITAMP11IE | TAMP_IER_ITAMP12IE | TAMP_IER_ITAMP13IE; // Enable TAMP interrupt at NVIC controller - NVIC_SetPriority(TAMP_IRQn, IRQ_PRI_TAMP); + NVIC_SetPriority(TAMP_IRQn, IRQ_PRI_HIGHEST); NVIC_EnableIRQ(TAMP_IRQn); } diff --git a/core/embed/trezorhal/stm32u5/touch/sitronix.c b/core/embed/trezorhal/stm32u5/touch/sitronix.c index b3f2c70e145..5cfb0a1f3e4 100644 --- a/core/embed/trezorhal/stm32u5/touch/sitronix.c +++ b/core/embed/trezorhal/stm32u5/touch/sitronix.c @@ -2,6 +2,7 @@ #include TREZOR_BOARD #include "i2c.h" +#include "irq.h" /** @addtogroup STM32U5x9J_DISCOVERY * @{ @@ -823,8 +824,8 @@ int32_t BSP_TS_EnableIT(uint32_t Instance) { HAL_GPIO_Init(TS_INT_GPIO_PORT, &gpio_init_structure); /* Enable and set Touch screen EXTI Interrupt to the lowest priority */ - HAL_NVIC_SetPriority((IRQn_Type)(TS_INT_EXTI_IRQn), 0x0F, 0x00); - HAL_NVIC_EnableIRQ((IRQn_Type)(TS_INT_EXTI_IRQn)); + NVIC_SetPriority((IRQn_Type)(TS_INT_EXTI_IRQn), IRQ_PRI_NORMAL); + NVIC_EnableIRQ((IRQn_Type)(TS_INT_EXTI_IRQn)); return BSP_ERROR_NONE; } diff --git a/core/embed/trezorhal/stm32u5/trustzone.c b/core/embed/trezorhal/stm32u5/trustzone.c index f77fbb4a159..047b06e880f 100644 --- a/core/embed/trezorhal/stm32u5/trustzone.c +++ b/core/embed/trezorhal/stm32u5/trustzone.c @@ -20,6 +20,7 @@ #include #include STM32_HAL_H +#include "irq.h" #ifdef BOARDLOADER @@ -142,8 +143,8 @@ void trustzone_init_boardloader(void) { HAL_GTZC_TZIC_EnableIT(GTZC_PERIPH_ALL); // Enable GTZC secure interrupt - HAL_NVIC_SetPriority(GTZC_IRQn, 0, 0); // Highest priority level - HAL_NVIC_EnableIRQ(GTZC_IRQn); + NVIC_SetPriority(GTZC_IRQn, IRQ_PRI_HIGHEST); + NVIC_EnableIRQ(GTZC_IRQn); } #endif // BOARDLOADER diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c index fb3e1163221..4f7dc55c98d 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c @@ -66,6 +66,7 @@ #include STM32_HAL_H #include "display_internal.h" +#include "irq.h" /* Common Error codes */ #define BSP_ERROR_NONE 0 @@ -86,15 +87,6 @@ #define BSP_BUTTON_USER_IT_PRIORITY \ 0x0FUL /* Default is lowest priority level */ -/* LCD interrupt priorities */ -#define BSP_LCD_GFXMMU_IT_PRIORITY \ - 0x0FUL /* Default is lowest priority level \ - */ -#define BSP_LCD_LTDC_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ -#define BSP_LCD_DSI_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ - -/* HSPI RAM interrupt priority */ -#define BSP_HSPI_RAM_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ #define LCD_PIXEL_FORMAT_ARGB8888 \ 0x00000000U /*!< ARGB8888 LTDC pixel format \ */ @@ -1336,8 +1328,8 @@ static void GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu) { __HAL_RCC_GFXMMU_CLK_ENABLE(); /* Enable GFXMMU interrupt */ - HAL_NVIC_SetPriority(GFXMMU_IRQn, BSP_LCD_GFXMMU_IT_PRIORITY, 0); - HAL_NVIC_EnableIRQ(GFXMMU_IRQn); + NVIC_SetPriority(GFXMMU_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(GFXMMU_IRQn); } /** @@ -1350,7 +1342,7 @@ static void GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu) { UNUSED(hgfxmmu); /* Disable GFXMMU interrupt */ - HAL_NVIC_DisableIRQ(GFXMMU_IRQn); + NVIC_DisableIRQ(GFXMMU_IRQn); /* GFXMMU clock disable */ __HAL_RCC_GFXMMU_CLK_DISABLE(); @@ -1369,11 +1361,11 @@ static void LTDC_MspInit(LTDC_HandleTypeDef *hltdc) { __HAL_RCC_LTDC_CLK_ENABLE(); /* Enable LTDC interrupt */ - HAL_NVIC_SetPriority(LTDC_IRQn, BSP_LCD_LTDC_IT_PRIORITY, 0); - HAL_NVIC_EnableIRQ(LTDC_IRQn); + NVIC_SetPriority(LTDC_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(LTDC_IRQn); - HAL_NVIC_SetPriority(LTDC_ER_IRQn, BSP_LCD_LTDC_IT_PRIORITY, 0); - HAL_NVIC_EnableIRQ(LTDC_ER_IRQn); + NVIC_SetPriority(LTDC_ER_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(LTDC_ER_IRQn); } /** @@ -1386,8 +1378,8 @@ static void LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc) { UNUSED(hltdc); /* Disable LTDC interrupts */ - HAL_NVIC_DisableIRQ(LTDC_ER_IRQn); - HAL_NVIC_DisableIRQ(LTDC_IRQn); + NVIC_DisableIRQ(LTDC_ER_IRQn); + NVIC_DisableIRQ(LTDC_IRQn); /* LTDC clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); @@ -1494,8 +1486,8 @@ static void DSI_MspInit(DSI_HandleTypeDef *hdsi) { /* Enable DSI NVIC interrupt */ /* Default is lowest priority level */ - HAL_NVIC_SetPriority(DSI_IRQn, 0x0FUL, 0); - HAL_NVIC_EnableIRQ(DSI_IRQn); + NVIC_SetPriority(DSI_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(DSI_IRQn); } /** @@ -1530,7 +1522,7 @@ static void DSI_MspDeInit(DSI_HandleTypeDef *hdsi) { __HAL_RCC_DSI_RELEASE_RESET(); /* Disable DSI interrupts */ - HAL_NVIC_DisableIRQ(DSI_IRQn); + NVIC_DisableIRQ(DSI_IRQn); } int32_t BSP_LCD_SetFrameBuffer(uint32_t Instance, uint32_t fb_addr) { From a8a8c1a8269b76e437e80b5a293c7feab81c479e Mon Sep 17 00:00:00 2001 From: cepetr Date: Fri, 31 May 2024 15:16:35 +0200 Subject: [PATCH 04/44] refactor(core/embed): improve display driver init/deinit [no changelog] --- core/embed/boardloader/main.c | 4 +- core/embed/bootloader/emulator.c | 2 +- core/embed/bootloader/main.c | 5 +- core/embed/firmware/main.c | 2 +- core/embed/prodtest/main.c | 3 +- core/embed/trezorhal/display.h | 21 ++- core/embed/trezorhal/stm32f4/common.c | 2 +- core/embed/trezorhal/stm32f4/displays/ltdc.c | 2 +- .../trezorhal/stm32f4/displays/st7789v.c | 2 +- .../stm32f4/displays/ug-2828tswig01.c | 2 +- .../stm32f4/displays/vg-2864ksweg01.c | 2 +- core/embed/trezorhal/stm32f4/supervise.c | 5 +- .../stm32f4/xdisplay/st-7789/display_driver.c | 43 +++--- .../stm32f429i-disc1/display_driver.c | 20 +-- .../stm32f4/xdisplay/ug-2828/display_driver.c | 23 ++- .../stm32f4/xdisplay/vg-2864/display_driver.c | 137 +++++++++--------- core/embed/trezorhal/stm32u5/common.c | 2 +- core/embed/trezorhal/stm32u5/displays/dsi.c | 2 +- .../xdisplay/stm32u5a9j-dk/display_driver.c | 75 +++++----- .../xdisplay/stm32u5a9j-dk/display_internal.h | 2 + .../xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c | 5 + core/embed/trezorhal/unix/display_driver.c | 46 +++--- core/embed/trezorhal/xdisplay.h | 30 ++-- core/embed/trezorhal/xdisplay_legacy.h | 10 +- core/embed/unix/main.c | 2 +- 25 files changed, 231 insertions(+), 218 deletions(-) diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index 6444fff90d2..9c07c2c2f0e 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -274,7 +274,8 @@ int main(void) { dma2d_init(); #endif - display_init(); + display_init(DISPLAY_RESET_CONTENT); + display_clear(); display_refresh(); @@ -324,6 +325,7 @@ int main(void) { // This includes the version of bootloader potentially updated from SD card. write_bootloader_min_version(hdr->monotonic); + display_deinit(DISPLAY_RETAIN_CONTENT); ensure_compatible_settings(); mpu_config_off(); diff --git a/core/embed/bootloader/emulator.c b/core/embed/bootloader/emulator.c index fb570b0c9b8..473357a22e8 100644 --- a/core/embed/bootloader/emulator.c +++ b/core/embed/bootloader/emulator.c @@ -92,7 +92,7 @@ bool load_firmware(const char *filename, uint8_t *hash) { } __attribute__((noreturn)) int main(int argc, char **argv) { - display_init(); + display_init(DISPLAY_RESET_CONTENT); flash_init(); flash_otp_init(); diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 72374efea30..4df0c964ef9 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -330,7 +330,7 @@ void real_jump_to_firmware(void) { ui_screen_boot_stage_1(false); } - display_finish_actions(); + display_deinit(DISPLAY_RETAIN_CONTENT); ensure_compatible_settings(); mpu_config_off(); @@ -339,7 +339,6 @@ void real_jump_to_firmware(void) { #ifdef STM32U5 __attribute__((noreturn)) void jump_to_fw_through_reset(void) { - display_finish_actions(); display_fade(display_backlight(-1), 0, 200); disable_irq(); @@ -371,7 +370,7 @@ int bootloader_main(void) { i2c_init(); #endif - display_reinit(); + display_init(DISPLAY_RETAIN_CONTENT); #ifdef USE_DMA2D dma2d_init(); diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 8c1c55525b9..357dcd5e158 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -155,7 +155,7 @@ int main(void) { dma2d_init(); #endif - display_reinit(); + display_init(DISPLAY_RETAIN_CONTENT); #ifdef STM32U5 check_oem_keys(); diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 433c591a33b..973e3e76cdc 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -777,8 +777,7 @@ void cpuid_read(void) { int main(void) { svc_init(); - display_reinit(); - display_orientation(0); + display_init(DISPLAY_RETAIN_CONTENT); random_delays_init(); #ifdef STM32U5 secure_aes_init(); diff --git a/core/embed/trezorhal/display.h b/core/embed/trezorhal/display.h index 5e296a8f751..38091eec6b5 100644 --- a/core/embed/trezorhal/display.h +++ b/core/embed/trezorhal/display.h @@ -63,7 +63,7 @@ int display_orientation(int degrees); int display_get_orientation(void); int display_backlight(int val); -void display_init(void); +void display_init_all(void); void display_reinit(void); void display_sync(void); void display_refresh(void); @@ -77,5 +77,24 @@ uint8_t *display_get_wr_addr(void); void display_shift_window(uint16_t pixels); uint16_t display_get_window_offset(void); +typedef enum { + // Clear the display content + DISPLAY_RESET_CONTENT, + // Keeps the display without any changes + DISPLAY_RETAIN_CONTENT +} display_content_mode_t; + +static inline void display_init(display_content_mode_t mode) { + if (mode == DISPLAY_RESET_CONTENT) { + display_init_all(); + } else { + display_reinit(); + } +} + +static inline void display_deinit(display_content_mode_t mode) { + display_finish_actions(); +} + #endif // NEW_RENDERING #endif // TREZORHAL_DISPLAY_H diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 88c397c27c8..dafde04c18f 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -42,7 +42,7 @@ uint32_t systick_val_copy = 0; extern void shutdown_privileged(void); void __attribute__((noreturn)) trezor_shutdown(void) { - display_finish_actions(); + display_deinit(DISPLAY_RETAIN_CONTENT); #ifdef USE_SVC_SHUTDOWN svc_shutdown(); #else diff --git a/core/embed/trezorhal/stm32f4/displays/ltdc.c b/core/embed/trezorhal/stm32f4/displays/ltdc.c index 93ee9659e2f..515106e74ab 100644 --- a/core/embed/trezorhal/stm32f4/displays/ltdc.c +++ b/core/embed/trezorhal/stm32f4/displays/ltdc.c @@ -221,7 +221,7 @@ int display_backlight(int val) { void display_init_seq(void) { display_unsleep(); } -void display_init(void) { +void display_init_all(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; /* Enable the LTDC and DMA2D Clock */ diff --git a/core/embed/trezorhal/stm32f4/displays/st7789v.c b/core/embed/trezorhal/stm32f4/displays/st7789v.c index 5ab1adb0fa0..0ece172800d 100644 --- a/core/embed/trezorhal/stm32f4/displays/st7789v.c +++ b/core/embed/trezorhal/stm32f4/displays/st7789v.c @@ -389,7 +389,7 @@ void display_setup_te_interrupt(void) { } #endif -void display_init(void) { +void display_init_all(void) { // init peripherals __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/core/embed/trezorhal/stm32f4/displays/ug-2828tswig01.c b/core/embed/trezorhal/stm32f4/displays/ug-2828tswig01.c index 4e09309a6fb..54c602e8000 100644 --- a/core/embed/trezorhal/stm32f4/displays/ug-2828tswig01.c +++ b/core/embed/trezorhal/stm32f4/displays/ug-2828tswig01.c @@ -270,7 +270,7 @@ void display_init_seq(void) { display_unsleep(); } -void display_init(void) { +void display_init_all(void) { // init peripherals __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); diff --git a/core/embed/trezorhal/stm32f4/displays/vg-2864ksweg01.c b/core/embed/trezorhal/stm32f4/displays/vg-2864ksweg01.c index e841854e76f..a7166a070f5 100644 --- a/core/embed/trezorhal/stm32f4/displays/vg-2864ksweg01.c +++ b/core/embed/trezorhal/stm32f4/displays/vg-2864ksweg01.c @@ -153,7 +153,7 @@ void display_handle_init(void) { spi_handle.Init.Mode = SPI_MODE_MASTER; } -void display_init(void) { +void display_init_all(void) { OLED_DC_CLK_ENA(); OLED_CS_CLK_ENA(); OLED_RST_CLK_ENA(); diff --git a/core/embed/trezorhal/stm32f4/supervise.c b/core/embed/trezorhal/stm32f4/supervise.c index d34806d08f1..83191ed08de 100644 --- a/core/embed/trezorhal/stm32f4/supervise.c +++ b/core/embed/trezorhal/stm32f4/supervise.c @@ -31,6 +31,8 @@ __attribute__((noreturn)) static void _reboot_to_bootloader( #else __attribute__((noreturn)) static void _reboot_to_bootloader( boot_command_t boot_command) { + display_deinit(DISPLAY_RETAIN_CONTENT); + ensure_compatible_settings(); mpu_config_bootloader(); jump_to_with_flag(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE), boot_command); @@ -40,14 +42,12 @@ __attribute__((noreturn)) static void _reboot_to_bootloader( #endif void svc_reboot_to_bootloader(void) { - display_finish_actions(); boot_command_t boot_command = bootargs_get_command(); if (is_mode_unprivileged() && !is_mode_handler()) { register uint32_t r0 __asm__("r0") = boot_command; __asm__ __volatile__("svc %0" ::"i"(SVC_REBOOT_TO_BOOTLOADER), "r"(r0) : "memory"); } else { - ensure_compatible_settings(); _reboot_to_bootloader(boot_command); } } @@ -83,7 +83,6 @@ void SVC_C_Handler(uint32_t *stack) { ; break; case SVC_REBOOT_TO_BOOTLOADER: - ensure_compatible_settings(); __asm__ volatile("msr control, %0" ::"r"(0x0)); __asm__ volatile("isb"); diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c index e486ebfaf3d..b49fcc0be44 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c @@ -43,40 +43,33 @@ // Display driver instance display_driver_t g_display_driver; -void display_init(void) { +void display_init(display_content_mode_t mode) { display_driver_t* drv = &g_display_driver; memset(drv, 0, sizeof(display_driver_t)); - display_io_init_gpio(); - display_io_init_fmc(); - display_panel_init(); - display_panel_set_little_endian(); - backlight_pwm_init(BACKLIGHT_RESET); - -#ifdef XFRAMEBUFFER - display_io_init_te_interrupt(); -#endif -} - -void display_reinit(void) { - display_driver_t* drv = &g_display_driver; - memset(drv, 0, sizeof(display_driver_t)); - - // Reinitialize FMC to set correct timing - // We have to do this in reinit because boardloader is fixed. - display_io_init_fmc(); - - // Important for model T as this is not set in boardloader - display_panel_set_little_endian(); - display_panel_reinit(); - backlight_pwm_init(BACKLIGHT_RETAIN); + if (mode == DISPLAY_RESET_CONTENT) { + display_io_init_gpio(); + display_io_init_fmc(); + display_panel_init(); + display_panel_set_little_endian(); + backlight_pwm_init(BACKLIGHT_RESET); + } else { + // Reinitialize FMC to set correct timing + // We have to do this in reinit because boardloader is fixed. + display_io_init_fmc(); + + // Important for model T as this is not set in boardloader + display_panel_set_little_endian(); + display_panel_reinit(); + backlight_pwm_init(BACKLIGHT_RETAIN); + } #ifdef XFRAMEBUFFER display_io_init_te_interrupt(); #endif } -void display_finish_actions(void) { +void display_deinit(display_content_mode_t mode) { #ifdef XFRAMEBUFFER #ifndef BOARDLOADER display_ensure_refreshed(); diff --git a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c index 378e63f7002..27fa3c13019 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c @@ -44,24 +44,20 @@ typedef struct { // Display driver instance static display_driver_t g_display_driver; -void display_init(void) { +void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; memset(drv, 0, sizeof(display_driver_t)); drv->framebuf = (uint16_t *)FRAME_BUFFER_ADDR; - // Initialize LTDC controller - BSP_LCD_Init(); - // Initialize external display controller - ili9341_init(); -} - -void display_reinit(void) { - display_driver_t *drv = &g_display_driver; - memset(drv, 0, sizeof(display_driver_t)); - drv->framebuf = (uint16_t *)FRAME_BUFFER_ADDR; + if (mode == DISPLAY_RESET_CONTENT) { + // Initialize LTDC controller + BSP_LCD_Init(); + // Initialize external display controller + ili9341_init(); + } } -void display_finish_actions(void) { +void display_deinit(display_content_mode_t mode) { // Not used and intentionally left empty } diff --git a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c index 7c2363713c9..9de46d12c38 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c @@ -291,25 +291,20 @@ static void display_init_interface(void) { HAL_SRAM_Init(&display_sram, &normal_mode_timing, NULL); } -void display_init(void) { +void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; memset(drv, 0, sizeof(display_driver_t)); - // Initialize GPIO & FSMC controller - display_init_interface(); - // Initialize display controller - display_init_controller(); -} - -void display_reinit(void) { - display_driver_t *drv = &g_display_driver; - memset(drv, 0, sizeof(display_driver_t)); - - // !@# TODO backlight level?? + if (mode == DISPLAY_RESET_CONTENT) { + // Initialize GPIO & FSMC controller + display_init_interface(); + // Initialize display controller + display_init_controller(); + } } -void display_finish_actions(void) { - /// Not used and intentionally left empty +void display_deinit(display_content_mode_t mode) { + // Not used and intentionally left empty } int display_set_backlight(int level) { diff --git a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c index c0860a2c33c..a3c4a8196de 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c @@ -220,84 +220,79 @@ static void display_sync_with_fb(display_driver_t *drv) { HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); } -void display_init(void) { +void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; memset(drv, 0, sizeof(display_driver_t)); drv->backlight_level = 255; - OLED_DC_CLK_ENA(); - OLED_CS_CLK_ENA(); - OLED_RST_CLK_ENA(); - OLED_SPI_SCK_CLK_ENA(); - OLED_SPI_MOSI_CLK_ENA(); - OLED_SPI_CLK_ENA(); - - GPIO_InitTypeDef GPIO_InitStructure; - - // Set GPIO for OLED display - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = 0; - GPIO_InitStructure.Pin = OLED_CS_PIN; - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); - HAL_GPIO_Init(OLED_CS_PORT, &GPIO_InitStructure); - GPIO_InitStructure.Pin = OLED_DC_PIN; - HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); - HAL_GPIO_Init(OLED_DC_PORT, &GPIO_InitStructure); - GPIO_InitStructure.Pin = OLED_RST_PIN; - HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET); - HAL_GPIO_Init(OLED_RST_PORT, &GPIO_InitStructure); - - // Enable SPI 1 for OLED display - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = OLED_SPI_AF; - GPIO_InitStructure.Pin = OLED_SPI_SCK_PIN; - HAL_GPIO_Init(OLED_SPI_SCK_PORT, &GPIO_InitStructure); - GPIO_InitStructure.Pin = OLED_SPI_MOSI_PIN; - HAL_GPIO_Init(OLED_SPI_MOSI_PORT, &GPIO_InitStructure); - - // Initialize SPI controller - display_init_spi(drv); - - // Set to CMD - HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); - // SPI deselect - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); - - // Reset the LCD - HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); - HAL_Delay(1); - HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET); - HAL_Delay(1); - HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); - - // SPI select - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); - // Send initialization command sequence - display_send_bytes(drv, &vg_2864ksweg01_init_seq[0], - sizeof(vg_2864ksweg01_init_seq)); - // SPI deselect - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); - - // Clear display internal framebuffer - display_sync_with_fb(drv); -} - -void display_reinit(void) { - display_driver_t *drv = &g_display_driver; - - memset(drv, 0, sizeof(display_driver_t)); - drv->backlight_level = 255; - - display_init_spi(drv); + if (mode == DISPLAY_RESET_CONTENT) { + OLED_DC_CLK_ENA(); + OLED_CS_CLK_ENA(); + OLED_RST_CLK_ENA(); + OLED_SPI_SCK_CLK_ENA(); + OLED_SPI_MOSI_CLK_ENA(); + OLED_SPI_CLK_ENA(); + + GPIO_InitTypeDef GPIO_InitStructure; + + // Set GPIO for OLED display + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = 0; + GPIO_InitStructure.Pin = OLED_CS_PIN; + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); + HAL_GPIO_Init(OLED_CS_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = OLED_DC_PIN; + HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); + HAL_GPIO_Init(OLED_DC_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = OLED_RST_PIN; + HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET); + HAL_GPIO_Init(OLED_RST_PORT, &GPIO_InitStructure); + + // Enable SPI 1 for OLED display + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = OLED_SPI_AF; + GPIO_InitStructure.Pin = OLED_SPI_SCK_PIN; + HAL_GPIO_Init(OLED_SPI_SCK_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = OLED_SPI_MOSI_PIN; + HAL_GPIO_Init(OLED_SPI_MOSI_PORT, &GPIO_InitStructure); + + // Initialize SPI controller + display_init_spi(drv); + + // Set to CMD + HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); + // SPI deselect + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); + + // Reset the LCD + HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); + HAL_Delay(1); + HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET); + HAL_Delay(1); + HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); + + // SPI select + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); + // Send initialization command sequence + display_send_bytes(drv, &vg_2864ksweg01_init_seq[0], + sizeof(vg_2864ksweg01_init_seq)); + // SPI deselect + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); + + // Clear display internal framebuffer + display_sync_with_fb(drv); + } else { + display_init_spi(drv); + } } -void display_finish_actions(void) { - /// Not used and intentionally left empty +void display_deinit(display_content_mode_t mode) { + // Not used and intentionally left empty } int display_set_backlight(int level) { diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c index 0541aabbc0c..67767878022 100644 --- a/core/embed/trezorhal/stm32u5/common.c +++ b/core/embed/trezorhal/stm32u5/common.c @@ -38,7 +38,7 @@ uint32_t systick_val_copy = 0; extern void shutdown_privileged(void); void __attribute__((noreturn)) trezor_shutdown(void) { - display_finish_actions(); + display_deinit(DISPLAY_RETAIN_CONTENT); __HAL_RCC_SAES_CLK_DISABLE(); // Erase all secrets diff --git a/core/embed/trezorhal/stm32u5/displays/dsi.c b/core/embed/trezorhal/stm32u5/displays/dsi.c index 785f0567133..775a451a717 100644 --- a/core/embed/trezorhal/stm32u5/displays/dsi.c +++ b/core/embed/trezorhal/stm32u5/displays/dsi.c @@ -1654,7 +1654,7 @@ int display_orientation(int degrees) { return degrees; } int display_get_orientation(void) { return 0; } int display_backlight(int val) { return val; } -void display_init(void) { +void display_init_all(void) { RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the common periph clock diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c index daa321df20d..d60c4fd0b39 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c @@ -41,44 +41,49 @@ typedef struct { // Display driver instance static display_driver_t g_display_driver; -void display_init(void) { - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - // Initializes the common periph clock - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI; - PeriphClkInit.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; - PeriphClkInit.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3; - PeriphClkInit.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; - PeriphClkInit.PLL3.PLL3M = 4; - PeriphClkInit.PLL3.PLL3N = 125; - PeriphClkInit.PLL3.PLL3P = 8; - PeriphClkInit.PLL3.PLL3Q = 2; - PeriphClkInit.PLL3.PLL3R = 24; - PeriphClkInit.PLL3.PLL3RGE = RCC_PLLVCIRANGE_0; - PeriphClkInit.PLL3.PLL3FRACN = 0; - PeriphClkInit.PLL3.PLL3ClockOut = RCC_PLL3_DIVP | RCC_PLL3_DIVR; - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); - - // Clear framebuffers - memset(physical_frame_buffer_0, 0x00, PHYSICAL_FRAME_BUFFER_SIZE); - memset(physical_frame_buffer_1, 0x00, PHYSICAL_FRAME_BUFFER_SIZE); - - BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT); - BSP_LCD_SetBrightness(0, 100); - BSP_LCD_DisplayOn(0); -} - -void display_reinit(void) { - BSP_LCD_Reinit(0); - if (current_frame_buffer == 0) { - BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); +void display_init(display_content_mode_t mode) { + if (mode == DISPLAY_RESET_CONTENT) { + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + // Initializes the common periph clock + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI; + PeriphClkInit.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; + PeriphClkInit.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3; + PeriphClkInit.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; + PeriphClkInit.PLL3.PLL3M = 4; + PeriphClkInit.PLL3.PLL3N = 125; + PeriphClkInit.PLL3.PLL3P = 8; + PeriphClkInit.PLL3.PLL3Q = 2; + PeriphClkInit.PLL3.PLL3R = 24; + PeriphClkInit.PLL3.PLL3RGE = RCC_PLLVCIRANGE_0; + PeriphClkInit.PLL3.PLL3FRACN = 0; + PeriphClkInit.PLL3.PLL3ClockOut = RCC_PLL3_DIVP | RCC_PLL3_DIVR; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + + // Clear framebuffers + memset(physical_frame_buffer_0, 0x00, PHYSICAL_FRAME_BUFFER_SIZE); + memset(physical_frame_buffer_1, 0x00, PHYSICAL_FRAME_BUFFER_SIZE); + + BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT); + BSP_LCD_SetBrightness(0, 100); + BSP_LCD_DisplayOn(0); } else { - BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); + // Retain display content + BSP_LCD_Reinit(0); + if (current_frame_buffer == 0) { + BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); + } else { + BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); + } } } -void display_finish_actions(void) { - // Not used and intentionally left empty +void display_deinit(display_content_mode_t mode) { + if (mode == DISPLAY_RESET_CONTENT) { + BSP_LCD_DisplayOff(0); + BSP_LCD_SetBrightness(0, 0); + BSP_LCD_DeInit(0); + } } int display_set_backlight(int level) { @@ -112,8 +117,6 @@ int display_get_orientation(void) { return drv->orientation_angle; } -void display_set_compatible_settings() {} - void display_fill(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h index cf3a1e8b669..4ebe2cea2ba 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h @@ -50,9 +50,11 @@ extern uint32_t current_frame_buffer; #define LCD_ORIENTATION_LANDSCAPE_ROT180 3U int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation); +int32_t BSP_LCD_DeInit(uint32_t Instance); int32_t BSP_LCD_Reinit(uint32_t Instance); int32_t BSP_LCD_SetBrightness(uint32_t Instance, uint32_t Brightness); int32_t BSP_LCD_DisplayOn(uint32_t Instance); +int32_t BSP_LCD_DisplayOff(uint32_t Instance); int32_t BSP_LCD_SetFrameBuffer(uint32_t Instance, uint32_t fb_addr); #endif // TREZOR_HAL_DISPLAY_INTERNAL_H diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c index 4f7dc55c98d..3cac3760f75 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c @@ -202,6 +202,11 @@ static void DSI_EndOfRefreshCallback(DSI_HandleTypeDef *hdsi); * @retval BSP status. */ int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation) { + memset(&hlcd_gfxmmu, 0, sizeof(hlcd_gfxmmu)); + memset(&hlcd_ltdc, 0, sizeof(hlcd_ltdc)); + memset(&hlcd_dsi, 0, sizeof(hlcd_dsi)); + memset(&DSIVidCfg, 0, sizeof(DSIVidCfg)); + int32_t status = BSP_ERROR_NONE; if ((Instance >= LCD_INSTANCES_NBR) || diff --git a/core/embed/trezorhal/unix/display_driver.c b/core/embed/trezorhal/unix/display_driver.c index ac4d23f2fcb..6a433c2e3e4 100644 --- a/core/embed/trezorhal/unix/display_driver.c +++ b/core/embed/trezorhal/unix/display_driver.c @@ -58,34 +58,18 @@ static display_driver_t g_display_driver; int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY; int sdl_touch_offset_x, sdl_touch_offset_y; -void display_deinit(void) { - display_driver_t *drv = &g_display_driver; - - SDL_FreeSurface(drv->prev_saved); - SDL_FreeSurface(drv->buffer); - if (drv->background != NULL) { - SDL_DestroyTexture(drv->background); - } - if (drv->texture != NULL) { - SDL_DestroyTexture(drv->texture); - } - if (drv->renderer != NULL) { - SDL_DestroyRenderer(drv->renderer); - } - if (drv->window != NULL) { - SDL_DestroyWindow(drv->window); - } - SDL_Quit(); +static void display_exit_handler(void) { + display_deinit(DISPLAY_RESET_CONTENT); } -void display_init(void) { +void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf("%s\n", SDL_GetError()); error_shutdown("SDL_Init error"); } - atexit(display_deinit); + atexit(display_exit_handler); char *window_title = NULL; char *window_title_alloc = NULL; @@ -162,12 +146,24 @@ void display_init(void) { #endif } -void display_reinit(void) { - // not used -} +void display_deinit(display_content_mode_t mode) { + display_driver_t *drv = &g_display_driver; -void display_finish_actions(void) { - // not used + SDL_FreeSurface(drv->prev_saved); + SDL_FreeSurface(drv->buffer); + if (drv->background != NULL) { + SDL_DestroyTexture(drv->background); + } + if (drv->texture != NULL) { + SDL_DestroyTexture(drv->texture); + } + if (drv->renderer != NULL) { + SDL_DestroyRenderer(drv->renderer); + } + if (drv->window != NULL) { + SDL_DestroyWindow(drv->window); + } + SDL_Quit(); } int display_set_backlight(int level) { diff --git a/core/embed/trezorhal/xdisplay.h b/core/embed/trezorhal/xdisplay.h index 0fc3a1420dc..8e856c7fdbf 100644 --- a/core/embed/trezorhal/xdisplay.h +++ b/core/embed/trezorhal/xdisplay.h @@ -46,18 +46,28 @@ // MIPI - // - STM32U5A9J-DK Discovery Board -// Fully initializes the display controller. -void display_init(void); +// Specifies how display content should be handled during +// initialization or deinitialization. +typedef enum { + // Clear the display content + DISPLAY_RESET_CONTENT, + // Retain the display content + DISPLAY_RETAIN_CONTENT +} display_content_mode_t; -// Called in application or bootloader to reinitialize an already initialized -// display controller without any distrubing visible effect (blinking, etc.). -void display_reinit(void); +// Initializes the display controller. +// +// If `mode` is `DISPLAY_RETAIN_CONTENT`, ensure the driver was previously +// initialized and `display_deinit(DISPLAY_RETAIN_CONTENT)` was called. +void display_init(display_content_mode_t mode); -// Waits for any backround operations (such as DMA copying) and returns. +// Deinitializes the display controller. // -// The function provides a barrier when jumping between -// boardloader/bootloader and firmware. -void display_finish_actions(void); +// If `mode` is `DISPLAY_RETAIN_CONTENT`, the function waits for +// background operations to complete and disables interrupts, so the +// application can safely proceed to the next boot stage and call +// `display_init(DISPLAY_RETAIN_CONTENT)`. +void display_deinit(display_content_mode_t mode); // Sets display backlight level ranging from 0 (off)..255 (maximum). // @@ -122,7 +132,7 @@ void display_refresh(void); // This is used when switching between the firmware and the bootloader. void display_set_compatible_settings(void); -// Following function define display's bitblt interface. +// Following functions define display's bitblt interface. // // These functions draw directly to to display or to the // currently inactive framebuffer. diff --git a/core/embed/trezorhal/xdisplay_legacy.h b/core/embed/trezorhal/xdisplay_legacy.h index 0fc4d75cc60..fddec1e7e4b 100644 --- a/core/embed/trezorhal/xdisplay_legacy.h +++ b/core/embed/trezorhal/xdisplay_legacy.h @@ -23,12 +23,12 @@ #include #include -// These declarationscode emulates will be removed after the -// final cleanup of display drivers. They are here just to simplify -// integration with the legacy code. +// These declarations will be removed after the final cleanup +// of display drivers. They are here just to simplify integration +// with the legacy code. // -// Most of these function are not called when NEW_RENDERING=1 -// and they are only needed to for succesfully code compilation +// Most of these functions are not called when NEW_RENDERING=1, +// and they are only needed for successful code compilation. #define DISPLAY_FRAMEBUFFER_WIDTH 768 #define DISPLAY_FRAMEBUFFER_HEIGHT 480 diff --git a/core/embed/unix/main.c b/core/embed/unix/main.c index cf8d5a8a0ba..ebabd7c3ae2 100644 --- a/core/embed/unix/main.c +++ b/core/embed/unix/main.c @@ -486,7 +486,7 @@ MP_NOINLINE int main_(int argc, char **argv) { pre_process_options(argc, argv); - display_init(); + display_init(DISPLAY_RESET_CONTENT); #if USE_TOUCH touch_init(); From a59a2ab6ffa4144c3f1ac02889967f9cd209f0f8 Mon Sep 17 00:00:00 2001 From: cepetr Date: Mon, 24 Jun 2024 17:00:51 +0200 Subject: [PATCH 05/44] refactor(core/embed): simplify ensure_compatible_settings [no changelog] --- core/embed/boardloader/main.c | 3 +++ core/embed/bootloader/emulator.c | 2 -- core/embed/bootloader/emulator.h | 4 +--- core/embed/bootloader/main.c | 3 +++ core/embed/models/T2T1/boards/trezor_t.h | 7 +++++++ core/embed/models/T2T1/compat_settings.c | 4 ++++ core/embed/trezorhal/display.h | 6 ++++++ core/embed/trezorhal/stm32f4/common.c | 16 ---------------- core/embed/trezorhal/stm32f4/displays/st7789v.c | 8 +++++++- core/embed/trezorhal/stm32f4/platform.h | 1 - core/embed/trezorhal/stm32f4/supervise.c | 4 +++- core/embed/trezorhal/stm32f4/supervise.h | 1 - .../stm32f4/xdisplay/st-7789/display_driver.c | 16 ++++++++++++++-- .../xdisplay/stm32f429i-disc1/display_driver.c | 2 -- .../stm32f4/xdisplay/ug-2828/display_driver.c | 2 -- .../stm32f4/xdisplay/vg-2864/display_driver.c | 2 -- core/embed/trezorhal/stm32u5/common.c | 5 ----- core/embed/trezorhal/stm32u5/platform.h | 1 - core/embed/trezorhal/unix/display-unix.c | 14 +++++++------- core/embed/trezorhal/unix/display_driver.c | 8 ++------ core/embed/trezorhal/xdisplay.h | 5 ----- core/site_scons/models/T2T1/trezor_t.py | 1 + 22 files changed, 58 insertions(+), 57 deletions(-) create mode 100644 core/embed/models/T2T1/compat_settings.c diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index 9c07c2c2f0e..b9f5cbb8d89 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -326,7 +326,10 @@ int main(void) { write_bootloader_min_version(hdr->monotonic); display_deinit(DISPLAY_RETAIN_CONTENT); + +#ifdef ENSURE_COMPATIBLE_SETTINGS ensure_compatible_settings(); +#endif mpu_config_off(); diff --git a/core/embed/bootloader/emulator.c b/core/embed/bootloader/emulator.c index 473357a22e8..d69d56dd72a 100644 --- a/core/embed/bootloader/emulator.c +++ b/core/embed/bootloader/emulator.c @@ -188,5 +188,3 @@ __attribute__((noreturn)) void jump_to(uint32_t address) { "STORAGE WAS RETAINED"); } } - -void ensure_compatible_settings(void) {} diff --git a/core/embed/bootloader/emulator.h b/core/embed/bootloader/emulator.h index 9facab471ce..f9ab5803765 100644 --- a/core/embed/bootloader/emulator.h +++ b/core/embed/bootloader/emulator.h @@ -15,8 +15,6 @@ void emulator_poll_events(void); void set_core_clock(int); void mpu_config_bootloader(void); void mpu_config_off(void); -void display_set_little_endian(void); -void jump_to(uint32_t address); -void ensure_compatible_settings(void); +void jump_to(void *addr); #endif diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 4df0c964ef9..1a9febca39f 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -331,7 +331,10 @@ void real_jump_to_firmware(void) { } display_deinit(DISPLAY_RETAIN_CONTENT); + +#ifdef ENSURE_COMPATIBLE_SETTINGS ensure_compatible_settings(); +#endif mpu_config_off(); jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); diff --git a/core/embed/models/T2T1/boards/trezor_t.h b/core/embed/models/T2T1/boards/trezor_t.h index 14e2ffd3fff..25a8711b719 100644 --- a/core/embed/models/T2T1/boards/trezor_t.h +++ b/core/embed/models/T2T1/boards/trezor_t.h @@ -58,4 +58,11 @@ #define SD_ENABLE_PORT GPIOC #define SD_ENABLE_PIN GPIO_PIN_0 +// 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. +#define ENSURE_COMPATIBLE_SETTINGS +extern void ensure_compatible_settings(void); + #endif //_TREZOR_T_H diff --git a/core/embed/models/T2T1/compat_settings.c b/core/embed/models/T2T1/compat_settings.c new file mode 100644 index 00000000000..a737b3c3760 --- /dev/null +++ b/core/embed/models/T2T1/compat_settings.c @@ -0,0 +1,4 @@ + +#include "platform.h" + +void ensure_compatible_settings(void) { set_core_clock(CLOCK_168_MHZ); } diff --git a/core/embed/trezorhal/display.h b/core/embed/trezorhal/display.h index 38091eec6b5..34def49aa44 100644 --- a/core/embed/trezorhal/display.h +++ b/core/embed/trezorhal/display.h @@ -93,6 +93,12 @@ static inline void display_init(display_content_mode_t mode) { } static inline void display_deinit(display_content_mode_t mode) { + +#ifdef TREZOR_MODEL_T + if (mode == DISPLAY_RESET_CONTENT) { + display_orientation(0); + } +#endif display_finish_actions(); } diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index dafde04c18f..8ebab7425ab 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -117,22 +117,6 @@ void collect_hw_entropy(void) { NULL); } -// this function resets settings changed in one layer (bootloader/firmware), -// which might be incompatible with the other layers older versions, -// where this setting might be unknown -void ensure_compatible_settings(void) { -#ifdef TREZOR_MODEL_T -#ifdef NEW_RENDERING - display_set_compatible_settings(); -#else - display_set_big_endian(); -#endif - display_orientation(0); - set_core_clock(CLOCK_168_MHZ); - backlight_pwm_deinit(BACKLIGHT_RETAIN); -#endif -} - void invalidate_firmware(void) { // erase start of the firmware (metadata) -> invalidate FW ensure(flash_unlock_write(), NULL); diff --git a/core/embed/trezorhal/stm32f4/displays/st7789v.c b/core/embed/trezorhal/stm32f4/displays/st7789v.c index 0ece172800d..68fc9ebaf98 100644 --- a/core/embed/trezorhal/stm32f4/displays/st7789v.c +++ b/core/embed/trezorhal/stm32f4/displays/st7789v.c @@ -723,6 +723,7 @@ void display_finish_actions(void) { #ifndef BOARDLOADER bg_copy_wait(); #endif + backlight_pwm_deinit(BACKLIGHT_RETAIN); } #else // NOT FRAMEBUFFER @@ -755,6 +756,11 @@ uint16_t display_get_window_offset(void) { return 0; } void display_shift_window(uint16_t pixels) {} -void display_finish_actions(void) {} +void display_finish_actions(void) { + backlight_pwm_deinit(BACKLIGHT_RETAIN); +#ifdef TREZOR_MODEL_T + display_set_big_endian(); +#endif +} #endif diff --git a/core/embed/trezorhal/stm32f4/platform.h b/core/embed/trezorhal/stm32f4/platform.h index 71071276166..00a2ce256fd 100644 --- a/core/embed/trezorhal/stm32f4/platform.h +++ b/core/embed/trezorhal/stm32f4/platform.h @@ -35,7 +35,6 @@ void set_core_clock(clock_settings_t settings); void memset_reg(volatile void *start, volatile void *stop, uint32_t val); void jump_to(uint32_t address); void jump_to_with_flag(uint32_t address, uint32_t register_flag); -void ensure_compatible_settings(void); void clear_otg_hs_memory(void); void drop_privileges(void); diff --git a/core/embed/trezorhal/stm32f4/supervise.c b/core/embed/trezorhal/stm32f4/supervise.c index 83191ed08de..bcb6e6767bb 100644 --- a/core/embed/trezorhal/stm32f4/supervise.c +++ b/core/embed/trezorhal/stm32f4/supervise.c @@ -31,8 +31,10 @@ __attribute__((noreturn)) static void _reboot_to_bootloader( #else __attribute__((noreturn)) static void _reboot_to_bootloader( boot_command_t boot_command) { - display_deinit(DISPLAY_RETAIN_CONTENT); + display_deinit(DISPLAY_RESET_CONTENT); +#ifdef ENSURE_COMPATIBLE_SETTINGS ensure_compatible_settings(); +#endif mpu_config_bootloader(); jump_to_with_flag(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE), boot_command); diff --git a/core/embed/trezorhal/stm32f4/supervise.h b/core/embed/trezorhal/stm32f4/supervise.h index 664939426cf..3d478e882f4 100644 --- a/core/embed/trezorhal/stm32f4/supervise.h +++ b/core/embed/trezorhal/stm32f4/supervise.h @@ -18,7 +18,6 @@ extern uint32_t systick_val_copy; // from util.s extern void shutdown_privileged(void); -extern void ensure_compatible_settings(void); // Initializes the supervise module // diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c index b49fcc0be44..5395f44f5fc 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c @@ -72,9 +72,23 @@ void display_init(display_content_mode_t mode) { void display_deinit(display_content_mode_t mode) { #ifdef XFRAMEBUFFER #ifndef BOARDLOADER + // Ensure that the ready frame buffer is transfered to + // the display controller display_ensure_refreshed(); + // Disable periodical interrupt svc_disableIRQ(DISPLAY_TE_INTERRUPT_NUM); #endif +#endif + + backlight_pwm_deinit(mode == DISPLAY_RESET_CONTENT ? BACKLIGHT_RESET : BACKLIGHT_RETAIN); + +#ifdef TREZOR_MODEL_T + // This ensures backward compatibility with legacy bootloader/firmware + // that relies on this hardware settings from the previous boot stage + if (mode == DISPLAY_RESET_CONTENT) { + display_set_orientation(0); + } + display_panel_set_big_endian(); #endif } @@ -123,5 +137,3 @@ int display_get_orientation(void) { return drv->orientation_angle; } - -void display_set_compatible_settings(void) { display_panel_set_big_endian(); } diff --git a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c index 27fa3c13019..28d57633648 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c @@ -107,8 +107,6 @@ void display_refresh(void) { // Do nothing as using just a single frame buffer } -void display_set_compatible_settings() {} - void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; diff --git a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c index 9de46d12c38..b249a58faa9 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c @@ -370,8 +370,6 @@ display_fb_info_t display_get_frame_buffer(void) { void display_refresh(void) { display_sync_with_fb(); } -void display_set_compatible_settings() {} - void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; diff --git a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c index a3c4a8196de..d922e446277 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c @@ -351,8 +351,6 @@ void display_refresh(void) { display_sync_with_fb(drv); } -void display_set_compatible_settings() {} - void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c index 67767878022..a10a6ccd0e6 100644 --- a/core/embed/trezorhal/stm32u5/common.c +++ b/core/embed/trezorhal/stm32u5/common.c @@ -101,11 +101,6 @@ void collect_hw_entropy(void) { NULL); } -// this function resets settings changed in one layer (bootloader/firmware), -// which might be incompatible with the other layers older versions, -// where this setting might be unknown -void ensure_compatible_settings(void) {} - void invalidate_firmware(void) { // on stm32u5, we need to disable the instruction cache before erasing the // firmware - otherwise, the write check will fail diff --git a/core/embed/trezorhal/stm32u5/platform.h b/core/embed/trezorhal/stm32u5/platform.h index 6a84e773ea4..fce29fb6ba5 100644 --- a/core/embed/trezorhal/stm32u5/platform.h +++ b/core/embed/trezorhal/stm32u5/platform.h @@ -34,7 +34,6 @@ typedef enum { } clock_settings_t; void set_core_clock(clock_settings_t settings); -void ensure_compatible_settings(void); void drop_privileges(void); // the following functions are defined in util.s diff --git a/core/embed/trezorhal/unix/display-unix.c b/core/embed/trezorhal/unix/display-unix.c index 60bbf1acc2a..07a45c82263 100644 --- a/core/embed/trezorhal/unix/display-unix.c +++ b/core/embed/trezorhal/unix/display-unix.c @@ -76,7 +76,7 @@ void display_pixeldata(pixel_color c) { c = (c & 0x8410) ? 0xFFFF : 0x0000; #endif if (!RENDERER) { - display_init(); + display_init_all(); } if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) { @@ -97,7 +97,7 @@ void display_reset_state() {} void display_init_seq(void) {} -void display_deinit(void) { +void display_exit_handler(void) { SDL_FreeSurface(PREV_SAVED); SDL_FreeSurface(BUFFER); if (BACKGROUND != NULL) { @@ -115,12 +115,12 @@ void display_deinit(void) { SDL_Quit(); } -void display_init(void) { +void display_init_all(void) { if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf("%s\n", SDL_GetError()); error_shutdown("SDL_Init error"); } - atexit(display_deinit); + atexit(display_exit_handler); char *window_title = NULL; char *window_title_alloc = NULL; @@ -197,7 +197,7 @@ void display_init(void) { void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { if (!RENDERER) { - display_init(); + display_init_all(); } PIXELWINDOW.start.x = x0; PIXELWINDOW.start.y = y0; @@ -211,7 +211,7 @@ void display_sync(void) {} void display_refresh(void) { if (!RENDERER) { - display_init(); + display_init_all(); } if (BACKGROUND) { const SDL_Rect r = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; @@ -267,7 +267,7 @@ int display_backlight(int val) { const char *display_save(const char *prefix) { if (!RENDERER) { - display_init(); + display_init_all(); } static int count; static char filename[256]; diff --git a/core/embed/trezorhal/unix/display_driver.c b/core/embed/trezorhal/unix/display_driver.c index 6a433c2e3e4..bcaada40fcc 100644 --- a/core/embed/trezorhal/unix/display_driver.c +++ b/core/embed/trezorhal/unix/display_driver.c @@ -254,7 +254,7 @@ void display_refresh(void) { display_driver_t *drv = &g_display_driver; if (!drv->renderer) { - display_init(); + return; } #ifdef DISPLAY_MONO @@ -287,10 +287,6 @@ void display_refresh(void) { SDL_RenderPresent(drv->renderer); } -void display_set_compatible_settings(void) { - // not used -} - #ifndef DISPLAY_MONO void display_fill(const gfx_bitblt_t *bb) { @@ -365,7 +361,7 @@ const char *display_save(const char *prefix) { display_driver_t *drv = &g_display_driver; if (!drv->renderer) { - display_init(); + return NULL; } #ifdef DISPLAY_MONO diff --git a/core/embed/trezorhal/xdisplay.h b/core/embed/trezorhal/xdisplay.h index 8e856c7fdbf..28f09485d9d 100644 --- a/core/embed/trezorhal/xdisplay.h +++ b/core/embed/trezorhal/xdisplay.h @@ -127,11 +127,6 @@ void display_wait_for_sync(void); // swaps the active (currently displayed) and the inactive frame buffers. void display_refresh(void); -// Sets display to the mode compatible with the legacy bootloader code. -// -// This is used when switching between the firmware and the bootloader. -void display_set_compatible_settings(void); - // Following functions define display's bitblt interface. // // These functions draw directly to to display or to the diff --git a/core/site_scons/models/T2T1/trezor_t.py b/core/site_scons/models/T2T1/trezor_t.py index 237db9aa96d..de100f8c1be 100644 --- a/core/site_scons/models/T2T1/trezor_t.py +++ b/core/site_scons/models/T2T1/trezor_t.py @@ -40,6 +40,7 @@ def configure( defines += [f"HW_REVISION={hw_revision}"] sources += [ "embed/models/T2T1/model_T2T1_layout.c", + "embed/models/T2T1/compat_settings.c", ] if "new_rendering" in features_wanted: sources += ["embed/trezorhal/xdisplay_legacy.c"] From 99fd9f91802ac63e167f4a13e2e798c659f0d5fd Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 25 Jun 2024 08:45:43 +0200 Subject: [PATCH 06/44] fix(core/embed): fix backlight pwm settings during display deinit [no changelog] --- core/embed/trezorhal/stm32f4/backlight_pwm.c | 34 +++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/core/embed/trezorhal/stm32f4/backlight_pwm.c b/core/embed/trezorhal/stm32f4/backlight_pwm.c index a65e84e0fbe..47d88000b15 100644 --- a/core/embed/trezorhal/stm32f4/backlight_pwm.c +++ b/core/embed/trezorhal/stm32f4/backlight_pwm.c @@ -198,28 +198,38 @@ void backlight_pwm_deinit(backlight_action_t action) { return; } - if (action == BACKLIGHT_RETAIN) { - // We keep both the GPIO and the timer running - #ifdef TREZOR_MODEL_T - // This code here is for backward compatibility with the old - // bootloader that used a different PWM settings. + // This code is for backward compatibility with the older + // bootloader/firmware on model T that used different + // PWM settings and relies on proper settings from the + // previous stage during boot. // about 10Hz (with PSC = (SystemCoreClock / 1000000) - 1) #define LED_PWM_SLOW_TIM_PERIOD (10000) #define LED_PWM_PRESCALER_SLOW (SystemCoreClock / 1000000 - 1) // 1 MHz - BACKLIGHT_PWM_TIM->PSC = LED_PWM_PRESCALER_SLOW; - BACKLIGHT_PWM_TIM->CR1 |= TIM_CR1_ARPE; - BACKLIGHT_PWM_TIM->CR2 |= TIM_CR2_CCPC; - BACKLIGHT_PWM_TIM->ARR = LED_PWM_SLOW_TIM_PERIOD - 1; + BACKLIGHT_PWM_TIM->PSC = LED_PWM_PRESCALER_SLOW; + BACKLIGHT_PWM_TIM->CR1 |= TIM_CR1_ARPE; + BACKLIGHT_PWM_TIM->CR2 |= TIM_CR2_CCPC; + BACKLIGHT_PWM_TIM->ARR = LED_PWM_SLOW_TIM_PERIOD - 1; + + if (action == BACKLIGHT_RESET) { + BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; + } else { // action == BACKLIGHT_RETAIN BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = (LED_PWM_SLOW_TIM_PERIOD * drv->current_level) / 255; -#endif - } else { - // TODO: deinitialize GPIOs and the TIMER } +#else + if (action == BACKLIGHT_RESET) { + // TODO: reset TIMER and GPIO + BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; + } else { // action == BACKLIGHT_RETAIN + BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = + (LED_PWM_TIM_PERIOD * drv->current_level) / 255; + } +#endif + drv->initialized = false; } From a8bd0848ee19d679cfab1640c98c15a507699dce Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 25 Jun 2024 10:07:52 +0200 Subject: [PATCH 07/44] refactor(core/embed): add initialized flag to display drivers [no changelog] --- .../stm32f4/xdisplay/st-7789/display_driver.c | 36 ++++++- .../stm32f4/xdisplay/st-7789/display_fb.c | 32 ++++++ .../xdisplay/st-7789/display_internal.h | 3 + .../stm32f429i-disc1/display_driver.c | 68 +++++++++++-- .../stm32f4/xdisplay/ug-2828/display_driver.c | 74 ++++++++++++-- .../stm32f4/xdisplay/vg-2864/display_driver.c | 63 ++++++++++-- .../xdisplay/stm32u5a9j-dk/display_driver.c | 60 ++++++++++-- .../xdisplay/stm32u5a9j-dk/display_fb.c | 16 +++ .../xdisplay/stm32u5a9j-dk/display_internal.h | 14 +++ core/embed/trezorhal/unix/display_driver.c | 97 ++++++++++++++++--- 10 files changed, 413 insertions(+), 50 deletions(-) diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c index 5395f44f5fc..559d1182ee0 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c @@ -41,10 +41,17 @@ #endif // Display driver instance -display_driver_t g_display_driver; +display_driver_t g_display_driver = { + .initialized = false, +}; void display_init(display_content_mode_t mode) { display_driver_t* drv = &g_display_driver; + + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); if (mode == DISPLAY_RESET_CONTENT) { @@ -67,9 +74,17 @@ void display_init(display_content_mode_t mode) { #ifdef XFRAMEBUFFER display_io_init_te_interrupt(); #endif + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { + display_driver_t* drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + #ifdef XFRAMEBUFFER #ifndef BOARDLOADER // Ensure that the ready frame buffer is transfered to @@ -80,7 +95,8 @@ void display_deinit(display_content_mode_t mode) { #endif #endif - backlight_pwm_deinit(mode == DISPLAY_RESET_CONTENT ? BACKLIGHT_RESET : BACKLIGHT_RETAIN); + backlight_pwm_deinit(mode == DISPLAY_RESET_CONTENT ? BACKLIGHT_RESET + : BACKLIGHT_RETAIN); #ifdef TREZOR_MODEL_T // This ensures backward compatibility with legacy bootloader/firmware @@ -90,9 +106,17 @@ void display_deinit(display_content_mode_t mode) { } display_panel_set_big_endian(); #endif + + drv->initialized = false; } int display_set_backlight(int level) { + display_driver_t* drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + #ifdef XFRAMEBUFFER #ifndef BOARDLOADER // if turning on the backlight, wait until the panel is refreshed @@ -110,6 +134,10 @@ int display_get_backlight(void) { return backlight_pwm_get(); } int display_set_orientation(int angle) { display_driver_t* drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { drv->orientation_angle = angle; @@ -135,5 +163,9 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t* drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c index fe3ae1d17f6..5d33219cffc 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c @@ -139,6 +139,14 @@ void DISPLAY_TE_INTERRUPT_HANDLER(void) { display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } + frame_buffer_state_t state; // We have to wait if the buffer was passed for copying @@ -191,6 +199,10 @@ static void wait_for_te_signal(void) { void display_refresh(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + if (drv->queue.entry[drv->queue.wix] != FB_STATE_PREPARING) { // No refresh needed as the frame buffer is not in // the state to be copied to the display @@ -234,6 +246,10 @@ void display_ensure_refreshed(void) { #ifndef BOARDLOADER display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + if (!is_mode_handler()) { bool copy_pending; @@ -265,6 +281,10 @@ void display_ensure_refreshed(void) { void display_fill(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -275,6 +295,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -285,6 +309,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -295,6 +323,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h index 611e02e0c93..bb6d7805a61 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h @@ -41,6 +41,9 @@ typedef struct { // Display driver state typedef struct { + // Set if the driver is initialized + bool initialized; + #ifdef XFRAMEBUFFER // Framebuffer queue // (accessed & updated in the context of the main thread diff --git a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c index 28d57633648..24e13a99852 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c @@ -33,6 +33,8 @@ // Display driver context. typedef struct { + // Set if the driver is initialized + bool initialized; // Pointer to the frame buffer uint16_t *framebuf; // Current display orientation (0, 90, 180, 270) @@ -42,10 +44,17 @@ typedef struct { } display_driver_t; // Display driver instance -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); drv->framebuf = (uint16_t *)FRAME_BUFFER_ADDR; @@ -55,15 +64,23 @@ void display_init(display_content_mode_t mode) { // Initialize external display controller ili9341_init(); } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { - // Not used and intentionally left empty + display_driver_t *drv = &g_display_driver; + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + // Just emulation, not doing anything drv->backlight_level = level; return level; @@ -72,12 +89,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { // Just emulation, not doing anything drv->orientation_angle = angle; @@ -89,18 +114,29 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; - display_fb_info_t fb = { - .ptr = (void *)drv->framebuf, - .stride = DISPLAY_RESX * sizeof(uint16_t), - }; - - return fb; + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { + display_fb_info_t fb = { + .ptr = (void *)drv->framebuf, + .stride = DISPLAY_RESX * sizeof(uint16_t), + }; + return fb; + } } void display_refresh(void) { @@ -110,6 +146,10 @@ void display_refresh(void) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); @@ -120,6 +160,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); @@ -130,6 +174,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); @@ -140,6 +188,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); diff --git a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c index b249a58faa9..dfdf9041c8d 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c @@ -37,6 +37,8 @@ // Display driver context. typedef struct { + // Set if the driver is initialized + bool initialized; // Frame buffer (8-bit Mono) uint8_t framebuf[DISPLAY_RESX * DISPLAY_RESY]; // Current display orientation (0 or 180) @@ -46,7 +48,9 @@ typedef struct { } display_driver_t; // Display driver instance -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; // Macros to access display parallel interface @@ -179,6 +183,10 @@ static void display_set_page_and_col(uint8_t page, uint8_t col) { static void display_sync_with_fb(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return NULL; + } + for (int y = 0; y < DISPLAY_RESY / 8; y++) { display_set_page_and_col(y, 0); uint8_t *src = &drv->framebuf[y * DISPLAY_RESX * 8]; @@ -293,6 +301,11 @@ static void display_init_interface(void) { void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); if (mode == DISPLAY_RESET_CONTENT) { @@ -301,15 +314,23 @@ void display_init(display_content_mode_t mode) { // Initialize display controller display_init_controller(); } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { - // Not used and intentionally left empty + display_driver_t *drv = &g_display_driver; + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (level != drv->backlight_level) { if (level >= 0 && level <= 255) { drv->backlight_level = level; @@ -325,12 +346,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { if (angle == 0 || angle == 180) { drv->orientation_angle = angle; @@ -354,25 +383,48 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; - display_fb_info_t fb = { - .ptr = &drv->framebuf[0], - .stride = DISPLAY_RESX, - }; - - return fb; + if (!drv->initialized) { + const static display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { + display_fb_info_t fb = { + .ptr = &drv->framebuf[0], + .stride = DISPLAY_RESX, + }; + return fb; + } } -void display_refresh(void) { display_sync_with_fb(); } +void display_refresh(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return NULL; + } + + display_sync_with_fb(); +} void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return NULL; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; @@ -383,6 +435,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return NULL; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; diff --git a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c index d922e446277..40b99e6f74c 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c @@ -42,6 +42,8 @@ // Display driver context. typedef struct { + // Set if the driver is initialized + bool initialized; // SPI driver instance SPI_HandleTypeDef spi; // Frame buffer (8-bit Mono) @@ -53,7 +55,9 @@ typedef struct { } display_driver_t; // Display driver instance -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; // Display controller registers #define OLED_SETCONTRAST 0x81 @@ -223,6 +227,10 @@ static void display_sync_with_fb(display_driver_t *drv) { void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); drv->backlight_level = 255; @@ -289,15 +297,23 @@ void display_init(display_content_mode_t mode) { } else { display_init_spi(drv); } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { - // Not used and intentionally left empty + display_driver_t *drv = &g_display_driver; + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + drv->backlight_level = 255; return drv->backlight_level; } @@ -305,12 +321,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { if (angle == 0 || angle == 180) { drv->orientation_angle = angle; @@ -324,23 +348,38 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; - display_fb_info_t fb = { - .ptr = &drv->framebuf[0], - .stride = DISPLAY_RESX, - }; - - return fb; + if (!drv->initialized) { + static const display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { + display_fb_info_t fb = { + .ptr = &drv->framebuf[0], + .stride = DISPLAY_RESX, + }; + return fb; + } } void display_refresh(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + #if defined USE_CONSUMPTION_MASK && !defined BOARDLOADER // This is an intentional randomization of the consumption masking algorithm // after every change on the display @@ -354,6 +393,10 @@ void display_refresh(void) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; @@ -364,6 +407,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c index d60c4fd0b39..f39df353c09 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c @@ -30,18 +30,18 @@ #error "Incompatible display resolution" #endif -// Display driver context. -typedef struct { - // Current display orientation (0, 90, 180, 270) - int orientation_angle; - // Current backlight level ranging from 0 to 255 - int backlight_level; -} display_driver_t; - // Display driver instance -static display_driver_t g_display_driver; +display_driver_t g_display_driver = { + .initialized = false, +}; void display_init(display_content_mode_t mode) { + display_driver_t *drv = &g_display_driver; + + if (drv->initialized) { + return; + } + if (mode == DISPLAY_RESET_CONTENT) { RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; @@ -76,19 +76,33 @@ void display_init(display_content_mode_t mode) { BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); } } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + if (mode == DISPLAY_RESET_CONTENT) { BSP_LCD_DisplayOff(0); BSP_LCD_SetBrightness(0, 0); BSP_LCD_DeInit(0); } + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + // Just emulation, not doing anything drv->backlight_level = level; return level; @@ -97,12 +111,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { // Just emulation, not doing anything drv->orientation_angle = angle; @@ -114,12 +136,20 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } void display_fill(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -130,6 +160,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -140,6 +174,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -150,6 +188,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c index 5b425176cc8..598dfc464df 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c @@ -39,6 +39,16 @@ __attribute__((section(".framebuffer_select"))) uint32_t current_frame_buffer = 0; display_fb_info_t display_get_frame_buffer(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } + uintptr_t addr; if (current_frame_buffer == 0) { @@ -63,6 +73,12 @@ display_fb_info_t display_get_frame_buffer(void) { } void display_refresh(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + if (current_frame_buffer == 0) { current_frame_buffer = 1; BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h index 4ebe2cea2ba..bb7d5582a23 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h @@ -20,8 +20,22 @@ #ifndef TREZOR_HAL_DISPLAY_INTERNAL_H #define TREZOR_HAL_DISPLAY_INTERNAL_H +#include #include +// Display driver context. +typedef struct { + // Set if the driver is initialized + bool initialized; + // Current display orientation (0, 90, 180, 270) + int orientation_angle; + // Current backlight level ranging from 0 to 255 + int backlight_level; +} display_driver_t; + +// Display driver instance +extern display_driver_t g_display_driver; + // Size of the physical frame buffer in bytes // // It's smaller than size of the virtual frame buffer diff --git a/core/embed/trezorhal/unix/display_driver.c b/core/embed/trezorhal/unix/display_driver.c index bcaada40fcc..5cb7b2314f5 100644 --- a/core/embed/trezorhal/unix/display_driver.c +++ b/core/embed/trezorhal/unix/display_driver.c @@ -32,6 +32,8 @@ #define EMULATOR_BORDER 16 typedef struct { + // Set if the driver is initialized + bool initialized; // Current display orientation (0 or 180) int orientation_angle; // Current backlight level ranging from 0 to 255 @@ -52,7 +54,9 @@ typedef struct { } display_driver_t; -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; //!@# TODO get rid of this... int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY; @@ -65,6 +69,10 @@ static void display_exit_handler(void) { void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + if (drv->initialized) { + return; + } + if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf("%s\n", SDL_GetError()); error_shutdown("SDL_Init error"); @@ -144,11 +152,16 @@ void display_init(display_content_mode_t mode) { #else drv->orientation_angle = 0; #endif + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + SDL_FreeSurface(drv->prev_saved); SDL_FreeSurface(drv->buffer); if (drv->background != NULL) { @@ -164,11 +177,17 @@ void display_deinit(display_content_mode_t mode) { SDL_DestroyWindow(drv->window); } SDL_Quit(); + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + #if !USE_BACKLIGHT level = 255; #endif @@ -183,11 +202,21 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { #if defined ORIENTATION_NSEW if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { @@ -205,6 +234,11 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } @@ -212,25 +246,32 @@ int display_get_orientation(void) { display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { #ifdef DISPLAY_MONO - display_fb_info_t fb = { - .ptr = drv->mono_framebuf, - .stride = DISPLAY_RESX, - }; + display_fb_info_t fb = { + .ptr = drv->mono_framebuf, + .stride = DISPLAY_RESX, + }; #else - display_fb_info_t fb = { - .ptr = drv->buffer->pixels, - .stride = DISPLAY_RESX * sizeof(uint16_t), - }; + display_fb_info_t fb = { + .ptr = drv->buffer->pixels, + .stride = DISPLAY_RESX * sizeof(uint16_t), + }; #endif - - return fb; + return fb; + } } #else // XFRAMEBUFFER void display_wait_for_sync(void) { - // not used + // not implemented in the emulator } #endif @@ -253,7 +294,7 @@ static void copy_mono_framebuf(display_driver_t *drv) { void display_refresh(void) { display_driver_t *drv = &g_display_driver; - if (!drv->renderer) { + if (!drv->initialized) { return; } @@ -292,6 +333,10 @@ void display_refresh(void) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -303,6 +348,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -314,6 +363,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -325,6 +378,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -338,6 +395,10 @@ void display_copy_mono4(const gfx_bitblt_t *bb) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->mono_framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX; @@ -348,6 +409,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->mono_framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX; @@ -360,7 +425,7 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { const char *display_save(const char *prefix) { display_driver_t *drv = &g_display_driver; - if (!drv->renderer) { + if (!drv->initialized) { return NULL; } @@ -396,6 +461,10 @@ const char *display_save(const char *prefix) { void display_clear_save(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + SDL_FreeSurface(drv->prev_saved); drv->prev_saved = NULL; } From b428946fe6522bd9daf931fd32b7469dae979ea9 Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 25 Jun 2024 12:45:01 +0200 Subject: [PATCH 08/44] fix(core/embed): fix display initialization on T3T1 in boardloader [no changelog] --- core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c index 559d1182ee0..c1308a43922 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c @@ -72,7 +72,9 @@ void display_init(display_content_mode_t mode) { } #ifdef XFRAMEBUFFER +#ifndef BOARDLOADER display_io_init_te_interrupt(); +#endif #endif drv->initialized = true; From 0dd94b7748a0299fddbce511b30197dc0fa2af41 Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 8 Aug 2024 17:12:57 +0200 Subject: [PATCH 09/44] refactor(core/embed): extract hw entropy logic to its own module [no changelog] --- .../extmod/modtrezorconfig/modtrezorconfig.c | 10 +++- core/embed/firmware/main.c | 3 +- core/embed/rust/build.rs | 5 +- core/embed/rust/src/trezorhal/storage.rs | 7 ++- core/embed/rust/trezorhal.h | 1 + core/embed/trezorhal/common.h | 4 -- core/embed/trezorhal/entropy.h | 31 +++++++++++ core/embed/trezorhal/stm32f4/common.c | 26 --------- core/embed/trezorhal/stm32f4/entropy.c | 55 +++++++++++++++++++ core/embed/trezorhal/stm32u5/common.c | 26 --------- core/embed/trezorhal/stm32u5/entropy.c | 55 +++++++++++++++++++ core/embed/trezorhal/unix/common.c | 4 -- core/embed/trezorhal/unix/entropy.c | 28 ++++++++++ core/embed/unix/main_main.c | 3 +- core/site_scons/models/stm32f4_common.py | 1 + core/site_scons/models/stm32u5_common.py | 1 + 16 files changed, 191 insertions(+), 69 deletions(-) create mode 100644 core/embed/trezorhal/entropy.h create mode 100644 core/embed/trezorhal/stm32f4/entropy.c create mode 100644 core/embed/trezorhal/stm32u5/entropy.c create mode 100644 core/embed/trezorhal/unix/entropy.c diff --git a/core/embed/extmod/modtrezorconfig/modtrezorconfig.c b/core/embed/extmod/modtrezorconfig/modtrezorconfig.c index 8bd5212e6db..10df09495ea 100644 --- a/core/embed/extmod/modtrezorconfig/modtrezorconfig.c +++ b/core/embed/extmod/modtrezorconfig/modtrezorconfig.c @@ -28,6 +28,7 @@ #include "embed/extmod/trezorobj.h" #include "common.h" +#include "entropy.h" #include "memzero.h" #include "storage.h" @@ -55,13 +56,16 @@ static secbool wrapped_ui_wait_callback(uint32_t wait, uint32_t progress, /// called from this module! /// """ STATIC mp_obj_t mod_trezorconfig_init(size_t n_args, const mp_obj_t *args) { + uint8_t entropy_data[HW_ENTROPY_LEN]; + entropy_get(entropy_data); + if (n_args > 0) { MP_STATE_VM(trezorconfig_ui_wait_callback) = args[0]; - storage_init(wrapped_ui_wait_callback, HW_ENTROPY_DATA, HW_ENTROPY_LEN); + storage_init(wrapped_ui_wait_callback, entropy_data, HW_ENTROPY_LEN); } else { - storage_init(NULL, HW_ENTROPY_DATA, HW_ENTROPY_LEN); + storage_init(NULL, entropy_data, HW_ENTROPY_LEN); } - memzero(HW_ENTROPY_DATA, sizeof(HW_ENTROPY_DATA)); + memzero(entropy_data, sizeof(entropy_data)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_init_obj, 0, 1, diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 357dcd5e158..a1f8ffed1e4 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -41,6 +41,7 @@ #include "common.h" #include "compiler_traits.h" #include "display.h" +#include "entropy.h" #include "fault_handlers.h" #include "flash.h" #include "image.h" @@ -179,7 +180,7 @@ int main(void) { mpu_config_firmware_initial(); - collect_hw_entropy(); + entropy_init(); #if PRODUCTION || BOOTLOADER_QA check_and_replace_bootloader(); diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index 6f2706e5552..543cf504632 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -306,8 +306,9 @@ fn generate_trezorhal_bindings() { // model .allowlist_var("MODEL_INTERNAL_NAME") .allowlist_var("MODEL_FULL_NAME") - // common - .allowlist_var("HW_ENTROPY_DATA") + // entropy + .allowlist_var("HW_ENTROPY_LEN") + .allowlist_function("entropy_get") // secbool .allowlist_type("secbool") .must_use_type("secbool") diff --git a/core/embed/rust/src/trezorhal/storage.rs b/core/embed/rust/src/trezorhal/storage.rs index 6bf44a3b716..2a7a94cacc5 100644 --- a/core/embed/rust/src/trezorhal/storage.rs +++ b/core/embed/rust/src/trezorhal/storage.rs @@ -97,10 +97,13 @@ pub type StorageResult = Result; /// This function must be called before any other storage function. pub fn init() { unsafe { + let mut entropy_data: [u8; ffi::HW_ENTROPY_LEN as usize] = + [0; ffi::HW_ENTROPY_LEN as usize]; + ffi::entropy_get(entropy_data.as_mut_ptr()); ffi::storage_init( Some(callback_wrapper), - ffi::HW_ENTROPY_DATA.as_ptr(), - ffi::HW_ENTROPY_DATA.len() as u16, + entropy_data.as_ptr(), + entropy_data.len() as u16, ); } } diff --git a/core/embed/rust/trezorhal.h b/core/embed/rust/trezorhal.h index 7dadc0abf4c..48ab14222f9 100644 --- a/core/embed/rust/trezorhal.h +++ b/core/embed/rust/trezorhal.h @@ -7,6 +7,7 @@ #include "display_draw.h" #include "dma2d.h" #include "dma2d_bitblt.h" +#include "entropy.h" #include "flash.h" #include "fonts/fonts.h" #include "gfx_bitblt.h" diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h index e42dcfd99ea..07db158bfb4 100644 --- a/core/embed/trezorhal/common.h +++ b/core/embed/trezorhal/common.h @@ -58,10 +58,6 @@ void hal_delay(uint32_t ms); uint32_t hal_ticks_ms(); void hal_delay_us(uint16_t delay_us); -void collect_hw_entropy(void); -#define HW_ENTROPY_LEN (12 + 32) -extern uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; - // Invalidates firmware on the device // Note: only works when write access to firmware area is enabled by MPU void invalidate_firmware(void); diff --git a/core/embed/trezorhal/entropy.h b/core/embed/trezorhal/entropy.h new file mode 100644 index 00000000000..bd50b48e3ac --- /dev/null +++ b/core/embed/trezorhal/entropy.h @@ -0,0 +1,31 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_ENTROPY_H +#define TREZORHAL_ENTROPY_H + +#include + +void entropy_init(void); + +#define HW_ENTROPY_LEN (12 + 32) + +void entropy_get(uint8_t *buf); + +#endif \ No newline at end of file diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 8ebab7425ab..6eb76497f39 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -91,32 +91,6 @@ void __attribute__((noreturn)) __stack_chk_fail(void) { error_shutdown("(SS)"); } -uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; - -void collect_hw_entropy(void) { - // collect entropy from UUID - uint32_t w = LL_GetUID_Word0(); - memcpy(HW_ENTROPY_DATA, &w, 4); - w = LL_GetUID_Word1(); - memcpy(HW_ENTROPY_DATA + 4, &w, 4); - w = LL_GetUID_Word2(); - memcpy(HW_ENTROPY_DATA + 8, &w, 4); - - // set entropy in the OTP randomness block - if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { - uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; - random_buffer(entropy, FLASH_OTP_BLOCK_SIZE); - ensure(flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy, - FLASH_OTP_BLOCK_SIZE), - NULL); - ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL); - } - // collect entropy from OTP randomness block - ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12, - FLASH_OTP_BLOCK_SIZE), - NULL); -} - void invalidate_firmware(void) { // erase start of the firmware (metadata) -> invalidate FW ensure(flash_unlock_write(), NULL); diff --git a/core/embed/trezorhal/stm32f4/entropy.c b/core/embed/trezorhal/stm32f4/entropy.c new file mode 100644 index 00000000000..0c655c2eca2 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/entropy.c @@ -0,0 +1,55 @@ +/* + * 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 "entropy.h" + +#include "entropy.h" +#include "flash_otp.h" +#include "model.h" +#include "rand.h" + +#include "stm32f4xx_ll_utils.h" + +static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; + +void entropy_init(void) { + // collect entropy from UUID + uint32_t w = LL_GetUID_Word0(); + memcpy(g_hw_entropy, &w, 4); + w = LL_GetUID_Word1(); + memcpy(g_hw_entropy + 4, &w, 4); + w = LL_GetUID_Word2(); + memcpy(g_hw_entropy + 8, &w, 4); + + // set entropy in the OTP randomness block + if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { + uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; + random_buffer(entropy, FLASH_OTP_BLOCK_SIZE); + ensure(flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy, + FLASH_OTP_BLOCK_SIZE), + NULL); + ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL); + } + // collect entropy from OTP randomness block + ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, g_hw_entropy + 12, + FLASH_OTP_BLOCK_SIZE), + NULL); +} + +void entropy_get(uint8_t *buf) { memcpy(buf, g_hw_entropy, HW_ENTROPY_LEN); } diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c index a10a6ccd0e6..711c6066e95 100644 --- a/core/embed/trezorhal/stm32u5/common.c +++ b/core/embed/trezorhal/stm32u5/common.c @@ -75,32 +75,6 @@ void __attribute__((noreturn)) __stack_chk_fail(void) { error_shutdown("(SS)"); } -uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; - -void collect_hw_entropy(void) { - // collect entropy from UUID - uint32_t w = LL_GetUID_Word0(); - memcpy(HW_ENTROPY_DATA, &w, 4); - w = LL_GetUID_Word1(); - memcpy(HW_ENTROPY_DATA + 4, &w, 4); - w = LL_GetUID_Word2(); - memcpy(HW_ENTROPY_DATA + 8, &w, 4); - - // set entropy in the OTP randomness block - if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { - uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; - random_buffer(entropy, FLASH_OTP_BLOCK_SIZE); - ensure(flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy, - FLASH_OTP_BLOCK_SIZE), - NULL); - // ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL); - } - // collect entropy from OTP randomness block - ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12, - FLASH_OTP_BLOCK_SIZE), - NULL); -} - void invalidate_firmware(void) { // on stm32u5, we need to disable the instruction cache before erasing the // firmware - otherwise, the write check will fail diff --git a/core/embed/trezorhal/stm32u5/entropy.c b/core/embed/trezorhal/stm32u5/entropy.c new file mode 100644 index 00000000000..c1af6ded35a --- /dev/null +++ b/core/embed/trezorhal/stm32u5/entropy.c @@ -0,0 +1,55 @@ +/* + * 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 "entropy.h" +#include "flash_otp.h" +#include "model.h" +#include "rand.h" + +#include "stm32u5xx_ll_utils.h" + +static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; + +void entropy_init(void) { + // collect entropy from UUID + uint32_t w = LL_GetUID_Word0(); + memcpy(g_hw_entropy, &w, 4); + w = LL_GetUID_Word1(); + memcpy(g_hw_entropy + 4, &w, 4); + w = LL_GetUID_Word2(); + memcpy(g_hw_entropy + 8, &w, 4); + + // set entropy in the OTP randomness block + if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { + uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; + random_buffer(entropy, FLASH_OTP_BLOCK_SIZE); + ensure(flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy, + FLASH_OTP_BLOCK_SIZE), + NULL); + // ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL); + } + // collect entropy from OTP randomness block + ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, g_hw_entropy + 12, + FLASH_OTP_BLOCK_SIZE), + NULL); +} + +void entropy_get(uint8_t *buf) { memcpy(buf, g_hw_entropy, HW_ENTROPY_LEN); } diff --git a/core/embed/trezorhal/unix/common.c b/core/embed/trezorhal/unix/common.c index afae59830f5..6a840870e13 100644 --- a/core/embed/trezorhal/unix/common.c +++ b/core/embed/trezorhal/unix/common.c @@ -74,7 +74,3 @@ void emulator_poll_events(void) { SDL_PumpEvents(); SDL_FilterEvents(emulator_event_filter, NULL); } - -uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; - -void collect_hw_entropy(void) { memzero(HW_ENTROPY_DATA, HW_ENTROPY_LEN); } diff --git a/core/embed/trezorhal/unix/entropy.c b/core/embed/trezorhal/unix/entropy.c new file mode 100644 index 00000000000..a7a091b6895 --- /dev/null +++ b/core/embed/trezorhal/unix/entropy.c @@ -0,0 +1,28 @@ +/* + * 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 "entropy.h" + +static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; + +void entropy_init(void) { memset(g_hw_entropy, 0, HW_ENTROPY_LEN); } + +void entropy_get(uint8_t *buf) { memcpy(buf, g_hw_entropy, HW_ENTROPY_LEN); } diff --git a/core/embed/unix/main_main.c b/core/embed/unix/main_main.c index f1e28931260..bdc9d561ab3 100644 --- a/core/embed/unix/main_main.c +++ b/core/embed/unix/main_main.c @@ -6,11 +6,12 @@ #endif #include "common.h" +#include "entropy.h" MP_NOINLINE int main_(int argc, char **argv); int main(int argc, char **argv) { - collect_hw_entropy(); + entropy_init(); #ifdef USE_SECP256K1_ZKP ensure(sectrue * (zkp_context_init() == 0), NULL); diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index 3a53387f73d..839be0364ed 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -43,6 +43,7 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/board_capabilities.c", "embed/trezorhal/stm32f4/boot_args.c", "embed/trezorhal/stm32f4/common.c", + "embed/trezorhal/stm32f4/entropy.c", "embed/trezorhal/stm32f4/fault_handlers.c", "embed/trezorhal/stm32f4/flash.c", "embed/trezorhal/stm32f4/flash_otp.c", diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index ff08f108c77..17a4e47fb42 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -52,6 +52,7 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/board_capabilities.c", "embed/trezorhal/stm32u5/boot_args.c", "embed/trezorhal/stm32u5/common.c", + "embed/trezorhal/stm32u5/entropy.c", "embed/trezorhal/stm32u5/fault_handlers.c", "embed/trezorhal/stm32u5/flash.c", "embed/trezorhal/stm32u5/flash_otp.c", From 68105910ae4cf55c3af02c79a1dcfea9d9b3103e Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 8 Aug 2024 17:18:32 +0200 Subject: [PATCH 10/44] refactor(core/build): remove hardcoded build path [no changelog] --- core/Makefile | 2 ++ core/SConscript.bootloader | 3 ++- core/SConscript.bootloader_emu | 3 ++- core/SConscript.firmware | 3 ++- core/SConscript.unix | 3 ++- core/embed/rust/build.rs | 21 +++++++++------------ core/embed/rust/src/protobuf/defs.rs | 17 +---------------- 7 files changed, 20 insertions(+), 32 deletions(-) diff --git a/core/Makefile b/core/Makefile index e6647bf5e71..6bea0e20fb7 100644 --- a/core/Makefile +++ b/core/Makefile @@ -143,6 +143,7 @@ test: ## run unit tests cd tests ; ./run_tests.sh $(TESTOPTS) test_rust: ## run rs unit tests + export BUILD_DIR=$(abspath $(UNIX_BUILD_DIR)) ; \ cd embed/rust ; cargo test $(TESTOPTS) --target=$(RUST_TARGET) \ --no-default-features --features $(MODEL_FEATURE),test \ -- --test-threads=1 --nocapture @@ -212,6 +213,7 @@ pyright: python ../tools/pyright_tool.py clippy: + export BUILD_DIR=$(abspath $(UNIX_BUILD_DIR)) ; \ cd embed/rust ; cargo clippy $(TESTOPTS) --all-features --target=$(RUST_TARGET) ## code generation: diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index e5226cd3139..8a1a0ce0e90 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -283,8 +283,9 @@ def cargo_build(): ] bindgen_macros = tools.get_bindgen_defines(env.get("CPPDEFINES"), ALLPATHS) + build_dir = str(Dir('.').abspath) - return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts) + return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; export BUILD_DIR=\'{build_dir}\'; cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts) rust = env.Command( target=RUST_LIBPATH, diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index 9d0627cbcc7..c7483132a71 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -300,8 +300,9 @@ def cargo_build(): ] bindgen_macros = tools.get_bindgen_defines(env.get("CPPDEFINES"), ALLPATHS) + build_dir = str(Dir('.').abspath) - return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; cd embed/rust; cargo build --profile {RUST_PROFILE} ' + ' '.join(cargo_opts) + return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; export BUILD_DIR=\'{build_dir}\'; cd embed/rust; cargo build --profile {RUST_PROFILE} ' + ' '.join(cargo_opts) rust = env.Command( target=RUST_LIBPATH, diff --git a/core/SConscript.firmware b/core/SConscript.firmware index b2a6abcc8a4..1be1a4b5c1c 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -861,8 +861,9 @@ def cargo_build(): env.get('ENV')['TREZOR_MODEL'] = TREZOR_MODEL bindgen_macros = tools.get_bindgen_defines(env.get("CPPDEFINES"), ALLPATHS) + build_dir = str(Dir('.').abspath) - return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts) + return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; export BUILD_DIR=\'{build_dir}\'; cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts) rust = env.Command( target=RUST_LIBPATH, diff --git a/core/SConscript.unix b/core/SConscript.unix index 4539e800d42..7e089781715 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -897,8 +897,9 @@ def cargo_build(): env.get('ENV')['TREZOR_MODEL'] = TREZOR_MODEL bindgen_macros = tools.get_bindgen_defines(env.get("CPPDEFINES"), ALLPATHS) + build_dir = str(Dir('.').abspath) - return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; cd embed/rust; cargo build --profile {RUST_PROFILE} --target-dir=../../build/unix/rust --no-default-features --features "{" ".join(features)}" --target {TARGET}' + return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; export BUILD_DIR=\'{build_dir}\'; cd embed/rust; cargo build --profile {RUST_PROFILE} --target-dir=../../build/unix/rust --no-default-features --features "{" ".join(features)}" --target {TARGET}' rust = env.Command( target=RUST_LIBPATH, diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index 543cf504632..e1cdaaefb65 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -14,6 +14,10 @@ fn main() { link_core_objects(); } +fn build_dir() -> String { + env::var("BUILD_DIR").expect("BUILD_DIR not defined") +} + const DEFAULT_BINDGEN_MACROS_COMMON: &[&str] = &[ "-I../unix", "-I../trezorhal/unix", @@ -94,14 +98,7 @@ fn generate_qstr_bindings() { is_global: false, }) // Pass in correct include paths. - .clang_args(&[ - "-I", - if is_firmware() { - "../../build/firmware" - } else { - "../../build/unix" - }, - ]) + .clang_args(&["-I", &build_dir()]) // Customize the standard types. .use_core() .ctypes_prefix("cty") @@ -127,6 +124,8 @@ fn generate_qstr_bindings() { fn prepare_bindings() -> bindgen::Builder { let mut bindings = bindgen::Builder::default(); + let build_dir_include = format!("-I{}", build_dir()); + let mut clang_args: Vec<&str> = Vec::new(); let bindgen_macros_env = env::var("BINDGEN_MACROS").ok(); @@ -142,12 +141,12 @@ fn prepare_bindings() -> bindgen::Builder { bindings = bindings.clang_args(["-DNEW_RENDERING"]); } + clang_args.push(&build_dir_include); + // Pass in correct include paths and defines. if is_firmware() { clang_args.push("-nostdinc"); - clang_args.push("-I../../build/firmware"); - // Append gcc-arm-none-eabi's include paths. let cc_output = Command::new("arm-none-eabi-gcc") .arg("-E") @@ -168,8 +167,6 @@ fn prepare_bindings() -> bindgen::Builder { .map(|s| format!("-I{}", s.trim())); bindings = bindings.clang_args(include_args); - } else { - clang_args.push("-I../../build/unix"); } bindings = bindings.clang_args(&clang_args); diff --git a/core/embed/rust/src/protobuf/defs.rs b/core/embed/rust/src/protobuf/defs.rs index cdae0d22f25..acf4165683d 100644 --- a/core/embed/rust/src/protobuf/defs.rs +++ b/core/embed/rust/src/protobuf/defs.rs @@ -109,24 +109,9 @@ struct NameDef { msg_offset: u16, } -#[cfg(target_arch = "arm")] macro_rules! proto_def_path { ($filename:expr) => { - concat!( - env!("CARGO_MANIFEST_DIR"), - "/../../build/firmware/rust/", - $filename - ) - }; -} -#[cfg(not(target_arch = "arm"))] -macro_rules! proto_def_path { - ($filename:expr) => { - concat!( - env!("CARGO_MANIFEST_DIR"), - "/../../build/unix/rust/", - $filename - ) + concat!(env!("BUILD_DIR"), "/rust/", $filename) }; } From 6e9b4a757a7cf7ef4cae5ad4754c2d5a4301b3b7 Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 8 Aug 2024 17:24:12 +0200 Subject: [PATCH 11/44] refactor(core/embed): remove FlashOTP module [no changelog] --- .../extmod/modtrezorio/modtrezorio-flash.h | 120 ----------- .../extmod/modtrezorio/modtrezorio-hid.h | 2 + core/embed/extmod/modtrezorio/modtrezorio.c | 3 - core/tests/production_tests/main.py | 190 ------------------ 4 files changed, 2 insertions(+), 313 deletions(-) delete mode 100644 core/embed/extmod/modtrezorio/modtrezorio-flash.h delete mode 100644 core/tests/production_tests/main.py diff --git a/core/embed/extmod/modtrezorio/modtrezorio-flash.h b/core/embed/extmod/modtrezorio/modtrezorio-flash.h deleted file mode 100644 index 3815f1e7124..00000000000 --- a/core/embed/extmod/modtrezorio/modtrezorio-flash.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 "flash_otp.h" - -#include "embed/extmod/trezorobj.h" - -/// package: trezorio.__init__ - -/// class FlashOTP: -/// """ -/// """ -typedef struct _mp_obj_FlashOTP_t { - mp_obj_base_t base; -} mp_obj_FlashOTP_t; - -/// def __init__(self) -> None: -/// """ -/// """ -STATIC mp_obj_t mod_trezorio_FlashOTP_make_new(const mp_obj_type_t *type, - size_t n_args, size_t n_kw, - const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 0, false); - mp_obj_FlashOTP_t *o = mp_obj_malloc(mp_obj_FlashOTP_t, type); - return MP_OBJ_FROM_PTR(o); -} - -/// def write(self, block: int, offset: int, data: bytes) -> None: -/// """ -/// Writes data to OTP flash -/// """ -STATIC mp_obj_t mod_trezorio_FlashOTP_write(size_t n_args, - const mp_obj_t *args) { - uint8_t block = trezor_obj_get_uint8(args[1]); - uint8_t offset = trezor_obj_get_uint8(args[2]); - mp_buffer_info_t data = {0}; - mp_get_buffer_raise(args[3], &data, MP_BUFFER_READ); - if (sectrue != flash_otp_write(block, offset, data.buf, data.len)) { - mp_raise_ValueError("write failed"); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_write_obj, 4, - 4, mod_trezorio_FlashOTP_write); - -/// def read(self, block: int, offset: int, data: bytearray) -> None: -/// """ -/// Reads data from OTP flash -/// """ -STATIC mp_obj_t mod_trezorio_FlashOTP_read(size_t n_args, - const mp_obj_t *args) { - uint8_t block = trezor_obj_get_uint8(args[1]); - uint8_t offset = trezor_obj_get_uint8(args[2]); - mp_buffer_info_t data = {0}; - mp_get_buffer_raise(args[3], &data, MP_BUFFER_WRITE); - if (sectrue != flash_otp_read(block, offset, data.buf, data.len)) { - mp_raise_ValueError("read failed"); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_read_obj, 4, 4, - mod_trezorio_FlashOTP_read); - -/// def lock(self, block: int) -> None: -/// """ -/// Lock OTP flash block -/// """ -STATIC mp_obj_t mod_trezorio_FlashOTP_lock(mp_obj_t self, mp_obj_t block) { - uint8_t b = trezor_obj_get_uint8(block); - if (sectrue != flash_otp_lock(b)) { - mp_raise_ValueError("lock failed"); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_lock_obj, - mod_trezorio_FlashOTP_lock); - -/// def is_locked(self, block: int) -> bool: -/// """ -/// Is OTP flash block locked? -/// """ -STATIC mp_obj_t mod_trezorio_FlashOTP_is_locked(mp_obj_t self, mp_obj_t block) { - uint8_t b = trezor_obj_get_uint8(block); - return (sectrue == flash_otp_is_locked(b)) ? mp_const_true : mp_const_false; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_is_locked_obj, - mod_trezorio_FlashOTP_is_locked); - -STATIC const mp_rom_map_elem_t mod_trezorio_FlashOTP_locals_dict_table[] = { - {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_FlashOTP_read_obj)}, - {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_FlashOTP_write_obj)}, - {MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorio_FlashOTP_lock_obj)}, - {MP_ROM_QSTR(MP_QSTR_is_locked), - MP_ROM_PTR(&mod_trezorio_FlashOTP_is_locked_obj)}, -}; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_FlashOTP_locals_dict, - mod_trezorio_FlashOTP_locals_dict_table); - -STATIC const mp_obj_type_t mod_trezorio_FlashOTP_type = { - {&mp_type_type}, - .name = MP_QSTR_FlashOTP, - .make_new = mod_trezorio_FlashOTP_make_new, - .locals_dict = (void *)&mod_trezorio_FlashOTP_locals_dict, -}; diff --git a/core/embed/extmod/modtrezorio/modtrezorio-hid.h b/core/embed/extmod/modtrezorio/modtrezorio-hid.h index 9cf38d48948..c5dd5195d3a 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-hid.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-hid.h @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#include "embed/extmod/trezorobj.h" + /// package: trezorio.__init__ /// class HID: diff --git a/core/embed/extmod/modtrezorio/modtrezorio.c b/core/embed/extmod/modtrezorio/modtrezorio.c index a40ae962633..7e63a81d695 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio.c +++ b/core/embed/extmod/modtrezorio/modtrezorio.c @@ -43,7 +43,6 @@ uint32_t last_touch_sample_time = 0; } // clang-format off -#include "modtrezorio-flash.h" #include "modtrezorio-hid.h" #include "modtrezorio-poll.h" #include "modtrezorio-vcp.h" @@ -114,8 +113,6 @@ STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_INT(BTN_RIGHT)}, #endif - {MP_ROM_QSTR(MP_QSTR_FlashOTP), MP_ROM_PTR(&mod_trezorio_FlashOTP_type)}, - {MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&mod_trezorio_USB_type)}, {MP_ROM_QSTR(MP_QSTR_HID), MP_ROM_PTR(&mod_trezorio_HID_type)}, {MP_ROM_QSTR(MP_QSTR_VCP), MP_ROM_PTR(&mod_trezorio_VCP_type)}, diff --git a/core/tests/production_tests/main.py b/core/tests/production_tests/main.py deleted file mode 100644 index 5a806f0ebd8..00000000000 --- a/core/tests/production_tests/main.py +++ /dev/null @@ -1,190 +0,0 @@ -import trezorio as io -import trezorui as ui -import utime - -usb_vcp = io.VCP( - iface_num=0x00, - data_iface_num=0x01, - ep_in=0x01, - ep_out=0x01, - ep_cmd=0x02, -) - -usb = io.USB( - vendor_id=0x1209, - product_id=0x53C1, - release_num=0x0200, - manufacturer="SatoshiLabs", - product="TREZOR", - serial_number="000000000000000000000000", - usb21_landing=False, -) - -usb.add(usb_vcp) - -usb.open() - -d = ui.Display() -otp = io.FlashOTP() -sd = io.SDCard() -sbu = io.SBU() - - -def test_display(colors): - d.clear() - m = { - "R": 0xF800, - "G": 0x07E0, - "B": 0x001F, - "W": 0xFFFF, - } - w = 240 // len(colors) - for i, c in enumerate(colors): - c = m.get(c, 0x0000) - d.bar(i * w, 0, i * w + w, 240, c) - d.refresh() - print("OK") - - -def test_touch(v): - d.clear() - c, t = int(v[0]), int(v[1]) - deadline = utime.ticks_add(utime.ticks_us(), t * 1000000) - if c == 1: - d.bar(0, 0, 120, 120, 0xFFFF) - elif c == 2: - d.bar(120, 0, 120, 120, 0xFFFF) - elif c == 3: - d.bar(120, 120, 120, 120, 0xFFFF) - else: - d.bar(0, 120, 120, 120, 0xFFFF) - d.refresh() - r = [0, 0] - # flush all events - while io.poll([io.TOUCH], r, 10000): - pass - # wait for event - touch = False - while True: - if not touch: - if ( - io.poll([io.TOUCH], r, 10000) - and r[0] == io.TOUCH - and r[1][0] == io.TOUCH_START - ): - touch = True - else: - if ( - io.poll([io.TOUCH], r, 10000) - and r[0] == io.TOUCH - and r[1][0] == io.TOUCH_END - ): - print(f"OK {r[1][1]} {r[1][2]}") - break - if utime.ticks_us() > deadline: - print("ERROR TIMEOUT") - break - # flush all events - while io.poll([io.TOUCH], r, 10000): - pass - d.clear() - d.refresh() - - -def test_pwm(v): - d.backlight(int(v)) - d.refresh() - print("OK") - - -def test_sd(): - if sd.present(): - sd.power(True) - buf1 = bytearray(8 * 1024) - try: - sd.read(0, buf1) - except OSError: - print("ERROR READING DATA") - sd.power(False) - return - try: - sd.write(0, buf1) - except OSError: - print("ERROR WRITING DATA") - sd.power(False) - return - buf2 = bytearray(8 * 1024) - try: - sd.read(0, buf2) - except OSError: - print("ERROR READING DATA") - sd.power(False) - return - if buf1 == buf2: - print("OK") - else: - print("ERROR DATA MISMATCH") - sd.power(False) - else: - print("ERROR NOCARD") - - -def test_sbu(v): - sbu1 = v[0] == "1" - sbu2 = v[1] == "1" - sbu.set(sbu1, sbu2) - print("OK") - - -def test_otp_read(): - data = bytearray(32) - otp.read(0, 0, data) - data = bytes(data).rstrip(b"\x00\xff").decode() - print("OK", data) - - -def test_otp_write(v): - if len(v) < 32: - v = v + "\x00" * (32 - len(v)) - data = v[:32].encode() - otp.write(0, 0, data) - otp.lock(0) - print("OK") - - -d.clear() - -while True: - - try: - line = input() - - if line == "PING": - print("OK") - - elif line.startswith("DISP "): - test_display(line[5:]) - - elif line.startswith("TOUCH "): - test_touch(line[6:]) - - elif line.startswith("PWM "): - test_pwm(line[4:]) - - elif line == "SD": - test_sd() - - elif line.startswith("SBU "): - test_sbu(line[4:]) - - elif line.startswith("OTP READ"): - test_otp_read() - - elif line.startswith("OTP WRITE "): - test_otp_write(line[10:]) - - else: - print("UNKNOWN") - - except Exception as ex: - print("ERROR", ex) From 8e4e9344b4a7402f23b10e7d745883bc2f2a2362 Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 13 Aug 2024 15:29:20 +0200 Subject: [PATCH 12/44] fix(core/embed): fix aborting of bg_copy operation [no changelog] --- core/embed/trezorhal/stm32u5/bg_copy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/embed/trezorhal/stm32u5/bg_copy.c b/core/embed/trezorhal/stm32u5/bg_copy.c index 4a81f299639..a3d66d415f4 100644 --- a/core/embed/trezorhal/stm32u5/bg_copy.c +++ b/core/embed/trezorhal/stm32u5/bg_copy.c @@ -45,6 +45,7 @@ void GPDMA1_Channel0_IRQHandler(void) { // transfer finished, disable the channel HAL_DMA_DeInit(&DMA_Handle); NVIC_DisableIRQ(GPDMA1_Channel0_IRQn); + DMA_Handle.Instance = NULL; data_src = NULL; data_dst = NULL; @@ -106,8 +107,11 @@ void bg_copy_start_const_out_8(const uint8_t *src, uint8_t *dst, size_t size, void bg_copy_abort(void) { dma_transfer_remaining = 0; dma_data_transferred = 0; - HAL_DMA_Abort(&DMA_Handle); - HAL_DMA_DeInit(&DMA_Handle); + if (DMA_Handle.Instance != NULL) { + HAL_DMA_Abort(&DMA_Handle); + HAL_DMA_DeInit(&DMA_Handle); + DMA_Handle.Instance = NULL; + } NVIC_DisableIRQ(GPDMA1_Channel0_IRQn); data_src = NULL; data_dst = NULL; From b60efc4ae7009fed9c056b9e8965f79002295a26 Mon Sep 17 00:00:00 2001 From: cepetr Date: Fri, 12 Jul 2024 11:35:49 +0200 Subject: [PATCH 13/44] feat(core/embed): introduce systick and systimer drivers [no changelog] --- core/SConscript.bootloader_emu | 2 + core/SConscript.unix | 2 + core/embed/boardloader/main.c | 4 + core/embed/bootloader/main.c | 6 +- core/embed/bootloader_ci/main.c | 5 +- core/embed/firmware/delay.c | 23 +- core/embed/firmware/main.c | 5 +- core/embed/prodtest/main.c | 6 +- core/embed/reflash/main.c | 4 + core/embed/rust/build.rs | 6 +- core/embed/rust/src/trezorhal/time.rs | 4 +- core/embed/trezorhal/common.h | 5 +- core/embed/trezorhal/random_delays.h | 3 +- core/embed/trezorhal/stm32f4/common.c | 16 -- core/embed/trezorhal/stm32f4/platform.c | 3 +- core/embed/trezorhal/stm32f4/random_delays.c | 14 +- core/embed/trezorhal/stm32f4/supervise.c | 3 - core/embed/trezorhal/stm32f4/supervise.h | 16 +- core/embed/trezorhal/stm32f4/systick.c | 218 +++++++++++++--- core/embed/trezorhal/stm32f4/systick.h | 37 --- .../trezorhal/stm32f4/systick_internal.h | 12 + core/embed/trezorhal/stm32f4/systimer.c | 237 ++++++++++++++++++ core/embed/trezorhal/stm32u5/common.c | 16 -- core/embed/trezorhal/stm32u5/systick.h | 1 - .../trezorhal/stm32u5/systick_internal.h | 1 + core/embed/trezorhal/stm32u5/systimer.c | 1 + core/embed/trezorhal/systick.h | 96 +++++++ core/embed/trezorhal/systimer.h | 93 +++++++ core/embed/trezorhal/unix/common.c | 8 - core/embed/trezorhal/unix/random_delays.c | 2 +- core/embed/trezorhal/unix/random_delays.h | 2 +- core/embed/trezorhal/unix/systick.c | 128 ++++++++++ core/embed/trezorhal/unix/systimer.c | 52 ++++ core/embed/unix/main.c | 4 + core/site_scons/models/stm32f4_common.py | 1 + core/site_scons/models/stm32u5_common.py | 1 + 36 files changed, 862 insertions(+), 175 deletions(-) delete mode 100644 core/embed/trezorhal/stm32f4/systick.h create mode 100644 core/embed/trezorhal/stm32f4/systick_internal.h create mode 100644 core/embed/trezorhal/stm32f4/systimer.c delete mode 120000 core/embed/trezorhal/stm32u5/systick.h create mode 120000 core/embed/trezorhal/stm32u5/systick_internal.h create mode 120000 core/embed/trezorhal/stm32u5/systimer.c create mode 100644 core/embed/trezorhal/systick.h create mode 100644 core/embed/trezorhal/systimer.h create mode 100644 core/embed/trezorhal/unix/systick.c create mode 100644 core/embed/trezorhal/unix/systimer.c diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index c7483132a71..9adc1a8465c 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -154,6 +154,8 @@ SOURCE_TREZORHAL = [ 'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/rng.c', 'embed/trezorhal/unix/secret.c', + 'embed/trezorhal/unix/systick.c', + 'embed/trezorhal/unix/systimer.c', 'embed/trezorhal/unix/usb.c', ] diff --git a/core/SConscript.unix b/core/SConscript.unix index 7e089781715..acd8e0285b8 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -424,6 +424,8 @@ SOURCE_UNIX = [ 'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/rng.c', + 'embed/trezorhal/unix/systick.c', + 'embed/trezorhal/unix/systimer.c', 'embed/trezorhal/unix/time_estimate.c', 'embed/trezorhal/unix/usb.c', 'embed/unix/main_main.c', diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index b9f5cbb8d89..7aa83445c2a 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -32,6 +32,7 @@ #include "model.h" #include "mpu.h" #include "rng.h" +#include "systimer.h" #include "terminal.h" #ifdef USE_SD_CARD @@ -232,6 +233,9 @@ static secbool copy_sdcard(void) { #endif int main(void) { + systick_init(); + systimer_init(); + reset_flags_reset(); // need the systick timer running before many HAL operations. diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 1a9febca39f..ade9fcbb8dd 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -33,6 +33,7 @@ #include "random_delays.h" #include "secbool.h" #include "secret.h" +#include "systimer.h" #ifdef USE_DMA2D #ifdef NEW_RENDERING @@ -359,7 +360,10 @@ int bootloader_main(void) { #endif secbool stay_in_bootloader = secfalse; - random_delays_init(); + systick_init(); + systimer_init(); + + rdi_init(); #if defined TREZOR_MODEL_T set_core_clock(CLOCK_180_MHZ); diff --git a/core/embed/bootloader_ci/main.c b/core/embed/bootloader_ci/main.c index 6d7565dcc30..43a83f35c94 100644 --- a/core/embed/bootloader_ci/main.c +++ b/core/embed/bootloader_ci/main.c @@ -176,7 +176,10 @@ static secbool check_vendor_header_lock(const vendor_header *const vhdr) { } int main(void) { - random_delays_init(); + systick_init(); + systimer_init(); + + rdi_init(); #ifdef USE_TOUCH touch_init(); #endif diff --git a/core/embed/firmware/delay.c b/core/embed/firmware/delay.c index a3d6da32a9c..037b0665bf8 100644 --- a/core/embed/firmware/delay.c +++ b/core/embed/firmware/delay.c @@ -48,27 +48,10 @@ #include "py/runtime.h" #include "py/mphal.h" #include "irq.h" +#include "systick.h" extern __IO uint32_t uwTick; -// We provide our own version of HAL_Delay that calls __WFI while waiting, -// and works when interrupts are disabled. This function is intended to be -// used only by the ST HAL functions. -void HAL_Delay(uint32_t Delay) { - if (IS_IRQ_ENABLED(query_irq())) { - // IRQs enabled, so can use systick counter to do the delay - uint32_t start = uwTick; - // Wraparound of tick is taken care of by 2's complement arithmetic. - while (uwTick - start < Delay) { - // Enter sleep mode, waiting for (at least) the SysTick interrupt. - __WFI(); - } - } else { - // IRQs disabled, use mp_hal_delay_ms routine. - mp_hal_delay_ms(Delay); - } -} - // Core delay function that does an efficient sleep and may switch thread context. // If IRQs are enabled then we must have the GIL. void mp_hal_delay_ms(mp_uint_t Delay) { @@ -110,9 +93,9 @@ void mp_hal_delay_us(mp_uint_t usec) { } mp_uint_t mp_hal_ticks_ms(void) { - return uwTick; + return systick_ms(); } mp_uint_t mp_hal_ticks_us(void) { - return uwTick * 1000; + return systick_ms() * 1000; } diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index a1f8ffed1e4..c6296ff6faf 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -51,6 +51,7 @@ #include "random_delays.h" #include "rust_ui.h" #include "secure_aes.h" +#include "systimer.h" #include TREZOR_BOARD @@ -132,8 +133,10 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data, int main(void) { svc_init(); + systick_init(); + systimer_init(); - random_delays_init(); + rdi_init(); #ifdef RDI rdi_start(); diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 973e3e76cdc..5f9e0e07828 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -42,6 +42,7 @@ #include "sdcard.h" #include "secbool.h" #include "supervise.h" +#include "systimer.h" #include "touch.h" #include "usb.h" #include "version.h" @@ -777,8 +778,11 @@ void cpuid_read(void) { int main(void) { svc_init(); + systick_init(); + systimer_init(); + rdi_init(); display_init(DISPLAY_RETAIN_CONTENT); - random_delays_init(); + #ifdef STM32U5 secure_aes_init(); #endif diff --git a/core/embed/reflash/main.c b/core/embed/reflash/main.c index b98a3bceb79..11487087209 100644 --- a/core/embed/reflash/main.c +++ b/core/embed/reflash/main.c @@ -33,6 +33,7 @@ #include "sbu.h" #include "sdcard.h" #include "secbool.h" +#include "systimer.h" #include "terminal.h" #include "touch.h" @@ -68,6 +69,9 @@ static void flash_from_sdcard(const flash_area_t* area, uint32_t source, } int main(void) { + systick_init(); + systimer_init(); + sdcard_init(); touch_init(); diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index e1cdaaefb65..4f438d77f37 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -399,9 +399,9 @@ fn generate_trezorhal_bindings() { .allowlist_function("random_uniform") // rgb led .allowlist_function("rgb_led_set_color") - // time - .allowlist_function("hal_delay") - .allowlist_function("hal_ticks_ms") + // systick + .allowlist_function("systick_delay_ms") + .allowlist_function("systick_ms") // toif .allowlist_type("toif_format_t") // dma2d diff --git a/core/embed/rust/src/trezorhal/time.rs b/core/embed/rust/src/trezorhal/time.rs index 30c9454cb3f..8c4e1e55c12 100644 --- a/core/embed/rust/src/trezorhal/time.rs +++ b/core/embed/rust/src/trezorhal/time.rs @@ -3,11 +3,11 @@ use crate::time::Duration; use super::ffi; pub fn ticks_ms() -> u32 { - unsafe { ffi::hal_ticks_ms() as _ } + unsafe { ffi::systick_ms() as _ } } pub fn sleep(delay: Duration) { unsafe { - ffi::hal_delay(delay.to_millis() as _); + ffi::systick_delay_ms(delay.to_millis() as _); } } diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h index 07db158bfb4..6675a6f0c09 100644 --- a/core/embed/trezorhal/common.h +++ b/core/embed/trezorhal/common.h @@ -26,6 +26,7 @@ #include "error_handling.h" #include "platform.h" +#include "systick.h" #ifndef MIN_8bits #define MIN_8bits(a, b) \ @@ -54,10 +55,6 @@ void __attribute__((noreturn)) trezor_shutdown(void); -void hal_delay(uint32_t ms); -uint32_t hal_ticks_ms(); -void hal_delay_us(uint16_t delay_us); - // Invalidates firmware on the device // Note: only works when write access to firmware area is enabled by MPU void invalidate_firmware(void); diff --git a/core/embed/trezorhal/random_delays.h b/core/embed/trezorhal/random_delays.h index ae8e0073fb1..19e136c4ebb 100644 --- a/core/embed/trezorhal/random_delays.h +++ b/core/embed/trezorhal/random_delays.h @@ -22,12 +22,11 @@ #include -void random_delays_init(void); +void rdi_init(void); void rdi_start(void); void rdi_stop(void); void rdi_refresh_session_delay(void); -void rdi_handler(uint32_t uw_tick); void wait_random(void); #endif diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 6eb76497f39..6da54de95c4 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -36,8 +36,6 @@ #include "backlight_pwm.h" #endif -uint32_t systick_val_copy = 0; - // from util.s extern void shutdown_privileged(void); @@ -54,20 +52,6 @@ void __attribute__((noreturn)) trezor_shutdown(void) { ; } -void hal_delay(uint32_t ms) { HAL_Delay(ms); } -uint32_t hal_ticks_ms() { return HAL_GetTick(); } -void hal_delay_us(uint16_t delay_us) { - uint32_t val = svc_get_systick_val(); - uint32_t t = hal_ticks_ms() * 1000 + - (((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000)); - uint32_t t2 = t; - do { - val = svc_get_systick_val(); - t2 = hal_ticks_ms() * 1000 + - (((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000)); - } while ((t2 - t) < delay_us); -} - // 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) diff --git a/core/embed/trezorhal/stm32f4/platform.c b/core/embed/trezorhal/stm32f4/platform.c index e7323d40337..595b9b13789 100644 --- a/core/embed/trezorhal/stm32f4/platform.c +++ b/core/embed/trezorhal/stm32f4/platform.c @@ -21,6 +21,7 @@ #include "platform.h" #include "rng.h" +#include "systick.h" #include TREZOR_BOARD const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, @@ -193,7 +194,7 @@ void set_core_clock(clock_settings_t settings) { /* Enable PLL as main clock */ RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_SW)) | RCC_CFGR_SW_PLL; - HAL_InitTick(TICK_INT_PRIORITY); + systick_update_freq(); // turn off the HSI as it is now unused (it will be turned on again // automatically if a clock security failure occurs) diff --git a/core/embed/trezorhal/stm32f4/random_delays.c b/core/embed/trezorhal/stm32f4/random_delays.c index 7a27cc4eb0e..afc8079fc14 100644 --- a/core/embed/trezorhal/stm32f4/random_delays.c +++ b/core/embed/trezorhal/stm32f4/random_delays.c @@ -44,6 +44,7 @@ Random Delays in Embedded Software by Michael Tunstall, Olivier Benoit: #include "common.h" #include "memzero.h" #include "rand.h" +#include "systimer.h" // from util.s extern void shutdown_privileged(void); @@ -151,7 +152,16 @@ static void wait(uint32_t delay) { : "r0", "r1"); } -void random_delays_init() { drbg_init(); } +// forward declaration +static void rdi_handler(void *context); + +void rdi_init() { + drbg_init(); + + systimer_t *timer = systimer_create(rdi_handler, NULL); + ensure(sectrue * (timer != NULL), "rdi_init failed"); + systimer_set_periodic(timer, 1); +} void rdi_start(void) { ensure(drbg_initialized, NULL); @@ -174,7 +184,7 @@ void rdi_refresh_session_delay(void) { refresh_session_delay = true; } -void rdi_handler(uint32_t uw_tick) { +static void rdi_handler(void *context) { if (rdi_disabled == secfalse) { // if rdi enabled if (refresh_session_delay) { session_delay = drbg_random8(); diff --git a/core/embed/trezorhal/stm32f4/supervise.c b/core/embed/trezorhal/stm32f4/supervise.c index bcb6e6767bb..d1cfd372e5e 100644 --- a/core/embed/trezorhal/stm32f4/supervise.c +++ b/core/embed/trezorhal/stm32f4/supervise.c @@ -102,9 +102,6 @@ void SVC_C_Handler(uint32_t *stack) { // raising privileges. stack[6] = (uintptr_t)_reboot_to_bootloader; return; - case SVC_GET_SYSTICK_VAL: - systick_val_copy = SysTick->VAL; - break; case SVC_REBOOT: NVIC_SystemReset(); break; diff --git a/core/embed/trezorhal/stm32f4/supervise.h b/core/embed/trezorhal/stm32f4/supervise.h index 3d478e882f4..e6934173758 100644 --- a/core/embed/trezorhal/stm32f4/supervise.h +++ b/core/embed/trezorhal/stm32f4/supervise.h @@ -5,17 +5,13 @@ #define SVC_SET_PRIORITY 2 #define SVC_SHUTDOWN 4 #define SVC_REBOOT_TO_BOOTLOADER 5 -#define SVC_GET_SYSTICK_VAL 6 -#define SVC_REBOOT 7 +#define SVC_REBOOT 6 #include #include "boot_args.h" #include "common.h" #include "image.h" -// from common.c -extern uint32_t systick_val_copy; - // from util.s extern void shutdown_privileged(void); @@ -76,13 +72,3 @@ static inline void svc_shutdown(void) { void svc_reboot_to_bootloader(void); void svc_reboot(void); - -static inline uint32_t svc_get_systick_val(void) { - if (is_mode_unprivileged() && !is_mode_handler()) { - __asm__ __volatile__("svc %0" ::"i"(SVC_GET_SYSTICK_VAL) : "memory"); - return systick_val_copy; - } else { - systick_val_copy = SysTick->VAL; - return systick_val_copy; - } -} diff --git a/core/embed/trezorhal/stm32f4/systick.c b/core/embed/trezorhal/stm32f4/systick.c index 5afa8a5bfca..a91ec425335 100644 --- a/core/embed/trezorhal/stm32f4/systick.c +++ b/core/embed/trezorhal/stm32f4/systick.c @@ -1,5 +1,3 @@ -// clang-format off - /* * This file is part of the Trezor project, https://trezor.io/ * @@ -19,52 +17,194 @@ * along with this program. If not, see . */ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +#include +#include #include "irq.h" +#include "platform.h" +#include "systemview.h" + #include "systick.h" +#include "systick_internal.h" +#include "systimer.h" -#ifdef RDI - #include "random_delays.h" -#endif +// SysTick driver state +typedef struct { + // Set if the driver is initialized + bool initialized; + // Number of hw cycles per millisecond (tick period) + uint32_t cycles_per_ms; + // Number of hw cycles per microsecond + uint32_t cycles_per_us; + // Current tick value in hardware cycles + volatile uint64_t cycles; + // Number of ticks (ms) since the system start + volatile uint32_t ticks; +} systick_driver_t; -#include "systemview.h" +static systick_driver_t g_systick_driver = { + .initialized = false, +}; + +void systick_init(void) { + systick_driver_t* drv = &g_systick_driver; + + if (drv->initialized) { + return; + } + + drv->cycles = 0; + drv->ticks = 0; + + // Set 1ms tick period + drv->cycles_per_ms = HAL_RCC_GetSysClockFreq() / 1000; + drv->cycles_per_us = drv->cycles_per_ms / 1000; + + // Initialize and enable SysTick timer + SysTick_Config(drv->cycles_per_ms); + + // We need to ensure that SysTick has the expected priority. + // The SysTick priority is configured in the boardloader, + // and some early versions didn't set this properly. + NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_NORMAL); + + drv->initialized = true; +} + +void systick_deinit(void) { + systick_driver_t* drv = &g_systick_driver; + + if (!drv->initialized) { + return; + } + + NVIC_DisableIRQ(SysTick_IRQn); + SysTick->CTRL = 0; + NVIC_ClearPendingIRQ(SysTick_IRQn); + + drv->initialized = false; +} + +void systick_update_freq(void) { + systick_driver_t* drv = &g_systick_driver; + + if (!drv->initialized) { + return; + } + + uint32_t clock_freq = HAL_RCC_GetSysClockFreq(); + drv->cycles_per_ms = clock_freq / 1000; + drv->cycles_per_us = drv->cycles_per_ms / 1000; + SysTick_Config(drv->cycles_per_ms); + + // We need to ensure that SysTick has the expected priority. + // The SysTick priority is configured in the boardloader, + // and some early versions didn't set this properly. + NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_NORMAL); +} + +uint64_t systick_cycles(void) { + systick_driver_t* drv = &g_systick_driver; + + uint32_t irq_state = disable_irq(); + + // Current value of the SysTick counter + uint32_t val = SysTick->VAL; + + // Check if the SysTick has already counted down to 0 or wrapped around + // Reading CTRL register automatically clears COUNTFLAG + if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0) { + // Re-read the current value of the SysTick counter + val = SysTick->VAL; + // Update the hardware cycles counter + // Since we have cleared COUNTFLAG, SysTick_Handler will not increment + drv->cycles += drv->cycles_per_ms; + // Increment regular ticks counter + drv->ticks++; + } + + uint64_t cycles = drv->cycles + ((val > 0) ? (drv->cycles_per_ms - val) : 0); + + enable_irq(irq_state); + + return cycles; +} + +uint64_t systick_us_to_cycles(uint64_t us) { + systick_driver_t* drv = &g_systick_driver; + + return us * drv->cycles_per_us; +} + +uint32_t systick_ms(void) { + systick_driver_t* drv = &g_systick_driver; + + return drv->ticks; +} + +uint64_t systick_us(void) { + systick_driver_t* drv = &g_systick_driver; -extern __IO uint32_t uwTick; + if (drv->cycles_per_us == 0) { + // The driver was not initialized yet - this could happen + // only if the function is called from the early initialization + // stage, before the `systick_init()` was called. In this case, + // we can't provide the correct value, so we return 0. + return 0; + } + + return systick_cycles() / drv->cycles_per_us; +} void SysTick_Handler(void) { SEGGER_SYSVIEW_RecordEnterISR(); - // this is a millisecond tick counter that wraps after approximately - // 49.71 days = (0xffffffff / (24 * 60 * 60 * 1000)) - uint32_t uw_tick = uwTick + 1; - uwTick = uw_tick; -#ifdef RDI - rdi_handler(uw_tick); -#endif + + systick_driver_t* drv = &g_systick_driver; + + if (drv->initialized) { + // Increment `cycles` counter if COUNTFLAG is set. + // If COUNTFLAG is not set, `cycles` were already incremented + // in `systick_cycles()` that also cleared the COUNTFLAG. + if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0) { + // Clear COUNTFLAG by reading VAL + (void)SysTick->VAL; + // Increment cycles counter by SysTick period + drv->cycles += drv->cycles_per_ms; + // Increment regular ticks counter + drv->ticks++; + } + + // Invoke callbacks of expired timers + systimer_dispatch_expired_timers(drv->cycles); + } SEGGER_SYSVIEW_RecordExitISR(); } + +void systick_delay_us(uint64_t us) { + uint64_t delay_cycles = systick_us_to_cycles(us); + int64_t cycles_per_ms = systick_us_to_cycles(1000); + + uint64_t end = systick_cycles() + delay_cycles; + bool irq_enabled = IS_IRQ_ENABLED(query_irq()); + int64_t diff; + + while ((diff = end - systick_cycles()) > 0) { + if (irq_enabled && (diff > cycles_per_ms)) { + // Enter sleep mode and wait for (at least) + // the SysTick interrupt. + __WFI(); + } + } +} + +void systick_delay_ms(uint32_t ms) { systick_delay_us((uint64_t)ms * 1000); } + +// We provide our own version of HAL_Delay that calls __WFI while waiting, +// and works when interrupts are disabled. This function is intended to be +// used only by the ST HAL functions. +void HAL_Delay(uint32_t ms) { systick_delay_ms(ms); } + +// We provide our own version of HAL_GetTick that replaces the default +// ST HAL function reading uwTick global variable. +uint32_t HAL_GetTick(void) { return systick_ms(); } diff --git a/core/embed/trezorhal/stm32f4/systick.h b/core/embed/trezorhal/stm32f4/systick.h deleted file mode 100644 index 7c94a91a3e3..00000000000 --- a/core/embed/trezorhal/stm32f4/systick.h +++ /dev/null @@ -1,37 +0,0 @@ -// clang-format off - -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_STM32_SYSTICK_H -#define MICROPY_INCLUDED_STM32_SYSTICK_H - -#include -#include - -// Works for x between 0 and 16 inclusive -#define POW2_CEIL(x) ((((x) - 1) | ((x) - 1) >> 1 | ((x) - 1) >> 2 | ((x) - 1) >> 3) + 1) - -#endif // MICROPY_INCLUDED_STM32_SYSTICK_H diff --git a/core/embed/trezorhal/stm32f4/systick_internal.h b/core/embed/trezorhal/stm32f4/systick_internal.h new file mode 100644 index 00000000000..0f7a9a071ac --- /dev/null +++ b/core/embed/trezorhal/stm32f4/systick_internal.h @@ -0,0 +1,12 @@ +#ifndef TREZORHAL_SYSTICK_INTERNAL_H +#define TREZORHAL_SYSTICK_INTERNAL_H + +#include + +#include "systick.h" + +// Internal function called from interrupt context. +// Handles expired timers and invoked their callbacks. +void systimer_dispatch_expired_timers(uint64_t cycles); + +#endif // TREZORHAL_SYSTICK_INTERNAL_H diff --git a/core/embed/trezorhal/stm32f4/systimer.c b/core/embed/trezorhal/stm32f4/systimer.c new file mode 100644 index 00000000000..4aacfa88731 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/systimer.c @@ -0,0 +1,237 @@ +/* + * 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 "irq.h" +#include "platform.h" +#include "systick_internal.h" +#include "systimer.h" + +// Maximum number of registered user timer +// +// Consider different implementation (i.e. priority queue +// using binary heap if MAX_SYSTIMERS exceeds 10 or more) +#define MAX_SYSTIMERS 4 + +// User timer instance +struct systimer { + // User callback function + // Non-NULL if the timer entry is valid + volatile systimer_callback_t callback; + // User callback context + void* context; + // Set if the timer is suspended + volatile bool suspended; + // Set if the timer is scheduled + volatile bool scheduled; + // Expiration time (valid if scheduled is set) + volatile uint64_t expiration; + // Period (= 0 for non-periodic timers) + volatile uint64_t period; +}; + +// systimer driver state +typedef struct { + // Set if the driver is initialized + bool initialized; + // Registered timers + // (unused slots have callback field set to NULL) + systimer_t timers[MAX_SYSTIMERS]; +} systimer_driver_t; + +static systimer_driver_t g_systimer_driver = { + .initialized = false, +}; + +void systimer_init(void) { + systimer_driver_t* drv = &g_systimer_driver; + + if (drv->initialized) { + return; + } + + memset(drv, 0, sizeof(systimer_driver_t)); + drv->initialized = true; +} + +void systimer_deinit(void) { + systimer_driver_t* drv = &g_systimer_driver; + + drv->initialized = false; +} + +static inline bool timer_valid(const systimer_driver_t* drv, + const systimer_t* timer) { + return drv->initialized && (timer >= &drv->timers[0]) && + (timer < &drv->timers[MAX_SYSTIMERS]); +} + +systimer_t* systimer_create(systimer_callback_t callback, void* context) { + systimer_driver_t* drv = &g_systimer_driver; + + if (!drv->initialized) { + return NULL; + } + + if (callback == NULL) { + // Since the callback is used to determine if the + // timer is valid, it must be non-NULL. + return NULL; + } + + uint32_t irq_state = disable_irq(); + + // Find a free timer entry + for (int i = 0; i < MAX_SYSTIMERS; i++) { + systimer_t* timer = &drv->timers[i]; + + if (timer->callback == NULL) { + timer->scheduled = false; + timer->suspended = false; + timer->context = context; + timer->callback = callback; + + enable_irq(irq_state); + return timer; + } + } + + // No free timer entry found + enable_irq(irq_state); + return NULL; +} + +void systimer_delete(systimer_t* timer) { + systimer_driver_t* drv = &g_systimer_driver; + if (!timer_valid(drv, timer)) { + return; + } + + timer->callback = NULL; +} + +void systimer_set(systimer_t* timer, uint32_t delay_ms) { + systimer_driver_t* drv = &g_systimer_driver; + + if (!timer_valid(drv, timer)) { + return; + } + + uint64_t delay = systick_us_to_cycles((uint64_t)delay_ms * 1000); + uint64_t expiration = systick_cycles() + delay; + + uint32_t irq_state = disable_irq(); + timer->expiration = expiration; + timer->period = 0; + timer->scheduled = true; + enable_irq(irq_state); +} + +void systimer_set_periodic(systimer_t* timer, uint32_t period_ms) { + systimer_driver_t* drv = &g_systimer_driver; + + if (!timer_valid(drv, timer)) { + return; + } + + uint64_t period = systick_us_to_cycles((uint64_t)period_ms * 1000); + uint64_t expiration = systick_cycles() + period; + + uint32_t irq_state = disable_irq(); + timer->expiration = expiration; + timer->period = period; + timer->scheduled = true; + enable_irq(irq_state); +} + +bool systimer_unset(systimer_t* timer) { + systimer_driver_t* drv = &g_systimer_driver; + + if (!timer_valid(drv, timer)) { + return false; + } + + uint32_t irq_state = disable_irq(); + bool was_scheduled = timer->scheduled; + timer->scheduled = false; + enable_irq(irq_state); + return was_scheduled; +} + +systimer_key_t systimer_suspend(systimer_t* timer) { + systimer_driver_t* drv = &g_systimer_driver; + + if (!timer_valid(drv, timer)) { + return false; + } + + uint32_t irq_state = disable_irq(); + bool was_suspended = timer->suspended; + timer->suspended = true; + enable_irq(irq_state); + return was_suspended; +} + +void systimer_resume(systimer_t* timer, systimer_key_t key) { + systimer_driver_t* drv = &g_systimer_driver; + + if (!timer_valid(drv, timer)) { + return; + } + + timer->suspended = key; +} + +// Called from interrupt context +void systimer_dispatch_expired_timers(uint64_t cycles) { + systimer_driver_t* drv = &g_systimer_driver; + + if (!drv->initialized) { + return; + } + + // Go through all timer slots and invoke callbacks of expired timers + // This algorithm is not efficient for large number of timers + // but it is good enough if MAX_SYSTIMERS ~ 10 + + for (int i = 0; i < MAX_SYSTIMERS; i++) { + systimer_t* timer = &drv->timers[i]; + + if (timer->callback == NULL || timer->suspended || !timer->scheduled) { + continue; + } + + if (cycles < timer->expiration) { + continue; + } + + if (timer->period > 0) { + // Reschedule periodic timer + timer->expiration = cycles + timer->period; + } else { + // Stop one-shot timer + timer->scheduled = false; + } + + // Callback is invoked from interrupt context + timer->callback(timer->context); + } +} diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c index 711c6066e95..d21a8116a43 100644 --- a/core/embed/trezorhal/stm32u5/common.c +++ b/core/embed/trezorhal/stm32u5/common.c @@ -32,8 +32,6 @@ #include "stm32u5xx_ll_utils.h" -uint32_t systick_val_copy = 0; - // from util.s extern void shutdown_privileged(void); @@ -55,20 +53,6 @@ void __attribute__((noreturn)) trezor_shutdown(void) { ; } -void hal_delay(uint32_t ms) { HAL_Delay(ms); } -uint32_t hal_ticks_ms() { return HAL_GetTick(); } -void hal_delay_us(uint16_t delay_us) { - uint32_t val = svc_get_systick_val(); - uint32_t t = hal_ticks_ms() * 1000 + - (((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000)); - uint32_t t2 = t; - do { - val = svc_get_systick_val(); - t2 = hal_ticks_ms() * 1000 + - (((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000)); - } while ((t2 - t) < delay_us); -} - uint32_t __stack_chk_guard = 0; void __attribute__((noreturn)) __stack_chk_fail(void) { diff --git a/core/embed/trezorhal/stm32u5/systick.h b/core/embed/trezorhal/stm32u5/systick.h deleted file mode 120000 index 1d1261d2cb5..00000000000 --- a/core/embed/trezorhal/stm32u5/systick.h +++ /dev/null @@ -1 +0,0 @@ -../stm32f4/systick.h \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/systick_internal.h b/core/embed/trezorhal/stm32u5/systick_internal.h new file mode 120000 index 00000000000..20607328674 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/systick_internal.h @@ -0,0 +1 @@ +../stm32f4/systick_internal.h \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/systimer.c b/core/embed/trezorhal/stm32u5/systimer.c new file mode 120000 index 00000000000..035d4ff20fd --- /dev/null +++ b/core/embed/trezorhal/stm32u5/systimer.c @@ -0,0 +1 @@ +../stm32f4/systimer.c \ No newline at end of file diff --git a/core/embed/trezorhal/systick.h b/core/embed/trezorhal/systick.h new file mode 100644 index 00000000000..af2cb677931 --- /dev/null +++ b/core/embed/trezorhal/systick.h @@ -0,0 +1,96 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_SYSTICK_H +#define TREZORHAL_SYSTICK_H + +#include +#include + +// Initializes systick subsystem +// +// Before calling this function, none of the other functions +// from this module should be called. +void systick_init(void); + +// Deinitialize systick subsystem +// +// The function should be called before jumping to the +// next bootloader stage or firmware. +void systick_deinit(void); + +// Updates systick subsystem with new system clock frequency +// +// The function should be called after the system clock frequency +// has been changed. +void systick_update_freq(void); + +// ---------------------------------------------------------------------------- +// Tick functions + +// Returns number of system clock cycles since the system start. +// +// Read monotonic counter with high resolution (Cortex-M SysTick clock) +// (On 160MHz CPU, 1 cycles is 1 / 160MHz = 6.25ns) +uint64_t systick_cycles(void); + +// Returns number of microseconds since the system start. +uint64_t systick_us(void); + +// Returns number of ticks (milliseconds) since the system start. +// +// The returned value is a 32-bit unsigned integer that wraps +// around every 49.7 days. +uint32_t systick_ms(void); + +// Converts microseconds to system clock cycles +uint64_t systick_us_to_cycles(uint64_t us); + +// Number of ticks (milliseconds) +typedef uint32_t ticks_t; + +// +#define ticks() systick_ms() + +// Helper function for building expiration time +#define ticks_timeout(timeout) (systick_ms() + (timeout)) + +// Helper function for checking ticks expiration +// +// It copes with the wrap-around of the `ticks_t` type but +// still assumes that the difference between the two ticks +// is less than half of the `ticks_t` range. +#define ticks_expired(ticks) ((int32_t)(systick_ms() - (ticks)) >= 0) + +// ---------------------------------------------------------------------------- +// Delay functions + +// Waits for at least `ms` milliseconds +void systick_delay_ms(uint32_t ms); + +// Waits for at least `us` microseconds +void systick_delay_us(uint64_t us); + +// legacy functions + +static inline uint32_t hal_ticks_ms(void) { return systick_ms(); } +static inline void hal_delay(uint32_t ms) { systick_delay_ms(ms); } +static inline void hal_delay_us(uint64_t us) { systick_delay_us(us); } + +#endif // TREZORHAL_SYSTICK_H diff --git a/core/embed/trezorhal/systimer.h b/core/embed/trezorhal/systimer.h new file mode 100644 index 00000000000..cca0c278996 --- /dev/null +++ b/core/embed/trezorhal/systimer.h @@ -0,0 +1,93 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_SYSTIMER_H +#define TREZORHAL_SYSTIMER_H + +#include +#include + +// Initializes systimer subsystem +// +// Before calling this function, none of the other functions +// from this module should be called. +void systimer_init(void); + +// Deinitialize sytimer subsystem +void systimer_deinit(void); + +// Timer handle +typedef struct systimer systimer_t; + +// Timer callback routine invoked when timer expires +// +// The callback should be as short as possible and should not +// block. It is invoked from the timer interrupt context. +// +// `context` is the pointer passed to `timer_create` +typedef void (*systimer_callback_t)(void* context); + +// Initializes the timer and returns its handle. +// +// There a limited number of timers and `NULL` is returned +// if no timer is available. +systimer_t* systimer_create(systimer_callback_t callback, void* context); + +// Deletes the timer +// +// Timer is unset and its resources are released. +void systimer_delete(systimer_t* timer); + +// Sets the timer to expire in `delay_ms` milliseconds +// +// If the timer is already set, it will be rescheduled. +void systimer_set(systimer_t* timer, uint32_t delay_ms); + +// Sets the timer to expire periodically every `period_ms` milliseconds +// +// If the timer is already set, it will be rescheduled. +void systimer_set_periodic(systimer_t* timer, uint32_t period_ms); + +// Unsets the timer (cancels the expiration) +// +// Timer is not deleted and can be set again. +// +// Returns `true` if the timer was unset before its expiration +// so the callback will not be invoked. +bool systimer_unset(systimer_t* timer); + +// Timer suspension state (opaque type). +// Allows to recursively suspend/resume timer. +typedef bool systimer_key_t; + +// Suspends timer callback invocation +// +// The purpose of this function is to prevent the timer callback +// from being invoked for synchronization purposes. The function +// returns a lock that should be passed to `systimer_resume()` to +// resume the timer callback invocation. +systimer_key_t systimer_suspend(systimer_t* timer); + +// Resumes timer callback invocation +// +// The timer callback invocation is resumed. The `key` should +// be the same as returned by `timer_suspend()`. +void systimer_resume(systimer_t* timer, systimer_key_t key); + +#endif // TREZORHAL_SYSTIMER_H diff --git a/core/embed/trezorhal/unix/common.c b/core/embed/trezorhal/unix/common.c index 6a840870e13..71830560aaf 100644 --- a/core/embed/trezorhal/unix/common.c +++ b/core/embed/trezorhal/unix/common.c @@ -40,14 +40,6 @@ void __attribute__((noreturn)) trezor_shutdown(void) { exit(3); } -void hal_delay(uint32_t ms) { usleep(1000 * ms); } - -uint32_t hal_ticks_ms() { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) { switch (event->type) { case SDL_QUIT: diff --git a/core/embed/trezorhal/unix/random_delays.c b/core/embed/trezorhal/unix/random_delays.c index 080bc683fe3..b9bcbe5ca4e 100644 --- a/core/embed/trezorhal/unix/random_delays.c +++ b/core/embed/trezorhal/unix/random_delays.c @@ -21,4 +21,4 @@ void wait_random(void) {} -void random_delays_init(void) {} +void rdi_init(void) {} diff --git a/core/embed/trezorhal/unix/random_delays.h b/core/embed/trezorhal/unix/random_delays.h index e720d6a7abb..01191b24cf9 100644 --- a/core/embed/trezorhal/unix/random_delays.h +++ b/core/embed/trezorhal/unix/random_delays.h @@ -20,7 +20,7 @@ #ifndef __TREZORHAL_RANDOM_DELAYS_H__ #define __TREZORHAL_RANDOM_DELAYS_H__ -void random_delays_init(void); +void rdi_init(void); void wait_random(void); #endif diff --git a/core/embed/trezorhal/unix/systick.c b/core/embed/trezorhal/unix/systick.c new file mode 100644 index 00000000000..7515884fd04 --- /dev/null +++ b/core/embed/trezorhal/unix/systick.c @@ -0,0 +1,128 @@ +/* + * 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 +#include +#include + +#include "systick.h" + +// Systick driver state +typedef struct { + // Set if the driver is initialized + bool initialized; + // Instant time [us] of driver initialization + uint64_t initial_time; + // Instant time [us] of driver deinitialization + uint64_t final_time; + +} systick_driver_t; + +static systick_driver_t g_systick_driver = { + .initialized = false, +}; + +// Returns number of microseconds since the os started +static uint64_t get_monotonic_clock(void) { + struct timespec tp; + + clock_gettime(CLOCK_MONOTONIC, &tp); + return tp.tv_sec * 1000000UL + tp.tv_nsec / 1000; +} + +void systick_init(void) { + systick_driver_t* drv = &g_systick_driver; + + if (drv->initialized) { + return; + } + + memset(drv, 0, sizeof(systick_driver_t)); + drv->initial_time = get_monotonic_clock(); + drv->initialized = true; +} + +void systick_deinit(void) { + systick_driver_t* drv = &g_systick_driver; + + if (!drv->initialized) { + return; + } + + // This will ensure that the time return by `systick_ms()` and + // `systick_us()` will not be reset to 0 after the `systick_deinit()` call. + drv->final_time = get_monotonic_clock(); + + drv->initialized = false; +} + +void systick_update_freq(void){}; + +uint32_t systick_ms() { + systick_driver_t* drv = &g_systick_driver; + + if (!drv->initialized) { + systick_init(); // temporary workaround required by rust unit tests + // return drv->final_time / 1000; + } + + return (get_monotonic_clock() - drv->initial_time) / 1000; +} + +uint64_t systick_us(void) { + systick_driver_t* drv = &g_systick_driver; + + if (!drv->initialized) { + systick_init(); // temporary workaround required by rust unit tests + // return drv->final_time; + } + + return get_monotonic_clock() - drv->initial_time; +} + +void systick_delay_us(uint64_t us) { + systick_driver_t* drv = &g_systick_driver; + + if (!drv->initialized) { + systick_init(); // temporary workaround required by rust unit tests + // return; + } + + struct timespec tp; + tp.tv_sec = us / 1000000; + tp.tv_nsec = (us % 1000000) * 1000; + nanosleep(&tp, NULL); +} + +void systick_delay_ms(uint32_t ms) { + systick_driver_t* drv = &g_systick_driver; + + if (!drv->initialized) { + systick_init(); // temporary workaround required by rust unit tests + // return; + } + + struct timespec tp; + tp.tv_sec = ms / 1000; + tp.tv_nsec = (ms % 1000) * 1000000; + nanosleep(&tp, NULL); +} diff --git a/core/embed/trezorhal/unix/systimer.c b/core/embed/trezorhal/unix/systimer.c new file mode 100644 index 00000000000..a678efd982a --- /dev/null +++ b/core/embed/trezorhal/unix/systimer.c @@ -0,0 +1,52 @@ +/* + * 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 "systimer.h" + +// systimer driver state +typedef struct { + // Set if the driver is initialized + bool initialized; +} systimer_driver_t; + +static systimer_driver_t g_systimer_driver = { + .initialized = false, +}; + +void systimer_init(void) { + systimer_driver_t* drv = &g_systimer_driver; + + if (drv->initialized) { + return; + } + + memset(&drv, 0, sizeof(systimer_driver_t)); + drv->initialized = true; +} + +void systimer_deinit(void) { + systimer_driver_t* drv = &g_systimer_driver; + + drv->initialized = false; +} + +// Timer driver is not fully implemented for unix platform +// since not neeeded for the emulator diff --git a/core/embed/unix/main.c b/core/embed/unix/main.c index ebabd7c3ae2..58ef8081313 100644 --- a/core/embed/unix/main.c +++ b/core/embed/unix/main.c @@ -53,6 +53,7 @@ #include "py/repl.h" #include "py/runtime.h" #include "py/stackctrl.h" +#include "systimer.h" #include "touch.h" #include "common.h" @@ -486,6 +487,9 @@ MP_NOINLINE int main_(int argc, char **argv) { pre_process_options(argc, argv); + systick_init(); + systimer_init(); + display_init(DISPLAY_RESET_CONTENT); #if USE_TOUCH diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index 839be0364ed..627c5bee41c 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -53,6 +53,7 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/platform.c", "embed/trezorhal/stm32f4/secret.c", "embed/trezorhal/stm32f4/systick.c", + "embed/trezorhal/stm32f4/systimer.c", "embed/trezorhal/stm32f4/supervise.c", "embed/trezorhal/stm32f4/time_estimate.c", "embed/trezorhal/stm32f4/random_delays.c", diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index 17a4e47fb42..5dba7f550c7 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -64,6 +64,7 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/secret.c", "embed/trezorhal/stm32u5/secure_aes.c", "embed/trezorhal/stm32u5/systick.c", + "embed/trezorhal/stm32f4/systimer.c", "embed/trezorhal/stm32f4/supervise.c", "embed/trezorhal/stm32u5/random_delays.c", "embed/trezorhal/stm32u5/rng.c", From e565d7326f869688585b671c8691776ea7113402 Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 8 Aug 2024 18:26:25 +0200 Subject: [PATCH 14/44] refactor(core/embed): remove supervise module [no changelog] --- .../extmod/modtrezorutils/modtrezorutils.c | 4 +- core/embed/firmware/main.c | 9 -- core/embed/firmware/systemview.c | 7 +- core/embed/lib/error_handling.c | 2 +- core/embed/prodtest/main.c | 6 +- core/embed/trezorhal/boot_args.h | 4 + core/embed/trezorhal/common.h | 2 - core/embed/trezorhal/stm32f4/boot_args.c | 42 ++++++ core/embed/trezorhal/stm32f4/common.c | 24 +--- .../trezorhal/stm32f4/displays/st7789v.c | 11 +- core/embed/trezorhal/stm32f4/fault_handlers.c | 11 ++ core/embed/trezorhal/stm32f4/platform.c | 17 --- core/embed/trezorhal/stm32f4/platform.h | 1 - core/embed/trezorhal/stm32f4/sdcard.c | 17 +-- core/embed/trezorhal/stm32f4/supervise.c | 126 ------------------ core/embed/trezorhal/stm32f4/supervise.h | 74 ---------- core/embed/trezorhal/stm32f4/usb/usbd_conf.c | 9 +- .../stm32f4/xdisplay/st-7789/display_driver.c | 5 +- .../stm32f4/xdisplay/st-7789/display_fb.c | 5 +- .../xdisplay/st-7789/display_internal.h | 5 + .../stm32f4/xdisplay/st-7789/display_io.c | 1 - core/embed/trezorhal/stm32u5/common.c | 23 +--- core/embed/trezorhal/stm32u5/fault_handlers.c | 8 ++ core/embed/trezorhal/stm32u5/platform.c | 15 --- core/embed/trezorhal/stm32u5/platform.h | 1 - core/embed/trezorhal/stm32u5/sdcard.c | 7 +- core/embed/trezorhal/stm32u5/supervise.c | 1 - core/embed/trezorhal/stm32u5/supervise.h | 1 - core/embed/trezorhal/stm32u5/tamper.c | 2 +- core/site_scons/models/stm32f4_common.py | 1 - core/site_scons/models/stm32u5_common.py | 1 - 31 files changed, 114 insertions(+), 328 deletions(-) delete mode 100644 core/embed/trezorhal/stm32f4/supervise.c delete mode 100644 core/embed/trezorhal/stm32f4/supervise.h delete mode 120000 core/embed/trezorhal/stm32u5/supervise.c delete mode 120000 core/embed/trezorhal/stm32u5/supervise.h diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index d00e35d11ff..a18aaeea17c 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -19,9 +19,6 @@ #include "py/objstr.h" #include "py/runtime.h" -#ifndef TREZOR_EMULATOR -#include "supervise.h" -#endif #include "image.h" #include "version.h" @@ -33,6 +30,7 @@ #include #include "blake2s.h" +#include "boot_args.h" #include "common.h" #include "flash.h" #include "unit_variant.h" diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index c6296ff6faf..933835f3007 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -100,7 +100,6 @@ #endif #include "platform.h" #include "rng.h" -#include "supervise.h" #ifdef USE_SECP256K1_ZKP #include "zkp_context.h" #endif @@ -108,9 +107,6 @@ #include "haptic.h" #endif -// from util.s -extern void shutdown_privileged(void); - #ifdef USE_OPTIGA #if !PYOPT #include @@ -132,7 +128,6 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data, #endif int main(void) { - svc_init(); systick_init(); systimer_init(); @@ -251,10 +246,6 @@ int main(void) { "Cannot initialize optiga."); #endif -#if !defined TREZOR_MODEL_1 - drop_privileges(); -#endif - #ifdef USE_SECP256K1_ZKP ensure(sectrue * (zkp_context_init() == 0), NULL); #endif diff --git a/core/embed/firmware/systemview.c b/core/embed/firmware/systemview.c index 06fc221e32d..91021d2f013 100644 --- a/core/embed/firmware/systemview.c +++ b/core/embed/firmware/systemview.c @@ -6,7 +6,6 @@ #include #include "irq.h" #include "mpconfigport.h" -#include "supervise.h" #include "SEGGER_SYSVIEW.h" #include "SEGGER_SYSVIEW_Conf.h" @@ -52,6 +51,12 @@ typedef struct { extern uint32_t SystemCoreClock; +static inline uint32_t is_mode_unprivileged(void) { + uint32_t r0; + __asm__ volatile("mrs %0, control" : "=r"(r0)); + return r0 & 1; +} + uint32_t svc_get_dwt_cyccnt() { if (is_mode_unprivileged()) { __asm__ __volatile__("svc %0" ::"i"(SVC_GET_DWT_CYCCNT)); diff --git a/core/embed/lib/error_handling.c b/core/embed/lib/error_handling.c index f93636c058a..e4f8227fb33 100644 --- a/core/embed/lib/error_handling.c +++ b/core/embed/lib/error_handling.c @@ -22,7 +22,7 @@ #include #endif -#include "common.h" +#include "boot_args.h" #include "display.h" #include "error_handling.h" #include "mini_printf.h" diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 5f9e0e07828..a40d06ad802 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -25,6 +25,7 @@ #include STM32_HAL_H #include "board_capabilities.h" +#include "boot_args.h" #include "button.h" #include "common.h" #include "display.h" @@ -34,6 +35,7 @@ #include "flash.h" #include "flash_otp.h" #include "i2c.h" +#include "image.h" #include "model.h" #include "mpu.h" #include "prodtest_common.h" @@ -41,7 +43,6 @@ #include "sbu.h" #include "sdcard.h" #include "secbool.h" -#include "supervise.h" #include "systimer.h" #include "touch.h" #include "usb.h" @@ -777,7 +778,6 @@ void cpuid_read(void) { #define BACKLIGHT_NORMAL 150 int main(void) { - svc_init(); systick_init(); systimer_init(); rdi_init(); @@ -823,8 +823,6 @@ int main(void) { mpu_config_prodtest(); fault_handlers_init(); - drop_privileges(); - display_clear(); draw_welcome_screen(); diff --git a/core/embed/trezorhal/boot_args.h b/core/embed/trezorhal/boot_args.h index 4236a42ae9c..4fd4c1d5191 100644 --- a/core/embed/trezorhal/boot_args.h +++ b/core/embed/trezorhal/boot_args.h @@ -36,4 +36,8 @@ boot_command_t bootargs_get_command(); // Returns the pointer to boot arguments const boot_args_t* bootargs_get_args(); +void __attribute__((noreturn)) trezor_shutdown(void); +void __attribute__((noreturn)) svc_reboot_to_bootloader(void); +void __attribute__((noreturn)) svc_reboot(void); + #endif // TREZORHAL_BOOT_ARGS_H diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h index 6675a6f0c09..457950dd463 100644 --- a/core/embed/trezorhal/common.h +++ b/core/embed/trezorhal/common.h @@ -53,8 +53,6 @@ }) #endif -void __attribute__((noreturn)) trezor_shutdown(void); - // Invalidates firmware on the device // Note: only works when write access to firmware area is enabled by MPU void invalidate_firmware(void); diff --git a/core/embed/trezorhal/stm32f4/boot_args.c b/core/embed/trezorhal/stm32f4/boot_args.c index 70caf21fc6d..52bd4495569 100644 --- a/core/embed/trezorhal/stm32f4/boot_args.c +++ b/core/embed/trezorhal/stm32f4/boot_args.c @@ -3,6 +3,10 @@ #include #include +#include "display.h" +#include "irq.h" +#include "mpu.h" + // The 'g_boot_command_shadow' shadows a real boot command passed // to the bootloader. // 1. In the bootloader, its value is set in the startup code. @@ -42,3 +46,41 @@ void bootargs_set(boot_command_t command, const void* args, size_t args_size) { boot_command_t bootargs_get_command() { return g_boot_command_shadow; } const boot_args_t* bootargs_get_args() { return &g_boot_args; } + +void __attribute__((noreturn)) trezor_shutdown(void) { + display_deinit(DISPLAY_RETAIN_CONTENT); + +#if defined(STM32U5) + __HAL_RCC_SAES_CLK_DISABLE(); + // Erase all secrets + TAMP->CR2 |= TAMP_CR2_BKERASE; +#endif + // from util.s + extern void shutdown_privileged(void); + shutdown_privileged(); + + for (;;) + ; +} + +void svc_reboot_to_bootloader(void) { + boot_command_t boot_command = bootargs_get_command(); + display_deinit(DISPLAY_RESET_CONTENT); +#ifdef ENSURE_COMPATIBLE_SETTINGS + ensure_compatible_settings(); +#endif +#ifdef STM32U5 + // extern uint32_t g_boot_command; + g_boot_command = boot_command; + disable_irq(); + delete_secrets(); + NVIC_SystemReset(); +#else + mpu_config_bootloader(); + jump_to_with_flag(BOOTLOADER_START + IMAGE_HEADER_SIZE, boot_command); + for (;;) + ; +#endif +} + +void svc_reboot(void) { NVIC_SystemReset(); } diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 6da54de95c4..327344525ab 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -23,12 +23,12 @@ #include "common.h" #include "display.h" +#include "error_handling.h" #include "model.h" #include "flash_otp.h" #include "platform.h" #include "rand.h" -#include "supervise.h" #include "stm32f4xx_ll_utils.h" @@ -36,20 +36,10 @@ #include "backlight_pwm.h" #endif -// from util.s -extern void shutdown_privileged(void); - -void __attribute__((noreturn)) trezor_shutdown(void) { - display_deinit(DISPLAY_RETAIN_CONTENT); -#ifdef USE_SVC_SHUTDOWN - svc_shutdown(); -#else - // It won't work properly unless called from the privileged mode - shutdown_privileged(); -#endif +uint32_t __stack_chk_guard = 0; - for (;;) - ; +void __attribute__((noreturn)) __stack_chk_fail(void) { + error_shutdown("(SS)"); } // reference RM0090 section 35.12.1 Figure 413 @@ -69,12 +59,6 @@ void clear_otg_hs_memory(void) { // the peripheral is not needed right now } -uint32_t __stack_chk_guard = 0; - -void __attribute__((noreturn)) __stack_chk_fail(void) { - error_shutdown("(SS)"); -} - void invalidate_firmware(void) { // erase start of the firmware (metadata) -> invalidate FW ensure(flash_unlock_write(), NULL); diff --git a/core/embed/trezorhal/stm32f4/displays/st7789v.c b/core/embed/trezorhal/stm32f4/displays/st7789v.c index 68fc9ebaf98..9d9bce4ed95 100644 --- a/core/embed/trezorhal/stm32f4/displays/st7789v.c +++ b/core/embed/trezorhal/stm32f4/displays/st7789v.c @@ -26,7 +26,6 @@ #include "irq.h" #include "memzero.h" #include "st7789v.h" -#include "supervise.h" #include STM32_HAL_H #ifdef TREZOR_MODEL_T @@ -253,6 +252,12 @@ int display_orientation(int degrees) { int display_get_orientation(void) { return DISPLAY_ORIENTATION; } +static inline uint32_t is_mode_handler(void) { + uint32_t r0; + __asm__ volatile("mrs %0, ipsr" : "=r"(r0)); + return (r0 & 0x1FF) != 0; +} + int display_backlight(int val) { #ifdef FRAMEBUFFER #ifndef BOARDLOADER @@ -624,14 +629,14 @@ static void switch_fb_in_backround(void) { pending_fb_switch = true; __HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN); - svc_enableIRQ(DISPLAY_TE_INTERRUPT_NUM); + NVIC_EnableIRQ(DISPLAY_TE_INTERRUPT_NUM); } else { act_frame_buffer = 0; memcpy(PhysFrameBuffer1, PhysFrameBuffer0, sizeof(PhysFrameBuffer1)); pending_fb_switch = true; __HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN); - svc_enableIRQ(DISPLAY_TE_INTERRUPT_NUM); + NVIC_EnableIRQ(DISPLAY_TE_INTERRUPT_NUM); } } #endif diff --git a/core/embed/trezorhal/stm32f4/fault_handlers.c b/core/embed/trezorhal/stm32f4/fault_handlers.c index f36e286baff..5c6d43152cc 100644 --- a/core/embed/trezorhal/stm32f4/fault_handlers.c +++ b/core/embed/trezorhal/stm32f4/fault_handlers.c @@ -1,3 +1,4 @@ +#include TREZOR_BOARD #include "common.h" void fault_handlers_init(void) { @@ -21,3 +22,13 @@ void NMI_Handler(void) { error_shutdown("(CS)"); } } + +// from util.s +extern void shutdown_privileged(void); + +void PVD_IRQHandler(void) { +#ifdef BACKLIGHT_PWM_TIM + BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; // turn off display backlight +#endif + shutdown_privileged(); +} diff --git a/core/embed/trezorhal/stm32f4/platform.c b/core/embed/trezorhal/stm32f4/platform.c index 595b9b13789..47aaa72e932 100644 --- a/core/embed/trezorhal/stm32f4/platform.c +++ b/core/embed/trezorhal/stm32f4/platform.c @@ -204,20 +204,3 @@ void set_core_clock(clock_settings_t settings) { ; } #endif - -void drop_privileges(void) { - // jump to unprivileged mode - // http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/CHDBIBGJ.html - __asm__ volatile("msr control, %0" ::"r"(0x1)); - __asm__ volatile("isb"); -} - -// from util.s -extern void shutdown_privileged(void); - -void PVD_IRQHandler(void) { -#ifdef BACKLIGHT_PWM_TIM - BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; // turn off display backlight -#endif - shutdown_privileged(); -} diff --git a/core/embed/trezorhal/stm32f4/platform.h b/core/embed/trezorhal/stm32f4/platform.h index 00a2ce256fd..c7314654463 100644 --- a/core/embed/trezorhal/stm32f4/platform.h +++ b/core/embed/trezorhal/stm32f4/platform.h @@ -36,7 +36,6 @@ void memset_reg(volatile void *start, volatile void *stop, uint32_t val); void jump_to(uint32_t address); void jump_to_with_flag(uint32_t address, uint32_t register_flag); void clear_otg_hs_memory(void); -void drop_privileges(void); extern uint32_t __stack_chk_guard; diff --git a/core/embed/trezorhal/stm32f4/sdcard.c b/core/embed/trezorhal/stm32f4/sdcard.c index f308dd12652..432e5cb49fa 100644 --- a/core/embed/trezorhal/stm32f4/sdcard.c +++ b/core/embed/trezorhal/stm32f4/sdcard.c @@ -51,7 +51,6 @@ #include "irq.h" #include "sdcard-set_clr_card_detect.h" #include "sdcard.h" -#include "supervise.h" #define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC1_CLK_ENABLE() #define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC1_CLK_DISABLE() @@ -134,8 +133,8 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { SDMMC_CLK_ENABLE(); // NVIC configuration for SDIO interrupts - svc_setpriority(SDMMC_IRQn, IRQ_PRI_NORMAL); - svc_enableIRQ(SDMMC_IRQn); + NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(SDMMC_IRQn); } // GPIO have already been initialised by sdcard_init @@ -143,7 +142,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { if (hsd->Instance == sd_handle.Instance) { - svc_disableIRQ(SDMMC_IRQn); + NVIC_DisableIRQ(SDMMC_IRQn); SDMMC_CLK_DISABLE(); } } @@ -324,7 +323,7 @@ secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, DMA_HandleTypeDef dummy_dma = {0}; sd_handle.hdmatx = &dummy_dma; - svc_enableIRQ(DMA2_Stream3_IRQn); + NVIC_EnableIRQ(DMA2_Stream3_IRQn); sdcard_reset_periph(); err = @@ -333,7 +332,7 @@ secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, err = sdcard_wait_finished(&sd_handle, 5000); } - svc_disableIRQ(DMA2_Stream3_IRQn); + NVIC_DisableIRQ(DMA2_Stream3_IRQn); HAL_DMA_DeInit(&sd_dma); sd_handle.hdmarx = NULL; @@ -380,7 +379,7 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, DMA_HandleTypeDef dummy_dma = {0}; sd_handle.hdmarx = &dummy_dma; - svc_enableIRQ(DMA2_Stream3_IRQn); + NVIC_EnableIRQ(DMA2_Stream3_IRQn); sdcard_reset_periph(); err = @@ -389,9 +388,11 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, err = sdcard_wait_finished(&sd_handle, 5000); } - svc_disableIRQ(DMA2_Stream3_IRQn); + NVIC_DisableIRQ(DMA2_Stream3_IRQn); HAL_DMA_DeInit(&sd_dma); sd_handle.hdmatx = NULL; return sectrue * (err == HAL_OK); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/supervise.c b/core/embed/trezorhal/stm32f4/supervise.c deleted file mode 100644 index d1cfd372e5e..00000000000 --- a/core/embed/trezorhal/stm32f4/supervise.c +++ /dev/null @@ -1,126 +0,0 @@ -#include STM32_HAL_H - -#include - -#include "../mpu.h" -#include "common.h" -#include "display.h" -#include "irq.h" -#include "supervise.h" - -#ifdef ARM_USER_MODE - -void svc_init(void) { - NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_HIGHEST); - - // We need to ensure that SysTick has the expected priority. - // The SysTick priority is configured in the boardloader, - // and some early versions didn't set this properly. - NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_HIGHEST); -} - -#ifdef STM32U5 -extern uint32_t g_boot_command; -__attribute__((noreturn)) static void _reboot_to_bootloader( - boot_command_t boot_command) { - g_boot_command = boot_command; - disable_irq(); - delete_secrets(); - NVIC_SystemReset(); -} -#else -__attribute__((noreturn)) static void _reboot_to_bootloader( - boot_command_t boot_command) { - display_deinit(DISPLAY_RESET_CONTENT); -#ifdef ENSURE_COMPATIBLE_SETTINGS - ensure_compatible_settings(); -#endif - mpu_config_bootloader(); - jump_to_with_flag(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE), - boot_command); - for (;;) - ; -} -#endif - -void svc_reboot_to_bootloader(void) { - boot_command_t boot_command = bootargs_get_command(); - if (is_mode_unprivileged() && !is_mode_handler()) { - register uint32_t r0 __asm__("r0") = boot_command; - __asm__ __volatile__("svc %0" ::"i"(SVC_REBOOT_TO_BOOTLOADER), "r"(r0) - : "memory"); - } else { - _reboot_to_bootloader(boot_command); - } -} - -void svc_reboot(void) { - if (is_mode_unprivileged() && !is_mode_handler()) { - __asm__ __volatile__("svc %0" ::"i"(SVC_REBOOT) : "memory"); - } else { - NVIC_SystemReset(); - } -} - -void SVC_C_Handler(uint32_t *stack) { - uint8_t svc_number = ((uint8_t *)stack[6])[-2]; - switch (svc_number) { - case SVC_ENABLE_IRQ: - NVIC_EnableIRQ(stack[0]); - break; - case SVC_DISABLE_IRQ: - NVIC_DisableIRQ(stack[0]); - break; - case SVC_SET_PRIORITY: - NVIC_SetPriority(stack[0], stack[1]); - break; -#ifdef SYSTEM_VIEW - case SVC_GET_DWT_CYCCNT: - cyccnt_cycles = *DWT_CYCCNT_ADDR; - break; -#endif - case SVC_SHUTDOWN: - shutdown_privileged(); - for (;;) - ; - break; - case SVC_REBOOT_TO_BOOTLOADER: - - __asm__ volatile("msr control, %0" ::"r"(0x0)); - __asm__ volatile("isb"); - - // The input stack[0] argument comes from R0 saved when SVC was called - // from svc_reboot_to_bootloader. The __asm__ directive expects address as - // argument, hence the & in front of it, otherwise it would try - // to dereference the value and fault - __asm__ volatile( - "mov r0, %[boot_command]" ::[boot_command] "r"(&stack[0])); - - // See stack layout in - // https://developer.arm.com/documentation/ka004005/latest We are changing - // return address in PC to land into reboot to avoid any bug with ROP and - // raising privileges. - stack[6] = (uintptr_t)_reboot_to_bootloader; - return; - case SVC_REBOOT: - NVIC_SystemReset(); - break; - default: - stack[0] = 0xffffffff; - break; - } -} - -__attribute__((naked)) void SVC_Handler(void) { - __asm volatile( - " tst lr, #4 \n" // Test Bit 3 to see which stack pointer we should - // use - " ite eq \n" // Tell the assembler that the nest 2 instructions - // are if-then-else - " mrseq r0, msp \n" // Make R0 point to main stack pointer - " mrsne r0, psp \n" // Make R0 point to process stack pointer - " b SVC_C_Handler \n" // Off to C land - ); -} - -#endif // ARM_USER_MODE diff --git a/core/embed/trezorhal/stm32f4/supervise.h b/core/embed/trezorhal/stm32f4/supervise.h deleted file mode 100644 index e6934173758..00000000000 --- a/core/embed/trezorhal/stm32f4/supervise.h +++ /dev/null @@ -1,74 +0,0 @@ -// supervisor call functions - -#define SVC_ENABLE_IRQ 0 -#define SVC_DISABLE_IRQ 1 -#define SVC_SET_PRIORITY 2 -#define SVC_SHUTDOWN 4 -#define SVC_REBOOT_TO_BOOTLOADER 5 -#define SVC_REBOOT 6 - -#include -#include "boot_args.h" -#include "common.h" -#include "image.h" - -// from util.s -extern void shutdown_privileged(void); - -// Initializes the supervise module -// -// Must be called before invoking the first `svc_xxx` call -void svc_init(void); - -static inline uint32_t is_mode_unprivileged(void) { - uint32_t r0; - __asm__ volatile("mrs %0, control" : "=r"(r0)); - return r0 & 1; -} - -static inline uint32_t is_mode_handler(void) { - uint32_t r0; - __asm__ volatile("mrs %0, ipsr" : "=r"(r0)); - return (r0 & 0x1FF) != 0; -} - -static inline void svc_enableIRQ(uint32_t IRQn) { - if (is_mode_unprivileged() && !is_mode_handler()) { - register uint32_t r0 __asm__("r0") = IRQn; - __asm__ __volatile__("svc %0" ::"i"(SVC_ENABLE_IRQ), "r"(r0) : "memory"); - } else { - NVIC_EnableIRQ(IRQn); - } -} - -static inline void svc_disableIRQ(uint32_t IRQn) { - if (is_mode_unprivileged() && !is_mode_handler()) { - register uint32_t r0 __asm__("r0") = IRQn; - __asm__ __volatile__("svc %0" ::"i"(SVC_DISABLE_IRQ), "r"(r0) : "memory"); - } else { - NVIC_DisableIRQ(IRQn); - } -} - -static inline void svc_setpriority(uint32_t IRQn, uint32_t priority) { - if (is_mode_unprivileged() && !is_mode_handler()) { - register uint32_t r0 __asm__("r0") = IRQn; - register uint32_t r1 __asm__("r1") = priority; - __asm__ __volatile__("svc %0" ::"i"(SVC_SET_PRIORITY), "r"(r0), "r"(r1) - : "memory"); - } else { - NVIC_SetPriority(IRQn, priority); - } -} - -static inline void svc_shutdown(void) { - if (is_mode_unprivileged() && !is_mode_handler()) { - __asm__ __volatile__("svc %0" ::"i"(SVC_SHUTDOWN) : "memory"); - } else { - shutdown_privileged(); - } -} - -void svc_reboot_to_bootloader(void); - -void svc_reboot(void); diff --git a/core/embed/trezorhal/stm32f4/usb/usbd_conf.c b/core/embed/trezorhal/stm32f4/usb/usbd_conf.c index 452adf4170d..598b47e128b 100644 --- a/core/embed/trezorhal/stm32f4/usb/usbd_conf.c +++ b/core/embed/trezorhal/stm32f4/usb/usbd_conf.c @@ -55,7 +55,6 @@ #include "usbd_core.h" #include "usb.h" #include "irq.h" -#include "supervise.h" #include "systemview.h" /* Private typedef -----------------------------------------------------------*/ @@ -147,10 +146,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) #endif /* Set USBFS Interrupt priority */ - svc_setpriority(OTG_FS_IRQn, IRQ_PRI_NORMAL); + NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_NORMAL); /* Enable USBFS Interrupt */ - svc_enableIRQ(OTG_FS_IRQn); + NVIC_EnableIRQ(OTG_FS_IRQn); } #endif #if defined(USE_USB_HS) @@ -302,10 +301,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) #endif // !USE_USB_HS_IN_FS /* Set USBHS Interrupt to the lowest priority */ - svc_setpriority(OTG_HS_IRQn, IRQ_PRI_NORMAL); + NVIC_SetPriority(OTG_HS_IRQn, IRQ_PRI_NORMAL); /* Enable USBHS Interrupt */ - svc_enableIRQ(OTG_HS_IRQn); + NVIC_EnableIRQ(OTG_HS_IRQn); } #endif // USE_USB_HS } diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c index c1308a43922..34de6abaeee 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c @@ -27,7 +27,6 @@ #include "display_panel.h" #include "backlight_pwm.h" -#include "supervise.h" #ifndef BOARDLOADER #include "bg_copy.h" @@ -93,7 +92,7 @@ void display_deinit(display_content_mode_t mode) { // the display controller display_ensure_refreshed(); // Disable periodical interrupt - svc_disableIRQ(DISPLAY_TE_INTERRUPT_NUM); + NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM); #endif #endif @@ -122,7 +121,7 @@ int display_set_backlight(int level) { #ifdef XFRAMEBUFFER #ifndef BOARDLOADER // if turning on the backlight, wait until the panel is refreshed - if (backlight_pwm_get() < level && !is_mode_handler()) { + if (backlight_pwm_get() < level && !is_mode_exception()) { display_ensure_refreshed(); } #endif diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c index 5d33219cffc..889c79545d8 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c @@ -32,7 +32,6 @@ #include "gfx_bitblt.h" #include "irq.h" -#include "supervise.h" #ifndef BOARDLOADER #include "bg_copy.h" @@ -210,7 +209,7 @@ void display_refresh(void) { } #ifndef BOARDLOADER - if (is_mode_handler()) { + if (is_mode_exception()) { // Disable scheduling of any new background copying NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM); // Wait for next TE signal. During this time the @@ -250,7 +249,7 @@ void display_ensure_refreshed(void) { return; } - if (!is_mode_handler()) { + if (!is_mode_exception()) { bool copy_pending; // Wait until all frame buffers are written to the display diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h index bb6d7805a61..4bcad64c8c4 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h @@ -59,4 +59,9 @@ typedef struct { // Display driver instance extern display_driver_t g_display_driver; +static inline uint32_t is_mode_exception(void) { + uint32_t isr_number = __get_IPSR() & IPSR_ISR_Msk; + return (isr_number > 0) && (isr_number << 11); +} + #endif // TREZORHAL_DISPLAY_INTERNAL_H diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c index 57d2baf88e7..1f52fdfb253 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c @@ -22,7 +22,6 @@ #include "display_io.h" #include "irq.h" -#include "supervise.h" __IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS = (__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE); diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c index d21a8116a43..b6e189b0bf2 100644 --- a/core/embed/trezorhal/stm32u5/common.c +++ b/core/embed/trezorhal/stm32u5/common.c @@ -23,36 +23,15 @@ #include "common.h" #include "display.h" +#include "error_handling.h" #include "flash_otp.h" #include "model.h" #include "platform.h" #include "rand.h" #include "secret.h" -#include "supervise.h" #include "stm32u5xx_ll_utils.h" -// from util.s -extern void shutdown_privileged(void); - -void __attribute__((noreturn)) trezor_shutdown(void) { - display_deinit(DISPLAY_RETAIN_CONTENT); - - __HAL_RCC_SAES_CLK_DISABLE(); - // Erase all secrets - TAMP->CR2 |= TAMP_CR2_BKERASE; - -#ifdef USE_SVC_SHUTDOWN - svc_shutdown(); -#else - // It won't work properly unless called from the privileged mode - shutdown_privileged(); -#endif - - for (;;) - ; -} - uint32_t __stack_chk_guard = 0; void __attribute__((noreturn)) __stack_chk_fail(void) { diff --git a/core/embed/trezorhal/stm32u5/fault_handlers.c b/core/embed/trezorhal/stm32u5/fault_handlers.c index bf19c8e8ef3..4a358125860 100644 --- a/core/embed/trezorhal/stm32u5/fault_handlers.c +++ b/core/embed/trezorhal/stm32u5/fault_handlers.c @@ -34,3 +34,11 @@ void NMI_Handler(void) { error_shutdown("(CS)"); } } + +// from util.s +extern void shutdown_privileged(void); + +void PVD_PVM_IRQHandler(void) { + TIM1->CCR1 = 0; // turn off display backlight + shutdown_privileged(); +} diff --git a/core/embed/trezorhal/stm32u5/platform.c b/core/embed/trezorhal/stm32u5/platform.c index fd31a29e2b2..19feb4d5a4c 100644 --- a/core/embed/trezorhal/stm32u5/platform.c +++ b/core/embed/trezorhal/stm32u5/platform.c @@ -213,18 +213,3 @@ void SystemInit(void) { // enable instruction cache in default 2-way mode ICACHE->CR = ICACHE_CR_EN; } - -void drop_privileges(void) { - // jump to unprivileged mode - // http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/CHDBIBGJ.html - __asm__ volatile("msr control, %0" ::"r"(0x1)); - __asm__ volatile("isb"); -} - -// from util.s -extern void shutdown_privileged(void); - -void PVD_PVM_IRQHandler(void) { - TIM1->CCR1 = 0; // turn off display backlight - shutdown_privileged(); -} diff --git a/core/embed/trezorhal/stm32u5/platform.h b/core/embed/trezorhal/stm32u5/platform.h index fce29fb6ba5..55953cc5063 100644 --- a/core/embed/trezorhal/stm32u5/platform.h +++ b/core/embed/trezorhal/stm32u5/platform.h @@ -34,7 +34,6 @@ typedef enum { } clock_settings_t; void set_core_clock(clock_settings_t settings); -void drop_privileges(void); // the following functions are defined in util.s void memset_reg(volatile void *start, volatile void *stop, uint32_t val); diff --git a/core/embed/trezorhal/stm32u5/sdcard.c b/core/embed/trezorhal/stm32u5/sdcard.c index 1cfbc6522e2..b040e186a79 100644 --- a/core/embed/trezorhal/stm32u5/sdcard.c +++ b/core/embed/trezorhal/stm32u5/sdcard.c @@ -50,7 +50,6 @@ #include "irq.h" #include "sdcard.h" -#include "supervise.h" #define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC1_CLK_ENABLE() #define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC1_CLK_DISABLE() @@ -138,8 +137,8 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { SDMMC_CLK_ENABLE(); // NVIC configuration for SDIO interrupts - svc_setpriority(SDMMC_IRQn, IRQ_PRI_NORMAL); - svc_enableIRQ(SDMMC_IRQn); + NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(SDMMC_IRQn); } // GPIO have already been initialised by sdcard_init @@ -147,7 +146,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { if (hsd->Instance == sd_handle.Instance) { - svc_disableIRQ(SDMMC_IRQn); + NVIC_DisableIRQ(SDMMC_IRQn); SDMMC_CLK_DISABLE(); } } diff --git a/core/embed/trezorhal/stm32u5/supervise.c b/core/embed/trezorhal/stm32u5/supervise.c deleted file mode 120000 index 385e9d43cad..00000000000 --- a/core/embed/trezorhal/stm32u5/supervise.c +++ /dev/null @@ -1 +0,0 @@ -../stm32f4/supervise.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/supervise.h b/core/embed/trezorhal/stm32u5/supervise.h deleted file mode 120000 index f519770f494..00000000000 --- a/core/embed/trezorhal/stm32u5/supervise.h +++ /dev/null @@ -1 +0,0 @@ -../stm32f4/supervise.h \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/tamper.c b/core/embed/trezorhal/stm32u5/tamper.c index 9959aeaaa83..a2bbba546e1 100644 --- a/core/embed/trezorhal/stm32u5/tamper.c +++ b/core/embed/trezorhal/stm32u5/tamper.c @@ -17,8 +17,8 @@ * along with this program. If not, see . */ +#include #include -#include #include #include STM32_HAL_H diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index 627c5bee41c..36df4244dbf 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -54,7 +54,6 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/secret.c", "embed/trezorhal/stm32f4/systick.c", "embed/trezorhal/stm32f4/systimer.c", - "embed/trezorhal/stm32f4/supervise.c", "embed/trezorhal/stm32f4/time_estimate.c", "embed/trezorhal/stm32f4/random_delays.c", "embed/trezorhal/stm32f4/rng.c", diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index 5dba7f550c7..8bce578f0aa 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -65,7 +65,6 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/secure_aes.c", "embed/trezorhal/stm32u5/systick.c", "embed/trezorhal/stm32f4/systimer.c", - "embed/trezorhal/stm32f4/supervise.c", "embed/trezorhal/stm32u5/random_delays.c", "embed/trezorhal/stm32u5/rng.c", "embed/trezorhal/stm32u5/tamper.c", From 77f941ddb73df44635a7037d5981e4308af5a40a Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 8 Aug 2024 18:28:56 +0200 Subject: [PATCH 15/44] chore(embed/core): add include guard to translations.h [no changelog] --- core/embed/lib/translations.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/embed/lib/translations.h b/core/embed/lib/translations.h index 6fede56ce17..9e823650b57 100644 --- a/core/embed/lib/translations.h +++ b/core/embed/lib/translations.h @@ -1,3 +1,25 @@ +/* + * 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 . + */ + +#ifndef LIB_TRANSLATIONS_H +#define LIB_TRANSLATIONS_H + #include #include @@ -8,3 +30,5 @@ const uint8_t* translations_read(uint32_t* len, uint32_t offset); void translations_erase(void); uint32_t translations_area_bytesize(void); + +#endif // LIB_TRANSLATIONS_H From b0fe474cf8c4f5224b7a3bb589f9250aef527942 Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 8 Aug 2024 18:34:28 +0200 Subject: [PATCH 16/44] refactor(core/embed): make i2c header common for all platforms [no changelog] --- core/embed/trezorhal/i2c.h | 38 ++++++++++++++++++++++++++++++ core/embed/trezorhal/stm32f4/i2c.h | 15 ------------ core/embed/trezorhal/stm32u5/i2c.h | 1 - 3 files changed, 38 insertions(+), 16 deletions(-) create mode 100644 core/embed/trezorhal/i2c.h delete mode 100644 core/embed/trezorhal/stm32f4/i2c.h delete mode 120000 core/embed/trezorhal/stm32u5/i2c.h diff --git a/core/embed/trezorhal/i2c.h b/core/embed/trezorhal/i2c.h new file mode 100644 index 00000000000..54986043983 --- /dev/null +++ b/core/embed/trezorhal/i2c.h @@ -0,0 +1,38 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_I2C_H +#define TREZORHAL_I2C_H + +#include STM32_HAL_H + +void i2c_init(void); +void i2c_cycle(uint16_t idx); +HAL_StatusTypeDef i2c_transmit(uint16_t idx, uint8_t addr, uint8_t *data, + uint16_t len, uint32_t timeout); +HAL_StatusTypeDef i2c_receive(uint16_t idx, uint8_t addr, uint8_t *data, + uint16_t len, uint32_t timeout); +HAL_StatusTypeDef i2c_mem_write(uint16_t idx, uint8_t addr, uint16_t mem_addr, + uint16_t mem_addr_size, uint8_t *data, + uint16_t len, uint32_t timeout); +HAL_StatusTypeDef i2c_mem_read(uint16_t idx, uint8_t addr, uint16_t mem_addr, + uint16_t mem_addr_size, uint8_t *data, + uint16_t len, uint32_t timeout); + +#endif // TREZORHAL_I2C_H diff --git a/core/embed/trezorhal/stm32f4/i2c.h b/core/embed/trezorhal/stm32f4/i2c.h deleted file mode 100644 index cb0eec852ee..00000000000 --- a/core/embed/trezorhal/stm32f4/i2c.h +++ /dev/null @@ -1,15 +0,0 @@ - -#include STM32_HAL_H - -void i2c_init(void); -void i2c_cycle(uint16_t idx); -HAL_StatusTypeDef i2c_transmit(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout); -HAL_StatusTypeDef i2c_receive(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout); -HAL_StatusTypeDef i2c_mem_write(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout); -HAL_StatusTypeDef i2c_mem_read(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout); diff --git a/core/embed/trezorhal/stm32u5/i2c.h b/core/embed/trezorhal/stm32u5/i2c.h deleted file mode 120000 index d9235cabc4b..00000000000 --- a/core/embed/trezorhal/stm32u5/i2c.h +++ /dev/null @@ -1 +0,0 @@ -../stm32f4/i2c.h \ No newline at end of file From 53adc24c5fa45aeaa8232ac2452bcd27f075fa49 Mon Sep 17 00:00:00 2001 From: cepetr Date: Fri, 16 Aug 2024 12:11:38 +0200 Subject: [PATCH 17/44] refactor(core/embed): rename boot_args to bootuils [no changelog] --- core/SConscript.bootloader_emu | 2 +- core/SConscript.unix | 2 +- core/embed/bootloader/emulator.c | 2 +- core/embed/bootloader/main.c | 2 +- core/embed/bootloader/messages.c | 2 +- core/embed/extmod/modtrezorutils/modtrezorutils.c | 2 +- core/embed/lib/error_handling.c | 2 +- core/embed/prodtest/main.c | 2 +- core/embed/trezorhal/{boot_args.h => bootutils.h} | 6 +++--- core/embed/trezorhal/stm32f4/{boot_args.c => bootutils.c} | 2 +- core/embed/trezorhal/stm32u5/boot_args.c | 1 - core/embed/trezorhal/stm32u5/bootutils.c | 1 + core/embed/trezorhal/unix/{boot_args.c => bootutils.c} | 2 +- core/site_scons/models/stm32f4_common.py | 2 +- core/site_scons/models/stm32u5_common.py | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) rename core/embed/trezorhal/{boot_args.h => bootutils.h} (92%) rename core/embed/trezorhal/stm32f4/{boot_args.c => bootutils.c} (98%) delete mode 120000 core/embed/trezorhal/stm32u5/boot_args.c create mode 120000 core/embed/trezorhal/stm32u5/bootutils.c rename core/embed/trezorhal/unix/{boot_args.c => bootutils.c} (98%) diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index 9adc1a8465c..a3baaf07002 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -145,7 +145,7 @@ SOURCE_BOOTLOADER = [ ] SOURCE_TREZORHAL = [ - 'embed/trezorhal/unix/boot_args.c', + 'embed/trezorhal/unix/bootutils.c', 'embed/trezorhal/unix/common.c', 'embed/trezorhal/unix/fault_handlers.c', 'embed/trezorhal/unix/flash.c', diff --git a/core/SConscript.unix b/core/SConscript.unix index acd8e0285b8..bcf5d635cb8 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -418,7 +418,7 @@ SOURCE_MICROPYTHON = [ ] SOURCE_UNIX = [ - 'embed/trezorhal/unix/boot_args.c', + 'embed/trezorhal/unix/bootutils.c', 'embed/trezorhal/unix/common.c', 'embed/trezorhal/unix/flash_otp.c', 'embed/trezorhal/unix/flash.c', diff --git a/core/embed/bootloader/emulator.c b/core/embed/bootloader/emulator.c index d69d56dd72a..24fbfd620ba 100644 --- a/core/embed/bootloader/emulator.c +++ b/core/embed/bootloader/emulator.c @@ -2,8 +2,8 @@ #include #include TREZOR_BOARD -#include "boot_args.h" #include "bootui.h" +#include "bootutils.h" #include "common.h" #include "display.h" #include "flash.h" diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index ade9fcbb8dd..4080c508937 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -20,7 +20,7 @@ #include #include -#include "boot_args.h" +#include "bootutils.h" #include "common.h" #include "display.h" #include "display_utils.h" diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index 5006afb856f..2239880afdb 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -24,7 +24,7 @@ #include #include "messages.pb.h" -#include "boot_args.h" +#include "bootutils.h" #include "common.h" #include "flash.h" #include "image.h" diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index a18aaeea17c..f779864ef9a 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -30,7 +30,7 @@ #include #include "blake2s.h" -#include "boot_args.h" +#include "bootutils.h" #include "common.h" #include "flash.h" #include "unit_variant.h" diff --git a/core/embed/lib/error_handling.c b/core/embed/lib/error_handling.c index e4f8227fb33..0906598d28b 100644 --- a/core/embed/lib/error_handling.c +++ b/core/embed/lib/error_handling.c @@ -22,7 +22,7 @@ #include #endif -#include "boot_args.h" +#include "bootutils.h" #include "display.h" #include "error_handling.h" #include "mini_printf.h" diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index a40d06ad802..af08a91229f 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -25,7 +25,7 @@ #include STM32_HAL_H #include "board_capabilities.h" -#include "boot_args.h" +#include "bootutils.h" #include "button.h" #include "common.h" #include "display.h" diff --git a/core/embed/trezorhal/boot_args.h b/core/embed/trezorhal/bootutils.h similarity index 92% rename from core/embed/trezorhal/boot_args.h rename to core/embed/trezorhal/bootutils.h index 4fd4c1d5191..6a6d2f84219 100644 --- a/core/embed/trezorhal/boot_args.h +++ b/core/embed/trezorhal/bootutils.h @@ -1,5 +1,5 @@ -#ifndef TREZORHAL_BOOT_ARGS_H -#define TREZORHAL_BOOT_ARGS_H +#ifndef TREZORHAL_BOOTUTILS_H +#define TREZORHAL_BOOTUTILS_H #include #include @@ -40,4 +40,4 @@ void __attribute__((noreturn)) trezor_shutdown(void); void __attribute__((noreturn)) svc_reboot_to_bootloader(void); void __attribute__((noreturn)) svc_reboot(void); -#endif // TREZORHAL_BOOT_ARGS_H +#endif // TREZORHAL_BOOTUTILS_H diff --git a/core/embed/trezorhal/stm32f4/boot_args.c b/core/embed/trezorhal/stm32f4/bootutils.c similarity index 98% rename from core/embed/trezorhal/stm32f4/boot_args.c rename to core/embed/trezorhal/stm32f4/bootutils.c index 52bd4495569..d069545d19b 100644 --- a/core/embed/trezorhal/stm32f4/boot_args.c +++ b/core/embed/trezorhal/stm32f4/bootutils.c @@ -1,5 +1,5 @@ -#include "../boot_args.h" +#include "../bootutils.h" #include #include diff --git a/core/embed/trezorhal/stm32u5/boot_args.c b/core/embed/trezorhal/stm32u5/boot_args.c deleted file mode 120000 index ea7e8b6c203..00000000000 --- a/core/embed/trezorhal/stm32u5/boot_args.c +++ /dev/null @@ -1 +0,0 @@ -../stm32f4/boot_args.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/bootutils.c b/core/embed/trezorhal/stm32u5/bootutils.c new file mode 120000 index 00000000000..cdb656edf34 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/bootutils.c @@ -0,0 +1 @@ +../stm32f4/bootutils.c \ No newline at end of file diff --git a/core/embed/trezorhal/unix/boot_args.c b/core/embed/trezorhal/unix/bootutils.c similarity index 98% rename from core/embed/trezorhal/unix/boot_args.c rename to core/embed/trezorhal/unix/bootutils.c index b9765d43e02..f88e76de3e1 100644 --- a/core/embed/trezorhal/unix/boot_args.c +++ b/core/embed/trezorhal/unix/bootutils.c @@ -1,5 +1,5 @@ -#include "../boot_args.h" +#include "../bootutils.h" #include #include diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index 36df4244dbf..3c419450475 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -41,7 +41,7 @@ def stm32f4_common_files(env, defines, sources, paths): sources += [ "embed/trezorhal/stm32f4/board_capabilities.c", - "embed/trezorhal/stm32f4/boot_args.c", + "embed/trezorhal/stm32f4/bootutils.c", "embed/trezorhal/stm32f4/common.c", "embed/trezorhal/stm32f4/entropy.c", "embed/trezorhal/stm32f4/fault_handlers.c", diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index 8bce578f0aa..123f904fe9c 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -50,7 +50,7 @@ def stm32u5_common_files(env, defines, sources, paths): sources += [ "embed/trezorhal/stm32u5/board_capabilities.c", - "embed/trezorhal/stm32u5/boot_args.c", + "embed/trezorhal/stm32u5/bootutils.c", "embed/trezorhal/stm32u5/common.c", "embed/trezorhal/stm32u5/entropy.c", "embed/trezorhal/stm32u5/fault_handlers.c", From 12c338c1240d81a6119f2ccdd901ddfb3fb0a055 Mon Sep 17 00:00:00 2001 From: cepetr Date: Fri, 16 Aug 2024 13:33:58 +0200 Subject: [PATCH 18/44] refactor(core/embed): improve bootuils api [no changelog] --- core/embed/extmod/modtrezorutils/modtrezorutils.c | 2 +- core/embed/lib/error_handling.c | 4 ++-- core/embed/prodtest/main.c | 2 +- core/embed/rust/src/trezorhal/fatal_error.rs | 6 +++--- core/embed/trezorhal/bootutils.h | 15 +++++++++++---- core/embed/trezorhal/stm32f4/bootutils.c | 10 +++++----- core/embed/trezorhal/unix/bootutils.c | 12 ++++++++++++ core/embed/trezorhal/unix/common.c | 10 ---------- 8 files changed, 35 insertions(+), 26 deletions(-) diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index f779864ef9a..69d48673ae8 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -308,7 +308,7 @@ STATIC mp_obj_t mod_trezorutils_reboot_to_bootloader(size_t n_args, } bootargs_set(boot_command, boot_args.buf, boot_args.len); - svc_reboot_to_bootloader(); + reboot_to_bootloader(); #endif return mp_const_none; } diff --git a/core/embed/lib/error_handling.c b/core/embed/lib/error_handling.c index 0906598d28b..266df4f59a1 100644 --- a/core/embed/lib/error_handling.c +++ b/core/embed/lib/error_handling.c @@ -58,7 +58,7 @@ error_shutdown_ex(const char *title, const char *message, const char *footer) { } term_printf("\n%s\n", footer); display_backlight(255); - trezor_shutdown(); + secure_shutdown(); #endif } @@ -99,7 +99,7 @@ __fatal_error(const char *msg, const char *file, int line) { #endif term_printf("\nPlease contact Trezor support.\n"); display_backlight(255); - trezor_shutdown(); + secure_shutdown(); #endif } diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index af08a91229f..4712891ef77 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -763,7 +763,7 @@ static void test_otp_write_device_variant(const char *args) { vcp_println("OK"); } -static void test_reboot(void) { svc_reboot(); } +static void test_reboot(void) { reboot(); } void cpuid_read(void) { uint32_t cpuid[3]; diff --git a/core/embed/rust/src/trezorhal/fatal_error.rs b/core/embed/rust/src/trezorhal/fatal_error.rs index 20c9692bbb9..132c41eb1c5 100644 --- a/core/embed/rust/src/trezorhal/fatal_error.rs +++ b/core/embed/rust/src/trezorhal/fatal_error.rs @@ -1,7 +1,7 @@ mod ffi { extern "C" { - // trezorhal/common.c - pub fn trezor_shutdown() -> !; + // trezorhal/bootuils.c + pub fn secure_shutdown() -> !; } } @@ -11,7 +11,7 @@ use crate::ui::{ }; fn shutdown() -> ! { - unsafe { ffi::trezor_shutdown() } + unsafe { ffi::secure_shutdown() } } /// Shows an error message and shuts down the device. diff --git a/core/embed/trezorhal/bootutils.h b/core/embed/trezorhal/bootutils.h index 6a6d2f84219..acf89207518 100644 --- a/core/embed/trezorhal/bootutils.h +++ b/core/embed/trezorhal/bootutils.h @@ -4,7 +4,7 @@ #include #include -// Defines boot command for 'svc_reboot_to_bootloader()' function +// Defines boot command for 'reboot_to_bootloader()' function typedef enum { // Normal boot sequence BOOT_COMMAND_NONE = 0x00000000, @@ -36,8 +36,15 @@ boot_command_t bootargs_get_command(); // Returns the pointer to boot arguments const boot_args_t* bootargs_get_args(); -void __attribute__((noreturn)) trezor_shutdown(void); -void __attribute__((noreturn)) svc_reboot_to_bootloader(void); -void __attribute__((noreturn)) svc_reboot(void); +// Reboots the device into the bootloader. +// The bootloader will read the command set by `bootargs_set()`. +void __attribute__((noreturn)) reboot_to_bootloader(void); + +// Causes immediate reset of the device. +void __attribute__((noreturn)) reboot(void); + +// Safely shuts down the device (clears secrets, memory, etc.). +// This function is called when the device is in an unrecoverable state. +void __attribute__((noreturn)) secure_shutdown(void); #endif // TREZORHAL_BOOTUTILS_H diff --git a/core/embed/trezorhal/stm32f4/bootutils.c b/core/embed/trezorhal/stm32f4/bootutils.c index d069545d19b..08ffc2147c4 100644 --- a/core/embed/trezorhal/stm32f4/bootutils.c +++ b/core/embed/trezorhal/stm32f4/bootutils.c @@ -11,13 +11,13 @@ // to the bootloader. // 1. In the bootloader, its value is set in the startup code. // 2. In the firmware it holds command for the next boot and it is used -// when svc_reboot_to_bootloader() is called +// when reboot_to_bootloader() is called boot_command_t g_boot_command_shadow; #ifdef STM32U5 // The 'g_boot_command' is persistent variable that holds the 'command' // for the next reboot/jump to the bootloader. Its value is set to -// g_boot_command_shadow when 'svc_reboot_to_bootloader()' is called. +// g_boot_command_shadow when 'reboot_to_bootloader()' is called. boot_command_t __attribute__((section(".boot_command"))) g_boot_command; #endif @@ -47,7 +47,7 @@ boot_command_t bootargs_get_command() { return g_boot_command_shadow; } const boot_args_t* bootargs_get_args() { return &g_boot_args; } -void __attribute__((noreturn)) trezor_shutdown(void) { +void __attribute__((noreturn)) secure_shutdown(void) { display_deinit(DISPLAY_RETAIN_CONTENT); #if defined(STM32U5) @@ -63,7 +63,7 @@ void __attribute__((noreturn)) trezor_shutdown(void) { ; } -void svc_reboot_to_bootloader(void) { +void reboot_to_bootloader(void) { boot_command_t boot_command = bootargs_get_command(); display_deinit(DISPLAY_RESET_CONTENT); #ifdef ENSURE_COMPATIBLE_SETTINGS @@ -83,4 +83,4 @@ void svc_reboot_to_bootloader(void) { #endif } -void svc_reboot(void) { NVIC_SystemReset(); } +void reboot(void) { NVIC_SystemReset(); } diff --git a/core/embed/trezorhal/unix/bootutils.c b/core/embed/trezorhal/unix/bootutils.c index f88e76de3e1..a80e560a55a 100644 --- a/core/embed/trezorhal/unix/bootutils.c +++ b/core/embed/trezorhal/unix/bootutils.c @@ -1,6 +1,8 @@ #include "../bootutils.h" #include +#include +#include #include // The 'g_boot_command_shadow' variable stores the 'command' for the next @@ -42,3 +44,13 @@ void bootargs_clear() { boot_command_t bootargs_get_command() { return g_boot_command_shadow; } const boot_args_t* bootargs_get_args() { return &g_boot_args; } + +void __attribute__((noreturn)) secure_shutdown(void) { + printf("SHUTDOWN\n"); + + // Wait some time to let the user see the displayed + // message before shutting down + hal_delay(3000); + + exit(3); +} diff --git a/core/embed/trezorhal/unix/common.c b/core/embed/trezorhal/unix/common.c index 71830560aaf..de06ef6deeb 100644 --- a/core/embed/trezorhal/unix/common.c +++ b/core/embed/trezorhal/unix/common.c @@ -30,16 +30,6 @@ void __attribute__((noreturn)) main_clean_exit(); -void __attribute__((noreturn)) trezor_shutdown(void) { - printf("SHUTDOWN\n"); - - // Wait some time to let the user see the displayed - // message before shutting down - hal_delay(3000); - - exit(3); -} - static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) { switch (event->type) { case SDL_QUIT: From bdd60556c49c0cda0b7179dc46dc4339d81ef758 Mon Sep 17 00:00:00 2001 From: cepetr Date: Sun, 18 Aug 2024 12:00:30 +0200 Subject: [PATCH 19/44] refactor(core/embed): move __stack_chk_fail to a better location [no changelog] --- core/embed/lib/error_handling.c | 8 ++++++++ core/embed/trezorhal/stm32f4/common.c | 6 ------ core/embed/trezorhal/stm32u5/common.c | 6 ------ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/core/embed/lib/error_handling.c b/core/embed/lib/error_handling.c index 266df4f59a1..1f223176032 100644 --- a/core/embed/lib/error_handling.c +++ b/core/embed/lib/error_handling.c @@ -38,6 +38,14 @@ #define COLOR_FATAL_ERROR COLOR_BLACK #endif +uint32_t __stack_chk_guard = 0; + +// Calls to this function are inserted by the compiler +// when stack protection is enabled. +void __attribute__((noreturn, used)) __stack_chk_fail(void) { + error_shutdown("(SS)"); +} + void __attribute__((noreturn)) error_shutdown_ex(const char *title, const char *message, const char *footer) { if (title == NULL) { diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 327344525ab..339de063841 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -36,12 +36,6 @@ #include "backlight_pwm.h" #endif -uint32_t __stack_chk_guard = 0; - -void __attribute__((noreturn)) __stack_chk_fail(void) { - error_shutdown("(SS)"); -} - // 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) diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c index b6e189b0bf2..abf3d943f69 100644 --- a/core/embed/trezorhal/stm32u5/common.c +++ b/core/embed/trezorhal/stm32u5/common.c @@ -32,12 +32,6 @@ #include "stm32u5xx_ll_utils.h" -uint32_t __stack_chk_guard = 0; - -void __attribute__((noreturn)) __stack_chk_fail(void) { - error_shutdown("(SS)"); -} - void invalidate_firmware(void) { // on stm32u5, we need to disable the instruction cache before erasing the // firmware - otherwise, the write check will fail From ed1b17d7c1019430196aff753d6c230bd18ae00f Mon Sep 17 00:00:00 2001 From: cepetr Date: Sun, 18 Aug 2024 16:56:14 +0200 Subject: [PATCH 20/44] refactor(core/embed): introduce fwutils module [no changelog] --- core/embed/prodtest/main.c | 1 + core/embed/trezorhal/common.h | 4 --- core/embed/trezorhal/fwutils.h | 28 +++++++++++++++ core/embed/trezorhal/stm32f4/common.c | 11 ------ core/embed/trezorhal/stm32f4/fwutils.c | 43 ++++++++++++++++++++++++ core/embed/trezorhal/stm32u5/common.c | 15 --------- core/embed/trezorhal/stm32u5/fwutils.c | 1 + core/site_scons/models/stm32f4_common.py | 1 + core/site_scons/models/stm32u5_common.py | 1 + 9 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 core/embed/trezorhal/fwutils.h create mode 100644 core/embed/trezorhal/stm32f4/fwutils.c create mode 120000 core/embed/trezorhal/stm32u5/fwutils.c diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 4712891ef77..66114bfe7c3 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -34,6 +34,7 @@ #include "fault_handlers.h" #include "flash.h" #include "flash_otp.h" +#include "fwutils.h" #include "i2c.h" #include "image.h" #include "model.h" diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h index 457950dd463..6756030dd65 100644 --- a/core/embed/trezorhal/common.h +++ b/core/embed/trezorhal/common.h @@ -53,8 +53,4 @@ }) #endif -// Invalidates firmware on the device -// Note: only works when write access to firmware area is enabled by MPU -void invalidate_firmware(void); - #endif diff --git a/core/embed/trezorhal/fwutils.h b/core/embed/trezorhal/fwutils.h new file mode 100644 index 00000000000..26e484c8ff2 --- /dev/null +++ b/core/embed/trezorhal/fwutils.h @@ -0,0 +1,28 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_FWUTILS_H +#define TREZORHAL_FWUTILS_H + +// Invalidates the firmware by erasing the first 1KB of the firmware area. +// +// Note: only works when write access to firmware area is enabled by MPU +void invalidate_firmware(void); + +#endif // TREZORHAL_FWUTILS_H diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 339de063841..17395f72082 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -52,14 +52,3 @@ void clear_otg_hs_memory(void) { __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as // the peripheral is not needed right now } - -void invalidate_firmware(void) { - // erase start of the firmware (metadata) -> invalidate FW - ensure(flash_unlock_write(), NULL); - for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i += FLASH_BLOCK_SIZE) { - flash_block_t data = {0}; - ensure(flash_area_write_block(&FIRMWARE_AREA, i * FLASH_BLOCK_SIZE, data), - NULL); - } - ensure(flash_lock_write(), NULL); -} diff --git a/core/embed/trezorhal/stm32f4/fwutils.c b/core/embed/trezorhal/stm32f4/fwutils.c new file mode 100644 index 00000000000..1d5990e1176 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/fwutils.c @@ -0,0 +1,43 @@ +/* + * 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 STM32_HAL_H + +#include "fwutils.h" +#include "error_handling.h" +#include "flash.h" +#include "flash_area.h" +#include "model.h" + +void invalidate_firmware(void) { +#ifdef STM32U5 + // on stm32u5, we need to disable the instruction cache before erasing the + // firmware - otherwise, the write check will fail + ICACHE->CR &= ~ICACHE_CR_EN; +#endif + + // erase start of the firmware (metadata) -> invalidate FW + ensure(flash_unlock_write(), NULL); + for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i += FLASH_BLOCK_SIZE) { + flash_block_t data = {0}; + ensure(flash_area_write_block(&FIRMWARE_AREA, i * FLASH_BLOCK_SIZE, data), + NULL); + } + ensure(flash_lock_write(), NULL); +} diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c index abf3d943f69..5efbb408874 100644 --- a/core/embed/trezorhal/stm32u5/common.c +++ b/core/embed/trezorhal/stm32u5/common.c @@ -31,18 +31,3 @@ #include "secret.h" #include "stm32u5xx_ll_utils.h" - -void invalidate_firmware(void) { - // on stm32u5, we need to disable the instruction cache before erasing the - // firmware - otherwise, the write check will fail - ICACHE->CR &= ~ICACHE_CR_EN; - - // erase start of the firmware (metadata) -> invalidate FW - ensure(flash_unlock_write(), NULL); - for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i += FLASH_BLOCK_SIZE) { - flash_block_t data = {0}; - ensure(flash_area_write_block(&FIRMWARE_AREA, i * FLASH_BLOCK_SIZE, data), - NULL); - } - ensure(flash_lock_write(), NULL); -} diff --git a/core/embed/trezorhal/stm32u5/fwutils.c b/core/embed/trezorhal/stm32u5/fwutils.c new file mode 120000 index 00000000000..8968a5a0247 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/fwutils.c @@ -0,0 +1 @@ +../stm32f4/fwutils.c \ No newline at end of file diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index 3c419450475..b778ea860d5 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -47,6 +47,7 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/fault_handlers.c", "embed/trezorhal/stm32f4/flash.c", "embed/trezorhal/stm32f4/flash_otp.c", + "embed/trezorhal/stm32f4/fwutils.c", "embed/trezorhal/stm32f4/lowlevel.c", "embed/trezorhal/stm32f4/monoctr.c", "embed/trezorhal/stm32f4/mpu.c", diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index 123f904fe9c..7d9c4656732 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -56,6 +56,7 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/fault_handlers.c", "embed/trezorhal/stm32u5/flash.c", "embed/trezorhal/stm32u5/flash_otp.c", + "embed/trezorhal/stm32u5/fwutils.c", "embed/trezorhal/stm32u5/lowlevel.c", "embed/trezorhal/stm32u5/hash_processor.c", "embed/trezorhal/stm32u5/monoctr.c", From ef81fa63823e4d5eb48c9992851a66d336afed17 Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 20 Aug 2024 08:55:15 +0200 Subject: [PATCH 21/44] fix(core/embed): make HardFault processing safer [no changelog] --- core/embed/trezorhal/stm32u5/fault_handlers.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/embed/trezorhal/stm32u5/fault_handlers.c b/core/embed/trezorhal/stm32u5/fault_handlers.c index 4a358125860..d2cfd3bbd07 100644 --- a/core/embed/trezorhal/stm32u5/fault_handlers.c +++ b/core/embed/trezorhal/stm32u5/fault_handlers.c @@ -5,7 +5,16 @@ void fault_handlers_init(void) { SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk); } -void HardFault_Handler(void) { error_shutdown("(HF)"); } +void HardFault_Handler(void) { + // A HardFault may also be caused by exception escalation. + // To ensure we have enough space to handle the exception, + // we set the stack pointer to the end of the stack. + extern uint8_t _estack; // linker script symbol + // Fix stack pointer + __set_MSP((uint32_t)&_estack); + + error_shutdown("(HF)"); +} void MemManage_Handler(void) { error_shutdown("(MM)"); } From 9758a609c8c4a65406f2bcfca7082b7ca1c983ea Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 20 Aug 2024 08:53:22 +0200 Subject: [PATCH 22/44] fix(embed/core): fix stack protection on STM32U5 [no changelog] --- core/embed/boardloader/startup_stm32u5.s | 2 +- core/embed/bootloader/startup_stm32u5.s | 2 +- core/embed/bootloader_ci/startup_stm32u5.s | 2 +- core/embed/firmware/startup_stm32u5.S | 2 +- core/embed/prodtest/startup_stm32u5.s | 2 +- core/embed/reflash/startup_stm32u5.s | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/embed/boardloader/startup_stm32u5.s b/core/embed/boardloader/startup_stm32u5.s index fc30e4b6377..3665db2de58 100644 --- a/core/embed/boardloader/startup_stm32u5.s +++ b/core/embed/boardloader/startup_stm32u5.s @@ -7,7 +7,7 @@ reset_handler: // set the stack protection ldr r0, =_sstack - add r0, r0, #16 // padding + add r0, r0, #128 // safety margin for the exception frame msr MSPLIM, r0 bl SystemInit diff --git a/core/embed/bootloader/startup_stm32u5.s b/core/embed/bootloader/startup_stm32u5.s index 0f90b010878..6f5c36e73bc 100644 --- a/core/embed/bootloader/startup_stm32u5.s +++ b/core/embed/bootloader/startup_stm32u5.s @@ -7,7 +7,7 @@ reset_handler: // set the stack protection ldr r0, =_sstack - add r0, r0, #16 // padding + add r0, r0, #128 // safety margin for the exception frame msr MSPLIM, r0 // setup environment for subsequent stage of code diff --git a/core/embed/bootloader_ci/startup_stm32u5.s b/core/embed/bootloader_ci/startup_stm32u5.s index ab5b61495d4..707b7a320cf 100644 --- a/core/embed/bootloader_ci/startup_stm32u5.s +++ b/core/embed/bootloader_ci/startup_stm32u5.s @@ -7,7 +7,7 @@ reset_handler: // set the stack protection ldr r0, =_sstack - add r0, r0, #16 // padding + add r0, r0, #128 // safety margin for the exception frame msr MSPLIM, r0 // setup environment for subsequent stage of code diff --git a/core/embed/firmware/startup_stm32u5.S b/core/embed/firmware/startup_stm32u5.S index f37f5b09285..db9a204c319 100644 --- a/core/embed/firmware/startup_stm32u5.S +++ b/core/embed/firmware/startup_stm32u5.S @@ -7,7 +7,7 @@ reset_handler: // set the stack protection ldr r0, =_sstack - add r0, r0, #16 // padding + add r0, r0, #128 // safety margin for the exception frame msr MSPLIM, r0 // setup environment for subsequent stage of code diff --git a/core/embed/prodtest/startup_stm32u5.s b/core/embed/prodtest/startup_stm32u5.s index f37f5b09285..db9a204c319 100644 --- a/core/embed/prodtest/startup_stm32u5.s +++ b/core/embed/prodtest/startup_stm32u5.s @@ -7,7 +7,7 @@ reset_handler: // set the stack protection ldr r0, =_sstack - add r0, r0, #16 // padding + add r0, r0, #128 // safety margin for the exception frame msr MSPLIM, r0 // setup environment for subsequent stage of code diff --git a/core/embed/reflash/startup_stm32u5.s b/core/embed/reflash/startup_stm32u5.s index f37f5b09285..db9a204c319 100644 --- a/core/embed/reflash/startup_stm32u5.s +++ b/core/embed/reflash/startup_stm32u5.s @@ -7,7 +7,7 @@ reset_handler: // set the stack protection ldr r0, =_sstack - add r0, r0, #16 // padding + add r0, r0, #128 // safety margin for the exception frame msr MSPLIM, r0 // setup environment for subsequent stage of code From 53547fc701b98477e751cb18cdbe1ce0c675b595 Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 27 Aug 2024 11:16:04 +0200 Subject: [PATCH 23/44] fix(core/embed): fix prodtest build [no changelog] --- core/embed/prodtest/memory_stm32f4.ld | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/embed/prodtest/memory_stm32f4.ld b/core/embed/prodtest/memory_stm32f4.ld index 61f7112ba83..4553af4e5a6 100644 --- a/core/embed/prodtest/memory_stm32f4.ld +++ b/core/embed/prodtest/memory_stm32f4.ld @@ -54,7 +54,11 @@ SECTIONS { . = ALIGN(4); *(.rodata*); . = ALIGN(128K); - } >FLASH AT>FLASH + } >FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } .data : ALIGN(4) { *(.data*); From 3f648be8f1b8643a3b6e774e8068feab7fb7afbc Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 27 Aug 2024 18:01:59 +0200 Subject: [PATCH 24/44] feat(code/embed): introduce ARRAY_LENGTH macro [no changelog] --- core/embed/trezorhal/common.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h index 6756030dd65..3c92580c84a 100644 --- a/core/embed/trezorhal/common.h +++ b/core/embed/trezorhal/common.h @@ -53,4 +53,6 @@ }) #endif +#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) + #endif From fa9f7d6c5fa7168cdc7f4bc9fa8b62cd6bc12e52 Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 27 Aug 2024 11:13:10 +0200 Subject: [PATCH 25/44] feat(core/embed): introduce non-blocking i2c drivers [no changelog] --- .../models/D001/boards/stm32f429i-disc1.h | 8 +- core/embed/models/D002/boards/stm32u5a9j-dk.h | 5 + core/embed/models/T2B1/boards/trezor_r_v10.h | 8 +- core/embed/models/T2T1/boards/trezor_t.h | 8 +- .../models/T3B1/boards/trezor_t3b1_revB.h | 5 + .../models/T3T1/boards/trezor_t3t1_revE.h | 15 + .../embed/models/T3T1/boards/trezor_t3t1_v4.h | 10 + core/embed/trezorhal/i2c_bus.h | 185 ++++ core/embed/trezorhal/stm32f4/i2c.c | 4 +- core/embed/trezorhal/stm32f4/i2c_bus.c | 936 ++++++++++++++++++ core/embed/trezorhal/stm32f4/systimer.c | 2 +- core/embed/trezorhal/stm32u5/i2c_bus.c | 894 +++++++++++++++++ core/site_scons/models/D001/discovery.py | 1 + core/site_scons/models/D002/discovery2.py | 5 +- core/site_scons/models/T2B1/trezor_r_v10.py | 6 +- core/site_scons/models/T2T1/trezor_t.py | 2 + .../models/T3B1/trezor_t3b1_revB.py | 1 + .../models/T3T1/trezor_t3t1_revE.py | 1 + core/site_scons/models/T3T1/trezor_t3t1_v4.py | 5 +- 19 files changed, 2090 insertions(+), 11 deletions(-) create mode 100644 core/embed/trezorhal/i2c_bus.h create mode 100644 core/embed/trezorhal/stm32f4/i2c_bus.c create mode 100644 core/embed/trezorhal/stm32u5/i2c_bus.c diff --git a/core/embed/models/D001/boards/stm32f429i-disc1.h b/core/embed/models/D001/boards/stm32f429i-disc1.h index cd37a97124e..28198342d25 100644 --- a/core/embed/models/D001/boards/stm32f429i-disc1.h +++ b/core/embed/models/D001/boards/stm32f429i-disc1.h @@ -24,7 +24,13 @@ #define I2C_INSTANCE_0_SCL_PORT GPIOA #define I2C_INSTANCE_0_SCL_PIN GPIO_PIN_8 #define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOA_CLK_ENABLE -#define I2C_INSTANCE_0_RESET_FLG RCC_APB1RSTR_I2C3RST +#define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR +#define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR_I2C3RST +#define I2C_INSTANCE_0_EV_IRQHandler I2C3_EV_IRQHandler +#define I2C_INSTANCE_0_ER_IRQHandler I2C3_ER_IRQHandler +#define I2C_INSTANCE_0_EV_IRQn I2C3_EV_IRQn +#define I2C_INSTANCE_0_ER_IRQn I2C3_ER_IRQn +#define I2C_INSTANCE_0_GUARD_TIME 0 #define TOUCH_I2C_INSTANCE 0 diff --git a/core/embed/models/D002/boards/stm32u5a9j-dk.h b/core/embed/models/D002/boards/stm32u5a9j-dk.h index baf3e711715..059fac72b06 100644 --- a/core/embed/models/D002/boards/stm32u5a9j-dk.h +++ b/core/embed/models/D002/boards/stm32u5a9j-dk.h @@ -30,6 +30,11 @@ #define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOH_CLK_ENABLE #define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR2 #define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR2_I2C5RST +#define I2C_INSTANCE_0_EV_IRQHandler I2C5_EV_IRQHandler +#define I2C_INSTANCE_0_ER_IRQHandler I2C5_ER_IRQHandler +#define I2C_INSTANCE_0_EV_IRQn I2C5_EV_IRQn +#define I2C_INSTANCE_0_ER_IRQn I2C5_ER_IRQn +#define I2C_INSTANCE_0_GUARD_TIME 0 #define TOUCH_I2C_INSTANCE 0 diff --git a/core/embed/models/T2B1/boards/trezor_r_v10.h b/core/embed/models/T2B1/boards/trezor_r_v10.h index b48479d526b..24cda1e8ccf 100644 --- a/core/embed/models/T2B1/boards/trezor_r_v10.h +++ b/core/embed/models/T2B1/boards/trezor_r_v10.h @@ -50,7 +50,13 @@ #define I2C_INSTANCE_0_SCL_PORT GPIOB #define I2C_INSTANCE_0_SCL_PIN GPIO_PIN_10 #define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE -#define I2C_INSTANCE_0_RESET_FLG RCC_APB1RSTR_I2C2RST +#define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR +#define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR_I2C2RST +#define I2C_INSTANCE_0_EV_IRQHandler I2C2_EV_IRQHandler +#define I2C_INSTANCE_0_ER_IRQHandler I2C2_ER_IRQHandler +#define I2C_INSTANCE_0_EV_IRQn I2C2_EV_IRQn +#define I2C_INSTANCE_0_ER_IRQn I2C2_ER_IRQn +#define I2C_INSTANCE_0_GUARD_TIME 50 // Optiga requires 50us guard time #define OPTIGA_I2C_INSTANCE 0 #define OPTIGA_RST_PORT GPIOD diff --git a/core/embed/models/T2T1/boards/trezor_t.h b/core/embed/models/T2T1/boards/trezor_t.h index 25a8711b719..60d569648b2 100644 --- a/core/embed/models/T2T1/boards/trezor_t.h +++ b/core/embed/models/T2T1/boards/trezor_t.h @@ -42,7 +42,13 @@ #define I2C_INSTANCE_0_SCL_PORT GPIOB #define I2C_INSTANCE_0_SCL_PIN GPIO_PIN_6 #define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE -#define I2C_INSTANCE_0_RESET_FLG RCC_APB1RSTR_I2C1RST +#define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR +#define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR_I2C1RST +#define I2C_INSTANCE_0_EV_IRQHandler I2C1_EV_IRQHandler +#define I2C_INSTANCE_0_ER_IRQHandler I2C1_ER_IRQHandler +#define I2C_INSTANCE_0_EV_IRQn I2C1_EV_IRQn +#define I2C_INSTANCE_0_ER_IRQn I2C1_ER_IRQn +#define I2C_INSTANCE_0_GUARD_TIME 0 #define TOUCH_SENSITIVITY 0x06 #define TOUCH_I2C_INSTANCE 0 diff --git a/core/embed/models/T3B1/boards/trezor_t3b1_revB.h b/core/embed/models/T3B1/boards/trezor_t3b1_revB.h index e91a2952d2a..7c57e7623d0 100644 --- a/core/embed/models/T3B1/boards/trezor_t3b1_revB.h +++ b/core/embed/models/T3B1/boards/trezor_t3b1_revB.h @@ -54,6 +54,11 @@ #define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE #define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR1 #define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR1_I2C1RST +#define I2C_INSTANCE_0_EV_IRQHandler I2C1_EV_IRQHandler +#define I2C_INSTANCE_0_ER_IRQHandler I2C1_ER_IRQHandler +#define I2C_INSTANCE_0_EV_IRQn I2C1_EV_IRQn +#define I2C_INSTANCE_0_ER_IRQn I2C1_ER_IRQn +#define I2C_INSTANCE_0_GUARD_TIME 50 // Optiga requires 50us guard time #define OPTIGA_I2C_INSTANCE 0 #define OPTIGA_RST_PORT GPIOE diff --git a/core/embed/models/T3T1/boards/trezor_t3t1_revE.h b/core/embed/models/T3T1/boards/trezor_t3t1_revE.h index 591ff37b52b..425b9afc498 100644 --- a/core/embed/models/T3T1/boards/trezor_t3t1_revE.h +++ b/core/embed/models/T3T1/boards/trezor_t3t1_revE.h @@ -50,6 +50,11 @@ #define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE #define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR1 #define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR1_I2C1RST +#define I2C_INSTANCE_0_EV_IRQHandler I2C1_EV_IRQHandler +#define I2C_INSTANCE_0_ER_IRQHandler I2C1_ER_IRQHandler +#define I2C_INSTANCE_0_EV_IRQn I2C1_EV_IRQn +#define I2C_INSTANCE_0_ER_IRQn I2C1_ER_IRQn +#define I2C_INSTANCE_0_GUARD_TIME 0 #define I2C_INSTANCE_1 I2C2 #define I2C_INSTANCE_1_CLK_EN __HAL_RCC_I2C2_CLK_ENABLE @@ -63,6 +68,11 @@ #define I2C_INSTANCE_1_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE #define I2C_INSTANCE_1_RESET_REG &RCC->APB1RSTR1 #define I2C_INSTANCE_1_RESET_BIT RCC_APB1RSTR1_I2C2RST +#define I2C_INSTANCE_1_EV_IRQHandler I2C2_EV_IRQHandler +#define I2C_INSTANCE_1_ER_IRQHandler I2C2_ER_IRQHandler +#define I2C_INSTANCE_1_EV_IRQn I2C2_EV_IRQn +#define I2C_INSTANCE_1_ER_IRQn I2C2_ER_IRQn +#define I2C_INSTANCE_1_GUARD_TIME 0 #define I2C_INSTANCE_2 I2C3 #define I2C_INSTANCE_2_CLK_EN __HAL_RCC_I2C3_CLK_ENABLE @@ -76,6 +86,11 @@ #define I2C_INSTANCE_2_SCL_CLK_EN __HAL_RCC_GPIOC_CLK_ENABLE #define I2C_INSTANCE_2_RESET_REG &RCC->APB3RSTR #define I2C_INSTANCE_2_RESET_BIT RCC_APB3RSTR_I2C3RST +#define I2C_INSTANCE_2_EV_IRQHandler I2C3_EV_IRQHandler +#define I2C_INSTANCE_2_ER_IRQHandler I2C3_ER_IRQHandler +#define I2C_INSTANCE_2_EV_IRQn I2C3_EV_IRQn +#define I2C_INSTANCE_2_ER_IRQn I2C3_ER_IRQn +#define I2C_INSTANCE_2_GUARD_TIME 50 // Optiga requires 50us guard time #define TOUCH_PANEL_LX154A2422CPT23 1 #define TOUCH_SENSITIVITY 0x40 diff --git a/core/embed/models/T3T1/boards/trezor_t3t1_v4.h b/core/embed/models/T3T1/boards/trezor_t3t1_v4.h index bf2c0a00d8d..1a8741e0a5f 100644 --- a/core/embed/models/T3T1/boards/trezor_t3t1_v4.h +++ b/core/embed/models/T3T1/boards/trezor_t3t1_v4.h @@ -51,6 +51,11 @@ #define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE #define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR1 #define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR1_I2C1RST +#define I2C_INSTANCE_0_EV_IRQHandler I2C1_EV_IRQHandler +#define I2C_INSTANCE_0_ER_IRQHandler I2C1_ER_IRQHandler +#define I2C_INSTANCE_0_EV_IRQn I2C1_EV_IRQn +#define I2C_INSTANCE_0_ER_IRQn I2C1_ER_IRQn +#define I2C_INSTANCE_0_GUARD_TIME 0 #define I2C_INSTANCE_1 I2C2 #define I2C_INSTANCE_1_CLK_EN __HAL_RCC_I2C2_CLK_ENABLE @@ -64,6 +69,11 @@ #define I2C_INSTANCE_1_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE #define I2C_INSTANCE_1_RESET_REG &RCC->APB1RSTR1 #define I2C_INSTANCE_1_RESET_BIT RCC_APB1RSTR1_I2C2RST +#define I2C_INSTANCE_1_EV_IRQHandler I2C2_EV_IRQHandler +#define I2C_INSTANCE_1_ER_IRQHandler I2C2_ER_IRQHandler +#define I2C_INSTANCE_1_EV_IRQn I2C2_EV_IRQn +#define I2C_INSTANCE_1_ER_IRQn I2C2_ER_IRQn +#define I2C_INSTANCE_1_GUARD_TIME 50 // Optiga requires 50us guard time #define TOUCH_SENSITIVITY 0x40 #define TOUCH_I2C_INSTANCE 0 diff --git a/core/embed/trezorhal/i2c_bus.h b/core/embed/trezorhal/i2c_bus.h new file mode 100644 index 00000000000..3203fcaa06f --- /dev/null +++ b/core/embed/trezorhal/i2c_bus.h @@ -0,0 +1,185 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_I2C_BUS_H +#define TREZORHAL_I2C_BUS_H + +#include +#include +#include + +// I2C bus abstraction +typedef struct i2c_bus i2c_bus_t; +// I2C packet (series of I2C operations) +typedef struct i2c_packet i2c_packet_t; +// I2C operation (single transfer) +typedef struct i2c_op i2c_op_t; + +// Completion callback +typedef void (*i2c_callback_t)(void* context, i2c_packet_t* packet); + +// I2C packet status +typedef enum { + I2C_STATUS_OK = 0, // Packet completed successfully + I2C_STATUS_PENDING = 1, // Packet is pending + I2C_STATUS_INVARG = 2, // Invalid packet/op parameters + I2C_STATUS_BUSY = 3, // Bus is busy + I2C_STATUS_TIMEOUT = 4, // Timeout occurred + I2C_STATUS_NACK = 5, // Device did not acknowledge + I2C_STATUS_ERROR = 6, // General error + I2C_STATUS_ABORTED = 7, // Packet was aborted + +} i2c_status_t; + +struct i2c_packet { + // Next packet in the driver queue + i2c_packet_t* next; + // I2C device address (7-bit address) + uint8_t address; + // Extra timeout (in milliseconds) added to the default timeout + // to finish each operation + uint16_t timeout; + // I2C_STATUS_xxx + i2c_status_t status; + // Number of operations + uint8_t op_count; + // Pointer to array of operations + i2c_op_t* ops; + // Completion callback function + i2c_callback_t callback; + // Callback context (user provided data) + void* context; +}; + +// I2C operation flags +#define I2C_FLAG_START 0x0001 // Generate START condition before the operation +#define I2C_FLAG_STOP 0x0002 // Generate STOP after the operation +#define I2C_FLAG_TX 0x0004 // Transmit data +#define I2C_FLAG_RX 0x0008 // Receive data +#define I2C_FLAG_EMBED 0x0010 // Embedded data (no reference) + +// I2C operation flags constraints: +// 1) I2C_FLAG_TX | I2C_FLAG_RX is not allowed +// 2) if I2C_FLAG_EMBED is set, size must be <= 4 + +struct i2c_op { + // I2C_FLAG_xxx + uint16_t flags; + // Number of bytes to transfer + uint16_t size; + // Data to read or write + union { + // Pointer to data (I2C_FLAG_EMBED is not set) + void* ptr; + // Embedded data (I2C_FLAG_EMBED is set) + uint8_t data[4]; + }; +}; + +// Acquires I2C bus reference by index (0..2 according to the model) +// +// Returns NULL if bus is not available or can't be initialized. +// +// If the bus was not acquired before, it will be initialized. +i2c_bus_t* i2c_bus_open(uint8_t bus_index); + +// Closes I2C bus handle +// +// After releasing the last bus reference, the bus will be deinitialized. +void i2c_bus_close(i2c_bus_t* bus); + +// Submits I2C packet to the bus +// +// After submitting the packet, the packet status will be set to +// I2C_STATUS_PENDING until the packet is completed. +// +// The caller must not modify the packet (or data pointed by the packet) +// until the packet is completed (callback is called or status +// is not I2C_STATUS_PENDING). +// +// Returns: +// I2C_STATUS_OK -- packet was successfully submitted +i2c_status_t i2c_bus_submit(i2c_bus_t* bus, i2c_packet_t* packet); + +// Aborts pending or queue packet +// +// Immediately after calling this function, the packet status will be +// set to I2C_STATUS_ABORTED and I2C driver will not access the packet anymore. +// +// If the packet is already completed, it does nothing. +// If the packet is queued it will be removed from the queue. +// If the packet is pending, it will be aborted. +// In any case completion callback will not be called. +void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet); + +// Returns I2C packet status +// +// If the packet is not completed yet, it returns I2C_STATUS_PENDING. +i2c_status_t i2c_packet_status(const i2c_packet_t* packet); + +// Waits until I2C packet is completed and returns its final status +i2c_status_t i2c_packet_wait(const i2c_packet_t* packet); + +// Helper function to submit and wait for the packet +static inline i2c_status_t i2c_bus_submit_and_wait(i2c_bus_t* bus, + i2c_packet_t* packet) { + i2c_status_t status = i2c_bus_submit(bus, packet); + if (status == I2C_STATUS_OK) { + status = i2c_packet_wait(packet); + } + return status; +} + +/* +void example() { + + i2c_bus_t* bus = i2c_bus_open(DEVICE_I2C_INSTANCE); + + static uint8_t data_out; + + static i2c_op_t ops[] = { + { + .flags = I2C_FLAG_TX | I2C_FLAG_EMBED, + .size = 1, + .data = {0x01}, + }, + { + .flags = I2C_FLAG_RX, + .size = sizeof(data_out), + .ptr = &data_out, + }, + }; + + static i2c_packet_t pkt = { + .callback = NULL, + .context = NULL, + .address = DEVICE_I2C_ADDRESS, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + + status = i2c_bus_submit(bus, &pkt); + + status = i2c_packet_wait(&pkt); + + i2c_bus_close(&bus); +} +*/ + +#endif // TREZORHAL_I2C_BUS_H diff --git a/core/embed/trezorhal/stm32f4/i2c.c b/core/embed/trezorhal/stm32f4/i2c.c index 319342b7657..a6b124ae024 100644 --- a/core/embed/trezorhal/stm32f4/i2c.c +++ b/core/embed/trezorhal/stm32f4/i2c.c @@ -25,7 +25,7 @@ i2c_instance_t i2c_defs[I2C_COUNT] = { .SclPin = I2C_INSTANCE_0_SCL_PIN, .SdaPin = I2C_INSTANCE_0_SDA_PIN, .PinAF = I2C_INSTANCE_0_PIN_AF, - .Reset = I2C_INSTANCE_0_RESET_FLG, + .Reset = I2C_INSTANCE_0_RESET_BIT, }, #ifdef I2C_INSTANCE_1 { @@ -35,7 +35,7 @@ i2c_instance_t i2c_defs[I2C_COUNT] = { .SclPin = I2C_INSTANCE_1_SCL_PIN, .SdaPin = I2C_INSTANCE_1_SDA_PIN, .PinAF = I2C_INSTANCE_1_PIN_AF, - .Reset = I2C_INSTANCE_1_RESET_FLG, + .Reset = I2C_INSTANCE_1_RESET_BIT, }, #endif diff --git a/core/embed/trezorhal/stm32f4/i2c_bus.c b/core/embed/trezorhal/stm32f4/i2c_bus.c new file mode 100644 index 00000000000..c5769e2e4d6 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/i2c_bus.c @@ -0,0 +1,936 @@ +/* + * 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 STM32_HAL_H +#include TREZOR_BOARD + +#include + +#include "common.h" +#include "i2c_bus.h" +#include "irq.h" +#include "systimer.h" + +// I2C bus SCL clock frequency +#define I2C_BUS_SCL_FREQ 200000 // Hz + +// We expect the I2C bus to be running at ~200kHz +// and max response time of the device is 1000us +#define I2C_BUS_CHAR_TIMEOUT (50 + 5) // us +#define I2C_BUS_OP_TIMEOUT 1000 // us + +#define I2C_BUS_TIMEOUT(n) \ + ((I2C_BUS_CHAR_TIMEOUT * (1 + n) + I2C_BUS_OP_TIMEOUT + 999) / 1000) + +// I2C bus hardware definition +typedef struct { + // I2C controller registers + I2C_TypeDef* regs; + // SCL pin GPIO port + GPIO_TypeDef* scl_port; + // SDA pin GPIO port + GPIO_TypeDef* sda_port; + // SCL pin number + uint16_t scl_pin; + // SDA pin number + uint16_t sda_pin; + // Alternate function for SCL and SDA pins + uint8_t pin_af; + // Register for I2C controller reset + volatile uint32_t* reset_reg; + // Reset bit specific for this I2C controller + uint32_t reset_bit; + // I2C event IRQ number + uint32_t ev_irq; + // I2C error IRQ number + uint32_t er_irq; + // Guard time [us] between STOP and START condition. + // If zero, the guard time is not used. + uint16_t guard_time; +} i2c_bus_def_t; + +// I2C bus hardware definitions +static const i2c_bus_def_t g_i2c_bus_def[I2C_COUNT] = { + { + .regs = I2C_INSTANCE_0, + .scl_port = I2C_INSTANCE_0_SCL_PORT, + .sda_port = I2C_INSTANCE_0_SDA_PORT, + .scl_pin = I2C_INSTANCE_0_SCL_PIN, + .sda_pin = I2C_INSTANCE_0_SDA_PIN, + .pin_af = I2C_INSTANCE_0_PIN_AF, + .reset_reg = I2C_INSTANCE_0_RESET_REG, + .reset_bit = I2C_INSTANCE_0_RESET_BIT, + .ev_irq = I2C_INSTANCE_0_EV_IRQn, + .er_irq = I2C_INSTANCE_0_ER_IRQn, + .guard_time = I2C_INSTANCE_0_GUARD_TIME, + }, +#ifdef I2C_INSTANCE_1 + { + .regs = I2C_INSTANCE_1, + .scl_port = I2C_INSTANCE_1_SCL_PORT, + .sda_port = I2C_INSTANCE_1_SDA_PORT, + .scl_pin = I2C_INSTANCE_1_SCL_PIN, + .sda_pin = I2C_INSTANCE_1_SDA_PIN, + .pin_af = I2C_INSTANCE_1_PIN_AF, + .reset_reg = I2C_INSTANCE_1_RESET_REG, + .reset_bit = I2C_INSTANCE_1_RESET_BIT, + .ev_irq = I2C_INSTANCE_1_EV_IRQn, + .er_irq = I2C_INSTANCE_1_ER_IRQn, + .guard_time = I2C_INSTANCE_1_GUARD_TIME, + }, +#endif +#ifdef I2C_INSTANCE_2 + { + .regs = I2C_INSTANCE_2, + .scl_port = I2C_INSTANCE_2_SCL_PORT, + .sda_port = I2C_INSTANCE_2_SDA_PORT, + .scl_pin = I2C_INSTANCE_2_SCL_PIN, + .sda_pin = I2C_INSTANCE_2_SDA_PIN, + .pin_af = I2C_INSTANCE_2_PIN_AF, + .reset_reg = I2C_INSTANCE_2_RESET_REG, + .reset_bit = I2C_INSTANCE_2_RESET_BIT, + .ev_irq = I2C_INSTANCE_2_EV_IRQn, + .er_irq = I2C_INSTANCE_2_ER_IRQn, + .guard_time = I2C_INSTANCE_2_GUARD_TIME, + }, +#endif +}; + +struct i2c_bus { + // Number of references to the bus + // (0 means the bus is not initialized) + uint32_t refcount; + + // Hardware definition + const i2c_bus_def_t* def; + + // Timer for timeout handling + systimer_t* timer; + + // Head of the packet queue + // (this packet is currently being processed) + i2c_packet_t* queue_head; + // Tail of the packet queue + // (this packet is the last in the queue) + i2c_packet_t* queue_tail; + + // Next operation index in the current packet + // == 0 => no operation is being processed + // == queue_head->op_count => no more operations + int next_op; + + // Current operation address byte + uint8_t addr_byte; + // Points to the data buffer of the current operation + uint8_t* buff_ptr; + // Remaining number of bytes of the buffer to transfer + uint16_t buff_size; + // Remaining number of bytes of the current operation + // (if the transfer is split into multiple operations it + // may be different from buff_size) + uint16_t transfer_size; + // For case of split transfer, points to the next operation + // that is part of the current transfer + int transfer_op; + + // Set if the STOP condition is requested after the current operation + // when data transfer is completed. + bool stop_requested; + // Set if pending transaction is being aborted + bool abort_pending; + + // Flag indicating that the completion callback is being executed + bool callback_executed; + + // The last time [us] the STOP condition was issued + uint64_t stop_time; +}; + +// I2C bus driver instances +static i2c_bus_t g_i2c_bus_driver[I2C_COUNT] = {0}; + +// Check if the I2C bus pointer is valid +static inline bool i2c_bus_ptr_valid(const i2c_bus_t* bus) { + if (bus >= &g_i2c_bus_driver[0] && bus < &g_i2c_bus_driver[I2C_COUNT]) { + uintptr_t offset = (uintptr_t)bus - (uintptr_t)&g_i2c_bus_driver[0]; + if (offset % sizeof(i2c_bus_t) == 0) { + return bus->refcount > 0; + } + } + return false; +} + +// forward declarations +static void i2c_bus_timer_callback(void* context); +static void i2c_bus_head_continue(i2c_bus_t* bus); + +static void i2c_bus_unlock(i2c_bus_t* bus) { + const i2c_bus_def_t* def = bus->def; + + GPIO_InitTypeDef GPIO_InitStructure = {0}; + + // Set SDA and SCL high + HAL_GPIO_WritePin(def->sda_port, def->sda_pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(def->scl_port, def->scl_pin, GPIO_PIN_SET); + + // Configure SDA and SCL as open-drain output + // and connect to the I2C peripheral + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + + GPIO_InitStructure.Pin = def->scl_pin; + HAL_GPIO_Init(def->scl_port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = def->sda_pin; + HAL_GPIO_Init(def->sda_port, &GPIO_InitStructure); + + uint32_t clock_count = 16; + + while ((HAL_GPIO_ReadPin(def->sda_port, def->sda_pin) == GPIO_PIN_RESET) && + (clock_count-- > 0)) { + // Clock SCL + HAL_GPIO_WritePin(def->scl_port, def->scl_pin, GPIO_PIN_RESET); + systick_delay_us(10); + HAL_GPIO_WritePin(def->scl_port, def->scl_pin, GPIO_PIN_SET); + systick_delay_us(10); + } +} + +static void i2c_bus_reset(i2c_bus_t* bus) { + const i2c_bus_def_t* def = bus->def; + + // Reset I2C peripheral + *def->reset_reg |= def->reset_bit; + *def->reset_reg &= ~def->reset_bit; + + I2C_TypeDef* regs = def->regs; + + // Configure I2C peripheral + + uint32_t pclk_hz = HAL_RCC_GetPCLK1Freq(); + uint32_t pclk_mhz = I2C_FREQRANGE(pclk_hz); + uint32_t i2c_speed_hz = I2C_BUS_SCL_FREQ; + + regs->CR1 = 0; + regs->TRISE = I2C_RISE_TIME(pclk_mhz, i2c_speed_hz); + regs->CR2 = pclk_mhz; + regs->CCR = I2C_SPEED(pclk_hz, i2c_speed_hz, I2C_DUTYCYCLE_16_9); + regs->FLTR = 0; + regs->OAR1 = 0; + regs->OAR2 = 0; + regs->CR1 |= I2C_CR1_PE; +} + +static void i2c_bus_deinit(i2c_bus_t* bus) { + const i2c_bus_def_t* def = bus->def; + + systimer_delete(bus->timer); + + if (bus->def == NULL) { + return; + } + + NVIC_DisableIRQ(def->ev_irq); + NVIC_DisableIRQ(def->er_irq); + + I2C_TypeDef* regs = def->regs; + + // Disable I2C peripheral + regs->CR1 = 0; + + // Reset I2C peripheral + *def->reset_reg |= def->reset_bit; + *def->reset_reg &= ~def->reset_bit; + + bus->def = NULL; +} + +static bool i2c_bus_init(i2c_bus_t* bus, int bus_index) { + memset(bus, 0, sizeof(i2c_bus_t)); + + switch (bus_index) { + case 0: + // enable I2C clock + I2C_INSTANCE_0_CLK_EN(); + I2C_INSTANCE_0_SCL_CLK_EN(); + I2C_INSTANCE_0_SDA_CLK_EN(); + break; + +#ifdef I2C_INSTANCE_1 + case 1: + I2C_INSTANCE_1_CLK_EN(); + I2C_INSTANCE_1_SCL_CLK_EN(); + I2C_INSTANCE_1_SDA_CLK_EN(); + break; +#endif + +#ifdef I2C_INSTANCE_2 + case 2: + I2C_INSTANCE_2_CLK_EN(); + I2C_INSTANCE_2_SCL_CLK_EN(); + I2C_INSTANCE_2_SDA_CLK_EN(); + break; +#endif + default: + goto cleanup; + } + + const i2c_bus_def_t* def = &g_i2c_bus_def[bus_index]; + + bus->def = def; + + // Unlocks potentially locked I2C bus by + // generating several clock pulses on SCL while SDA is low + i2c_bus_unlock(bus); + + GPIO_InitTypeDef GPIO_InitStructure = {0}; + + // Configure SDA and SCL as open-drain output + // and connect to the I2C peripheral + GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + + GPIO_InitStructure.Alternate = def->pin_af; + GPIO_InitStructure.Pin = def->scl_pin; + HAL_GPIO_Init(def->scl_port, &GPIO_InitStructure); + + GPIO_InitStructure.Alternate = def->pin_af; + GPIO_InitStructure.Pin = def->sda_pin; + HAL_GPIO_Init(def->sda_port, &GPIO_InitStructure); + + i2c_bus_reset(bus); + + NVIC_SetPriority(def->ev_irq, IRQ_PRI_NORMAL); + NVIC_SetPriority(def->er_irq, IRQ_PRI_NORMAL); + + NVIC_EnableIRQ(def->ev_irq); + NVIC_EnableIRQ(def->er_irq); + + bus->timer = systimer_create(i2c_bus_timer_callback, bus); + if (bus->timer == NULL) { + goto cleanup; + } + + return true; + +cleanup: + i2c_bus_deinit(bus); + return false; +} + +i2c_bus_t* i2c_bus_open(uint8_t bus_index) { + if (bus_index >= I2C_COUNT) { + return NULL; + } + + i2c_bus_t* bus = &g_i2c_bus_driver[bus_index]; + + if (bus->refcount == 0) { + if (!i2c_bus_init(bus, bus_index)) { + return NULL; + } + } + + ++bus->refcount; + + return bus; +} + +void i2c_bus_close(i2c_bus_t* bus) { + if (!i2c_bus_ptr_valid(bus)) { + return; + } + + if (bus->refcount > 0) { + if (--bus->refcount == 0) { + i2c_bus_deinit(bus); + } + } +} + +i2c_status_t i2c_packet_status(const i2c_packet_t* packet) { + uint32_t irq_state = disable_irq(); + i2c_status_t status = packet->status; + enable_irq(irq_state); + return status; +} + +i2c_status_t i2c_packet_wait(const i2c_packet_t* packet) { + while (true) { + i2c_status_t status = i2c_packet_status(packet); + + if (status != I2C_STATUS_PENDING) { + return status; + } + + // Enter sleep mode and wait for any interrupt + __WFI(); + } +} + +// Invokes the packet completion callback +static inline void i2c_bus_invoke_callback(i2c_bus_t* bus, i2c_packet_t* packet, + i2c_status_t status) { + packet->status = status; + if (packet->callback) { + bus->callback_executed = true; + packet->callback(packet->context, packet); + bus->callback_executed = false; + } +} + +// Appends the packet to the end of the queue +// Returns true if the queue was empty before +// Expects disabled IRQ or calling from IRQ context +static inline bool i2c_bus_add_packet(i2c_bus_t* bus, i2c_packet_t* packet) { + if (bus->queue_tail == NULL) { + bus->queue_head = packet; + bus->queue_tail = packet; + return true; + } else { + bus->queue_tail->next = packet; + bus->queue_tail = packet; + return false; + } +} + +// Removes the packet from the queue (if present) +// Returns true if the removed we removed head of the queue +// Expects disabled IRQ or calling from IRQ context +static inline bool i2c_bus_remove_packet(i2c_bus_t* bus, i2c_packet_t* packet) { + if (packet == bus->queue_head) { + // Remove head of the queue + bus->queue_head = packet->next; + // If the removed packet was also the tail, reset the tail + if (bus->queue_tail == packet) { + bus->queue_tail = NULL; + } + packet->next = NULL; + return true; + } + + // Remove from the middle or tail of the queue + i2c_packet_t* p = bus->queue_head; + while (p->next != NULL && p->next != packet) { + p = p->next; + } + + if (p->next == packet) { + // The packet found in the queue, remove it + p->next = packet->next; + // Update the tail if necessary + if (bus->queue_tail == packet) { + bus->queue_tail = p; + } + packet->next = NULL; + } + + return false; +} + +i2c_status_t i2c_bus_submit(i2c_bus_t* bus, i2c_packet_t* packet) { + if (!i2c_bus_ptr_valid(bus) || packet == NULL) { + // Invalid bus or packet + return I2C_STATUS_ERROR; + } + + if (packet->next != NULL) { + // Packet is already queued + return I2C_STATUS_ERROR; + } + + packet->status = I2C_STATUS_PENDING; + + // Insert packet into the queue + uint32_t irq_state = disable_irq(); + if (i2c_bus_add_packet(bus, packet)) { + // The queue was empty, start the operation + if (!bus->callback_executed && !bus->abort_pending) { + i2c_bus_head_continue(bus); + } + } + enable_irq(irq_state); + + return I2C_STATUS_OK; +} + +void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) { + if (!i2c_bus_ptr_valid(bus) || packet == NULL) { + // Invalid bus or packet + return; + } + + uint32_t irq_state = disable_irq(); + + if (packet->status == I2C_STATUS_PENDING) { + if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) { + // The packet was being processed + + // Reset internal state + bus->next_op = 0; + bus->buff_ptr = NULL; + bus->buff_size = 0; + bus->transfer_size = 0; + bus->transfer_op = 0; + + // Inform interrupt handler about pending abort + bus->abort_pending = true; + bus->stop_requested = true; + + // Abort operation may fail if the bus is busy or noisy + // so we need to set a timeout. + systimer_set(bus->timer, I2C_BUS_TIMEOUT(2)); + } + packet->status = I2C_STATUS_ABORTED; + } + + enable_irq(irq_state); +} + +// Completes the current packet by removing it from the queue +// an invoking the completion callback +// +// Must be called with IRQ disabled or from IRQ context +// Expects the operation is finished +static void i2c_bus_head_complete(i2c_bus_t* bus, i2c_status_t status) { + i2c_packet_t* packet = bus->queue_head; + if (packet != NULL) { + // Remove packet from the queue + i2c_bus_remove_packet(bus, packet); + + // Reset internal state + bus->next_op = 0; + bus->buff_ptr = NULL; + bus->buff_size = 0; + bus->transfer_size = 0; + bus->transfer_op = 0; + bus->abort_pending = false; + + systimer_unset(bus->timer); + + // Invoke the completion callback + i2c_bus_invoke_callback(bus, packet, status); + } +} + +// Starts the next operation in the packet by +// programming the I2C controller +// +// Must be called with IRQ disabled or from IRQ context +// Expects no other operation is being processed +static void i2c_bus_head_continue(i2c_bus_t* bus) { + I2C_TypeDef* regs = bus->def->regs; + + if (bus->stop_requested) { + // Issue STOP condition + regs->CR1 |= I2C_CR1_STOP; + if (bus->def->guard_time > 0) { + bus->stop_time = systick_us(); + } + bus->stop_requested = false; + } + + if (bus->abort_pending) { + systimer_unset(bus->timer); + bus->abort_pending = false; + } + + // Check if the bus is in a faulty state + if (bus->queue_head != NULL && bus->next_op == 0) { + uint32_t sr2 = regs->SR2; + + if ((sr2 & I2C_SR2_BUSY) && ((sr2 & I2C_SR2_MSL) == 0)) { + // the bus is busy but not in master mode. + // It may happen if in case of noise or other issues. + i2c_bus_reset(bus); + } + } + + uint32_t cr1 = regs->CR1; + cr1 &= ~(I2C_CR1_POS | I2C_CR1_ACK | I2C_CR1_STOP | I2C_CR1_START); + + uint32_t cr2 = regs->CR2; + cr2 &= ~(I2C_CR2_ITBUFEN | I2C_CR2_ITEVTEN | I2C_CR2_ITERREN); + + if (bus->queue_head != NULL) { + i2c_packet_t* packet = bus->queue_head; + + if (bus->next_op < packet->op_count) { + i2c_op_t* op = &packet->ops[bus->next_op++]; + + // Get data ptr and data length + if (op->flags & I2C_FLAG_EMBED) { + bus->buff_ptr = op->data; + bus->buff_size = MIN(op->size, sizeof(op->data)); + } else { + bus->buff_ptr = op->ptr; + bus->buff_size = op->size; + } + + // Calculate transfer size + bus->transfer_size = bus->buff_size; + bus->transfer_op = bus->next_op; + + // Include following operations in the transfer if: + // 1) We are not processing the last operation + // 2) STOP condition is not requested in the current operation + // 3) START condition is not requested in the next operation + // 4) The next operation has the same direction + + while ((bus->next_op != packet->op_count) && + ((op->flags & I2C_FLAG_STOP) == 0) && + (((op + 1)->flags & I2C_FLAG_START) == 0) && + (((op + 1)->flags & I2C_FLAG_TX) == (op->flags & I2C_FLAG_TX))) { + // Move to the next operation + op = &packet->ops[bus->next_op++]; + + if (op->flags & I2C_FLAG_EMBED) { + bus->transfer_size += MIN(op->size, sizeof(op->data)); + } else { + bus->transfer_size += op->size; + } + } + + // STOP condition: + // 1) if it is explicitly requested + // 2) if it is the last operation in the packet + bus->stop_requested = ((op->flags & I2C_FLAG_STOP) != 0) || + (bus->next_op == packet->op_count); + + // Calculate address byte + bus->addr_byte = packet->address << 1; + + // ACK, POS, ITBUFEN flags are set based on the operation + if (bus->transfer_size > 0) { + if (op->flags & I2C_FLAG_TX) { + cr2 |= I2C_CR2_ITBUFEN; + } else if (op->flags & I2C_FLAG_RX) { + bus->addr_byte |= 1; // Set RW bit to 1 (READ) + if (bus->transfer_size == 1) { + cr2 |= I2C_CR2_ITBUFEN; + } else if (bus->transfer_size == 2) { + cr1 |= I2C_CR1_POS; + } else if (bus->transfer_size == 3) { + cr1 |= I2C_CR1_ACK; + } else if (bus->transfer_size > 3) { + cr2 |= I2C_CR2_ITBUFEN; + cr1 |= I2C_CR1_ACK; + } + } + } + + // Enable event and error interrupts + cr2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITERREN; + + // Generate start condition + // (this also clears all status flags) + cr1 |= I2C_CR1_START; + + // Each operation has its own timeout calculated + // based on the number of bytes to transfer and the bus speed + + // expected operation overhead + systimer_set(bus->timer, + I2C_BUS_TIMEOUT(bus->transfer_size) + packet->timeout); + + // Guard time between operations STOP and START condition + if (bus->def->guard_time > 0) { + // Add 5us as a safety margin since the stop_time was set before the + // STOP condition was issued + uint16_t guard_time = bus->def->guard_time + 5; + while (systick_us() - bus->stop_time < guard_time) + ; + } + } + + // Clear BTF flag + (void)regs->DR; + } + + regs->CR1 = cr1; + regs->CR2 = cr2; +} + +// Timer callback handling I2C bus timeout +static void i2c_bus_timer_callback(void* context) { + i2c_bus_t* bus = (i2c_bus_t*)context; + + if (bus->abort_pending) { + // This may be caused by the bus being busy/noisy. + // Reset I2C Controller + i2c_bus_reset(bus); + // Start the next packet + i2c_bus_head_continue(bus); + } else { + // Timeout during normal operation occurred + i2c_packet_t* packet = bus->queue_head; + if (packet != NULL) { + // Determine the status based on the current bus state + I2C_TypeDef* regs = bus->def->regs; + i2c_status_t status; + + if ((regs->CR1 & I2C_CR1_START) && (regs->SR2 & I2C_SR2_BUSY)) { + // START condition was issued but the bus is still busy + status = I2C_STATUS_BUSY; + } else { + status = I2C_STATUS_TIMEOUT; + } + + // Abort pending packet + i2c_bus_abort(bus, packet); + // Invoke the completion callback + i2c_bus_invoke_callback(bus, packet, status); + } + } +} + +static uint8_t i2c_bus_read_buff(i2c_bus_t* bus) { + if (bus->transfer_size > 0) { + while (bus->buff_size == 0 && bus->transfer_op < bus->next_op) { + i2c_op_t* op = &bus->queue_head->ops[bus->transfer_op++]; + if (op->flags & I2C_FLAG_EMBED) { + bus->buff_ptr = op->data; + bus->buff_size = MIN(op->size, sizeof(op->data)); + } else { + bus->buff_ptr = op->ptr; + bus->buff_size = op->size; + } + } + + --bus->transfer_size; + + if (bus->buff_size > 0) { + --bus->buff_size; + return *bus->buff_ptr++; + } + } + + return 0; +} + +static void i2c_bus_write_buff(i2c_bus_t* bus, uint8_t data) { + if (bus->transfer_size > 0) { + while (bus->buff_size == 0 && bus->transfer_op < bus->next_op) { + i2c_op_t* op = &bus->queue_head->ops[bus->transfer_op++]; + if (op->flags & I2C_FLAG_EMBED) { + bus->buff_ptr = op->data; + bus->buff_size = MIN(op->size, sizeof(op->data)); + } else { + bus->buff_ptr = op->ptr; + bus->buff_size = op->size; + } + } + + --bus->transfer_size; + + if (bus->buff_size > 0) { + *bus->buff_ptr++ = data; + --bus->buff_size; + } + } +} + +// I2C bus event interrupt handler +static void i2c_bus_ev_handler(i2c_bus_t* bus) { + I2C_TypeDef* regs = bus->def->regs; + + uint32_t sr1 = regs->SR1; + + if (sr1 & I2C_SR1_SB) { + // START condition generated + // Send the address byte + regs->DR = bus->addr_byte; + // Operation cannot be aborted at this point. + // We need to wait for ADDR flag. + } else if (sr1 & I2C_SR1_ADDR) { + // Address sent and ACKed by the slave + // By reading SR2 we clear ADDR flag and start the data transfer + regs->SR2; + + if (bus->abort_pending) { + // Only TX operation can be aborted at this point + // For RX operation, we need to wait for the first byte + if ((bus->addr_byte & 1) == 0) { + // Issue STOP condition and start the next packet + i2c_bus_head_continue(bus); + } + } else if (bus->transfer_size == 0) { + // Operation contains only address without any data + if (bus->next_op == bus->queue_head->op_count) { + i2c_bus_head_complete(bus, I2C_STATUS_OK); + } + i2c_bus_head_continue(bus); + } + } else if ((bus->addr_byte & 1) == 0) { + // Data transmit phase + if (bus->abort_pending) { + // Issue STOP condition and start the next packet + i2c_bus_head_continue(bus); + } else if ((sr1 & I2C_SR1_TXE) && (regs->CR2 & I2C_CR2_ITBUFEN)) { + // I2C controller transmit buffer is empty. + // The interrupt flag is cleared by writing the DR register. + if (bus->transfer_size > 0) { + // Send the next byte + regs->DR = i2c_bus_read_buff(bus); + if (bus->transfer_size == 0) { + // All data bytes were transmitted + // Disable RXNE interrupt and wait for BTF + regs->CR2 &= ~I2C_CR2_ITBUFEN; + } + } + } else if (sr1 & I2C_SR1_BTF) { + if (bus->transfer_size == 0) { + // All data bytes were shifted out + if (bus->next_op == bus->queue_head->op_count) { + // Last operation in the packet + i2c_bus_head_complete(bus, I2C_STATUS_OK); + } + i2c_bus_head_continue(bus); + } + } + } else { // Data receive phase + if (bus->abort_pending) { + regs->CR1 &= ~(I2C_CR1_ACK | I2C_CR1_POS); + (void)regs->DR; + // Issue STOP condition and start the next packet + i2c_bus_head_continue(bus); + } else if ((sr1 & I2C_SR1_RXNE) && (regs->CR2 & I2C_CR2_ITBUFEN)) { + uint8_t received_byte = regs->DR; + if (bus->transfer_size > 0) { + // Receive the next byte + i2c_bus_write_buff(bus, received_byte); + if (bus->transfer_size == 3) { + // 3 bytes left to receive + // Disable RXNE interrupt and wait for BTF + regs->CR2 &= ~I2C_CR2_ITBUFEN; + } else if (bus->transfer_size == 0) { + // All data bytes were received + // We get here only in case of 1 byte transfers + if (bus->next_op == bus->queue_head->op_count) { + // Last operation in the packet + i2c_bus_head_complete(bus, I2C_STATUS_OK); + } + i2c_bus_head_continue(bus); + } + } + } else if (sr1 & I2C_SR1_BTF) { + if (bus->transfer_size == 3) { + // 3 bytes left to receive + regs->CR1 &= ~I2C_CR1_ACK; + i2c_bus_write_buff(bus, regs->DR); + } else if (bus->transfer_size == 2) { + // 2 left bytes are already in DR a shift register + if (bus->stop_requested) { + // Issue STOP condition before reading the 2 last bytes + regs->CR1 |= I2C_CR1_STOP; + if (bus->def->guard_time > 0) { + bus->stop_time = systick_us(); + } + bus->stop_requested = false; + } + i2c_bus_write_buff(bus, regs->DR); + i2c_bus_write_buff(bus, regs->DR); + + if (bus->next_op == bus->queue_head->op_count) { + i2c_bus_head_complete(bus, I2C_STATUS_OK); + } + i2c_bus_head_continue(bus); + } + } + } +} + +// I2C bus error interrupt handler +static void i2c_bus_er_handler(i2c_bus_t* bus) { + I2C_TypeDef* regs = bus->def->regs; + + uint32_t sr1 = regs->SR1; + + // Clear error flags + regs->SR1 &= ~(I2C_SR1_AF | I2C_SR1_ARLO | I2C_SR1_BERR); + + if (sr1 & I2C_SR1_AF) { + // NACK received + if (bus->abort_pending) { + // Start the next packet + i2c_bus_head_continue(bus); + } else if (bus->next_op > 0) { + // Complete packet with error + i2c_bus_head_complete(bus, I2C_STATUS_NACK); + // Issue stop condition and start the next packet + bus->stop_requested = true; + i2c_bus_head_continue(bus); + } else { + // Invalid state + } + } + + if (sr1 & I2C_SR1_ARLO) { + if (bus->abort_pending) { + // Packet aborted or invalid state + // Start the next packet + bus->stop_requested = false; + i2c_bus_head_continue(bus); + } else if (bus->next_op > 0) { + // Arbitration lost, complete packet with error + i2c_bus_head_complete(bus, I2C_STATUS_ERROR); + // Start the next packet + bus->stop_requested = false; + i2c_bus_head_continue(bus); + } + } + + if (sr1 & I2C_SR1_BERR) { + // Bus error + // Ignore and continue with pending operation + } +} + +// Interrupt handlers + +#ifdef I2C_INSTANCE_0 +void I2C_INSTANCE_0_EV_IRQHandler(void) { + i2c_bus_ev_handler(&g_i2c_bus_driver[0]); +} + +void I2C_INSTANCE_0_ER_IRQHandler(void) { + i2c_bus_er_handler(&g_i2c_bus_driver[0]); +} +#endif + +#ifdef I2C_INSTANCE_1 +void I2C_INSTANCE_1_EV_IRQHandler(void) { + i2c_bus_ev_handler(&g_i2c_bus_driver[1]); +} + +void I2C_INSTANCE_1_ER_IRQHandler(void) { + i2c_bus_er_handler(&g_i2c_bus_driver[1]); +} +#endif + +#ifdef I2C_INSTANCE_2 +void I2C_INSTANCE_2_EV_IRQHandler(void) { + i2c_bus_ev_handler(&g_i2c_bus_driver[2]); +} + +void I2C_INSTANCE_2_ER_IRQHandler(void) { + i2c_bus_er_handler(&g_i2c_bus_driver[2]); +} +#endif diff --git a/core/embed/trezorhal/stm32f4/systimer.c b/core/embed/trezorhal/stm32f4/systimer.c index 4aacfa88731..723ff781d07 100644 --- a/core/embed/trezorhal/stm32f4/systimer.c +++ b/core/embed/trezorhal/stm32f4/systimer.c @@ -29,7 +29,7 @@ // // Consider different implementation (i.e. priority queue // using binary heap if MAX_SYSTIMERS exceeds 10 or more) -#define MAX_SYSTIMERS 4 +#define MAX_SYSTIMERS 8 // User timer instance struct systimer { diff --git a/core/embed/trezorhal/stm32u5/i2c_bus.c b/core/embed/trezorhal/stm32u5/i2c_bus.c new file mode 100644 index 00000000000..58b157cf1e6 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/i2c_bus.c @@ -0,0 +1,894 @@ +/* + * 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 STM32_HAL_H +#include TREZOR_BOARD + +#include + +#include "common.h" +#include "i2c_bus.h" +#include "irq.h" +#include "systimer.h" + +// Using calculation from STM32CubeMX +// PCLKx as source, assumed 160MHz +// Fast mode, freq = 400kHz, Rise time = 250ns, Fall time = 100ns +// Fast mode, freq = 200kHz, Rise time = 250ns, Fall time = 100ns +// SCLH and SCLL are manually modified to achieve more symmetric clock +#define I2C_TIMING_400000_Hz 0x30D22728 +#define I2C_TIMING_200000_Hz 0x30D2595A +#define I2C_TIMING I2C_TIMING_200000_Hz + +// We expect the I2C bus to be running at ~200kHz +// and max response time of the device is 1000us +#define I2C_BUS_CHAR_TIMEOUT (50 + 5) // us +#define I2C_BUS_OP_TIMEOUT 1000 // us + +#define I2C_BUS_TIMEOUT(n) \ + ((I2C_BUS_CHAR_TIMEOUT * (1 + n) + I2C_BUS_OP_TIMEOUT + 999) / 1000) + +// I2C bus hardware definition +typedef struct { + // I2C controller registers + I2C_TypeDef* regs; + // SCL pin GPIO port + GPIO_TypeDef* scl_port; + // SDA pin GPIO port + GPIO_TypeDef* sda_port; + // SCL pin number + uint16_t scl_pin; + // SDA pin number + uint16_t sda_pin; + // Alternate function for SCL and SDA pins + uint8_t pin_af; + // Register for I2C controller reset + volatile uint32_t* reset_reg; + // Reset bit specific for this I2C controller + uint32_t reset_bit; + // I2C event IRQ number + uint32_t ev_irq; + // I2C error IRQ number + uint32_t er_irq; + // Guard time [us] between STOP and START condition. + // If zero, the guard time is not used. + uint16_t guard_time; +} i2c_bus_def_t; + +// I2C bus hardware definitions +static const i2c_bus_def_t g_i2c_bus_def[I2C_COUNT] = { + { + .regs = I2C_INSTANCE_0, + .scl_port = I2C_INSTANCE_0_SCL_PORT, + .sda_port = I2C_INSTANCE_0_SDA_PORT, + .scl_pin = I2C_INSTANCE_0_SCL_PIN, + .sda_pin = I2C_INSTANCE_0_SDA_PIN, + .pin_af = I2C_INSTANCE_0_PIN_AF, + .reset_reg = I2C_INSTANCE_0_RESET_REG, + .reset_bit = I2C_INSTANCE_0_RESET_BIT, + .ev_irq = I2C_INSTANCE_0_EV_IRQn, + .er_irq = I2C_INSTANCE_0_ER_IRQn, + .guard_time = I2C_INSTANCE_0_GUARD_TIME, + }, +#ifdef I2C_INSTANCE_1 + { + .regs = I2C_INSTANCE_1, + .scl_port = I2C_INSTANCE_1_SCL_PORT, + .sda_port = I2C_INSTANCE_1_SDA_PORT, + .scl_pin = I2C_INSTANCE_1_SCL_PIN, + .sda_pin = I2C_INSTANCE_1_SDA_PIN, + .pin_af = I2C_INSTANCE_1_PIN_AF, + .reset_reg = I2C_INSTANCE_1_RESET_REG, + .reset_bit = I2C_INSTANCE_1_RESET_BIT, + .ev_irq = I2C_INSTANCE_1_EV_IRQn, + .er_irq = I2C_INSTANCE_1_ER_IRQn, + .guard_time = I2C_INSTANCE_1_GUARD_TIME, + }, +#endif +#ifdef I2C_INSTANCE_2 + { + .regs = I2C_INSTANCE_2, + .scl_port = I2C_INSTANCE_2_SCL_PORT, + .sda_port = I2C_INSTANCE_2_SDA_PORT, + .scl_pin = I2C_INSTANCE_2_SCL_PIN, + .sda_pin = I2C_INSTANCE_2_SDA_PIN, + .pin_af = I2C_INSTANCE_2_PIN_AF, + .reset_reg = I2C_INSTANCE_2_RESET_REG, + .reset_bit = I2C_INSTANCE_2_RESET_BIT, + .ev_irq = I2C_INSTANCE_2_EV_IRQn, + .er_irq = I2C_INSTANCE_2_ER_IRQn, + .guard_time = I2C_INSTANCE_2_GUARD_TIME, + }, +#endif +}; + +struct i2c_bus { + // Number of references to the bus + // (0 means the bus is not initialized) + uint32_t refcount; + + // Hardware definition + const i2c_bus_def_t* def; + + // Timer for timeout handling + systimer_t* timer; + + // Head of the packet queue + // (this packet is currently being processed) + i2c_packet_t* queue_head; + // Tail of the packet queue + // (this packet is the last in the queue) + i2c_packet_t* queue_tail; + + // Next operation index in the current packet + // == 0 => no operation is being processed + // == queue_head->op_count => no more operations + int next_op; + + // Points to the data buffer of the current operation + uint8_t* buff_ptr; + // Remaining number of bytes of the buffer to transfer + uint16_t buff_size; + // Remaining number of bytes of the current operation + // (if the transfer is split into multiple operations it + // may be different from buff_size) + uint16_t transfer_size; + // For case of split transfer, points to the next operation + // that is part of the current transfer + int transfer_op; + + // Set if the STOP condition is requested after the current operation + // when data transfer is completed. + bool stop_requested; + // Set if pending transaction is being aborted + bool abort_pending; + // Set if NACK was detected + bool nack; + // Data for clearing TXIS interrupt flag + // during an invalid or abort state + uint8_t dummy_data; + + // Flag indicating that the completion callback is being executed + bool callback_executed; + + // The last time [us] the STOP condition was issued + uint64_t stop_time; +}; + +// I2C bus driver instances +static i2c_bus_t g_i2c_bus_driver[I2C_COUNT] = {0}; + +// Check if the I2C bus pointer is valid +static inline bool i2c_bus_ptr_valid(const i2c_bus_t* bus) { + if (bus >= &g_i2c_bus_driver[0] && bus < &g_i2c_bus_driver[I2C_COUNT]) { + uintptr_t offset = (uintptr_t)bus - (uintptr_t)&g_i2c_bus_driver[0]; + if (offset % sizeof(i2c_bus_t) == 0) { + return bus->refcount > 0; + } + } + return false; +} + +// forward declarations +static void i2c_bus_timer_callback(void* context); +static void i2c_bus_head_continue(i2c_bus_t* bus); + +static void i2c_bus_unlock(i2c_bus_t* bus) { + const i2c_bus_def_t* def = bus->def; + + GPIO_InitTypeDef GPIO_InitStructure = {0}; + + // Set SDA and SCL high + HAL_GPIO_WritePin(def->sda_port, def->sda_pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(def->scl_port, def->scl_pin, GPIO_PIN_SET); + + // Configure SDA and SCL as open-drain output + // and connect to the I2C peripheral + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + + GPIO_InitStructure.Pin = def->scl_pin; + HAL_GPIO_Init(def->scl_port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = def->sda_pin; + HAL_GPIO_Init(def->sda_port, &GPIO_InitStructure); + + uint32_t clock_count = 16; + + while ((HAL_GPIO_ReadPin(def->sda_port, def->sda_pin) == GPIO_PIN_RESET) && + (clock_count-- > 0)) { + // Clock SCL + HAL_GPIO_WritePin(def->scl_port, def->scl_pin, GPIO_PIN_RESET); + systick_delay_us(10); + HAL_GPIO_WritePin(def->scl_port, def->scl_pin, GPIO_PIN_SET); + systick_delay_us(10); + } +} + +static void i2c_bus_deinit(i2c_bus_t* bus) { + const i2c_bus_def_t* def = bus->def; + + systimer_delete(bus->timer); + + if (bus->def == NULL) { + return; + } + + NVIC_DisableIRQ(def->ev_irq); + NVIC_DisableIRQ(def->er_irq); + + I2C_TypeDef* regs = def->regs; + + // Disable I2C peripheral + regs->CR1 = 0; + + // Reset I2C peripheral + *def->reset_reg |= def->reset_bit; + *def->reset_reg &= ~def->reset_bit; + + bus->def = NULL; +} + +static bool i2c_bus_init(i2c_bus_t* bus, int bus_index) { + memset(bus, 0, sizeof(i2c_bus_t)); + + switch (bus_index) { + case 0: + // enable I2C clock + I2C_INSTANCE_0_CLK_EN(); + I2C_INSTANCE_0_SCL_CLK_EN(); + I2C_INSTANCE_0_SDA_CLK_EN(); + break; + +#ifdef I2C_INSTANCE_1 + case 1: + I2C_INSTANCE_1_CLK_EN(); + I2C_INSTANCE_1_SCL_CLK_EN(); + I2C_INSTANCE_1_SDA_CLK_EN(); + break; +#endif + +#ifdef I2C_INSTANCE_2 + case 2: + I2C_INSTANCE_2_CLK_EN(); + I2C_INSTANCE_2_SCL_CLK_EN(); + I2C_INSTANCE_2_SDA_CLK_EN(); + break; +#endif + default: + goto cleanup; + } + + const i2c_bus_def_t* def = &g_i2c_bus_def[bus_index]; + + bus->def = def; + + // Unlocks potentially locked I2C bus by + // generating several clock pulses on SCL while SDA is low + i2c_bus_unlock(bus); + + GPIO_InitTypeDef GPIO_InitStructure = {0}; + + // Configure SDA and SCL as open-drain output + // and connect to the I2C peripheral + GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + + GPIO_InitStructure.Alternate = def->pin_af; + GPIO_InitStructure.Pin = def->scl_pin; + HAL_GPIO_Init(def->scl_port, &GPIO_InitStructure); + + GPIO_InitStructure.Alternate = def->pin_af; + GPIO_InitStructure.Pin = def->sda_pin; + HAL_GPIO_Init(def->sda_port, &GPIO_InitStructure); + + // Reset I2C peripheral + *def->reset_reg |= def->reset_bit; + *def->reset_reg &= ~def->reset_bit; + + I2C_TypeDef* regs = def->regs; + + // Configure I2C peripheral + regs->CR1 = 0; + regs->TIMINGR = I2C_TIMING; + regs->CR2 = 0; + regs->OAR1 = 0; + regs->OAR2 = 0; + regs->CR1 |= I2C_CR1_PE; + + // Configure I2C interrupts + regs->CR1 |= I2C_CR1_ERRIE | I2C_CR1_NACKIE | I2C_CR1_STOPIE | I2C_CR1_TCIE | + I2C_CR1_RXIE | I2C_CR1_TXIE; + + NVIC_SetPriority(def->ev_irq, IRQ_PRI_NORMAL); + NVIC_SetPriority(def->er_irq, IRQ_PRI_NORMAL); + + NVIC_EnableIRQ(def->ev_irq); + NVIC_EnableIRQ(def->er_irq); + + bus->timer = systimer_create(i2c_bus_timer_callback, bus); + if (bus->timer == NULL) { + goto cleanup; + } + + return true; + +cleanup: + i2c_bus_deinit(bus); + return false; +} + +i2c_bus_t* i2c_bus_open(uint8_t bus_index) { + if (bus_index >= I2C_COUNT) { + return NULL; + } + + i2c_bus_t* bus = &g_i2c_bus_driver[bus_index]; + + if (bus->refcount == 0) { + if (!i2c_bus_init(bus, bus_index)) { + return NULL; + } + } + + ++bus->refcount; + + return bus; +} + +void i2c_bus_close(i2c_bus_t* bus) { + if (!i2c_bus_ptr_valid(bus)) { + return; + } + + if (bus->refcount > 0) { + if (--bus->refcount == 0) { + i2c_bus_deinit(bus); + } + } +} + +i2c_status_t i2c_packet_status(const i2c_packet_t* packet) { + uint32_t irq_state = disable_irq(); + i2c_status_t status = packet->status; + enable_irq(irq_state); + return status; +} + +i2c_status_t i2c_packet_wait(const i2c_packet_t* packet) { + while (true) { + i2c_status_t status = i2c_packet_status(packet); + + if (status != I2C_STATUS_PENDING) { + return status; + } + + // Enter sleep mode and wait for any interrupt + __WFI(); + } +} + +static uint8_t i2c_bus_read_buff(i2c_bus_t* bus) { + if (bus->transfer_size > 0) { + while (bus->buff_size == 0 && bus->transfer_op < bus->next_op) { + i2c_op_t* op = &bus->queue_head->ops[bus->transfer_op++]; + if (op->flags & I2C_FLAG_EMBED) { + bus->buff_ptr = op->data; + bus->buff_size = MIN(op->size, sizeof(op->data)); + } else { + bus->buff_ptr = op->ptr; + bus->buff_size = op->size; + } + } + + --bus->transfer_size; + + if (bus->buff_size > 0) { + --bus->buff_size; + return *bus->buff_ptr++; + } + } + + return 0; +} + +static void i2c_bus_write_buff(i2c_bus_t* bus, uint8_t data) { + if (bus->transfer_size > 0) { + while (bus->buff_size == 0 && bus->transfer_op < bus->next_op) { + i2c_op_t* op = &bus->queue_head->ops[bus->transfer_op++]; + if (op->flags & I2C_FLAG_EMBED) { + bus->buff_ptr = op->data; + bus->buff_size = MIN(op->size, sizeof(op->data)); + } else { + bus->buff_ptr = op->ptr; + bus->buff_size = op->size; + } + } + + --bus->transfer_size; + + if (bus->buff_size > 0) { + *bus->buff_ptr++ = data; + --bus->buff_size; + } + } +} + +// Invokes the packet completion callback +static inline void i2c_bus_invoke_callback(i2c_bus_t* bus, i2c_packet_t* packet, + i2c_status_t status) { + packet->status = status; + if (packet->callback) { + bus->callback_executed = true; + packet->callback(packet->context, packet); + bus->callback_executed = false; + } +} + +// Appends the packet to the end of the queue +// Returns true if the queue was empty before +// Expects disabled IRQ or calling from IRQ context +static inline bool i2c_bus_add_packet(i2c_bus_t* bus, i2c_packet_t* packet) { + if (bus->queue_tail == NULL) { + bus->queue_head = packet; + bus->queue_tail = packet; + return true; + } else { + bus->queue_tail->next = packet; + bus->queue_tail = packet; + return false; + } +} + +// Removes the packet from the queue (if present) +// Returns true if the removed we removed head of the queue +// Expects disabled IRQ or calling from IRQ context +static inline bool i2c_bus_remove_packet(i2c_bus_t* bus, i2c_packet_t* packet) { + if (packet == bus->queue_head) { + // Remove head of the queue + bus->queue_head = packet->next; + // If the removed packet was also the tail, reset the tail + if (bus->queue_tail == packet) { + bus->queue_tail = NULL; + } + packet->next = NULL; + return true; + } + + // Remove from the middle or tail of the queue + i2c_packet_t* p = bus->queue_head; + while (p->next != NULL && p->next != packet) { + p = p->next; + } + + if (p->next == packet) { + // The packet found in the queue, remove it + p->next = packet->next; + // Update the tail if necessary + if (bus->queue_tail == packet) { + bus->queue_tail = p; + } + packet->next = NULL; + } + + return false; +} + +i2c_status_t i2c_bus_submit(i2c_bus_t* bus, i2c_packet_t* packet) { + if (!i2c_bus_ptr_valid(bus) || packet == NULL) { + // Invalid bus or packet + return I2C_STATUS_ERROR; + } + + if (packet->next != NULL) { + // Packet is already queued + return I2C_STATUS_ERROR; + } + + packet->status = I2C_STATUS_PENDING; + + // Insert packet into the queue + uint32_t irq_state = disable_irq(); + if (i2c_bus_add_packet(bus, packet)) { + // The queue was empty, start the operation + if (!bus->callback_executed && !bus->abort_pending) { + i2c_bus_head_continue(bus); + } + } + enable_irq(irq_state); + + return I2C_STATUS_OK; +} + +void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) { + if (!i2c_bus_ptr_valid(bus) || packet == NULL) { + // Invalid bus or packet + return; + } + + uint32_t irq_state = disable_irq(); + + if (packet->status == I2C_STATUS_PENDING) { + if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) { + // The packet was being processed + + if (bus->transfer_size > 0) { + bus->dummy_data = i2c_bus_read_buff(bus); + } + + // Reset internal state + bus->next_op = 0; + bus->buff_ptr = NULL; + bus->buff_size = 0; + bus->transfer_size = 0; + bus->transfer_op = 0; + bus->stop_requested = false; + + // Inform interrupt handler about pending abort + bus->abort_pending = true; + + // Abort operation may fail if the bus is busy or noisy + // so we need to set a timeout. + systimer_set(bus->timer, I2C_BUS_TIMEOUT(2)); + } + + packet->status = I2C_STATUS_ABORTED; + } + + enable_irq(irq_state); +} + +// Completes the current packet by removing it from the queue +// an invoking the completion callback +// +// Must be called with IRQ disabled or from IRQ context +// Expects the operation is finished +static void i2c_bus_head_complete(i2c_bus_t* bus, i2c_status_t status) { + i2c_packet_t* packet = bus->queue_head; + if (packet != NULL) { + // Remove packet from the queue + i2c_bus_remove_packet(bus, packet); + + // Reset internal state + bus->next_op = 0; + bus->buff_ptr = NULL; + bus->buff_size = 0; + bus->transfer_size = 0; + bus->transfer_op = 0; + bus->stop_requested = false; + bus->abort_pending = false; + + systimer_unset(bus->timer); + + // Invoke the completion callback + i2c_bus_invoke_callback(bus, packet, status); + } +} + +// Starts the next operation in the packet by +// programming the I2C controller +// +// Must be called with IRQ disabled or from IRQ context +// Expects no other operation is being processed +static void i2c_bus_head_continue(i2c_bus_t* bus) { + if (bus->abort_pending) { + systimer_unset(bus->timer); + bus->abort_pending = false; + } + + if (bus->queue_head != NULL) { + i2c_packet_t* packet = bus->queue_head; + + if (bus->next_op < packet->op_count) { + i2c_op_t* op = &packet->ops[bus->next_op++]; + I2C_TypeDef* regs = bus->def->regs; + + uint32_t cr2 = regs->CR2; + cr2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | + I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_SADD_Msk); + + // Set device address + cr2 |= ((packet->address & 0x7F) << 1) << I2C_CR2_SADD_Pos; + + // Get data ptr and its length + if (op->flags & I2C_FLAG_EMBED) { + bus->buff_ptr = op->data; + bus->buff_size = MIN(op->size, sizeof(op->data)); + } else { + bus->buff_ptr = op->ptr; + bus->buff_size = op->size; + } + + // Calculate transfer size + bus->transfer_size = bus->buff_size; + bus->transfer_op = bus->next_op; + + // Include following operations in the transfer if: + // 1) We are not processing the last operation + // 2) STOP condition is not requested in the current operation + // 3) START condition is not requested in the next operation + // 4) The next operation has the same direction + + while ((bus->next_op != packet->op_count) && + ((op->flags & I2C_FLAG_STOP) == 0) && + (((op + 1)->flags & I2C_FLAG_START) == 0) && + (((op + 1)->flags & I2C_FLAG_TX) == (op->flags & I2C_FLAG_TX))) { + // Move to the next operation + op = &packet->ops[bus->next_op++]; + + if (op->flags & I2C_FLAG_EMBED) { + bus->transfer_size += MIN(op->size, sizeof(op->data)); + } else { + bus->transfer_size += op->size; + } + } + + if (bus->transfer_size > 0) { + // I2C controller can handle only 255 bytes at once + // More data will be handled by the TCR interrupt + cr2 |= MIN(255, bus->transfer_size) << I2C_CR2_NBYTES_Pos; + + if (bus->transfer_size > 255) { + cr2 |= I2C_CR2_RELOAD; + } + + if (op->flags & I2C_FLAG_TX) { + // Transmitting has priority over receive. + // Flush TXDR register possibly filled by some previous + // invalid operation or abort. + regs->ISR = I2C_ISR_TXE; + } else if (op->flags & I2C_FLAG_RX) { + // Receive data from the device + cr2 |= I2C_CR2_RD_WRN; + } + } + + // STOP condition: + // 1) if it is explicitly requested + // 2) if it is the last operation in the packet + bus->stop_requested = ((op->flags & I2C_FLAG_STOP) != 0) || + (bus->next_op == packet->op_count); + + bus->nack = false; + + // START condition + cr2 |= I2C_CR2_START; + + // Guard time between operations STOP and START condition + if (bus->def->guard_time > 0) { + while (systick_us() - bus->stop_time < bus->def->guard_time) + ; + } + + regs->CR2 = cr2; + + // Each operation has its own timeout calculated + // based on the number of bytes to transfer and the bus speed + + // expected operation overhead + systimer_set(bus->timer, + I2C_BUS_TIMEOUT(bus->transfer_size) + packet->timeout); + } + } +} + +// Timer callback handling I2C bus timeout +static void i2c_bus_timer_callback(void* context) { + i2c_bus_t* bus = (i2c_bus_t*)context; + + if (bus->abort_pending) { + // Packet abort was not completed in time (STOPF was not detected) + // This may be caused by the bus being busy/noisy. + I2C_TypeDef* regs = bus->def->regs; + + // Reset the I2C controller + regs->CR1 &= ~I2C_CR1_PE; + regs->CR1 |= I2C_CR1_PE; + + // Continue with the next packet + i2c_bus_head_continue(bus); + } else { + // Timeout during normal operation occurred + i2c_packet_t* packet = bus->queue_head; + if (packet != NULL) { + // Determine the status based on the current bus state + I2C_TypeDef* regs = bus->def->regs; + i2c_status_t status; + if ((regs->CR2 & I2C_CR2_START) && (regs->ISR & I2C_ISR_BUSY)) { + // START condition was issued but the bus is still busy + status = I2C_STATUS_BUSY; + } else { + status = I2C_STATUS_TIMEOUT; + } + + // Abort pending packet + i2c_bus_abort(bus, packet); + + // Invoke the completion callback + i2c_bus_invoke_callback(bus, packet, status); + } + } +} + +// I2C bus event interrupt handler +static void i2c_bus_ev_handler(i2c_bus_t* bus) { + I2C_TypeDef* regs = bus->def->regs; + + uint32_t isr = regs->ISR; + + if (isr & I2C_ISR_RXNE) { + // I2C controller receive buffer is not empty. + // The interrupt flag is cleared by reading the RXDR register. + uint8_t received_byte = regs->RXDR; + if (bus->next_op > 0 && bus->transfer_size > 0) { + i2c_bus_write_buff(bus, received_byte); + } else if (bus->abort_pending) { + regs->CR2 |= I2C_CR2_STOP; + } else { + // Invalid state, ignore + } + } + + if (isr & I2C_ISR_TXIS) { + // I2C controller transmit buffer is empty. + // The interrupt flag is cleared by writing the TXDR register. + if (bus->next_op > 0 && bus->transfer_size > 0) { + regs->TXDR = i2c_bus_read_buff(bus); + } else { + regs->TXDR = bus->dummy_data; + if (bus->abort_pending) { + regs->CR2 |= I2C_CR2_STOP; + } else { + // Invalid state, ignore + } + } + } + + if (isr & I2C_ISR_TCR) { + // Data transfer is partially completed and RELOAD is required + if (bus->abort_pending) { + // Packet is being aborted, issue STOP condition + regs->CR2 &= ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD); + regs->CR2 |= I2C_CR2_STOP; + } else if (bus->transfer_size > 0) { + // There are still some bytes left in the current operation buffer + uint32_t cr2 = regs->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD); + + cr2 |= MIN(bus->transfer_size, 255) << I2C_CR2_NBYTES_Pos; + + if (bus->transfer_size > 255) { + // Set RELOAD if we the remaining data is still over + // the 255 bytes limit + cr2 |= I2C_CR2_RELOAD; + } + regs->CR2 = cr2; + } else if (bus->queue_head != NULL) { + // Data transfer is split between two or more operations, + // continues in the next operation + i2c_bus_head_continue(bus); + } else { + // Invalid state, clear the TCR flag + regs->CR2 &= ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD); + regs->CR2 |= I2C_CR2_STOP; + } + } + + if (isr & I2C_ISR_TC) { + // Transfer complete + if (bus->stop_requested || bus->abort_pending) { + // Issue stop condition and wait for ISR_STOPF flag + regs->CR2 |= I2C_CR2_STOP; + } else if (bus->queue_head != NULL) { + // Continue with the next operation + i2c_bus_head_continue(bus); + } else { + // Invalid state, clear the TC flag + regs->CR2 |= I2C_CR2_STOP; + } + } + + if (isr & I2C_ISR_NACKF) { + // Clear the NACKF flag + regs->ICR = I2C_ICR_NACKCF; + bus->nack = true; + // STOP condition is automatically generated + // by the hardware and the STOPF is set later. + } + + if (isr & I2C_ISR_STOPF) { + // Clear the STOPF flag + regs->ICR = I2C_ICR_STOPCF; + + if (bus->def->guard_time > 0) { + bus->stop_time = systick_us(); + } + + if (bus->next_op > 0 && bus->next_op == bus->queue_head->op_count) { + // Last operation in the packet + i2c_bus_head_complete(bus, bus->nack ? I2C_STATUS_NACK : I2C_STATUS_OK); + } + + // Continue with the next operation + // or complete the pending packet and move to the next + i2c_bus_head_continue(bus); + } +} + +// I2C bus error interrupt handler +static void i2c_bus_er_handler(i2c_bus_t* bus) { + I2C_TypeDef* regs = bus->def->regs; + + uint32_t isr = regs->ISR; + + // Clear error flags + regs->ICR = I2C_ICR_BERRCF | I2C_ICR_ARLOCF | I2C_ICR_OVRCF; + + if (isr & I2C_ISR_BERR) { + // Bus error + // Ignore and continue with pending operation + } + + if (isr & I2C_ISR_ARLO) { + if (bus->next_op > 0) { + // Arbitration lost, complete packet with error + i2c_bus_head_complete(bus, I2C_STATUS_ERROR); + // Start the next packet + i2c_bus_head_continue(bus); + } else { + // Packet aborted or invalid state + } + } + + if (isr & I2C_ISR_OVR) { + // This should not happen in master mode + } +} + +// Interrupt handlers + +#ifdef I2C_INSTANCE_0 +void I2C_INSTANCE_0_EV_IRQHandler(void) { + i2c_bus_ev_handler(&g_i2c_bus_driver[0]); +} + +void I2C_INSTANCE_0_ER_IRQHandler(void) { + i2c_bus_er_handler(&g_i2c_bus_driver[0]); +} +#endif + +#ifdef I2C_INSTANCE_1 +void I2C_INSTANCE_1_EV_IRQHandler(void) { + i2c_bus_ev_handler(&g_i2c_bus_driver[1]); +} + +void I2C_INSTANCE_1_ER_IRQHandler(void) { + i2c_bus_er_handler(&g_i2c_bus_driver[1]); +} +#endif + +#ifdef I2C_INSTANCE_2 +void I2C_INSTANCE_2_EV_IRQHandler(void) { + i2c_bus_ev_handler(&g_i2c_bus_driver[2]); +} + +void I2C_INSTANCE_2_ER_IRQHandler(void) { + i2c_bus_er_handler(&g_i2c_bus_driver[2]); +} +#endif diff --git a/core/site_scons/models/D001/discovery.py b/core/site_scons/models/D001/discovery.py index b0533b56793..65b332e6ab0 100644 --- a/core/site_scons/models/D001/discovery.py +++ b/core/site_scons/models/D001/discovery.py @@ -73,6 +73,7 @@ def configure( if "input" in features_wanted: sources += ["embed/trezorhal/stm32f4/i2c.c"] + sources += ["embed/trezorhal/stm32f4/i2c_bus.c"] sources += ["embed/trezorhal/stm32f4/touch/stmpe811.c"] features_available.append("touch") diff --git a/core/site_scons/models/D002/discovery2.py b/core/site_scons/models/D002/discovery2.py index cba3537d1f7..9041123cb16 100644 --- a/core/site_scons/models/D002/discovery2.py +++ b/core/site_scons/models/D002/discovery2.py @@ -60,9 +60,8 @@ def configure( sources += [ "embed/trezorhal/stm32u5/i2c.c", ] - sources += [ - "embed/trezorhal/stm32u5/touch/sitronix.c", - ] + sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] + sources += ["embed/trezorhal/stm32u5/touch/sitronix.c"] features_available.append("touch") # if "sd_card" in features_wanted: diff --git a/core/site_scons/models/T2B1/trezor_r_v10.py b/core/site_scons/models/T2B1/trezor_r_v10.py index 9cb1723ea6e..49c63e50c53 100644 --- a/core/site_scons/models/T2B1/trezor_r_v10.py +++ b/core/site_scons/models/T2B1/trezor_r_v10.py @@ -48,7 +48,10 @@ def configure( else: sources += [f"embed/trezorhal/stm32f4/displays/{display}"] - sources += ["embed/trezorhal/stm32f4/i2c.c"] + sources += [ + "embed/trezorhal/stm32f4/i2c.c", + "embed/trezorhal/stm32f4/i2c_bus.c", + ] if "input" in features_wanted: sources += ["embed/trezorhal/stm32f4/button.c"] @@ -79,6 +82,7 @@ def configure( if "optiga" in features_wanted: defines += ["USE_OPTIGA=1"] + sources += ["embed/trezorhal/stm32f4/i2c_bus.c"] sources += ["embed/trezorhal/stm32f4/optiga_hal.c"] sources += ["embed/trezorhal/optiga/optiga.c"] sources += ["embed/trezorhal/optiga/optiga_commands.c"] diff --git a/core/site_scons/models/T2T1/trezor_t.py b/core/site_scons/models/T2T1/trezor_t.py index de100f8c1be..18f4af2dcf2 100644 --- a/core/site_scons/models/T2T1/trezor_t.py +++ b/core/site_scons/models/T2T1/trezor_t.py @@ -42,6 +42,7 @@ def configure( "embed/models/T2T1/model_T2T1_layout.c", "embed/models/T2T1/compat_settings.c", ] + if "new_rendering" in features_wanted: sources += ["embed/trezorhal/xdisplay_legacy.c"] sources += ["embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c"] @@ -82,6 +83,7 @@ def configure( if "input" in features_wanted: sources += ["embed/trezorhal/stm32f4/i2c.c"] + sources += ["embed/trezorhal/stm32f4/i2c_bus.c"] sources += ["embed/trezorhal/stm32f4/touch/ft6x36.c"] features_available.append("touch") diff --git a/core/site_scons/models/T3B1/trezor_t3b1_revB.py b/core/site_scons/models/T3B1/trezor_t3b1_revB.py index 67e3f1bfc4a..ae923cdd5f6 100644 --- a/core/site_scons/models/T3B1/trezor_t3b1_revB.py +++ b/core/site_scons/models/T3B1/trezor_t3b1_revB.py @@ -74,6 +74,7 @@ def configure( if "optiga" in features_wanted: defines += ["USE_OPTIGA=1"] sources += ["embed/trezorhal/stm32u5/i2c.c"] + sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] sources += ["embed/trezorhal/stm32u5/optiga_hal.c"] sources += ["embed/trezorhal/optiga/optiga.c"] sources += ["embed/trezorhal/optiga/optiga_commands.c"] diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py index 85edb12c541..450ab408b8d 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py @@ -72,6 +72,7 @@ def configure( if "input" in features_wanted: sources += ["embed/trezorhal/stm32u5/i2c.c"] + sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] sources += ["embed/trezorhal/stm32u5/touch/ft6x36.c"] sources += ["embed/trezorhal/stm32u5/touch/panels/lx154a2422cpt23.c"] features_available.append("touch") diff --git a/core/site_scons/models/T3T1/trezor_t3t1_v4.py b/core/site_scons/models/T3T1/trezor_t3t1_v4.py index 4d8e3e59bca..661a44e923b 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_v4.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_v4.py @@ -46,7 +46,9 @@ def configure( sources += [ "embed/models/T3T1/model_T3T1_layout.c", ] - sources += [f"embed/trezorhal/stm32u5/displays/{display}"] + sources += [ + f"embed/trezorhal/stm32u5/displays/{display}", + ] if "new_rendering" in features_wanted: sources += ["embed/trezorhal/xdisplay_legacy.c"] @@ -74,6 +76,7 @@ def configure( if "input" in features_wanted: sources += ["embed/trezorhal/stm32u5/i2c.c"] + sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] sources += ["embed/trezorhal/stm32u5/touch/ft6x36.c"] features_available.append("touch") From f0b42e46039add6d1cd5838dc2094ead5d2d821c Mon Sep 17 00:00:00 2001 From: cepetr Date: Wed, 28 Aug 2024 07:50:09 +0200 Subject: [PATCH 26/44] refactor(embed/core): replace enable/disable_irq by irq_lock/unlock [no changelog] --- core/embed/bootloader/main.c | 2 +- core/embed/firmware/mpconfigport.h | 4 +- core/embed/trezorhal/stm32f4/bootutils.c | 2 +- core/embed/trezorhal/stm32f4/i2c_bus.c | 12 +++--- core/embed/trezorhal/stm32f4/irq.h | 54 +++++++++++++++++++----- core/embed/trezorhal/stm32f4/sdcard.c | 6 +-- core/embed/trezorhal/stm32f4/systick.c | 4 +- core/embed/trezorhal/stm32f4/systimer.c | 22 +++++----- core/embed/trezorhal/stm32u5/i2c_bus.c | 12 +++--- core/embed/trezorhal/stm32u5/sdcard.c | 6 +-- 10 files changed, 79 insertions(+), 45 deletions(-) diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 4080c508937..b273ead7695 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -345,7 +345,7 @@ void real_jump_to_firmware(void) { __attribute__((noreturn)) void jump_to_fw_through_reset(void) { display_fade(display_backlight(-1), 0, 200); - disable_irq(); + __disable_irq(); delete_secrets(); NVIC_SystemReset(); for (;;) diff --git a/core/embed/firmware/mpconfigport.h b/core/embed/firmware/mpconfigport.h index b80f257c606..0e9e990b1b6 100644 --- a/core/embed/firmware/mpconfigport.h +++ b/core/embed/firmware/mpconfigport.h @@ -194,8 +194,8 @@ typedef long mp_off_t; #include "irq.h" -#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() -#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) +#define MICROPY_BEGIN_ATOMIC_SECTION() irq_lock() +#define MICROPY_END_ATOMIC_SECTION(state) irq_unlock(state) #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(bool); \ diff --git a/core/embed/trezorhal/stm32f4/bootutils.c b/core/embed/trezorhal/stm32f4/bootutils.c index 08ffc2147c4..4667fc5e8de 100644 --- a/core/embed/trezorhal/stm32f4/bootutils.c +++ b/core/embed/trezorhal/stm32f4/bootutils.c @@ -72,7 +72,7 @@ void reboot_to_bootloader(void) { #ifdef STM32U5 // extern uint32_t g_boot_command; g_boot_command = boot_command; - disable_irq(); + __disable_irq(); delete_secrets(); NVIC_SystemReset(); #else diff --git a/core/embed/trezorhal/stm32f4/i2c_bus.c b/core/embed/trezorhal/stm32f4/i2c_bus.c index c5769e2e4d6..2dfacc3abe1 100644 --- a/core/embed/trezorhal/stm32f4/i2c_bus.c +++ b/core/embed/trezorhal/stm32f4/i2c_bus.c @@ -367,9 +367,9 @@ void i2c_bus_close(i2c_bus_t* bus) { } i2c_status_t i2c_packet_status(const i2c_packet_t* packet) { - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); i2c_status_t status = packet->status; - enable_irq(irq_state); + irq_unlock(irq_key); return status; } @@ -460,14 +460,14 @@ i2c_status_t i2c_bus_submit(i2c_bus_t* bus, i2c_packet_t* packet) { packet->status = I2C_STATUS_PENDING; // Insert packet into the queue - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); if (i2c_bus_add_packet(bus, packet)) { // The queue was empty, start the operation if (!bus->callback_executed && !bus->abort_pending) { i2c_bus_head_continue(bus); } } - enable_irq(irq_state); + irq_unlock(irq_key); return I2C_STATUS_OK; } @@ -478,7 +478,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) { return; } - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); if (packet->status == I2C_STATUS_PENDING) { if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) { @@ -502,7 +502,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) { packet->status = I2C_STATUS_ABORTED; } - enable_irq(irq_state); + irq_unlock(irq_key); } // Completes the current packet by removing it from the queue diff --git a/core/embed/trezorhal/stm32f4/irq.h b/core/embed/trezorhal/stm32f4/irq.h index b237d7b0882..525bb92043e 100644 --- a/core/embed/trezorhal/stm32f4/irq.h +++ b/core/embed/trezorhal/stm32f4/irq.h @@ -36,22 +36,56 @@ extern uint32_t irq_stats[IRQ_STATS_MAX]; #define IRQ_EXIT(irq) #endif +typedef uint32_t irq_key_t; + // Checks if interrupts are enabled -#define IS_IRQ_ENABLED(state) (((state) & 1) == 0) +#define IS_IRQ_ENABLED(key) (((key) & 1) == 0) // Get the current value of the CPU's exception mask register. // The least significant bit indicates if interrupts are enabled or disabled. -static inline uint32_t query_irq(void) { return __get_PRIMASK(); } +static inline irq_key_t query_irq(void) { return __get_PRIMASK(); } -// Restore the CPU's exception mask register to a previous state -static inline void enable_irq(uint32_t state) { __set_PRIMASK(state); } +// Disables interrupts and returns the previous interrupt state. +// +// This function is used to create critical sections by disabling interrupts +// on a Cortex-M platform. It returns the current state of the PRIMASK register, +// which controls the global interrupt enable/disable state. +// +// Important: +// - The `"memory"` clobber is included to prevent the compiler from reordering +// memory operations across this function, ensuring that all memory accesses +// efore `irq_lock()` are completed before interrupts are disabled. +// - The order of operations on non-volatile variables relative to this +// function is not guaranteed without memory barriers or other +// synchronization mechanisms. +// - When using Link-Time Optimization (LTO), ensure that the behavior of these +// functions is thoroughly tested, as LTO can lead to more aggressive +// optimizations. While GCC typically respects the order of `volatile` +// operations, this is not guaranteed by the C standard. +static inline irq_key_t irq_lock(void) { + uint32_t key; + __asm volatile( + "MRS %0, PRIMASK\n" + "CPSID i" + : "=r"(key) + : + : "memory" // Clobber memory to ensure correct memory operations + ); + return key; +} -// Disable all interrupts and return the current state of the -// CPU's exception mask register -static inline uint32_t disable_irq(void) { - uint32_t state = __get_PRIMASK(); - __disable_irq(); - return state; +// Restores the interrupt state to what it was before `irq_lock`. +// +// This function re-enables interrupts based on the PRIMASK state passed to it. +// It should be used in conjunction with `irq_lock` to restore the previous +// interrupt state after a critical section. +static inline void irq_unlock(irq_key_t key) { + __asm volatile( + "MSR PRIMASK, %0\n" + : + : "r"(key) + : "memory" // Clobber memory to ensure correct memory operations + ); } // IRQ priority levels used throughout the system diff --git a/core/embed/trezorhal/stm32f4/sdcard.c b/core/embed/trezorhal/stm32f4/sdcard.c index 432e5cb49fa..21c7b099ece 100644 --- a/core/embed/trezorhal/stm32f4/sdcard.c +++ b/core/embed/trezorhal/stm32f4/sdcard.c @@ -253,13 +253,13 @@ static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t start = HAL_GetTick(); for (;;) { // Do an atomic check of the state; WFI will exit even if IRQs are disabled - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); if (sd->State != HAL_SD_STATE_BUSY) { - enable_irq(irq_state); + irq_unlock(irq_key); break; } __WFI(); - enable_irq(irq_state); + irq_unlock(irq_key); if (HAL_GetTick() - start >= timeout) { return HAL_TIMEOUT; } diff --git a/core/embed/trezorhal/stm32f4/systick.c b/core/embed/trezorhal/stm32f4/systick.c index a91ec425335..13a1b71eb48 100644 --- a/core/embed/trezorhal/stm32f4/systick.c +++ b/core/embed/trezorhal/stm32f4/systick.c @@ -106,7 +106,7 @@ void systick_update_freq(void) { uint64_t systick_cycles(void) { systick_driver_t* drv = &g_systick_driver; - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); // Current value of the SysTick counter uint32_t val = SysTick->VAL; @@ -125,7 +125,7 @@ uint64_t systick_cycles(void) { uint64_t cycles = drv->cycles + ((val > 0) ? (drv->cycles_per_ms - val) : 0); - enable_irq(irq_state); + irq_unlock(irq_key); return cycles; } diff --git a/core/embed/trezorhal/stm32f4/systimer.c b/core/embed/trezorhal/stm32f4/systimer.c index 723ff781d07..ca7ae63d28e 100644 --- a/core/embed/trezorhal/stm32f4/systimer.c +++ b/core/embed/trezorhal/stm32f4/systimer.c @@ -97,7 +97,7 @@ systimer_t* systimer_create(systimer_callback_t callback, void* context) { return NULL; } - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); // Find a free timer entry for (int i = 0; i < MAX_SYSTIMERS; i++) { @@ -109,13 +109,13 @@ systimer_t* systimer_create(systimer_callback_t callback, void* context) { timer->context = context; timer->callback = callback; - enable_irq(irq_state); + irq_unlock(irq_key); return timer; } } // No free timer entry found - enable_irq(irq_state); + irq_unlock(irq_key); return NULL; } @@ -138,11 +138,11 @@ void systimer_set(systimer_t* timer, uint32_t delay_ms) { uint64_t delay = systick_us_to_cycles((uint64_t)delay_ms * 1000); uint64_t expiration = systick_cycles() + delay; - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); timer->expiration = expiration; timer->period = 0; timer->scheduled = true; - enable_irq(irq_state); + irq_unlock(irq_key); } void systimer_set_periodic(systimer_t* timer, uint32_t period_ms) { @@ -155,11 +155,11 @@ void systimer_set_periodic(systimer_t* timer, uint32_t period_ms) { uint64_t period = systick_us_to_cycles((uint64_t)period_ms * 1000); uint64_t expiration = systick_cycles() + period; - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); timer->expiration = expiration; timer->period = period; timer->scheduled = true; - enable_irq(irq_state); + irq_unlock(irq_key); } bool systimer_unset(systimer_t* timer) { @@ -169,10 +169,10 @@ bool systimer_unset(systimer_t* timer) { return false; } - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); bool was_scheduled = timer->scheduled; timer->scheduled = false; - enable_irq(irq_state); + irq_unlock(irq_key); return was_scheduled; } @@ -183,10 +183,10 @@ systimer_key_t systimer_suspend(systimer_t* timer) { return false; } - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); bool was_suspended = timer->suspended; timer->suspended = true; - enable_irq(irq_state); + irq_unlock(irq_key); return was_suspended; } diff --git a/core/embed/trezorhal/stm32u5/i2c_bus.c b/core/embed/trezorhal/stm32u5/i2c_bus.c index 58b157cf1e6..127aabed7f9 100644 --- a/core/embed/trezorhal/stm32u5/i2c_bus.c +++ b/core/embed/trezorhal/stm32u5/i2c_bus.c @@ -367,9 +367,9 @@ void i2c_bus_close(i2c_bus_t* bus) { } i2c_status_t i2c_packet_status(const i2c_packet_t* packet) { - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); i2c_status_t status = packet->status; - enable_irq(irq_state); + irq_unlock(irq_key); return status; } @@ -506,14 +506,14 @@ i2c_status_t i2c_bus_submit(i2c_bus_t* bus, i2c_packet_t* packet) { packet->status = I2C_STATUS_PENDING; // Insert packet into the queue - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); if (i2c_bus_add_packet(bus, packet)) { // The queue was empty, start the operation if (!bus->callback_executed && !bus->abort_pending) { i2c_bus_head_continue(bus); } } - enable_irq(irq_state); + irq_unlock(irq_key); return I2C_STATUS_OK; } @@ -524,7 +524,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) { return; } - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); if (packet->status == I2C_STATUS_PENDING) { if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) { @@ -553,7 +553,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) { packet->status = I2C_STATUS_ABORTED; } - enable_irq(irq_state); + irq_unlock(irq_key); } // Completes the current packet by removing it from the queue diff --git a/core/embed/trezorhal/stm32u5/sdcard.c b/core/embed/trezorhal/stm32u5/sdcard.c index b040e186a79..714a48d4e1d 100644 --- a/core/embed/trezorhal/stm32u5/sdcard.c +++ b/core/embed/trezorhal/stm32u5/sdcard.c @@ -256,13 +256,13 @@ static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t start = HAL_GetTick(); for (;;) { // Do an atomic check of the state; WFI will exit even if IRQs are disabled - uint32_t irq_state = disable_irq(); + irq_key_t irq_key = irq_lock(); if (sd->State != HAL_SD_STATE_BUSY) { - enable_irq(irq_state); + irq_unlock(irq_key); break; } __WFI(); - enable_irq(irq_state); + irq_unlock(irq_key); if (HAL_GetTick() - start >= timeout) { return HAL_TIMEOUT; } From 5562abe612190e9d6c0319f737dad3233d3e0fdf Mon Sep 17 00:00:00 2001 From: cepetr Date: Wed, 28 Aug 2024 13:44:21 +0200 Subject: [PATCH 27/44] refactor(core/embed): use new i2c driver in ft6x36 driver [no changelog] --- core/embed/trezorhal/stm32f4/touch/ft6x36.c | 125 +++++++++++--------- core/embed/trezorhal/stm32f4/touch/ft6x36.h | 3 +- 2 files changed, 71 insertions(+), 57 deletions(-) diff --git a/core/embed/trezorhal/stm32f4/touch/ft6x36.c b/core/embed/trezorhal/stm32f4/touch/ft6x36.c index 2d8e5485bf0..f03ac46a331 100644 --- a/core/embed/trezorhal/stm32f4/touch/ft6x36.c +++ b/core/embed/trezorhal/stm32f4/touch/ft6x36.c @@ -27,7 +27,7 @@ #include "common.h" #include "ft6x36.h" -#include "i2c.h" +#include "i2c_bus.h" #include "touch.h" #ifdef TOUCH_PANEL_LX154A2422CPT23 @@ -40,6 +40,8 @@ typedef struct { // Set if the driver is initialized secbool initialized; + // I2c bus where the touch controller is connected + i2c_bus_t* i2c_bus; // Set if the driver is ready to report touches. // FT6X36 needs about 300ms after power-up to stabilize. secbool ready; @@ -71,30 +73,32 @@ static touch_driver_t g_touch_driver = { // // If the I2C bus is busy, the function will cycle the // bus and retry the operation. -static secbool ft6x36_read_regs(uint8_t reg, uint8_t* value, size_t count) { - uint16_t i2c_bus = TOUCH_I2C_INSTANCE; - uint8_t i2c_addr = FT6X36_I2C_ADDR; - uint8_t txdata[] = {reg}; - uint8_t retries = 3; - - do { - int result = i2c_transmit(i2c_bus, i2c_addr, txdata, sizeof(txdata), 10); - if (HAL_OK == result) { - result = i2c_receive(i2c_bus, i2c_addr, value, count, 10); - } +static secbool ft6x36_read_regs(i2c_bus_t* bus, uint8_t reg, uint8_t* value, + size_t count) { + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_TX | I2C_FLAG_EMBED, + .size = 1, + .data = {reg}, + }, + { + .flags = I2C_FLAG_RX, + .size = count, + .ptr = value, + }, + }; - if (HAL_OK == result) { - // success - return sectrue; - } else if (HAL_BUSY == result && retries > 0) { - // I2C bus is busy, cycle it and try again - i2c_cycle(i2c_bus); - retries--; - } else { - // Aother error or retries exhausted - return secfalse; - } - } while (1); + i2c_packet_t pkt = { + .address = FT6X36_I2C_ADDR, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + + if (I2C_STATUS_OK != i2c_bus_submit_and_wait(bus, &pkt)) { + return secfalse; + } + + return sectrue; } // Writes a register to the FT6X36. @@ -104,26 +108,26 @@ static secbool ft6x36_read_regs(uint8_t reg, uint8_t* value, size_t count) { // // If the I2C bus is busy, the function will cycle the // bus and retry the operation. -static secbool ft6x36_write_reg(uint8_t reg, uint8_t value) { - uint16_t i2c_bus = TOUCH_I2C_INSTANCE; - uint8_t i2c_addr = FT6X36_I2C_ADDR; - uint8_t txdata[] = {reg, value}; - uint8_t retries = 3; - - do { - int result = i2c_transmit(i2c_bus, i2c_addr, txdata, sizeof(txdata), 10); - if (HAL_OK == result) { - // success - return sectrue; - } else if (HAL_BUSY == result && retries > 0) { - // I2C bus is busy, cycle it and try again - i2c_cycle(i2c_bus); - retries--; - } else { - // Another error or retries exhausted - return secfalse; - } - } while (1); +static secbool ft6x36_write_reg(i2c_bus_t* bus, uint8_t reg, uint8_t value) { + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_TX | I2C_FLAG_EMBED, + .size = 2, + .data = {reg, value}, + }, + }; + + i2c_packet_t pkt = { + .address = FT6X36_I2C_ADDR, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + + if (I2C_STATUS_OK != i2c_bus_submit_and_wait(bus, &pkt)) { + return secfalse; + } + + return sectrue; } // Powers down the touch controller and puts all @@ -208,7 +212,7 @@ static bool ft6x36_test_and_clear_interrupt(void) { } // Configures the touch controller to the funtional state. -static secbool ft6x36_configure(void) { +static secbool ft6x36_configure(i2c_bus_t* i2c_bus) { const static uint8_t config[] = { // Set touch controller to the interrupt trigger mode. // Basically, CTPM generates a pulse when new data is available. @@ -224,7 +228,7 @@ static secbool ft6x36_configure(void) { uint8_t reg = config[i]; uint8_t value = config[i + 1]; - if (sectrue != ft6x36_write_reg(reg, value)) { + if (sectrue != ft6x36_write_reg(i2c_bus, reg, value)) { return secfalse; } } @@ -250,6 +254,8 @@ secbool touch_init(void) { return sectrue; } + memset(driver, 0, sizeof(touch_driver_t)); + // Initialize GPIO to the default configuration // (touch controller is powered down) ft6x36_power_down(); @@ -257,10 +263,14 @@ secbool touch_init(void) { // Power up the touch controller and perform the reset sequence ft6x36_power_up(); + driver->i2c_bus = i2c_bus_open(TOUCH_I2C_INSTANCE); + if (driver->i2c_bus == NULL) { + goto cleanup; + } + // Configure the touch controller - if (sectrue != ft6x36_configure()) { - ft6x36_power_down(); - return secfalse; + if (sectrue != ft6x36_configure(driver->i2c_bus)) { + goto cleanup; } driver->init_ticks = hal_ticks_ms(); @@ -269,16 +279,20 @@ secbool touch_init(void) { driver->initialized = sectrue; return sectrue; + +cleanup: + i2c_bus_close(driver->i2c_bus); + ft6x36_power_down(); + memset(driver, 0, sizeof(touch_driver_t)); + return secfalse; } void touch_deinit(void) { touch_driver_t* driver = &g_touch_driver; if (sectrue == driver->initialized) { - // Do not need to deinitialized the controller - // just power it off + i2c_bus_close(driver->i2c_bus); ft6x36_power_down(); - memset(driver, 0, sizeof(touch_driver_t)); } } @@ -301,7 +315,7 @@ secbool touch_set_sensitivity(uint8_t value) { touch_driver_t* driver = &g_touch_driver; if (sectrue == driver->initialized) { - return ft6x36_write_reg(FT6X36_REG_TH_GROUP, value); + return ft6x36_write_reg(driver->i2c_bus, FT6X36_REG_TH_GROUP, value); } else { return secfalse; } @@ -324,7 +338,8 @@ uint8_t touch_get_version(void) { uint8_t fw_version = 0; - if (sectrue != ft6x36_read_regs(FT6X36_REG_FIRMID, &fw_version, 1)) { + if (sectrue != + ft6x36_read_regs(driver->i2c_bus, FT6X36_REG_FIRMID, &fw_version, 1)) { ft6x36_power_down(); return secfalse; } @@ -432,7 +447,7 @@ uint32_t touch_get_event(void) { driver->read_ticks = ticks; // Read the set of registers containing touch event and coordinates - if (sectrue != ft6x36_read_regs(0x00, regs, sizeof(regs))) { + if (sectrue != ft6x36_read_regs(driver->i2c_bus, 0x00, regs, sizeof(regs))) { // Failed to read the touch registers return 0; } diff --git a/core/embed/trezorhal/stm32f4/touch/ft6x36.h b/core/embed/trezorhal/stm32f4/touch/ft6x36.h index 8629a126938..852b8fea391 100644 --- a/core/embed/trezorhal/stm32f4/touch/ft6x36.h +++ b/core/embed/trezorhal/stm32f4/touch/ft6x36.h @@ -21,8 +21,7 @@ #define _TOUCH_FT6X36_H // I2C address of the FT6X36 on the I2C bus. -// `<< 1` is required because the HAL expects the address to be shifted by 1. -#define FT6X36_I2C_ADDR (0x38 << 1) +#define FT6X36_I2C_ADDR 0x38 // ------------------------------------------------------------ // FT6X36 registers From 0b4dbe1a7b78ae70dbe6812948c9d7684e9fbf59 Mon Sep 17 00:00:00 2001 From: cepetr Date: Wed, 28 Aug 2024 13:44:29 +0200 Subject: [PATCH 28/44] refactor(core/embed): use new i2c driver in drv2625 driver [no changelog] --- .../stm32u5/haptic/drv2625/drv2625.c | 77 +++++++++++++------ .../stm32u5/haptic/drv2625/drv2625.h | 3 +- 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c b/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c index 4f81f5ba6c7..d87ace2fddf 100644 --- a/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c +++ b/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c @@ -25,7 +25,7 @@ #include "common.h" #include "drv2625.h" #include "haptic.h" -#include "i2c.h" +#include "i2c_bus.h" #include STM32_HAL_H @@ -64,6 +64,8 @@ typedef struct { // Set if driver is initialized bool initialized; + // I2c bus where the touch controller is connected + i2c_bus_t *i2c_bus; // Set if driver is enabled bool enabled; // Set to if real-time playing is activated. @@ -78,10 +80,26 @@ static haptic_driver_t g_haptic_driver = { .initialized = false, }; -static bool drv2625_set_reg(uint8_t addr, uint8_t value) { - uint8_t data[] = {addr, value}; - return i2c_transmit(DRV2625_I2C_INSTANCE, DRV2625_I2C_ADDRESS, data, - sizeof(data), 1) == HAL_OK; +static bool drv2625_set_reg(i2c_bus_t *bus, uint8_t addr, uint8_t value) { + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_TX | I2C_FLAG_EMBED, + .size = 2, + .data = {addr, value}, + }, + }; + + i2c_packet_t pkt = { + .address = DRV2625_I2C_ADDRESS, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + + if (I2C_STATUS_OK != i2c_bus_submit_and_wait(bus, &pkt)) { + return false; + } + + return true; } bool haptic_init(void) { @@ -93,34 +111,41 @@ bool haptic_init(void) { memset(driver, 0, sizeof(haptic_driver_t)); + driver->i2c_bus = i2c_bus_open(DRV2625_I2C_INSTANCE); + if (driver->i2c_bus == NULL) { + goto cleanup; + } + // select library - if (!drv2625_set_reg(DRV2625_REG_LIBRARY, + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_LIBRARY, LIB_SEL | DRV2625_REG_LIBRARY_GAIN_25)) { - return false; + goto cleanup; } if (!drv2625_set_reg( - DRV2625_REG_LRAERM, + driver->i2c_bus, DRV2625_REG_LRAERM, LRA_ERM_SEL | LOOP_SEL | DRV2625_REG_LRAERM_AUTO_BRK_OL)) { + goto cleanup; } - if (!drv2625_set_reg(DRV2625_REG_OD_CLAMP, ACTUATOR_OD_CLAMP)) { - return false; + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_OD_CLAMP, + ACTUATOR_OD_CLAMP)) { + goto cleanup; } - if (!drv2625_set_reg(DRV2625_REG_LRA_WAVE_SHAPE, + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_LRA_WAVE_SHAPE, DRV2625_REG_LRA_WAVE_SHAPE_SINE)) { - return false; + goto cleanup; } - if (!drv2625_set_reg(DRV2625_REG_OL_LRA_PERIOD_LO, + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_OL_LRA_PERIOD_LO, ACTUATOR_LRA_PERIOD & 0xFF)) { - return false; + goto cleanup; } - if (!drv2625_set_reg(DRV2625_REG_OL_LRA_PERIOD_HI, + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_OL_LRA_PERIOD_HI, ACTUATOR_LRA_PERIOD >> 8)) { - return false; + goto cleanup; } GPIO_InitTypeDef GPIO_InitStructure = {0}; @@ -158,6 +183,11 @@ bool haptic_init(void) { driver->enabled = true; return true; + +cleanup: + i2c_bus_close(driver->i2c_bus); + memset(driver, 0, sizeof(haptic_driver_t)); + return false; } void haptic_deinit(void) { @@ -167,6 +197,8 @@ void haptic_deinit(void) { return; } + i2c_bus_close(driver->i2c_bus); + // TODO: deinitialize GPIOs and the TIMER memset(driver, 0, sizeof(haptic_driver_t)); @@ -197,7 +229,7 @@ static bool haptic_play_rtp(int8_t amplitude, uint16_t duration_ms) { if (!driver->playing_rtp) { if (!drv2625_set_reg( - DRV2625_REG_MODE, + driver->i2c_bus, DRV2625_REG_MODE, DRV2625_REG_MODE_RTP | DRV2625_REG_MODE_TRGFUNC_ENABLE)) { return false; } @@ -205,7 +237,7 @@ static bool haptic_play_rtp(int8_t amplitude, uint16_t duration_ms) { driver->playing_rtp = true; } - if (!drv2625_set_reg(DRV2625_REG_RTP, (uint8_t)amplitude)) { + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_RTP, (uint8_t)amplitude)) { return false; } @@ -233,19 +265,20 @@ static bool haptic_play_lib(drv2625_lib_effect_t effect) { driver->playing_rtp = false; - if (!drv2625_set_reg(DRV2625_REG_MODE, DRV2625_REG_MODE_WAVEFORM)) { + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_MODE, + DRV2625_REG_MODE_WAVEFORM)) { return false; } - if (!drv2625_set_reg(DRV2625_REG_WAVESEQ1, effect)) { + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_WAVESEQ1, effect)) { return false; } - if (!drv2625_set_reg(DRV2625_REG_WAVESEQ2, 0)) { + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_WAVESEQ2, 0)) { return false; } - if (!drv2625_set_reg(DRV2625_REG_GO, DRV2625_REG_GO_GO)) { + if (!drv2625_set_reg(driver->i2c_bus, DRV2625_REG_GO, DRV2625_REG_GO_GO)) { return false; } diff --git a/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.h b/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.h index 40a0d5e594f..fe67b2c77ff 100644 --- a/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.h +++ b/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.h @@ -2,8 +2,7 @@ #define TREZOR_HAL_DRV_2625_H // I2C address of the DRV2625 on the I2C bus. -// `<< 1` is required because the HAL expects the address to be shifted by 1. -#define DRV2625_I2C_ADDRESS (0x5A << 1) +#define DRV2625_I2C_ADDRESS 0x5A // ------------------------------------------------------------ // DRV2625 registers From bb3b00c24f2c75f7e61f648c54dc6a2e161055ca Mon Sep 17 00:00:00 2001 From: cepetr Date: Wed, 28 Aug 2024 16:50:11 +0200 Subject: [PATCH 29/44] refactor(core/embed): use new i2c driver in optiga driver [no changelog] --- .../embed/trezorhal/optiga/optiga_transport.c | 61 +++++++++++++++---- core/embed/trezorhal/optiga_common.h | 1 + 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/core/embed/trezorhal/optiga/optiga_transport.c b/core/embed/trezorhal/optiga/optiga_transport.c index 2d183f7b664..8876c190ed4 100644 --- a/core/embed/trezorhal/optiga/optiga_transport.c +++ b/core/embed/trezorhal/optiga/optiga_transport.c @@ -26,7 +26,7 @@ #include #include "aes/aesccm.h" #include "common.h" -#include "i2c.h" +#include "i2c_bus.h" #include "memzero.h" #include "optiga_hal.h" #include "tls_prf.h" @@ -58,9 +58,6 @@ static const uint8_t I2C_STATE_BYTE1_RESP_RDY = 0x40; // I2C base address of Optiga. static const uint8_t BASE_ADDR = 0x30; -// Address of Optiga use by our HAL which requires it to be shifted by one bit. -static const uint16_t OPTIGA_ADDRESS = (BASE_ADDR << 1); - // Constants for our I2C HAL. static const uint32_t I2C_TIMEOUT_MS = 25; static const int I2C_MAX_RETRY_COUNT = 10; @@ -110,6 +107,8 @@ enum { SCTR_PROTECTED = 0x23, // Record exchange message. Fully protected. }; +static i2c_bus_t *i2c_bus = NULL; + static uint8_t frame_num_out = 0xff; static uint8_t frame_num_in = 0xff; static uint8_t frame_buffer[1 + OPTIGA_DATA_REG_LEN]; @@ -190,35 +189,73 @@ static uint16_t calc_crc(uint8_t *data, size_t data_size) { optiga_result optiga_init(void) { optiga_hal_init(); + + i2c_bus = i2c_bus_open(OPTIGA_I2C_INSTANCE); + if (i2c_bus == NULL) { + return OPTIGA_ERR_I2C_OPEN; + } + return optiga_set_data_reg_len(OPTIGA_DATA_REG_LEN); } static optiga_result optiga_i2c_write(const uint8_t *data, uint16_t data_size) { OPTIGA_LOG(">>>", data, data_size) + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_TX, + .size = data_size, + .ptr = (void *)data, + }, + }; + + i2c_packet_t pkt = { + .address = BASE_ADDR, + .timeout = I2C_TIMEOUT_MS, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + for (int try_count = 0; try_count <= I2C_MAX_RETRY_COUNT; ++try_count) { if (try_count != 0) { - hal_delay(1); + systick_delay_ms(1); } - if (HAL_OK == i2c_transmit(OPTIGA_I2C_INSTANCE, OPTIGA_ADDRESS, - (uint8_t *)data, data_size, I2C_TIMEOUT_MS)) { - hal_delay_us(1000); + + if (I2C_STATUS_OK == i2c_bus_submit_and_wait(i2c_bus, &pkt)) { + systick_delay_ms(1); return OPTIGA_SUCCESS; } - hal_delay_us(1000); + + systick_delay_ms(1); } return OPTIGA_ERR_I2C_WRITE; } static optiga_result optiga_i2c_read(uint8_t *buffer, uint16_t buffer_size) { + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_RX, + .size = buffer_size, + .ptr = buffer, + }, + }; + + i2c_packet_t pkt = { + .address = BASE_ADDR, + .timeout = I2C_TIMEOUT_MS, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + for (int try_count = 0; try_count <= I2C_MAX_RETRY_COUNT; ++try_count) { - HAL_Delay(1); - if (HAL_OK == i2c_receive(OPTIGA_I2C_INSTANCE, OPTIGA_ADDRESS, buffer, - buffer_size, I2C_TIMEOUT_MS)) { + systick_delay_ms(1); + + if (I2C_STATUS_OK == i2c_bus_submit_and_wait(i2c_bus, &pkt)) { OPTIGA_LOG("<<<", buffer, buffer_size) return OPTIGA_SUCCESS; } } + return OPTIGA_ERR_I2C_READ; } diff --git a/core/embed/trezorhal/optiga_common.h b/core/embed/trezorhal/optiga_common.h index 1c1e24e67e6..21d74aed689 100644 --- a/core/embed/trezorhal/optiga_common.h +++ b/core/embed/trezorhal/optiga_common.h @@ -24,6 +24,7 @@ typedef enum _optiga_result { OPTIGA_SUCCESS = 0, // Operation completed successfully. + OPTIGA_ERR_I2C_OPEN, // HAL failed to open I2C driver. OPTIGA_ERR_I2C_WRITE, // HAL failed on I2C write. OPTIGA_ERR_I2C_READ, // HAL failed on I2C read. OPTIGA_ERR_BUSY, // Optiga is busy processing another command. From a3f2b5b2d0bc3182d3d22355b706f852e698a78f Mon Sep 17 00:00:00 2001 From: cepetr Date: Wed, 28 Aug 2024 16:50:25 +0200 Subject: [PATCH 30/44] refactor(core/embed): use new i2c driver in sitronix touch driver [no changelog] --- core/embed/trezorhal/stm32u5/touch/sitronix.c | 91 +++++++++++++++++-- 1 file changed, 82 insertions(+), 9 deletions(-) diff --git a/core/embed/trezorhal/stm32u5/touch/sitronix.c b/core/embed/trezorhal/stm32u5/touch/sitronix.c index 5cfb0a1f3e4..4da2aeb1bd6 100644 --- a/core/embed/trezorhal/stm32u5/touch/sitronix.c +++ b/core/embed/trezorhal/stm32u5/touch/sitronix.c @@ -1,7 +1,8 @@ #include STM32_HAL_H #include TREZOR_BOARD -#include "i2c.h" +#include "common.h" +#include "i2c_bus.h" #include "irq.h" /** @addtogroup STM32U5x9J_DISCOVERY @@ -49,7 +50,12 @@ #define BSP_ERROR_BUS_DMA_FAILURE -107 /* TS I2C address */ -#define TS_I2C_ADDRESS 0xE0U +#define TS_I2C_ADDRESS 0x70U + +#define SITRONIX_OK (0) +#define SITRONIX_ERROR (-1) + +static i2c_bus_t *i2c_bus = NULL; /******************************************************************************* * Function Name : sitronix_read_reg @@ -59,8 +65,29 @@ * Output : pdata Read *******************************************************************************/ int32_t sitronix_read_reg(uint8_t reg, uint8_t *pdata, uint16_t length) { - return i2c_mem_read(TOUCH_I2C_INSTANCE, TS_I2C_ADDRESS, reg, length, pdata, - length, 1000); + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_TX | I2C_FLAG_EMBED, + .size = 1, + .data = {reg}, + }, + { + .flags = I2C_FLAG_RX, + .size = length, + .ptr = pdata, + }, + }; + + i2c_packet_t pkt = { + .address = TS_I2C_ADDRESS, + .timeout = 100, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + + i2c_status_t status = i2c_bus_submit_and_wait(i2c_bus, &pkt); + + return (status == I2C_STATUS_OK) ? SITRONIX_OK : SITRONIX_ERROR; } /******************************************************************************* @@ -71,8 +98,29 @@ int32_t sitronix_read_reg(uint8_t reg, uint8_t *pdata, uint16_t length) { * Output : None *******************************************************************************/ int32_t sitronix_write_reg(uint8_t reg, uint8_t *pdata, uint16_t length) { - return i2c_mem_write(TOUCH_I2C_INSTANCE, TS_I2C_ADDRESS, reg, length, pdata, - length, 1000); + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_TX | I2C_FLAG_EMBED, + .size = 1, + .data = {reg}, + }, + { + .flags = I2C_FLAG_TX, + .size = length, + .ptr = pdata, + }, + }; + + i2c_packet_t pkt = { + .address = TS_I2C_ADDRESS, + .timeout = 100, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + + i2c_status_t status = i2c_bus_submit_and_wait(i2c_bus, &pkt); + + return (status == I2C_STATUS_OK) ? SITRONIX_OK : SITRONIX_ERROR; } /******************************************************************************* @@ -83,7 +131,24 @@ int32_t sitronix_write_reg(uint8_t reg, uint8_t *pdata, uint16_t length) { * Output : pdata Read *******************************************************************************/ int32_t sitronix_read_data(uint8_t *pdata, uint16_t length) { - return i2c_receive(TOUCH_I2C_INSTANCE, TS_I2C_ADDRESS, pdata, length, 1000); + i2c_op_t ops[] = { + { + .flags = I2C_FLAG_RX, + .size = length, + .ptr = pdata, + }, + }; + + i2c_packet_t pkt = { + .address = TS_I2C_ADDRESS, + .timeout = 100, + .op_count = ARRAY_LENGTH(ops), + .ops = ops, + }; + + i2c_status_t status = i2c_bus_submit_and_wait(i2c_bus, &pkt); + + return (status == I2C_STATUS_OK) ? SITRONIX_OK : SITRONIX_ERROR; } /* Includes ------------------------------------------------------------------*/ @@ -96,8 +161,6 @@ int32_t sitronix_read_data(uint8_t *pdata, uint16_t length) { /** @defgroup SITRONIX_Exported_Constants SITRONIX Exported Constants * @{ */ -#define SITRONIX_OK (0) -#define SITRONIX_ERROR (-1) /* Max detectable simultaneous touches */ #define SITRONIX_MAX_DETECTABLE_TOUCH 10U @@ -747,6 +810,11 @@ static int32_t SITRONIX_Probe(uint32_t Instance); int32_t BSP_TS_Init(uint32_t Instance, TS_Init_t *TS_Init) { int32_t status = BSP_ERROR_NONE; + i2c_bus = i2c_bus_open(TOUCH_I2C_INSTANCE); + if (i2c_bus == NULL) { + return BSP_ERROR_COMPONENT_FAILURE; + } + if ((TS_Init == NULL) || (Instance >= TS_INSTANCES_NBR)) { status = BSP_ERROR_WRONG_PARAM; } else { @@ -798,6 +866,11 @@ int32_t BSP_TS_DeInit(uint32_t Instance) { if (Ts_Drv[Instance]->DeInit(Ts_CompObj[Instance]) < 0) { status = BSP_ERROR_COMPONENT_FAILURE; } + + if (i2c_bus != NULL) { + i2c_bus_close(i2c_bus); + i2c_bus = NULL; + } } return status; From ac8ed8db79964202ac8d338dfe8cbbc050c83b9b Mon Sep 17 00:00:00 2001 From: cepetr Date: Wed, 28 Aug 2024 16:59:31 +0200 Subject: [PATCH 31/44] refactor(core/embed): use new i2c driver in stmpe811 touch driver [no changelog] --- core/embed/trezorhal/stm32f4/touch/stmpe811.c | 147 ++++++++++++------ 1 file changed, 97 insertions(+), 50 deletions(-) diff --git a/core/embed/trezorhal/stm32f4/touch/stmpe811.c b/core/embed/trezorhal/stm32f4/touch/stmpe811.c index 05a6f557271..8fc25092b1c 100644 --- a/core/embed/trezorhal/stm32f4/touch/stmpe811.c +++ b/core/embed/trezorhal/stm32f4/touch/stmpe811.c @@ -25,7 +25,7 @@ #include "common.h" #include "secbool.h" -#include "i2c.h" +#include "i2c_bus.h" #include "stmpe811.h" #include "touch.h" @@ -157,8 +157,6 @@ #define STMPE811_TS_CTRL_ENABLE 0x01 #define STMPE811_TS_CTRL_STATUS 0x80 -#define TOUCH_ADDRESS \ - (0x38U << 1) // the HAL requires the 7-bit address to be shifted by one bit #define TOUCH_PACKET_SIZE 7U #define EVENT_PRESS_DOWN 0x00U #define EVENT_CONTACT 0x80U @@ -173,17 +171,14 @@ #define EVENT_OLD_TIMEOUT_MS 50 #define EVENT_MISSING_TIMEOUT_MS 50 -#define TS_I2C_ADDRESS 0x82 +#define TS_I2C_ADDRESS (0x82 >> 1) #define I2Cx_TIMEOUT_MAX \ 0x3000 /*initialized != sectrue) { + i2c_bus = i2c_bus_open(TOUCH_I2C_INSTANCE); + if (i2c_bus == NULL) { + return secfalse; + } + stmpe811_Reset(); touch_set_mode(); @@ -589,6 +635,7 @@ void touch_deinit(void) { if (driver->initialized == sectrue) { // Not implemented properly + i2c_bus_close(i2c_bus); memset(driver, 0, sizeof(touch_driver_t)); } } From 694ac201a98d5e6f03d1e3e4348a84bc6fb32a1b Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 10 Sep 2024 15:12:05 +0200 Subject: [PATCH 32/44] chore(core/embed): remove unused legacy i2c driver [no changelog] --- core/embed/bootloader/main.c | 7 - core/embed/firmware/main.c | 7 - core/embed/prodtest/main.c | 4 - core/embed/trezorhal/i2c.h | 38 ---- core/embed/trezorhal/stm32f4/i2c.c | 199 ------------------ core/embed/trezorhal/stm32u5/i2c.c | 179 ---------------- core/site_scons/models/D001/discovery.py | 1 - core/site_scons/models/D002/discovery2.py | 3 - core/site_scons/models/T2B1/trezor_r_v10.py | 5 - core/site_scons/models/T2T1/trezor_t.py | 1 - .../models/T3B1/trezor_t3b1_revB.py | 1 - .../models/T3T1/trezor_t3t1_revE.py | 1 - core/site_scons/models/T3T1/trezor_t3t1_v4.py | 1 - 13 files changed, 447 deletions(-) delete mode 100644 core/embed/trezorhal/i2c.h delete mode 100644 core/embed/trezorhal/stm32f4/i2c.c delete mode 100644 core/embed/trezorhal/stm32u5/i2c.c diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index b273ead7695..0d5d8984059 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -42,9 +42,6 @@ #include "dma2d.h" #endif #endif -#ifdef USE_I2C -#include "i2c.h" -#endif #ifdef USE_OPTIGA #include "optiga_hal.h" #endif @@ -373,10 +370,6 @@ int bootloader_main(void) { hash_processor_init(); #endif -#ifdef USE_I2C - i2c_init(); -#endif - display_init(DISPLAY_RETAIN_CONTENT); #ifdef USE_DMA2D diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 933835f3007..74af894c8b5 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -72,9 +72,6 @@ #ifdef USE_BUTTON #include "button.h" #endif -#ifdef USE_I2C -#include "i2c.h" -#endif #ifdef USE_TOUCH #include "touch.h" #endif @@ -207,10 +204,6 @@ int main(void) { consumption_mask_init(); #endif -#ifdef USE_I2C - i2c_init(); -#endif - #ifdef USE_TOUCH touch_init(); #endif diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 66114bfe7c3..e05502a5270 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -35,7 +35,6 @@ #include "flash.h" #include "flash_otp.h" #include "fwutils.h" -#include "i2c.h" #include "image.h" #include "model.h" #include "mpu.h" @@ -796,9 +795,6 @@ int main(void) { #ifdef USE_BUTTON button_init(); #endif -#ifdef USE_I2C - i2c_init(); -#endif #ifdef USE_TOUCH touch_init(); #endif diff --git a/core/embed/trezorhal/i2c.h b/core/embed/trezorhal/i2c.h deleted file mode 100644 index 54986043983..00000000000 --- a/core/embed/trezorhal/i2c.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 . - */ - -#ifndef TREZORHAL_I2C_H -#define TREZORHAL_I2C_H - -#include STM32_HAL_H - -void i2c_init(void); -void i2c_cycle(uint16_t idx); -HAL_StatusTypeDef i2c_transmit(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout); -HAL_StatusTypeDef i2c_receive(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout); -HAL_StatusTypeDef i2c_mem_write(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout); -HAL_StatusTypeDef i2c_mem_read(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout); - -#endif // TREZORHAL_I2C_H diff --git a/core/embed/trezorhal/stm32f4/i2c.c b/core/embed/trezorhal/stm32f4/i2c.c deleted file mode 100644 index a6b124ae024..00000000000 --- a/core/embed/trezorhal/stm32f4/i2c.c +++ /dev/null @@ -1,199 +0,0 @@ - - -#include STM32_HAL_H -#include TREZOR_BOARD -#include "i2c.h" -#include "common.h" - -static I2C_HandleTypeDef i2c_handle[I2C_COUNT]; - -typedef struct { - I2C_TypeDef *Instance; - GPIO_TypeDef *SclPort; - GPIO_TypeDef *SdaPort; - uint16_t SclPin; - uint16_t SdaPin; - uint8_t PinAF; - uint32_t Reset; -} i2c_instance_t; - -i2c_instance_t i2c_defs[I2C_COUNT] = { - { - .Instance = I2C_INSTANCE_0, - .SclPort = I2C_INSTANCE_0_SCL_PORT, - .SdaPort = I2C_INSTANCE_0_SDA_PORT, - .SclPin = I2C_INSTANCE_0_SCL_PIN, - .SdaPin = I2C_INSTANCE_0_SDA_PIN, - .PinAF = I2C_INSTANCE_0_PIN_AF, - .Reset = I2C_INSTANCE_0_RESET_BIT, - }, -#ifdef I2C_INSTANCE_1 - { - .Instance = I2C_INSTANCE_1, - .SclPort = I2C_INSTANCE_1_SCL_PORT, - .SdaPort = I2C_INSTANCE_1_SDA_PORT, - .SclPin = I2C_INSTANCE_1_SCL_PIN, - .SdaPin = I2C_INSTANCE_1_SDA_PIN, - .PinAF = I2C_INSTANCE_1_PIN_AF, - .Reset = I2C_INSTANCE_1_RESET_BIT, - }, -#endif - -}; - -void i2c_init_instance(uint16_t idx, i2c_instance_t *instance) { - if (i2c_handle[idx].Instance) { - return; - } - - GPIO_InitTypeDef GPIO_InitStructure = {0}; - - // configure CTP I2C SCL and SDA GPIO lines - GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = - GPIO_SPEED_FREQ_LOW; // I2C is a KHz bus and low speed is still good into - // the low MHz - - GPIO_InitStructure.Alternate = instance->PinAF; - GPIO_InitStructure.Pin = instance->SclPin; - HAL_GPIO_Init(instance->SclPort, &GPIO_InitStructure); - - GPIO_InitStructure.Alternate = instance->PinAF; - GPIO_InitStructure.Pin = instance->SdaPin; - HAL_GPIO_Init(instance->SdaPort, &GPIO_InitStructure); - - i2c_handle[idx].Instance = instance->Instance; - i2c_handle[idx].Init.ClockSpeed = 200000; - i2c_handle[idx].Init.DutyCycle = I2C_DUTYCYCLE_16_9; - i2c_handle[idx].Init.OwnAddress1 = 0xFE; // master - i2c_handle[idx].Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - i2c_handle[idx].Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; - i2c_handle[idx].Init.OwnAddress2 = 0; - i2c_handle[idx].Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; - i2c_handle[idx].Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; - - if (HAL_OK != HAL_I2C_Init(&i2c_handle[idx])) { - error_shutdown("I2C was not loaded properly."); - return; - } -} - -void i2c_init(void) { - // enable I2C clock - I2C_INSTANCE_0_CLK_EN(); - I2C_INSTANCE_0_SCL_CLK_EN(); - I2C_INSTANCE_0_SDA_CLK_EN(); - - i2c_init_instance(0, &i2c_defs[0]); - -#ifdef I2C_INSTANCE_1 - I2C_INSTANCE_1_CLK_EN(); - I2C_INSTANCE_1_SCL_CLK_EN(); - I2C_INSTANCE_1_SDA_CLK_EN(); - i2c_init_instance(1, &i2c_defs[1]); -#endif -} - -void i2c_deinit(uint16_t idx) { - if (i2c_handle[idx].Instance) { - HAL_I2C_DeInit(&i2c_handle[idx]); - i2c_handle[idx].Instance = NULL; - } -} - -void i2c_ensure_pin(GPIO_TypeDef *port, uint16_t GPIO_Pin, - GPIO_PinState PinState) { - HAL_GPIO_WritePin(port, GPIO_Pin, PinState); - while (HAL_GPIO_ReadPin(port, GPIO_Pin) != PinState) - ; -} - -// I2C cycle described in section 2.9.7 of STM CD00288116 Errata sheet -// -// https://www.st.com/content/ccc/resource/technical/document/errata_sheet/7f/05/b0/bc/34/2f/4c/21/CD00288116.pdf/files/CD00288116.pdf/jcr:content/translations/en.CD00288116.pdf - -void i2c_cycle(uint16_t idx) { - i2c_instance_t *instance = &i2c_defs[0]; - - // 1. Disable I2C peripheral - i2c_deinit(idx); - - // 2. Configure SCL/SDA as GPIO OUTPUT Open Drain - GPIO_InitTypeDef GPIO_InitStructure = {0}; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = instance->SdaPin; - HAL_GPIO_Init(instance->SdaPort, &GPIO_InitStructure); - GPIO_InitStructure.Pin = instance->SclPin; - HAL_GPIO_Init(instance->SclPort, &GPIO_InitStructure); - HAL_Delay(50); - - // 3. Check SCL and SDA High level - i2c_ensure_pin(instance->SclPort, instance->SclPin, GPIO_PIN_SET); - i2c_ensure_pin(instance->SdaPort, instance->SdaPin, GPIO_PIN_SET); - // 4+5. Check SDA Low level - i2c_ensure_pin(instance->SdaPort, instance->SdaPin, GPIO_PIN_RESET); - // 6+7. Check SCL Low level - i2c_ensure_pin(instance->SclPort, instance->SclPin, GPIO_PIN_RESET); - // 8+9. Check SCL High level - i2c_ensure_pin(instance->SclPort, instance->SclPin, GPIO_PIN_SET); - // 10+11. Check SDA High level - i2c_ensure_pin(instance->SclPort, instance->SdaPin, GPIO_PIN_SET); - - // 12. Configure SCL/SDA as Alternate function Open-Drain - GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Alternate = instance->PinAF; - GPIO_InitStructure.Pin = instance->SclPin; - HAL_GPIO_Init(instance->SclPort, &GPIO_InitStructure); - GPIO_InitStructure.Pin = instance->SdaPin; - HAL_GPIO_Init(instance->SdaPort, &GPIO_InitStructure); - HAL_Delay(50); - - // 13. Force reset - RCC->APB1RSTR |= instance->Reset; - - HAL_Delay(50); - - // 14. Release reset - RCC->APB1RSTR &= ~instance->Reset; - - // 15. Enable the I2C peripheral - i2c_init_instance(idx, instance); - HAL_Delay(10); -} - -HAL_StatusTypeDef i2c_transmit(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout) { - return HAL_I2C_Master_Transmit(&i2c_handle[idx], addr, data, len, timeout); -} - -HAL_StatusTypeDef i2c_receive(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout) { - HAL_StatusTypeDef ret = - HAL_I2C_Master_Receive(&i2c_handle[idx], addr, data, len, timeout); -#ifdef USE_OPTIGA - if (idx == OPTIGA_I2C_INSTANCE) { - // apply GUARD_TIME as specified by the OPTIGA datasheet - // (only applies to the I2C bus to which the OPTIGA is connected) - hal_delay_us(50); - } -#endif - return ret; -} - -HAL_StatusTypeDef i2c_mem_write(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout) { - return HAL_I2C_Mem_Write(&i2c_handle[idx], addr, mem_addr, mem_addr_size, - data, len, timeout); -} -HAL_StatusTypeDef i2c_mem_read(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout) { - return HAL_I2C_Mem_Read(&i2c_handle[idx], addr, mem_addr, mem_addr_size, data, - len, timeout); -} diff --git a/core/embed/trezorhal/stm32u5/i2c.c b/core/embed/trezorhal/stm32u5/i2c.c deleted file mode 100644 index 70b568b0107..00000000000 --- a/core/embed/trezorhal/stm32u5/i2c.c +++ /dev/null @@ -1,179 +0,0 @@ - - -#include STM32_HAL_H -#include TREZOR_BOARD -#include "i2c.h" -#include "common.h" - -static I2C_HandleTypeDef i2c_handle[I2C_COUNT]; - -typedef struct { - I2C_TypeDef *Instance; - GPIO_TypeDef *SclPort; - GPIO_TypeDef *SdaPort; - uint16_t SclPin; - uint16_t SdaPin; - uint8_t PinAF; - volatile uint32_t *ResetReg; - uint32_t ResetBit; -} i2c_instance_t; - -i2c_instance_t i2c_defs[I2C_COUNT] = { - { - .Instance = I2C_INSTANCE_0, - .SclPort = I2C_INSTANCE_0_SCL_PORT, - .SdaPort = I2C_INSTANCE_0_SDA_PORT, - .SclPin = I2C_INSTANCE_0_SCL_PIN, - .SdaPin = I2C_INSTANCE_0_SDA_PIN, - .PinAF = I2C_INSTANCE_0_PIN_AF, - .ResetReg = I2C_INSTANCE_0_RESET_REG, - .ResetBit = I2C_INSTANCE_0_RESET_BIT, - }, -#ifdef I2C_INSTANCE_1 - { - .Instance = I2C_INSTANCE_1, - .SclPort = I2C_INSTANCE_1_SCL_PORT, - .SdaPort = I2C_INSTANCE_1_SDA_PORT, - .SclPin = I2C_INSTANCE_1_SCL_PIN, - .SdaPin = I2C_INSTANCE_1_SDA_PIN, - .PinAF = I2C_INSTANCE_1_PIN_AF, - .ResetReg = I2C_INSTANCE_1_RESET_REG, - .ResetBit = I2C_INSTANCE_1_RESET_BIT, - }, -#endif -#ifdef I2C_INSTANCE_2 - { - .Instance = I2C_INSTANCE_2, - .SclPort = I2C_INSTANCE_2_SCL_PORT, - .SdaPort = I2C_INSTANCE_2_SDA_PORT, - .SclPin = I2C_INSTANCE_2_SCL_PIN, - .SdaPin = I2C_INSTANCE_2_SDA_PIN, - .PinAF = I2C_INSTANCE_2_PIN_AF, - .ResetReg = I2C_INSTANCE_2_RESET_REG, - .ResetBit = I2C_INSTANCE_2_RESET_BIT, - }, -#endif - -}; - -/* - * Using calculation from STM32CubeMX - * PCLKx as source, assumed 160MHz - * Fast mode, freq = 400kHz, Rise time = 250ns, Fall time = 100ns - * Fast mode, freq = 200kHz, Rise time = 250ns, Fall time = 100ns - * SCLH and SCLL are manually modified to achieve more symmetric clock - */ -#define I2C_TIMING_400000_Hz 0x30D22728 -#define I2C_TIMING_200000_Hz 0x30D2595A -#define I2C_TIMING I2C_TIMING_200000_Hz - -void i2c_init_instance(uint16_t idx, i2c_instance_t *instance) { - if (i2c_handle[idx].Instance) { - return; - } - - GPIO_InitTypeDef GPIO_InitStructure = {0}; - - // configure CTP I2C SCL and SDA GPIO lines - GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = - GPIO_SPEED_FREQ_LOW; // I2C is a KHz bus and low speed is still good into - // the low MHz - - GPIO_InitStructure.Alternate = instance->PinAF; - GPIO_InitStructure.Pin = instance->SclPin; - HAL_GPIO_Init(instance->SclPort, &GPIO_InitStructure); - - GPIO_InitStructure.Alternate = instance->PinAF; - GPIO_InitStructure.Pin = instance->SdaPin; - HAL_GPIO_Init(instance->SdaPort, &GPIO_InitStructure); - - i2c_handle[idx].Instance = instance->Instance; - i2c_handle[idx].Init.Timing = I2C_TIMING; - i2c_handle[idx].Init.OwnAddress1 = 0xFE; // master - i2c_handle[idx].Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - i2c_handle[idx].Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; - i2c_handle[idx].Init.OwnAddress2 = 0; - i2c_handle[idx].Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; - i2c_handle[idx].Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; - - if (HAL_OK != HAL_I2C_Init(&i2c_handle[idx])) { - error_shutdown("I2C was not loaded properly."); - return; - } -} - -void i2c_init(void) { - // enable I2C clock - I2C_INSTANCE_0_CLK_EN(); - I2C_INSTANCE_0_SCL_CLK_EN(); - I2C_INSTANCE_0_SDA_CLK_EN(); - i2c_init_instance(0, &i2c_defs[0]); - -#ifdef I2C_INSTANCE_1 - I2C_INSTANCE_1_CLK_EN(); - I2C_INSTANCE_1_SCL_CLK_EN(); - I2C_INSTANCE_1_SDA_CLK_EN(); - i2c_init_instance(1, &i2c_defs[1]); -#endif - -#ifdef I2C_INSTANCE_2 - I2C_INSTANCE_2_CLK_EN(); - I2C_INSTANCE_2_SCL_CLK_EN(); - I2C_INSTANCE_2_SDA_CLK_EN(); - i2c_init_instance(2, &i2c_defs[2]); -#endif -} - -void i2c_deinit(uint16_t idx) { - if (i2c_handle[idx].Instance) { - HAL_I2C_DeInit(&i2c_handle[idx]); - i2c_handle[idx].Instance = NULL; - } -} - -void i2c_ensure_pin(GPIO_TypeDef *port, uint16_t GPIO_Pin, - GPIO_PinState PinState) { - HAL_GPIO_WritePin(port, GPIO_Pin, PinState); - while (HAL_GPIO_ReadPin(port, GPIO_Pin) != PinState) - ; -} - -void i2c_cycle(uint16_t idx) { - SET_BIT(*i2c_defs[idx].ResetReg, i2c_defs[idx].ResetBit); - CLEAR_BIT(*i2c_defs[idx].ResetReg, i2c_defs[idx].ResetBit); -} - -HAL_StatusTypeDef i2c_transmit(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout) { - return HAL_I2C_Master_Transmit(&i2c_handle[idx], addr, data, len, timeout); -} - -HAL_StatusTypeDef i2c_receive(uint16_t idx, uint8_t addr, uint8_t *data, - uint16_t len, uint32_t timeout) { - HAL_StatusTypeDef ret = - HAL_I2C_Master_Receive(&i2c_handle[idx], addr, data, len, timeout); -#ifdef USE_OPTIGA - if (idx == OPTIGA_I2C_INSTANCE) { - // apply GUARD_TIME as specified by the OPTIGA datasheet - // (only applies to the I2C bus to which the OPTIGA is connected) - hal_delay_us(50); - } -#endif - - return ret; -} - -HAL_StatusTypeDef i2c_mem_write(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout) { - return HAL_I2C_Mem_Write(&i2c_handle[idx], addr, mem_addr, mem_addr_size, - data, len, timeout); -} -HAL_StatusTypeDef i2c_mem_read(uint16_t idx, uint8_t addr, uint16_t mem_addr, - uint16_t mem_addr_size, uint8_t *data, - uint16_t len, uint32_t timeout) { - return HAL_I2C_Mem_Read(&i2c_handle[idx], addr, mem_addr, mem_addr_size, data, - len, timeout); -} diff --git a/core/site_scons/models/D001/discovery.py b/core/site_scons/models/D001/discovery.py index 65b332e6ab0..84592a75815 100644 --- a/core/site_scons/models/D001/discovery.py +++ b/core/site_scons/models/D001/discovery.py @@ -72,7 +72,6 @@ def configure( features_available.append("display_rgb565") if "input" in features_wanted: - sources += ["embed/trezorhal/stm32f4/i2c.c"] sources += ["embed/trezorhal/stm32f4/i2c_bus.c"] sources += ["embed/trezorhal/stm32f4/touch/stmpe811.c"] features_available.append("touch") diff --git a/core/site_scons/models/D002/discovery2.py b/core/site_scons/models/D002/discovery2.py index 9041123cb16..f6a4272bf76 100644 --- a/core/site_scons/models/D002/discovery2.py +++ b/core/site_scons/models/D002/discovery2.py @@ -57,9 +57,6 @@ def configure( ] if "input" in features_wanted: - sources += [ - "embed/trezorhal/stm32u5/i2c.c", - ] sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] sources += ["embed/trezorhal/stm32u5/touch/sitronix.c"] features_available.append("touch") diff --git a/core/site_scons/models/T2B1/trezor_r_v10.py b/core/site_scons/models/T2B1/trezor_r_v10.py index 49c63e50c53..1d8951e0c20 100644 --- a/core/site_scons/models/T2B1/trezor_r_v10.py +++ b/core/site_scons/models/T2B1/trezor_r_v10.py @@ -48,11 +48,6 @@ def configure( else: sources += [f"embed/trezorhal/stm32f4/displays/{display}"] - sources += [ - "embed/trezorhal/stm32f4/i2c.c", - "embed/trezorhal/stm32f4/i2c_bus.c", - ] - if "input" in features_wanted: sources += ["embed/trezorhal/stm32f4/button.c"] features_available.append("button") diff --git a/core/site_scons/models/T2T1/trezor_t.py b/core/site_scons/models/T2T1/trezor_t.py index 18f4af2dcf2..d35ab5152b2 100644 --- a/core/site_scons/models/T2T1/trezor_t.py +++ b/core/site_scons/models/T2T1/trezor_t.py @@ -82,7 +82,6 @@ def configure( features_available.append("backlight") if "input" in features_wanted: - sources += ["embed/trezorhal/stm32f4/i2c.c"] sources += ["embed/trezorhal/stm32f4/i2c_bus.c"] sources += ["embed/trezorhal/stm32f4/touch/ft6x36.c"] features_available.append("touch") diff --git a/core/site_scons/models/T3B1/trezor_t3b1_revB.py b/core/site_scons/models/T3B1/trezor_t3b1_revB.py index ae923cdd5f6..e26b52c71a8 100644 --- a/core/site_scons/models/T3B1/trezor_t3b1_revB.py +++ b/core/site_scons/models/T3B1/trezor_t3b1_revB.py @@ -73,7 +73,6 @@ def configure( if "optiga" in features_wanted: defines += ["USE_OPTIGA=1"] - sources += ["embed/trezorhal/stm32u5/i2c.c"] sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] sources += ["embed/trezorhal/stm32u5/optiga_hal.c"] sources += ["embed/trezorhal/optiga/optiga.c"] diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py index 450ab408b8d..2e68dacc1f8 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py @@ -71,7 +71,6 @@ def configure( features_available.append("backlight") if "input" in features_wanted: - sources += ["embed/trezorhal/stm32u5/i2c.c"] sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] sources += ["embed/trezorhal/stm32u5/touch/ft6x36.c"] sources += ["embed/trezorhal/stm32u5/touch/panels/lx154a2422cpt23.c"] diff --git a/core/site_scons/models/T3T1/trezor_t3t1_v4.py b/core/site_scons/models/T3T1/trezor_t3t1_v4.py index 661a44e923b..a2f1c7ceee3 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_v4.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_v4.py @@ -75,7 +75,6 @@ def configure( features_available.append("backlight") if "input" in features_wanted: - sources += ["embed/trezorhal/stm32u5/i2c.c"] sources += ["embed/trezorhal/stm32u5/i2c_bus.c"] sources += ["embed/trezorhal/stm32u5/touch/ft6x36.c"] features_available.append("touch") From ba25763707d9e446efbf5c8f317943f9eca27684 Mon Sep 17 00:00:00 2001 From: cepetr Date: Fri, 30 Aug 2024 11:12:05 +0200 Subject: [PATCH 33/44] refactor(core/embed): simplify bootutils api [no changelog] --- core/embed/bootloader/emulator.c | 4 +- core/embed/bootloader/emulator.h | 2 +- core/embed/bootloader/main.c | 7 +- core/embed/bootloader/messages.c | 2 +- core/embed/bootloader/startup_stm32f4.s | 2 +- core/embed/bootloader/startup_stm32u5.s | 2 +- .../extmod/modtrezorutils/modtrezorutils.c | 28 ++-- core/embed/trezorhal/bootargs.h | 57 +++++++++ core/embed/trezorhal/bootutils.h | 75 ++++++----- core/embed/trezorhal/stm32f4/bootutils.c | 121 ++++++++++++------ core/embed/trezorhal/stm32u5/platform.h | 10 -- core/embed/trezorhal/stm32u5/secret.c | 4 +- core/embed/trezorhal/unix/bootutils.c | 44 ++++--- 13 files changed, 230 insertions(+), 128 deletions(-) create mode 100644 core/embed/trezorhal/bootargs.h diff --git a/core/embed/bootloader/emulator.c b/core/embed/bootloader/emulator.c index 24fbfd620ba..f1c8481ff37 100644 --- a/core/embed/bootloader/emulator.c +++ b/core/embed/bootloader/emulator.c @@ -2,8 +2,8 @@ #include #include TREZOR_BOARD +#include "bootargs.h" #include "bootui.h" -#include "bootutils.h" #include "common.h" #include "display.h" #include "flash.h" @@ -174,7 +174,7 @@ void mpu_config_bootloader(void) {} void mpu_config_off(void) {} -__attribute__((noreturn)) void jump_to(uint32_t address) { +void jump_to(uint32_t address) { bool storage_is_erased = storage_empty(&STORAGE_AREAS[0]) && storage_empty(&STORAGE_AREAS[1]); diff --git a/core/embed/bootloader/emulator.h b/core/embed/bootloader/emulator.h index f9ab5803765..9cf747075bd 100644 --- a/core/embed/bootloader/emulator.h +++ b/core/embed/bootloader/emulator.h @@ -15,6 +15,6 @@ void emulator_poll_events(void); void set_core_clock(int); void mpu_config_bootloader(void); void mpu_config_off(void); -void jump_to(void *addr); +__attribute__((noreturn)) void jump_to(uint32_t address); #endif diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 0d5d8984059..171eb690fd8 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -20,6 +20,7 @@ #include #include +#include "bootargs.h" #include "bootutils.h" #include "common.h" #include "display.h" @@ -342,11 +343,7 @@ void real_jump_to_firmware(void) { __attribute__((noreturn)) void jump_to_fw_through_reset(void) { display_fade(display_backlight(-1), 0, 200); - __disable_irq(); - delete_secrets(); - NVIC_SystemReset(); - for (;;) - ; + reboot(); } #endif diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index 2239880afdb..ddc94e5bfe3 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -24,7 +24,7 @@ #include #include "messages.pb.h" -#include "bootutils.h" +#include "bootargs.h" #include "common.h" #include "flash.h" #include "image.h" diff --git a/core/embed/bootloader/startup_stm32f4.s b/core/embed/bootloader/startup_stm32f4.s index a1fb0c7e551..96ad4d3ae6b 100644 --- a/core/embed/bootloader/startup_stm32f4.s +++ b/core/embed/bootloader/startup_stm32f4.s @@ -35,7 +35,7 @@ reset_handler: // r11 contains the command passed to bootargs_set() // function called when the firmware rebooted to the bootloader - ldr r0, =g_boot_command_shadow + ldr r0, =g_boot_command_saved str r11, [r0] // enter the application code diff --git a/core/embed/bootloader/startup_stm32u5.s b/core/embed/bootloader/startup_stm32u5.s index 6f5c36e73bc..ad97873e613 100644 --- a/core/embed/bootloader/startup_stm32u5.s +++ b/core/embed/bootloader/startup_stm32u5.s @@ -57,7 +57,7 @@ reset_handler: // copy & clear g_boot_command ldr r0, =g_boot_command ldr r1, [r0] - ldr r0, =g_boot_command_shadow + ldr r0, =g_boot_command_saved str r1, [r0] ldr r0, =g_boot_command mov r1, #0 diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index 69d48673ae8..5babd7301ca 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -284,31 +284,37 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_sd_hotswap_enabled_obj, STATIC mp_obj_t mod_trezorutils_reboot_to_bootloader(size_t n_args, const mp_obj_t *args) { #ifndef TREZOR_EMULATOR - boot_command_t boot_command = BOOT_COMMAND_NONE; - mp_buffer_info_t boot_args = {0}; - if (n_args > 0 && args[0] != mp_const_none) { mp_int_t value = mp_obj_get_int(args[0]); switch (value) { case 0: - boot_command = BOOT_COMMAND_STOP_AND_WAIT; + // Reboot and stay in bootloader + reboot_to_bootloader(); break; case 1: - boot_command = BOOT_COMMAND_INSTALL_UPGRADE; + // Reboot and continue with the firmware upgrade + mp_buffer_info_t hash = {0}; + + if (n_args > 1 && args[1] != mp_const_none) { + mp_get_buffer_raise(args[1], &hash, MP_BUFFER_READ); + } + + if (hash.len != 32) { + mp_raise_ValueError("Invalid value."); + } + + reboot_and_upgrade((uint8_t *)hash.buf); break; default: mp_raise_ValueError("Invalid value."); break; } + } else { + // Just reboot and go through the normal boot sequence + reboot(); } - if (n_args > 1 && args[1] != mp_const_none) { - mp_get_buffer_raise(args[1], &boot_args, MP_BUFFER_READ); - } - - bootargs_set(boot_command, boot_args.buf, boot_args.len); - reboot_to_bootloader(); #endif return mp_const_none; } diff --git a/core/embed/trezorhal/bootargs.h b/core/embed/trezorhal/bootargs.h new file mode 100644 index 00000000000..1cfc5b97e8c --- /dev/null +++ b/core/embed/trezorhal/bootargs.h @@ -0,0 +1,57 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_BOOTARGS_H +#define TREZORHAL_BOOTARGS_H + +#include +#include + +// Defines boot command processed in bootloader on next reboot +typedef enum { + // Normal boot sequence + BOOT_COMMAND_NONE = 0x00000000, + // Stop and wait for further instructions + BOOT_COMMAND_STOP_AND_WAIT = 0x0FC35A96, + // Do not ask anything, install an upgrade + BOOT_COMMAND_INSTALL_UPGRADE = 0xFA4A5C8D, +} boot_command_t; + +// Maximum size boot_args array +#define BOOT_ARGS_MAX_SIZE (256 - 8) + +typedef union { + uint8_t raw[BOOT_ARGS_MAX_SIZE]; + + // firmware header hash, BOOT_COMMAND_INSTALL_UPGRADE + uint8_t hash[32]; + +} boot_args_t; + +// 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); + +// Returns the last boot command saved during bootloader startup +boot_command_t bootargs_get_command(); + +// Returns the pointer to boot arguments +const boot_args_t* bootargs_get_args(); + +#endif // TREZORHAL_BOOTARGS_H diff --git a/core/embed/trezorhal/bootutils.h b/core/embed/trezorhal/bootutils.h index acf89207518..cd1e84dbaa9 100644 --- a/core/embed/trezorhal/bootutils.h +++ b/core/embed/trezorhal/bootutils.h @@ -1,50 +1,49 @@ +/* + * 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 . + */ + #ifndef TREZORHAL_BOOTUTILS_H #define TREZORHAL_BOOTUTILS_H #include #include -// Defines boot command for 'reboot_to_bootloader()' function -typedef enum { - // Normal boot sequence - BOOT_COMMAND_NONE = 0x00000000, - // Stop and wait for further instructions - BOOT_COMMAND_STOP_AND_WAIT = 0x0FC35A96, - // Do not ask anything, install an upgrade - BOOT_COMMAND_INSTALL_UPGRADE = 0xFA4A5C8D, -} boot_command_t; - -// Maximum size boot_args array -#define BOOT_ARGS_MAX_SIZE (256 - 8) - -typedef union { - uint8_t raw[BOOT_ARGS_MAX_SIZE]; - - // firmware header hash, BOOT_COMMAND_INSTALL_UPGRADE - uint8_t hash[32]; - -} boot_args_t; - -// Sets boot command and arguments for the next reboot -// arguments have too respect boot_args_t structure layout -// (function can be called multiple times before reboting) -void bootargs_set(boot_command_t command, const void* args, size_t args_size); - -// Returns the last boot command set by bootargs_set_command() -boot_command_t bootargs_get_command(); - -// Returns the pointer to boot arguments -const boot_args_t* bootargs_get_args(); +// Immediately resets the device and initiates the normal boot sequence. +void __attribute__((noreturn)) reboot(void); -// Reboots the device into the bootloader. -// The bootloader will read the command set by `bootargs_set()`. +// Resets the device and enters the bootloader, +// halting there and waiting for further user instructions. void __attribute__((noreturn)) reboot_to_bootloader(void); -// Causes immediate reset of the device. -void __attribute__((noreturn)) reboot(void); - -// Safely shuts down the device (clears secrets, memory, etc.). -// This function is called when the device is in an unrecoverable state. +// Resets the device into the bootloader and automatically continues +// with the installation of new firmware (also known as an +// interaction-less upgrade). +// +// If the provided hash is NULL or invalid, the device will stop +// at the bootloader and will require user acknowledgment to proceed +// 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.). +// +// This function is called when the device enters an +// unrecoverable error state. void __attribute__((noreturn)) secure_shutdown(void); #endif // TREZORHAL_BOOTUTILS_H diff --git a/core/embed/trezorhal/stm32f4/bootutils.c b/core/embed/trezorhal/stm32f4/bootutils.c index 4667fc5e8de..ee01d390659 100644 --- a/core/embed/trezorhal/stm32f4/bootutils.c +++ b/core/embed/trezorhal/stm32f4/bootutils.c @@ -1,33 +1,46 @@ +/* + * 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 "../bootutils.h" -#include #include +#include "bootargs.h" +#include "bootutils.h" +#include "common.h" #include "display.h" #include "irq.h" #include "mpu.h" -// The 'g_boot_command_shadow' shadows a real boot command passed -// to the bootloader. -// 1. In the bootloader, its value is set in the startup code. -// 2. In the firmware it holds command for the next boot and it is used -// when reboot_to_bootloader() is called -boot_command_t g_boot_command_shadow; - #ifdef STM32U5 -// The 'g_boot_command' is persistent variable that holds the 'command' -// for the next reboot/jump to the bootloader. Its value is set to -// g_boot_command_shadow when 'reboot_to_bootloader()' is called. +// Persistent variable that holds the 'command' for the next reboot. boot_command_t __attribute__((section(".boot_command"))) g_boot_command; +#else +// Holds the 'command' for the next jump to the bootloader. +static boot_command_t g_boot_command = BOOT_COMMAND_NONE; #endif -// The 'g_boot_args' is persistent array that stores extra arguments passed -// to the function bootargs_set. +// Persistent array that holds extra arguments for the command passed +// to the bootloader. static boot_args_t __attribute__((section(".boot_args"))) g_boot_args; void bootargs_set(boot_command_t command, const void* args, size_t args_size) { // save boot command - g_boot_command_shadow = command; + g_boot_command = command; size_t copy_size = 0; // copy arguments up to BOOT_ARGS_MAX_SIZE @@ -43,44 +56,76 @@ void bootargs_set(boot_command_t command, const void* args, size_t args_size) { } } -boot_command_t bootargs_get_command() { return g_boot_command_shadow; } +#ifdef BOOTLOADER +// Contains the current boot command saved during bootloader startup. +boot_command_t g_boot_command_saved; + +boot_command_t bootargs_get_command() { return g_boot_command_saved; } const boot_args_t* bootargs_get_args() { return &g_boot_args; } +#endif -void __attribute__((noreturn)) secure_shutdown(void) { - display_deinit(DISPLAY_RETAIN_CONTENT); +// Deletes all secrets and SRAM2 where stack is located +// to prevent stack smashing error, do not return from function calling this +#ifdef STM32U5 +static inline void __attribute__((always_inline)) delete_secrets(void) { + __disable_irq(); -#if defined(STM32U5) + // Disable SAES peripheral clock, so that we don't get tamper events __HAL_RCC_SAES_CLK_DISABLE(); - // Erase all secrets - TAMP->CR2 |= TAMP_CR2_BKERASE; -#endif - // from util.s - extern void shutdown_privileged(void); - shutdown_privileged(); - for (;;) - ; + TAMP->CR2 |= TAMP_CR2_BKERASE; } +#endif // STM32U5 + +// 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) { + bootargs_set(command, args, args_size); -void reboot_to_bootloader(void) { - boot_command_t boot_command = bootargs_get_command(); - display_deinit(DISPLAY_RESET_CONTENT); -#ifdef ENSURE_COMPATIBLE_SETTINGS - ensure_compatible_settings(); -#endif #ifdef STM32U5 - // extern uint32_t g_boot_command; - g_boot_command = boot_command; - __disable_irq(); delete_secrets(); NVIC_SystemReset(); #else + display_deinit(DISPLAY_RESET_CONTENT); +#ifdef ENSURE_COMPATIBLE_SETTINGS + ensure_compatible_settings(); +#endif mpu_config_bootloader(); - jump_to_with_flag(BOOTLOADER_START + IMAGE_HEADER_SIZE, boot_command); + jump_to_with_flag(BOOTLOADER_START + IMAGE_HEADER_SIZE, g_boot_command); for (;;) ; #endif } -void reboot(void) { NVIC_SystemReset(); } +void reboot_to_bootloader(void) { + reboot_with_args(BOOT_COMMAND_STOP_AND_WAIT, NULL, 0); +} + +void reboot_and_upgrade(const uint8_t hash[32]) { + reboot_with_args(BOOT_COMMAND_INSTALL_UPGRADE, hash, 32); +} + +void reboot(void) { + bootargs_set(BOOT_COMMAND_NONE, NULL, 0); + +#ifdef STM32U5 + delete_secrets(); +#endif + + NVIC_SystemReset(); +} + +void __attribute__((noreturn)) secure_shutdown(void) { + display_deinit(DISPLAY_RETAIN_CONTENT); + +#ifdef STM32U5 + delete_secrets(); +#endif + // from util.s + extern void shutdown_privileged(void); + shutdown_privileged(); + + for (;;) + ; +} diff --git a/core/embed/trezorhal/stm32u5/platform.h b/core/embed/trezorhal/stm32u5/platform.h index 55953cc5063..d5c9ffb6e51 100644 --- a/core/embed/trezorhal/stm32u5/platform.h +++ b/core/embed/trezorhal/stm32u5/platform.h @@ -42,16 +42,6 @@ void jump_to_with_flag(uint32_t address, uint32_t register_flag); extern uint32_t __stack_chk_guard; -// this deletes all secrets and SRAM2 where stack is located -// to prevent stack smashing error, do not return from function calling this -static inline void __attribute__((always_inline)) delete_secrets(void) { - // Disable SAES peripheral clock, so that we don't get tamper events - __HAL_RCC_SAES_CLK_DISABLE(); - - // Erase all - TAMP->CR2 |= TAMP_CR2_BKERASE; -} - void check_oem_keys(void); #endif // TREZORHAL_STM32_H diff --git a/core/embed/trezorhal/stm32u5/secret.c b/core/embed/trezorhal/stm32u5/secret.c index d148f0a54d7..104fdb5ddfc 100644 --- a/core/embed/trezorhal/stm32u5/secret.c +++ b/core/embed/trezorhal/stm32u5/secret.c @@ -1,6 +1,7 @@ #include "secret.h" #include #include +#include "bootutils.h" #include "common.h" #include "flash.h" #include "memzero.h" @@ -122,8 +123,7 @@ static secbool secret_present(uint32_t offset, uint32_t len) { // read access to it. static void secret_bhk_load(void) { if (sectrue == secret_bhk_locked()) { - delete_secrets(); - NVIC_SystemReset(); + reboot(); } uint32_t secret[SECRET_BHK_LEN / sizeof(uint32_t)] = {0}; diff --git a/core/embed/trezorhal/unix/bootutils.c b/core/embed/trezorhal/unix/bootutils.c index a80e560a55a..1fe3afed888 100644 --- a/core/embed/trezorhal/unix/bootutils.c +++ b/core/embed/trezorhal/unix/bootutils.c @@ -1,26 +1,39 @@ +/* + * 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 "../bootutils.h" -#include #include #include #include -// The 'g_boot_command_shadow' variable stores the 'command' for the next -// reboot/jumping to the bootloadeer. It may be one of the -// 'BOOT_COMMAND_xxx' values defined in the enumeration, or it could -// be any other value that should be treated as a non-special action, -// in which case the bootloader should behave as if the device was -// just powered up. +#include +#include "bootargs.h" +#include "bootutils.h" -static boot_command_t g_boot_command_shadow; +// Holds the 'command' for the next reboot. +static boot_command_t g_boot_command; -// The 'g_boot_args' array stores extra arguments passed -// function boot_args. It sits at section that persists jump to the bootloader. +// Holds extra arguments for the command passed to the bootloader. static boot_args_t g_boot_args; void bootargs_set(boot_command_t command, const void* args, size_t args_size) { // save boot command - g_boot_command_shadow = command; + g_boot_command = command; size_t copy_size = 0; // copy arguments up to BOOT_ARGS_MAX_SIZE @@ -36,12 +49,7 @@ void bootargs_set(boot_command_t command, const void* args, size_t args_size) { } } -void bootargs_clear() { - g_boot_command_shadow = BOOT_COMMAND_NONE; - memset(&g_boot_args, 0, sizeof(g_boot_args)); -} - -boot_command_t bootargs_get_command() { return g_boot_command_shadow; } +boot_command_t bootargs_get_command() { return g_boot_command; } const boot_args_t* bootargs_get_args() { return &g_boot_args; } From e6bacff8e528798b5d9adbd83dc3b7b96864b88b Mon Sep 17 00:00:00 2001 From: cepetr Date: Fri, 30 Aug 2024 14:38:04 +0200 Subject: [PATCH 34/44] refactor(core/embed): moving specific algorithms into fwutils [no changelog] --- core/SConscript.unix | 1 + .../extmod/modtrezorutils/modtrezorutils.c | 57 +++----------- core/embed/prodtest/main.c | 2 +- core/embed/trezorhal/fwutils.h | 36 ++++++++- core/embed/trezorhal/stm32f4/fwutils.c | 75 ++++++++++++++++++- core/embed/trezorhal/unix/fwutils.c | 1 + 6 files changed, 121 insertions(+), 51 deletions(-) create mode 120000 core/embed/trezorhal/unix/fwutils.c diff --git a/core/SConscript.unix b/core/SConscript.unix index bcf5d635cb8..767af01a8f8 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -422,6 +422,7 @@ SOURCE_UNIX = [ 'embed/trezorhal/unix/common.c', 'embed/trezorhal/unix/flash_otp.c', 'embed/trezorhal/unix/flash.c', + 'embed/trezorhal/unix/fwutils.c', 'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/rng.c', 'embed/trezorhal/unix/systick.c', diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index 5babd7301ca..c77ed28373d 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -31,25 +31,20 @@ #include #include "blake2s.h" #include "bootutils.h" -#include "common.h" -#include "flash.h" +#include "error_handling.h" +#include "fwutils.h" #include "unit_variant.h" #include "usb.h" #include TREZOR_BOARD #include "model.h" -#ifndef TREZOR_EMULATOR -#include "image.h" -#endif - #if USE_OPTIGA && !defined(TREZOR_EMULATOR) #include "secret.h" #endif -#define FW_HASHING_CHUNK_SIZE 1024 +static void ui_progress(void *context, uint32_t current, uint32_t total) { + mp_obj_t ui_wait_callback = (mp_obj_t)context; -static void ui_progress(mp_obj_t ui_wait_callback, uint32_t current, - uint32_t total) { if (mp_obj_is_callable(ui_wait_callback)) { mp_call_function_2_protected(ui_wait_callback, mp_obj_new_int(current), mp_obj_new_int(total)); @@ -153,51 +148,23 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_halt_obj, 0, 1, /// """ STATIC mp_obj_t mod_trezorutils_firmware_hash(size_t n_args, const mp_obj_t *args) { - BLAKE2S_CTX ctx; mp_buffer_info_t chal = {0}; if (n_args > 0 && args[0] != mp_const_none) { mp_get_buffer_raise(args[0], &chal, MP_BUFFER_READ); } - if (chal.len != 0) { - if (blake2s_InitKey(&ctx, BLAKE2S_DIGEST_LENGTH, chal.buf, chal.len) != 0) { - mp_raise_msg(&mp_type_ValueError, "Invalid challenge."); - } - } else { - blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); - } - mp_obj_t ui_wait_callback = mp_const_none; if (n_args > 1 && args[1] != mp_const_none) { ui_wait_callback = args[1]; } - uint32_t firmware_size = flash_area_get_size(&FIRMWARE_AREA); - uint32_t chunks = firmware_size / FW_HASHING_CHUNK_SIZE; - - ensure((firmware_size % FW_HASHING_CHUNK_SIZE == 0) * sectrue, - "Cannot compute FW hash."); - - ui_progress(ui_wait_callback, 0, chunks); - for (int i = 0; i < chunks; i++) { - const void *data = flash_area_get_address( - &FIRMWARE_AREA, i * FW_HASHING_CHUNK_SIZE, FW_HASHING_CHUNK_SIZE); - if (data == NULL) { - mp_raise_msg(&mp_type_RuntimeError, "Failed to read firmware."); - } - blake2s_Update(&ctx, data, FW_HASHING_CHUNK_SIZE); - if (i % 128 == 0) { - ui_progress(ui_wait_callback, i + 1, chunks); - } - } - - ui_progress(ui_wait_callback, chunks, chunks); - vstr_t vstr = {0}; vstr_init_len(&vstr, BLAKE2S_DIGEST_LENGTH); - if (blake2s_Final(&ctx, vstr.buf, vstr.len) != 0) { + + if (sectrue != firmware_calc_hash(chal.buf, chal.len, (uint8_t *)vstr.buf, + vstr.len, ui_progress, ui_wait_callback)) { vstr_clear(&vstr); - mp_raise_msg(&mp_type_RuntimeError, "Failed to finalize firmware hash."); + mp_raise_msg(&mp_type_RuntimeError, "Failed to calculate firmware hash."); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); @@ -213,13 +180,11 @@ STATIC mp_obj_t mod_trezorutils_firmware_vendor(void) { #ifdef TREZOR_EMULATOR return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)"EMULATOR", 8); #else - vendor_header vhdr = {0}; - const void *data = flash_area_get_address(&FIRMWARE_AREA, 0, 0); - if (data == NULL || sectrue != read_vendor_header(data, &vhdr)) { + char vendor[64] = {0}; + if (sectrue != firmware_get_vendor(vendor, sizeof(vendor))) { mp_raise_msg(&mp_type_RuntimeError, "Failed to read vendor header."); } - return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)vhdr.vstr, - vhdr.vstr_len); + return mp_obj_new_str_copy(&mp_type_str, (byte *)vendor, strlen(vendor)); #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_firmware_vendor_obj, diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index e05502a5270..9a1d96f3e35 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -621,7 +621,7 @@ static void test_boardloader_version(const boardloader_version_t *version) { } static void test_wipe(void) { - invalidate_firmware(); + firmware_invalidate_header(); display_clear(); display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY / 2 + 10, "WIPED", -1, FONT_BOLD, COLOR_WHITE, COLOR_BLACK); diff --git a/core/embed/trezorhal/fwutils.h b/core/embed/trezorhal/fwutils.h index 26e484c8ff2..b4c13626f93 100644 --- a/core/embed/trezorhal/fwutils.h +++ b/core/embed/trezorhal/fwutils.h @@ -20,9 +20,43 @@ #ifndef TREZORHAL_FWUTILS_H #define TREZORHAL_FWUTILS_H +#include + +#include "secbool.h" + +// Callback function for firmware hash calculation. +typedef void (*firmware_hash_callback_t)(void* context, uint32_t progress, + uint32_t total); + +// Calculates hash of the firmware area. +// +// `challenge` is a optional pointer to the challenge data. +// `challenge_len` is the length of the challenge data (1..32). +// `hash` is a pointer to a buffer where the hash will be stored. +// `hash_len` is size of the buffer (must be at least 32). +// `callback` is an optional callback function that will be called during the +// hash calculation. +// `callback_context` is a pointer that will be passed to the callback function. +// +// Returns `sectrue` if the hash was calculated successfully, `secfalse` +// otherwise. +secbool firmware_calc_hash(const uint8_t* challenge, size_t challenge_len, + uint8_t* hash, size_t hash_len, + firmware_hash_callback_t callback, + void* callback_context); + +// Reads the firmware vendor string from the header in the firmware area. +// +// `buff` is a pointer to a buffer where the vendor string will be stored. +// `buff_size` is the length of the buffer (reserve at least 64 bytes). +// +// Returns `sectrue` if the vendor string was read successfully, `secfalse` +// otherwise. +secbool firmware_get_vendor(char* buff, size_t buff_size); + // Invalidates the firmware by erasing the first 1KB of the firmware area. // // Note: only works when write access to firmware area is enabled by MPU -void invalidate_firmware(void); +void firmware_invalidate_header(void); #endif // TREZORHAL_FWUTILS_H diff --git a/core/embed/trezorhal/stm32f4/fwutils.c b/core/embed/trezorhal/stm32f4/fwutils.c index 1d5990e1176..e583203d7f7 100644 --- a/core/embed/trezorhal/stm32f4/fwutils.c +++ b/core/embed/trezorhal/stm32f4/fwutils.c @@ -17,15 +17,84 @@ * along with this program. If not, see . */ -#include STM32_HAL_H +#include -#include "fwutils.h" +#include "blake2s.h" #include "error_handling.h" #include "flash.h" #include "flash_area.h" +#include "fwutils.h" +#include "image.h" #include "model.h" -void invalidate_firmware(void) { +#define FW_HASHING_CHUNK_SIZE 1024 + +secbool firmware_calc_hash(const uint8_t* challenge, size_t challenge_len, + uint8_t* hash, size_t hash_len, + firmware_hash_callback_t callback, + void* callback_context) { + BLAKE2S_CTX ctx; + + if (challenge_len != 0) { + if (blake2s_InitKey(&ctx, BLAKE2S_DIGEST_LENGTH, challenge, + challenge_len) != 0) { + return secfalse; + } + } else { + blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); + } + + uint32_t firmware_size = flash_area_get_size(&FIRMWARE_AREA); + uint32_t chunks = firmware_size / FW_HASHING_CHUNK_SIZE; + + ensure((firmware_size % FW_HASHING_CHUNK_SIZE == 0) * sectrue, + "Cannot compute FW hash."); + + for (int i = 0; i < chunks; i++) { + if (callback != NULL && (i % 128 == 0)) { + callback(callback_context, i, chunks); + } + + const void* data = flash_area_get_address( + &FIRMWARE_AREA, i * FW_HASHING_CHUNK_SIZE, FW_HASHING_CHUNK_SIZE); + + if (data == NULL) { + return secfalse; + } + + blake2s_Update(&ctx, data, FW_HASHING_CHUNK_SIZE); + } + + if (callback != NULL) { + callback(callback_context, chunks, chunks); + } + + if (blake2s_Final(&ctx, hash, hash_len) != 0) { + return secfalse; + } + + return sectrue; +} + +secbool firmware_get_vendor(char* buff, size_t buff_size) { + const void* data = flash_area_get_address(&FIRMWARE_AREA, 0, 0); + + vendor_header vhdr = {0}; + + if (data == NULL || sectrue != read_vendor_header(data, &vhdr)) { + return secfalse; + } + + if (buff == NULL || buff_size < vhdr.vstr_len + 1) { + return secfalse; + } + + strncpy(buff, vhdr.vstr, buff_size); + + return sectrue; +} + +void firmware_invalidate_header(void) { #ifdef STM32U5 // on stm32u5, we need to disable the instruction cache before erasing the // firmware - otherwise, the write check will fail diff --git a/core/embed/trezorhal/unix/fwutils.c b/core/embed/trezorhal/unix/fwutils.c new file mode 120000 index 00000000000..8968a5a0247 --- /dev/null +++ b/core/embed/trezorhal/unix/fwutils.c @@ -0,0 +1 @@ +../stm32f4/fwutils.c \ No newline at end of file From 3f8166da8f75d361f848cf80a0073f86425d8d15 Mon Sep 17 00:00:00 2001 From: cepetr Date: Sat, 7 Sep 2024 13:50:10 +0200 Subject: [PATCH 35/44] refactor(core/embed): introduce new mpu driver [no changelog] --- core/SConscript.boardloader | 1 + core/SConscript.bootloader | 1 + core/SConscript.bootloader_ci | 1 + core/SConscript.bootloader_emu | 2 + core/SConscript.firmware | 1 + core/SConscript.unix | 1 + core/embed/boardloader/main.c | 11 +- core/embed/bootloader/emulator.c | 4 - core/embed/bootloader/emulator.h | 2 - core/embed/bootloader/main.c | 13 +- core/embed/bootloader/messages.c | 6 +- core/embed/bootloader_ci/main.c | 5 +- core/embed/bootloader_ci/messages.c | 10 +- core/embed/firmware/main.c | 5 +- core/embed/lib/flash_utils.c | 105 ++++ core/embed/lib/flash_utils.h | 46 ++ core/embed/lib/translations.c | 8 + core/embed/lib/unit_variant.c | 1 + core/embed/models/D002/model_D002_layout.c | 18 +- core/embed/models/T2B1/model_T2B1_layout.c | 15 +- core/embed/models/T2T1/model_T2T1_layout.c | 35 +- core/embed/models/T3B1/model_T3B1_layout.c | 18 +- core/embed/models/T3T1/model_T3T1_layout.c | 18 +- core/embed/models/layout_common.h | 3 +- core/embed/prodtest/main.c | 14 +- core/embed/trezorhal/mpu.h | 54 +- .../trezorhal/stm32f4/board_capabilities.c | 10 +- core/embed/trezorhal/stm32f4/bootutils.c | 4 +- core/embed/trezorhal/stm32f4/entropy.c | 5 + core/embed/trezorhal/stm32f4/flash_otp.c | 30 +- core/embed/trezorhal/stm32f4/lowlevel.c | 11 + core/embed/trezorhal/stm32f4/monoctr.c | 1 + core/embed/trezorhal/stm32f4/mpu.c | 564 ++++++++++-------- core/embed/trezorhal/stm32f4/secret.c | 26 +- .../stm32f4/xdisplay/st-7789/display_io.c | 3 + core/embed/trezorhal/stm32u5/entropy.c | 5 + core/embed/trezorhal/stm32u5/flash_otp.c | 39 +- core/embed/trezorhal/stm32u5/monoctr.c | 6 + core/embed/trezorhal/stm32u5/mpu.c | 266 ++++++--- core/embed/trezorhal/stm32u5/secret.c | 32 +- core/embed/trezorhal/unix/mpu.c | 30 + 41 files changed, 928 insertions(+), 502 deletions(-) create mode 100644 core/embed/lib/flash_utils.c create mode 100644 core/embed/lib/flash_utils.h create mode 100644 core/embed/trezorhal/unix/mpu.c diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader index cc31e0b6b8d..70cf6ae167d 100644 --- a/core/SConscript.boardloader +++ b/core/SConscript.boardloader @@ -69,6 +69,7 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/display_utils.c', 'embed/lib/error_handling.c', + 'embed/lib/flash_utils.c', 'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/fonts.c', 'embed/lib/gfx_color.c', diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 8a1a0ce0e90..52897b3d424 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -108,6 +108,7 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/display_utils.c', 'embed/lib/error_handling.c', + 'embed/lib/flash_utils.c', 'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/fonts.c', 'embed/lib/gfx_color.c', diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci index 93f9277bd9e..9bdb258ba4b 100644 --- a/core/SConscript.bootloader_ci +++ b/core/SConscript.bootloader_ci @@ -101,6 +101,7 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/display_utils.c', 'embed/lib/error_handling.c', + 'embed/lib/flash_utils.c', 'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/fonts.c', 'embed/lib/gfx_color.c', diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index a3baaf07002..a3462cc8851 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -103,6 +103,7 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/display_utils.c', 'embed/lib/error_handling.c', + 'embed/lib/flash_utils.c', 'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/fonts.c', 'embed/lib/gfx_color.c', @@ -150,6 +151,7 @@ SOURCE_TREZORHAL = [ 'embed/trezorhal/unix/fault_handlers.c', 'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/flash_otp.c', + 'embed/trezorhal/unix/mpu.c', 'embed/trezorhal/unix/monoctr.c', 'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/rng.c', diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 1be1a4b5c1c..41e6677273c 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -228,6 +228,7 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/display_utils.c', 'embed/lib/error_handling.c', + 'embed/lib/flash_utils.c', 'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/fonts.c', 'embed/lib/gfx_color.c', diff --git a/core/SConscript.unix b/core/SConscript.unix index 767af01a8f8..728ebc5d264 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -423,6 +423,7 @@ SOURCE_UNIX = [ 'embed/trezorhal/unix/flash_otp.c', 'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/fwutils.c', + 'embed/trezorhal/unix/mpu.c', 'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/rng.c', 'embed/trezorhal/unix/systick.c', diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index 7aa83445c2a..d63cca32237 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -28,6 +28,7 @@ #include "display_draw.h" #include "fault_handlers.h" #include "flash.h" +#include "flash_utils.h" #include "image.h" #include "model.h" #include "mpu.h" @@ -208,7 +209,7 @@ static secbool copy_sdcard(void) { term_printf("\n\nerasing flash:\n\n"); // erase all flash (except boardloader) - if (sectrue != flash_area_erase(&ALL_WIPE_AREA, progress_callback)) { + if (sectrue != erase_device(progress_callback)) { term_printf(" failed\n"); return secfalse; } @@ -244,9 +245,7 @@ int main(void) { if (sectrue != flash_configure_option_bytes()) { // display is not initialized so don't call ensure - const secbool r = - flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL); - (void)r; + erase_storage(NULL); return 2; } @@ -262,8 +261,6 @@ int main(void) { clear_otg_hs_memory(); #endif - mpu_config_boardloader(); - fault_handlers_init(); #ifdef USE_SDRAM @@ -335,7 +332,7 @@ int main(void) { ensure_compatible_settings(); #endif - mpu_config_off(); + mpu_reconfig(MPU_MODE_DISABLED); // g_boot_command is preserved on STM32U5 jump_to(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE)); diff --git a/core/embed/bootloader/emulator.c b/core/embed/bootloader/emulator.c index f1c8481ff37..99d2dd8611b 100644 --- a/core/embed/bootloader/emulator.c +++ b/core/embed/bootloader/emulator.c @@ -170,10 +170,6 @@ __attribute__((noreturn)) int main(int argc, char **argv) { jump_to(0); } -void mpu_config_bootloader(void) {} - -void mpu_config_off(void) {} - void jump_to(uint32_t address) { bool storage_is_erased = storage_empty(&STORAGE_AREAS[0]) && storage_empty(&STORAGE_AREAS[1]); diff --git a/core/embed/bootloader/emulator.h b/core/embed/bootloader/emulator.h index 9cf747075bd..7cd1adb01a7 100644 --- a/core/embed/bootloader/emulator.h +++ b/core/embed/bootloader/emulator.h @@ -13,8 +13,6 @@ extern uint8_t *FIRMWARE_START; void emulator_poll_events(void); void set_core_clock(int); -void mpu_config_bootloader(void); -void mpu_config_off(void); __attribute__((noreturn)) void jump_to(uint32_t address); #endif diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 171eb690fd8..f2bea94e7ba 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -28,6 +28,7 @@ #include "fault_handlers.h" #include "flash.h" #include "flash_otp.h" +#include "flash_utils.h" #include "image.h" #include "lowlevel.h" #include "messages.pb.h" @@ -335,7 +336,8 @@ void real_jump_to_firmware(void) { ensure_compatible_settings(); #endif - mpu_config_off(); + mpu_reconfig(MPU_MODE_DISABLED); + jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); } @@ -394,8 +396,6 @@ int bootloader_main(void) { ui_screen_boot_stage_1(false); - mpu_config_bootloader(); - fault_handlers_init(); #ifdef TREZOR_EMULATOR @@ -559,9 +559,7 @@ int bootloader_main(void) { #ifdef STM32U5 secret_bhk_regenerate(); #endif - // erase storage - ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), - NULL); + ensure(erase_storage(NULL), NULL); // keep the model screen up for a while #ifndef USE_BACKLIGHT @@ -669,8 +667,7 @@ int bootloader_main(void) { #ifdef STM32U5 secret_bhk_regenerate(); #endif - ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), - NULL); + ensure(erase_storage(NULL), NULL); } ensure(dont_optimize_out_true * (continue_to_firmware == continue_to_firmware_backup), diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index ddc94e5bfe3..e5c16ce75b0 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -27,6 +27,7 @@ #include "bootargs.h" #include "common.h" #include "flash.h" +#include "flash_utils.h" #include "image.h" #include "secbool.h" #include "secret.h" @@ -715,8 +716,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, #ifdef STM32U5 secret_bhk_regenerate(); #endif - ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), - NULL); + ensure(erase_storage(NULL), NULL); } headers_offset = IMAGE_CODE_ALIGN(IMAGE_HEADER_SIZE + vhdr.hdrlen); @@ -840,7 +840,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, } secbool bootloader_WipeDevice(void) { - return flash_area_erase(&WIPE_AREA, ui_screen_wipe_progress); + return erase_device(ui_screen_wipe_progress); } int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { diff --git a/core/embed/bootloader_ci/main.c b/core/embed/bootloader_ci/main.c index 43a83f35c94..93e52fe5e09 100644 --- a/core/embed/bootloader_ci/main.c +++ b/core/embed/bootloader_ci/main.c @@ -188,8 +188,6 @@ int main(void) { hash_processor_init(); #endif - mpu_config_bootloader(); - #if PRODUCTION && !defined STM32U5 // for STM32U5, this check is moved to boardloader ensure_bootloader_min_version(); @@ -270,7 +268,8 @@ int main(void) { // do not check any trust flags on header, proceed - mpu_config_off(); + mpu_reconfig(MPU_MODE_DISABLED); + jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); return 0; diff --git a/core/embed/bootloader_ci/messages.c b/core/embed/bootloader_ci/messages.c index ee177017a13..8303a998528 100644 --- a/core/embed/bootloader_ci/messages.c +++ b/core/embed/bootloader_ci/messages.c @@ -26,6 +26,7 @@ #include "common.h" #include "flash.h" +#include "flash_utils.h" #include "image.h" #include "model.h" #include "secbool.h" @@ -648,14 +649,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, } int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { - flash_area_t wipe_area[STORAGE_AREAS_COUNT + 1]; - for (int i = 0; i < STORAGE_AREAS_COUNT; i++) { - memcpy(&wipe_area[i], &STORAGE_AREAS[i], sizeof(flash_area_t)); - } - memcpy(&wipe_area[STORAGE_AREAS_COUNT], &FIRMWARE_AREA, sizeof(flash_area_t)); - - if (sectrue != flash_area_erase_bulk(wipe_area, STORAGE_AREAS_COUNT + 1, - ui_screen_wipe_progress)) { + if (sectrue != erase_device(ui_screen_wipe_progress)) { MSG_SEND_INIT(Failure); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_STRING(message, "Could not erase flash"); diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 74af894c8b5..07ffb1f6e7a 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -173,15 +173,12 @@ int main(void) { secbool secret_ok = secret_optiga_get(secret); #endif - mpu_config_firmware_initial(); - entropy_init(); #if PRODUCTION || BOOTLOADER_QA check_and_replace_bootloader(); #endif - // Enable MPU - mpu_config_firmware(); + #endif // Init peripherals diff --git a/core/embed/lib/flash_utils.c b/core/embed/lib/flash_utils.c new file mode 100644 index 00000000000..5c4c6183b7a --- /dev/null +++ b/core/embed/lib/flash_utils.c @@ -0,0 +1,105 @@ +/* + * 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 TREZOR_BOARD + +#include "flash_utils.h" +#include "common.h" +#include "flash_area.h" +#include "model.h" +#include "mpu.h" +#include "secbool.h" + +typedef struct { + const flash_area_t* area; + mpu_mode_t mpu_mode; +} flash_area_ref_t; + +// Erases the given list of flash areas. +// +// Invokes the progress_cb after each erased sector or page. +static secbool erase_areas(const flash_area_ref_t* areas, int area_count, + flash_progress_callback_t progress_cb) { + int total = 0; + int progress = 0; + + for (int i = 0; i < area_count; i++) { + total += flash_area_get_size(areas[i].area); + } + + mpu_mode_t mpu_mode = mpu_get_mode(); + + for (int i = 0; i < area_count; i++) { + const flash_area_t* area = areas[i].area; + uint32_t offset = 0; + uint32_t bytes_erased = 0; + + mpu_reconfig(areas[i].mpu_mode); + + do { + if (progress_cb) { + progress_cb(progress, total); + } + + if (sectrue != flash_area_erase_partial(area, offset, &bytes_erased)) { + mpu_restore(mpu_mode); + return secfalse; + } + + offset += bytes_erased; + progress += bytes_erased; + + } while (bytes_erased > 0); + } + + mpu_restore(mpu_mode); + return sectrue; +} + +secbool erase_storage(flash_progress_callback_t progress_cb) { + _Static_assert(STORAGE_AREAS_COUNT == 2, + "Unsupported number of storage areas"); + + static const flash_area_ref_t areas[] = { + {.area = &STORAGE_AREAS[0], .mpu_mode = MPU_MODE_STORAGE}, + {.area = &STORAGE_AREAS[1], .mpu_mode = MPU_MODE_STORAGE}, + }; + + return erase_areas(areas, ARRAY_LENGTH(areas), progress_cb); +} + +secbool erase_device(flash_progress_callback_t progress_cb) { + _Static_assert(STORAGE_AREAS_COUNT == 2, + "Unsupported number of storage areas"); + + static const flash_area_ref_t areas[] = { + {.area = &STORAGE_AREAS[0], .mpu_mode = MPU_MODE_STORAGE}, + {.area = &STORAGE_AREAS[1], .mpu_mode = MPU_MODE_STORAGE}, + {.area = &TRANSLATIONS_AREA, .mpu_mode = MPU_MODE_ASSETS}, +#if defined(BOARDLOADER) || defined(BOOTLOADER) + {.area = &FIRMWARE_AREA, .mpu_mode = MPU_MODE_DEFAULT}, +#endif +#if defined(BOARDLOADER) && defined(USE_SD_CARD) + {.area = &BOOTLOADER_AREA, .mpu_mode = MPU_MODE_DEFAULT}, + {.area = &UNUSED_AREA, .mpu_mode = MPU_MODE_UNUSED_FLASH}, +#endif + }; + + return erase_areas(areas, ARRAY_LENGTH(areas), progress_cb); +} diff --git a/core/embed/lib/flash_utils.h b/core/embed/lib/flash_utils.h new file mode 100644 index 00000000000..04f14d87922 --- /dev/null +++ b/core/embed/lib/flash_utils.h @@ -0,0 +1,46 @@ +/* + * 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 . + */ + +#ifndef LIB_FLASH_UTILS_H +#define LIB_FLASH_UTILS_H + +#include "secbool.h" + +#ifdef KERNEL_MODE + +// Progress callback function called during the flash erase operation. +// +// Progress is reported as: (100 * pos) / total [%]. +typedef void (*flash_progress_callback_t)(int pos, int total); + +// Erases both storage areas +// +// Callback is invoked after each sector or page is erased. +secbool erase_storage(flash_progress_callback_t progress_cb); + +// Erases all flash areas including storage, assets and firmware. +// +// If called from boardloader, also erases bootloader area. +// +// Callback is invoked after each sector or page is erased. +secbool erase_device(flash_progress_callback_t progress_cb); + +#endif // KERNEL_MODE + +#endif // LIB_FLASH_UTILS_H diff --git a/core/embed/lib/translations.c b/core/embed/lib/translations.c index d00fa0d483e..191bcd989b7 100644 --- a/core/embed/lib/translations.c +++ b/core/embed/lib/translations.c @@ -5,6 +5,7 @@ #include "common.h" #include "flash.h" #include "model.h" +#include "mpu.h" bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) { uint32_t size = translations_area_bytesize(); @@ -12,12 +13,17 @@ bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) { return false; } + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_ASSETS); + ensure(flash_unlock_write(), "translations_write unlock"); // todo consider alignment ensure(flash_area_write_data_padded(&TRANSLATIONS_AREA, offset, data, len, 0xFF, FLASH_ALIGN(len)), "translations_write write"); ensure(flash_lock_write(), "translations_write lock"); + + mpu_restore(mpu_mode); + return true; } @@ -30,7 +36,9 @@ const uint8_t* translations_read(uint32_t* len, uint32_t offset) { } void translations_erase(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_ASSETS); ensure(flash_area_erase(&TRANSLATIONS_AREA, NULL), "translations erase"); + mpu_restore(mpu_mode); } uint32_t translations_area_bytesize(void) { diff --git a/core/embed/lib/unit_variant.c b/core/embed/lib/unit_variant.c index e062284de52..8170d19e028 100644 --- a/core/embed/lib/unit_variant.c +++ b/core/embed/lib/unit_variant.c @@ -2,6 +2,7 @@ #include "flash_otp.h" #include "model.h" +#include "mpu.h" #include "unit_variant.h" #include TREZOR_BOARD diff --git a/core/embed/models/D002/model_D002_layout.c b/core/embed/models/D002/model_D002_layout.c index d1f3b48b107..4bb5eb8f9e5 100644 --- a/core/embed/models/D002/model_D002_layout.c +++ b/core/embed/models/D002/model_D002_layout.c @@ -77,20 +77,6 @@ const flash_area_t TRANSLATIONS_AREA = { }, }; -const flash_area_t WIPE_AREA = { - .num_subareas = 1, - .subarea[0] = - { - .first_sector = STORAGE_1_SECTOR_START, - .num_sectors = 488, - }, -}; - -const flash_area_t ALL_WIPE_AREA = { - .num_subareas = 1, - .subarea[0] = - { - .first_sector = BOOTLOADER_SECTOR_START, - .num_sectors = 504, - }, +const flash_area_t UNUSED_AREA = { + .num_subareas = 0, }; diff --git a/core/embed/models/T2B1/model_T2B1_layout.c b/core/embed/models/T2B1/model_T2B1_layout.c index 430f4d49437..b4f510cc14e 100644 --- a/core/embed/models/T2B1/model_T2B1_layout.c +++ b/core/embed/models/T2B1/model_T2B1_layout.c @@ -74,21 +74,16 @@ const flash_area_t FIRMWARE_AREA = { }, }; -const flash_area_t WIPE_AREA = { - .num_subareas = 3, +const flash_area_t UNUSED_AREA = { + .num_subareas = 2, .subarea[0] = { - .first_sector = 4, + .first_sector = 3, .num_sectors = 1, }, .subarea[1] = { - .first_sector = 6, - .num_sectors = 6, - }, - .subarea[2] = - { - .first_sector = 16, - .num_sectors = 8, + .first_sector = 15, + .num_sectors = 1, }, }; diff --git a/core/embed/models/T2T1/model_T2T1_layout.c b/core/embed/models/T2T1/model_T2T1_layout.c index 091eebcf54a..aca5c3812f1 100644 --- a/core/embed/models/T2T1/model_T2T1_layout.c +++ b/core/embed/models/T2T1/model_T2T1_layout.c @@ -65,40 +65,25 @@ const flash_area_t FIRMWARE_AREA = { }, }; -const flash_area_t WIPE_AREA = { - .num_subareas = 3, +const flash_area_t SECRET_AREA = { + .num_subareas = 1, .subarea[0] = { - .first_sector = 4, - .num_sectors = 1, - }, - .subarea[1] = - { - .first_sector = 6, - .num_sectors = - 9, // sector 15 skipped due to bootloader MPU settings - }, - .subarea[2] = - { - .first_sector = 16, - .num_sectors = 8, + .first_sector = 0, + .num_sectors = 0, }, }; -const flash_area_t ALL_WIPE_AREA = { - .num_subareas = 1, +const flash_area_t UNUSED_AREA = { + .num_subareas = 2, .subarea[0] = { .first_sector = 3, - .num_sectors = 21, + .num_sectors = 1, }, -}; - -const flash_area_t SECRET_AREA = { - .num_subareas = 1, - .subarea[0] = + .subarea[1] = { - .first_sector = 0, - .num_sectors = 0, + .first_sector = 15, + .num_sectors = 1, }, }; diff --git a/core/embed/models/T3B1/model_T3B1_layout.c b/core/embed/models/T3B1/model_T3B1_layout.c index 3baae222edb..f776dfccaef 100644 --- a/core/embed/models/T3B1/model_T3B1_layout.c +++ b/core/embed/models/T3B1/model_T3B1_layout.c @@ -77,20 +77,6 @@ const flash_area_t TRANSLATIONS_AREA = { }, }; -const flash_area_t WIPE_AREA = { - .num_subareas = 1, - .subarea[0] = - { - .first_sector = STORAGE_1_SECTOR_START, - .num_sectors = 232, - }, -}; - -const flash_area_t ALL_WIPE_AREA = { - .num_subareas = 1, - .subarea[0] = - { - .first_sector = BOOTLOADER_SECTOR_START, - .num_sectors = 248, - }, +const flash_area_t UNUSED_AREA = { + .num_subareas = 0, }; diff --git a/core/embed/models/T3T1/model_T3T1_layout.c b/core/embed/models/T3T1/model_T3T1_layout.c index 3baae222edb..f776dfccaef 100644 --- a/core/embed/models/T3T1/model_T3T1_layout.c +++ b/core/embed/models/T3T1/model_T3T1_layout.c @@ -77,20 +77,6 @@ const flash_area_t TRANSLATIONS_AREA = { }, }; -const flash_area_t WIPE_AREA = { - .num_subareas = 1, - .subarea[0] = - { - .first_sector = STORAGE_1_SECTOR_START, - .num_sectors = 232, - }, -}; - -const flash_area_t ALL_WIPE_AREA = { - .num_subareas = 1, - .subarea[0] = - { - .first_sector = BOOTLOADER_SECTOR_START, - .num_sectors = 248, - }, +const flash_area_t UNUSED_AREA = { + .num_subareas = 0, }; diff --git a/core/embed/models/layout_common.h b/core/embed/models/layout_common.h index 318bf5abd46..7a9d72dc561 100644 --- a/core/embed/models/layout_common.h +++ b/core/embed/models/layout_common.h @@ -20,7 +20,6 @@ extern const flash_area_t BHK_AREA; extern const flash_area_t TRANSLATIONS_AREA; extern const flash_area_t BOOTLOADER_AREA; extern const flash_area_t FIRMWARE_AREA; -extern const flash_area_t WIPE_AREA; -extern const flash_area_t ALL_WIPE_AREA; +extern const flash_area_t UNUSED_AREA; #endif diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 9a1d96f3e35..fc56a4c3270 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -595,14 +595,19 @@ static void test_firmware_version(void) { } static uint32_t read_bootloader_version(void) { + uint32_t version = 0; + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_BOOTUPDATE); + const image_header *header = read_image_header( (const uint8_t *)BOOTLOADER_START, BOOTLOADER_IMAGE_MAGIC, 0xffffffff); - if (secfalse == header) { - return 0; + if (header != NULL) { + version = header->version; } - return header->version; + mpu_restore(mpu_mode); + return version; } static void test_bootloader_version(uint32_t version) { @@ -809,15 +814,12 @@ int main(void) { uint32_t bootloader_version = read_bootloader_version(); const boardloader_version_t *boardloader_version = read_boardloader_version(); - mpu_config_prodtest_initial(); - #ifdef USE_OPTIGA optiga_init(); optiga_open_application(); pair_optiga(); #endif - mpu_config_prodtest(); fault_handlers_init(); display_clear(); diff --git a/core/embed/trezorhal/mpu.h b/core/embed/trezorhal/mpu.h index a4aa0372829..989d622c301 100644 --- a/core/embed/trezorhal/mpu.h +++ b/core/embed/trezorhal/mpu.h @@ -17,15 +17,49 @@ * along with this program. If not, see . */ -#ifndef __MPU_H__ -#define __MPU_H__ +#ifndef TREZORHAL_MPU_H +#define TREZORHAL_MPU_H -void mpu_config_off(void); -void mpu_config_boardloader(void); -void mpu_config_bootloader(void); -void mpu_config_firmware_initial(void); -void mpu_config_firmware(void); -void mpu_config_prodtest_initial(void); -void mpu_config_prodtest(void); +// The MPU driver can be set to on of the following modes. +// +// In each mode, the MPU is configured to allow access to specific +// memory regions. +// +// The `MPU_MODE_DEFAULT` mode is the most restrictive and serves as +// a base for other modes. +typedef enum { + MPU_MODE_DISABLED, // MPU is disabled + MPU_MODE_DEFAULT, // Default + MPU_MODE_BOARDCAPS, // + boardloader capabilities (privileged RO) + MPU_MODE_BOOTUPDATE, // + bootloader area (privileged RW) + MPU_MODE_OTP, // + OTP (privileged RW) + MPU_MODE_FSMC_REGS, // + FSMC control registers (privileged RW) + MPU_MODE_FLASHOB, // + Option bytes mapping (privileged RW) + MPU_MODE_SECRET, // + secret area (priviledeg RW) + MPU_MODE_STORAGE, // + both storage areas (privilehed RW) + MPU_MODE_ASSETS, // + assets (privileged RW) + MPU_MODE_UNUSED_FLASH, // + unused flash areas (privileged RW) + MPU_MODE_APP, // + unprivileged DMA2D (RW) & Assets (RO) +} mpu_mode_t; -#endif +// Initializes the MPU and sets it to MPU_MODE_DISABLED. +// +// This function should be called before any other MPU function. +void mpu_init(void); + +// Returns the current MPU mode. +// +// If the MPU is not initialized, returns MPU_MODE_DISABLED. +mpu_mode_t mpu_get_mode(void); + +// Reconfigures the MPU to the given mode and returns the previous mode. +// +// If the MPU is not initialized, does nothing and returns MPU_MODE_DISABLED. +mpu_mode_t mpu_reconfig(mpu_mode_t mode); + +// Restores the MPU to the given mode. +// +// Same as `mpu_reconfig()`, but with a more descriptive name. +void mpu_restore(mpu_mode_t mode); + +#endif // TREZORHAL_MPU_H diff --git a/core/embed/trezorhal/stm32f4/board_capabilities.c b/core/embed/trezorhal/stm32f4/board_capabilities.c index c867c87cdc5..461fbaa15ca 100644 --- a/core/embed/trezorhal/stm32f4/board_capabilities.c +++ b/core/embed/trezorhal/stm32f4/board_capabilities.c @@ -17,10 +17,12 @@ * along with this program. If not, see . */ -#include "board_capabilities.h" #include + +#include "board_capabilities.h" #include "common.h" #include "model.h" +#include "mpu.h" static uint32_t board_name = 0; @@ -33,11 +35,14 @@ const boardloader_version_t *get_boardloader_version() { } void parse_boardloader_capabilities() { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_BOARDCAPS); + const uint8_t *pos = (const uint8_t *)BOARD_CAPABILITIES_ADDR; const uint8_t *end = (const uint8_t *)(BOARD_CAPABILITIES_ADDR + BOARD_CAPABILITIES_SIZE); if (memcmp(pos, CAPABILITIES_HEADER, 4) != 0) { + mpu_restore(mpu_mode); return; } @@ -70,6 +75,7 @@ void parse_boardloader_capabilities() { memcpy(&boardloader_version, pos, length); break; case TAG_TERMINATOR: + mpu_restore(mpu_mode); return; default: break; @@ -77,4 +83,6 @@ void parse_boardloader_capabilities() { pos += length; } + + mpu_restore(mpu_mode); } diff --git a/core/embed/trezorhal/stm32f4/bootutils.c b/core/embed/trezorhal/stm32f4/bootutils.c index ee01d390659..2fdd3f9afd2 100644 --- a/core/embed/trezorhal/stm32f4/bootutils.c +++ b/core/embed/trezorhal/stm32f4/bootutils.c @@ -91,7 +91,9 @@ reboot_with_args(boot_command_t command, const void* args, size_t args_size) { #ifdef ENSURE_COMPATIBLE_SETTINGS ensure_compatible_settings(); #endif - mpu_config_bootloader(); + + mpu_reconfig(MPU_MODE_DISABLED); + jump_to_with_flag(BOOTLOADER_START + IMAGE_HEADER_SIZE, g_boot_command); for (;;) ; diff --git a/core/embed/trezorhal/stm32f4/entropy.c b/core/embed/trezorhal/stm32f4/entropy.c index 0c655c2eca2..4aec016ab8f 100644 --- a/core/embed/trezorhal/stm32f4/entropy.c +++ b/core/embed/trezorhal/stm32f4/entropy.c @@ -22,6 +22,7 @@ #include "entropy.h" #include "flash_otp.h" #include "model.h" +#include "mpu.h" #include "rand.h" #include "stm32f4xx_ll_utils.h" @@ -29,6 +30,8 @@ static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; void entropy_init(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + // collect entropy from UUID uint32_t w = LL_GetUID_Word0(); memcpy(g_hw_entropy, &w, 4); @@ -37,6 +40,8 @@ void entropy_init(void) { w = LL_GetUID_Word2(); memcpy(g_hw_entropy + 8, &w, 4); + mpu_restore(mpu_mode); + // set entropy in the OTP randomness block if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; diff --git a/core/embed/trezorhal/stm32f4/flash_otp.c b/core/embed/trezorhal/stm32f4/flash_otp.c index 28fbb34ffbf..53672c36f24 100644 --- a/core/embed/trezorhal/stm32f4/flash_otp.c +++ b/core/embed/trezorhal/stm32f4/flash_otp.c @@ -22,6 +22,7 @@ #include "flash_otp.h" #include "common.h" #include "flash.h" +#include "mpu.h" #define FLASH_OTP_LOCK_BASE 0x1FFF7A00U @@ -35,10 +36,16 @@ secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, offset + datalen > FLASH_OTP_BLOCK_SIZE) { return secfalse; } + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + for (uint8_t i = 0; i < datalen; i++) { data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i); } + + mpu_restore(mpu_mode); + return sectrue; } @@ -48,6 +55,9 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, offset + datalen > FLASH_OTP_BLOCK_SIZE) { return secfalse; } + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + ensure(flash_unlock_write(), NULL); for (uint8_t i = 0; i < datalen; i++) { uint32_t address = @@ -57,6 +67,9 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, NULL); } ensure(flash_lock_write(), NULL); + + mpu_restore(mpu_mode); + return sectrue; } @@ -64,13 +77,28 @@ secbool flash_otp_lock(uint8_t block) { if (block >= FLASH_OTP_NUM_BLOCKS) { return secfalse; } + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + ensure(flash_unlock_write(), NULL); HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, FLASH_OTP_LOCK_BASE + block, 0x00); ensure(flash_lock_write(), NULL); + + mpu_restore(mpu_mode); + return sectrue * (ret == HAL_OK); } secbool flash_otp_is_locked(uint8_t block) { - return sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block)); + secbool is_locked; + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + + is_locked = + sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block)); + + mpu_restore(mpu_mode); + + return is_locked; } diff --git a/core/embed/trezorhal/stm32f4/lowlevel.c b/core/embed/trezorhal/stm32f4/lowlevel.c index 5107522ed11..188142f21a7 100644 --- a/core/embed/trezorhal/stm32f4/lowlevel.c +++ b/core/embed/trezorhal/stm32f4/lowlevel.c @@ -20,6 +20,9 @@ #include STM32_HAL_H #include "lowlevel.h" + +#include + #include "flash_otp.h" #pragma GCC optimize( \ @@ -80,19 +83,27 @@ secbool flash_check_option_bytes(void) { if (FLASH->OPTCR1 != FLASH_OPTCR1_nWRP) { return secfalse; } + + mpu_mode_t mode = mpu_reconfig(MPU_MODE_FLASHOB); // check values stored in flash memory if ((OPTION_BYTES_RDP_USER & ~3) != OPTION_BYTES_RDP_USER_VALUE) { // bits 0 and 1 are unused + mpu_reconfig(mode); return secfalse; } if ((OPTION_BYTES_BANK1_WRP & 0xCFFFU) != OPTION_BYTES_BANK1_WRP_VALUE) { // bits 12 and 13 are unused + mpu_reconfig(mode); return secfalse; } if ((OPTION_BYTES_BANK2_WRP & 0xFFFU) != OPTION_BYTES_BANK2_WRP_VALUE) { // bits 12, 13, 14, and 15 are unused + mpu_reconfig(mode); return secfalse; } + + mpu_reconfig(mode); + return sectrue; } diff --git a/core/embed/trezorhal/stm32f4/monoctr.c b/core/embed/trezorhal/stm32f4/monoctr.c index 4907fc0f953..c05bc046471 100644 --- a/core/embed/trezorhal/stm32f4/monoctr.c +++ b/core/embed/trezorhal/stm32f4/monoctr.c @@ -20,6 +20,7 @@ #include "monoctr.h" #include "flash_otp.h" #include "model.h" +#include "mpu.h" #include "string.h" #if !PRODUCTION diff --git a/core/embed/trezorhal/stm32f4/mpu.c b/core/embed/trezorhal/stm32f4/mpu.c index af40d3814db..23a1f208d95 100644 --- a/core/embed/trezorhal/stm32f4/mpu.c +++ b/core/embed/trezorhal/stm32f4/mpu.c @@ -19,292 +19,338 @@ #include STM32_HAL_H #include TREZOR_BOARD -#include "stm32f4xx_ll_cortex.h" - -// http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABDJJGF.html -#define MPU_RASR_ATTR_FLASH (MPU_RASR_C_Msk) -#define MPU_RASR_ATTR_SRAM (MPU_RASR_C_Msk | MPU_RASR_S_Msk) -#define MPU_RASR_ATTR_PERIPH (MPU_RASR_B_Msk | MPU_RASR_S_Msk) -#define MPU_SUBREGION_DISABLE(X) ((X) << MPU_RASR_SRD_Pos) +#include +#include -void mpu_config_off(void) { - // Disable MPU - HAL_MPU_Disable(); -} +#include "irq.h" +#include "model.h" +#include "mpu.h" -void mpu_config_boardloader(void) { - // nothing to be done -} - -void mpu_config_bootloader(void) { - // Disable MPU - HAL_MPU_Disable(); +#include "stm32f4xx_ll_cortex.h" - // Note: later entries overwrite previous ones - - // Everything (0x00000000 - 0xFFFFFFFF, 4 GiB, read-write) - MPU->RNR = MPU_REGION_NUMBER0; - MPU->RBAR = 0; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS; - - // Flash (0x0800C000 - 0x0800FFFF, 16 KiB, no access) - MPU->RNR = MPU_REGION_NUMBER1; - MPU->RBAR = FLASH_BASE + 0xC000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; - - // Flash (0x0810C000 - 0x0810FFFF, 16 KiB, no access) - MPU->RNR = MPU_REGION_NUMBER2; - MPU->RBAR = FLASH_BASE + 0x10C000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; - - // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, - // read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER3; - MPU->RBAR = SRAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | - LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); - -#ifdef USE_SDRAM - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // SDRAM (0xC0000000 - 0xDFFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER4; - MPU->RBAR = 0; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | - LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xBB); -#else - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER4; - MPU->RBAR = PERIPH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | - LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; +// http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABDJJGF.html +#define MPU_RASR_ATTR_FLASH_CODE (MPU_RASR_C_Msk) +#define MPU_RASR_ATTR_FLASH_DATA (MPU_RASR_C_Msk | MPU_RASR_XN_Msk) +#define MPU_RASR_ATTR_SRAM (MPU_RASR_C_Msk | MPU_RASR_S_Msk | MPU_RASR_XN_Msk) +#define MPU_RASR_ATTR_PERIPH (MPU_RASR_B_Msk | MPU_RASR_S_Msk | MPU_RASR_XN_Msk) + +#define SET_REGION(region, start, size, mask, attr, access) \ + do { \ + uint32_t _enable = MPU_RASR_ENABLE_Msk; \ + uint32_t _size = LL_MPU_REGION_##size; \ + uint32_t _mask = (mask) << MPU_RASR_SRD_Pos; \ + uint32_t _attr = MPU_RASR_ATTR_##attr; \ + uint32_t _access = LL_MPU_REGION_##access; \ + MPU->RNR = region; \ + MPU->RBAR = (start) & ~0x1F; \ + MPU->RASR = _enable | _size | _mask | _attr | _access; \ + } while (0) + +#define DIS_REGION(region) \ + do { \ + MPU->RNR = region; \ + MPU->RBAR = 0; \ + MPU->RASR = 0; \ + } while (0) + +typedef struct { + // Set if the driver is initialized + bool initialized; + // Current mode + mpu_mode_t mode; + +} mpu_driver_t; + +mpu_driver_t g_mpu_driver = { + .initialized = false, + .mode = MPU_MODE_DISABLED, +}; + +static void mpu_init_fixed_regions(void) { + // Regions #0 to #4 are fixed for all targets + +#ifdef BOARDLOADER + // clang-format off + // Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable) + // Subregion: 48KB = 64KB except 2/8 at end + SET_REGION( 0, BOARDLOADER_START, SIZE_64KB, 0xC0, FLASH_CODE, PRIV_RO_URO ); + // Rest of the code in the Flash Bank #1 (Unprivileged, Read-Only) + // Subregion: 896KB = 1024KB except 1/8 at start + SET_REGION( 1, FLASH_BASE, SIZE_1MB, 0x01, FLASH_DATA, FULL_ACCESS ); + // Rest of the code in the Flash Bank #2 (Unprivileged, Read-Only) + // Subregion: 896KB = 1024KB except 1/8 at start + SET_REGION( 2, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_DATA, FULL_ACCESS ); + // All CCMRAM (Unprivileged, Read-Write, Non-Executable) + SET_REGION( 3, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS ); + // All SRAM (Unprivileged, Read-Write, Non-Executable) + // Subregion: 192KB = 256KB except 2/8 at end + SET_REGION( 4, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS ); + // clang-format on #endif - -#if defined STM32F427xx || defined STM32F429xx - // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER5; - MPU->RBAR = CCMDATARAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | - LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; -#elif STM32F405xx - // no CCMRAM -#else -#error Unsupported MCU +#ifdef BOOTLOADER + // clang-format off + // Bootloader code in the Flash Bank #1 (Unprivileged, Read-Only, Executable) + // Subregion: 128KB = 1024KB except 2/8 at start + SET_REGION( 0, BOOTLOADER_START, SIZE_128KB, 0x00, FLASH_CODE, PRIV_RO_URO ); + // Kernel/coreapp code in the Flash Bank #1 (Unprivileged, Read-Only) + // Subregion: 768KB = 1024KB except 2/8 at start + SET_REGION( 1, FLASH_BASE, SIZE_1MB, 0x03, FLASH_DATA, FULL_ACCESS ); + // Kernel/coreapp code in the Flash Bank #2 (Unprivileged, Read-Only) + // Subregion: 896KB = 1024KB except 1/8 at start + SET_REGION( 2, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_DATA, FULL_ACCESS ); + // All CCMRAM (Unprivileged, Read-Write, Non-Executable) + SET_REGION( 3, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS ); + // All SRAM (Unprivileged, Read-Write, Non-Executable) + // Subregion: 192KB = 256KB except 2/8 at end + SET_REGION( 4, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS ); + // clang-format on +#endif +#ifdef KERNEL + // clang-format off + // Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable) + // Subregion: 768KB = 1024KB except 2/8 at start + SET_REGION( 0, FLASH_BASE, SIZE_1MB, 0x03, FLASH_CODE, PRIV_RO_URO ); + // Code in the Flash Bank #2 (Unprivileged, Read-Only, Executable) + // Subregion: 896KB = 1024KB except 1/8 at start + SET_REGION( 1, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_CODE, PRIV_RO_URO ); + // All CCMRAM (Unprivileged, Read-Write, Non-Executable) + SET_REGION( 2, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS ); + // All SRAM (Unprivileged, Read-Write, Non-Executable) + // Subregion: 192KB = 256KB except 2/8 at end + SET_REGION( 3, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS ); + // Kernel RAM (Privileged, Read-Write, Non-Executable) + // TODO: !@# + // SET_REGION( 4, ..., SIZE_xxx, 0xXX, ATTR_SRAM, PRIV_RW ); + DIS_REGION( 4 ); + // clang-format on +#endif +#ifdef FIRMWARE + // clang-format off + // Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable) + // Subregion: 768KB = 1024KB except 2/8 at start + SET_REGION( 0, FLASH_BASE, SIZE_1MB, 0x03, FLASH_CODE, PRIV_RO_URO ); + // Code in the Flash Bank #2 (Unprivileged, Read-Only, Executable) + // Subregion: 896KB = 1024KB except 1/8 at start + SET_REGION( 1, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_CODE, PRIV_RO_URO ); + // All CCMRAM (Unprivileged, Read-Write, Non-Executable) + SET_REGION( 2, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS ); + // All SRAM (Unprivileged, Read-Write, Non-Executable) + // Subregion: 192KB = 256KB except 2/8 at end + SET_REGION( 3, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS ); + DIS_REGION( 4 ); + // clang-format on +#endif +#ifdef TREZOR_PRODTEST + // clang-format off + // Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable) + // Subregion: 768KB = 1024KB except 2/8 at start + SET_REGION( 0, FLASH_BASE, SIZE_1MB, 0x03, FLASH_CODE, PRIV_RO_URO ); + // Code in the Flash Bank #2 (Unprivileged, Read-Only, Executable) + // Subregion: 896KB = 1024KB except 1/8 at start + SET_REGION( 1, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_CODE, PRIV_RO_URO ); + // All CCMRAM (Unprivileged, Read-Write, Non-Executable) + SET_REGION( 2, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS ); + // All SRAM (Unprivileged, Read-Write, Non-Executable) + // Subregion: 192KB = 256KB except 2/8 at end + SET_REGION( 3, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS ); + // Firmware header (Unprivileged, Read-Write, Non-Executable) + // (used in production test to invalidate the firmware) + SET_REGION( 4, FIRMWARE_START, SIZE_1KB, 0x00, FLASH_DATA, PRIV_RW_URO ); + // clang-format on #endif - // Enable MPU - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + // Regions #5 to #7 are banked + DIS_REGION(5); + DIS_REGION(6); + DIS_REGION(7); } -void mpu_config_firmware_initial(void) {} - -void mpu_config_firmware(void) { - // Disable MPU - HAL_MPU_Disable(); +void mpu_init(void) { + mpu_driver_t* drv = &g_mpu_driver; - // Note: later entries overwrite previous ones + if (drv->initialized) { + return; + } - /* - // Boardloader (0x08000000 - 0x0800FFFF, 64 KiB, read-only, execute never) - MPU->RBAR = FLASH_BASE | MPU_REGION_NUMBER0; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO | MPU_RASR_XN_Msk; - */ + irq_key_t irq_key = irq_lock(); - // Bootloader (0x08020000 - 0x0803FFFF, 128 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER0; - MPU->RBAR = FLASH_BASE + 0x20000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_128KB | LL_MPU_REGION_PRIV_RO_URO; + HAL_MPU_Disable(); - // Storage#1 (0x08010000 - 0x0801FFFF, 64 KiB, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER1; - MPU->RBAR = FLASH_BASE + 0x10000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; + mpu_init_fixed_regions(); -#ifdef USE_OPTIGA - // Translations + Storage#2 - secret (0x08104000 - 0x0811FFFF, 112 KiB, - // read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER2; - MPU->RBAR = FLASH_BASE + 0x100000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_128KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0x01); -#else - // Translations + Storage#2 (0x08100000 - 0x0811FFFF, 128 KiB, read-write, - // execute never) - MPU->RNR = MPU_REGION_NUMBER2; - MPU->RBAR = FLASH_BASE + 0x100000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_128KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; -#endif + drv->mode = MPU_MODE_DISABLED; + drv->initialized = true; - // Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at - // start = 768 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER3; - MPU->RBAR = FLASH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | - MPU_SUBREGION_DISABLE(0x03); - - // Firmware extra (0x08120000 - 0x081FFFFF, 7 * 128 KiB = 1024 KiB except 1/8 - // at start = 896 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER4; - MPU->RBAR = FLASH_BASE + 0x100000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | - MPU_SUBREGION_DISABLE(0x01); - - // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, - // read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER5; - MPU->RBAR = SRAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | - LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); - -#ifdef USE_SDRAM - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // SDRAM (0xC0000000 - 0xDFFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER6; - MPU->RBAR = 0; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | - LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xBB); -#else - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER6; - MPU->RBAR = PERIPH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | - LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; -#endif + irq_unlock(irq_key); +} -#if defined STM32F427xx || defined STM32F429xx - // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER7; - MPU->RBAR = CCMDATARAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | - LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; -#elif STM32F405xx - // no CCMRAM -#else -#error Unsupported MCU -#endif +mpu_mode_t mpu_get_mode(void) { + mpu_driver_t* drv = &g_mpu_driver; - // Enable MPU - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + if (!drv->initialized) { + return MPU_MODE_DISABLED; + } - __asm__ volatile("dsb"); - __asm__ volatile("isb"); + return drv->mode; } -void mpu_config_prodtest_initial(void) {} +// STM32F4xx memory map +// +// 0x08000000 2MB FLASH +// 0x10000000 64KB CCMRAM +// 0x1FFF7800 528B OTP +// 0x20000000 192KB SRAM +// 0x40000000 512MB PERIPH + +// STM32F4xx flash layout +// +// 0x08000000 4x 16KB (BANK #1) +// 0x08010000 1x 64KB (BANK #1) +// 0x08020000 7x 128KB (BANK #1) +// 0x08100000 4x 16KB (BANK #2) +// 0x08110000 1x 64KB (BANK #3) +// 0x08120000 7x 128KB (BANK #4) + +mpu_mode_t mpu_reconfig(mpu_mode_t mode) { + mpu_driver_t* drv = &g_mpu_driver; + + if (!drv->initialized) { + // Solves the issue when some IRQ handler tries to reconfigure + // MPU before it is initialized + return MPU_MODE_DISABLED; + } + + irq_key_t irq_key = irq_lock(); -void mpu_config_prodtest(void) { - // Disable MPU HAL_MPU_Disable(); - // Note: later entries overwrite previous ones - - // // Boardloader (0x08000000 - 0x0800BFFF, 48 KiB, read-only, execute never) - // MPU->RNR = MPU_REGION_NUMBER0; - // MPU->RBAR = FLASH_BASE; - // MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - // LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO | - // MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); - - // Secret area (0x08100000 - 0x08103FFF, 16 KiB, read-write, execute never) - // MPU->RNR = MPU_REGION_NUMBER0; - // MPU->RBAR = FLASH_BASE + 0x100000; - // MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - // LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_FULL_ACCESS | - // MPU_RASR_XN_Msk; - - // Bootloader (0x08020000 - 0x0803FFFF, 64 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER1; - MPU->RBAR = FLASH_BASE + 0x20000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO; - - // Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at - // start = 768 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER2; - MPU->RBAR = FLASH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_FULL_ACCESS | - MPU_SUBREGION_DISABLE(0x03); - - // Firmware extra (0x08120000 - 0x081FFFFF, 7 * 128 KiB = 1024 KiB except 1/8 - // at start = 896 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER3; - MPU->RBAR = FLASH_BASE + 0x100000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_FULL_ACCESS | - MPU_SUBREGION_DISABLE(0x01); - - // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, - // read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER4; - MPU->RBAR = SRAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | - LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); - -#ifdef USE_SDRAM - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // SDRAM (0xC0000000 - 0xDFFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER5; - MPU->RBAR = 0; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | - LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xBB); -#else - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER5; - MPU->RBAR = PERIPH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | - LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; + // Region #5 and #6 are banked + + // clang-format off + switch (mode) { +#if !defined(BOARDLOADER) + case MPU_MODE_BOARDCAPS: + DIS_REGION( 5 ); + // Boardloader (Privileged, Read-Only, Non-Executable) + // Subregion: 48KB = 64KB except 2/8 at end + SET_REGION( 6, FLASH_BASE, SIZE_64KB, 0xC0, FLASH_DATA, PRIV_RO ); + break; #endif -#if defined STM32F427xx || defined STM32F429xx - // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER6; - MPU->RBAR = CCMDATARAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | - LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; -#elif STM32F405xx - // no CCMRAM -#else -#error Unsupported MCU +#if !defined(BOARDLOADER) && !defined(BOOTLOADER) + case MPU_MODE_BOOTUPDATE: + DIS_REGION( 5 ); + // Bootloader (Privileged, Read-Write, Non-Executable) + SET_REGION( 6, FLASH_BASE + 0x20000, SIZE_128KB, 0x00, FLASH_DATA, PRIV_RW ); + break; #endif - // OTP (0x1FFF7800 - 0x1FFF7C00, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER7; - MPU->RBAR = FLASH_OTP_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | - LL_MPU_REGION_SIZE_1KB | LL_MPU_REGION_FULL_ACCESS | - MPU_RASR_XN_Msk; + case MPU_MODE_OTP: + DIS_REGION( 5 ); + // OTP (Privileged, Read-Write, Non-Executable) + SET_REGION( 6, FLASH_OTP_BASE, SIZE_1KB, 0x00, FLASH_DATA, FULL_ACCESS ); + break; + + case MPU_MODE_FSMC_REGS: + DIS_REGION( 5 ); + // FSMC Control Registers (Privileged, Read-Write, Non-Executable) + // 0xA0000000 = FMSC_R_BASE (not defined in used headers) + SET_REGION( 6, 0xA0000000, SIZE_4KB, 0x00, FLASH_DATA, FULL_ACCESS ); + break; + + case MPU_MODE_FLASHOB: + SET_REGION( 5, 0x1FFFC000, SIZE_1KB, 0x00, FLASH_DATA, PRIV_RO ); + SET_REGION( 6, 0x1FFEC000, SIZE_1KB, 0x00, FLASH_DATA, PRIV_RO ); + break; + + case MPU_MODE_UNUSED_FLASH: + // Unused Flash Area #1 (Privileged, Read-Write, Non-Executable) + SET_REGION( 5, FLASH_BASE + 0x00C000, SIZE_16KB, 0x00, FLASH_DATA, PRIV_RW ); + // Unused Flash Area #2 (Privileged, Read-Write, Non-Executable) + SET_REGION( 6, FLASH_BASE + 0x10C000, SIZE_16KB, 0x00, FLASH_DATA, PRIV_RW ); + break; + +#ifdef USE_OPTIGA + // with optiga, we use the secret sector, and assets area is smaller + case MPU_MODE_SECRET: + DIS_REGION( 5 ); + // Secret sector in Bank #2 (Privileged, Read-Write, Non-Executable) + SET_REGION( 6, FLASH_BASE + 0x100000, SIZE_16KB, 0x00, FLASH_DATA, PRIV_RW ); + break; + + case MPU_MODE_ASSETS: + DIS_REGION( 5 ); + // Assets (Privileged, Read-Write, Non-Executable) + SET_REGION( 6, FLASH_BASE + 0x108000, SIZE_32KB, 0x00, FLASH_DATA, PRIV_RW ); + break; + + case MPU_MODE_APP: + // Unused (maybe privileged kernel code in the future) + DIS_REGION( 5 ); + // Assets (Unprivileged, Read-Only, Non-Executable) + SET_REGION( 6, FLASH_BASE + 0x108000, SIZE_32KB, 0x00, FLASH_DATA, PRIV_RO_URO ); + break; + +#else + // without optiga, we use additional sector for assets area + case MPU_MODE_ASSETS: + DIS_REGION( 5 ); + // Assets (Privileged, Read-Write, Non-Executable) + // Subregion: 48KB = 64KB except 2/8 at end + SET_REGION( 6, FLASH_BASE + 0x100000, SIZE_64KB, 0xC0, FLASH_DATA, PRIV_RW ); + break; + + case MPU_MODE_APP: + // Unused (maybe privileged kernel code in the future) + DIS_REGION( 5 ); + // Assets (Unprivileged, Read-Only, Non-Executable) + // Subregion: 48KB = 64KB except 2/8 at end + SET_REGION( 6, FLASH_BASE + 0x100000, SIZE_64KB, 0xC0, FLASH_DATA, PRIV_RO_URO ); + break; - // Enable MPU - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); +#endif - __asm__ volatile("dsb"); - __asm__ volatile("isb"); + case MPU_MODE_STORAGE: + // Storage in the Flash Bank #1 (Privileged, Read-Write, Non-Executable) + SET_REGION( 5, FLASH_BASE + 0x10000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW ); + // Storage in the Flash Bank #2 (Privileged, Read-Write, Non-Executable) + SET_REGION( 6, FLASH_BASE + 0x110000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW ); + break; + + default: + DIS_REGION( 5 ); + DIS_REGION( 6 ); + break; + } + // clang-format on + + // Region #7 is banked + + // clang-format off + switch (mode) { + case MPU_MODE_APP: + // Dma2D (Unprivileged, Read-Write, Non-Executable) + // 3KB = 4KB except 1/4 at end + SET_REGION( 7, 0x4002B000, SIZE_4KB, 0xC0, PERIPH, FULL_ACCESS ); + break; + default: + // All Peripherals (Privileged, Read-Write, Non-Executable) + SET_REGION( 7, PERIPH_BASE, SIZE_1GB, 0x00, PERIPH, PRIV_RW ); + break; + } + // clang-format on + + if (mode != MPU_MODE_DISABLED) { + HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + } + + mpu_mode_t prev_mode = drv->mode; + drv->mode = mode; + + irq_unlock(irq_key); + + return prev_mode; } + +void mpu_restore(mpu_mode_t mode) { mpu_reconfig(mode); } diff --git a/core/embed/trezorhal/stm32f4/secret.c b/core/embed/trezorhal/stm32f4/secret.c index 72a3aefc012..a02df263603 100644 --- a/core/embed/trezorhal/stm32f4/secret.c +++ b/core/embed/trezorhal/stm32f4/secret.c @@ -4,6 +4,7 @@ #include "display_draw.h" #include "flash.h" #include "model.h" +#include "mpu.h" #ifdef FANCY_FATAL_ERROR #include "rust_ui.h" @@ -20,10 +21,15 @@ secbool secret_verify_header(void) { return secfalse; } + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); + bootloader_locked = memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0 ? sectrue : secfalse; + + mpu_restore(mpu_mode); + bootloader_locked_set = sectrue; return bootloader_locked; } @@ -44,12 +50,14 @@ void secret_write_header(void) { } void secret_write(const uint8_t* data, uint32_t offset, uint32_t len) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); ensure(flash_unlock_write(), "secret write"); for (int i = 0; i < len; i++) { ensure(flash_area_write_byte(&SECRET_AREA, offset + i, data[i]), "secret write"); } ensure(flash_lock_write(), "secret write"); + mpu_restore(mpu_mode); } secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) { @@ -63,28 +71,40 @@ secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) { return secfalse; } + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); memcpy(data, addr, len); + mpu_restore(mpu_mode); return sectrue; } secbool secret_wiped(void) { uint32_t size = flash_area_get_size(&SECRET_AREA); + secbool wiped = sectrue; + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); for (int i = 0; i < size; i += 4) { uint32_t* addr = (uint32_t*)flash_area_get_address(&SECRET_AREA, i, 4); if (addr == NULL) { - return secfalse; + wiped = secfalse; + break; } if (*addr != 0xFFFFFFFF) { - return secfalse; + wiped = secfalse; + break; } } - return sectrue; + + mpu_restore(mpu_mode); + + return wiped; } void secret_erase(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase"); + mpu_restore(mpu_mode); } secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) { diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c index 1f52fdfb253..fec5bf3c372 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c @@ -22,6 +22,7 @@ #include "display_io.h" #include "irq.h" +#include "mpu.h" __IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS = (__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE); @@ -127,7 +128,9 @@ void display_io_init_fmc(void) { normal_mode_timing.DataLatency = 2; // don't care normal_mode_timing.AccessMode = FMC_ACCESS_MODE_A; + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_FSMC_REGS); HAL_SRAM_Init(&external_display_data_sram, &normal_mode_timing, NULL); + mpu_restore(mpu_mode); } #ifdef DISPLAY_TE_INTERRUPT_HANDLER diff --git a/core/embed/trezorhal/stm32u5/entropy.c b/core/embed/trezorhal/stm32u5/entropy.c index c1af6ded35a..c05f2762ee6 100644 --- a/core/embed/trezorhal/stm32u5/entropy.c +++ b/core/embed/trezorhal/stm32u5/entropy.c @@ -22,6 +22,7 @@ #include "entropy.h" #include "flash_otp.h" #include "model.h" +#include "mpu.h" #include "rand.h" #include "stm32u5xx_ll_utils.h" @@ -29,6 +30,8 @@ static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; void entropy_init(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + // collect entropy from UUID uint32_t w = LL_GetUID_Word0(); memcpy(g_hw_entropy, &w, 4); @@ -37,6 +40,8 @@ void entropy_init(void) { w = LL_GetUID_Word2(); memcpy(g_hw_entropy + 8, &w, 4); + mpu_restore(mpu_mode); + // set entropy in the OTP randomness block if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; diff --git a/core/embed/trezorhal/stm32u5/flash_otp.c b/core/embed/trezorhal/stm32u5/flash_otp.c index c5c6d7aa618..f3c6163e01f 100644 --- a/core/embed/trezorhal/stm32u5/flash_otp.c +++ b/core/embed/trezorhal/stm32u5/flash_otp.c @@ -22,6 +22,7 @@ #include "flash_otp.h" #include "common.h" #include "flash.h" +#include "mpu.h" void flash_otp_init() { // intentionally left empty @@ -33,10 +34,16 @@ secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, offset + datalen > FLASH_OTP_BLOCK_SIZE) { return secfalse; } + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + for (uint8_t i = 0; i < datalen; i++) { data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i); } + + mpu_restore(mpu_mode); + return sectrue; } @@ -49,6 +56,9 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, offset + datalen > FLASH_OTP_BLOCK_SIZE) { return secfalse; } + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + ensure(flash_unlock_write(), NULL); for (uint8_t i = 0; i < datalen; i += 16) { uint32_t address = @@ -58,35 +68,60 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, NULL); } ensure(flash_lock_write(), NULL); + + mpu_restore(mpu_mode); + return sectrue; } secbool flash_otp_lock(uint8_t block) { + if (block >= FLASH_OTP_NUM_BLOCKS) { + return secfalse; + } + // check that all quadwords in the block have been written to volatile uint8_t *addr = (__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + secbool qw_locked = secfalse; for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) { if (addr[i] != 0xFF) { qw_locked = sectrue; } if (i % 16 == 15 && qw_locked == secfalse) { + mpu_restore(mpu_mode); return secfalse; } } + + mpu_restore(mpu_mode); + return sectrue; } secbool flash_otp_is_locked(uint8_t block) { + if (block >= FLASH_OTP_NUM_BLOCKS) { + return secfalse; + } + + secbool is_locked = secfalse; + // considering block locked if any quadword in the block is non-0xFF volatile uint8_t *addr = (__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP); + for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) { if (addr[i] != 0xFF) { - return sectrue; + is_locked = sectrue; + break; } } - return secfalse; + + mpu_restore(mpu_mode); + + return is_locked; } diff --git a/core/embed/trezorhal/stm32u5/monoctr.c b/core/embed/trezorhal/stm32u5/monoctr.c index 6504371fa26..24171eab85a 100644 --- a/core/embed/trezorhal/stm32u5/monoctr.c +++ b/core/embed/trezorhal/stm32u5/monoctr.c @@ -20,6 +20,7 @@ #include "monoctr.h" #include "flash_area.h" #include "model.h" +#include "mpu.h" #include "secret.h" static int32_t get_offset(monoctr_type_t type) { @@ -80,6 +81,8 @@ secbool monoctr_read(monoctr_type_t type, uint8_t *value) { return secfalse; } + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); + int counter = 0; int i = 0; @@ -111,10 +114,13 @@ secbool monoctr_read(monoctr_type_t type, uint8_t *value) { if (not_cleared != sectrue) { // monotonic counter is not valid + mpu_restore(mpu_mode); return secfalse; } } + mpu_restore(mpu_mode); + if (value != NULL) { *value = counter; } else { diff --git a/core/embed/trezorhal/stm32u5/mpu.c b/core/embed/trezorhal/stm32u5/mpu.c index 25c04d5e13b..5b3c1671fd0 100644 --- a/core/embed/trezorhal/stm32u5/mpu.c +++ b/core/embed/trezorhal/stm32u5/mpu.c @@ -19,8 +19,11 @@ #include STM32_HAL_H #include + #include "common.h" #include "model.h" +#include "mpu.h" + #include "stm32u5xx_ll_cortex.h" // region type @@ -126,22 +129,11 @@ static void mpu_set_attributes(void) { #error "Unknown MCU" #endif -#define L1_REST_SIZE (FLASH_SIZE - (BOARDLOADER_SIZE + SECRET_SIZE)) - -#define L2_PREV_SIZE (SECRET_SIZE + BOARDLOADER_SIZE) -#define L2_REST_SIZE \ - (FLASH_SIZE - (BOOTLOADER_SIZE + BOARDLOADER_SIZE + SECRET_SIZE)) - -#define L3_PREV_SIZE \ - (STORAGE_SIZE + BOOTLOADER_SIZE + BOARDLOADER_SIZE + SECRET_SIZE) - #define ASSETS_START (FIRMWARE_START + FIRMWARE_SIZE) #define ASSETS_SIZE \ (FLASH_SIZE - (FIRMWARE_SIZE + BOOTLOADER_SIZE + BOARDLOADER_SIZE + \ SECRET_SIZE + STORAGE_SIZE)) -#define L3_PREV_SIZE_BLD (STORAGE_SIZE + BOOTLOADER_SIZE) - #ifdef STM32U585xx #define GRAPHICS_START FMC_BANK1 #define GRAPHICS_SIZE SIZE_16M @@ -152,106 +144,194 @@ static void mpu_set_attributes(void) { #define OTP_AND_ID_SIZE 0x800 -void mpu_config_boardloader(void) { - HAL_MPU_Disable(); - mpu_set_attributes(); +// clang-format on + +#define KERNEL_RAM_START (SRAM2_BASE - SIZE_16K) +#define KERNEL_RAM_SIZE (SIZE_24K) + +#define COREAPP_RAM1_START SRAM1_BASE +#define COREAPP_RAM1_SIZE (SIZE_192K - SIZE_16K) + +#define COREAPP_RAM2_START (SRAM2_BASE + SIZE_8K) +#define COREAPP_RAM2_SIZE (SRAM_SIZE - (SIZE_192K + SIZE_8K)) + +typedef struct { + // Set if the driver is initialized + bool initialized; + // Current mode + mpu_mode_t mode; + +} mpu_driver_t; + +mpu_driver_t g_mpu_driver = { + .initialized = false, + .mode = MPU_MODE_DISABLED, +}; + +static void mpu_init_fixed_regions(void) { + // Regions #0 to #5 are fixed for all targets + // clang-format off +#if defined(BOARDLOADER) + // REGION ADDRESS SIZE TYPE WRITE UNPRIV + SET_REGION( 0, BOARDLOADER_START, BOARDLOADER_SIZE, FLASH_CODE, NO, NO ); + SET_REGION( 1, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); + SET_REGION( 2, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_DATA, YES, NO ); + SET_REGION( 3, FIRMWARE_START, FIRMWARE_SIZE, FLASH_DATA, YES, NO ); + DIS_REGION( 4 ); + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); +#endif +#if defined(BOOTLOADER) // REGION ADDRESS SIZE TYPE WRITE UNPRIV - SET_REGION( 0, SECRET_START, SECRET_SIZE, FLASH_DATA, YES, NO ); // Secret - SET_REGION( 1, BOARDLOADER_START, BOARDLOADER_SIZE, FLASH_CODE, NO, NO ); // Boardloader code - SET_REGION( 2, BOOTLOADER_START, L1_REST_SIZE, FLASH_DATA, YES, NO ); // Bootloader + Storage + Firmware - SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); // SRAM1/2/3/5 - SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); // Frame buffer or display interface - SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, NO ); // Peripherals + SET_REGION( 0, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_CODE, NO, NO ); + SET_REGION( 1, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); + SET_REGION( 2, FIRMWARE_START, FIRMWARE_SIZE, FLASH_DATA, YES, NO ); + DIS_REGION( 3 ); + DIS_REGION( 4 ); + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); +#endif +#if defined(KERNEL) + // REGION ADDRESS SIZE TYPE WRITE UNPRIV + SET_REGION( 0, KERNEL_START, KERNEL_SIZE, FLASH_CODE, NO, NO ); + SET_REGION( 1, KERNEL_RAM_START, KERNEL_RAM_SIZE, SRAM, YES, NO ); + SET_REGION( 2, COREAPP_START, COREAPP_SIZE, FLASH_CODE, NO, YES ); + SET_REGION( 3, COREAPP_RAM1_START, COREAPP_RAM1_SIZE, SRAM, YES, YES ); + SET_REGION( 4, COREAPP_RAM2_START, COREAPP_RAM2_SIZE, SRAM, YES, YES ); + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); +#endif +#if defined(FIRMWARE) + // REGION ADDRESS SIZE TYPE WRITE UNPRIV + SET_REGION( 0, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, NO ); + SET_REGION( 1, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); + DIS_REGION( 2 ); + DIS_REGION( 3 ); + DIS_REGION( 4 ); + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); +#endif +#if defined(TREZOR_PRODTEST) + SET_REGION( 0, FIRMWARE_START, 1024, FLASH_DATA, YES, NO ); + SET_REGION( 1, FIRMWARE_START + 1024, FIRMWARE_SIZE - 1024, FLASH_CODE, NO, NO ); + SET_REGION( 2, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); + DIS_REGION( 3 ); + DIS_REGION( 4 ); + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); +#endif + + // Regions #6 and #7 are banked + DIS_REGION( 6 ); - SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, NO ); // SRAM4 + DIS_REGION( 7 ); // clang-format on - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); } -void mpu_config_bootloader(void) { - HAL_MPU_Disable(); - mpu_set_attributes(); - // clang-format off - // REGION ADDRESS SIZE TYPE WRITE UNPRIV - SET_REGION( 0, SECRET_START, L2_PREV_SIZE, FLASH_DATA, YES, NO ); // Secret + Boardloader - SET_REGION( 1, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_CODE, NO, NO ); // Bootloader code - SET_REGION( 2, STORAGE_START, L2_REST_SIZE, FLASH_DATA, YES, NO ); // Storage + Firmware - SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); // SRAM1/2/3/5 - SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); // Frame buffer or display interface - SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, NO ); // Peripherals - SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, NO ); // OTP - SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, NO ); // SRAM4 - // clang-format on - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); -} +void mpu_init(void) { + mpu_driver_t* drv = &g_mpu_driver; + + if (drv->initialized) { + return; + } + + irq_key_t irq_key = irq_lock(); -void mpu_config_firmware_initial(void) { HAL_MPU_Disable(); + mpu_set_attributes(); - // clang-format off - // REGION ADDRESS SIZE TYPE WRITE UNPRIV - SET_REGION( 0, BOOTLOADER_START, L3_PREV_SIZE_BLD, FLASH_DATA, YES, YES ); // Bootloader + Storage - SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, YES ); // Firmware - SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets - SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5 - SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface - SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals - SET_REGION( 6, FLASH_OTP_BASE, SIZE_2K, FLASH_DATA, YES, YES ); // OTP - SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4 - // clang-format on - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + + mpu_init_fixed_regions(); + + drv->mode = MPU_MODE_DISABLED; + drv->initialized = true; + + irq_unlock(irq_key); } -void mpu_config_firmware(void) { - HAL_MPU_Disable(); - mpu_set_attributes(); - // clang-format off - // REGION ADDRESS SIZE TYPE WRITE UNPRIV - SET_REGION( 0, STORAGE_START, STORAGE_SIZE, FLASH_DATA, YES, YES ); // Storage - SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, YES ); // Firmware - SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets - SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5 - SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface - SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals - SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP - SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4 - // clang-format on - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); +mpu_mode_t mpu_get_mode(void) { + mpu_driver_t* drv = &g_mpu_driver; + + if (!drv->initialized) { + return MPU_MODE_DISABLED; + } + + return drv->mode; } -void mpu_config_prodtest_initial(void) { +mpu_mode_t mpu_reconfig(mpu_mode_t mode) { + mpu_driver_t* drv = &g_mpu_driver; + + if (!drv->initialized) { + // Solves the issue when some IRQ handler tries to reconfigure + // MPU before it is initialized + return MPU_MODE_DISABLED; + } + + irq_key_t irq_key = irq_lock(); + HAL_MPU_Disable(); - mpu_set_attributes(); + + // Region #6 is banked + // clang-format off - // REGION ADDRESS SIZE TYPE WRITE UNPRIV - SET_REGION( 0, FLASH_BASE, L3_PREV_SIZE, FLASH_DATA, YES, YES ); // Secret, Bld, Storage - SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, YES ); // Firmware - SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets - SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5 - SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface - SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals - SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP - SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4 + switch (mode) { + case MPU_MODE_DISABLED: + break; +#if !defined(BOARDLOADER) + case MPU_MODE_BOARDCAPS: + // REGION ADDRESS SIZE TYPE WRITE UNPRIV + SET_REGION( 6, BOARDLOADER_START, BOARDLOADER_SIZE, FLASH_DATA, NO, NO ); + break; +#endif +#if !defined(BOOTLOADER) && !defined(BOARDLOADER) + case MPU_MODE_BOOTUPDATE: + SET_REGION( 6, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_DATA, YES, NO ); + break; +#endif + case MPU_MODE_OTP: + SET_REGION( 6, FLASH_OTP_BASE, OTP_AND_ID_SIZE, FLASH_DATA, NO, NO ); + break; + case MPU_MODE_SECRET: + SET_REGION( 6, SECRET_START, SECRET_SIZE, FLASH_DATA, YES, NO ); + break; + case MPU_MODE_STORAGE: + SET_REGION( 6, STORAGE_START, STORAGE_SIZE, FLASH_DATA, YES, NO ); + break; + case MPU_MODE_ASSETS: + SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, NO ); + break; + case MPU_MODE_APP: + SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, NO, YES ); + break; + default: + DIS_REGION( 6 ); + break; + } // clang-format on - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); -} -void mpu_config_prodtest(void) { - HAL_MPU_Disable(); - mpu_set_attributes(); + // Region #7 is banked + // clang-format off - // REGION ADDRESS SIZE TYPE WRITE UNPRIV - SET_REGION( 0, STORAGE_START, STORAGE_SIZE, FLASH_DATA, YES, YES ); // Storage - SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, YES, YES ); // Firmware - SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets - SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5 - SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface - SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals - SET_REGION( 6, FLASH_OTP_BASE, OTP_AND_ID_SIZE, FLASH_DATA, YES, YES ); // OTP + device ID - SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4 + switch (mode) { + case MPU_MODE_APP: + // REGION ADDRESS SIZE TYPE WRITE UNPRIV + // DMA2D peripherals (Unprivileged, Read-Write, Non-Executable) + SET_REGION( 7, 0x5002B000, SIZE_3K, PERIPHERAL, YES, YES ); + break; + default: + // All peripherals (Privileged, Read-Write, Non-Executable) + SET_REGION( 7, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, NO ); + break; + } // clang-format on - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + + if (mode != MPU_MODE_DISABLED) { + HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + } + + mpu_mode_t prev_mode = drv->mode; + drv->mode = mode; + + irq_unlock(irq_key); + + return prev_mode; } -void mpu_config_off(void) { HAL_MPU_Disable(); } +void mpu_restore(mpu_mode_t mode) { mpu_reconfig(mode); } diff --git a/core/embed/trezorhal/stm32u5/secret.c b/core/embed/trezorhal/stm32u5/secret.c index 104fdb5ddfc..17fb93d08ba 100644 --- a/core/embed/trezorhal/stm32u5/secret.c +++ b/core/embed/trezorhal/stm32u5/secret.c @@ -4,8 +4,10 @@ #include "bootutils.h" #include "common.h" #include "flash.h" +#include "flash_utils.h" #include "memzero.h" #include "model.h" +#include "mpu.h" #include "rng.h" #include "secure_aes.h" @@ -19,17 +21,21 @@ secbool secret_verify_header(void) { return secfalse; } + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); + bootloader_locked = memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0 ? sectrue : secfalse; + + mpu_restore(mpu_mode); + return bootloader_locked; } secbool secret_ensure_initialized(void) { if (sectrue != secret_verify_header()) { - ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), - "erase storage failed"); + ensure(erase_storage(NULL), "erase storage failed"); secret_erase(); secret_write_header(); return secfalse; @@ -58,6 +64,7 @@ void secret_write_header(void) { } void secret_write(const uint8_t *data, uint32_t offset, uint32_t len) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); ensure(flash_unlock_write(), "secret write"); for (int i = 0; i < len / 16; i++) { ensure(flash_area_write_quadword(&SECRET_AREA, offset + (i * 16), @@ -65,6 +72,7 @@ void secret_write(const uint8_t *data, uint32_t offset, uint32_t len) { "secret write"); } ensure(flash_lock_write(), "secret write"); + mpu_restore(mpu_mode); } secbool secret_read(uint8_t *data, uint32_t offset, uint32_t len) { @@ -76,7 +84,10 @@ secbool secret_read(uint8_t *data, uint32_t offset, uint32_t len) { if (addr == NULL) { return secfalse; } + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); memcpy(data, addr, len); + mpu_restore(mpu_mode); return sectrue; } @@ -106,6 +117,8 @@ static secbool secret_present(uint32_t offset, uint32_t len) { return secfalse; } + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); + int secret_empty_bytes = 0; for (int i = 0; i < len; i++) { @@ -115,6 +128,9 @@ static secbool secret_present(uint32_t offset, uint32_t len) { secret_empty_bytes++; } } + + mpu_restore(mpu_mode); + return sectrue * (secret_empty_bytes != len); } @@ -152,6 +168,8 @@ static void secret_bhk_load(void) { } void secret_bhk_regenerate(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); + ensure(flash_area_erase(&BHK_AREA, NULL), "Failed regenerating BHK"); ensure(flash_unlock_write(), "Failed regenerating BHK"); for (int i = 0; i < 2; i++) { @@ -164,6 +182,9 @@ void secret_bhk_regenerate(void) { memzero(val, sizeof(val)); ensure(res, "Failed regenerating BHK"); } + + mpu_restore(mpu_mode); + ensure(flash_lock_write(), "Failed regenerating BHK"); } @@ -187,6 +208,8 @@ secbool secret_optiga_writable(void) { return secfalse; } + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); + int secret_empty_bytes = 0; for (int i = 0; i < len; i++) { @@ -196,6 +219,9 @@ secbool secret_optiga_writable(void) { secret_empty_bytes++; } } + + mpu_restore(mpu_mode); + return sectrue * (secret_empty_bytes == len); } @@ -272,7 +298,9 @@ void secret_optiga_erase(void) { } void secret_erase(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase"); + mpu_restore(mpu_mode); } void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all) { diff --git a/core/embed/trezorhal/unix/mpu.c b/core/embed/trezorhal/unix/mpu.c new file mode 100644 index 00000000000..e91a8fa723d --- /dev/null +++ b/core/embed/trezorhal/unix/mpu.c @@ -0,0 +1,30 @@ +/* + * 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 "mpu.h" + +void mpu_init(void) { + // MPU functions are not fully implemented in Emulator +} + +mpu_mode_t mpu_get_mode(void) { return MPU_MODE_DISABLED; } + +mpu_mode_t mpu_reconfig(mpu_mode_t mode) { return MPU_MODE_DISABLED; } + +void mpu_restore(mpu_mode_t mode) {} From 52cbd291acd10323ae59595e58ced4ddef6125a2 Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 13 Aug 2024 07:47:59 +0200 Subject: [PATCH 36/44] refactor(core/embed): split firmware into kernel & coreapp [no changelog] --- core/Makefile | 36 + core/SConscript.boardloader | 1 + core/SConscript.bootloader | 1 + core/SConscript.bootloader_ci | 1 + core/SConscript.bootloader_emu | 1 + core/SConscript.coreapp | 941 ++++++++++++++++++ core/SConscript.firmware | 5 +- core/SConscript.kernel | 502 ++++++++++ core/SConscript.prodtest | 1 + core/SConscript.reflash | 4 + core/SConscript.unix | 2 + core/SConstruct | 2 + core/embed/coreapp/header.S | 54 + core/embed/coreapp/main.c | 105 ++ core/embed/coreapp/memory_DISC1.ld | 1 + core/embed/coreapp/memory_DISC2.ld | 130 +++ core/embed/coreapp/memory_R.ld | 1 + core/embed/coreapp/memory_T.ld | 109 ++ core/embed/coreapp/memory_T3B1.ld | 1 + core/embed/coreapp/memory_T3T1.ld | 115 +++ core/embed/coreapp/mpconfigport.h | 224 +++++ core/embed/coreapp/mphalport.c | 57 ++ core/embed/coreapp/mphalport.h | 24 + core/embed/coreapp/nlrthumb.c | 166 +++ core/embed/coreapp/startup_stm32f4.S | 42 + core/embed/coreapp/startup_stm32u5.S | 58 ++ core/embed/coreapp/version.h | 11 + core/embed/firmware/memory_T3T1.ld | 1 - core/embed/kernel/header.S | 54 + core/embed/kernel/main.c | 188 ++++ core/embed/kernel/memory_T3T1.ld | 122 +++ core/embed/kernel/startup_stm32u5.S | 72 ++ core/embed/kernel/version.h | 11 + core/embed/lib/sizedefs.h | 3 + core/embed/lib/translations.c | 4 + core/embed/lib/unit_variant.c | 4 + core/embed/lib/unit_variant.h | 5 + core/embed/models/D002/model_D002.h | 3 + core/embed/models/T3T1/model_T3T1.h | 3 + core/embed/trezorhal/bg_copy.h | 4 + core/embed/trezorhal/board_capabilities.h | 4 + core/embed/trezorhal/button.h | 5 + core/embed/trezorhal/consumption_mask.h | 24 +- core/embed/trezorhal/entropy.h | 6 +- core/embed/trezorhal/flash.h | 3 +- core/embed/trezorhal/flash_otp.h | 4 + core/embed/trezorhal/fwutils.h | 4 + core/embed/trezorhal/haptic.h | 4 + core/embed/trezorhal/hash_processor.h | 4 + core/embed/trezorhal/i2c_bus.h | 4 + core/embed/trezorhal/lowlevel.h | 4 + core/embed/trezorhal/monoctr.h | 4 + core/embed/trezorhal/mpu.h | 4 + core/embed/trezorhal/optiga/optiga.c | 4 + core/embed/trezorhal/optiga/optiga_commands.c | 4 + .../embed/trezorhal/optiga/optiga_transport.c | 4 + core/embed/trezorhal/random_delays.h | 12 +- core/embed/trezorhal/rgb_led.h | 29 + core/embed/trezorhal/rng.h | 6 + core/embed/trezorhal/sdcard.h | 5 + core/embed/trezorhal/secret.h | 18 +- .../trezorhal/stm32f4/board_capabilities.c | 4 + core/embed/trezorhal/stm32f4/bootutils.c | 6 + core/embed/trezorhal/stm32f4/button.c | 4 + core/embed/trezorhal/stm32f4/common.c | 4 + .../trezorhal/stm32f4/consumption_mask.c | 4 + core/embed/trezorhal/stm32f4/entropy.c | 6 + core/embed/trezorhal/stm32f4/fault_handlers.c | 34 +- core/embed/trezorhal/stm32f4/flash.c | 4 + core/embed/trezorhal/stm32f4/flash_otp.c | 4 + core/embed/trezorhal/stm32f4/fwutils.c | 4 + core/embed/trezorhal/stm32f4/i2c_bus.c | 17 + .../{limited_util.s => limited_util.S} | 0 core/embed/trezorhal/stm32f4/lowlevel.c | 4 + core/embed/trezorhal/stm32f4/monoctr.c | 4 + core/embed/trezorhal/stm32f4/mpu.c | 4 + core/embed/trezorhal/stm32f4/optiga_hal.c | 4 + core/embed/trezorhal/stm32f4/platform.c | 4 + core/embed/trezorhal/stm32f4/random_delays.c | 4 + core/embed/trezorhal/stm32f4/rgb_led.c | 4 + core/embed/trezorhal/stm32f4/rng.c | 4 + core/embed/trezorhal/stm32f4/sdcard.c | 9 +- core/embed/trezorhal/stm32f4/secret.c | 6 +- core/embed/trezorhal/stm32f4/syscall.c | 205 ++++ core/embed/trezorhal/stm32f4/syscall.h | 209 ++++ .../trezorhal/stm32f4/syscall_dispatch.c | 499 ++++++++++ .../embed/trezorhal/stm32f4/syscall_numbers.h | 146 +++ core/embed/trezorhal/stm32f4/syscall_stubs.c | 616 ++++++++++++ core/embed/trezorhal/stm32f4/systick.c | 7 + core/embed/trezorhal/stm32f4/systimer.c | 4 + core/embed/trezorhal/stm32f4/touch/ft6x36.c | 4 + core/embed/trezorhal/stm32f4/usb/usb.c | 4 + .../trezorhal/stm32f4/usb/usb_class_hid.c | 4 + .../trezorhal/stm32f4/usb/usb_class_vcp.c | 4 + .../trezorhal/stm32f4/usb/usb_class_webusb.c | 4 + core/embed/trezorhal/stm32f4/usb/usbd_conf.c | 14 + core/embed/trezorhal/stm32f4/usb/usbd_core.c | 4 + .../embed/trezorhal/stm32f4/usb/usbd_ctlreq.c | 4 + core/embed/trezorhal/stm32f4/usb/usbd_ioreq.c | 4 + .../trezorhal/stm32f4/{util.s => util.S} | 0 .../stm32f4/{vectortable.s => vectortable.S} | 12 + .../stm32f4/xdisplay/st-7789/display_driver.c | 4 + .../stm32f4/xdisplay/st-7789/display_fb.c | 13 +- .../stm32f4/xdisplay/st-7789/display_io.c | 4 + .../stm32f4/xdisplay/st-7789/display_nofb.c | 4 + .../stm32f4/xdisplay/st-7789/display_panel.c | 4 + core/embed/trezorhal/stm32u5/bg_copy.c | 9 + .../trezorhal/stm32u5/consumption_mask.c | 4 + core/embed/trezorhal/stm32u5/entropy.c | 4 + core/embed/trezorhal/stm32u5/fault_handlers.c | 31 +- core/embed/trezorhal/stm32u5/flash.c | 4 + core/embed/trezorhal/stm32u5/flash_otp.c | 4 + .../stm32u5/haptic/drv2625/drv2625.c | 4 + core/embed/trezorhal/stm32u5/hash_processor.c | 11 +- core/embed/trezorhal/stm32u5/i2c_bus.c | 17 + .../{limited_util.s => limited_util.S} | 0 core/embed/trezorhal/stm32u5/lowlevel.c | 4 + core/embed/trezorhal/stm32u5/monoctr.c | 4 + core/embed/trezorhal/stm32u5/mpu.c | 6 + core/embed/trezorhal/stm32u5/platform.c | 4 + core/embed/trezorhal/stm32u5/sdcard.c | 7 + core/embed/trezorhal/stm32u5/secret.c | 4 + core/embed/trezorhal/stm32u5/secure_aes.c | 4 + core/embed/trezorhal/stm32u5/syscall.c | 1 + core/embed/trezorhal/stm32u5/syscall.h | 1 + .../trezorhal/stm32u5/syscall_dispatch.c | 1 + .../embed/trezorhal/stm32u5/syscall_numbers.h | 1 + core/embed/trezorhal/stm32u5/syscall_stubs.c | 1 + core/embed/trezorhal/stm32u5/tamper.c | 7 + .../trezorhal/stm32u5/{util.s => util.S} | 4 + .../stm32u5/{vectortable.s => vectortable.S} | 11 + core/embed/trezorhal/systick.h | 4 + core/embed/trezorhal/systimer.h | 4 + core/embed/trezorhal/tamper.h | 4 + core/embed/trezorhal/touch.h | 4 + core/embed/trezorhal/xdisplay.h | 4 + core/site_scons/models/stm32f4_common.py | 9 +- core/site_scons/models/stm32u5_common.py | 11 +- 138 files changed, 5284 insertions(+), 40 deletions(-) create mode 100644 core/SConscript.coreapp create mode 100644 core/SConscript.kernel create mode 100644 core/embed/coreapp/header.S create mode 100644 core/embed/coreapp/main.c create mode 120000 core/embed/coreapp/memory_DISC1.ld create mode 100644 core/embed/coreapp/memory_DISC2.ld create mode 120000 core/embed/coreapp/memory_R.ld create mode 100644 core/embed/coreapp/memory_T.ld create mode 120000 core/embed/coreapp/memory_T3B1.ld create mode 100644 core/embed/coreapp/memory_T3T1.ld create mode 100644 core/embed/coreapp/mpconfigport.h create mode 100644 core/embed/coreapp/mphalport.c create mode 100644 core/embed/coreapp/mphalport.h create mode 100644 core/embed/coreapp/nlrthumb.c create mode 100644 core/embed/coreapp/startup_stm32f4.S create mode 100644 core/embed/coreapp/startup_stm32u5.S create mode 100644 core/embed/coreapp/version.h create mode 100644 core/embed/kernel/header.S create mode 100644 core/embed/kernel/main.c create mode 100644 core/embed/kernel/memory_T3T1.ld create mode 100644 core/embed/kernel/startup_stm32u5.S create mode 100644 core/embed/kernel/version.h rename core/embed/trezorhal/stm32f4/{limited_util.s => limited_util.S} (100%) create mode 100644 core/embed/trezorhal/stm32f4/syscall.c create mode 100644 core/embed/trezorhal/stm32f4/syscall.h create mode 100644 core/embed/trezorhal/stm32f4/syscall_dispatch.c create mode 100644 core/embed/trezorhal/stm32f4/syscall_numbers.h create mode 100644 core/embed/trezorhal/stm32f4/syscall_stubs.c rename core/embed/trezorhal/stm32f4/{util.s => util.S} (100%) rename core/embed/trezorhal/stm32f4/{vectortable.s => vectortable.S} (96%) rename core/embed/trezorhal/stm32u5/{limited_util.s => limited_util.S} (100%) create mode 120000 core/embed/trezorhal/stm32u5/syscall.c create mode 120000 core/embed/trezorhal/stm32u5/syscall.h create mode 120000 core/embed/trezorhal/stm32u5/syscall_dispatch.c create mode 120000 core/embed/trezorhal/stm32u5/syscall_numbers.h create mode 120000 core/embed/trezorhal/stm32u5/syscall_stubs.c rename core/embed/trezorhal/stm32u5/{util.s => util.S} (99%) rename core/embed/trezorhal/stm32u5/{vectortable.s => vectortable.S} (97%) diff --git a/core/Makefile b/core/Makefile index 6bea0e20fb7..4f5703e2b60 100644 --- a/core/Makefile +++ b/core/Makefile @@ -18,6 +18,8 @@ BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci BOOTLOADER_EMU_BUILD_DIR = $(BUILD_DIR)/bootloader_emu PRODTEST_BUILD_DIR = $(BUILD_DIR)/prodtest REFLASH_BUILD_DIR = $(BUILD_DIR)/reflash +KERNEL_BUILD_DIR = $(BUILD_DIR)/kernel +COREAPP_BUILD_DIR = $(BUILD_DIR)/coreapp FIRMWARE_BUILD_DIR = $(BUILD_DIR)/firmware UNIX_BUILD_DIR = $(BUILD_DIR)/unix RUST_BUILD_DIR = $(BUILD_DIR)/rust @@ -78,6 +80,9 @@ endif FLASH_START = $(shell layout_parser ${TREZOR_MODEL} FLASH_START) BOARDLOADER_START = $(shell layout_parser ${TREZOR_MODEL} BOARDLOADER_START) BOOTLOADER_START = $(shell layout_parser ${TREZOR_MODEL} BOOTLOADER_START) +KERNEL_START = $(shell layout_parser ${TREZOR_MODEL} KERNEL_START) +COREAPP_START = $(shell layout_parser ${TREZOR_MODEL} COREAPP_START) +COREAPP_P2_START = $(shell layout_parser ${TREZOR_MODEL} COREAPP_P2_START) FIRMWARE_START = $(shell layout_parser ${TREZOR_MODEL} FIRMWARE_START) FIRMWARE_P2_START = $(shell layout_parser ${TREZOR_MODEL} FIRMWARE_P2_START) STORAGE_1_OFFSET = $(shell layout_parser ${TREZOR_MODEL} STORAGE_1_OFFSET) @@ -270,6 +275,20 @@ build_reflash: ## build reflash firmware + reflash image dd if=build/boardloader/boardloader.bin of=$(REFLASH_BUILD_DIR)/sdimage.bin bs=1 seek=0 dd if=build/bootloader/bootloader.bin of=$(REFLASH_BUILD_DIR)/sdimage.bin bs=1 seek=49152 +build_kernel: ## build kernel image + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ + TREZOR_MODEL="$(TREZOR_MODEL)" \ + BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ + $(KERNEL_BUILD_DIR)/kernel.bin + +build_coreapp: templates build_cross ## build coreapp with frozen modules + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ + TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ + PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \ + BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ + DISABLE_OPTIGA="$(DISABLE_OPTIGA)" THP="$(THP)" NEW_RENDERING="$(NEW_RENDERING)" \ + $(COREAPP_BUILD_DIR)/coreapp.bin + build_firmware: templates build_cross ## build firmware with frozen modules $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ @@ -322,6 +341,12 @@ clean_prodtest: ## clean prodtest build clean_reflash: ## clean reflash build rm -rf $(REFLASH_BUILD_DIR) +clean_kernel: ## clean kernel build + rm -rf $(KERNEL_BUILD_DIR) + +clean_coreapp: ## clean coreapp build + rm -rf $(COREAPP_BUILD_DIR) $(RUST_BUILD_DIR) + clean_firmware: ## clean firmware build rm -rf $(FIRMWARE_BUILD_DIR) $(RUST_BUILD_DIR) @@ -347,6 +372,17 @@ flash_bootloader_ci: $(BOOTLOADER_CI_BUILD_DIR)/bootloader.bin ## flash CI bootl flash_prodtest: $(PRODTEST_BUILD_DIR)/prodtest.bin ## flash prodtest using OpenOCD $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_START); exit" +flash_kernel: $(KERNEL_BUILD_DIR)/kernel.bin ## flash kernel using OpenOCD + $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(KERNEL_START); exit" + +flash_coreapp: $(COREAPP_BUILD_DIR)/coreapp.bin ## flash coreapp using OpenOCD +ifeq ($(MCU),$(filter $(MCU),STM32F4)) + $(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(COREAPP_START); flash write_image erase $<.p2 $(COREAPP_P2_START); exit" + +else + $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(COREAPP_START); exit" +endif + flash_firmware: $(FIRMWARE_BUILD_DIR)/firmware.bin ## flash firmware using OpenOCD ifeq ($(MCU),$(filter $(MCU),STM32F4)) $(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(FIRMWARE_START); flash write_image erase $<.p2 $(FIRMWARE_P2_START); exit" diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader index 70cf6ae167d..056d11adee5 100644 --- a/core/SConscript.boardloader +++ b/core/SConscript.boardloader @@ -41,6 +41,7 @@ CPPPATH_MOD += [ 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ + 'KERNEL_MODE', 'AES_128', 'AES_192', 'USE_KECCAK', diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 52897b3d424..b79bd06f532 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -71,6 +71,7 @@ CPPPATH_MOD += [ 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ + 'KERNEL_MODE', 'AES_128', 'AES_192', 'USE_KECCAK', diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci index 9bdb258ba4b..d01be32d2a1 100644 --- a/core/SConscript.bootloader_ci +++ b/core/SConscript.bootloader_ci @@ -69,6 +69,7 @@ CPPPATH_MOD += [ 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ + 'KERNEL_MODE', 'AES_128', 'AES_192', 'USE_KECCAK', diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index a3462cc8851..fb3e3ed2f23 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -68,6 +68,7 @@ CPPPATH_MOD += [ 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ + 'KERNEL_MODE', 'AES_128', 'AES_192', 'USE_KECCAK', diff --git a/core/SConscript.coreapp b/core/SConscript.coreapp new file mode 100644 index 00000000000..2550ef94e3d --- /dev/null +++ b/core/SConscript.coreapp @@ -0,0 +1,941 @@ +# pylint: disable=E0602 +# fmt: off + +import os +import tools, models + +BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0') +PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1' +BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1' +BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' +EVERYTHING = BITCOIN_ONLY != '1' +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') +CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) +PYOPT = ARGUMENTS.get('PYOPT', '1') +DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1' +HW_REVISION = ARGUMENTS.get('HW_REVISION', None) +THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol +NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' or TREZOR_MODEL in ('T3T1',) + + +FEATURE_FLAGS = { + "RDI": True, + "SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) + "AES_GCM": False, +} + +FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"] +if DISABLE_OPTIGA and PYOPT == '0': + FEATURES_WANTED.remove("optiga") +if NEW_RENDERING: + FEATURES_WANTED.append("new_rendering") + +CCFLAGS_MOD = '' +CPPPATH_MOD = [] +CPPDEFINES_MOD = [] +SOURCE_MOD = [] +SOURCE_MOD_CRYPTO = [] +CPPDEFINES_HAL = [] +SOURCE_HAL = [] +PATH_HAL = [] + +FROZEN = True + +if TREZOR_MODEL in ('1', 'R', 'T3B1'): + FONT_NORMAL='Font_PixelOperator_Regular_8' + FONT_DEMIBOLD='Font_Unifont_Bold_16' + FONT_BOLD='Font_PixelOperator_Bold_8' + FONT_MONO='Font_PixelOperatorMono_Regular_8' + FONT_BIG='Font_Unifont_Regular_16' + FONT_NORMAL_UPPER='Font_PixelOperator_Regular_8_upper' + FONT_BOLD_UPPER='Font_PixelOperator_Bold_8_upper' + FONT_SUB=None +elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + FONT_NORMAL='Font_TTHoves_Regular_21' + FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' + FONT_BOLD=None + FONT_MONO='Font_RobotoMono_Medium_20' + FONT_BIG=None + FONT_NORMAL_UPPER=None + FONT_BOLD_UPPER='Font_TTHoves_Bold_17_upper' + FONT_SUB=None +elif TREZOR_MODEL in ('T3T1',): + FONT_NORMAL='Font_TTSatoshi_DemiBold_21' + FONT_DEMIBOLD='Font_TTSatoshi_DemiBold_21' + FONT_BOLD='Font_TTSatoshi_DemiBold_21' + FONT_MONO='Font_RobotoMono_Medium_21' + FONT_BIG='Font_TTSatoshi_DemiBold_42' + FONT_NORMAL_UPPER=None + FONT_BOLD_UPPER=None + FONT_SUB='Font_TTSatoshi_DemiBold_18' + +# modtrezorconfig +CPPPATH_MOD += [ + 'embed/extmod/modtrezorconfig', + 'vendor/trezor-storage', +] +SOURCE_MOD += [ + 'embed/extmod/modtrezorconfig/modtrezorconfig.c', + 'vendor/trezor-storage/norcow.c', + 'vendor/trezor-storage/storage.c', + 'vendor/trezor-storage/storage_utils.c', + 'vendor/trezor-storage/flash_area.c', +] + +# modtrezorcrypto +CCFLAGS_MOD += '-Wno-sequence-point ' +CPPPATH_MOD += [ + 'vendor/trezor-crypto', +] +CPPDEFINES_MOD += [ + 'AES_128', + 'AES_192', + ('USE_BIP32_CACHE', '0'), + ('USE_KECCAK', '1'), + ('USE_ETHEREUM', '1' if EVERYTHING else '0'), + ('USE_MONERO', '1' if EVERYTHING else '0'), + ('USE_CARDANO', '1' if EVERYTHING else '0'), + ('USE_NEM', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'), + ('USE_EOS', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'), +] +SOURCE_MOD += [ + 'embed/extmod/trezorobj.c', + 'embed/extmod/modtrezorcrypto/crc.c', + 'embed/extmod/modtrezorcrypto/modtrezorcrypto.c', + 'embed/extmod/modtrezorcrypto/rand.c', +] +SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/address.c', + 'vendor/trezor-crypto/aes/aes_modes.c', + 'vendor/trezor-crypto/aes/aesccm.c', + 'vendor/trezor-crypto/aes/aescrypt.c', + 'vendor/trezor-crypto/aes/aeskey.c', + 'vendor/trezor-crypto/aes/aestab.c', + 'vendor/trezor-crypto/base32.c', + 'vendor/trezor-crypto/base58.c', + 'vendor/trezor-crypto/bignum.c', + 'vendor/trezor-crypto/bip32.c', + 'vendor/trezor-crypto/bip39.c', + 'vendor/trezor-crypto/bip39_english.c', + 'vendor/trezor-crypto/blake256.c', + 'vendor/trezor-crypto/blake2b.c', + 'vendor/trezor-crypto/blake2s.c', + 'vendor/trezor-crypto/buffer.c', + 'vendor/trezor-crypto/chacha20poly1305/chacha20poly1305.c', + 'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c', + 'vendor/trezor-crypto/chacha20poly1305/poly1305-donna.c', + 'vendor/trezor-crypto/chacha20poly1305/rfc7539.c', + 'vendor/trezor-crypto/chacha_drbg.c', + 'vendor/trezor-crypto/curves.c', + 'vendor/trezor-crypto/der.c', + 'vendor/trezor-crypto/ecdsa.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-32bit-tables.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-basepoint-table.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-impl-base.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-keccak.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-sha3.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519.c', + 'vendor/trezor-crypto/ed25519-donna/modm-donna-32bit.c', + 'vendor/trezor-crypto/groestl.c', + 'vendor/trezor-crypto/hasher.c', + 'vendor/trezor-crypto/hmac.c', + 'vendor/trezor-crypto/hmac_drbg.c', + 'vendor/trezor-crypto/memzero.c', + 'vendor/trezor-crypto/nem.c', + 'vendor/trezor-crypto/nist256p1.c', + 'vendor/trezor-crypto/pbkdf2.c', + 'vendor/trezor-crypto/rand.c', + 'vendor/trezor-crypto/rfc6979.c', + 'vendor/trezor-crypto/ripemd160.c', + 'vendor/trezor-crypto/secp256k1.c', + 'vendor/trezor-crypto/segwit_addr.c', + 'vendor/trezor-crypto/sha2.c', + 'vendor/trezor-crypto/sha3.c', + 'vendor/trezor-crypto/shamir.c', + 'vendor/trezor-crypto/slip39.c', + 'vendor/trezor-crypto/slip39_english.c', + 'vendor/trezor-crypto/tls_prf.c', +] +if EVERYTHING: + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/cardano.c', + 'vendor/trezor-crypto/monero/base58.c', + 'vendor/trezor-crypto/monero/serialize.c', + 'vendor/trezor-crypto/monero/xmr.c', + ] + +# libsecp256k1-zkp +if FEATURE_FLAGS["SECP256K1_ZKP"]: + CPPPATH_MOD += [ + 'vendor/secp256k1-zkp', + 'vendor/secp256k1-zkp/src', + 'vendor/secp256k1-zkp/include', + ] + CPPDEFINES_MOD += [ + 'USE_SECP256K1_ZKP', + 'USE_SECP256K1_ZKP_ECDSA', + ('SECP256K1_CONTEXT_SIZE', '180'), + 'USE_ASM_ARM', + 'USE_EXTERNAL_ASM', + 'USE_EXTERNAL_DEFAULT_CALLBACKS', + ('ECMULT_GEN_PREC_BITS', '2'), + ('ECMULT_WINDOW_SIZE', '2'), + 'ENABLE_MODULE_GENERATOR', + 'ENABLE_MODULE_RECOVERY', + 'ENABLE_MODULE_SCHNORRSIG', + 'ENABLE_MODULE_EXTRAKEYS', + 'ENABLE_MODULE_ECDH', + ] + SOURCE_MOD_SECP256K1_ZKP = [ + 'vendor/secp256k1-zkp/src/secp256k1.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult_gen.c', + 'vendor/secp256k1-zkp/src/asm/field_10x26_arm.s' + ] + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/zkp_context.c', + 'vendor/trezor-crypto/zkp_ecdsa.c', + 'vendor/trezor-crypto/zkp_bip340.c', + ] + +# AES-GCM +if FEATURE_FLAGS["AES_GCM"]: + CPPDEFINES_MOD += [ + 'USE_AES_GCM', + 'AES_VAR', + ] + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/aes/gf128mul.c', + 'vendor/trezor-crypto/aes/aesgcm.c', + ] + +# modtrezorio +SOURCE_MOD += [ + 'embed/extmod/modtrezorio/modtrezorio.c', +] + +# modtrezorui +CPPPATH_MOD += [ + 'vendor/micropython/lib/uzlib', +] +SOURCE_MOD += [ + 'embed/extmod/modtrezorui/modtrezorui.c', + 'embed/lib/buffers.c', + 'embed/lib/colors.c', + 'embed/lib/display_utils.c', + 'embed/lib/error_handling.c', + 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/fonts/fonts.c', + 'embed/lib/gfx_color.c', + 'embed/lib/gfx_bitblt_rgb565.c', + 'embed/lib/gfx_bitblt_rgba8888.c', + 'embed/lib/gfx_bitblt_mono8.c', + 'embed/lib/image.c', + 'embed/lib/mini_printf.c', + 'embed/lib/terminal.c', + 'embed/lib/translations.c', + 'embed/lib/unit_variant.c', + 'vendor/micropython/lib/uzlib/adler32.c', + 'vendor/micropython/lib/uzlib/crc32.c', + 'vendor/micropython/lib/uzlib/tinflate.c', +] + +if NEW_RENDERING: + CPPDEFINES_MOD += ['NEW_RENDERING'] + SOURCE_MOD += [ + 'embed/lib/gfx_draw.c', + ] +else: + SOURCE_MOD += [ + 'embed/lib/display_draw.c', + ] + + +CPPDEFINES_MOD += [ + 'TREZOR_UI2', + 'TRANSLATIONS', +] + +if TREZOR_MODEL not in ('1', ): + CPPDEFINES_MOD += [ + 'FANCY_FATAL_ERROR', + ] + +# modtrezorutils +SOURCE_MOD += [ + 'embed/extmod/modtrezorutils/modtrezorutils.c', +] + +# rust mods +SOURCE_MOD += [ + 'embed/extmod/rustmods.c', +] + +# modutime +SOURCE_MOD += [ + 'embed/extmod/modutime.c', +] + +SOURCE_MICROPYTHON = [ + 'vendor/micropython/extmod/modubinascii.c', + 'vendor/micropython/extmod/moductypes.c', + 'vendor/micropython/extmod/moduheapq.c', + 'vendor/micropython/extmod/modutimeq.c', + 'vendor/micropython/extmod/utime_mphal.c', + 'vendor/micropython/shared/libc/abort_.c', + 'vendor/micropython/shared/libc/printf.c', + 'vendor/micropython/shared/runtime/gchelper_m3.s', + 'vendor/micropython/shared/runtime/gchelper_native.c', + 'vendor/micropython/shared/runtime/interrupt_char.c', + 'vendor/micropython/shared/runtime/pyexec.c', + 'vendor/micropython/shared/runtime/stdout_helpers.c', + 'vendor/micropython/shared/timeutils/timeutils.c', + 'vendor/micropython/ports/stm32/gccollect.c', + 'vendor/micropython/py/argcheck.c', + 'vendor/micropython/py/asmarm.c', + 'vendor/micropython/py/asmbase.c', + 'vendor/micropython/py/asmthumb.c', + 'vendor/micropython/py/asmx64.c', + 'vendor/micropython/py/asmx86.c', + 'vendor/micropython/py/asmxtensa.c', + 'vendor/micropython/py/bc.c', + 'vendor/micropython/py/binary.c', + 'vendor/micropython/py/builtinevex.c', + 'vendor/micropython/py/builtinhelp.c', + 'vendor/micropython/py/builtinimport.c', + 'vendor/micropython/py/compile.c', + 'vendor/micropython/py/emitbc.c', + 'vendor/micropython/py/emitcommon.c', + 'vendor/micropython/py/emitglue.c', + 'vendor/micropython/py/emitinlinethumb.c', + 'vendor/micropython/py/emitinlinextensa.c', + 'vendor/micropython/py/formatfloat.c', + 'vendor/micropython/py/frozenmod.c', + 'vendor/micropython/py/lexer.c', + 'vendor/micropython/py/malloc.c', + 'vendor/micropython/py/map.c', + 'vendor/micropython/py/modarray.c', + 'vendor/micropython/py/modbuiltins.c', + 'vendor/micropython/py/modgc.c', + 'vendor/micropython/py/modmath.c', + 'vendor/micropython/py/modmicropython.c', + 'vendor/micropython/py/modstruct.c', + 'vendor/micropython/py/modsys.c', + 'vendor/micropython/py/mpprint.c', + 'vendor/micropython/py/mpstate.c', + 'vendor/micropython/py/mpz.c', + 'vendor/micropython/py/nativeglue.c', + 'vendor/micropython/py/obj.c', + 'vendor/micropython/py/objarray.c', + 'vendor/micropython/py/objattrtuple.c', + 'vendor/micropython/py/objbool.c', + 'vendor/micropython/py/objboundmeth.c', + 'vendor/micropython/py/objcell.c', + 'vendor/micropython/py/objclosure.c', + 'vendor/micropython/py/objcomplex.c', + 'vendor/micropython/py/objdict.c', + 'vendor/micropython/py/objenumerate.c', + 'vendor/micropython/py/objexcept.c', + 'vendor/micropython/py/objfilter.c', + 'vendor/micropython/py/objfloat.c', + 'vendor/micropython/py/objfun.c', + 'vendor/micropython/py/objgenerator.c', + 'vendor/micropython/py/objgetitemiter.c', + 'vendor/micropython/py/objint.c', + 'vendor/micropython/py/objint_longlong.c', + 'vendor/micropython/py/objint_mpz.c', + 'vendor/micropython/py/objlist.c', + 'vendor/micropython/py/objmap.c', + 'vendor/micropython/py/objmodule.c', + 'vendor/micropython/py/objnamedtuple.c', + 'vendor/micropython/py/objnone.c', + 'vendor/micropython/py/objobject.c', + 'vendor/micropython/py/objpolyiter.c', + 'vendor/micropython/py/objproperty.c', + 'vendor/micropython/py/objrange.c', + 'vendor/micropython/py/objreversed.c', + 'vendor/micropython/py/objset.c', + 'vendor/micropython/py/objsingleton.c', + 'vendor/micropython/py/objslice.c', + 'vendor/micropython/py/objstr.c', + 'vendor/micropython/py/objstringio.c', + 'vendor/micropython/py/objstrunicode.c', + 'vendor/micropython/py/objtuple.c', + 'vendor/micropython/py/objtype.c', + 'vendor/micropython/py/objzip.c', + 'vendor/micropython/py/opmethods.c', + 'vendor/micropython/py/pairheap.c', + 'vendor/micropython/py/parse.c', + 'vendor/micropython/py/parsenum.c', + 'vendor/micropython/py/parsenumbase.c', + 'vendor/micropython/py/persistentcode.c', + 'vendor/micropython/py/qstr.c', + 'vendor/micropython/py/reader.c', + 'vendor/micropython/py/repl.c', + 'vendor/micropython/py/runtime.c', + 'vendor/micropython/py/runtime_utils.c', + 'vendor/micropython/py/scheduler.c', + 'vendor/micropython/py/scope.c', + 'vendor/micropython/py/sequence.c', + 'vendor/micropython/py/showbc.c', + 'vendor/micropython/py/smallint.c', + 'vendor/micropython/py/stackctrl.c', + 'vendor/micropython/py/stream.c', + 'vendor/micropython/py/unicode.c', + 'vendor/micropython/py/vstr.c', + 'vendor/micropython/py/warning.c', +] + +SOURCE_MICROPYTHON_SPEED = [ + 'vendor/micropython/py/gc.c', + 'vendor/micropython/py/pystack.c', + 'vendor/micropython/py/vm.c', +] + +CPPDEFINES_MOD += ['USE_SVC_SHUTDOWN'] + +if FEATURE_FLAGS["RDI"]: + CPPDEFINES_MOD += ['RDI'] + +TRANSLATION_DATA = [ + "translations/en.json", + "translations/order.json", +] + +if THP: + CPPDEFINES_MOD += ['USE_THP'] + SOURCE_MOD += [ + 'vendor/trezor-crypto/elligator2.c', + ] + +# fonts +tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('DEMIBOLD', FONT_DEMIBOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('MONO', FONT_MONO, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BIG', FONT_BIG, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('NORMAL_UPPER', FONT_NORMAL_UPPER, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BOLD_UPPER', FONT_BOLD_UPPER, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('SUB', FONT_SUB, CPPDEFINES_MOD, SOURCE_MOD) + +SOURCE_QSTR = SOURCE_MOD + SOURCE_MICROPYTHON + SOURCE_MICROPYTHON_SPEED + +env = Environment( + ENV=os.environ, + CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODUCTION={int(PRODUCTION)} -DPYOPT={PYOPT} -DBOOTLOADER_QA={int(BOOTLOADER_QA)} -DBITCOIN_ONLY={BITCOIN_ONLY}", + CPPDEFINES_IMPLICIT=[] + ) + +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/coreapp/header.S', + 'embed/coreapp/main.c', + 'embed/coreapp/mphalport.c', + 'embed/coreapp/nlrthumb.c', + f'embed/coreapp/startup_{FILE_SUFFIX}.S', +] + + +if TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + UI_LAYOUT = 'UI_LAYOUT_TT' + ui_layout_feature = 'model_tt' +elif TREZOR_MODEL in ('1', 'R', 'T3B1'): + UI_LAYOUT = 'UI_LAYOUT_TR' + ui_layout_feature = 'model_tr' +elif TREZOR_MODEL in ('T3T1',): + UI_LAYOUT = 'UI_LAYOUT_MERCURY' + ui_layout_feature = 'model_mercury' +else: + raise ValueError('Unknown Trezor model') + +if 'sd_card' in FEATURES_AVAILABLE: + SDCARD = True +else: + SDCARD = False + +env.Tool('micropython') + +env.Replace( + CAT='cat', + DD='dd', + CP='cp', + SED='sed', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', ) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL,) + +if TREZOR_MODEL in ('1',): + LD_VARIANT = '' if EVERYTHING else '_min' +else: + LD_VARIANT = '' + +ALLPATHS = [ + '.', + 'embed/rust', + 'embed/coreapp', + 'embed/lib', + 'embed/models', + 'embed/trezorhal', + 'embed/extmod/modtrezorui', + 'vendor/micropython', + ] + CPPPATH_MOD + PATH_HAL + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-Os'), + CCFLAGS='$COPT ' + '-g3 ' + '-nostdlib ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -fno-common ' + '-fsingle-precision-constant -fdata-sections -ffunction-sections ' + '-ffreestanding ' + '-fstack-protector-all ' + + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, + CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', + LINKFLAGS='-T embed/coreapp/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/coreapp/coreapp.map -Wl,--warn-common' % LD_VARIANT, + CPPPATH=ALLPATHS, + CPPDEFINES=[ + 'FIRMWARE', + 'TREZOR_MODEL_'+TREZOR_MODEL, + 'USE_HAL_DRIVER', + 'ARM_USER_MODE', + UI_LAYOUT, + ] + CPPDEFINES_MOD + CPPDEFINES_HAL, + ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], + ASPPFLAGS='$CFLAGS $CCFLAGS', + ) + +env.Replace( + HEADERTOOL='headertool', + PYTHON='python', + MAKEQSTRDATA='$PYTHON vendor/micropython/py/makeqstrdata.py', + MAKEVERSIONHDR='$PYTHON vendor/micropython/py/makeversionhdr.py', + MAKEMODULEDEFS='$PYTHON vendor/micropython/py/makemoduledefs.py', + MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', + MPY_TOOL='$PYTHON vendor/micropython/tools/mpy-tool.py', + MPY_CROSS='vendor/micropython/mpy-cross/mpy-cross -O' + PYOPT, + PB2PY='$PYTHON ../common/protob/pb2py', +) + +# +# Qstrings +# + +PROTO_SOURCES_DIR = '../../../common/protob/' +PROTO_SOURCES = Glob(PROTO_SOURCES_DIR + '*.proto', + exclude=[PROTO_SOURCES_DIR + 'messages-bootloader.proto'] +) +qstr_protobuf = env.Command( + target=[ + 'genhdr/qstrdefs.protobuf.h', + ], + source=PROTO_SOURCES, + action='$PB2PY $SOURCES --qstr-out ${TARGET} --bitcoin-only=%s' % BITCOIN_ONLY, +) + +qstr_micropython = 'vendor/micropython/py/qstrdefs.h' + +micropy_defines = env.MicroPyDefines(source=SOURCE_QSTR) + +qstr_collected = env.CollectQstr( + target='genhdr/qstrdefs.collected.h', source=micropy_defines) + +qstr_preprocessed = env.PreprocessQstr( + target='genhdr/qstrdefs.preprocessed.h', + source=[qstr_micropython, qstr_protobuf, qstr_collected]) + +qstr_generated = env.GenerateQstrDefs( + target='genhdr/qstrdefs.generated.h', source=qstr_preprocessed) + +env.Ignore(qstr_collected, qstr_generated) + +# +# Micropython module declarations +# + +moduledefs_collected = env.CollectModules( + target='genhdr/moduledefs.collected.h', source=micropy_defines) + +hdr_moduledefs = env.Command( + target='genhdr/moduledefs.h', + source=moduledefs_collected, + action='$MAKEMODULEDEFS $SOURCE > $TARGET', ) + +env.Ignore(micropy_defines, micropy_defines) +env.Ignore(micropy_defines, qstr_generated) +env.Ignore(micropy_defines, hdr_moduledefs) + +# +# Micropython version +# + +hdr_version = env.Command( + target='genhdr/mpversion.h', + source='', + action='$MAKEVERSIONHDR $TARGET', ) + +env.Ignore(hdr_moduledefs, hdr_moduledefs) +env.Ignore(hdr_moduledefs, qstr_collected) +env.Ignore(hdr_moduledefs, qstr_preprocessed) +env.Ignore(hdr_moduledefs, qstr_generated) + +# +# Frozen modules +# + +if FROZEN: + SOURCE_PY_DIR = 'src/' + + SOURCE_PY = Glob(SOURCE_PY_DIR + '*.py') + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/*.py', + exclude=[ + SOURCE_PY_DIR + 'trezor/sdcard.py', + ] if not SDCARD else [] + )) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/crypto/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/*.py')) + + # UI layouts - common files and then model-specific. Exclude FIDO when BTC-only. + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/*.py', + exclude=[ + SOURCE_PY_DIR + 'trezor/ui/layouts/fido.py', + ] if not EVERYTHING else [] + )) + if UI_LAYOUT == 'UI_LAYOUT_TT': + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/*.py', + exclude=[ + SOURCE_PY_DIR + 'trezor/ui/layouts/tt/fido.py', + ] if not EVERYTHING else [] + )) + elif UI_LAYOUT == 'UI_LAYOUT_TR': + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tr/*.py', + exclude=[ + SOURCE_PY_DIR + 'trezor/ui/layouts/tr/fido.py', + ] if not EVERYTHING else [] + )) + elif UI_LAYOUT == 'UI_LAYOUT_MERCURY': + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/mercury/*.py', + exclude=[ + SOURCE_PY_DIR + 'trezor/ui/layouts/mercury/fido.py', + ] if not EVERYTHING else [] + )) + else: + raise ValueError('Unknown layout') + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/wire/*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'storage/*.py', + exclude=[ + SOURCE_PY_DIR + 'storage/sd_salt.py', + ] if not SDCARD else [] + )) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/messages/__init__.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/*.py', + exclude=[ + SOURCE_PY_DIR + 'trezor/enums/Binance*.py', + SOURCE_PY_DIR + 'trezor/enums/Cardano*.py', + SOURCE_PY_DIR + 'trezor/enums/DebugMonero*.py', + SOURCE_PY_DIR + 'trezor/enums/Eos*.py', + SOURCE_PY_DIR + 'trezor/enums/Ethereum*.py', + SOURCE_PY_DIR + 'trezor/enums/Monero*.py', + SOURCE_PY_DIR + 'trezor/enums/NEM*.py', + SOURCE_PY_DIR + 'trezor/enums/Ripple*.py', + SOURCE_PY_DIR + 'trezor/enums/Solana*.py', + SOURCE_PY_DIR + 'trezor/enums/Stellar*.py', + SOURCE_PY_DIR + 'trezor/enums/Tezos*.py', + SOURCE_PY_DIR + 'trezor/enums/Zcash*.py', + ]) + ) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/common/*.py', + exclude=[ + SOURCE_PY_DIR + 'apps/common/sdcard.py', + ] if not SDCARD else [] + )) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/debug/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/homescreen/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py', + exclude=[ + SOURCE_PY_DIR + 'apps/management/sd_protect.py', + ] if not SDCARD else []) + ) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*/*.py', + exclude=[ + SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py', + SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py', + SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash_v4.py', + ]) + ) + + if EVERYTHING: + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/binance/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Binance*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/cardano/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/cardano/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Cardano*.py')) + + if TREZOR_MODEL == "T": + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/eos/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/eos/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Eos*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ethereum/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Ethereum*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/monero/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/monero/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/monero/*/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/DebugMonero*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Monero*.py')) + + if TREZOR_MODEL == "T": + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/nem/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/nem/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/NEM*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ripple/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Ripple*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/solana/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/solana/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Solana*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/stellar/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/stellar/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Stellar*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/tezos/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Tezos*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/zcash/*.py')) + + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py')) + + if TREZOR_MODEL == "T": + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash_v4.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Zcash*.py')) + + source_mpy = env.FrozenModule( + source=SOURCE_PY, + source_dir=SOURCE_PY_DIR, + bitcoin_only=BITCOIN_ONLY, + backlight='backlight' in FEATURES_AVAILABLE, + optiga='optiga' in FEATURES_AVAILABLE, + ui_layout=UI_LAYOUT, + thp=THP, + ) + + source_mpyc = env.FrozenCFile( + target='frozen_mpy.c', source=source_mpy, qstr_header=qstr_preprocessed) + + env.Depends(source_mpyc, qstr_generated) + + +# +# Program objects +# + +source_files = SOURCE_MOD + SOURCE_MOD_CRYPTO + SOURCE_FIRMWARE + SOURCE_MICROPYTHON + SOURCE_MICROPYTHON_SPEED + SOURCE_HAL +obj_program = [] +obj_program.extend(env.Object(source=SOURCE_MOD)) +obj_program.extend(env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-auto-var-init=zero')) +if FEATURE_FLAGS["SECP256K1_ZKP"]: + obj_program.extend(env.Object(source=SOURCE_MOD_SECP256K1_ZKP, CCFLAGS='$CCFLAGS -Wno-unused-function')) + source_files.extend(SOURCE_MOD_SECP256K1_ZKP) +obj_program.extend(env.Object(source=SOURCE_FIRMWARE)) +obj_program.extend(env.Object(source=SOURCE_MICROPYTHON)) +obj_program.extend(env.Object(source=SOURCE_MICROPYTHON_SPEED, COPT='-O3')) +obj_program.extend(env.Object(source=SOURCE_HAL)) +if FROZEN: + obj_program.extend(env.Object(source=source_mpyc)) + +env.Replace( + ALLSOURCES=source_files, + ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'] + env['CPPDEFINES_IMPLICIT'] + [f"PRODUCTION={int(PRODUCTION)}", f"BOOTLOADER_QA={int(BOOTLOADER_QA)}", f"PYOPT={PYOPT}", f"BITCOIN_ONLY={BITCOIN_ONLY}"])) + + +cmake_gen = env.Command( + target='CMakeLists.txt', + source='', + action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', +) + +# +# Rust library +# + +protobuf_blobs = env.Command( + target=[ + 'rust/proto_enums.data', + 'rust/proto_msgs.data', + 'rust/proto_names.data', + 'rust/proto_wire.data', + ], + source=PROTO_SOURCES, + action='$PB2PY --bitcoin-only=%s --blob-outdir ${TARGET.dir} $SOURCES --qstr-defs build/coreapp/genhdr/qstrdefs.generated.h' % BITCOIN_ONLY, +) +env.Depends(protobuf_blobs, qstr_generated) + +RUST_PROFILE = 'release' +RUST_LIB = 'trezor_lib' +RUST_LIBDIR = f'build/coreapp/rust/{env.get("ENV")["RUST_TARGET"]}/{RUST_PROFILE}' +RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a' + +def cargo_build(): + # Determine the profile build flags. + if RUST_PROFILE == 'release': + profile = '--release' + else: + profile = '' + + features = ['micropython', 'protobuf', ui_layout_feature] + if EVERYTHING: + features.append('universal_fw') + features.append('ui') + features.append('translations') + + if NEW_RENDERING: + features.append('new_rendering') + + if PYOPT == '0': + features.append('debug') + features.append('ui_debug') + if TREZOR_MODEL in ('T', 'T3T1', 'DISC1', 'DISC2'): + features.append('ui_blurring') + features.append('ui_jpeg_decoder') + + if NEW_RENDERING and TREZOR_MODEL in ('T3T1', 'DISC2'): + features.append('ui_image_buffer') + features.append('ui_overlay') + + features.extend(FEATURES_AVAILABLE) + + cargo_opts = [ + f'--target={env.get("ENV")["RUST_TARGET"]}', + f'--target-dir=../../build/coreapp/rust', + '--no-default-features', + '--features ' + ','.join(features), + '-Z build-std=core', + '-Z build-std-features=panic_immediate_abort', + ] + + env.get('ENV')['TREZOR_MODEL'] = TREZOR_MODEL + + bindgen_macros = tools.get_bindgen_defines(env.get("CPPDEFINES"), ALLPATHS) + build_dir = str(Dir('.').abspath) + + return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; export BUILD_DIR=\'{build_dir}\'; cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts) + +rust = env.Command( + target=RUST_LIBPATH, + source='', + action=cargo_build(), ) +env.Depends(rust, protobuf_blobs) +env.Depends(rust, TRANSLATION_DATA) + +env.Append(LINKFLAGS=f' -L{RUST_LIBDIR}') +env.Append(LINKFLAGS=f' -l{RUST_LIB}') + + +MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) +BOOTLOADER_SUFFIX = MODEL_IDENTIFIER +if BOOTLOADER_QA or BOOTLOADER_DEVEL: + BOOTLOADER_SUFFIX += '_qa' + +# select vendor header +if BOOTLOADER_QA or BOOTLOADER_DEVEL: + vendor = "dev_DO_NOT_SIGN_signed_dev" +elif not PRODUCTION: + vendor = "unsafe_signed_prod" +else: + if TREZOR_MODEL in ('T',): + vendor = "satoshilabs_signed_prod" + elif BITCOIN_ONLY == '1': + vendor = "trezor_btconly_signed_prod" + else: + vendor = "trezor_signed_prod" + +VENDORHEADER = f'embed/models/{MODEL_IDENTIFIER}/vendorheader/vendorheader_{vendor}.bin' + + +if TREZOR_MODEL not in ('1',): + obj_program.extend( + env.Command( + target='embed/coreapp/vendorheader.o', + source=VENDORHEADER, + action='$OBJCOPY -I binary -O elf32-littlearm -B arm' + ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' + ' $SOURCE $TARGET', )) + +env.Depends(obj_program, qstr_generated) + +program_elf = env.Command( + target='coreapp.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', +) + +if CMAKELISTS != 0: + env.Depends(program_elf, cmake_gen) +env.Depends(program_elf, rust) + +BINARY_NAME = f"build/coreapp/coreapp-{models.get_model_identifier(TREZOR_MODEL)}" +if not EVERYTHING: + BINARY_NAME += "-btconly" +BINARY_NAME += "-" + tools.get_version('embed/coreapp/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + + +if TREZOR_MODEL in ('1'): + action_bin=[ + '$OBJCOPY -O binary -j .header -j .flash -j .data -j .confidential $SOURCE $TARGET', + '../legacy/bootloader/firmware_sign.py -f $TARGET', + '$CP $TARGET ' + BINARY_NAME, + ] +else: + if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', + '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', + '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', + '$CP $TARGET ' + BINARY_NAME, + ] + elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$CP $TARGET ' + BINARY_NAME, + ] + else: + raise Exception("Unknown MCU") + +program_bin = env.Command( + target='coreapp.bin', + source=program_elf, + action=action_bin, +) diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 41e6677273c..74a2e634cdb 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -77,10 +77,6 @@ CPPPATH_MOD += [ ] SOURCE_MOD += [ 'embed/extmod/modtrezorconfig/modtrezorconfig.c', - 'vendor/trezor-storage/norcow.c', - 'vendor/trezor-storage/storage.c', - 'vendor/trezor-storage/storage_utils.c', - 'vendor/trezor-storage/flash_area.c', ] # modtrezorcrypto @@ -89,6 +85,7 @@ CPPPATH_MOD += [ 'vendor/trezor-crypto', ] CPPDEFINES_MOD += [ + 'KERNEL_MODE', 'AES_128', 'AES_192', ('USE_BIP32_CACHE', '0'), diff --git a/core/SConscript.kernel b/core/SConscript.kernel new file mode 100644 index 00000000000..2be27fc7f54 --- /dev/null +++ b/core/SConscript.kernel @@ -0,0 +1,502 @@ +# pylint: disable=E0602 +# fmt: off + +import os +import tools, models + +BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0') +PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1' +BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1' +BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' +EVERYTHING = BITCOIN_ONLY != '1' +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') +CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) +PYOPT = ARGUMENTS.get('PYOPT', '1') +DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1' +HW_REVISION = ARGUMENTS.get('HW_REVISION', None) +THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol +NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' or TREZOR_MODEL in ('T3T1',) + + +FEATURE_FLAGS = { + "RDI": True, + "SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) + "SYSTEM_VIEW": False, + "AES_GCM": False, +} + +FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"] +if DISABLE_OPTIGA and PYOPT == '0': + FEATURES_WANTED.remove("optiga") +if NEW_RENDERING: + FEATURES_WANTED.append("new_rendering") + +CCFLAGS_MOD = '' +CPPPATH_MOD = [] +CPPDEFINES_MOD = [] +SOURCE_MOD = [] +SOURCE_MOD_CRYPTO = [] +CPPDEFINES_HAL = [] +SOURCE_HAL = [] +PATH_HAL = [] + +FROZEN = True + +if TREZOR_MODEL in ('1', 'R'): + FONT_NORMAL='Font_PixelOperator_Regular_8' + FONT_DEMIBOLD='Font_Unifont_Bold_16' + FONT_BOLD='Font_PixelOperator_Bold_8' + FONT_MONO='Font_PixelOperatorMono_Regular_8' + FONT_BIG='Font_Unifont_Regular_16' + FONT_NORMAL_UPPER='Font_PixelOperator_Regular_8_upper' + FONT_BOLD_UPPER='Font_PixelOperator_Bold_8_upper' + FONT_SUB=None +elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + FONT_NORMAL='Font_TTHoves_Regular_21' + FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' + FONT_BOLD=None + FONT_MONO='Font_RobotoMono_Medium_20' + FONT_BIG=None + FONT_NORMAL_UPPER=None + FONT_BOLD_UPPER='Font_TTHoves_Bold_17_upper' + FONT_SUB=None +elif TREZOR_MODEL in ('T3T1',): + FONT_NORMAL='Font_TTSatoshi_DemiBold_21' + FONT_DEMIBOLD='Font_TTSatoshi_DemiBold_21' + FONT_BOLD='Font_TTSatoshi_DemiBold_21' + FONT_MONO='Font_RobotoMono_Medium_21' + FONT_BIG='Font_TTSatoshi_DemiBold_42' + FONT_NORMAL_UPPER=None + FONT_BOLD_UPPER=None + FONT_SUB='Font_TTSatoshi_DemiBold_18' + +# modtrezorconfig +CPPPATH_MOD += [ + 'embed/extmod/modtrezorconfig', + 'vendor/trezor-storage', +] +SOURCE_MOD += [ +# 'embed/extmod/modtrezorconfig/modtrezorconfig.c', + 'vendor/trezor-storage/norcow.c', + 'vendor/trezor-storage/storage.c', + 'vendor/trezor-storage/storage_utils.c', + 'vendor/trezor-storage/flash_area.c', +] + +# modtrezorcrypto +CCFLAGS_MOD += '-Wno-sequence-point ' +CPPPATH_MOD += [ + 'vendor/trezor-crypto', +] +CPPDEFINES_MOD += [ + 'KERNEL_MODE', + 'SYSCALL_DISPATCH', + 'AES_128', + 'AES_192', + ('USE_BIP32_CACHE', '0'), + ('USE_KECCAK', '1'), + ('USE_ETHEREUM', '1' if EVERYTHING else '0'), + ('USE_MONERO', '1' if EVERYTHING else '0'), + ('USE_CARDANO', '1' if EVERYTHING else '0'), + ('USE_NEM', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'), + ('USE_EOS', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'), +] +SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/address.c', + 'vendor/trezor-crypto/aes/aes_modes.c', + 'vendor/trezor-crypto/aes/aesccm.c', + 'vendor/trezor-crypto/aes/aescrypt.c', + 'vendor/trezor-crypto/aes/aeskey.c', + 'vendor/trezor-crypto/aes/aestab.c', + 'vendor/trezor-crypto/base32.c', + 'vendor/trezor-crypto/base58.c', + 'vendor/trezor-crypto/bignum.c', + 'vendor/trezor-crypto/bip32.c', + 'vendor/trezor-crypto/bip39.c', + 'vendor/trezor-crypto/bip39_english.c', + 'vendor/trezor-crypto/blake256.c', + 'vendor/trezor-crypto/blake2b.c', + 'vendor/trezor-crypto/blake2s.c', + 'vendor/trezor-crypto/buffer.c', + 'vendor/trezor-crypto/chacha20poly1305/chacha20poly1305.c', + 'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c', + 'vendor/trezor-crypto/chacha20poly1305/poly1305-donna.c', + 'vendor/trezor-crypto/chacha20poly1305/rfc7539.c', + 'vendor/trezor-crypto/chacha_drbg.c', + 'vendor/trezor-crypto/curves.c', + 'vendor/trezor-crypto/der.c', + 'vendor/trezor-crypto/ecdsa.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-32bit-tables.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-basepoint-table.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-impl-base.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-keccak.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-sha3.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519.c', + 'vendor/trezor-crypto/ed25519-donna/modm-donna-32bit.c', + 'vendor/trezor-crypto/groestl.c', + 'vendor/trezor-crypto/hasher.c', + 'vendor/trezor-crypto/hmac.c', + 'vendor/trezor-crypto/hmac_drbg.c', + 'vendor/trezor-crypto/memzero.c', + 'vendor/trezor-crypto/nem.c', + 'vendor/trezor-crypto/nist256p1.c', + 'vendor/trezor-crypto/pbkdf2.c', + 'vendor/trezor-crypto/rand.c', + 'vendor/trezor-crypto/rfc6979.c', + 'vendor/trezor-crypto/ripemd160.c', + 'vendor/trezor-crypto/secp256k1.c', + 'vendor/trezor-crypto/segwit_addr.c', + 'vendor/trezor-crypto/sha2.c', + 'vendor/trezor-crypto/sha3.c', + 'vendor/trezor-crypto/shamir.c', + 'vendor/trezor-crypto/slip39.c', + 'vendor/trezor-crypto/slip39_english.c', + 'vendor/trezor-crypto/tls_prf.c', +] +if EVERYTHING: + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/cardano.c', + 'vendor/trezor-crypto/monero/base58.c', + 'vendor/trezor-crypto/monero/serialize.c', + 'vendor/trezor-crypto/monero/xmr.c', + ] + +# libsecp256k1-zkp +if FEATURE_FLAGS["SECP256K1_ZKP"]: + CPPPATH_MOD += [ + 'vendor/secp256k1-zkp', + 'vendor/secp256k1-zkp/src', + 'vendor/secp256k1-zkp/include', + ] + CPPDEFINES_MOD += [ + 'USE_SECP256K1_ZKP', + 'USE_SECP256K1_ZKP_ECDSA', + ('SECP256K1_CONTEXT_SIZE', '180'), + 'USE_ASM_ARM', + 'USE_EXTERNAL_ASM', + 'USE_EXTERNAL_DEFAULT_CALLBACKS', + ('ECMULT_GEN_PREC_BITS', '2'), + ('ECMULT_WINDOW_SIZE', '2'), + 'ENABLE_MODULE_GENERATOR', + 'ENABLE_MODULE_RECOVERY', + 'ENABLE_MODULE_SCHNORRSIG', + 'ENABLE_MODULE_EXTRAKEYS', + 'ENABLE_MODULE_ECDH', + ] + SOURCE_MOD_SECP256K1_ZKP = [ + 'vendor/secp256k1-zkp/src/secp256k1.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult_gen.c', + 'vendor/secp256k1-zkp/src/asm/field_10x26_arm.s' + ] + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/zkp_context.c', + 'vendor/trezor-crypto/zkp_ecdsa.c', + 'vendor/trezor-crypto/zkp_bip340.c', + ] + +# AES-GCM +if FEATURE_FLAGS["AES_GCM"]: + CPPDEFINES_MOD += [ + 'USE_AES_GCM', + 'AES_VAR', + ] + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/aes/gf128mul.c', + 'vendor/trezor-crypto/aes/aesgcm.c', + ] + +SOURCE_MOD += [ +# 'embed/lib/buffers.c', +# 'embed/lib/colors.c', +# 'embed/lib/display_utils.c', + 'embed/lib/error_handling.c', + 'embed/lib/fonts/font_bitmap.c', +# 'embed/lib/fonts/fonts.c', + 'embed/lib/gfx_color.c', + 'embed/lib/gfx_bitblt_rgb565.c', + 'embed/lib/gfx_bitblt_rgba8888.c', + 'embed/lib/gfx_bitblt_mono8.c', + 'embed/lib/image.c', + 'embed/lib/mini_printf.c', + 'embed/lib/terminal.c', + 'embed/lib/translations.c', + 'embed/lib/unit_variant.c', + 'embed/extmod/modtrezorcrypto/rand.c', +] + +if NEW_RENDERING: + CPPDEFINES_MOD += ['NEW_RENDERING'] + SOURCE_MOD += [ + 'embed/lib/gfx_draw.c', + ] +else: + SOURCE_MOD += [ + 'embed/lib/display_draw.c', + ] + + +CPPDEFINES_MOD += [ + 'TREZOR_UI2', + 'TRANSLATIONS', +] + +if TREZOR_MODEL not in ('1', ): + CPPDEFINES_MOD += [ + # 'FANCY_FATAL_ERROR', + ] + +CPPDEFINES_MOD += ['USE_SVC_SHUTDOWN'] + +if FEATURE_FLAGS["RDI"]: + CPPDEFINES_MOD += ['RDI'] + +if FEATURE_FLAGS["SYSTEM_VIEW"]: + SOURCE_FIRMWARE += [ + 'embed/segger/SEGGER/SEGGER_SYSVIEW_Config_NoOS.c', + 'embed/segger/SEGGER/SEGGER_SYSVIEW.c', + 'embed/segger/SEGGER/SEGGER_RTT.c', + 'embed/segger/SEGGER/SEGGER_RTT_ASM_ARMv7M.S', + 'embed/segger/SEGGER/Syscalls/SEGGER_RTT_Syscalls_GCC.c', + 'embed/firmware/systemview.c', + ] + CPPPATH_MOD += [ + 'embed/segger/SEGGER/', + 'embed/segger/Config/', + ] + CPPDEFINES_MOD += ['SYSTEM_VIEW'] + CCFLAGS_MOD += '-DSYSTEM_VIEW ' + +TRANSLATION_DATA = [ + "translations/en.json", + "translations/order.json", +] + +if THP: + CPPDEFINES_MOD += ['USE_THP'] + SOURCE_MOD += [ + 'vendor/trezor-crypto/elligator2.c', + ] + +# fonts +tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('DEMIBOLD', FONT_DEMIBOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('MONO', FONT_MONO, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BIG', FONT_BIG, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('NORMAL_UPPER', FONT_NORMAL_UPPER, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BOLD_UPPER', FONT_BOLD_UPPER, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('SUB', FONT_SUB, CPPDEFINES_MOD, SOURCE_MOD) + +env = Environment( + ENV=os.environ, + CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODUCTION={int(PRODUCTION)} -DPYOPT={PYOPT} -DBOOTLOADER_QA={int(BOOTLOADER_QA)} -DBITCOIN_ONLY={BITCOIN_ONLY}", + CPPDEFINES_IMPLICIT=[] + ) + +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/kernel/header.S', + 'embed/kernel/main.c', + f'embed/kernel/startup_{FILE_SUFFIX}.S', +] + + +if TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + UI_LAYOUT = 'UI_LAYOUT_TT' + ui_layout_feature = 'model_tt' +elif TREZOR_MODEL in ('1', 'R'): + UI_LAYOUT = 'UI_LAYOUT_TR' + ui_layout_feature = 'model_tr' +elif TREZOR_MODEL in ('T3T1',): + UI_LAYOUT = 'UI_LAYOUT_MERCURY' + ui_layout_feature = 'model_mercury' +else: + raise ValueError('Unknown Trezor model') + +if 'sd_card' in FEATURES_AVAILABLE: + SDCARD = True +else: + SDCARD = False + +env.Replace( + CAT='cat', + DD='dd', + CP='cp', + SED='sed', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', ) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL,) + +if TREZOR_MODEL in ('1',): + LD_VARIANT = '' if EVERYTHING else '_min' +else: + LD_VARIANT = '' + +ALLPATHS = [ + '.', + 'embed/firmware', + 'embed/lib', + 'embed/models', + 'embed/trezorhal', + ] + CPPPATH_MOD + PATH_HAL + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-Os'), + CCFLAGS='$COPT ' + '-g3 ' + '-nostdlib ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -fno-common ' + '-fsingle-precision-constant -fdata-sections -ffunction-sections ' + '-ffreestanding ' + '-fstack-protector-all ' + + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, + LINKFLAGS='-T embed/kernel/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/kernel/kernel.map -Wl,--warn-common' % LD_VARIANT, + CPPPATH=ALLPATHS, + CPPDEFINES=[ + 'FIRMWARE', + 'TREZOR_MODEL_'+TREZOR_MODEL, + 'USE_HAL_DRIVER', + 'ARM_USER_MODE', + UI_LAYOUT, + ] + CPPDEFINES_MOD + CPPDEFINES_HAL, + ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], + ASPPFLAGS='$CFLAGS $CCFLAGS', + ) + +env.Replace( + HEADERTOOL='headertool', + PYTHON='python', + MAKEVERSIONHDR='$PYTHON vendor/micropython/py/makeversionhdr.py', + MAKEMODULEDEFS='$PYTHON vendor/micropython/py/makemoduledefs.py', + MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', +) + + +# +# Program objects +# + +source_files = SOURCE_MOD + SOURCE_MOD_CRYPTO + SOURCE_FIRMWARE + SOURCE_HAL +obj_program = [] +obj_program.extend(env.Object(source=SOURCE_MOD)) +obj_program.extend(env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-auto-var-init=zero')) +if FEATURE_FLAGS["SECP256K1_ZKP"]: + obj_program.extend(env.Object(source=SOURCE_MOD_SECP256K1_ZKP, CCFLAGS='$CCFLAGS -Wno-unused-function')) + source_files.extend(SOURCE_MOD_SECP256K1_ZKP) +obj_program.extend(env.Object(source=SOURCE_FIRMWARE)) +obj_program.extend(env.Object(source=SOURCE_HAL)) + +env.Replace( + ALLSOURCES=source_files, + ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'] + env['CPPDEFINES_IMPLICIT'] + [f"PRODUCTION={int(PRODUCTION)}", f"BOOTLOADER_QA={int(BOOTLOADER_QA)}", f"PYOPT={PYOPT}", f"BITCOIN_ONLY={BITCOIN_ONLY}"])) + + +cmake_gen = env.Command( + target='CMakeLists.txt', + source='', + action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', +) + +MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) +BOOTLOADER_SUFFIX = MODEL_IDENTIFIER +if BOOTLOADER_QA: + BOOTLOADER_SUFFIX += '_qa' + +# select vendor header +if BOOTLOADER_QA or BOOTLOADER_DEVEL: + vendor = "dev_DO_NOT_SIGN_signed_dev" +elif not PRODUCTION: + vendor = "unsafe_signed_prod" +else: + if TREZOR_MODEL in ('T',): + vendor = "satoshilabs_signed_prod" + elif BITCOIN_ONLY == '1': + vendor = "trezor_btconly_signed_prod" + else: + vendor = "trezor_signed_prod" + +VENDORHEADER = f'embed/models/{MODEL_IDENTIFIER}/vendorheader/vendorheader_{vendor}.bin' + + +if TREZOR_MODEL not in ('1',): + obj_program.extend( + env.Command( + target='embed/kernel/vendorheader.o', + source=VENDORHEADER, + action='$OBJCOPY -I binary -O elf32-littlearm -B arm' + ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' + ' $SOURCE $TARGET', )) + +if False: # TREZOR_MODEL not in ('DISC1', 'DISC2'): + tools.embed_binary( + obj_program, + env, + 'bootloader', + 'embed/firmware/bootloaders/bootloader.o', + f'embed/firmware/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin', + ) + + +program_elf = env.Command( + target='kernel.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', +) + +if CMAKELISTS != 0: + env.Depends(program_elf, cmake_gen) + +BINARY_NAME = f"build/kernel/kernel-{models.get_model_identifier(TREZOR_MODEL)}" +if not EVERYTHING: + BINARY_NAME += "-btconly" +BINARY_NAME += "-" + tools.get_version('embed/kernel/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + + +if TREZOR_MODEL in ('1'): + action_bin=[ + '$OBJCOPY -O binary -j .header -j .flash -j .data -j .confidential $SOURCE $TARGET', + '../legacy/bootloader/firmware_sign.py -f $TARGET', + '$CP $TARGET ' + BINARY_NAME, + ] +else: + if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', + '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', + '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', + '$CP $TARGET ' + BINARY_NAME, + ] + elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$CP $TARGET ' + BINARY_NAME, + ] + else: + raise Exception("Unknown MCU") + +program_bin = env.Command( + target='kernel.bin', + source=program_elf, + action=action_bin, +) diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index 91c9f5bf2b5..3ae2a8c825c 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -29,6 +29,7 @@ if NEW_RENDERING: CCFLAGS_MOD = '' CPPPATH_MOD = [] CPPDEFINES_MOD = [ + 'KERNEL_MODE', 'AES_128', 'USE_INSECURE_PRNG', ] diff --git a/core/SConscript.reflash b/core/SConscript.reflash index 1567744f8fa..481450e22ab 100644 --- a/core/SConscript.reflash +++ b/core/SConscript.reflash @@ -61,6 +61,10 @@ elif TREZOR_MODEL in ('T3T1',): FONT_BOLD_UPPER=None FONT_SUB=None +CPPDEFINES_MOD += [ + 'KERNEL_MODE', +] + # modtrezorcrypto CPPPATH_MOD += [ 'vendor/trezor-crypto', diff --git a/core/SConscript.unix b/core/SConscript.unix index 728ebc5d264..43cf4936099 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -94,6 +94,7 @@ CPPPATH_MOD += [ 'vendor/trezor-crypto', ] CPPDEFINES_MOD += [ + 'KERNEL_MODE', 'AES_128', 'AES_192', 'USE_INSECURE_PRNG', @@ -420,6 +421,7 @@ SOURCE_MICROPYTHON = [ SOURCE_UNIX = [ 'embed/trezorhal/unix/bootutils.c', 'embed/trezorhal/unix/common.c', + 'embed/trezorhal/unix/entropy.c', 'embed/trezorhal/unix/flash_otp.c', 'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/fwutils.c', diff --git a/core/SConstruct b/core/SConstruct index d4c5aae455b..4bca3b7423a 100644 --- a/core/SConstruct +++ b/core/SConstruct @@ -7,6 +7,8 @@ SConscript('SConscript.boardloader', variant_dir='build/boardloader', duplicate= SConscript('SConscript.bootloader', variant_dir='build/bootloader', duplicate=False) SConscript('SConscript.bootloader_ci', variant_dir='build/bootloader_ci', duplicate=False) SConscript('SConscript.bootloader_emu', variant_dir='build/bootloader_emu', duplicate=False) +SConscript('SConscript.kernel', variant_dir='build/kernel', duplicate=False) +SConscript('SConscript.coreapp', variant_dir='build/coreapp', duplicate=False) SConscript('SConscript.firmware', variant_dir='build/firmware', duplicate=False) SConscript('SConscript.prodtest', variant_dir='build/prodtest', duplicate=False) SConscript('SConscript.reflash', variant_dir='build/reflash', duplicate=False) diff --git a/core/embed/coreapp/header.S b/core/embed/coreapp/header.S new file mode 100644 index 00000000000..3531e239553 --- /dev/null +++ b/core/embed/coreapp/header.S @@ -0,0 +1,54 @@ + .syntax unified + +#include "version.h" + + .section .header, "a" + + .type g_header, %object + .size g_header, .-g_header + +// Firmware header for both Trezor One and Trezor T. +// Trezor One must have bootloader version >= 1.8.0 (before that version the hdrlen used to be reset vector) + +g_header: + .byte 'T','R','Z','F' // magic + .word g_header_end - g_header // hdrlen +#ifdef TREZOR_MODEL_T + .word 0 // expiry +#else + .word 1 // expiry +#endif + .word _codelen // codelen + .byte VERSION_MAJOR // vmajor + .byte VERSION_MINOR // vminor + .byte VERSION_PATCH // vpatch + .byte VERSION_BUILD // vbuild + .byte FIX_VERSION_MAJOR // fix_vmajor + .byte FIX_VERSION_MINOR // fix_vminor + .byte FIX_VERSION_PATCH // fix_vpatch + .byte FIX_VERSION_BUILD // fix_vbuild + .word HW_MODEL // type of the designated hardware + .byte HW_REVISION // revision of the designated hardware + .byte VERSION_MONOTONIC // monotonic version of the binary + . = . + 2 // reserved + . = . + 512 // hash1 ... hash16 + +#if !defined TREZOR_MODEL_1 +// trezor-core header style + . = . + 415 // reserved + .byte 0 // sigmask + . = . + 64 // sig +#else +// model 1 compatibility header + . = . + 64 // sig1 + . = . + 64 // sig2 + . = . + 64 // sig3 + .byte 0 // sigindex1 + .byte 0 // sigindex2 + .byte 0 // sigindex3 + . = . + 220 // reserved + . = . + 65 // reserved +#endif + +g_header_end: + diff --git a/core/embed/coreapp/main.c b/core/embed/coreapp/main.c new file mode 100644 index 00000000000..8ea6f269bb1 --- /dev/null +++ b/core/embed/coreapp/main.c @@ -0,0 +1,105 @@ +/* + * 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 STM32_HAL_H + +#include +#include +#include + +#include "py/builtin.h" +#include "py/compile.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/nlr.h" +#include "py/repl.h" +#include "py/runtime.h" +#include "py/stackctrl.h" +#include "shared/runtime/pyexec.h" + +#include "ports/stm32/gccollect.h" +#include "ports/stm32/pendsv.h" + +#include "error_handling.h" +#include "rust_ui_common.h" +#include "secbool.h" + +#ifdef USE_SECP256K1_ZKP +#include "zkp_context.h" +#endif + +int main(void) { + screen_boot_stage_2(); + +#ifdef USE_SECP256K1_ZKP + ensure(sectrue * (zkp_context_init() == 0), NULL); +#endif + + 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); + +#if MICROPY_ENABLE_PYSTACK + static mp_obj_t pystack[1024]; + mp_pystack_init(pystack, &pystack[MP_ARRAY_SIZE(pystack)]); +#endif + + // GC init + printf("CORE: Starting GC\n"); + gc_init(&_heap_start, &_heap_end); + + // Interpreter init + printf("CORE: Starting interpreter\n"); + mp_init(); + mp_obj_list_init(mp_sys_argv, 0); + mp_obj_list_init(mp_sys_path, 0); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen)); + + // Execute the main script + printf("CORE: Executing main script\n"); + pyexec_frozen_module("main.py"); + + // Clean up + printf("CORE: Main script finished, cleaning up\n"); + mp_deinit(); + + // Python code shouldn't ever exit, avoid black screen if it does + error_shutdown("(PE)"); + + return 0; +} + +// MicroPython default exception handler + +void __attribute__((noreturn)) nlr_jump_fail(void *val) { + error_shutdown("(UE)"); +} + +// MicroPython builtin stubs + +mp_import_stat_t mp_import_stat(const char *path) { + return MP_IMPORT_STAT_NO_EXIST; +} + +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); diff --git a/core/embed/coreapp/memory_DISC1.ld b/core/embed/coreapp/memory_DISC1.ld new file mode 120000 index 00000000000..3f68ec99f6c --- /dev/null +++ b/core/embed/coreapp/memory_DISC1.ld @@ -0,0 +1 @@ +memory_T.ld \ No newline at end of file diff --git a/core/embed/coreapp/memory_DISC2.ld b/core/embed/coreapp/memory_DISC2.ld new file mode 100644 index 00000000000..ae6d1272926 --- /dev/null +++ b/core/embed/coreapp/memory_DISC2.ld @@ -0,0 +1,130 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 + SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K + SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K + SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K + SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 + SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_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); + +/* 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 */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); +sram3_start = ORIGIN(SRAM3); +sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); +sram4_start = ORIGIN(SRAM4); +sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +sram5_start = ORIGIN(SRAM5); +sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); +sram6_start = ORIGIN(SRAM6); +sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash : ALIGN(1024) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .data_ccm : ALIGN(4) { + *(.no_dma_buffers*); + . = ALIGN(4); + *(.buf*); + . = ALIGN(4); + } >SRAM1 + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ + } >SRAM1 + + .stack : ALIGN(8) { + . = 16K; /* Overflow causes UsageFault */ + } >SRAM2 + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .fb1 : ALIGN(4) { + __fb_start = .; + *(.fb1*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + . = ALIGN(4); + } >SRAM3 + + .fb2 : ALIGN(4) { + *(.fb2*); + __fb_end = .; + . = ALIGN(4); + } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/coreapp/memory_R.ld b/core/embed/coreapp/memory_R.ld new file mode 120000 index 00000000000..3f68ec99f6c --- /dev/null +++ b/core/embed/coreapp/memory_R.ld @@ -0,0 +1 @@ +memory_T.ld \ No newline at end of file diff --git a/core/embed/coreapp/memory_T.ld b/core/embed/coreapp/memory_T.ld new file mode 100644 index 00000000000..9affc00a900 --- /dev/null +++ b/core/embed/coreapp/memory_T.ld @@ -0,0 +1,109 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x08040000, LENGTH = 768K + FLASH2 (r) : ORIGIN = 0x08120000, LENGTH = 896K + CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x1000FF00, LENGTH = 0x100 + SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K +} + +main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM); +_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); + +/* used by the startup code to wipe memory */ +ccmram_start = ORIGIN(CCMRAM); +ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +/* used by the startup code to wipe memory */ +sram_start = ORIGIN(SRAM); +sram_end = ORIGIN(SRAM) + LENGTH(SRAM); +_ram_start = sram_start; +_ram_end = sram_end; + +_codelen = LENGTH(FLASH) - SIZEOF(.vendorheader) - SIZEOF(.header) + SIZEOF(.flash2); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash2 : ALIGN(512) { + build/firmware/frozen_mpy.o(.rodata*); + build/firmware/vendor/secp256k1-zkp/src/secp256k1.o(.rodata*); + build/firmware/vendor/secp256k1-zkp/src/precomputed_ecmult.o(.rodata*); + build/firmware/vendor/secp256k1-zkp/src/precomputed_ecmult_gen.o(.rodata*); + build/firmware/vendor/trezor-crypto/aes/aestab.o(.rodata*); + . = ALIGN(4); + */libtrezor_lib.a:(.text*); + . = ALIGN(4); + */libtrezor_lib.a:(.rodata*); + . = ALIGN(512); + } >FLASH2 AT>FLASH2 + + .flash : ALIGN(512) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .stack : ALIGN(8) { + . = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */ + } >SRAM + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM AT>FLASH + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(sram_end); /* this explicitly sets the end of the heap */ + } >SRAM + + .data_ccm : ALIGN(4) { + *(.no_dma_buffers*); + . = ALIGN(4); + } >CCMRAM + + .boot_args : ALIGN(8) { + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/coreapp/memory_T3B1.ld b/core/embed/coreapp/memory_T3B1.ld new file mode 120000 index 00000000000..b5bfd3715e0 --- /dev/null +++ b/core/embed/coreapp/memory_T3B1.ld @@ -0,0 +1 @@ +memory_T3T1.ld \ No newline at end of file diff --git a/core/embed/coreapp/memory_T3T1.ld b/core/embed/coreapp/memory_T3T1.ld new file mode 100644 index 00000000000..3fc9d3fae2c --- /dev/null +++ b/core/embed/coreapp/memory_T3T1.ld @@ -0,0 +1,115 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x0C050000 + 0x28000, LENGTH = 1664K - 0x28000 + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 16K + BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 + SRAM2 (wal) : ORIGIN = 0x30030000 + 8K, LENGTH = 64K - 8K + SRAM3 (wal) : ORIGIN = 0x30040000 + 0x38400, LENGTH = 512K - 0x38400 + SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_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 */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); +sram3_start = ORIGIN(SRAM3); +sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); +sram4_start = ORIGIN(SRAM4); +sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +sram5_start = ORIGIN(SRAM5); +sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); +sram6_start = ORIGIN(SRAM6); +sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash : ALIGN(512) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.no_dma_buffers*); + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .stack : ALIGN(8) { + . = 32K; /* Overflow causes UsageFault */ + } >SRAM2 + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM3 + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(sram3_end); /* this explicitly sets the end of the heap */ + } >SRAM3 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/coreapp/mpconfigport.h b/core/embed/coreapp/mpconfigport.h new file mode 100644 index 00000000000..0e9e990b1b6 --- /dev/null +++ b/core/embed/coreapp/mpconfigport.h @@ -0,0 +1,224 @@ +// clang-format off + +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Options to control how MicroPython is built for this port, +// overriding defaults in py/mpconfig.h. + +#pragma once +#ifndef __INCLUDED_MPCONFIGPORT_H +#define __INCLUDED_MPCONFIGPORT_H + +// frozen modules +#define MICROPY_MODULE_FROZEN_MPY (1) +#define MICROPY_QSTR_EXTRA_POOL (mp_qstr_frozen_const_pool) + +// memory allocation policies +#define MICROPY_ALLOC_PATH_MAX (128) +#define MICROPY_ENABLE_PYSTACK (1) +#define MICROPY_LOADED_MODULES_DICT_SIZE (160) + +// emitters +#define MICROPY_PERSISTENT_CODE_LOAD (0) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) + +// compiler configuration +#define MICROPY_ENABLE_COMPILER (0) +#define MICROPY_COMP_MODULE_CONST (1) +#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) +#define MICROPY_COMP_RETURN_IF_EXPR (1) + +// optimisations +#define MICROPY_OPT_COMPUTED_GOTO (1) +#define MICROPY_OPT_MPZ_BITWISE (1) +#define MICROPY_OPT_MATH_FACTORIAL (0) +#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (1) +#define MICROPY_OPT_MAP_LOOKUP_CACHE (1) + +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) + +// Python internal features +#define MICROPY_READER_VFS (0) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_STACK_CHECK (1) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) +#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_EMACS_KEYS (1) +#define MICROPY_REPL_AUTO_INDENT (1) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_ENABLE_SOURCE_LINE (1) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_STREAMS_NON_BLOCK (1) +#define MICROPY_MODULE_WEAK_LINKS (1) +#define MICROPY_CAN_OVERRIDE_BUILTINS (0) +#define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_ENABLE_SCHEDULER (0) +#define MICROPY_SCHEDULER_DEPTH (0) +#define MICROPY_VFS (0) + +// control over Python builtins +#define MICROPY_PY_FUNCTION_ATTRS (1) +#define MICROPY_PY_DESCRIPTORS (0) +#define MICROPY_PY_DELATTR_SETATTR (0) +#define MICROPY_PY_BUILTINS_STR_UNICODE (1) +#define MICROPY_PY_BUILTINS_STR_CENTER (1) +#define MICROPY_PY_BUILTINS_STR_PARTITION (1) +#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_BUILTINS_FROZENSET (0) +#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) +#define MICROPY_PY_BUILTINS_SLICE_INDICES (0) +#define MICROPY_PY_BUILTINS_ROUND_INT (0) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) +#define MICROPY_PY_ALL_SPECIAL_METHODS (0) +#define MICROPY_PY_BUILTINS_COMPILE (MICROPY_ENABLE_COMPILER) +#define MICROPY_PY_BUILTINS_EXECFILE (MICROPY_ENABLE_COMPILER) +#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) +#define MICROPY_PY_BUILTINS_INPUT (0) +#define MICROPY_PY_BUILTINS_POW3 (0) +#define MICROPY_PY_BUILTINS_HELP (0) +#define MICROPY_PY_BUILTINS_HELP_TEXT stm32_help_text +#define MICROPY_PY_BUILTINS_HELP_MODULES (0) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) +#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_PY_COLLECTIONS (0) +#define MICROPY_PY_COLLECTIONS_DEQUE (0) +#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) +#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) +#define MICROPY_PY_MATH_ISCLOSE (0) +#define MICROPY_PY_MATH_FACTORIAL (0) +#define MICROPY_PY_CMATH (0) +#define MICROPY_PY_IO (0) +#define MICROPY_PY_IO_IOBASE (0) +#define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT) // because mp_type_fileio/textio point to fatfs impl +#define MICROPY_PY_SYS_MAXSIZE (0) +#define MICROPY_PY_SYS_EXIT (0) +#define MICROPY_PY_SYS_STDFILES (0) +#define MICROPY_PY_SYS_STDIO_BUFFER (0) +#define MICROPY_PY_SYS_PLATFORM "trezor" +#define MICROPY_PY_UERRNO (0) +#define MICROPY_PY_THREAD (0) +#define MICROPY_PY_FSTRINGS (1) + +// extended modules +#define MICROPY_PY_UCTYPES (1) +#define MICROPY_PY_UZLIB (0) +#define MICROPY_PY_UJSON (0) +#define MICROPY_PY_UOS (0) +#define MICROPY_PY_URE (0) +#define MICROPY_PY_URE_SUB (0) +#define MICROPY_PY_UHEAPQ (0) +#define MICROPY_PY_UHASHLIB (0) +#define MICROPY_PY_UHASHLIB_MD5 (0) +#define MICROPY_PY_UHASHLIB_SHA1 (0) +#define MICROPY_PY_UCRYPTOLIB (0) +#define MICROPY_PY_UBINASCII (1) +#define MICROPY_PY_UBINASCII_CRC32 (0) +#define MICROPY_PY_URANDOM (0) +#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) +#define MICROPY_PY_USELECT (0) +#define MICROPY_PY_UTIME (1) +#define MICROPY_PY_UTIMEQ (1) +#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_OS_DUPTERM (0) +#define MICROPY_PY_LWIP_SOCK_RAW (0) +#define MICROPY_PY_MACHINE (0) +#define MICROPY_PY_UWEBSOCKET (0) +#define MICROPY_PY_WEBREPL (0) +#define MICROPY_PY_FRAMEBUF (0) +#define MICROPY_PY_USOCKET (0) +#define MICROPY_PY_NETWORK (0) + +#define MICROPY_PY_TREZORCONFIG (1) +#define MICROPY_PY_TREZORCRYPTO (1) +#define MICROPY_PY_TREZORIO (1) +#define MICROPY_PY_TREZORUI (1) +#define MICROPY_PY_TREZORUTILS (1) +#define MICROPY_PY_TREZORPROTO (1) +#define MICROPY_PY_TREZORTRANSLATE (1) +#define MICROPY_PY_TREZORUI2 (1) + +#ifdef SYSTEM_VIEW +#define MP_PLAT_PRINT_STRN(str, len) segger_print(str, len) +// uncomment DEST_RTT and comment DEST_SYSTEMVIEW +// if you want to print to RTT instead of SystemView +// OpenOCD supports only the RTT output method +// #define SYSTEMVIEW_DEST_RTT (1) +#define SYSTEMVIEW_DEST_SYSTEMVIEW (1) +#endif + +#define MP_STATE_PORT MP_STATE_VM + +// ============= this ends common config section =================== + + +// type definitions for the specific machine + +#define BYTES_PER_WORD (4) + +#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) + +#define MP_SSIZE_MAX (0x0fffffff) + +typedef int mp_int_t; // must be pointer size +typedef unsigned int mp_uint_t; // must be pointer size +typedef long mp_off_t; + +#include "irq.h" + +#define MICROPY_BEGIN_ATOMIC_SECTION() irq_lock() +#define MICROPY_END_ATOMIC_SECTION(state) irq_unlock(state) +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(bool); \ + mp_handle_pending(true); \ + __WFI(); \ + } while (0); + +#define MICROPY_HW_BOARD_NAME "TREZORv2" +#define MICROPY_HW_MCU_NAME "STM32F427xx" +#define MICROPY_HW_HAS_SDCARD 1 + +// There is no classical C heap in bare-metal ports, only Python +// garbage-collected heap. For completeness, emulate C heap via +// GC heap. Note that MicroPython core never uses malloc() and friends, +// so these defines are mostly to help extension module writers. +#define malloc(n) m_malloc(n) +#define free(p) m_free(p) +#define realloc(p, n) m_realloc(p, n) + +#define MICROPY_PORT_ROOT_POINTERS \ + mp_obj_t trezorconfig_ui_wait_callback; \ + +// We need to provide a declaration/definition of alloca() +#include + +#endif // __INCLUDED_MPCONFIGPORT_H diff --git a/core/embed/coreapp/mphalport.c b/core/embed/coreapp/mphalport.c new file mode 100644 index 00000000000..9509ca37d55 --- /dev/null +++ b/core/embed/coreapp/mphalport.c @@ -0,0 +1,57 @@ +/* + * 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 "common.h" +#include "py/mphal.h" + +#include "systick.h" +#include "usb.h" + +static int vcp_iface_num = -1; + +int mp_hal_stdin_rx_chr(void) { + ensure(sectrue * (vcp_iface_num >= 0), "vcp stdio is not configured"); + uint8_t c = 0; + int r = usb_vcp_read_blocking(vcp_iface_num, &c, 1, -1); + (void)r; + return c; +} + +void mp_hal_stdout_tx_strn(const char *str, size_t len) { + if (vcp_iface_num >= 0) { + // The write timeout is set to 0, because otherwise when the VCP receive + // buffer on the host gets full, the timeout will block device operation. + int r = usb_vcp_write_blocking(vcp_iface_num, (const uint8_t *)str, len, 0); + (void)r; + } +} + +void mp_hal_set_vcp_iface(int iface_num) { vcp_iface_num = iface_num; } + +// Dummy implementation required by ports/stm32/gccollect.c. +// The normal version requires MICROPY_ENABLE_SCHEDULER which we don't use. +void soft_timer_gc_mark_all(void) {} + +void mp_hal_delay_ms(mp_uint_t Delay) { systick_delay_ms(Delay); } + +void mp_hal_delay_us(mp_uint_t usec) { systick_delay_us(usec); } + +mp_uint_t mp_hal_ticks_ms(void) { return systick_ms(); } + +mp_uint_t mp_hal_ticks_us(void) { return systick_ms() * 1000; } diff --git a/core/embed/coreapp/mphalport.h b/core/embed/coreapp/mphalport.h new file mode 100644 index 00000000000..8954eec6312 --- /dev/null +++ b/core/embed/coreapp/mphalport.h @@ -0,0 +1,24 @@ +/* + * 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 "shared/runtime/interrupt_char.h" + +static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; } + +void mp_hal_set_vcp_iface(int iface_num); diff --git a/core/embed/coreapp/nlrthumb.c b/core/embed/coreapp/nlrthumb.c new file mode 100644 index 00000000000..8fdaba88b20 --- /dev/null +++ b/core/embed/coreapp/nlrthumb.c @@ -0,0 +1,166 @@ +// clang-format off + +/* + * 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 . + */ + +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma GCC optimize("no-stack-protector") // applies to all functions in this file + +#include "py/mpstate.h" +#include "py/nlr.h" + +#if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) + +#undef nlr_push + +// We only need the functions here if we are on arm/thumb, and we are not +// using setjmp/longjmp. +// +// For reference, arm/thumb callee save regs are: +// r4-r11, r13=sp + +__attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { + + __asm volatile ( + "str r4, [r0, #12] \n" // store r4 into nlr_buf + "str r5, [r0, #16] \n" // store r5 into nlr_buf + "str r6, [r0, #20] \n" // store r6 into nlr_buf + "str r7, [r0, #24] \n" // store r7 into nlr_buf + +#if defined(__ARM_ARCH_6M__) + "mov r1, r8 \n" + "str r1, [r0, #28] \n" // store r8 into nlr_buf + "mov r1, r9 \n" + "str r1, [r0, #32] \n" // store r9 into nlr_buf + "mov r1, r10 \n" + "str r1, [r0, #36] \n" // store r10 into nlr_buf + "mov r1, r11 \n" + "str r1, [r0, #40] \n" // store r11 into nlr_buf + "mov r1, r13 \n" + "str r1, [r0, #44] \n" // store r13=sp into nlr_buf + "mov r1, lr \n" + "str r1, [r0, #8] \n" // store lr into nlr_buf +#else + "str r8, [r0, #28] \n" // store r8 into nlr_buf + "str r9, [r0, #32] \n" // store r9 into nlr_buf + "str r10, [r0, #36] \n" // store r10 into nlr_buf + "str r11, [r0, #40] \n" // store r11 into nlr_buf + "str r13, [r0, #44] \n" // store r13=sp into nlr_buf + "str lr, [r0, #8] \n" // store lr into nlr_buf +#endif + +#if defined(__ARM_ARCH_6M__) + "ldr r1, nlr_push_tail_var \n" + "bx r1 \n" // do the rest in C + ".align 2 \n" + "nlr_push_tail_var: .word nlr_push_tail \n" +#else + "b nlr_push_tail \n" // do the rest in C +#endif + ); + + return 0; // needed to silence compiler warning +} + +__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) { + nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); + nlr->prev = *top; + *top = nlr; + return 0; // normal return +} + +void nlr_pop(void) { + nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); + *top = (*top)->prev; +} + +NORETURN __attribute__((naked)) void nlr_jump(void *val) { + nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); + nlr_buf_t *top = *top_ptr; + if (top == NULL) { + nlr_jump_fail(val); + } + + top->ret_val = val; + *top_ptr = top->prev; + + __asm volatile ( + "mov r0, %0 \n" // r0 points to nlr_buf + "ldr r4, [r0, #12] \n" // load r4 from nlr_buf + "ldr r5, [r0, #16] \n" // load r5 from nlr_buf + "ldr r6, [r0, #20] \n" // load r6 from nlr_buf + "ldr r7, [r0, #24] \n" // load r7 from nlr_buf + +#if defined(__ARM_ARCH_6M__) + "ldr r1, [r0, #28] \n" // load r8 from nlr_buf + "mov r8, r1 \n" + "ldr r1, [r0, #32] \n" // load r9 from nlr_buf + "mov r9, r1 \n" + "ldr r1, [r0, #36] \n" // load r10 from nlr_buf + "mov r10, r1 \n" + "ldr r1, [r0, #40] \n" // load r11 from nlr_buf + "mov r11, r1 \n" + "ldr r1, [r0, #44] \n" // load r13=sp from nlr_buf + "mov r13, r1 \n" + "ldr r1, [r0, #8] \n" // load lr from nlr_buf + "mov lr, r1 \n" +#else + "ldr r8, [r0, #28] \n" // load r8 from nlr_buf + "ldr r9, [r0, #32] \n" // load r9 from nlr_buf + "ldr r10, [r0, #36] \n" // load r10 from nlr_buf + "ldr r11, [r0, #40] \n" // load r11 from nlr_buf + "ldr r13, [r0, #44] \n" // load r13=sp from nlr_buf + "ldr lr, [r0, #8] \n" // load lr from nlr_buf +#endif + "movs r0, #1 \n" // return 1, non-local return + "bx lr \n" // return + : // output operands + : "r"(top) // input operands + : // clobbered registers + ); + + for (;;); // needed to silence compiler warning +} + +#endif // (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) diff --git a/core/embed/coreapp/startup_stm32f4.S b/core/embed/coreapp/startup_stm32f4.S new file mode 100644 index 00000000000..f1a8a6784e9 --- /dev/null +++ b/core/embed/coreapp/startup_stm32f4.S @@ -0,0 +1,42 @@ + .syntax unified + + .text + + .global reset_handler + .type reset_handler, STT_FUNC +reset_handler: + + // setup environment for subsequent stage of code + ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM + ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM + ldr r2, =0 // r2 - the word-sized value to be written + bl memset_reg + + ldr r0, =boot_args_start // r0 - point to beginning of BOOT_ARGS + ldr r1, =boot_args_end // r1 - point to byte after the end of BOOT_ARGS + ldr r2, =0 // r2 - the word-sized value to be written + bl memset_reg + + ldr r0, =sram_start // r0 - point to beginning of SRAM + ldr r1, =sram_end // r1 - point to byte after the end of SRAM + ldr r2, =0 // r2 - the word-sized value to be written + 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] + + // enter the application code + bl main + + b secure_shutdown + + + .end diff --git a/core/embed/coreapp/startup_stm32u5.S b/core/embed/coreapp/startup_stm32u5.S new file mode 100644 index 00000000000..6d94c656d70 --- /dev/null +++ b/core/embed/coreapp/startup_stm32u5.S @@ -0,0 +1,58 @@ + .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 PSPLIM, r0 + + ldr r0, =bss_start + ldr r1, =bss_end + ldr r2, =0 + 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 secure_shutdown + + +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 + + + .end diff --git a/core/embed/coreapp/version.h b/core/embed/coreapp/version.h new file mode 100644 index 00000000000..b1b21300ce3 --- /dev/null +++ b/core/embed/coreapp/version.h @@ -0,0 +1,11 @@ +#define VERSION_MAJOR 2 +#define VERSION_MINOR 8 +#define VERSION_PATCH 2 +#define VERSION_BUILD 0 + +#define FIX_VERSION_MAJOR 2 +#define FIX_VERSION_MINOR 8 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 + +#define VERSION_MONOTONIC 1 diff --git a/core/embed/firmware/memory_T3T1.ld b/core/embed/firmware/memory_T3T1.ld index 35674f169d5..4e3a2a88cdf 100644 --- a/core/embed/firmware/memory_T3T1.ld +++ b/core/embed/firmware/memory_T3T1.ld @@ -100,7 +100,6 @@ SECTIONS { __fb_start = .; *(.fb1*); *(.fb2*); - *(.framebuffer_select*); __fb_end = .; . = ALIGN(4); } >SRAM3 diff --git a/core/embed/kernel/header.S b/core/embed/kernel/header.S new file mode 100644 index 00000000000..3531e239553 --- /dev/null +++ b/core/embed/kernel/header.S @@ -0,0 +1,54 @@ + .syntax unified + +#include "version.h" + + .section .header, "a" + + .type g_header, %object + .size g_header, .-g_header + +// Firmware header for both Trezor One and Trezor T. +// Trezor One must have bootloader version >= 1.8.0 (before that version the hdrlen used to be reset vector) + +g_header: + .byte 'T','R','Z','F' // magic + .word g_header_end - g_header // hdrlen +#ifdef TREZOR_MODEL_T + .word 0 // expiry +#else + .word 1 // expiry +#endif + .word _codelen // codelen + .byte VERSION_MAJOR // vmajor + .byte VERSION_MINOR // vminor + .byte VERSION_PATCH // vpatch + .byte VERSION_BUILD // vbuild + .byte FIX_VERSION_MAJOR // fix_vmajor + .byte FIX_VERSION_MINOR // fix_vminor + .byte FIX_VERSION_PATCH // fix_vpatch + .byte FIX_VERSION_BUILD // fix_vbuild + .word HW_MODEL // type of the designated hardware + .byte HW_REVISION // revision of the designated hardware + .byte VERSION_MONOTONIC // monotonic version of the binary + . = . + 2 // reserved + . = . + 512 // hash1 ... hash16 + +#if !defined TREZOR_MODEL_1 +// trezor-core header style + . = . + 415 // reserved + .byte 0 // sigmask + . = . + 64 // sig +#else +// model 1 compatibility header + . = . + 64 // sig1 + . = . + 64 // sig2 + . = . + 64 // sig3 + .byte 0 // sigindex1 + .byte 0 // sigindex2 + .byte 0 // sigindex3 + . = . + 220 // reserved + . = . + 65 // reserved +#endif + +g_header_end: + diff --git a/core/embed/kernel/main.c b/core/embed/kernel/main.c new file mode 100644 index 00000000000..4b3f97e3b5b --- /dev/null +++ b/core/embed/kernel/main.c @@ -0,0 +1,188 @@ +/* + * 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 STM32_HAL_H + +#include "image.h" +#include "irq.h" +#include "syscall.h" + +#include "board_capabilities.h" +#include "display.h" +#include "dma2d.h" +#include "entropy.h" +#include "fault_handlers.h" +#include "haptic.h" +#include "image.h" +#include "irq.h" +#include "memzero.h" +#include "mpu.h" +#include "optiga_commands.h" +#include "optiga_transport.h" +#include "random_delays.h" +#include "sdcard.h" +#include "secret.h" +#include "secure_aes.h" +#include "systick.h" +#include "systimer.h" +#include "tamper.h" +#include "touch.h" +#include "unit_variant.h" + +#ifdef USE_OPTIGA +#if !PYOPT +#include +#if 1 // color log +#define OPTIGA_LOG_FORMAT \ + "%" PRIu32 " \x1b[35moptiga\x1b[0m \x1b[32mDEBUG\x1b[0m %s: " +#else +#define OPTIGA_LOG_FORMAT "%" PRIu32 " optiga DEBUG %s: " +#endif +static void optiga_log_hex(const char *prefix, const uint8_t *data, + size_t data_size) { + printf(OPTIGA_LOG_FORMAT, hal_ticks_ms() * 1000, prefix); + for (size_t i = 0; i < data_size; i++) { + printf("%02x", data[i]); + } + printf("\n"); +} +#endif +#endif + +void drivers_init() { + syscall_init(); + + systick_init(); + systimer_init(); + + fault_handlers_init(); + + systick_delay_ms(10); + +#if defined TREZOR_MODEL_T + set_core_clock(CLOCK_180_MHZ); +#endif + +#ifdef STM32U5 + tamper_init(); +#endif + + rdi_init(); + +#ifdef RDI + rdi_start(); +#endif + +#ifdef SYSTEM_VIEW + enable_systemview(); +#endif + +#ifdef USE_HASH_PROCESSOR + hash_processor_init(); +#endif + +#ifdef USE_DMA2D + dma2d_init(); +#endif + + display_init(DISPLAY_RETAIN_CONTENT); + +#ifdef STM32U5 + check_oem_keys(); +#endif + + parse_boardloader_capabilities(); + + unit_variant_init(); + +#ifdef STM32U5 + secure_aes_init(); +#endif + +#ifdef USE_OPTIGA + uint8_t secret[SECRET_OPTIGA_KEY_LEN] = {0}; + secbool secret_ok = secret_optiga_get(secret); +#endif + + entropy_init(); + +#if PRODUCTION || BOOTLOADER_QA + // check_and_replace_bootloader(); +#endif + +#ifdef USE_BUTTON + button_init(); +#endif + +#ifdef USE_RGB_LED + rgb_led_init(); +#endif + +#ifdef USE_CONSUMPTION_MASK + consumption_mask_init(); +#endif + +#ifdef USE_TOUCH + touch_init(); +#endif + +#ifdef USE_SD_CARD + sdcard_init(); +#endif + +#ifdef USE_HAPTIC + haptic_init(); +#endif + +#ifdef USE_OPTIGA + +#if !PYOPT + // command log is relatively quiet so we enable it in debug builds + optiga_command_set_log_hex(optiga_log_hex); + // transport log can be spammy, uncomment if you want it: + // optiga_transport_set_log_hex(optiga_log_hex); +#endif + + optiga_init(); + if (sectrue == secret_ok) { + // If the shielded connection cannot be established, reset Optiga and + // continue without it. In this case, OID_KEY_FIDO and OID_KEY_DEV cannot be + // used, which means device and FIDO attestation will not work. + if (optiga_sec_chan_handshake(secret, sizeof(secret)) != OPTIGA_SUCCESS) { + optiga_soft_reset(); + } + } + memzero(secret, sizeof(secret)); + ensure(sectrue * (optiga_open_application() == OPTIGA_SUCCESS), + "Cannot initialize optiga."); + +#endif +} + +int main(void) { + mpu_init(); + + // Initialize hardware drivers + drivers_init(); + + // Start unprivileged application + start_unprivileged_app(); + + return 0; +} diff --git a/core/embed/kernel/memory_T3T1.ld b/core/embed/kernel/memory_T3T1.ld new file mode 100644 index 00000000000..f799bf49270 --- /dev/null +++ b/core/embed/kernel/memory_T3T1.ld @@ -0,0 +1,122 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 160K + SRAM1 (wal) : ORIGIN = 0x3002C000, LENGTH = 16K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 + SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 8K + SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 0x38400 + SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_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); + +/* 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 */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); +sram3_start = ORIGIN(SRAM3); +sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); +sram4_start = ORIGIN(SRAM4); +sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +sram5_start = ORIGIN(SRAM5); +sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); +sram6_start = ORIGIN(SRAM6); +sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash : ALIGN(512) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.no_dma_buffers*); + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .stack : ALIGN(8) { + . = 4K; /* Overflow causes UsageFault */ + } >SRAM2 + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .fb : ALIGN(4) { + __fb_start = .; + *(.fb1*); + *(.fb2*); + *(.framebuffer_select*); + __fb_end = .; + . = ALIGN(4); + } >SRAM3 + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM3 + + .heap : ALIGN(4) { + } >SRAM3 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/kernel/startup_stm32u5.S b/core/embed/kernel/startup_stm32u5.S new file mode 100644 index 00000000000..db9a204c319 --- /dev/null +++ b/core/embed/kernel/startup_stm32u5.S @@ -0,0 +1,72 @@ + .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, =sram1_start // r0 - point to beginning of SRAM + ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram2_start // r0 - point to beginning of SRAM + ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram4_start // r0 - point to beginning of SRAM + ldr r1, =sram4_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram6_start // r0 - point to beginning of SRAM + ldr r1, =sram6_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =boot_args_start // r0 - point to beginning of boot args + ldr r1, =boot_args_end // r1 - point to byte after the end of boot args + bl memset_reg + + ldr r0, =sram3_start // r0 - point to beginning of SRAM + ldr r1, =__fb_start // r1 - point to beginning of framebuffer + bl memset_reg + + ldr r0, =__fb_end // r0 - point to end of framebuffer + ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + 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/kernel/version.h b/core/embed/kernel/version.h new file mode 100644 index 00000000000..4a3ed90d599 --- /dev/null +++ b/core/embed/kernel/version.h @@ -0,0 +1,11 @@ +#define VERSION_MAJOR 2 +#define VERSION_MINOR 8 +#define VERSION_PATCH 1 +#define VERSION_BUILD 0 + +#define FIX_VERSION_MAJOR 2 +#define FIX_VERSION_MINOR 8 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 + +#define VERSION_MONOTONIC 1 diff --git a/core/embed/lib/sizedefs.h b/core/embed/lib/sizedefs.h index 9f8bb7a6c57..07889e1abcb 100644 --- a/core/embed/lib/sizedefs.h +++ b/core/embed/lib/sizedefs.h @@ -2,7 +2,10 @@ #define SIZEDEFS_H_ #define SIZE_2K (2 * 1024) +#define SIZE_3K (3 * 1024) +#define SIZE_8K (8 * 1024) #define SIZE_16K (16 * 1024) +#define SIZE_24K (24 * 1024) #define SIZE_48K (48 * 1024) #define SIZE_64K (64 * 1024) #define SIZE_128K (128 * 1024) diff --git a/core/embed/lib/translations.c b/core/embed/lib/translations.c index 191bcd989b7..9f68a29b3ad 100644 --- a/core/embed/lib/translations.c +++ b/core/embed/lib/translations.c @@ -7,6 +7,8 @@ #include "model.h" #include "mpu.h" +#ifdef KERNEL_MODE + bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) { uint32_t size = translations_area_bytesize(); if (offset > size || size - offset < len) { @@ -44,3 +46,5 @@ void translations_erase(void) { uint32_t translations_area_bytesize(void) { return flash_area_get_size(&TRANSLATIONS_AREA); } + +#endif // KERNEL_MODE diff --git a/core/embed/lib/unit_variant.c b/core/embed/lib/unit_variant.c index 8170d19e028..6fffb7049da 100644 --- a/core/embed/lib/unit_variant.c +++ b/core/embed/lib/unit_variant.c @@ -6,6 +6,8 @@ #include "unit_variant.h" #include TREZOR_BOARD +#ifdef KERNEL_MODE + static uint8_t unit_variant_color = 0; static uint8_t unit_variant_packaging = 0; static bool unit_variant_btconly = false; @@ -94,3 +96,5 @@ bool unit_variant_is_sd_hotswap_enabled(void) { #endif #endif } + +#endif // KERNEL_MODE diff --git a/core/embed/lib/unit_variant.h b/core/embed/lib/unit_variant.h index 3d08974e75d..fea6d77b0ca 100644 --- a/core/embed/lib/unit_variant.h +++ b/core/embed/lib/unit_variant.h @@ -4,7 +4,12 @@ #include #include +#ifdef KERNEL_MODE + void unit_variant_init(void); + +#endif // KERNEL_MODE + bool unit_variant_present(void); uint8_t unit_variant_get_color(void); uint8_t unit_variant_get_packaging(void); diff --git a/core/embed/models/D002/model_D002.h b/core/embed/models/D002/model_D002.h index 217974ca69f..6b0712631b3 100644 --- a/core/embed/models/D002/model_D002.h +++ b/core/embed/models/D002/model_D002.h @@ -32,6 +32,9 @@ #define FLASH_START 0x0C000000 #define BOARDLOADER_START 0x0C004000 #define BOOTLOADER_START 0x0C010000 +#define KERNEL_START 0x0C050000 +#define KERNEL_SIZE 0x00028000 +#define COREAPP_START 0x0C078000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 #define STORAGE_2_OFFSET 0x50000 diff --git a/core/embed/models/T3T1/model_T3T1.h b/core/embed/models/T3T1/model_T3T1.h index cbada112e44..35af3e6d203 100644 --- a/core/embed/models/T3T1/model_T3T1.h +++ b/core/embed/models/T3T1/model_T3T1.h @@ -32,6 +32,9 @@ #define FLASH_START 0x0C000000 #define BOARDLOADER_START 0x0C004000 #define BOOTLOADER_START 0x0C010000 +#define KERNEL_START 0x0C050000 +#define KERNEL_SIZE 0x00028000 +#define COREAPP_START 0x0C078000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 #define STORAGE_2_OFFSET 0x50000 diff --git a/core/embed/trezorhal/bg_copy.h b/core/embed/trezorhal/bg_copy.h index be40c254285..dac9383d79d 100644 --- a/core/embed/trezorhal/bg_copy.h +++ b/core/embed/trezorhal/bg_copy.h @@ -6,6 +6,8 @@ #include #include +#ifdef KERNEL_MODE + /** * Callback function invoked from the IRQ context * when the transfer is complete @@ -38,4 +40,6 @@ void bg_copy_wait(void); void bg_copy_abort(void); +#endif // KERNEL_MODE + #endif diff --git a/core/embed/trezorhal/board_capabilities.h b/core/embed/trezorhal/board_capabilities.h index 66a4c28f590..6bf820dfc9e 100644 --- a/core/embed/trezorhal/board_capabilities.h +++ b/core/embed/trezorhal/board_capabilities.h @@ -35,6 +35,8 @@ Last tag must be terminator or all space used. #include +#ifdef KERNEL_MODE + #define BOARD_CAPABILITIES_SIZE 256 #define CAPABILITIES_HEADER "TRZC" @@ -77,4 +79,6 @@ void parse_boardloader_capabilities(); const uint32_t get_board_name(); const boardloader_version_t* get_boardloader_version(); +#endif // KERNEL_MODE + #endif diff --git a/core/embed/trezorhal/button.h b/core/embed/trezorhal/button.h index f1389f7f4ee..fa54013bcb3 100644 --- a/core/embed/trezorhal/button.h +++ b/core/embed/trezorhal/button.h @@ -28,7 +28,12 @@ #define BTN_LEFT 0 #define BTN_RIGHT 1 +#ifdef KERNEL_MODE + void button_init(void); + +#endif + uint32_t button_read(void); char button_state_left(void); char button_state_right(void); diff --git a/core/embed/trezorhal/consumption_mask.h b/core/embed/trezorhal/consumption_mask.h index d11fdabf9d3..fdf1abb95ff 100644 --- a/core/embed/trezorhal/consumption_mask.h +++ b/core/embed/trezorhal/consumption_mask.h @@ -1,9 +1,31 @@ +/* + * 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 . + */ #ifndef CORE_CONSUMPTION_MASK_H #define CORE_CONSUMPTION_MASK_H -void consumption_mask_randomize(); +#ifdef KERNEL_MODE void consumption_mask_init(void); +void consumption_mask_randomize(); + +#endif + #endif // CORE_CONSUMPTION_MASK_H diff --git a/core/embed/trezorhal/entropy.h b/core/embed/trezorhal/entropy.h index bd50b48e3ac..c71d0aab4f0 100644 --- a/core/embed/trezorhal/entropy.h +++ b/core/embed/trezorhal/entropy.h @@ -22,10 +22,14 @@ #include +#ifdef KERNEL_MODE + void entropy_init(void); +#endif + #define HW_ENTROPY_LEN (12 + 32) void entropy_get(uint8_t *buf); -#endif \ No newline at end of file +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/flash.h b/core/embed/trezorhal/flash.h index 2918b11ee55..ae0169af788 100644 --- a/core/embed/trezorhal/flash.h +++ b/core/embed/trezorhal/flash.h @@ -23,11 +23,10 @@ #include #include +#include "flash_ll.h" #include "platform.h" #include "secbool.h" -#include "flash_ll.h" - void flash_init(void); #endif // TREZORHAL_FLASH_H diff --git a/core/embed/trezorhal/flash_otp.h b/core/embed/trezorhal/flash_otp.h index c3f8705ab4a..56d05a237a2 100644 --- a/core/embed/trezorhal/flash_otp.h +++ b/core/embed/trezorhal/flash_otp.h @@ -3,6 +3,8 @@ #include +#ifdef KERNEL_MODE + #define FLASH_OTP_NUM_BLOCKS 16 #define FLASH_OTP_BLOCK_SIZE 32 @@ -15,4 +17,6 @@ secbool __wur flash_otp_write(uint8_t block, uint8_t offset, secbool __wur flash_otp_lock(uint8_t block); secbool __wur flash_otp_is_locked(uint8_t block); +#endif // KERNEL_MODE + #endif // TREZORHAL_FLASH_OTP_H diff --git a/core/embed/trezorhal/fwutils.h b/core/embed/trezorhal/fwutils.h index b4c13626f93..f29bc5ff638 100644 --- a/core/embed/trezorhal/fwutils.h +++ b/core/embed/trezorhal/fwutils.h @@ -54,9 +54,13 @@ secbool firmware_calc_hash(const uint8_t* challenge, size_t challenge_len, // otherwise. secbool firmware_get_vendor(char* buff, size_t buff_size); +#ifdef KERNEL_MODE + // Invalidates the firmware by erasing the first 1KB of the firmware area. // // Note: only works when write access to firmware area is enabled by MPU void firmware_invalidate_header(void); +#endif // KERNEL_MODE + #endif // TREZORHAL_FWUTILS_H diff --git a/core/embed/trezorhal/haptic.h b/core/embed/trezorhal/haptic.h index ca7223b6586..6cb60ee9bbf 100644 --- a/core/embed/trezorhal/haptic.h +++ b/core/embed/trezorhal/haptic.h @@ -30,6 +30,8 @@ typedef enum { HAPTIC_HOLD_TO_CONFIRM = 1, } haptic_effect_t; +#ifdef KERNEL_MODE + // Initializes the haptic driver // // The function initializes the GPIO pins and the hardware @@ -44,6 +46,8 @@ bool haptic_init(void); // haptic driver so the device can be eventually put into a low-power mode. void haptic_deinit(void); +#endif // KERNEL_MODE + // Enables or disables the haptic driver // // When the driver is disabled, it does not play any haptic effects diff --git a/core/embed/trezorhal/hash_processor.h b/core/embed/trezorhal/hash_processor.h index 1ebc9bb94da..66c85653b93 100644 --- a/core/embed/trezorhal/hash_processor.h +++ b/core/embed/trezorhal/hash_processor.h @@ -10,9 +10,13 @@ typedef struct { uint8_t buffer[HASH_SHA256_BUFFER_SIZE]; /*!< data being processed */ } hash_sha265_context_t; +#ifdef KERNEL_MODE + // Initialize the hash processor void hash_processor_init(void); +#endif + // Calculate SHA256 hash of data // for best performance, data should be 32-bit aligned - as this allows DMA to // be used diff --git a/core/embed/trezorhal/i2c_bus.h b/core/embed/trezorhal/i2c_bus.h index 3203fcaa06f..2296a4d2c4d 100644 --- a/core/embed/trezorhal/i2c_bus.h +++ b/core/embed/trezorhal/i2c_bus.h @@ -24,6 +24,8 @@ #include #include +#ifdef KERNEL_MODE + // I2C bus abstraction typedef struct i2c_bus i2c_bus_t; // I2C packet (series of I2C operations) @@ -182,4 +184,6 @@ void example() { } */ +#endif // KERNEL_MODE + #endif // TREZORHAL_I2C_BUS_H diff --git a/core/embed/trezorhal/lowlevel.h b/core/embed/trezorhal/lowlevel.h index 49757aeac94..7d6cf789163 100644 --- a/core/embed/trezorhal/lowlevel.h +++ b/core/embed/trezorhal/lowlevel.h @@ -22,6 +22,8 @@ #include "secbool.h" +#ifdef KERNEL_MODE + secbool flash_check_option_bytes(void); void flash_lock_option_bytes(void); void flash_unlock_option_bytes(void); @@ -31,4 +33,6 @@ void periph_init(void); secbool reset_flags_check(void); void reset_flags_reset(void); +#endif // KERNEL_MODE + #endif // __TREZORHAL_LOWLEVEL_H__ diff --git a/core/embed/trezorhal/monoctr.h b/core/embed/trezorhal/monoctr.h index 296b573dbfb..e6394583f11 100644 --- a/core/embed/trezorhal/monoctr.h +++ b/core/embed/trezorhal/monoctr.h @@ -20,6 +20,8 @@ #ifndef TREZORHAL_MONOCTR #define TREZORHAL_MONOCTR +#ifdef KERNEL_MODE + // Monoctr module provides monotonic counter functionality #define MONOCTR_MAX_VALUE 63 @@ -40,4 +42,6 @@ secbool monoctr_write(monoctr_type_t type, uint8_t value); // Read the current value of the monotonic counter secbool monoctr_read(monoctr_type_t type, uint8_t* value); +#endif // KERNEL_MODE + #endif diff --git a/core/embed/trezorhal/mpu.h b/core/embed/trezorhal/mpu.h index 989d622c301..c8486767a3f 100644 --- a/core/embed/trezorhal/mpu.h +++ b/core/embed/trezorhal/mpu.h @@ -20,6 +20,8 @@ #ifndef TREZORHAL_MPU_H #define TREZORHAL_MPU_H +#ifdef KERNEL_MODE + // The MPU driver can be set to on of the following modes. // // In each mode, the MPU is configured to allow access to specific @@ -62,4 +64,6 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode); // Same as `mpu_reconfig()`, but with a more descriptive name. void mpu_restore(mpu_mode_t mode); +#endif // KERNEL_MODE + #endif // TREZORHAL_MPU_H diff --git a/core/embed/trezorhal/optiga/optiga.c b/core/embed/trezorhal/optiga/optiga.c index 2189fc8dd92..d4fa2e2391a 100644 --- a/core/embed/trezorhal/optiga/optiga.c +++ b/core/embed/trezorhal/optiga/optiga.c @@ -27,6 +27,8 @@ #include "rand.h" #include "storage.h" +#ifdef KERNEL_MODE + // Counter-protected PIN secret and reset key for OID_STRETCHED_PIN_CTR (OID // 0xF1D0). #define OID_PIN_SECRET (OPTIGA_OID_DATA + 0) @@ -973,3 +975,5 @@ bool optiga_pin_decrease_rem(uint32_t count) { optiga_count_data_object(OID_STRETCHED_PIN_CTR, count) == OPTIGA_SUCCESS; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/optiga/optiga_commands.c b/core/embed/trezorhal/optiga/optiga_commands.c index a77d7959151..1041adc887c 100644 --- a/core/embed/trezorhal/optiga/optiga_commands.c +++ b/core/embed/trezorhal/optiga/optiga_commands.c @@ -33,6 +33,8 @@ #include "optiga_transport.h" #include "sha2.h" +#ifdef KERNEL_MODE + // Static buffer for commands and responses. static uint8_t tx_buffer[OPTIGA_MAX_APDU_SIZE] = {0}; static size_t tx_size = 0; @@ -959,3 +961,5 @@ optiga_result optiga_set_priv_key(uint16_t oid, const uint8_t priv_key[32]) { return process_output_fixedlen(NULL, 0); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/optiga/optiga_transport.c b/core/embed/trezorhal/optiga/optiga_transport.c index 8876c190ed4..3ac1d820541 100644 --- a/core/embed/trezorhal/optiga/optiga_transport.c +++ b/core/embed/trezorhal/optiga/optiga_transport.c @@ -31,6 +31,8 @@ #include "optiga_hal.h" #include "tls_prf.h" +#ifdef KERNEL_MODE + #include TREZOR_BOARD // Maximum possible packet size that can be transmitted. @@ -812,3 +814,5 @@ optiga_result optiga_sec_chan_handshake(const uint8_t *secret, sec_chan_established = true; return OPTIGA_SUCCESS; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/random_delays.h b/core/embed/trezorhal/random_delays.h index 19e136c4ebb..ecdd6d44bd5 100644 --- a/core/embed/trezorhal/random_delays.h +++ b/core/embed/trezorhal/random_delays.h @@ -17,16 +17,22 @@ * along with this program. If not, see . */ -#ifndef __TREZORHAL_RANDOM_DELAYS_H__ -#define __TREZORHAL_RANDOM_DELAYS_H__ +#ifndef TREZORHAL_RANDOM_DELAYS_H +#define TREZORHAL_RANDOM_DELAYS_H #include +#ifdef KERNEL_MODE + void rdi_init(void); void rdi_start(void); void rdi_stop(void); + +#endif + void rdi_refresh_session_delay(void); void wait_random(void); -#endif + +#endif // TREZORHAL_RANDOM_DELAYS_H diff --git a/core/embed/trezorhal/rgb_led.h b/core/embed/trezorhal/rgb_led.h index a342b9a8580..1ad62d9b80c 100644 --- a/core/embed/trezorhal/rgb_led.h +++ b/core/embed/trezorhal/rgb_led.h @@ -1,4 +1,33 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_RGB_LED_H +#define TREZORHAL_RGB_LED_H + +#include + +#ifdef KERNEL_MODE void rgb_led_init(void); +#endif + void rgb_led_set_color(uint32_t color); + +#endif // TREZORHAL_RGB_LED_H diff --git a/core/embed/trezorhal/rng.h b/core/embed/trezorhal/rng.h index 083b2c15080..7c9dc69a18e 100644 --- a/core/embed/trezorhal/rng.h +++ b/core/embed/trezorhal/rng.h @@ -22,8 +22,14 @@ #include +#ifdef KERNEL_MODE + void rng_init(void); + uint32_t rng_read(const uint32_t previous, const uint32_t compare_previous); + +#endif // KERNEL_MODE + uint32_t rng_get(void); #endif diff --git a/core/embed/trezorhal/sdcard.h b/core/embed/trezorhal/sdcard.h index e2f1bf4b8ab..730b33210fd 100644 --- a/core/embed/trezorhal/sdcard.h +++ b/core/embed/trezorhal/sdcard.h @@ -52,8 +52,13 @@ // this is a fixed size and should not be changed #define SDCARD_BLOCK_SIZE (512) +#ifdef KERNEL_MODE + void sdcard_init(void); secbool __wur sdcard_power_on_unchecked(bool low_speed); + +#endif + secbool __wur sdcard_power_on(void); void sdcard_power_off(void); secbool __wur sdcard_is_present(void); diff --git a/core/embed/trezorhal/secret.h b/core/embed/trezorhal/secret.h index 8c85ac9e5a2..288e98f7f91 100644 --- a/core/embed/trezorhal/secret.h +++ b/core/embed/trezorhal/secret.h @@ -1,7 +1,11 @@ +#ifndef TREZORHAL_SECRET_H +#define TREZORHAL_SECRET_H #include #include "secbool.h" +#ifdef KERNEL_MODE + #define SECRET_HEADER_MAGIC "TRZS" #define SECRET_HEADER_LEN 16 #define SECRET_OPTIGA_KEY_OFFSET 16 @@ -14,11 +18,6 @@ #define SECRET_BHK_OFFSET (1024 * 8) #define SECRET_BHK_LEN 32 -// Checks if bootloader is locked, that is the secret storage contains optiga -// pairing secret on platforms where access to the secret storage cannot be -// restricted for unofficial firmware -secbool secret_bootloader_locked(void); - // Writes data to the secret storage void secret_write(const uint8_t* data, uint32_t offset, uint32_t len); @@ -70,3 +69,12 @@ void secret_bhk_regenerate(void); // Disables access to the secret storage until next reset, if possible // This function is called by the bootloader before starting the firmware void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all); + +#endif // KERNEL_MODE + +// Checks if bootloader is locked, that is the secret storage contains optiga +// pairing secret on platforms where access to the secret storage cannot be +// restricted for unofficial firmware +secbool secret_bootloader_locked(void); + +#endif // TREZORHAL_SECRET_H diff --git a/core/embed/trezorhal/stm32f4/board_capabilities.c b/core/embed/trezorhal/stm32f4/board_capabilities.c index 461fbaa15ca..68757bbe9ee 100644 --- a/core/embed/trezorhal/stm32f4/board_capabilities.c +++ b/core/embed/trezorhal/stm32f4/board_capabilities.c @@ -24,6 +24,8 @@ #include "model.h" #include "mpu.h" +#ifdef KERNEL_MODE + static uint32_t board_name = 0; static struct BoardloaderVersion boardloader_version; @@ -86,3 +88,5 @@ void parse_boardloader_capabilities() { mpu_restore(mpu_mode); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/bootutils.c b/core/embed/trezorhal/stm32f4/bootutils.c index 2fdd3f9afd2..4e573905623 100644 --- a/core/embed/trezorhal/stm32f4/bootutils.c +++ b/core/embed/trezorhal/stm32f4/bootutils.c @@ -23,9 +23,13 @@ #include "bootutils.h" #include "common.h" #include "display.h" +#include "image.h" #include "irq.h" +#include "model.h" #include "mpu.h" +#ifdef KERNEL_MODE + #ifdef STM32U5 // Persistent variable that holds the 'command' for the next reboot. boot_command_t __attribute__((section(".boot_command"))) g_boot_command; @@ -131,3 +135,5 @@ void __attribute__((noreturn)) secure_shutdown(void) { for (;;) ; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/button.c b/core/embed/trezorhal/stm32f4/button.c index b8ca256b7f2..544b8ba4824 100644 --- a/core/embed/trezorhal/stm32f4/button.c +++ b/core/embed/trezorhal/stm32f4/button.c @@ -2,6 +2,8 @@ #include "button.h" #include TREZOR_BOARD +#ifdef KERNEL_MODE + static char last_left = 0, last_right = 0; void button_init(void) { @@ -45,3 +47,5 @@ uint32_t button_read(void) { char button_state_left(void) { return last_left; } char button_state_right(void) { return last_right; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 17395f72082..7ac11fe6acb 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -36,6 +36,8 @@ #include "backlight_pwm.h" #endif +#ifdef KERNEL_MODE + // 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) @@ -52,3 +54,5 @@ void clear_otg_hs_memory(void) { __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as // the peripheral is not needed right now } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/consumption_mask.c b/core/embed/trezorhal/stm32f4/consumption_mask.c index 1da81915083..3252fdaecee 100644 --- a/core/embed/trezorhal/stm32f4/consumption_mask.c +++ b/core/embed/trezorhal/stm32f4/consumption_mask.c @@ -20,6 +20,8 @@ #include STM32_HAL_H #include "rng.h" +#ifdef KERNEL_MODE + #define SAMPLES 110 #define TIMER_PERIOD 16640 // cca 10 KHz @ 180MHz @@ -106,3 +108,5 @@ void consumption_mask_init(void) { HAL_TIM_Base_Start(&TIM8_Handle); HAL_TIM_PWM_Start(&TIM8_Handle, TIM_CHANNEL_1); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/entropy.c b/core/embed/trezorhal/stm32f4/entropy.c index 4aec016ab8f..99fb0d69746 100644 --- a/core/embed/trezorhal/stm32f4/entropy.c +++ b/core/embed/trezorhal/stm32f4/entropy.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#include + #include "entropy.h" #include "entropy.h" @@ -27,6 +29,8 @@ #include "stm32f4xx_ll_utils.h" +#ifdef KERNEL_MODE + static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; void entropy_init(void) { @@ -58,3 +62,5 @@ void entropy_init(void) { } void entropy_get(uint8_t *buf) { memcpy(buf, g_hw_entropy, HW_ENTROPY_LEN); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/fault_handlers.c b/core/embed/trezorhal/stm32f4/fault_handlers.c index 5c6d43152cc..35fc0ed0302 100644 --- a/core/embed/trezorhal/stm32f4/fault_handlers.c +++ b/core/embed/trezorhal/stm32f4/fault_handlers.c @@ -1,34 +1,58 @@ #include TREZOR_BOARD + #include "common.h" +#include "mpu.h" + +#ifdef KERNEL_MODE void fault_handlers_init(void) { // Enable BUS fault and USAGE fault handlers SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk); } -void HardFault_Handler(void) { error_shutdown("(HF)"); } +void HardFault_Handler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(HF)"); +} -void MemManage_Handler_MM(void) { error_shutdown("(MM)"); } +void MemManage_Handler_MM(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(MM)"); +} -void MemManage_Handler_SO(void) { error_shutdown("(SO)"); } +void MemManage_Handler_SO(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(SO)"); +} -void BusFault_Handler(void) { error_shutdown("(BF)"); } +void BusFault_Handler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(BF)"); +} -void UsageFault_Handler(void) { error_shutdown("(UF)"); } +void UsageFault_Handler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(UF)"); +} void NMI_Handler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); // Clock Security System triggered NMI if ((RCC->CIR & RCC_CIR_CSSF) != 0) { error_shutdown("(CS)"); } + mpu_restore(mpu_mode); } // from util.s extern void shutdown_privileged(void); void PVD_IRQHandler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); #ifdef BACKLIGHT_PWM_TIM BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; // turn off display backlight #endif shutdown_privileged(); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/flash.c b/core/embed/trezorhal/stm32f4/flash.c index 8a34cc6947f..5a0b2c5cb4d 100644 --- a/core/embed/trezorhal/stm32f4/flash.c +++ b/core/embed/trezorhal/stm32f4/flash.c @@ -24,6 +24,8 @@ #include "common.h" #include "flash.h" +#ifdef KERNEL_MODE + #if defined STM32F427xx || defined STM32F429xx #define FLASH_SECTOR_COUNT 24 #elif defined STM32F405x @@ -198,3 +200,5 @@ secbool flash_write_block(uint16_t sector, uint32_t offset, const flash_block_t block) { return flash_write_word(sector, offset, block[0]); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/flash_otp.c b/core/embed/trezorhal/stm32f4/flash_otp.c index 53672c36f24..6260426994e 100644 --- a/core/embed/trezorhal/stm32f4/flash_otp.c +++ b/core/embed/trezorhal/stm32f4/flash_otp.c @@ -24,6 +24,8 @@ #include "flash.h" #include "mpu.h" +#ifdef KERNEL_MODE + #define FLASH_OTP_LOCK_BASE 0x1FFF7A00U void flash_otp_init() { @@ -102,3 +104,5 @@ secbool flash_otp_is_locked(uint8_t block) { return is_locked; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/fwutils.c b/core/embed/trezorhal/stm32f4/fwutils.c index e583203d7f7..e2a6a5a39d8 100644 --- a/core/embed/trezorhal/stm32f4/fwutils.c +++ b/core/embed/trezorhal/stm32f4/fwutils.c @@ -27,6 +27,8 @@ #include "image.h" #include "model.h" +#ifdef KERNEL_MODE + #define FW_HASHING_CHUNK_SIZE 1024 secbool firmware_calc_hash(const uint8_t* challenge, size_t challenge_len, @@ -110,3 +112,5 @@ void firmware_invalidate_header(void) { } ensure(flash_lock_write(), NULL); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/i2c_bus.c b/core/embed/trezorhal/stm32f4/i2c_bus.c index 2dfacc3abe1..5b4c11e52c1 100644 --- a/core/embed/trezorhal/stm32f4/i2c_bus.c +++ b/core/embed/trezorhal/stm32f4/i2c_bus.c @@ -25,8 +25,11 @@ #include "common.h" #include "i2c_bus.h" #include "irq.h" +#include "mpu.h" #include "systimer.h" +#ifdef KERNEL_MODE + // I2C bus SCL clock frequency #define I2C_BUS_SCL_FREQ 200000 // Hz @@ -907,30 +910,44 @@ static void i2c_bus_er_handler(i2c_bus_t* bus) { #ifdef I2C_INSTANCE_0 void I2C_INSTANCE_0_EV_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_ev_handler(&g_i2c_bus_driver[0]); + mpu_restore(mpu_mode); } void I2C_INSTANCE_0_ER_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_er_handler(&g_i2c_bus_driver[0]); + mpu_restore(mpu_mode); } #endif #ifdef I2C_INSTANCE_1 void I2C_INSTANCE_1_EV_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_ev_handler(&g_i2c_bus_driver[1]); + mpu_restore(mpu_mode); } void I2C_INSTANCE_1_ER_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_er_handler(&g_i2c_bus_driver[1]); + mpu_restore(mpu_mode); } #endif #ifdef I2C_INSTANCE_2 void I2C_INSTANCE_2_EV_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_ev_handler(&g_i2c_bus_driver[2]); + mpu_restore(mpu_mode); } void I2C_INSTANCE_2_ER_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_er_handler(&g_i2c_bus_driver[2]); + mpu_restore(mpu_mode); } #endif + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/limited_util.s b/core/embed/trezorhal/stm32f4/limited_util.S similarity index 100% rename from core/embed/trezorhal/stm32f4/limited_util.s rename to core/embed/trezorhal/stm32f4/limited_util.S diff --git a/core/embed/trezorhal/stm32f4/lowlevel.c b/core/embed/trezorhal/stm32f4/lowlevel.c index 188142f21a7..1174991f193 100644 --- a/core/embed/trezorhal/stm32f4/lowlevel.c +++ b/core/embed/trezorhal/stm32f4/lowlevel.c @@ -25,6 +25,8 @@ #include "flash_otp.h" +#ifdef KERNEL_MODE + #pragma GCC optimize( \ "no-stack-protector") // applies to all functions in this file @@ -197,3 +199,5 @@ secbool reset_flags_check(void) { void reset_flags_reset(void) { RCC->CSR |= RCC_CSR_RMVF; // clear the reset flags } + +#endif // #ifdef KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/monoctr.c b/core/embed/trezorhal/stm32f4/monoctr.c index c05bc046471..119b2070bf8 100644 --- a/core/embed/trezorhal/stm32f4/monoctr.c +++ b/core/embed/trezorhal/stm32f4/monoctr.c @@ -23,6 +23,8 @@ #include "mpu.h" #include "string.h" +#ifdef KERNEL_MODE + #if !PRODUCTION // we don't want to override OTP on development boards // lets mock this functionality @@ -139,3 +141,5 @@ secbool monoctr_read(monoctr_type_t type, uint8_t* value) { return sectrue; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/mpu.c b/core/embed/trezorhal/stm32f4/mpu.c index 23a1f208d95..72f593d7212 100644 --- a/core/embed/trezorhal/stm32f4/mpu.c +++ b/core/embed/trezorhal/stm32f4/mpu.c @@ -29,6 +29,8 @@ #include "stm32f4xx_ll_cortex.h" +#ifdef KERNEL_MODE + // http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABDJJGF.html #define MPU_RASR_ATTR_FLASH_CODE (MPU_RASR_C_Msk) #define MPU_RASR_ATTR_FLASH_DATA (MPU_RASR_C_Msk | MPU_RASR_XN_Msk) @@ -354,3 +356,5 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { } void mpu_restore(mpu_mode_t mode) { mpu_reconfig(mode); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/optiga_hal.c b/core/embed/trezorhal/stm32f4/optiga_hal.c index ec7a3091196..b3d659fcf13 100644 --- a/core/embed/trezorhal/stm32f4/optiga_hal.c +++ b/core/embed/trezorhal/stm32f4/optiga_hal.c @@ -2,6 +2,8 @@ #include "common.h" #include TREZOR_BOARD +#ifdef KERNEL_MODE + void optiga_hal_init(void) { OPTIGA_RST_CLK_EN(); // init reset pin @@ -27,3 +29,5 @@ void optiga_reset(void) { // warm reset startup time min 15ms hal_delay(20); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/platform.c b/core/embed/trezorhal/stm32f4/platform.c index 47aaa72e932..8d801d507fd 100644 --- a/core/embed/trezorhal/stm32f4/platform.c +++ b/core/embed/trezorhal/stm32f4/platform.c @@ -24,6 +24,8 @@ #include "systick.h" #include TREZOR_BOARD +#ifdef KERNEL_MODE + const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; @@ -204,3 +206,5 @@ void set_core_clock(clock_settings_t settings) { ; } #endif + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/random_delays.c b/core/embed/trezorhal/stm32f4/random_delays.c index afc8079fc14..9dbbe0a9d53 100644 --- a/core/embed/trezorhal/stm32f4/random_delays.c +++ b/core/embed/trezorhal/stm32f4/random_delays.c @@ -46,6 +46,8 @@ Random Delays in Embedded Software by Michael Tunstall, Olivier Benoit: #include "rand.h" #include "systimer.h" +#ifdef KERNEL_MODE + // from util.s extern void shutdown_privileged(void); @@ -220,3 +222,5 @@ void wait_random(void) { } #endif } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/rgb_led.c b/core/embed/trezorhal/stm32f4/rgb_led.c index a6e8768d2f2..8d0fbd37990 100644 --- a/core/embed/trezorhal/stm32f4/rgb_led.c +++ b/core/embed/trezorhal/stm32f4/rgb_led.c @@ -39,6 +39,8 @@ #include "common.h" +#ifdef KERNEL_MODE + #include STM32_HAL_H #define RESET_DATA_LEN 18 // >80us no pulse before sending data @@ -166,3 +168,5 @@ void rgb_led_init(void) { // turns off the LED rgb_led_set_color(0x000000); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/rng.c b/core/embed/trezorhal/stm32f4/rng.c index 29a98c12189..a6ae2b57c3c 100644 --- a/core/embed/trezorhal/stm32f4/rng.c +++ b/core/embed/trezorhal/stm32f4/rng.c @@ -21,6 +21,8 @@ #include "rng.h" +#if KERNEL_MODE + #pragma GCC optimize( \ "no-stack-protector") // applies to all functions in this file @@ -56,3 +58,5 @@ uint32_t rng_get(void) { current = rng_read(previous, 1); return current; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/sdcard.c b/core/embed/trezorhal/stm32f4/sdcard.c index 21c7b099ece..386ccef0369 100644 --- a/core/embed/trezorhal/stm32f4/sdcard.c +++ b/core/embed/trezorhal/stm32f4/sdcard.c @@ -49,9 +49,12 @@ #include #include "irq.h" +#include "mpu.h" #include "sdcard-set_clr_card_detect.h" #include "sdcard.h" +#ifdef KERNEL_MODE + #define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC1_CLK_ENABLE() #define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC1_CLK_DISABLE() #define SDMMC_IRQn SDMMC1_IRQn @@ -61,9 +64,9 @@ static DMA_HandleTypeDef sd_dma = {0}; void DMA2_Stream3_IRQHandler(void) { IRQ_ENTER(DMA2_Stream3_IRQn); - + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); HAL_DMA_IRQHandler(&sd_dma); - + mpu_restore(mpu_mode); IRQ_EXIT(DMA2_Stream3_IRQn); } @@ -231,9 +234,11 @@ uint64_t sdcard_get_capacity_in_bytes(void) { void SDIO_IRQHandler(void) { IRQ_ENTER(SDIO_IRQn); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); if (sd_handle.Instance) { HAL_SD_IRQHandler(&sd_handle); } + mpu_restore(mpu_mode); IRQ_EXIT(SDIO_IRQn); } diff --git a/core/embed/trezorhal/stm32f4/secret.c b/core/embed/trezorhal/stm32f4/secret.c index a02df263603..0f6f92ef637 100644 --- a/core/embed/trezorhal/stm32f4/secret.c +++ b/core/embed/trezorhal/stm32f4/secret.c @@ -6,9 +6,7 @@ #include "model.h" #include "mpu.h" -#ifdef FANCY_FATAL_ERROR -#include "rust_ui.h" -#endif +#ifdef KERNEL_MODE static secbool bootloader_locked_set = secfalse; static secbool bootloader_locked = secfalse; @@ -134,3 +132,5 @@ void secret_prepare_fw(secbool allow_run_with_secret, secbool _trust_all) { } #endif } + +#endif // KERNEL_MODE \ No newline at end of file diff --git a/core/embed/trezorhal/stm32f4/syscall.c b/core/embed/trezorhal/stm32f4/syscall.c new file mode 100644 index 00000000000..8fde6b42ac7 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/syscall.c @@ -0,0 +1,205 @@ +/* + * 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 STM32_HAL_H + +#include "syscall.h" +#include "image.h" +#include "irq.h" +#include "mpu.h" + +#ifdef SYSCALL_DISPATCH + +void syscall_init(void) { + // SVCall priority should be the lowest since it is + // generally a blocking operation + NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_LOWEST); +} + +__attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback( + uint32_t arg1, uint32_t arg2, uint32_t arg3, void *callback) { + __asm__ volatile( + "push {r1-r12, lr} \n" + + "mrs r12, PSP \n" // reserved frame on unprivileged stack (!@# + // TODO check PSP value???) + "push {r12} \n" + "sub r12, r12, #32 \n" + "msr PSP, r12 \n" + + "str r0, [r12, #0] \n" // r0 + "str r1, [r12, #4] \n" // r1" + "str r2, [r12, #8] \n" // r2" + + "mov r1, #0 \n" + "str r1, [r12, #12] \n" // r3" + "str r1, [r12, #16] \n" // r12" + "str r1, [r12, #20] \n" // lr" + + "bic r3, r3, #1 \n" + "str r3, [r12, #24] \n" // return address + + "ldr r1, = 0x01000000 \n" + "str r1, [r12, #28] \n" // xPSR + + "ldr r1, = 0xE000EF34 \n" // FPU->FPPCCR + "ldr r0, [r1] \n" + "bic r0, r0, #1 \n" // Clear LSPACT to suppress lazy stacking to + "str r0, [r1] \n" // avoid potential PSP stack overwrite. + + "mrs r1, CONTROL \n" + "bic r1, r1, #4 \n" // Clear FPCA to suppress lazy stacking to + "msr CONTROL, r1 \n" // avoid potential PSP stack overwrite. + + // return to Secure Thread mode (use Secure PSP) + "ldr lr, = 0xFFFFFFFD \n" + "bx lr \n"); +} + +uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3, + void *callback) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_APP); + uint32_t retval = _invoke_app_callback(args1, arg2, arg3, callback); + mpu_reconfig(mpu_mode); + return retval; +} + +// Jumps to reset vector of unprivileged application code +// +// Can be called only from an exception handler +__attribute__((naked, no_stack_protector)) static void start_app( + uint32_t app_start) { + __asm__ volatile( + "ldr r12, [r0, #0] \n" // stack pointer + "sub r12, r12, #32 \n" + "msr PSP, r12 \n" + + "mov r1, #0 \n" + "str r1, [r12, #0] \n" // r0 + "str r1, [r12, #4] \n" // r1" + "str r1, [r12, #8] \n" // r2" + "str r1, [r12, #12] \n" // r3" + "str r1, [r12, #16] \n" // r12" + "str r1, [r12, #20] \n" // lr" + + "ldr r1, [r0, #4] \n" // reset vector + "bic r1, r1, #1 \n" + "str r1, [r12, #24] \n" // return address + + "ldr r1, = 0x01000000 \n" + "str r1, [r12, #28] \n" // xPSR + + "ldr r1, = 0xE000EF34 \n" // FPU->FPPCCR + "ldr r0, [r1] \n" + "bic r0, r0, #1 \n" // Clear LSPACT to suppress lazy stacking to + "str r0, [r1] \n" // avoid potential PSP stack overwrite. + + "mrs r1, CONTROL \n" + "bic r1, r1, #4 \n" // Clear FPCA to suppress lazy stacking to + "msr CONTROL, r1 \n" // avoid potential PSP stack overwrite. + + "mrs r1, CONTROL \n" // Switch thread mode to unprivileged + "orr r1, r1, #1 \n" // by setting nPRIV bit in CONTROL register. + "msr CONTROL, r1 \n" // This applies after return from this + // handler. + + // return to Secure Thread mode (use Secure PSP) + "ldr lr, = 0xFFFFFFFD \n" + "bx lr \n"); +} + +void SVC_C_Handler(uint32_t *stack, uint32_t r4, uint32_t r5, uint32_t r6) { + uint8_t svc_number = ((uint8_t *)stack[6])[-2]; + uint32_t args[6] = {stack[0], stack[1], stack[2], stack[3], r4, r5}; + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); + + switch (svc_number) { +#ifdef SYSTEM_VIEW + case SVC_GET_DWT_CYCCNT: + cyccnt_cycles = *DWT_CYCCNT_ADDR; + break; +#endif + case SVC_START_APP: + mpu_reconfig(MPU_MODE_APP); + start_app(args[0]); + break; + case SVC_SYSCALL: + syscall_handler(args, r6); + stack[0] = args[0]; + stack[1] = args[1]; + break; + default: + stack[0] = 0xffffffff; + stack[1] = 0xffffffff; + break; + } + + mpu_restore(mpu_mode); +} + +__attribute__((naked, no_stack_protector)) void SVC_Handler(void) { + __asm__ volatile( + " tst lr, #4 \n" // Bit #3 tells which stack pointer should we + // use + " ite eq \n" // Next 2 instructions are if-then-else + " mrseq r0, msp \n" // Make R0 point to main stack pointer + " mrsne r0, psp \n" // Make R0 point to process stack pointer + + " ldr r1, [r0, #24] \n" // Load the PC of the SVC handler + " ldrb r1, [r1, #-2] \n" // Load the instruction at the PC + " cmp r1, #2 \n" // SVC_CALLBACK_RETURN + " beq svc_callback_return \n" + + " mov r1, r4 \n" // pass R4 (arg5), R5 (arg6) and + " mov r2, r5 \n" // R6 (sycall_number) as arguments + " mov r3, r6 \n" // to SCV_C_Handler + " b SVC_C_Handler \n" // + + "svc_callback_return: \n" + + " ldr r0, [r0] \n" + " pop {r1} \n" + " msr PSP, r1 \n" + " pop {r1-r12, lr} \n" + " bx lr \n"); +} + +void __attribute__((no_stack_protector, noreturn)) +start_unprivileged_app(void) { + //!@# TODO calculate better + static const uint32_t app_start = COREAPP_START + IMAGE_HEADER_SIZE + 0x0400; + + mpu_reconfig(MPU_MODE_APP); + + register uint32_t ret __asm__("r0") = app_start; + + // SVC_START_APP is the only SVC that is allowed to be invoked from kernel + // itself and it is used to start the unprivileged application code + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_START_APP), "r"(ret) + : "memory"); + + // We never get here, just to supress compiler warning + while (1) { + } +} + +#endif // SYSCALL_DISPATCH diff --git a/core/embed/trezorhal/stm32f4/syscall.h b/core/embed/trezorhal/stm32f4/syscall.h new file mode 100644 index 00000000000..32da335d907 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/syscall.h @@ -0,0 +1,209 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_SYSCALL_H +#define TREZORHAL_SYSCALL_H + +#include + +#include "syscall_numbers.h" + +// Reserved SVC numbers +#define SVC_SYSCALL 0 +#define SVC_START_APP 1 +#define SVC_CALLBACK_RETURN 2 + +#ifdef KERNEL_MODE + +// Initializes the SVC/Syscall handlers +void syscall_init(void); + +// Handles all syscall requests. +// +// `args` points to an array of six 32-bit arguments. +// `syscall` is the syscall number, which is one of the `SYSCALL_XXX` constants. +// +// Input parameters are passed in `args[0]` to `args[5]`, +// and unused arguments may have undefined values. +// +// Return values must be copied to `args[0]` and +// `args[1]` (if returning a 64-bit value). +void syscall_handler(uint32_t *args, uint32_t syscall); + +// Invokes application callback from the syscall handler +uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3, + void *callback); + +// Jumps to reset vector in the unprivileged application +void __attribute__((noreturn)) start_unprivileged_app(void); + +#else // KERNEL_MODE + +static inline uint32_t __attribute__((no_stack_protector)) +syscall_invoke0(uint32_t syscall) { + register uint32_t ret __asm__("r0"); + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_SYSCALL), "r"(r6) + : "memory"); + + return ret; +} + +static inline uint64_t __attribute__((no_stack_protector)) +syscall_invoke0_ret64(uint32_t syscall) { + register uint32_t ret_lo __asm__("r0"); + register uint32_t ret_hi __asm__("r1"); + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret_lo), "=r"(ret_hi) + : [svid] "i"(SVC_SYSCALL), "r"(r6) + : "memory"); + + return ((uint64_t)ret_hi << 32) | ret_lo; +} + +static inline uint32_t __attribute__((no_stack_protector)) +syscall_invoke1(uint32_t arg1, uint32_t syscall) { + register uint32_t ret __asm__("r0") = arg1; + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_SYSCALL), "r"(ret), "r"(r6) + : "memory"); + return ret; +} + +static inline uint32_t __attribute__((no_stack_protector)) +syscall_invoke2(uint32_t arg1, uint32_t arg2, uint32_t syscall) { + register uint32_t ret __asm__("r0") = arg1; + register uint32_t r1 __asm__("r1") = arg2; + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_SYSCALL), "r"(ret), "r"(r1), "r"(r6) + : "memory"); + + return ret; +} + +static inline uint64_t __attribute__((no_stack_protector)) +syscall_invoke2_ret64(uint32_t arg1, uint32_t arg2, uint32_t syscall) { + register uint32_t ret_lo __asm__("r0") = arg1; + register uint32_t ret_hi __asm__("r1") = arg2; + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret_lo), "=r"(ret_hi) + : [svid] "i"(SVC_SYSCALL), "r"(ret_lo), "r"(ret_hi), "r"(r6) + : "memory"); + + return ((uint64_t)ret_hi << 32) | ret_lo; +} + +static inline uint32_t __attribute__((no_stack_protector)) +syscall_invoke3(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t syscall) { + register uint32_t ret __asm__("r0") = arg1; + register uint32_t r1 __asm__("r1") = arg2; + register uint32_t r2 __asm__("r2") = arg3; + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_SYSCALL), "r"(ret), "r"(r1), "r"(r2), + "r"(r6) + : "memory"); + + return ret; +} + +static inline uint32_t __attribute__((no_stack_protector)) +syscall_invoke4(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, + uint32_t syscall) { + register uint32_t ret __asm__("r0") = arg1; + register uint32_t r1 __asm__("r1") = arg2; + register uint32_t r2 __asm__("r2") = arg3; + register uint32_t r3 __asm__("r3") = arg4; + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_SYSCALL), "r"(ret), "r"(r1), "r"(r2), + "r"(r3), "r"(r6) + : "memory"); + + return ret; +} + +static inline uint32_t __attribute__((no_stack_protector)) +syscall_invoke5(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, + uint32_t arg5, uint32_t syscall) { + register uint32_t ret __asm__("r0") = arg1; + register uint32_t r1 __asm__("r1") = arg2; + register uint32_t r2 __asm__("r2") = arg3; + register uint32_t r3 __asm__("r3") = arg4; + register uint32_t r4 __asm__("r4") = arg5; + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_SYSCALL), "r"(ret), "r"(r1), "r"(r2), + "r"(r3), "r"(r4), "r"(r6) + : "memory"); + + return ret; +} + +static inline uint32_t __attribute__((no_stack_protector)) +syscall_invoke6(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, + uint32_t arg5, uint32_t arg6, uint32_t syscall) { + register uint32_t ret __asm__("r0") = arg1; + register uint32_t r1 __asm__("r1") = arg2; + register uint32_t r2 __asm__("r2") = arg3; + register uint32_t r3 __asm__("r3") = arg4; + register uint32_t r4 __asm__("r4") = arg5; + register uint32_t r5 __asm__("r5") = arg6; + register uint32_t r6 __asm__("r6") = syscall; + + __asm__ volatile("svc %[svid]\n" + : "=r"(ret) + : [svid] "i"(SVC_SYSCALL), "r"(ret), "r"(r1), "r"(r2), + "r"(r3), "r"(r4), "r"(r5), "r"(r6) + : "memory"); + + return ret; +} + +static inline void __attribute__((no_stack_protector)) +syscall_return_from_callback(uint32_t retval) { + register uint32_t r0 __asm__("r0") = retval; + __asm__ volatile("svc %[svid]\n" + : + : [svid] "i"(SVC_CALLBACK_RETURN), "r"(r0) + : "memory"); +} + +#endif // KERNEL_MODE + +#endif // TREZORHAL_SYSCALL_H diff --git a/core/embed/trezorhal/stm32f4/syscall_dispatch.c b/core/embed/trezorhal/stm32f4/syscall_dispatch.c new file mode 100644 index 00000000000..3e4510f9899 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/syscall_dispatch.c @@ -0,0 +1,499 @@ +/* + * 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 STM32_HAL_H + +#include "syscall.h" + +#include "bootutils.h" +#include "button.h" +#include "display.h" +#include "entropy.h" +#include "fwutils.h" +#include "haptic.h" +#include "hash_processor.h" +#include "irq.h" +#include "mpu.h" +#include "optiga.h" +#include "rng.h" +#include "sdcard.h" +#include "secret.h" +#include "systick.h" +#include "touch.h" +#include "translations.h" +#include "unit_variant.h" +#include "usb.h" +#include "usb_hid.h" +#include "usb_vcp.h" +#include "usb_webusb.h" + +#ifdef SYSCALL_DISPATCH + +static PIN_UI_WAIT_CALLBACK storage_init_callback = NULL; + +static secbool storage_init_callback_wrapper( + uint32_t wait, uint32_t progress, enum storage_ui_message_t message) { + return (secbool)invoke_app_callback(wait, progress, message, + storage_init_callback); +} + +static firmware_hash_callback_t firmware_hash_callback = NULL; + +static void firmware_hash_callback_wrapper(void *context, uint32_t progress, + uint32_t total) { + invoke_app_callback((uint32_t)context, progress, total, + firmware_hash_callback); +} + +void syscall_handler(uint32_t *args, uint32_t syscall) { + switch (syscall) { + case SYSCALL_SYSTICK_CYCLES: { + uint64_t cycles = systick_cycles(); + args[0] = cycles & 0xFFFFFFFF; + args[1] = cycles >> 32; + } break; + + case SYSCALL_SYSTICK_US: { + uint64_t cycles = systick_us(); + args[0] = cycles & 0xFFFFFFFF; + args[1] = cycles >> 32; + } break; + + case SYSCALL_SYSTICK_MS: + args[0] = systick_ms(); + break; + + case SYSCALL_SYSTICK_US_TO_CYCLES: { + uint64_t us = args[0] + ((uint64_t)args[1] << 32); + uint64_t cycles = systick_us_to_cycles(us); + args[0] = cycles & 0xFFFFFFFF; + args[1] = cycles >> 32; + } break; + + case SYSCALL_SECURE_SHUTDOWN: + secure_shutdown(); + break; + case SYSCALL_REBOOT: + reboot(); + break; + case SYSCALL_REBOOT_TO_BOOTLOADER: + reboot_to_bootloader(); + break; + case SYSCALL_REBOOT_AND_UPGRADE: + reboot_and_upgrade((uint8_t *)args[0]); + break; + +#ifdef STM32U5 + case SYSCALL_SHA256_INIT: { + hash_sha265_context_t *ctx = (hash_sha265_context_t *)args[0]; + hash_processor_sha256_init(ctx); + } break; + case SYSCALL_SHA256_UPDATE: { + hash_sha265_context_t *ctx = (hash_sha265_context_t *)args[0]; + const uint8_t *data = (const uint8_t *)args[1]; + uint32_t len = args[2]; + hash_processor_sha256_update(ctx, data, len); + } break; + case SYSCALL_SHA256_FINAL: { + hash_sha265_context_t *ctx = (hash_sha265_context_t *)args[0]; + uint8_t *output = (uint8_t *)args[1]; + hash_processor_sha256_final(ctx, output); + } break; + case SYSCALL_SHA256_CALC: { + const uint8_t *data = (const uint8_t *)args[0]; + uint32_t len = args[1]; + uint8_t *hash = (uint8_t *)args[2]; + hash_processor_sha256_calc(data, len, hash); + } break; +#endif // STM32U5 + + case SYSCALL_DISPLAY_SET_BACKLIGHT: { + args[0] = display_set_backlight((int)args[0]); + } break; + case SYSCALL_DISPLAY_GET_BACKLIGHT: { + args[0] = display_get_backlight(); + } break; + case SYSCALL_DISPLAY_SET_ORIENTATION: { + args[0] = display_set_orientation((int)args[0]); + } break; + case SYSCALL_DISPLAY_GET_ORIENTATION: { + args[0] = display_get_orientation(); + + } break; +#if XFRAMEBUFFER + case SYSCALL_DISPLAY_GET_FB_INFO: { + display_fb_info_t *info = (display_fb_info_t *)args[0]; + *info = display_get_frame_buffer(); + } break; +#else + case SYSCALL_DISPLAY_WAIT_FOR_SYNC: { + display_wait_for_sync(); + } break; +#endif + case SYSCALL_DISPLAY_REFRESH: { + display_refresh(); + } break; + case SYSCALL_USB_INIT: { + const usb_dev_info_t *dev_info = (const usb_dev_info_t *)args[0]; + args[0] = usb_init(dev_info); + } break; + case SYSCALL_USB_DEINIT: { + usb_deinit(); + } break; + case SYSCALL_USB_START: { + args[0] = usb_start(); + } break; + case SYSCALL_USB_STOP: { + usb_stop(); + } break; + case SYSCALL_USB_CONFIGURED: { + args[0] = usb_configured(); + } break; + case SYSCALL_USB_HID_ADD: { + args[0] = usb_hid_add((const usb_hid_info_t *)args[0]); + } break; + case SYSCALL_USB_HID_CAN_READ: { + args[0] = usb_hid_can_read((uint8_t)args[0]); + } break; + case SYSCALL_USB_HID_CAN_WRITE: { + args[0] = usb_hid_can_write((uint8_t)args[0]); + } break; + case SYSCALL_USB_HID_READ: { + args[0] = usb_hid_read((uint8_t)args[0], (uint8_t *)args[1], args[2]); + } break; + case SYSCALL_USB_HID_WRITE: { + args[0] = + usb_hid_write((uint8_t)args[0], (const uint8_t *)args[1], args[2]); + } break; + case SYSCALL_USB_HID_READ_SELECT: { + args[0] = usb_hid_read_select((uint32_t)args[0]); + } break; + case SYSCALL_USB_HID_READ_BLOCKING: { + args[0] = usb_hid_read_blocking((uint8_t)args[0], (uint8_t *)args[1], + args[2], (int)args[3]); + } break; + case SYSCALL_USB_HID_WRITE_BLOCKING: { + args[0] = usb_hid_write_blocking( + (uint8_t)args[0], (const uint8_t *)args[1], args[2], (int)args[3]); + } break; + case SYSCALL_USB_VCP_ADD: { + args[0] = usb_vcp_add((const usb_vcp_info_t *)args[0]); + } break; + case SYSCALL_USB_VCP_CAN_READ: { + args[0] = usb_vcp_can_read((uint8_t)args[0]); + } break; + case SYSCALL_USB_VCP_CAN_WRITE: { + args[0] = usb_vcp_can_write((uint8_t)args[0]); + } break; + case SYSCALL_USB_VCP_READ: { + args[0] = usb_vcp_read((uint8_t)args[0], (uint8_t *)args[1], args[2]); + } break; + case SYSCALL_USB_VCP_WRITE: { + args[0] = + usb_vcp_write((uint8_t)args[0], (const uint8_t *)args[1], args[2]); + } break; + case SYSCALL_USB_VCP_READ_BLOCKING: { + args[0] = usb_vcp_read_blocking((uint8_t)args[0], (uint8_t *)args[1], + args[2], (int)args[3]); + } break; + case SYSCALL_USB_VCP_WRITE_BLOCKING: { + args[0] = usb_vcp_write_blocking( + (uint8_t)args[0], (const uint8_t *)args[1], args[2], (int)args[3]); + } break; + case SYSCALL_USB_WEBUSB_ADD: { + args[0] = usb_webusb_add((const usb_webusb_info_t *)args[0]); + } break; + case SYSCALL_USB_WEBUSB_CAN_READ: { + args[0] = usb_webusb_can_read((uint8_t)args[0]); + } break; + case SYSCALL_USB_WEBUSB_CAN_WRITE: { + args[0] = usb_webusb_can_write((uint8_t)args[0]); + } break; + case SYSCALL_USB_WEBUSB_READ: { + args[0] = usb_webusb_read((uint8_t)args[0], (uint8_t *)args[1], args[2]); + } break; + case SYSCALL_USB_WEBUSB_WRITE: { + args[0] = + usb_webusb_write((uint8_t)args[0], (const uint8_t *)args[1], args[2]); + } break; + case SYSCALL_USB_WEBUSB_READ_SELECT: { + args[0] = usb_webusb_read_select((uint32_t)args[0]); + } break; + case SYSCALL_USB_WEBUSB_READ_BLOCKING: { + args[0] = usb_webusb_read_blocking((uint8_t)args[0], (uint8_t *)args[1], + args[2], (int)args[3]); + } break; + case SYSCALL_USB_WEBUSB_WRITE_BLOCKING: { + args[0] = usb_webusb_write_blocking( + (uint8_t)args[0], (const uint8_t *)args[1], args[2], (int)args[3]); + } break; +#ifdef USE_SD_CARD + case SYSCALL_SDCARD_POWER_ON: { + args[0] = sdcard_power_on(); + } break; + case SYSCALL_SDCARD_POWER_OFF: { + sdcard_power_off(); + } break; + case SYSCALL_SDCARD_IS_PRESENT: { + args[0] = sdcard_is_present(); + } break; + case SYSCALL_SDCARD_GET_CAPACITY: { + args[0] = sdcard_get_capacity_in_bytes(); + } break; + case SYSCALL_SDCARD_READ_BLOCKS: { + args[0] = sdcard_read_blocks((uint32_t *)args[0], args[1], args[2]); + } break; + case SYSCALL_SDCARD_WRITE_BLOCKS: { + args[0] = + sdcard_write_blocks((const uint32_t *)args[0], args[1], args[2]); + } break; +#endif + + case SYSCALL_UNIT_VARIANT_PRESENT: { + args[0] = unit_variant_present(); + } break; + case SYSCALL_UNIT_VARIANT_GET_COLOR: { + args[0] = unit_variant_get_color(); + } break; + case SYSCALL_UNIT_VARIANT_GET_PACKAGING: { + args[0] = unit_variant_get_packaging(); + } break; + case SYSCALL_UNIT_VARIANT_GET_BTCONLY: { + args[0] = unit_variant_get_btconly(); + } break; + case SYSCALL_UNIT_VARIANT_IS_SD_HOTSWAP_ENABLED: { + args[0] = unit_variant_is_sd_hotswap_enabled(); + } break; + case SYSCALL_SECRET_BOOTLOADER_LOCKED: { + args[0] = secret_bootloader_locked(); + } break; +#ifdef USE_BUTTON + case SYSCALL_BUTTON_READ: { + args[0] = button_read(); + } break; + case SYSCALL_BUTTON_STATE_LEFT: { + args[0] = button_state_left(); + } break; + case SYSCALL_BUTTON_STATE_RIGHT: { + args[0] = button_state_right(); + } break; +#endif +#ifdef USE_TOUCH + case SYSCALL_TOUCH_GET_EVENT: { + args[0] = touch_get_event(); + } break; +#endif +#ifdef USE_HAPTIC + case SYSCALL_HAPTIC_SET_ENABLED: { + haptic_set_enabled(args[0]); + } break; + case SYSCALL_HAPTIC_GET_ENABLED: { + args[0] = haptic_get_enabled(); + } break; + case SYSCALL_HAPTIC_TEST: { + args[0] = haptic_test(args[0]); + } break; + case SYSCALL_HAPTIC_PLAY: { + args[0] = haptic_play(args[0]); + } break; + case SYSCALL_HAPTIC_PLAY_CUSTOM: { + args[0] = haptic_play_custom(args[0], args[1]); + } break; +#endif + +#ifdef USE_OPTIGA + /*optiga_sign_result optiga_sign(uint8_t index, const uint8_t *digest, + size_t digest_size, uint8_t + *signature, size_t max_sig_size, size_t *sig_size); + + */ + case SYSCALL_OPTIGA_CERT_SIZE: { + uint8_t index = args[0]; + size_t *cert_size = (size_t *)args[1]; + args[0] = optiga_cert_size(index, cert_size); + } break; + case SYSCALL_OPTIGA_READ_CERT: { + uint8_t index = args[0]; + uint8_t *cert = (uint8_t *)args[1]; + size_t max_cert_size = args[2]; + size_t *cert_size = (size_t *)args[3]; + args[0] = optiga_read_cert(index, cert, max_cert_size, cert_size); + } break; + case SYSCALL_OPTIGA_READ_SEC: { + uint8_t *sec = (uint8_t *)args[0]; + args[0] = optiga_read_sec(sec); + } break; + case SYSCALL_OPTIGA_RANDOM_BUFFER: { + uint8_t *dest = (uint8_t *)args[0]; + size_t size = args[1]; + args[0] = optiga_random_buffer(dest, size); + } break; +#if PYOPT == 0 + case SYSCALL_OPTIGA_SET_SEC_MAX: { + optiga_set_sec_max(); + } break; +#endif +#endif + case SYSCALL_STORAGE_INIT: { + storage_init_callback = (PIN_UI_WAIT_CALLBACK)args[0]; + const uint8_t *salt = (const uint8_t *)args[1]; + uint16_t salt_len = args[2]; + mpu_reconfig(MPU_MODE_STORAGE); + storage_init(storage_init_callback_wrapper, salt, salt_len); + } break; + case SYSCALL_STORAGE_WIPE: { + mpu_reconfig(MPU_MODE_STORAGE); + storage_wipe(); + } break; + case SYSCALL_STORAGE_IS_UNLOCKED: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_is_unlocked(); + } break; + case SYSCALL_STORAGE_LOCK: { + mpu_reconfig(MPU_MODE_STORAGE); + storage_lock(); + } break; + case SYSCALL_STORAGE_UNLOCK: { + const uint8_t *pin = (const uint8_t *)args[0]; + size_t pin_len = args[1]; + const uint8_t *ext_salt = (const uint8_t *)args[2]; + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_unlock(pin, pin_len, ext_salt); + } break; + case SYSCALL_STORAGE_HAS_PIN: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_has_pin(); + } break; + case SYSCALL_STORAGE_PIN_FAILS_INCREASE: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_pin_fails_increase(); + } break; + case SYSCALL_STORAGE_GET_PIN_REM: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_get_pin_rem(); + } break; + case SYSCALL_STORAGE_CHANGE_PIN: { + const uint8_t *oldpin = (const uint8_t *)args[0]; + size_t oldpin_len = args[1]; + const uint8_t *newpin = (const uint8_t *)args[2]; + size_t newpin_len = args[3]; + const uint8_t *old_ext_salt = (const uint8_t *)args[4]; + const uint8_t *new_ext_salt = (const uint8_t *)args[5]; + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_change_pin(oldpin, oldpin_len, newpin, newpin_len, + old_ext_salt, new_ext_salt); + } break; + case SYSCALL_STORAGE_ENSURE_NOT_WIPE_CODE: { + const uint8_t *pin = (const uint8_t *)args[0]; + size_t pin_len = args[1]; + mpu_reconfig(MPU_MODE_STORAGE); + storage_ensure_not_wipe_code(pin, pin_len); + } break; + case SYSCALL_STORAGE_HAS_WIPE_CODE: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_has_wipe_code(); + } break; + case SYSCALL_STORAGE_CHANGE_WIPE_CODE: { + const uint8_t *pin = (const uint8_t *)args[0]; + size_t pin_len = args[1]; + const uint8_t *ext_salt = (const uint8_t *)args[2]; + const uint8_t *wipe_code = (const uint8_t *)args[3]; + size_t wipe_code_len = args[4]; + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_change_wipe_code(pin, pin_len, ext_salt, wipe_code, + wipe_code_len); + } break; + case SYSCALL_STORAGE_HAS: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_has((uint16_t)args[0]); + } break; + + case SYSCALL_STORAGE_GET: { + uint16_t key = (uint16_t)args[0]; + void *val = (void *)args[1]; + uint16_t max_len = (uint16_t)args[2]; + uint16_t *len = (uint16_t *)args[3]; + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_get(key, val, max_len, len); + } break; + case SYSCALL_STORAGE_SET: { + uint16_t key = (uint16_t)args[0]; + const void *val = (const void *)args[1]; + uint16_t len = (uint16_t)args[2]; + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_set(key, val, len); + } break; + case SYSCALL_STORAGE_DELETE: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_delete((uint16_t)args[0]); + } break; + case SYSCALL_STORAGE_SET_COUNTER: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_set_counter((uint16_t)args[0], args[1]); + } break; + case SYSCALL_STORAGE_NEXT_COUNTER: { + mpu_reconfig(MPU_MODE_STORAGE); + args[0] = storage_next_counter((uint16_t)args[0], (uint32_t *)args[1]); + } break; + case SYSCALL_ENTROPY_GET: { + uint8_t *buf = (uint8_t *)args[0]; + entropy_get(buf); + } break; + case SYSCALL_TRANSLATIONS_WRITE: { + const uint8_t *data = (const uint8_t *)args[0]; + uint32_t offset = args[1]; + uint32_t len = args[2]; + args[0] = translations_write(data, offset, len); + } break; + case SYSCALL_TRANSLATIONS_READ: { + uint32_t *len = (uint32_t *)args[0]; + uint32_t offset = args[1]; + args[0] = (uint32_t)translations_read(len, offset); + } break; + case SYSCALL_TRANSLATIONS_ERASE: { + translations_erase(); + } break; + case SYSCALL_TRANSLATIONS_AREA_BYTESIZE: { + args[0] = translations_area_bytesize(); + } break; + case SYSCALL_RNG_GET: { + args[0] = rng_get(); + } break; + case SYSCALL_FIRMWARE_GET_VENDOR: { + args[0] = firmware_get_vendor((char *)args[0], args[1]); + } break; + case SYSCALL_FIRMWARE_CALC_HASH: { + const uint8_t *challenge = (const uint8_t *)args[0]; + size_t challenge_len = args[1]; + uint8_t *hash = (uint8_t *)args[2]; + size_t hash_len = args[3]; + firmware_hash_callback = (firmware_hash_callback_t)args[4]; + void *callback_context = (void *)args[5]; + + args[0] = + firmware_calc_hash(challenge, challenge_len, hash, hash_len, + firmware_hash_callback_wrapper, callback_context); + } break; + default: + args[0] = 0xffffffff; + break; + } +} + +#endif // SYSCALL_DISPATCH diff --git a/core/embed/trezorhal/stm32f4/syscall_numbers.h b/core/embed/trezorhal/stm32f4/syscall_numbers.h new file mode 100644 index 00000000000..adc0d5b563d --- /dev/null +++ b/core/embed/trezorhal/stm32f4/syscall_numbers.h @@ -0,0 +1,146 @@ +/* + * 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 . + */ + +#ifndef SYSCALL_NUMBERS_H +#define SYSCALL_NUMBERS_H + +typedef enum { + + // Syscalls numbers + SYSCALL_SYSTICK_CYCLES = 1, + SYSCALL_SYSTICK_MS, + SYSCALL_SYSTICK_US, + SYSCALL_SYSTICK_US_TO_CYCLES, + + SYSCALL_SECURE_SHUTDOWN, + SYSCALL_REBOOT, + SYSCALL_REBOOT_TO_BOOTLOADER, + SYSCALL_REBOOT_AND_UPGRADE, + + SYSCALL_SHA256_INIT, + SYSCALL_SHA256_UPDATE, + SYSCALL_SHA256_FINAL, + SYSCALL_SHA256_CALC, + + SYSCALL_DISPLAY_SET_BACKLIGHT, + SYSCALL_DISPLAY_GET_BACKLIGHT, + SYSCALL_DISPLAY_SET_ORIENTATION, + SYSCALL_DISPLAY_GET_ORIENTATION, + SYSCALL_DISPLAY_GET_FB_INFO, + SYSCALL_DISPLAY_WAIT_FOR_SYNC, + SYSCALL_DISPLAY_REFRESH, + + SYSCALL_USB_INIT, + SYSCALL_USB_DEINIT, + SYSCALL_USB_START, + SYSCALL_USB_STOP, + SYSCALL_USB_CONFIGURED, + + SYSCALL_USB_HID_ADD, + SYSCALL_USB_HID_CAN_READ, + SYSCALL_USB_HID_CAN_WRITE, + SYSCALL_USB_HID_READ, + SYSCALL_USB_HID_WRITE, + SYSCALL_USB_HID_READ_SELECT, + SYSCALL_USB_HID_READ_BLOCKING, + SYSCALL_USB_HID_WRITE_BLOCKING, + SYSCALL_USB_VCP_ADD, + SYSCALL_USB_VCP_CAN_READ, + SYSCALL_USB_VCP_CAN_WRITE, + SYSCALL_USB_VCP_READ, + SYSCALL_USB_VCP_WRITE, + SYSCALL_USB_VCP_READ_BLOCKING, + SYSCALL_USB_VCP_WRITE_BLOCKING, + SYSCALL_USB_WEBUSB_ADD, + SYSCALL_USB_WEBUSB_CAN_READ, + SYSCALL_USB_WEBUSB_CAN_WRITE, + SYSCALL_USB_WEBUSB_READ, + SYSCALL_USB_WEBUSB_WRITE, + SYSCALL_USB_WEBUSB_READ_SELECT, + SYSCALL_USB_WEBUSB_READ_BLOCKING, + SYSCALL_USB_WEBUSB_WRITE_BLOCKING, + + SYSCALL_SDCARD_POWER_ON, + SYSCALL_SDCARD_POWER_OFF, + SYSCALL_SDCARD_IS_PRESENT, + SYSCALL_SDCARD_GET_CAPACITY, + SYSCALL_SDCARD_READ_BLOCKS, + SYSCALL_SDCARD_WRITE_BLOCKS, + + SYSCALL_UNIT_VARIANT_PRESENT, + SYSCALL_UNIT_VARIANT_GET_COLOR, + SYSCALL_UNIT_VARIANT_GET_PACKAGING, + SYSCALL_UNIT_VARIANT_GET_BTCONLY, + SYSCALL_UNIT_VARIANT_IS_SD_HOTSWAP_ENABLED, + + SYSCALL_SECRET_BOOTLOADER_LOCKED, + + SYSCALL_BUTTON_READ, + SYSCALL_BUTTON_STATE_LEFT, + SYSCALL_BUTTON_STATE_RIGHT, + + SYSCALL_TOUCH_GET_EVENT, + + SYSCALL_HAPTIC_SET_ENABLED, + SYSCALL_HAPTIC_GET_ENABLED, + SYSCALL_HAPTIC_TEST, + SYSCALL_HAPTIC_PLAY, + SYSCALL_HAPTIC_PLAY_CUSTOM, + + SYSCALL_OPTIGA_SIGN, + SYSCALL_OPTIGA_CERT_SIZE, + SYSCALL_OPTIGA_READ_CERT, + SYSCALL_OPTIGA_READ_SEC, + SYSCALL_OPTIGA_RANDOM_BUFFER, + SYSCALL_OPTIGA_SET_SEC_MAX, + + SYSCALL_STORAGE_INIT, + SYSCALL_STORAGE_WIPE, + SYSCALL_STORAGE_IS_UNLOCKED, + SYSCALL_STORAGE_LOCK, + SYSCALL_STORAGE_UNLOCK, + SYSCALL_STORAGE_HAS_PIN, + SYSCALL_STORAGE_PIN_FAILS_INCREASE, + SYSCALL_STORAGE_GET_PIN_REM, + SYSCALL_STORAGE_CHANGE_PIN, + SYSCALL_STORAGE_ENSURE_NOT_WIPE_CODE, + SYSCALL_STORAGE_HAS_WIPE_CODE, + SYSCALL_STORAGE_CHANGE_WIPE_CODE, + SYSCALL_STORAGE_HAS, + SYSCALL_STORAGE_GET, + SYSCALL_STORAGE_SET, + SYSCALL_STORAGE_DELETE, + SYSCALL_STORAGE_SET_COUNTER, + SYSCALL_STORAGE_NEXT_COUNTER, + + SYSCALL_ENTROPY_GET, + + SYSCALL_TRANSLATIONS_WRITE, + SYSCALL_TRANSLATIONS_READ, + SYSCALL_TRANSLATIONS_ERASE, + SYSCALL_TRANSLATIONS_AREA_BYTESIZE, + + SYSCALL_RNG_GET, + + SYSCALL_FIRMWARE_GET_VENDOR, + SYSCALL_FIRMWARE_CALC_HASH, + +} syscall_number_t; + +#endif // SYSCALL_NUMBERS_H \ No newline at end of file diff --git a/core/embed/trezorhal/stm32f4/syscall_stubs.c b/core/embed/trezorhal/stm32f4/syscall_stubs.c new file mode 100644 index 00000000000..1da1d3ef170 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/syscall_stubs.c @@ -0,0 +1,616 @@ +/* + * 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 "syscall.h" + +#ifndef KERNEL_MODE + +// ============================================================================= +// systick.h +// ============================================================================= + +#include "systick.h" + +uint64_t __attribute__((no_stack_protector)) systick_cycles(void) { + return syscall_invoke0_ret64(SYSCALL_SYSTICK_CYCLES); +} + +uint64_t systick_us(void) { return syscall_invoke0_ret64(SYSCALL_SYSTICK_US); } + +uint32_t systick_ms(void) { return syscall_invoke0(SYSCALL_SYSTICK_MS); } + +uint64_t systick_us_to_cycles(uint64_t us) { + uint32_t arg0 = us & 0xFFFFFFFF; + uint32_t arg1 = us >> 32; + return syscall_invoke2_ret64(arg0, arg1, SYSCALL_SYSTICK_US_TO_CYCLES); +} + +// ============================================================================= +// bootutils.h +// ============================================================================= + +#include "bootutils.h" + +void secure_shutdown(void) { + syscall_invoke0(SYSCALL_SECURE_SHUTDOWN); + while (1) + ; +} + +void reboot_to_bootloader(void) { + syscall_invoke0(SYSCALL_REBOOT_TO_BOOTLOADER); + while (1) + ; +} + +void reboot_and_upgrade(const uint8_t hash[32]) { + syscall_invoke1(SYSCALL_REBOOT_AND_UPGRADE, (uint32_t)hash); + while (1) + ; +} + +void reboot(void) { + syscall_invoke0(SYSCALL_REBOOT); + while (1) + ; +} + +// ============================================================================= +// hash_processor.h +// ============================================================================= + +#include "hash_processor.h" + +void hash_processor_sha256_init(hash_sha265_context_t *ctx) { + syscall_invoke1((uint32_t)ctx, SYSCALL_SHA256_INIT); +} + +// Feed the hash next chunk of data +void hash_processor_sha256_update(hash_sha265_context_t *ctx, + const uint8_t *data, uint32_t len) { + syscall_invoke3((uint32_t)ctx, (uint32_t)data, len, SYSCALL_SHA256_UPDATE); +} + +// Finalize the hash calculation, retrieve the digest +void hash_processor_sha256_final(hash_sha265_context_t *ctx, uint8_t *output) { + syscall_invoke2((uint32_t)ctx, (uint32_t)output, SYSCALL_SHA256_FINAL); +} + +void hash_processor_sha256_calc(const uint8_t *data, uint32_t len, + uint8_t *hash) { + syscall_invoke3((uint32_t)data, len, (uint32_t)hash, SYSCALL_SHA256_CALC); +} + +// ============================================================================= +// xdisplay.h +// ============================================================================= + +#include "display.h" + +int display_set_backlight(int level) { + return (int)syscall_invoke1((uint32_t)level, SYSCALL_DISPLAY_SET_BACKLIGHT); +} + +int display_get_backlight(void) { + return (int)syscall_invoke0(SYSCALL_DISPLAY_GET_BACKLIGHT); +} + +int display_set_orientation(int angle) { + return (int)syscall_invoke1((uint32_t)angle, SYSCALL_DISPLAY_SET_ORIENTATION); +} + +int display_get_orientation(void) { + return (int)syscall_invoke0(SYSCALL_DISPLAY_GET_ORIENTATION); +} + +#ifdef XFRAMEBUFFER + +display_fb_info_t display_get_frame_buffer(void) { + display_fb_info_t info; + syscall_invoke1((uint32_t)&info, SYSCALL_DISPLAY_GET_FB_INFO); + return info; +} + +#else // XFRAMEBUFFER + +void display_wait_for_sync(void) { + syscall_invoke0(SYSCALL_DISPLAY_WAIT_FOR_SYNC); +} +#endif + +void display_refresh(void) { syscall_invoke0(SYSCALL_DISPLAY_REFRESH); } + +// ============================================================================= +// usb.h +// ============================================================================= + +#include "usb.h" + +secbool usb_init(const usb_dev_info_t *dev_info) { + return (secbool)syscall_invoke1((uint32_t)dev_info, SYSCALL_USB_INIT); +} + +void usb_deinit(void) { syscall_invoke0(SYSCALL_USB_DEINIT); } + +secbool usb_start(void) { return (secbool)syscall_invoke0(SYSCALL_USB_START); } + +void usb_stop(void) { syscall_invoke0(SYSCALL_USB_STOP); } + +secbool usb_configured(void) { + return (secbool)syscall_invoke0(SYSCALL_USB_CONFIGURED); +} + +// ============================================================================= +// usb_hid.h +// ============================================================================= + +#include "usb_hid.h" + +secbool usb_hid_add(const usb_hid_info_t *hid_info) { + return (secbool)syscall_invoke1((uint32_t)hid_info, SYSCALL_USB_HID_ADD); +} + +secbool usb_hid_can_read(uint8_t iface_num) { + return (secbool)syscall_invoke1((uint32_t)iface_num, + SYSCALL_USB_HID_CAN_READ); +} + +secbool usb_hid_can_write(uint8_t iface_num) { + return (secbool)syscall_invoke1((uint32_t)iface_num, + SYSCALL_USB_HID_CAN_WRITE); +} + +int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { + return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len, + SYSCALL_USB_HID_READ); +} + +int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { + return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len, + SYSCALL_USB_HID_WRITE); +} + +int usb_hid_read_select(uint32_t timeout) { + return (int)syscall_invoke1(timeout, SYSCALL_USB_HID_READ_SELECT); +} + +int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout) { + return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout, + SYSCALL_USB_HID_READ_BLOCKING); +} + +int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, + int timeout) { + return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout, + SYSCALL_USB_HID_WRITE_BLOCKING); +} + +// ============================================================================= +// usb_vcp.h +// ============================================================================= + +#include "usb_vcp.h" + +secbool usb_vcp_add(const usb_vcp_info_t *vcp_info) { + return (secbool)syscall_invoke1((uint32_t)vcp_info, SYSCALL_USB_VCP_ADD); +} + +secbool usb_vcp_can_read(uint8_t iface_num) { + return (secbool)syscall_invoke1((uint32_t)iface_num, + SYSCALL_USB_VCP_CAN_READ); +} + +secbool usb_vcp_can_write(uint8_t iface_num) { + return (secbool)syscall_invoke1((uint32_t)iface_num, + SYSCALL_USB_VCP_CAN_WRITE); +} + +int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { + return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len, + SYSCALL_USB_VCP_READ); +} + +int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { + return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len, + SYSCALL_USB_VCP_WRITE); +} + +int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout) { + return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout, + SYSCALL_USB_VCP_READ_BLOCKING); +} + +int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, + int timeout) { + return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout, + SYSCALL_USB_VCP_WRITE_BLOCKING); +} + +// ============================================================================= +// usb_webusb.h +// ============================================================================= + +#include "usb_webusb.h" + +secbool usb_webusb_add(const usb_webusb_info_t *webusb_info) { + return (secbool)syscall_invoke1((uint32_t)webusb_info, + SYSCALL_USB_WEBUSB_ADD); +} + +secbool usb_webusb_can_read(uint8_t iface_num) { + return (secbool)syscall_invoke1((uint32_t)iface_num, + SYSCALL_USB_WEBUSB_CAN_READ); +} + +secbool usb_webusb_can_write(uint8_t iface_num) { + return (secbool)syscall_invoke1((uint32_t)iface_num, + SYSCALL_USB_WEBUSB_CAN_WRITE); +} + +int usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { + return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len, + SYSCALL_USB_WEBUSB_READ); +} + +int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { + return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len, + SYSCALL_USB_WEBUSB_WRITE); +} + +int usb_webusb_read_select(uint32_t timeout) { + return (int)syscall_invoke1(timeout, SYSCALL_USB_WEBUSB_READ_SELECT); +} + +int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout) { + return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout, + SYSCALL_USB_WEBUSB_READ_BLOCKING); +} + +int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, + uint32_t len, int timeout) { + return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout, + SYSCALL_USB_WEBUSB_WRITE_BLOCKING); +} + +// ============================================================================= +// sdcard.h +// ============================================================================= + +#include "sdcard.h" + +secbool sdcard_power_on(void) { + return (secbool)syscall_invoke0(SYSCALL_SDCARD_POWER_ON); +} + +void sdcard_power_off(void) { syscall_invoke0(SYSCALL_SDCARD_POWER_OFF); } + +secbool sdcard_is_present(void) { + return (secbool)syscall_invoke0(SYSCALL_SDCARD_IS_PRESENT); +} + +uint64_t sdcard_get_capacity_in_bytes(void) { + return syscall_invoke0_ret64(SYSCALL_SDCARD_GET_CAPACITY); +} + +secbool __wur sdcard_read_blocks(uint32_t *dest, uint32_t block_num, + uint32_t num_blocks) { + return (secbool)syscall_invoke3((uint32_t)dest, block_num, num_blocks, + SYSCALL_SDCARD_READ_BLOCKS); +} + +secbool __wur sdcard_write_blocks(const uint32_t *src, uint32_t block_num, + uint32_t num_blocks) { + return (secbool)syscall_invoke3((uint32_t)src, block_num, num_blocks, + SYSCALL_SDCARD_WRITE_BLOCKS); +} + +// ============================================================================= +// unit_variant.h +// ============================================================================= + +bool unit_variant_present(void) { + return (bool)syscall_invoke0(SYSCALL_UNIT_VARIANT_PRESENT); +} +uint8_t unit_variant_get_color(void) { + return (uint8_t)syscall_invoke0(SYSCALL_UNIT_VARIANT_GET_COLOR); +} + +uint8_t unit_variant_get_packaging(void) { + return (uint8_t)syscall_invoke0(SYSCALL_UNIT_VARIANT_GET_PACKAGING); +} + +bool unit_variant_get_btconly(void) { + return (bool)syscall_invoke0(SYSCALL_UNIT_VARIANT_GET_BTCONLY); +} + +bool unit_variant_is_sd_hotswap_enabled(void) { + return (bool)syscall_invoke0(SYSCALL_UNIT_VARIANT_IS_SD_HOTSWAP_ENABLED); +} + +// ============================================================================= +// secret.h +// ============================================================================= + +secbool secret_bootloader_locked(void) { + return (secbool)syscall_invoke0(SYSCALL_SECRET_BOOTLOADER_LOCKED); +} + +// ============================================================================= +// button.h +// ============================================================================= + +#include "button.h" + +uint32_t button_read(void) { return syscall_invoke0(SYSCALL_BUTTON_READ); } + +char button_state_left(void) { + return (char)syscall_invoke0(SYSCALL_BUTTON_STATE_LEFT); +} +char button_state_right(void) { + return (char)syscall_invoke0(SYSCALL_BUTTON_STATE_RIGHT); +} + +// ============================================================================= +// touch.h +// ============================================================================= + +#include "touch.h" + +uint32_t touch_get_event(void) { + return syscall_invoke0(SYSCALL_TOUCH_GET_EVENT); +} + +// ============================================================================= +// haptic.h +// ============================================================================= + +#include "haptic.h" + +void haptic_set_enabled(bool enabled) { + syscall_invoke1((uint32_t)enabled, SYSCALL_HAPTIC_SET_ENABLED); +} + +bool haptic_get_enabled(void) { + return (bool)syscall_invoke0(SYSCALL_HAPTIC_GET_ENABLED); +} + +bool haptic_test(uint16_t duration_ms) { + return (bool)syscall_invoke1(duration_ms, SYSCALL_HAPTIC_TEST); +} + +bool haptic_play(haptic_effect_t effect) { + return (bool)syscall_invoke1((uint32_t)effect, SYSCALL_HAPTIC_PLAY); +} + +bool haptic_play_custom(int8_t amplitude_pct, uint16_t duration_ms) { + return (bool)syscall_invoke2((uint32_t)amplitude_pct, duration_ms, + SYSCALL_HAPTIC_PLAY_CUSTOM); +} + +// ============================================================================= +// optiga.h +// ============================================================================= + +#include "optiga.h" + +optiga_sign_result optiga_sign(uint8_t index, const uint8_t *digest, + size_t digest_size, uint8_t *signature, + size_t max_sig_size, size_t *sig_size) { + return (optiga_sign_result)syscall_invoke6( + index, (uint32_t)digest, digest_size, (uint32_t)signature, max_sig_size, + (uint32_t)sig_size, SYSCALL_OPTIGA_SIGN); +} + +bool optiga_cert_size(uint8_t index, size_t *cert_size) { + return (bool)syscall_invoke2(index, (uint32_t)cert_size, + SYSCALL_OPTIGA_CERT_SIZE); +} + +bool optiga_read_cert(uint8_t index, uint8_t *cert, size_t max_cert_size, + size_t *cert_size) { + return (bool)syscall_invoke4(index, (uint32_t)cert, max_cert_size, + (uint32_t)cert_size, SYSCALL_OPTIGA_READ_CERT); +} + +bool optiga_read_sec(uint8_t *sec) { + return (bool)syscall_invoke1((uint32_t)sec, SYSCALL_OPTIGA_READ_SEC); +} + +bool optiga_random_buffer(uint8_t *dest, size_t size) { + return (bool)syscall_invoke2((uint32_t)dest, size, + SYSCALL_OPTIGA_RANDOM_BUFFER); +} + +#if PYOPT == 0 +void optiga_set_sec_max(void) { syscall_invoke0(SYSCALL_OPTIGA_SET_SEC_MAX); } + +#endif + +// ============================================================================= +// storage.h +// ============================================================================= + +#include "storage.h" + +static PIN_UI_WAIT_CALLBACK storage_init_callback = NULL; + +static void storage_init_callback_wrapper(uint32_t wait, uint32_t progress, + enum storage_ui_message_t message) { + secbool retval = storage_init_callback(wait, progress, message); + syscall_return_from_callback(retval); +} + +void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt, + const uint16_t salt_len) { + storage_init_callback = callback; + + syscall_invoke3((uint32_t)storage_init_callback_wrapper, (uint32_t)salt, + salt_len, SYSCALL_STORAGE_INIT); +} + +void storage_wipe(void) { syscall_invoke0(SYSCALL_STORAGE_WIPE); } +secbool storage_is_unlocked(void) { + return (secbool)syscall_invoke0(SYSCALL_STORAGE_IS_UNLOCKED); +} + +void storage_lock(void) { syscall_invoke0(SYSCALL_STORAGE_LOCK); } + +secbool storage_unlock(const uint8_t *pin, size_t pin_len, + const uint8_t *ext_salt) { + return (secbool)syscall_invoke3((uint32_t)pin, pin_len, (uint32_t)ext_salt, + SYSCALL_STORAGE_UNLOCK); +} + +secbool storage_has_pin(void) { + return (secbool)syscall_invoke0(SYSCALL_STORAGE_HAS_PIN); +} +secbool storage_pin_fails_increase(void) { + return (secbool)syscall_invoke0(SYSCALL_STORAGE_PIN_FAILS_INCREASE); +} + +uint32_t storage_get_pin_rem(void) { + return syscall_invoke0(SYSCALL_STORAGE_GET_PIN_REM); +} + +secbool storage_change_pin(const uint8_t *oldpin, size_t oldpin_len, + const uint8_t *newpin, size_t newpin_len, + const uint8_t *old_ext_salt, + const uint8_t *new_ext_salt) { + return (secbool)syscall_invoke6( + (uint32_t)oldpin, oldpin_len, (uint32_t)newpin, newpin_len, + (uint32_t)old_ext_salt, (uint32_t)new_ext_salt, + SYSCALL_STORAGE_CHANGE_PIN); +} + +void storage_ensure_not_wipe_code(const uint8_t *pin, size_t pin_len) { + syscall_invoke2((uint32_t)pin, pin_len, SYSCALL_STORAGE_ENSURE_NOT_WIPE_CODE); +} + +secbool storage_has_wipe_code(void) { + return (secbool)syscall_invoke0(SYSCALL_STORAGE_HAS_WIPE_CODE); +} + +secbool storage_change_wipe_code(const uint8_t *pin, size_t pin_len, + const uint8_t *ext_salt, + const uint8_t *wipe_code, + size_t wipe_code_len) { + return (secbool)syscall_invoke5((uint32_t)pin, pin_len, (uint32_t)ext_salt, + (uint32_t)wipe_code, wipe_code_len, + SYSCALL_STORAGE_CHANGE_WIPE_CODE); +} + +secbool storage_has(const uint16_t key) { + return (secbool)syscall_invoke1(key, SYSCALL_STORAGE_HAS); +} + +secbool storage_get(const uint16_t key, void *val, const uint16_t max_len, + uint16_t *len) { + return (secbool)syscall_invoke4(key, (uint32_t)val, max_len, (uint32_t)len, + SYSCALL_STORAGE_GET); +} + +secbool storage_set(const uint16_t key, const void *val, const uint16_t len) { + return (secbool)syscall_invoke3(key, (uint32_t)val, len, SYSCALL_STORAGE_SET); +} + +secbool storage_delete(const uint16_t key) { + return (secbool)syscall_invoke1(key, SYSCALL_STORAGE_DELETE); +} + +secbool storage_set_counter(const uint16_t key, const uint32_t count) { + return (secbool)syscall_invoke2(key, count, SYSCALL_STORAGE_SET_COUNTER); +} + +secbool storage_next_counter(const uint16_t key, uint32_t *count) { + return (secbool)syscall_invoke2(key, (uint32_t)count, + SYSCALL_STORAGE_NEXT_COUNTER); +} + +// ============================================================================= +// entropy.h +// ============================================================================= + +void entropy_get(uint8_t *buf) { + syscall_invoke1((uint32_t)buf, SYSCALL_ENTROPY_GET); +} + +// ============================================================================= +// translations.h +// ============================================================================= + +#include "translations.h" + +bool translations_write(const uint8_t *data, uint32_t offset, uint32_t len) { + return (bool)syscall_invoke3((uint32_t)data, offset, len, + SYSCALL_TRANSLATIONS_WRITE); +} + +const uint8_t *translations_read(uint32_t *len, uint32_t offset) { + return (const uint8_t *)syscall_invoke2((uint32_t)len, offset, + SYSCALL_TRANSLATIONS_READ); +} + +void translations_erase(void) { syscall_invoke0(SYSCALL_TRANSLATIONS_ERASE); } + +uint32_t translations_area_bytesize(void) { + return syscall_invoke0(SYSCALL_TRANSLATIONS_AREA_BYTESIZE); +} + +// ============================================================================= +// rng.h +// ============================================================================= + +#include "rng.h" + +uint32_t rng_get(void) { return syscall_invoke0(SYSCALL_RNG_GET); } + +// ============================================================================= +// fwutils.h +// ============================================================================= + +#include "fwutils.h" + +secbool firmware_get_vendor(char *buff, size_t buff_size) { + return syscall_invoke2((uint32_t)buff, buff_size, + SYSCALL_FIRMWARE_GET_VENDOR); +} + +static firmware_hash_callback_t firmware_hash_callback = NULL; + +static void firmware_hash_callback_wrapper(void *context, uint32_t progress, + uint32_t total) { + firmware_hash_callback(context, progress, total); + syscall_return_from_callback(0); +} + +secbool firmware_calc_hash(const uint8_t *challenge, size_t challenge_len, + uint8_t *hash, size_t hash_len, + firmware_hash_callback_t callback, + void *callback_context) { + firmware_hash_callback = callback; + + return syscall_invoke6((uint32_t)challenge, challenge_len, (uint32_t)hash, + hash_len, (uint32_t)firmware_hash_callback_wrapper, + (uint32_t)callback_context, + SYSCALL_FIRMWARE_CALC_HASH); +} +#endif diff --git a/core/embed/trezorhal/stm32f4/systick.c b/core/embed/trezorhal/stm32f4/systick.c index 13a1b71eb48..5bfbe2cac29 100644 --- a/core/embed/trezorhal/stm32f4/systick.c +++ b/core/embed/trezorhal/stm32f4/systick.c @@ -21,6 +21,7 @@ #include #include "irq.h" +#include "mpu.h" #include "platform.h" #include "systemview.h" @@ -28,6 +29,8 @@ #include "systick_internal.h" #include "systimer.h" +#ifdef KERNEL_MODE + // SysTick driver state typedef struct { // Set if the driver is initialized @@ -158,6 +161,7 @@ uint64_t systick_us(void) { void SysTick_Handler(void) { SEGGER_SYSVIEW_RecordEnterISR(); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); systick_driver_t* drv = &g_systick_driver; @@ -178,9 +182,12 @@ void SysTick_Handler(void) { systimer_dispatch_expired_timers(drv->cycles); } + mpu_restore(mpu_mode); SEGGER_SYSVIEW_RecordExitISR(); } +#endif // KERNEL_MODE + void systick_delay_us(uint64_t us) { uint64_t delay_cycles = systick_us_to_cycles(us); int64_t cycles_per_ms = systick_us_to_cycles(1000); diff --git a/core/embed/trezorhal/stm32f4/systimer.c b/core/embed/trezorhal/stm32f4/systimer.c index ca7ae63d28e..10736a5b771 100644 --- a/core/embed/trezorhal/stm32f4/systimer.c +++ b/core/embed/trezorhal/stm32f4/systimer.c @@ -25,6 +25,8 @@ #include "systick_internal.h" #include "systimer.h" +#ifdef KERNEL_MODE + // Maximum number of registered user timer // // Consider different implementation (i.e. priority queue @@ -235,3 +237,5 @@ void systimer_dispatch_expired_timers(uint64_t cycles) { timer->callback(timer->context); } } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/touch/ft6x36.c b/core/embed/trezorhal/stm32f4/touch/ft6x36.c index f03ac46a331..e107bbf8ab8 100644 --- a/core/embed/trezorhal/stm32f4/touch/ft6x36.c +++ b/core/embed/trezorhal/stm32f4/touch/ft6x36.c @@ -20,6 +20,8 @@ #include STM32_HAL_H #include TREZOR_BOARD +#ifdef KERNEL_MODE + #include #include #include @@ -554,3 +556,5 @@ uint32_t touch_get_event(void) { return event; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/usb/usb.c b/core/embed/trezorhal/stm32f4/usb/usb.c index 7b0bd295e19..b4e7a974fdf 100644 --- a/core/embed/trezorhal/stm32f4/usb/usb.c +++ b/core/embed/trezorhal/stm32f4/usb/usb.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#ifdef KERNEL_MODE + #include STM32_HAL_H #include "usb.h" @@ -736,3 +738,5 @@ static const USBD_ClassTypeDef usb_class = { .GetDeviceQualifierDescriptor = NULL, .GetUsrStrDescriptor = usb_class_get_usrstr_desc, }; + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/usb/usb_class_hid.c b/core/embed/trezorhal/stm32f4/usb/usb_class_hid.c index 48feb58866f..67512153afb 100644 --- a/core/embed/trezorhal/stm32f4/usb/usb_class_hid.c +++ b/core/embed/trezorhal/stm32f4/usb/usb_class_hid.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#ifdef KERNEL_MODE + #include "common.h" #include "random_delays.h" @@ -444,3 +446,5 @@ static const USBD_ClassTypeDef usb_hid_class = { .GetDeviceQualifierDescriptor = NULL, .GetUsrStrDescriptor = NULL, }; + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/usb/usb_class_vcp.c b/core/embed/trezorhal/stm32f4/usb/usb_class_vcp.c index 7905d884f4b..4559fef33ba 100644 --- a/core/embed/trezorhal/stm32f4/usb/usb_class_vcp.c +++ b/core/embed/trezorhal/stm32f4/usb/usb_class_vcp.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#ifdef KERNEL_MODE + #include "common.h" #include "usb_internal.h" @@ -586,3 +588,5 @@ static const USBD_ClassTypeDef usb_vcp_class = { }; static const USBD_ClassTypeDef usb_vcp_data_class = {}; + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/usb/usb_class_webusb.c b/core/embed/trezorhal/stm32f4/usb/usb_class_webusb.c index 5d326517c32..8d9765829fe 100644 --- a/core/embed/trezorhal/stm32f4/usb/usb_class_webusb.c +++ b/core/embed/trezorhal/stm32f4/usb/usb_class_webusb.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#ifdef KERNEL_MODE + #include "common.h" #include "random_delays.h" @@ -354,3 +356,5 @@ static const USBD_ClassTypeDef usb_webusb_class = { .GetDeviceQualifierDescriptor = NULL, .GetUsrStrDescriptor = NULL, }; + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/usb/usbd_conf.c b/core/embed/trezorhal/stm32f4/usb/usbd_conf.c index 598b47e128b..2db2a648843 100644 --- a/core/embed/trezorhal/stm32f4/usb/usbd_conf.c +++ b/core/embed/trezorhal/stm32f4/usb/usbd_conf.c @@ -50,11 +50,15 @@ * ****************************************************************************** */ + +#ifdef KERNEL_MODE + /* Includes ------------------------------------------------------------------*/ #include STM32_HAL_H #include "usbd_core.h" #include "usb.h" #include "irq.h" +#include "mpu.h" #include "systemview.h" /* Private typedef -----------------------------------------------------------*/ @@ -796,9 +800,11 @@ void OTG_FS_IRQHandler(void) { #endif SEGGER_SYSVIEW_RecordEnterISR(); IRQ_ENTER(OTG_FS_IRQn); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); if (pcd_fs_handle.Instance) { HAL_PCD_IRQHandler(&pcd_fs_handle); } + mpu_restore(mpu_mode); IRQ_EXIT(OTG_FS_IRQn); SEGGER_SYSVIEW_RecordExitISR(); } @@ -807,9 +813,11 @@ void OTG_FS_IRQHandler(void) { void OTG_HS_IRQHandler(void) { SEGGER_SYSVIEW_RecordEnterISR(); IRQ_ENTER(OTG_HS_IRQn); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); if (pcd_hs_handle.Instance) { HAL_PCD_IRQHandler(&pcd_hs_handle); } + mpu_restore(mpu_mode); IRQ_EXIT(OTG_HS_IRQn); SEGGER_SYSVIEW_RecordExitISR(); } @@ -862,25 +870,31 @@ static void OTG_CMD_WKUP_Handler(PCD_HandleTypeDef *pcd_handle) { #if defined(USE_USB_FS) void OTG_FS_WKUP_IRQHandler(void) { IRQ_ENTER(OTG_FS_WKUP_IRQn); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); if (pcd_fs_handle.Instance) { OTG_CMD_WKUP_Handler(&pcd_fs_handle); } /* Clear EXTI pending Bit*/ __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG(); + mpu_restore(mpu_mode); IRQ_EXIT(OTG_FS_WKUP_IRQn); } #endif #if defined(USE_USB_HS) void OTG_HS_WKUP_IRQHandler(void) { IRQ_ENTER(OTG_HS_WKUP_IRQn); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); if (pcd_hs_handle.Instance) { OTG_CMD_WKUP_Handler(&pcd_hs_handle); } /* Clear EXTI pending Bit*/ __HAL_USB_HS_EXTI_CLEAR_FLAG(); + mpu_restore(mpu_mode); IRQ_EXIT(OTG_HS_WKUP_IRQn); } #endif #endif +#endif // KERNEL_MODE + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/core/embed/trezorhal/stm32f4/usb/usbd_core.c b/core/embed/trezorhal/stm32f4/usb/usbd_core.c index 2663a6d88c3..5188125601d 100644 --- a/core/embed/trezorhal/stm32f4/usb/usbd_core.c +++ b/core/embed/trezorhal/stm32f4/usb/usbd_core.c @@ -27,6 +27,8 @@ ****************************************************************************** */ +#ifdef KERNEL_MODE + /* Includes ------------------------------------------------------------------*/ #include "usbd_core.h" @@ -576,5 +578,7 @@ USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev) * @} */ +#endif // KERNEL_MODE + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/core/embed/trezorhal/stm32f4/usb/usbd_ctlreq.c b/core/embed/trezorhal/stm32f4/usb/usbd_ctlreq.c index 31c97e5f635..6b4d2177c88 100644 --- a/core/embed/trezorhal/stm32f4/usb/usbd_ctlreq.c +++ b/core/embed/trezorhal/stm32f4/usb/usbd_ctlreq.c @@ -27,6 +27,8 @@ ****************************************************************************** */ +#ifdef KERNEL_MODE + /* Includes ------------------------------------------------------------------*/ #include "usbd_ctlreq.h" #include "usbd_ioreq.h" @@ -784,4 +786,6 @@ static uint8_t USBD_GetLen(const uint8_t *buf) * @} */ +#endif // KERNEL_MODE + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/core/embed/trezorhal/stm32f4/usb/usbd_ioreq.c b/core/embed/trezorhal/stm32f4/usb/usbd_ioreq.c index ebbdd3b1520..c22e0eef62b 100644 --- a/core/embed/trezorhal/stm32f4/usb/usbd_ioreq.c +++ b/core/embed/trezorhal/stm32f4/usb/usbd_ioreq.c @@ -27,6 +27,8 @@ ****************************************************************************** */ +#ifdef KERNEL_MODE + /* Includes ------------------------------------------------------------------*/ #include "usbd_ioreq.h" @@ -235,4 +237,6 @@ uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t ep_addr) * @} */ +#endif // KERNEL_MODE + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/core/embed/trezorhal/stm32f4/util.s b/core/embed/trezorhal/stm32f4/util.S similarity index 100% rename from core/embed/trezorhal/stm32f4/util.s rename to core/embed/trezorhal/stm32f4/util.S diff --git a/core/embed/trezorhal/stm32f4/vectortable.s b/core/embed/trezorhal/stm32f4/vectortable.S similarity index 96% rename from core/embed/trezorhal/stm32f4/vectortable.s rename to core/embed/trezorhal/stm32f4/vectortable.S index 08b34f99f8f..1cfec8c262f 100644 --- a/core/embed/trezorhal/stm32f4/vectortable.s +++ b/core/embed/trezorhal/stm32f4/vectortable.S @@ -2,6 +2,8 @@ .text +#ifdef KERNEL_MODE + .global default_handler .type default_handler, STT_FUNC default_handler: @@ -126,4 +128,14 @@ vector_table: add_handler LTDC_ER_IRQHandler add_handler DMA2D_IRQHandler +#else + + .section .vector_table, "a" +vector_table: + .word main_stack_base // defined in linker script + .word reset_handler + + +#endif + .end diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c index 34de6abaeee..d08911ae8c0 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c @@ -39,6 +39,8 @@ #error "Incompatible display resolution" #endif +#ifdef KERNEL_MODE + // Display driver instance display_driver_t g_display_driver = { .initialized = false, @@ -170,3 +172,5 @@ int display_get_orientation(void) { return drv->orientation_angle; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c index 889c79545d8..af3ff91e448 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c @@ -32,6 +32,7 @@ #include "gfx_bitblt.h" #include "irq.h" +#include "mpu.h" #ifndef BOARDLOADER #include "bg_copy.h" @@ -41,6 +42,8 @@ #error Framebuffer only supported on STM32U5 for now #endif +#ifdef KERNEL_MODE + // The following code supports only 1 or 2 frame buffers _Static_assert(FRAME_BUFFER_COUNT == 1 || FRAME_BUFFER_COUNT == 2); @@ -95,7 +98,7 @@ static void bg_copy_callback(void) { } // Interrupt routing handling TE signal -void DISPLAY_TE_INTERRUPT_HANDLER(void) { +static void display_te_interrupt_handler(void) { display_driver_t *drv = &g_display_driver; __HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN); @@ -133,6 +136,12 @@ void DISPLAY_TE_INTERRUPT_HANDLER(void) { break; } } + +void DISPLAY_TE_INTERRUPT_HANDLER(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); + display_te_interrupt_handler(); + mpu_restore(mpu_mode); +} #endif display_fb_info_t display_get_frame_buffer(void) { @@ -277,6 +286,8 @@ void display_ensure_refreshed(void) { #endif } +#endif // KERNEL_MODE + void display_fill(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c index fec5bf3c372..8976f552bca 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c @@ -24,6 +24,8 @@ #include "irq.h" #include "mpu.h" +#ifdef KERNEL_MODE + __IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS = (__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE); __IO DISP_MEM_TYPE *const DISPLAY_DATA_ADDRESS = @@ -148,3 +150,5 @@ void display_io_init_te_interrupt(void) { NVIC_EnableIRQ(DISPLAY_TE_INTERRUPT_NUM); } #endif + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c index 412427a0b94..c2f4c7e166f 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c @@ -24,6 +24,8 @@ #include "display_io.h" #include "display_panel.h" +#ifdef KERNEL_MODE + void display_refresh(void) { // If the framebuffer is not used the, we do not need // to refresh the display explicitly as we write the data @@ -49,6 +51,8 @@ static inline void set_window(const gfx_bitblt_t* bb) { bb->dst_y + bb->height + 1); } +#endif // KERNEL_MODE + // For future notice, if we ever want to do a new model using progressive // rendering. // diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_panel.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_panel.c index 0d9bcf41519..bfe04057024 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_panel.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_panel.c @@ -34,6 +34,8 @@ #include "panels/lx154a2482.h" #endif +#ifdef KERNEL_MODE + // using const volatile instead of #define results in binaries that change // only in 1-byte when the flag changes. // using #define leads compiler to over-optimize the code leading to bigger @@ -248,3 +250,5 @@ void display_panel_rotate(int angle) { lx154a2482_rotate(angle, &g_window_padding); #endif } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/bg_copy.c b/core/embed/trezorhal/stm32u5/bg_copy.c index a3d66d415f4..ba54494bf6c 100644 --- a/core/embed/trezorhal/stm32u5/bg_copy.c +++ b/core/embed/trezorhal/stm32u5/bg_copy.c @@ -1,8 +1,11 @@ #include "bg_copy.h" #include "irq.h" +#include "mpu.h" #include STM32_HAL_H +#ifdef KERNEL_MODE + #define MAX_DATA_SIZE 0xFFF0 static volatile uint32_t dma_transfer_remaining = 0; @@ -33,6 +36,8 @@ void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma) { } void GPDMA1_Channel0_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); + if ((DMA_Handle.Instance->CSR & DMA_CSR_TCF) == 0) { // error, abort the transfer and allow the next one to start dma_data_transferred = 0; @@ -53,6 +58,8 @@ void GPDMA1_Channel0_IRQHandler(void) { bg_copy_callback(); } } + + mpu_restore(mpu_mode); } bool bg_copy_pending(void) { return dma_transfer_remaining > 0; } @@ -116,3 +123,5 @@ void bg_copy_abort(void) { data_src = NULL; data_dst = NULL; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/consumption_mask.c b/core/embed/trezorhal/stm32u5/consumption_mask.c index fcc51b3f326..3d81dc184e1 100644 --- a/core/embed/trezorhal/stm32u5/consumption_mask.c +++ b/core/embed/trezorhal/stm32u5/consumption_mask.c @@ -20,6 +20,8 @@ #include STM32_HAL_H #include "rng.h" +#ifdef KERNEL_MODE + #define SAMPLES 119 #define TIMER_PERIOD 16000 // cca 10 KHz @ 160MHz @@ -138,3 +140,5 @@ void consumption_mask_init(void) { HAL_DMAEx_List_Start(&dma_handle); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/entropy.c b/core/embed/trezorhal/stm32u5/entropy.c index c05f2762ee6..695371d3048 100644 --- a/core/embed/trezorhal/stm32u5/entropy.c +++ b/core/embed/trezorhal/stm32u5/entropy.c @@ -27,6 +27,8 @@ #include "stm32u5xx_ll_utils.h" +#ifdef KERNEL_MODE + static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; void entropy_init(void) { @@ -58,3 +60,5 @@ void entropy_init(void) { } void entropy_get(uint8_t *buf) { memcpy(buf, g_hw_entropy, HW_ENTROPY_LEN); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/fault_handlers.c b/core/embed/trezorhal/stm32u5/fault_handlers.c index d2cfd3bbd07..2e4bbc78f83 100644 --- a/core/embed/trezorhal/stm32u5/fault_handlers.c +++ b/core/embed/trezorhal/stm32u5/fault_handlers.c @@ -1,4 +1,7 @@ #include "common.h" +#include "mpu.h" + +#ifdef KERNEL_MODE void fault_handlers_init(void) { // Enable BUS fault and USAGE fault handlers @@ -13,12 +16,19 @@ void HardFault_Handler(void) { // Fix stack pointer __set_MSP((uint32_t)&_estack); + mpu_reconfig(MPU_MODE_DEFAULT); error_shutdown("(HF)"); } -void MemManage_Handler(void) { error_shutdown("(MM)"); } +void MemManage_Handler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(MM)"); +} -void BusFault_Handler(void) { error_shutdown("(BF)"); } +void BusFault_Handler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(BF)"); +} void UsageFault_Handler(void) { if (SCB->CFSR & SCB_CFSR_STKOF_Msk) { @@ -26,28 +36,41 @@ void UsageFault_Handler(void) { extern uint8_t _estack; // linker script symbol // Fix stack pointer __set_MSP((uint32_t)&_estack); + mpu_reconfig(MPU_MODE_DEFAULT); error_shutdown("(SO)"); } else { // Other error + mpu_reconfig(MPU_MODE_DEFAULT); error_shutdown("(UF)"); } } -void SecureFault_Handler(void) { error_shutdown("(SF)"); } +void SecureFault_Handler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(SF)"); +} -void GTZC_IRQHandler(void) { error_shutdown("(IA)"); } +void GTZC_IRQHandler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + error_shutdown("(IA)"); +} void NMI_Handler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); // Clock Security System triggered NMI if ((RCC->CIFR & RCC_CIFR_CSSF) != 0) { error_shutdown("(CS)"); } + mpu_restore(mpu_mode); } // from util.s extern void shutdown_privileged(void); void PVD_PVM_IRQHandler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); TIM1->CCR1 = 0; // turn off display backlight shutdown_privileged(); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/flash.c b/core/embed/trezorhal/stm32u5/flash.c index 3f72031cf7d..f25c2ba6c85 100644 --- a/core/embed/trezorhal/stm32u5/flash.c +++ b/core/embed/trezorhal/stm32u5/flash.c @@ -26,6 +26,8 @@ #include "flash.h" #include "model.h" +#ifdef KERNEL_MODE + #ifdef STM32U585xx #define FLASH_BANK_PAGES 128 #define FLASH_SECTOR_COUNT (FLASH_BANK_PAGES * 2) @@ -213,3 +215,5 @@ secbool flash_write_block(uint16_t sector, uint32_t offset, const flash_block_t block) { return flash_write_quadword(sector, offset, block); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/flash_otp.c b/core/embed/trezorhal/stm32u5/flash_otp.c index f3c6163e01f..9486ccf7a44 100644 --- a/core/embed/trezorhal/stm32u5/flash_otp.c +++ b/core/embed/trezorhal/stm32u5/flash_otp.c @@ -24,6 +24,8 @@ #include "flash.h" #include "mpu.h" +#ifdef KERNEL_MODE + void flash_otp_init() { // intentionally left empty } @@ -125,3 +127,5 @@ secbool flash_otp_is_locked(uint8_t block) { return is_locked; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c b/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c index d87ace2fddf..7b1168c50b1 100644 --- a/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c +++ b/core/embed/trezorhal/stm32u5/haptic/drv2625/drv2625.c @@ -29,6 +29,8 @@ #include STM32_HAL_H +#ifdef KERNEL_MODE + // Maximum amplitude of the vibration effect // (DRV2625 supports 7-bit amplitude) #define MAX_AMPLITUDE 127 @@ -324,3 +326,5 @@ bool haptic_play_custom(int8_t amplitude_pct, uint16_t duration_ms) { bool haptic_test(uint16_t duration_ms) { return haptic_play_rtp(PRODTEST_EFFECT_AMPLITUDE, duration_ms); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/hash_processor.c b/core/embed/trezorhal/stm32u5/hash_processor.c index b9be38dbd97..6d048abfb52 100644 --- a/core/embed/trezorhal/stm32u5/hash_processor.c +++ b/core/embed/trezorhal/stm32u5/hash_processor.c @@ -4,8 +4,11 @@ #include STM32_HAL_H #include "irq.h" #include "memzero.h" +#include "mpu.h" #include "sha2.h" +#ifdef KERNEL_MODE + HASH_HandleTypeDef hhash = {0}; DMA_HandleTypeDef DMA_Handle = {0}; @@ -44,7 +47,11 @@ void hash_processor_init(void) { NVIC_EnableIRQ(GPDMA1_Channel12_IRQn); } -void GPDMA1_Channel12_IRQHandler(void) { HAL_DMA_IRQHandler(&DMA_Handle); } +void GPDMA1_Channel12_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); + HAL_DMA_IRQHandler(&DMA_Handle); + mpu_restore(mpu_mode); +} static void hash_processor_sha256_calc_dma(const uint8_t *data, uint32_t len, uint8_t *hash) { @@ -125,3 +132,5 @@ void hash_processor_sha256_final(hash_sha265_context_t *ctx, uint8_t *output) { memcpy(output, tmp_out, SHA256_DIGEST_LENGTH); memzero(tmp_out, sizeof(tmp_out)); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/i2c_bus.c b/core/embed/trezorhal/stm32u5/i2c_bus.c index 127aabed7f9..2a0a1211aa3 100644 --- a/core/embed/trezorhal/stm32u5/i2c_bus.c +++ b/core/embed/trezorhal/stm32u5/i2c_bus.c @@ -25,8 +25,11 @@ #include "common.h" #include "i2c_bus.h" #include "irq.h" +#include "mpu.h" #include "systimer.h" +#ifdef KERNEL_MODE + // Using calculation from STM32CubeMX // PCLKx as source, assumed 160MHz // Fast mode, freq = 400kHz, Rise time = 250ns, Fall time = 100ns @@ -865,30 +868,44 @@ static void i2c_bus_er_handler(i2c_bus_t* bus) { #ifdef I2C_INSTANCE_0 void I2C_INSTANCE_0_EV_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_ev_handler(&g_i2c_bus_driver[0]); + mpu_restore(mpu_mode); } void I2C_INSTANCE_0_ER_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_er_handler(&g_i2c_bus_driver[0]); + mpu_restore(mpu_mode); } #endif #ifdef I2C_INSTANCE_1 void I2C_INSTANCE_1_EV_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_ev_handler(&g_i2c_bus_driver[1]); + mpu_restore(mpu_mode); } void I2C_INSTANCE_1_ER_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_er_handler(&g_i2c_bus_driver[1]); + mpu_restore(mpu_mode); } #endif #ifdef I2C_INSTANCE_2 void I2C_INSTANCE_2_EV_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_ev_handler(&g_i2c_bus_driver[2]); + mpu_restore(mpu_mode); } void I2C_INSTANCE_2_ER_IRQHandler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); i2c_bus_er_handler(&g_i2c_bus_driver[2]); + mpu_restore(mpu_mode); } #endif + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/limited_util.s b/core/embed/trezorhal/stm32u5/limited_util.S similarity index 100% rename from core/embed/trezorhal/stm32u5/limited_util.s rename to core/embed/trezorhal/stm32u5/limited_util.S diff --git a/core/embed/trezorhal/stm32u5/lowlevel.c b/core/embed/trezorhal/stm32u5/lowlevel.c index e30aa526739..7270180782d 100644 --- a/core/embed/trezorhal/stm32u5/lowlevel.c +++ b/core/embed/trezorhal/stm32u5/lowlevel.c @@ -19,6 +19,8 @@ #include STM32_HAL_H +#ifdef KERNEL_MODE + #include "lowlevel.h" #include "common.h" #include "flash.h" @@ -310,3 +312,5 @@ secbool reset_flags_check(void) { void reset_flags_reset(void) { RCC->CSR |= RCC_CSR_RMVF; // clear the reset flags } + +#endif // #ifdef KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/monoctr.c b/core/embed/trezorhal/stm32u5/monoctr.c index 24171eab85a..f44711b4ad2 100644 --- a/core/embed/trezorhal/stm32u5/monoctr.c +++ b/core/embed/trezorhal/stm32u5/monoctr.c @@ -23,6 +23,8 @@ #include "mpu.h" #include "secret.h" +#ifdef KERNEL_MODE + static int32_t get_offset(monoctr_type_t type) { switch (type) { case MONOCTR_BOOTLOADER_VERSION: @@ -129,3 +131,5 @@ secbool monoctr_read(monoctr_type_t type, uint8_t *value) { return sectrue; } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/mpu.c b/core/embed/trezorhal/stm32u5/mpu.c index 5b3c1671fd0..e0ab0adf1bd 100644 --- a/core/embed/trezorhal/stm32u5/mpu.c +++ b/core/embed/trezorhal/stm32u5/mpu.c @@ -21,11 +21,14 @@ #include #include "common.h" +#include "irq.h" #include "model.h" #include "mpu.h" #include "stm32u5xx_ll_cortex.h" +#ifdef KERNEL_MODE + // region type #define MPUX_TYPE_FLASH_CODE 0 #define MPUX_TYPE_SRAM 1 @@ -115,6 +118,7 @@ static void mpu_set_attributes(void) { #define BOARDLOADER_SIZE SIZE_48K #define BOOTLOADER_SIZE BOOTLOADER_IMAGE_MAXSIZE #define FIRMWARE_SIZE FIRMWARE_IMAGE_MAXSIZE +#define COREAPP_SIZE (FIRMWARE_IMAGE_MAXSIZE - KERNEL_SIZE) #define STORAGE_START \ (FLASH_BASE + SECRET_SIZE + BOARDLOADER_SIZE + BOOTLOADER_SIZE) #define STORAGE_SIZE NORCOW_SECTOR_SIZE* STORAGE_AREAS_COUNT @@ -335,3 +339,5 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { } void mpu_restore(mpu_mode_t mode) { mpu_reconfig(mode); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/platform.c b/core/embed/trezorhal/stm32u5/platform.c index 19feb4d5a4c..393a43b5303 100644 --- a/core/embed/trezorhal/stm32u5/platform.c +++ b/core/embed/trezorhal/stm32u5/platform.c @@ -23,6 +23,8 @@ #include "rng.h" #include TREZOR_BOARD +#ifdef KERNEL_MODE + const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U}; const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; @@ -213,3 +215,5 @@ void SystemInit(void) { // enable instruction cache in default 2-way mode ICACHE->CR = ICACHE_CR_EN; } + +#endif // #ifdef KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/sdcard.c b/core/embed/trezorhal/stm32u5/sdcard.c index 714a48d4e1d..4d83000ae15 100644 --- a/core/embed/trezorhal/stm32u5/sdcard.c +++ b/core/embed/trezorhal/stm32u5/sdcard.c @@ -49,12 +49,15 @@ #include #include "irq.h" +#include "mpu.h" #include "sdcard.h" #define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC1_CLK_ENABLE() #define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC1_CLK_DISABLE() #define SDMMC_IRQn SDMMC1_IRQn +#ifdef KERNEL_MODE + static SD_HandleTypeDef sd_handle = {0}; // this function is inspired by functions in stm32f4xx_ll_sdmmc.c @@ -234,9 +237,11 @@ uint64_t sdcard_get_capacity_in_bytes(void) { void SDMMC1_IRQHandler(void) { IRQ_ENTER(SDIO_IRQn); + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); if (sd_handle.Instance) { HAL_SD_IRQHandler(&sd_handle); } + mpu_restore(mpu_mode); IRQ_EXIT(SDIO_IRQn); } @@ -333,3 +338,5 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, return sectrue * (err == HAL_OK); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/secret.c b/core/embed/trezorhal/stm32u5/secret.c index 17fb93d08ba..47602e50b86 100644 --- a/core/embed/trezorhal/stm32u5/secret.c +++ b/core/embed/trezorhal/stm32u5/secret.c @@ -11,6 +11,8 @@ #include "rng.h" #include "secure_aes.h" +#ifdef KERNEL_MODE + static secbool bootloader_locked = secfalse; secbool secret_verify_header(void) { @@ -349,3 +351,5 @@ void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all) { secret_disable_access(); } } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/secure_aes.c b/core/embed/trezorhal/stm32u5/secure_aes.c index 61fa3cd8a0d..94f8afe5c8c 100644 --- a/core/embed/trezorhal/stm32u5/secure_aes.c +++ b/core/embed/trezorhal/stm32u5/secure_aes.c @@ -25,6 +25,8 @@ #include #include "memzero.h" +#ifdef KERNEL_MODE + #define AES_BLOCK_SIZE 16 secbool secure_aes_init(void) { @@ -199,3 +201,5 @@ secbool secure_aes_ecb_decrypt_hw(const uint8_t* input, size_t size, return sectrue; } + +#endif // KERNEL_MODE \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/syscall.c b/core/embed/trezorhal/stm32u5/syscall.c new file mode 120000 index 00000000000..4995488e2a7 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/syscall.c @@ -0,0 +1 @@ +../stm32f4/syscall.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/syscall.h b/core/embed/trezorhal/stm32u5/syscall.h new file mode 120000 index 00000000000..8563747ddfd --- /dev/null +++ b/core/embed/trezorhal/stm32u5/syscall.h @@ -0,0 +1 @@ +../stm32f4/syscall.h \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/syscall_dispatch.c b/core/embed/trezorhal/stm32u5/syscall_dispatch.c new file mode 120000 index 00000000000..f7542fb99e5 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/syscall_dispatch.c @@ -0,0 +1 @@ +../stm32f4/syscall_dispatch.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/syscall_numbers.h b/core/embed/trezorhal/stm32u5/syscall_numbers.h new file mode 120000 index 00000000000..f2e572e9647 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/syscall_numbers.h @@ -0,0 +1 @@ +../stm32f4/syscall_numbers.h \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/syscall_stubs.c b/core/embed/trezorhal/stm32u5/syscall_stubs.c new file mode 120000 index 00000000000..877f2904f02 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/syscall_stubs.c @@ -0,0 +1 @@ +../stm32f4/syscall_stubs.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/tamper.c b/core/embed/trezorhal/stm32u5/tamper.c index a2bbba546e1..4f6cfb605df 100644 --- a/core/embed/trezorhal/stm32u5/tamper.c +++ b/core/embed/trezorhal/stm32u5/tamper.c @@ -19,9 +19,12 @@ #include #include +#include #include #include STM32_HAL_H +#ifdef KERNEL_MODE + // Fixes a typo in CMSIS Device library for STM32U5 #undef TAMP_CR3_ITAMP7NOER_Msk #undef TAMP_CR3_ITAMP7NOER @@ -234,6 +237,8 @@ void tamper_init(void) { // Interrupt handle for all tamper events // It displays an error message void TAMP_IRQHandler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); + uint32_t sr = TAMP->SR; TAMP->SCR = sr; @@ -271,3 +276,5 @@ void TAMP_IRQHandler(void) { error_shutdown_ex("INTERNAL TAMPER", reason, NULL); #endif } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/util.s b/core/embed/trezorhal/stm32u5/util.S similarity index 99% rename from core/embed/trezorhal/stm32u5/util.s rename to core/embed/trezorhal/stm32u5/util.S index 827451624a6..06258ded409 100644 --- a/core/embed/trezorhal/stm32u5/util.s +++ b/core/embed/trezorhal/stm32u5/util.S @@ -2,6 +2,8 @@ .text +#ifdef KERNEL_MODE + .global memset_reg .type memset_reg, STT_FUNC memset_reg: @@ -134,4 +136,6 @@ shutdown_privileged: ldr r0, =0 b . // loop forever +#endif + .end diff --git a/core/embed/trezorhal/stm32u5/vectortable.s b/core/embed/trezorhal/stm32u5/vectortable.S similarity index 97% rename from core/embed/trezorhal/stm32u5/vectortable.s rename to core/embed/trezorhal/stm32u5/vectortable.S index 2a9e9cb6530..472414caeb9 100644 --- a/core/embed/trezorhal/stm32u5/vectortable.s +++ b/core/embed/trezorhal/stm32u5/vectortable.S @@ -2,6 +2,8 @@ .text +#ifdef KERNEL_MODE + .global default_handler .type default_handler, STT_FUNC default_handler: @@ -174,4 +176,13 @@ vector_table: add_handler DSI_IRQHandler add_handler DCACHE2_IRQHandler +#else + + .section .vector_table, "a" +vector_table: + .word main_stack_base // defined in linker script + .word reset_handler + +#endif + .end diff --git a/core/embed/trezorhal/systick.h b/core/embed/trezorhal/systick.h index af2cb677931..71403c06f79 100644 --- a/core/embed/trezorhal/systick.h +++ b/core/embed/trezorhal/systick.h @@ -23,6 +23,8 @@ #include #include +#ifdef KERNEL_MODE + // Initializes systick subsystem // // Before calling this function, none of the other functions @@ -41,6 +43,8 @@ void systick_deinit(void); // has been changed. void systick_update_freq(void); +#endif // KERNEL_MODE + // ---------------------------------------------------------------------------- // Tick functions diff --git a/core/embed/trezorhal/systimer.h b/core/embed/trezorhal/systimer.h index cca0c278996..058e585b20a 100644 --- a/core/embed/trezorhal/systimer.h +++ b/core/embed/trezorhal/systimer.h @@ -23,6 +23,8 @@ #include #include +#ifdef KERNEL_MODE + // Initializes systimer subsystem // // Before calling this function, none of the other functions @@ -90,4 +92,6 @@ systimer_key_t systimer_suspend(systimer_t* timer); // be the same as returned by `timer_suspend()`. void systimer_resume(systimer_t* timer, systimer_key_t key); +#endif // KERNEL_MODE + #endif // TREZORHAL_SYSTIMER_H diff --git a/core/embed/trezorhal/tamper.h b/core/embed/trezorhal/tamper.h index 5d3fe12b092..abfbe812668 100644 --- a/core/embed/trezorhal/tamper.h +++ b/core/embed/trezorhal/tamper.h @@ -22,6 +22,8 @@ #include +#ifdef KERNEL_MODE + // Tamper module enables the internal tamper detection on STM32 microcontroller // as well as external tamper input if it's available on the device @@ -35,4 +37,6 @@ void tamper_init(void); // are supported void tamper_test(uint32_t tamper_type); +#endif // KERNEL_MODE + #endif // TREZOR_HAL_TAMPER_H diff --git a/core/embed/trezorhal/touch.h b/core/embed/trezorhal/touch.h index 7b28534a7fc..05843d1e366 100644 --- a/core/embed/trezorhal/touch.h +++ b/core/embed/trezorhal/touch.h @@ -4,6 +4,8 @@ #include #include "secbool.h" +#ifdef KERNEL_MODE + // Initializes the touch driver // // Powers on and initializes touch driver controller. @@ -48,6 +50,8 @@ secbool touch_set_sensitivity(uint8_t value); // The function should not be used together with `touch_get_event()`. secbool touch_activity(void); +#endif // KERNEL_MODE + // Returns the last event in packed 32-bit format // // Returns `0` if there's no event or the driver is not initialized. diff --git a/core/embed/trezorhal/xdisplay.h b/core/embed/trezorhal/xdisplay.h index 28f09485d9d..80cdcb04d82 100644 --- a/core/embed/trezorhal/xdisplay.h +++ b/core/embed/trezorhal/xdisplay.h @@ -46,6 +46,8 @@ // MIPI - // - STM32U5A9J-DK Discovery Board +#ifdef KERNEL_MODE + // Specifies how display content should be handled during // initialization or deinitialization. typedef enum { @@ -69,6 +71,8 @@ void display_init(display_content_mode_t mode); // `display_init(DISPLAY_RETAIN_CONTENT)`. void display_deinit(display_content_mode_t mode); +#endif // KERNEL_MODE + // Sets display backlight level ranging from 0 (off)..255 (maximum). // // The default backligt level is 0. Without settings it diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index b778ea860d5..c38b12e01fb 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -53,12 +53,15 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/mpu.c", "embed/trezorhal/stm32f4/platform.c", "embed/trezorhal/stm32f4/secret.c", + "embed/trezorhal/stm32f4/syscall.c", + "embed/trezorhal/stm32f4/syscall_dispatch.c", + "embed/trezorhal/stm32f4/syscall_stubs.c", "embed/trezorhal/stm32f4/systick.c", "embed/trezorhal/stm32f4/systimer.c", "embed/trezorhal/stm32f4/time_estimate.c", "embed/trezorhal/stm32f4/random_delays.c", "embed/trezorhal/stm32f4/rng.c", - "embed/trezorhal/stm32f4/vectortable.s", + "embed/trezorhal/stm32f4/vectortable.S", ] # boardloader needs separate assembler for some function unencumbered by various FW+bootloader hacks @@ -66,11 +69,11 @@ def stm32f4_common_files(env, defines, sources, paths): env_constraints = env.get("CONSTRAINTS") if env_constraints and "limited_util_s" in env_constraints: sources += [ - "embed/trezorhal/stm32f4/limited_util.s", + "embed/trezorhal/stm32f4/limited_util.S", ] else: sources += [ - "embed/trezorhal/stm32f4/util.s", + "embed/trezorhal/stm32f4/util.S", ] env.get("ENV")["SUFFIX"] = "stm32f4" diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index 7d9c4656732..0eea378cf68 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -64,14 +64,17 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/platform.c", "embed/trezorhal/stm32u5/secret.c", "embed/trezorhal/stm32u5/secure_aes.c", + "embed/trezorhal/stm32u5/syscall.c", + "embed/trezorhal/stm32u5/syscall_dispatch.c", + "embed/trezorhal/stm32u5/syscall_stubs.c", "embed/trezorhal/stm32u5/systick.c", - "embed/trezorhal/stm32f4/systimer.c", + "embed/trezorhal/stm32u5/systimer.c", "embed/trezorhal/stm32u5/random_delays.c", "embed/trezorhal/stm32u5/rng.c", "embed/trezorhal/stm32u5/tamper.c", "embed/trezorhal/stm32u5/time_estimate.c", "embed/trezorhal/stm32u5/trustzone.c", - "embed/trezorhal/stm32u5/vectortable.s", + "embed/trezorhal/stm32u5/vectortable.S", ] # boardloader needs separate assembler for some function unencumbered by various FW+bootloader hacks @@ -79,11 +82,11 @@ def stm32u5_common_files(env, defines, sources, paths): env_constraints = env.get("CONSTRAINTS") if env_constraints and "limited_util_s" in env_constraints: sources += [ - "embed/trezorhal/stm32u5/limited_util.s", + "embed/trezorhal/stm32u5/limited_util.S", ] else: sources += [ - "embed/trezorhal/stm32u5/util.s", + "embed/trezorhal/stm32u5/util.S", ] env.get("ENV")["SUFFIX"] = "stm32u5" From 813aa0b91320f7e47c91af100f2b4c0b4f605faf Mon Sep 17 00:00:00 2001 From: cepetr Date: Wed, 18 Sep 2024 09:24:59 +0200 Subject: [PATCH 37/44] refactor(core/embed): introduce system, tasks, applets and emergency mode [no changelog] --- core/SConscript.boardloader | 1 + core/SConscript.bootloader | 1 + core/SConscript.bootloader_ci | 1 + core/SConscript.bootloader_emu | 3 +- core/SConscript.coreapp | 1 + core/SConscript.firmware | 1 + core/SConscript.kernel | 5 +- core/SConscript.prodtest | 1 + core/SConscript.reflash | 1 + core/SConscript.unix | 2 + core/embed/boardloader/main.c | 10 +- core/embed/boardloader/memory_stm32u58.ld | 2 + core/embed/bootloader/main.c | 8 +- core/embed/bootloader/memory_stm32u58.ld | 2 + core/embed/bootloader_ci/main.c | 6 +- core/embed/bootloader_ci/memory_stm32u58.ld | 2 + core/embed/coreapp/main.c | 14 +- core/embed/coreapp/memory_T3T1.ld | 6 +- core/embed/coreapp/startup_stm32f4.S | 37 +- core/embed/coreapp/startup_stm32u5.S | 55 +- core/embed/firmware/main.c | 8 +- core/embed/firmware/memory_T3T1.ld | 2 + core/embed/kernel/main.c | 103 ++- core/embed/kernel/memory_T3T1.ld | 3 + core/embed/lib/error_handling.c | 78 +-- core/embed/lib/rsod.c | 177 +++++ .../unix/fault_handlers.c => lib/rsod.h} | 22 +- core/embed/prodtest/main.c | 10 +- core/embed/prodtest/memory_stm32u58.ld | 2 + core/embed/reflash/main.c | 8 +- core/embed/reflash/memory_stm32u58.ld | 2 + core/embed/rust/rust_ui_common.h | 5 +- core/embed/rust/src/trezorhal/fatal_error.rs | 41 +- core/embed/rust/src/ui/api/common_c.rs | 22 +- core/embed/trezorhal/applet.h | 81 +++ core/embed/trezorhal/fault_handlers.h | 7 - core/embed/trezorhal/stm32f4/applet.c | 73 ++ core/embed/trezorhal/stm32f4/fault_handlers.c | 58 -- core/embed/trezorhal/stm32f4/syscall.c | 186 ++--- core/embed/trezorhal/stm32f4/syscall.h | 22 +- .../trezorhal/stm32f4/syscall_dispatch.c | 19 +- .../embed/trezorhal/stm32f4/syscall_numbers.h | 8 +- core/embed/trezorhal/stm32f4/syscall_stubs.c | 27 + core/embed/trezorhal/stm32f4/systask.c | 639 ++++++++++++++++++ core/embed/trezorhal/stm32f4/system.c | 310 +++++++++ core/embed/trezorhal/stm32f4/util.S | 12 - core/embed/trezorhal/stm32f4/vectortable.S | 3 +- core/embed/trezorhal/stm32u5/applet.c | 1 + core/embed/trezorhal/stm32u5/fault_handlers.c | 76 --- core/embed/trezorhal/stm32u5/systask.c | 1 + core/embed/trezorhal/stm32u5/system.c | 1 + core/embed/trezorhal/stm32u5/vectortable.S | 3 +- core/embed/trezorhal/systask.h | 182 +++++ core/embed/trezorhal/system.h | 68 ++ core/embed/trezorhal/unix/system.c | 107 +++ core/site_scons/models/stm32f4_common.py | 4 +- core/site_scons/models/stm32u5_common.py | 4 +- 57 files changed, 2012 insertions(+), 522 deletions(-) create mode 100644 core/embed/lib/rsod.c rename core/embed/{trezorhal/unix/fault_handlers.c => lib/rsod.h} (56%) create mode 100644 core/embed/trezorhal/applet.h delete mode 100644 core/embed/trezorhal/fault_handlers.h create mode 100644 core/embed/trezorhal/stm32f4/applet.c delete mode 100644 core/embed/trezorhal/stm32f4/fault_handlers.c create mode 100644 core/embed/trezorhal/stm32f4/systask.c create mode 100644 core/embed/trezorhal/stm32f4/system.c create mode 120000 core/embed/trezorhal/stm32u5/applet.c delete mode 100644 core/embed/trezorhal/stm32u5/fault_handlers.c create mode 120000 core/embed/trezorhal/stm32u5/systask.c create mode 120000 core/embed/trezorhal/stm32u5/system.c create mode 100644 core/embed/trezorhal/systask.h create mode 100644 core/embed/trezorhal/system.h create mode 100644 core/embed/trezorhal/unix/system.c diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader index 056d11adee5..af532a192ca 100644 --- a/core/SConscript.boardloader +++ b/core/SConscript.boardloader @@ -79,6 +79,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_mono8.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', ] if NEW_RENDERING: diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index b79bd06f532..b8f039bbe75 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -118,6 +118,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_rgba8888.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/unit_variant.c', 'vendor/micropython/lib/uzlib/adler32.c', diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci index d01be32d2a1..841f48b1df4 100644 --- a/core/SConscript.bootloader_ci +++ b/core/SConscript.bootloader_ci @@ -111,6 +111,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_rgba8888.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index fb3e3ed2f23..a98ae71d514 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -113,6 +113,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_rgba8888.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/unit_variant.c', 'vendor/micropython/lib/uzlib/adler32.c', @@ -149,7 +150,6 @@ SOURCE_BOOTLOADER = [ SOURCE_TREZORHAL = [ 'embed/trezorhal/unix/bootutils.c', 'embed/trezorhal/unix/common.c', - 'embed/trezorhal/unix/fault_handlers.c', 'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/flash_otp.c', 'embed/trezorhal/unix/mpu.c', @@ -157,6 +157,7 @@ SOURCE_TREZORHAL = [ 'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/rng.c', 'embed/trezorhal/unix/secret.c', + 'embed/trezorhal/unix/system.c', 'embed/trezorhal/unix/systick.c', 'embed/trezorhal/unix/systimer.c', 'embed/trezorhal/unix/usb.c', diff --git a/core/SConscript.coreapp b/core/SConscript.coreapp index 2550ef94e3d..a65908aac0b 100644 --- a/core/SConscript.coreapp +++ b/core/SConscript.coreapp @@ -235,6 +235,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_mono8.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/translations.c', 'embed/lib/unit_variant.c', diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 74a2e634cdb..c201d098b7d 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -234,6 +234,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_mono8.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/translations.c', 'embed/lib/unit_variant.c', diff --git a/core/SConscript.kernel b/core/SConscript.kernel index 2be27fc7f54..3b15bac4db2 100644 --- a/core/SConscript.kernel +++ b/core/SConscript.kernel @@ -222,6 +222,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_mono8.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/translations.c', 'embed/lib/unit_variant.c', @@ -246,7 +247,7 @@ CPPDEFINES_MOD += [ if TREZOR_MODEL not in ('1', ): CPPDEFINES_MOD += [ - # 'FANCY_FATAL_ERROR', + 'FANCY_FATAL_ERROR', ] CPPDEFINES_MOD += ['USE_SVC_SHUTDOWN'] @@ -367,7 +368,7 @@ env.Replace( LINKFLAGS='-T embed/kernel/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/kernel/kernel.map -Wl,--warn-common' % LD_VARIANT, CPPPATH=ALLPATHS, CPPDEFINES=[ - 'FIRMWARE', + 'KERNEL', 'TREZOR_MODEL_'+TREZOR_MODEL, 'USE_HAL_DRIVER', 'ARM_USER_MODE', diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index 3ae2a8c825c..2302c2658dd 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -115,6 +115,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_mono8.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/qr-code-generator/qrcodegen.c', 'embed/lib/terminal.c', 'vendor/micropython/lib/uzlib/adler32.c', diff --git a/core/SConscript.reflash b/core/SConscript.reflash index 481450e22ab..dc6dfc18c53 100644 --- a/core/SConscript.reflash +++ b/core/SConscript.reflash @@ -90,6 +90,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_rgba8888.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', diff --git a/core/SConscript.unix b/core/SConscript.unix index 43cf4936099..f2071181b0b 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -243,6 +243,7 @@ SOURCE_MOD += [ 'embed/lib/gfx_bitblt_mono8.c', 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/translations.c', 'embed/lib/unit_variant.c', @@ -428,6 +429,7 @@ SOURCE_UNIX = [ 'embed/trezorhal/unix/mpu.c', 'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/rng.c', + 'embed/trezorhal/unix/system.c', 'embed/trezorhal/unix/systick.c', 'embed/trezorhal/unix/systimer.c', 'embed/trezorhal/unix/time_estimate.c', diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index d63cca32237..17eb8d4b716 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -21,19 +21,20 @@ #include TREZOR_BOARD #include "board_capabilities.h" +#include "bootutils.h" #include "buffers.h" #include "common.h" #include "compiler_traits.h" #include "display.h" #include "display_draw.h" -#include "fault_handlers.h" #include "flash.h" #include "flash_utils.h" #include "image.h" #include "model.h" #include "mpu.h" #include "rng.h" -#include "systimer.h" +#include "rsod.h" +#include "system.h" #include "terminal.h" #ifdef USE_SD_CARD @@ -234,8 +235,7 @@ static secbool copy_sdcard(void) { #endif int main(void) { - systick_init(); - systimer_init(); + system_init(&rsod_panic_handler); reset_flags_reset(); @@ -261,8 +261,6 @@ int main(void) { clear_otg_hs_memory(); #endif - fault_handlers_init(); - #ifdef USE_SDRAM sdram_init(); #endif diff --git a/core/embed/boardloader/memory_stm32u58.ld b/core/embed/boardloader/memory_stm32u58.ld index b92fcf30372..51aa0845c32 100644 --- a/core/embed/boardloader/memory_stm32u58.ld +++ b/core/embed/boardloader/memory_stm32u58.ld @@ -40,6 +40,8 @@ sram5_start = ORIGIN(SRAM5); sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); sram6_start = ORIGIN(SRAM6); sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index f2bea94e7ba..c417d8312dc 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -25,7 +25,6 @@ #include "common.h" #include "display.h" #include "display_utils.h" -#include "fault_handlers.h" #include "flash.h" #include "flash_otp.h" #include "flash_utils.h" @@ -33,8 +32,10 @@ #include "lowlevel.h" #include "messages.pb.h" #include "random_delays.h" +#include "rsod.h" #include "secbool.h" #include "secret.h" +#include "system.h" #include "systimer.h" #ifdef USE_DMA2D @@ -356,8 +357,7 @@ int bootloader_main(void) { #endif secbool stay_in_bootloader = secfalse; - systick_init(); - systimer_init(); + system_init(&rsod_panic_handler); rdi_init(); @@ -396,8 +396,6 @@ int bootloader_main(void) { ui_screen_boot_stage_1(false); - fault_handlers_init(); - #ifdef TREZOR_EMULATOR // wait a bit so that the empty lock icon is visible // (on a real device, we are waiting for touch init which takes longer) diff --git a/core/embed/bootloader/memory_stm32u58.ld b/core/embed/bootloader/memory_stm32u58.ld index 0812d1925ca..6711c5c4b41 100644 --- a/core/embed/bootloader/memory_stm32u58.ld +++ b/core/embed/bootloader/memory_stm32u58.ld @@ -40,6 +40,8 @@ sram5_start = ORIGIN(SRAM5); sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); sram6_start = ORIGIN(SRAM6); sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); diff --git a/core/embed/bootloader_ci/main.c b/core/embed/bootloader_ci/main.c index 93e52fe5e09..b43e06a6c52 100644 --- a/core/embed/bootloader_ci/main.c +++ b/core/embed/bootloader_ci/main.c @@ -20,6 +20,7 @@ #include #include +#include "bootutils.h" #include "common.h" #include "display.h" #include "display_draw.h" @@ -30,7 +31,9 @@ #include "mpu.h" #include "random_delays.h" #include "rng.h" +#include "rsod.h" #include "secbool.h" +#include "system.h" #ifdef USE_TOUCH #include "touch.h" #endif @@ -176,8 +179,7 @@ static secbool check_vendor_header_lock(const vendor_header *const vhdr) { } int main(void) { - systick_init(); - systimer_init(); + system_init(&rsod_panic_handler); rdi_init(); #ifdef USE_TOUCH diff --git a/core/embed/bootloader_ci/memory_stm32u58.ld b/core/embed/bootloader_ci/memory_stm32u58.ld index 876807cb8c6..69f2570187b 100644 --- a/core/embed/bootloader_ci/memory_stm32u58.ld +++ b/core/embed/bootloader_ci/memory_stm32u58.ld @@ -40,6 +40,8 @@ sram5_start = ORIGIN(SRAM5); sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); sram6_start = ORIGIN(SRAM6); sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); diff --git a/core/embed/coreapp/main.c b/core/embed/coreapp/main.c index 8ea6f269bb1..6a51611729e 100644 --- a/core/embed/coreapp/main.c +++ b/core/embed/coreapp/main.c @@ -37,16 +37,28 @@ #include "ports/stm32/pendsv.h" #include "error_handling.h" +#include "rsod.h" #include "rust_ui_common.h" #include "secbool.h" +#include "systask.h" +#include "system.h" #ifdef USE_SECP256K1_ZKP #include "zkp_context.h" #endif -int main(void) { +int main(uint32_t cmd, void *arg) { + if (cmd == 1) { + systask_postmortem_t *info = (systask_postmortem_t *)arg; + rsod_gui(info); + system_exit(0); + } + screen_boot_stage_2(); + // uint32_t *p = 0; + // *p = 0; + #ifdef USE_SECP256K1_ZKP ensure(sectrue * (zkp_context_init() == 0), NULL); #endif diff --git a/core/embed/coreapp/memory_T3T1.ld b/core/embed/coreapp/memory_T3T1.ld index 3fc9d3fae2c..810877697d2 100644 --- a/core/embed/coreapp/memory_T3T1.ld +++ b/core/embed/coreapp/memory_T3T1.ld @@ -16,15 +16,13 @@ MEMORY { main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ _sstack = ORIGIN(SRAM2); _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); @@ -43,6 +41,8 @@ sram5_start = ORIGIN(SRAM5); sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); sram6_start = ORIGIN(SRAM6); sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); diff --git a/core/embed/coreapp/startup_stm32f4.S b/core/embed/coreapp/startup_stm32f4.S index f1a8a6784e9..d1a921abb34 100644 --- a/core/embed/coreapp/startup_stm32f4.S +++ b/core/embed/coreapp/startup_stm32f4.S @@ -6,21 +6,17 @@ .type reset_handler, STT_FUNC reset_handler: - // setup environment for subsequent stage of code - ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of BOOT_ARGS - ldr r1, =boot_args_end // r1 - point to byte after the end of BOOT_ARGS - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg + 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 @@ -28,15 +24,14 @@ reset_handler: 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] + pop {r0, r1} // enter the application code + // returns exit code in r0 bl main - b secure_shutdown - + // terminate the application + // pass exit code in r0 + b system_exit .end diff --git a/core/embed/coreapp/startup_stm32u5.S b/core/embed/coreapp/startup_stm32u5.S index 6d94c656d70..cc26b7470b8 100644 --- a/core/embed/coreapp/startup_stm32u5.S +++ b/core/embed/coreapp/startup_stm32u5.S @@ -6,53 +6,38 @@ .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 PSPLIM, r0 + 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, =bss_end - ldr r2, =0 - bl memset_reg + 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 + ldr r0, =data_vma + ldr r1, =data_lma + ldr r2, =data_size 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 + ldr r0, =confidential_vma + ldr r1, =confidential_lma + ldr r2, =confidential_size 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] + pop {r0, r1} // enter the application code + // returns exit code in r0 bl main - b secure_shutdown - - -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 - + // terminate the application + // pass exit code in r0 + b system_exit .end diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 07ffb1f6e7a..4ac0b79ccf5 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -42,15 +42,16 @@ #include "compiler_traits.h" #include "display.h" #include "entropy.h" -#include "fault_handlers.h" #include "flash.h" #include "image.h" #include "memzero.h" #include "model.h" #include "mpu.h" #include "random_delays.h" +#include "rsod.h" #include "rust_ui.h" #include "secure_aes.h" +#include "system.h" #include "systimer.h" #include TREZOR_BOARD @@ -125,8 +126,7 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data, #endif int main(void) { - systick_init(); - systimer_init(); + system_init(&rsod_gui); rdi_init(); @@ -183,8 +183,6 @@ int main(void) { // Init peripherals - fault_handlers_init(); - #if defined TREZOR_MODEL_T set_core_clock(CLOCK_180_MHZ); #endif diff --git a/core/embed/firmware/memory_T3T1.ld b/core/embed/firmware/memory_T3T1.ld index 4e3a2a88cdf..9bbf390476d 100644 --- a/core/embed/firmware/memory_T3T1.ld +++ b/core/embed/firmware/memory_T3T1.ld @@ -40,6 +40,8 @@ sram5_start = ORIGIN(SRAM5); sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); sram6_start = ORIGIN(SRAM6); sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); diff --git a/core/embed/kernel/main.c b/core/embed/kernel/main.c index 4b3f97e3b5b..7ad6f8ce113 100644 --- a/core/embed/kernel/main.c +++ b/core/embed/kernel/main.c @@ -19,15 +19,14 @@ #include STM32_HAL_H -#include "image.h" -#include "irq.h" -#include "syscall.h" +#include +#include "applet.h" #include "board_capabilities.h" +#include "bootutils.h" #include "display.h" #include "dma2d.h" #include "entropy.h" -#include "fault_handlers.h" #include "haptic.h" #include "image.h" #include "irq.h" @@ -36,11 +35,12 @@ #include "optiga_commands.h" #include "optiga_transport.h" #include "random_delays.h" +#include "rsod.h" #include "sdcard.h" #include "secret.h" #include "secure_aes.h" +#include "system.h" #include "systick.h" -#include "systimer.h" #include "tamper.h" #include "touch.h" #include "unit_variant.h" @@ -66,15 +66,6 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data, #endif void drivers_init() { - syscall_init(); - - systick_init(); - systimer_init(); - - fault_handlers_init(); - - systick_delay_ms(10); - #if defined TREZOR_MODEL_T set_core_clock(CLOCK_180_MHZ); #endif @@ -175,14 +166,92 @@ void drivers_init() { #endif } +// Initializes coreapp applet +static void coreapp_init(applet_t *applet) { + applet_header_t *coreapp_header = + (applet_header_t *)(COREAPP_START + IMAGE_HEADER_SIZE + 0x0400); + + applet_layout_t coreapp_layout = { + 0 + /* .data1_start = COREAPP_RAM1_START, + .data1_size = COREAPP_RAM1_SIZE, + .data2_start = COREAPP_RAM2_START, + .data2_size = COREAPP_RAM2_SIZE,*/ + }; + + applet_init(applet, coreapp_header, &coreapp_layout); +} + +// Shows RSOD (Red Screen of Death) +static void show_rsod(const systask_postmortem_t *pminfo) { +#ifdef FANCY_FATAL_ERROR + applet_t coreapp; + coreapp_init(&coreapp); + + // Reset and run the coreapp in RSOD mode + if (applet_reset(&coreapp, 1, pminfo, sizeof(systask_postmortem_t))) { + systask_yield_to(&coreapp.task); + + if (coreapp.task.pminfo.reason == TASK_TERM_REASON_EXIT) { + // If the RSOD was shown successfully, proceed to shutdown + secure_shutdown(); + } + } +#endif + + // If coreapp crashed, fallback to showing the error using a terminal + rsod_terminal(pminfo); +} + +// Initializes system in emergency mode and shows RSOD +static void init_and_show_rsod(const systask_postmortem_t *pminfo) { + // Initialize the system's core services + // (If the kernel crashes in emergency mode, we are out of options + // and show the RSOD without attempting to re-enter emergency mode) + system_init(&rsod_terminal); + + // Initialize necessary drivers + display_init(DISPLAY_RESET_CONTENT); + + // Show RSOD + show_rsod(pminfo); + + // Wait for the user to manually power off the device + secure_shutdown(); +} + +// Kernel panic handler +// (may be called from interrupt context) +static void kernel_panic(const systask_postmortem_t *pminfo) { + // Since the system state is unreliable, enter emergency mode + // and show the RSOD. + system_emergency_rescue(&init_and_show_rsod, pminfo); + // The previous function call never returns +} + int main(void) { - mpu_init(); + // Initialize system's core services + system_init(&kernel_panic); // Initialize hardware drivers drivers_init(); - // Start unprivileged application - start_unprivileged_app(); + // Initialize coreapp task + applet_t coreapp; + coreapp_init(&coreapp); + + // Reset and run the coreapp + if (!applet_reset(&coreapp, 0, NULL, 0)) { + error_shutdown("Cannot start coreapp"); + } + + systask_yield_to(&coreapp.task); + + // Coreapp crashed, show RSOD + show_rsod(&coreapp.task.pminfo); + + // Wait for the user to manually power off the device + secure_shutdown(); return 0; } diff --git a/core/embed/kernel/memory_T3T1.ld b/core/embed/kernel/memory_T3T1.ld index f799bf49270..07a90ccc539 100644 --- a/core/embed/kernel/memory_T3T1.ld +++ b/core/embed/kernel/memory_T3T1.ld @@ -21,6 +21,9 @@ _estack = main_stack_base; 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); diff --git a/core/embed/lib/error_handling.c b/core/embed/lib/error_handling.c index 1f223176032..cfaab483796 100644 --- a/core/embed/lib/error_handling.c +++ b/core/embed/lib/error_handling.c @@ -18,25 +18,10 @@ */ #include -#ifdef TREZOR_EMULATOR -#include -#endif +#include -#include "bootutils.h" -#include "display.h" #include "error_handling.h" -#include "mini_printf.h" -#ifdef FANCY_FATAL_ERROR -#include "rust_ui.h" -#else -#include "terminal.h" -#endif - -#ifdef RGB16 -#define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00) -#else -#define COLOR_FATAL_ERROR COLOR_BLACK -#endif +#include "system.h" uint32_t __stack_chk_guard = 0; @@ -48,26 +33,9 @@ void __attribute__((noreturn, used)) __stack_chk_fail(void) { void __attribute__((noreturn)) error_shutdown_ex(const char *title, const char *message, const char *footer) { - if (title == NULL) { - title = "INTERNAL ERROR"; - } - if (footer == NULL) { - footer = "PLEASE VISIT\nTREZOR.IO/RSOD"; - } - -#ifdef FANCY_FATAL_ERROR - error_shutdown_rust(title, message, footer); -#else - display_orientation(0); - term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR); - term_printf("%s\n", title); - if (message) { - term_printf("%s\n", message); - } - term_printf("\n%s\n", footer); - display_backlight(255); - secure_shutdown(); -#endif + system_exit_error(title, message, footer); + while (1) + ; } void __attribute__((noreturn)) error_shutdown(const char *message) { @@ -76,39 +44,9 @@ void __attribute__((noreturn)) error_shutdown(const char *message) { void __attribute__((noreturn)) __fatal_error(const char *msg, const char *file, int line) { -#ifdef TREZOR_EMULATOR - fprintf(stderr, "FATAL ERROR: %s\n", msg); - if (file) { - fprintf(stderr, "file: %s:%d\n", file, line); - } - fflush(stderr); -#endif -#ifdef FANCY_FATAL_ERROR - if (msg == NULL) { - char buf[128] = {0}; - mini_snprintf(buf, sizeof(buf), "%s:%d", file, line); - msg = buf; - } - error_shutdown(msg); -#else - display_orientation(0); - term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR); - term_printf("\nINTERNAL ERROR:\n"); - if (msg) { - term_printf("msg : %s\n", msg); - } - if (file) { - term_printf("file: %s:%d\n", file, line); - } -#ifdef SCM_REVISION - const uint8_t *rev = (const uint8_t *)SCM_REVISION; - term_printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3], - rev[4]); -#endif - term_printf("\nPlease contact Trezor support.\n"); - display_backlight(255); - secure_shutdown(); -#endif + system_exit_fatal(msg, file, line); + while (1) + ; } void __attribute__((noreturn)) show_wipe_code_screen(void) { diff --git a/core/embed/lib/rsod.c b/core/embed/lib/rsod.c new file mode 100644 index 00000000000..7be3da488b9 --- /dev/null +++ b/core/embed/lib/rsod.c @@ -0,0 +1,177 @@ +/* + * 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 "rsod.h" +#include "bootutils.h" +#include "display.h" +#include "mini_printf.h" +#include "system.h" +#include "terminal.h" + +#define RSOD_DEFAULT_TITLE "INTERNAL ERROR"; +#define RSOD_DEFAULT_MESSAGE "UNSPECIFIED"; +#define RSOD_DEFAULT_FOOTER "PLEASE VISIT TREZOR.IO/RSOD"; +#define RSOD_EXIT_MESSAGE "EXIT %d" + +#ifdef KERNEL_MODE + +#define RSOD_FG_COLOR COLOR_WHITE + +#ifdef USE_RGB_COLORS +#define RSOD_BG_COLOR RGB16(0x7F, 0x00, 0x00) +#else +#define RSOD_BG_COLOR COLOR_BLACK +#endif + +void rsod_terminal(const systask_postmortem_t* pminfo) { + display_orientation(0); + term_set_color(RSOD_FG_COLOR, RSOD_BG_COLOR); + + const char* title = RSOD_DEFAULT_TITLE; + const char* message = RSOD_DEFAULT_MESSAGE; + const char* footer = RSOD_DEFAULT_FOOTER; + const char* file = NULL; + char message_buf[32] = {0}; + int line = 0; + + switch (pminfo->reason) { + case TASK_TERM_REASON_EXIT: + mini_snprintf(message_buf, sizeof(message_buf), RSOD_EXIT_MESSAGE, + pminfo->exit.code); + message = message_buf; + break; + case TASK_TERM_REASON_ERROR: + title = pminfo->error.title; + message = pminfo->error.message; + footer = pminfo->error.footer; + break; + case TASK_TERM_REASON_FATAL: + message = pminfo->fatal.expr; + file = pminfo->fatal.file; + line = pminfo->fatal.line; + break; + case TASK_TERM_REASON_FAULT: + message = system_fault_message(&pminfo->fault); + break; + } + + if (title != NULL) { + term_printf("%s\n", title); + } + + if (message != NULL) { + term_printf("msg : %s\n", message); + } + + if (file) { + term_printf("file: %s:%d\n", file, line); + } + +#ifdef SCM_REVISION + const uint8_t* rev = (const uint8_t*)SCM_REVISION; + term_printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3], + rev[4]); +#endif + + if (footer != NULL) { + term_printf("\n%s\n", footer); + } + + display_backlight(255); +} + +#endif // KERNEL_MODE + +#if (defined(FIRMWARE) || defined(BOOTLOADER)) && defined(FANCY_FATAL_ERROR) + +#include "rust_ui.h" + +void rsod_gui(const systask_postmortem_t* pminfo) { + const char* title = RSOD_DEFAULT_TITLE; + const char* message = RSOD_DEFAULT_MESSAGE; + const char* footer = RSOD_DEFAULT_FOOTER; + char message_buf[128] = {0}; + + switch (pminfo->reason) { + case TASK_TERM_REASON_EXIT: + mini_snprintf(message_buf, sizeof(message_buf), RSOD_EXIT_MESSAGE, + pminfo->exit.code); + message = message_buf; + break; + + case TASK_TERM_REASON_ERROR: + title = pminfo->error.title; + message = pminfo->error.message; + footer = pminfo->error.footer; + break; + + case TASK_TERM_REASON_FATAL: + message = pminfo->fatal.expr; + if (message[0] == '\0') { + mini_snprintf(message_buf, sizeof(message_buf), "%s:%u", + pminfo->fatal.file, (unsigned int)pminfo->fatal.line); + message = message_buf; + } + break; + + case TASK_TERM_REASON_FAULT: + message = system_fault_message(&pminfo->fault); + break; + } + + // Render the RSOD in Rust + display_rsod_rust(title, message, footer); +} + +#endif + +#ifdef KERNEL_MODE + +// Initializes system in emergency mode and shows RSOD +static void init_and_show_rsod(const systask_postmortem_t* pminfo) { + // Initialize the system's core services + // (If the kernel crashes in emergency mode, we are out of options + // and show the RSOD without attempting to re-enter emergency mode) + system_init(&rsod_terminal); + + // Initialize necessary drivers + display_init(DISPLAY_RESET_CONTENT); + +#if (defined(FIRMWARE) || defined(BOOTLOADER)) && defined(FANCY_FATAL_ERROR) + // Show the RSOD using Rust GUI + rsod_gui(pminfo); +#else + // Show the RSOD using terminal + rsod_terminal(pminfo); +#endif + + // Wait for the user to manually power off the device + secure_shutdown(); +} + +// Universal panic handler +// (may be called from interrupt context) +void rsod_panic_handler(const systask_postmortem_t* pminfo) { + // Since the system state is unreliable, enter emergency mode + // and show the RSOD. + system_emergency_rescue(&init_and_show_rsod, pminfo); + // The previous function call never returns +} + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/unix/fault_handlers.c b/core/embed/lib/rsod.h similarity index 56% rename from core/embed/trezorhal/unix/fault_handlers.c rename to core/embed/lib/rsod.h index 1e7754849cc..86f302d8617 100644 --- a/core/embed/trezorhal/unix/fault_handlers.c +++ b/core/embed/lib/rsod.h @@ -17,6 +17,24 @@ * along with this program. If not, see . */ -#include +#ifndef LIB_RSOD_H +#define LIB_RSOD_H -void fault_handlers_init(void) {} +#include "systask.h" + +// Shows RSOD (Red Screen of Death) using terminal. +void rsod_terminal(const systask_postmortem_t* pminfo); + +// Shows RSOD (Red Screen of Death) using Rust GUI. +void rsod_gui(const systask_postmortem_t* pminfo); + +#ifdef KERNEL_MODE + +// Universal panic handler that can be passed to `system_init()` function +// to show RSOD screen describing the system error. +// (may be called from interrupt context) +void rsod_panic_handler(const systask_postmortem_t* pminfo); + +#endif // KERNEL_MODE + +#endif // LIB_RSOD_H diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index fc56a4c3270..3ff73d873c2 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -31,7 +31,6 @@ #include "display.h" #include "display_draw.h" #include "display_utils.h" -#include "fault_handlers.h" #include "flash.h" #include "flash_otp.h" #include "fwutils.h" @@ -40,9 +39,11 @@ #include "mpu.h" #include "prodtest_common.h" #include "random_delays.h" +#include "rsod.h" #include "sbu.h" #include "sdcard.h" #include "secbool.h" +#include "system.h" #include "systimer.h" #include "touch.h" #include "usb.h" @@ -783,9 +784,8 @@ void cpuid_read(void) { #define BACKLIGHT_NORMAL 150 int main(void) { - systick_init(); - systimer_init(); - rdi_init(); + system_init(&rsod_panic_handler); + display_init(DISPLAY_RETAIN_CONTENT); #ifdef STM32U5 @@ -820,8 +820,6 @@ int main(void) { pair_optiga(); #endif - fault_handlers_init(); - display_clear(); draw_welcome_screen(); diff --git a/core/embed/prodtest/memory_stm32u58.ld b/core/embed/prodtest/memory_stm32u58.ld index eaa108f73f8..53c52168659 100644 --- a/core/embed/prodtest/memory_stm32u58.ld +++ b/core/embed/prodtest/memory_stm32u58.ld @@ -40,6 +40,8 @@ sram5_start = ORIGIN(SRAM5); sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); sram6_start = ORIGIN(SRAM6); sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); diff --git a/core/embed/reflash/main.c b/core/embed/reflash/main.c index 11487087209..0e7ef455802 100644 --- a/core/embed/reflash/main.c +++ b/core/embed/reflash/main.c @@ -23,6 +23,7 @@ #include STM32_HAL_H +#include "bootutils.h" #include "common.h" #include "display.h" #include "display_draw.h" @@ -30,9 +31,11 @@ #include "image.h" #include "model.h" #include "rng.h" +#include "rsod.h" #include "sbu.h" #include "sdcard.h" #include "secbool.h" +#include "system.h" #include "systimer.h" #include "terminal.h" #include "touch.h" @@ -43,7 +46,7 @@ static void progress_callback(int pos, int len) { term_printf("."); } -static void flash_from_sdcard(const flash_area_t* area, uint32_t source, +static void flash_from_sdcard(const flash_area_t *area, uint32_t source, uint32_t length) { static uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)]; @@ -69,8 +72,7 @@ static void flash_from_sdcard(const flash_area_t* area, uint32_t source, } int main(void) { - systick_init(); - systimer_init(); + system_init(&rsod_panic_handler); sdcard_init(); touch_init(); diff --git a/core/embed/reflash/memory_stm32u58.ld b/core/embed/reflash/memory_stm32u58.ld index e00c0df10f1..586970355da 100644 --- a/core/embed/reflash/memory_stm32u58.ld +++ b/core/embed/reflash/memory_stm32u58.ld @@ -40,6 +40,8 @@ sram5_start = ORIGIN(SRAM5); sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); sram6_start = ORIGIN(SRAM6); sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); diff --git a/core/embed/rust/rust_ui_common.h b/core/embed/rust/rust_ui_common.h index 11f03965a8b..6c8a8b7dec0 100644 --- a/core/embed/rust/rust_ui_common.h +++ b/core/embed/rust/rust_ui_common.h @@ -1,8 +1,7 @@ #include "common.h" -__attribute__((noreturn)) void error_shutdown_rust(const char* title, - const char* msg, - const char* footer); +void display_rsod_rust(const char* title, const char* message, + const char* footer); void screen_boot_stage_2(void); diff --git a/core/embed/rust/src/trezorhal/fatal_error.rs b/core/embed/rust/src/trezorhal/fatal_error.rs index 132c41eb1c5..dec821bd815 100644 --- a/core/embed/rust/src/trezorhal/fatal_error.rs +++ b/core/embed/rust/src/trezorhal/fatal_error.rs @@ -1,31 +1,28 @@ mod ffi { extern "C" { - // trezorhal/bootuils.c - pub fn secure_shutdown() -> !; + // error_handling.h + pub fn error_shutdown(msg: *const cty::c_char) -> !; } } -use crate::ui::{ - shape, - ui_features::{ModelUI, UIFeaturesCommon}, -}; +pub fn error_shutdown(msg: &str) -> ! { + const MAX_LEN: usize = 63; + let mut buffer: [u8; MAX_LEN + 1] = [0; MAX_LEN + 1]; -fn shutdown() -> ! { - unsafe { ffi::secure_shutdown() } -} - -/// Shows an error message and shuts down the device. -pub fn error_shutdown(title: &str, msg: &str, footer: &str) -> ! { - // SAFETY: - // This is the only situation we are allowed use this function - // to allow nested calls to `run_with_bumps`/`render_on_display`, - // because after the error message is displayed, the application will - // shut down. - unsafe { shape::unlock_bumps_on_failure() }; + // Copy the message to the buffer + let msg_bytes = msg.as_bytes(); + let len = if msg_bytes.len() < MAX_LEN { + msg_bytes.len() + } else { + MAX_LEN + }; + buffer[..len].copy_from_slice(&msg_bytes[..len]); - ModelUI::screen_fatal_error(title, msg, footer); - ModelUI::backlight_on(); - shutdown() + unsafe { + // SAFETY: `buffer` is a valid null-terminated string + // and the function never returns. + ffi::error_shutdown(buffer.as_ptr() as *const cty::c_char); + } } /// Shows an error message on the screen and shuts down the device. @@ -46,7 +43,7 @@ pub fn __fatal_error(msg: &str, _file: &str, _line: u32) -> ! { dbg_println!("==="); } - error_shutdown("INTERNAL_ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD"); + error_shutdown(msg); } pub trait UnwrapOrFatalError { diff --git a/core/embed/rust/src/ui/api/common_c.rs b/core/embed/rust/src/ui/api/common_c.rs index ccbed0d3a35..7eafbef5aa5 100644 --- a/core/embed/rust/src/ui/api/common_c.rs +++ b/core/embed/rust/src/ui/api/common_c.rs @@ -10,19 +10,33 @@ use crate::ui::{ geometry::{Alignment2D, Point}, }; -use crate::{trezorhal::fatal_error, ui::util::from_c_str}; +#[cfg(feature = "new_rendering")] +use crate::ui::shape; + +use crate::ui::util::from_c_str; #[no_mangle] -extern "C" fn error_shutdown_rust( +extern "C" fn display_rsod_rust( title: *const cty::c_char, msg: *const cty::c_char, footer: *const cty::c_char, -) -> ! { +) { let title = unsafe { from_c_str(title) }.unwrap_or(""); let msg = unsafe { from_c_str(msg) }.unwrap_or(""); let footer = unsafe { from_c_str(footer) }.unwrap_or(""); - fatal_error::error_shutdown(title, msg, footer) + // SAFETY: + // This is the only situation we are allowed use this function + // to allow nested calls to `run_with_bumps`/`render_on_display`, + // because after the error message is displayed, the application will + // shut down. + #[cfg(feature = "new_rendering")] + unsafe { + shape::unlock_bumps_on_failure() + }; + + ModelUI::screen_fatal_error(title, msg, footer); + ModelUI::backlight_on(); } #[no_mangle] diff --git a/core/embed/trezorhal/applet.h b/core/embed/trezorhal/applet.h new file mode 100644 index 00000000000..5309e7b5d8a --- /dev/null +++ b/core/embed/trezorhal/applet.h @@ -0,0 +1,81 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_APPLET_H +#define TREZORHAL_APPLET_H + +#include +#include + +#ifdef SYSCALL_DISPATCH + +#include "systask.h" + +// Applet entry point +typedef void (*applet_startup_t)(const char* args, uint32_t random); + +// Applet header found at the beginning of the applet binary +typedef struct { + // Stack area + uint32_t stack_start; + uint32_t stack_size; + // Applet entry point + applet_startup_t startup; +} applet_header_t; + +// Applet memory layout +typedef struct { + // Data area 1 + uint32_t data1_start; + uint32_t data1_size; + // Data area 2 + uint32_t data2_start; + uint32_t data2_size; + +} applet_layout_t; + +typedef struct { + // Points to the applet header found at the beginning of the applet binary + applet_header_t* header; + // Applet memory layout describing the memory areas + // the applet is allowed to use + applet_layout_t layout; + // Applet task + systask_t task; + + // + privileges + +} applet_t; + +// Initializes the applet structure +void applet_init(applet_t* applet, applet_header_t* header, + applet_layout_t* layout); + +// Resets the applet and prepares it for execution from its entry point. +// +// Applet does not start immediately, it needs to be scheduled by +// `systask_yield_to(&applet->task)` after calling this function. +// +// Returns `true` if the applet was successfully reset. +bool applet_reset(applet_t* applet, uint32_t cmd, const void* arg, + size_t arg_size); + +#endif // SYSCALL_DISPATCH + +#endif // TREZORHAL_APPLET_H diff --git a/core/embed/trezorhal/fault_handlers.h b/core/embed/trezorhal/fault_handlers.h deleted file mode 100644 index 8372135f37c..00000000000 --- a/core/embed/trezorhal/fault_handlers.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef TREZORHAL_FAULT_HANDLERS_H -#define TREZORHAL_FAULT_HANDLERS_H - -// Initializes and enables fault handlers -void fault_handlers_init(void); - -#endif // TREZORHAL_FAULT_HANDLERS_H diff --git a/core/embed/trezorhal/stm32f4/applet.c b/core/embed/trezorhal/stm32f4/applet.c new file mode 100644 index 00000000000..a36e2f9cf33 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/applet.c @@ -0,0 +1,73 @@ +/* + * 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 "applet.h" +#include "mpu.h" +#include "rng.h" +#include "systask.h" + +#ifdef SYSCALL_DISPATCH + +void applet_init(applet_t* applet, applet_header_t* header, + applet_layout_t* layout) { + memset(applet, 0, sizeof(applet_t)); + + applet->header = header; + applet->layout = *layout; +} + +static void applet_clear_memory(applet_t* applet) { + if (applet->layout.data1_size > 0) { + memset((void*)applet->layout.data1_start, 0, applet->layout.data1_size); + } + if (applet->layout.data2_size > 0) { + memset((void*)applet->layout.data2_start, 0, applet->layout.data2_size); + } +} + +bool applet_reset(applet_t* applet, uint32_t cmd, const void* arg, + size_t arg_size) { + // Clear all memory the applet is allowed to use + applet_clear_memory(applet); + + // Reset the applet task (stack pointer, etc.) + systask_init(&applet->task, applet->header->stack_start, + applet->header->stack_size); + + // Copy the arguments onto the applet stack + void* arg_copy = NULL; + if (arg != NULL && arg_size > 0) { + arg_copy = systask_push_data(&applet->task, arg, arg_size); + if (arg_copy == NULL) { + return false; + } + } + + // Schedule the applet task run + uint32_t arg1 = cmd; + uint32_t arg2 = (uint32_t)arg_copy; + uint32_t arg3 = rng_get(); + + return systask_push_call(&applet->task, applet->header->startup, arg1, arg2, + arg3); +} + +#endif // SYSCALL_DISPATCH diff --git a/core/embed/trezorhal/stm32f4/fault_handlers.c b/core/embed/trezorhal/stm32f4/fault_handlers.c deleted file mode 100644 index 35fc0ed0302..00000000000 --- a/core/embed/trezorhal/stm32f4/fault_handlers.c +++ /dev/null @@ -1,58 +0,0 @@ -#include TREZOR_BOARD - -#include "common.h" -#include "mpu.h" - -#ifdef KERNEL_MODE - -void fault_handlers_init(void) { - // Enable BUS fault and USAGE fault handlers - SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk); -} - -void HardFault_Handler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(HF)"); -} - -void MemManage_Handler_MM(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(MM)"); -} - -void MemManage_Handler_SO(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(SO)"); -} - -void BusFault_Handler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(BF)"); -} - -void UsageFault_Handler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(UF)"); -} - -void NMI_Handler(void) { - mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); - // Clock Security System triggered NMI - if ((RCC->CIR & RCC_CIR_CSSF) != 0) { - error_shutdown("(CS)"); - } - mpu_restore(mpu_mode); -} - -// from util.s -extern void shutdown_privileged(void); - -void PVD_IRQHandler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); -#ifdef BACKLIGHT_PWM_TIM - BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; // turn off display backlight -#endif - shutdown_privileged(); -} - -#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/syscall.c b/core/embed/trezorhal/stm32f4/syscall.c index 8fde6b42ac7..2846ba68e66 100644 --- a/core/embed/trezorhal/stm32f4/syscall.c +++ b/core/embed/trezorhal/stm32f4/syscall.c @@ -17,40 +17,44 @@ * along with this program. If not, see . */ -#include STM32_HAL_H - #include "syscall.h" -#include "image.h" -#include "irq.h" #include "mpu.h" #ifdef SYSCALL_DISPATCH -void syscall_init(void) { - // SVCall priority should be the lowest since it is - // generally a blocking operation - NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_LOWEST); -} - __attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback( - uint32_t arg1, uint32_t arg2, uint32_t arg3, void *callback) { + uint32_t arg1, uint32_t arg2, uint32_t arg3, void* callback) { __asm__ volatile( "push {r1-r12, lr} \n" - "mrs r12, PSP \n" // reserved frame on unprivileged stack (!@# - // TODO check PSP value???) +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + "mrs r12, PSPLIM \n" // Backup unprivileged stack limit + "push {r12} \n" +#endif + "mrs r12, PSP \n" // Backup unprivileged stack pointer "push {r12} \n" - "sub r12, r12, #32 \n" + + "sub r12, r12, #32 \n" // Reserve space for stack frame "msr PSP, r12 \n" - "str r0, [r12, #0] \n" // r0 - "str r1, [r12, #4] \n" // r1" - "str r2, [r12, #8] \n" // r2" + "str r0, [r12, #0] \n" // pass r0 + "str r1, [r12, #4] \n" // pass r1 + "str r2, [r12, #8] \n" // pass r2 "mov r1, #0 \n" - "str r1, [r12, #12] \n" // r3" - "str r1, [r12, #16] \n" // r12" - "str r1, [r12, #20] \n" // lr" + + "mov r4, r1 \n" // Clear registers r4-r11 + "mov r5, r1 \n" + "mov r6, r1 \n" + "mov r7, r1 \n" + "mov r8, r1 \n" + "mov r9, r1 \n" + "mov r10, r1 \n" + "mov r11, r1 \n" + + "str r1, [r12, #12] \n" // clear r3 + "str r1, [r12, #16] \n" // clear r12 + "str r1, [r12, #20] \n" // clear lr "bic r3, r3, #1 \n" "str r3, [r12, #24] \n" // return address @@ -58,14 +62,8 @@ __attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback( "ldr r1, = 0x01000000 \n" "str r1, [r12, #28] \n" // xPSR - "ldr r1, = 0xE000EF34 \n" // FPU->FPPCCR - "ldr r0, [r1] \n" - "bic r0, r0, #1 \n" // Clear LSPACT to suppress lazy stacking to - "str r0, [r1] \n" // avoid potential PSP stack overwrite. - - "mrs r1, CONTROL \n" - "bic r1, r1, #4 \n" // Clear FPCA to suppress lazy stacking to - "msr CONTROL, r1 \n" // avoid potential PSP stack overwrite. + "vmov r0, s0 \n" // Use FPU instruction to ensure lazy + // stacking // return to Secure Thread mode (use Secure PSP) "ldr lr, = 0xFFFFFFFD \n" @@ -73,133 +71,31 @@ __attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback( } uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3, - void *callback) { + void* callback) { mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_APP); uint32_t retval = _invoke_app_callback(args1, arg2, arg3, callback); mpu_reconfig(mpu_mode); return retval; } -// Jumps to reset vector of unprivileged application code -// -// Can be called only from an exception handler -__attribute__((naked, no_stack_protector)) static void start_app( - uint32_t app_start) { +__attribute__((naked, no_stack_protector)) void return_from_app_callback( + uint32_t retval, uint32_t* msp) { __asm__ volatile( - "ldr r12, [r0, #0] \n" // stack pointer - "sub r12, r12, #32 \n" - "msr PSP, r12 \n" - - "mov r1, #0 \n" - "str r1, [r12, #0] \n" // r0 - "str r1, [r12, #4] \n" // r1" - "str r1, [r12, #8] \n" // r2" - "str r1, [r12, #12] \n" // r3" - "str r1, [r12, #16] \n" // r12" - "str r1, [r12, #20] \n" // lr" - - "ldr r1, [r0, #4] \n" // reset vector - "bic r1, r1, #1 \n" - "str r1, [r12, #24] \n" // return address - - "ldr r1, = 0x01000000 \n" - "str r1, [r12, #28] \n" // xPSR - - "ldr r1, = 0xE000EF34 \n" // FPU->FPPCCR - "ldr r0, [r1] \n" - "bic r0, r0, #1 \n" // Clear LSPACT to suppress lazy stacking to - "str r0, [r1] \n" // avoid potential PSP stack overwrite. - - "mrs r1, CONTROL \n" - "bic r1, r1, #4 \n" // Clear FPCA to suppress lazy stacking to - "msr CONTROL, r1 \n" // avoid potential PSP stack overwrite. - - "mrs r1, CONTROL \n" // Switch thread mode to unprivileged - "orr r1, r1, #1 \n" // by setting nPRIV bit in CONTROL register. - "msr CONTROL, r1 \n" // This applies after return from this - // handler. - - // return to Secure Thread mode (use Secure PSP) - "ldr lr, = 0xFFFFFFFD \n" - "bx lr \n"); -} - -void SVC_C_Handler(uint32_t *stack, uint32_t r4, uint32_t r5, uint32_t r6) { - uint8_t svc_number = ((uint8_t *)stack[6])[-2]; - uint32_t args[6] = {stack[0], stack[1], stack[2], stack[3], r4, r5}; - - mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); - - switch (svc_number) { -#ifdef SYSTEM_VIEW - case SVC_GET_DWT_CYCCNT: - cyccnt_cycles = *DWT_CYCCNT_ADDR; - break; + "MSR MSP, R1 \n" + "POP {R1} \n" + "MSR PSP, R1 \n" +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + "POP {R1} \n" + "MSR PSPLIM, R1 \n" #endif - case SVC_START_APP: - mpu_reconfig(MPU_MODE_APP); - start_app(args[0]); - break; - case SVC_SYSCALL: - syscall_handler(args, r6); - stack[0] = args[0]; - stack[1] = args[1]; - break; - default: - stack[0] = 0xffffffff; - stack[1] = 0xffffffff; - break; - } - - mpu_restore(mpu_mode); -} - -__attribute__((naked, no_stack_protector)) void SVC_Handler(void) { - __asm__ volatile( - " tst lr, #4 \n" // Bit #3 tells which stack pointer should we - // use - " ite eq \n" // Next 2 instructions are if-then-else - " mrseq r0, msp \n" // Make R0 point to main stack pointer - " mrsne r0, psp \n" // Make R0 point to process stack pointer - - " ldr r1, [r0, #24] \n" // Load the PC of the SVC handler - " ldrb r1, [r1, #-2] \n" // Load the instruction at the PC - " cmp r1, #2 \n" // SVC_CALLBACK_RETURN - " beq svc_callback_return \n" - - " mov r1, r4 \n" // pass R4 (arg5), R5 (arg6) and - " mov r2, r5 \n" // R6 (sycall_number) as arguments - " mov r3, r6 \n" // to SCV_C_Handler - " b SVC_C_Handler \n" // - - "svc_callback_return: \n" - - " ldr r0, [r0] \n" - " pop {r1} \n" - " msr PSP, r1 \n" - " pop {r1-r12, lr} \n" - " bx lr \n"); -} - -void __attribute__((no_stack_protector, noreturn)) -start_unprivileged_app(void) { - //!@# TODO calculate better - static const uint32_t app_start = COREAPP_START + IMAGE_HEADER_SIZE + 0x0400; - - mpu_reconfig(MPU_MODE_APP); - - register uint32_t ret __asm__("r0") = app_start; - // SVC_START_APP is the only SVC that is allowed to be invoked from kernel - // itself and it is used to start the unprivileged application code - __asm__ volatile("svc %[svid]\n" - : "=r"(ret) - : [svid] "i"(SVC_START_APP), "r"(ret) - : "memory"); + "LDR R1, = 0xE000EF34 \n" // FPU->FPCCR + "LDR R2, [R1] \n" + "BIC R2, R2, #1 \n" // Clear LSPACT to suppress repeated lazy + "STR R2, [R1] \n" // stacking that was already done - // We never get here, just to supress compiler warning - while (1) { - } + "POP {R1-R12, LR} \n" + "BX LR \n"); } #endif // SYSCALL_DISPATCH diff --git a/core/embed/trezorhal/stm32f4/syscall.h b/core/embed/trezorhal/stm32f4/syscall.h index 32da335d907..de64aaa906c 100644 --- a/core/embed/trezorhal/stm32f4/syscall.h +++ b/core/embed/trezorhal/stm32f4/syscall.h @@ -22,18 +22,16 @@ #include +#include "applet.h" #include "syscall_numbers.h" // Reserved SVC numbers #define SVC_SYSCALL 0 -#define SVC_START_APP 1 +#define SVC_SYSTASK_YIELD 1 #define SVC_CALLBACK_RETURN 2 #ifdef KERNEL_MODE -// Initializes the SVC/Syscall handlers -void syscall_init(void); - // Handles all syscall requests. // // `args` points to an array of six 32-bit arguments. @@ -44,14 +42,20 @@ void syscall_init(void); // // Return values must be copied to `args[0]` and // `args[1]` (if returning a 64-bit value). -void syscall_handler(uint32_t *args, uint32_t syscall); +void syscall_handler(uint32_t* args, uint32_t syscall); -// Invokes application callback from the syscall handler +// Invokes the application callback from the syscall handler. +// +// This is a *temporary* helper function used to invoke application callbacks +// from the syscall handler. It will be removed once all callback arguments +// are eliminated from syscalls. uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3, - void *callback); + void* callback); -// Jumps to reset vector in the unprivileged application -void __attribute__((noreturn)) start_unprivileged_app(void); +// Internal function for returning from an application callback. +// This function is called from an unprivileged app via an SVC call. It restores +// the stack pointer and returns control to the privileged caller. +void return_from_app_callback(uint32_t retval, uint32_t* msp); #else // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/syscall_dispatch.c b/core/embed/trezorhal/stm32f4/syscall_dispatch.c index 3e4510f9899..c4dafbb3705 100644 --- a/core/embed/trezorhal/stm32f4/syscall_dispatch.c +++ b/core/embed/trezorhal/stm32f4/syscall_dispatch.c @@ -34,6 +34,8 @@ #include "rng.h" #include "sdcard.h" #include "secret.h" +#include "systask.h" +#include "system.h" #include "systick.h" #include "touch.h" #include "translations.h" @@ -61,8 +63,23 @@ static void firmware_hash_callback_wrapper(void *context, uint32_t progress, firmware_hash_callback); } -void syscall_handler(uint32_t *args, uint32_t syscall) { +__attribute((no_stack_protector)) void syscall_handler(uint32_t *args, + uint32_t syscall) { switch (syscall) { + case SYSCALL_SYSTEM_EXIT: { + systask_t *task = systask_active(); + systask_exit(task, (int)args[0]); + } break; + case SYSCALL_SYSTEM_EXIT_ERROR: { + systask_t *task = systask_active(); + systask_exit_error(task, (const char *)args[0], (const char *)args[1], + (const char *)args[2]); + } break; + case SYSCALL_SYSTEM_EXIT_FATAL: { + systask_t *task = systask_active(); + systask_exit_fatal(task, (const char *)args[0], (const char *)args[1], + (int)args[2]); + } break; case SYSCALL_SYSTICK_CYCLES: { uint64_t cycles = systick_cycles(); args[0] = cycles & 0xFFFFFFFF; diff --git a/core/embed/trezorhal/stm32f4/syscall_numbers.h b/core/embed/trezorhal/stm32f4/syscall_numbers.h index adc0d5b563d..4e602032eeb 100644 --- a/core/embed/trezorhal/stm32f4/syscall_numbers.h +++ b/core/embed/trezorhal/stm32f4/syscall_numbers.h @@ -20,10 +20,14 @@ #ifndef SYSCALL_NUMBERS_H #define SYSCALL_NUMBERS_H +// Syscall identifiers typedef enum { - // Syscalls numbers - SYSCALL_SYSTICK_CYCLES = 1, + SYSCALL_SYSTEM_EXIT = 1, + SYSCALL_SYSTEM_EXIT_ERROR, + SYSCALL_SYSTEM_EXIT_FATAL, + + SYSCALL_SYSTICK_CYCLES, SYSCALL_SYSTICK_MS, SYSCALL_SYSTICK_US, SYSCALL_SYSTICK_US_TO_CYCLES, diff --git a/core/embed/trezorhal/stm32f4/syscall_stubs.c b/core/embed/trezorhal/stm32f4/syscall_stubs.c index 1da1d3ef170..10fc13cd3dc 100644 --- a/core/embed/trezorhal/stm32f4/syscall_stubs.c +++ b/core/embed/trezorhal/stm32f4/syscall_stubs.c @@ -21,6 +21,33 @@ #ifndef KERNEL_MODE +// ============================================================================= +// system.h +// ============================================================================= + +#include "system.h" + +void system_exit(int exit_code) { + syscall_invoke1(exit_code, SYSCALL_SYSTEM_EXIT); + while (1) + ; +} + +void system_exit_error(const char *title, const char *message, + const char *footer) { + syscall_invoke3((uint32_t)title, (uint32_t)message, (uint32_t)footer, + SYSCALL_SYSTEM_EXIT_ERROR); + while (1) + ; +} + +void system_exit_fatal(const char *message, const char *file, int line) { + syscall_invoke3((uint32_t)message, (uint32_t)file, line, + SYSCALL_SYSTEM_EXIT_FATAL); + while (1) + ; +} + // ============================================================================= // systick.h // ============================================================================= diff --git a/core/embed/trezorhal/stm32f4/systask.c b/core/embed/trezorhal/stm32f4/systask.c new file mode 100644 index 00000000000..56456f7c08b --- /dev/null +++ b/core/embed/trezorhal/stm32f4/systask.c @@ -0,0 +1,639 @@ +/* + * 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 STM32_HAL_H + +#include +#include + +#include "bootutils.h" +#include "irq.h" +#include "mpu.h" +#include "syscall.h" +#include "systask.h" +#include "system.h" + +#ifdef KERNEL_MODE + +// Disable stack protector for this file since it may interfere +// with the stack manipulation and fault handling +#pragma GCC optimize("no-stack-protector") + +#define STK_FRAME_R0 0 +#define STK_FRAME_R1 1 +#define STK_FRAME_R2 2 +#define STK_FRAME_R3 3 +#define STK_FRAME_R12 4 +#define STK_FRAME_LR 5 +#define STK_FRAME_RET_ADDR 6 +#define STK_FRAME_XPSR 7 + +// Task manager state +typedef struct { + // Error handler called when a kernel task terminates + systask_error_handler_t error_handler; + // Background kernel task + systask_t kernel_task; + // Currently running task + systask_t* active_task; + // Task to be scheduled next + 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 + // to function correctly before the scheduler is initialized. + .active_task = &g_systask_scheduler.kernel_task, + .waiting_task = &g_systask_scheduler.kernel_task, + .kernel_task = { + .sp_lim = (uint32_t)&_sstack, + }}; + +void systask_scheduler_init(systask_error_handler_t error_handler) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + memset(scheduler, 0, sizeof(systask_scheduler_t)); + + scheduler->error_handler = error_handler; + scheduler->active_task = &scheduler->kernel_task; + scheduler->waiting_task = scheduler->active_task; + + scheduler->kernel_task.sp_lim = (uint32_t)&_sstack; + + // SVCall priority should be the lowest since it is + // generally a blocking operation + NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_LOWEST); + NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_LOWEST); + + // Enable BusFault and UsageFault handlers + SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk); +} + +systask_t* systask_active(void) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + return scheduler->active_task; +} + +static void systask_yield(void) { + bool handler_mode = (__get_IPSR() & IPSR_ISR_Msk) != 0; + + if (handler_mode) { + SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; + __DSB(); + } else { + // SVC_SYSTASK_YIELD is the only SVC that is allowed to be invoked from + // kernel itself, and it is used to start the unprivileged application code. + __asm__ volatile("svc %[svid]\n" + : // no output + : [svid] "i"(SVC_SYSTASK_YIELD) + : "memory"); + } +} + +void systask_yield_to(systask_t* task) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + irq_key_t irq_key = irq_lock(); + scheduler->waiting_task = task; + irq_unlock(irq_key); + + systask_yield(); +} + +void systask_init(systask_t* task, uint32_t stack_ptr, uint32_t stack_size) { + memset(task, 0, sizeof(systask_t)); + task->sp = stack_ptr + stack_size; + task->sp_lim = stack_ptr + 256; + task->exc_return = 0xFFFFFFED; // Thread mode, use PSP, pop FP context + task->mpu_mode = MPU_MODE_APP; +} + +uint32_t* systask_push_data(systask_t* task, const void* data, size_t size) { + if (task->sp < task->sp_lim) { + // Stack overflow + return NULL; + } + + uint32_t stack_remaining = task->sp - task->sp_lim; + + if (stack_remaining < size) { + // Not enough space on the stack + return NULL; + } + + task->sp -= size; + + if (data != NULL) { + memcpy((void*)task->sp, data, size); + } else { + memset((void*)task->sp, 0, size); + } + + return (void*)task->sp; +} + +void systask_pop_data(systask_t* task, size_t size) { task->sp += size; } + +bool systask_push_call(systask_t* task, void* entrypoint, uint32_t arg1, + uint32_t arg2, uint32_t arg3) { + uint32_t original_sp = task->sp; + + // Align stack pointer to 8 bytes + task->sp &= ~7; + + // FP extension context + if (systask_push_data(task, NULL, 0x48) == NULL) { + goto cleanup; + } + + // Standard exception frame + uint32_t* stk_frame = systask_push_data(task, NULL, 0x20); + if (stk_frame == NULL) { + goto cleanup; + } + + // Registers r4-r11 + if (systask_push_data(task, NULL, 0x20) == NULL) { + goto cleanup; + } + // Registers s16-s31 + if (systask_push_data(task, NULL, 0x40) == NULL) { + goto cleanup; + } + + // Return to thread mode, use PSP, pop FP context + task->exc_return = 0xFFFFFFED; + + stk_frame[STK_FRAME_R0] = arg1; + stk_frame[STK_FRAME_R1] = arg2; + stk_frame[STK_FRAME_R2] = arg3; + stk_frame[STK_FRAME_RET_ADDR] = (uint32_t)entrypoint & ~1; + stk_frame[STK_FRAME_XPSR] = 0x01000000; // T (Thumb state) bit set + + return true; + +cleanup: + task->sp = original_sp; + return false; +} + +static void systask_kill(systask_t* task) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + task->killed = 1; + + if (task == &scheduler->kernel_task) { + // Call panic handler + if (scheduler->error_handler != NULL) { + scheduler->error_handler(&task->pminfo); + } + secure_shutdown(); + } else if (task == scheduler->active_task) { + // Switch to the kernel task + systask_yield_to(&scheduler->kernel_task); + } +} + +void systask_exit(systask_t* task, int exit_code) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + if (task == NULL) { + bool handler_mode = (__get_IPSR() & IPSR_ISR_Msk) != 0; + task = handler_mode ? &scheduler->kernel_task : scheduler->active_task; + } + + systask_postmortem_t* pminfo = &task->pminfo; + + memset(pminfo, 0, sizeof(systask_postmortem_t)); + pminfo->reason = TASK_TERM_REASON_EXIT; + pminfo->privileged = (task == &scheduler->kernel_task); + pminfo->exit.code = exit_code; + + systask_kill(task); +} + +void systask_exit_error(systask_t* task, const char* title, const char* message, + const char* footer) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + if (task == NULL) { + bool handler_mode = (__get_IPSR() & IPSR_ISR_Msk) != 0; + task = handler_mode ? &scheduler->kernel_task : scheduler->active_task; + } + + systask_postmortem_t* pminfo = &task->pminfo; + + memset(pminfo, 0, sizeof(systask_postmortem_t)); + pminfo->reason = TASK_TERM_REASON_ERROR; + pminfo->privileged = (task == &scheduler->kernel_task); + + if (title != NULL) { + strncpy(pminfo->error.title, title, sizeof(pminfo->error.title) - 1); + } + + if (message != NULL) { + strncpy(pminfo->error.message, message, sizeof(pminfo->error.message) - 1); + } + + if (footer != NULL) { + strncpy(pminfo->error.footer, footer, sizeof(pminfo->error.footer) - 1); + } + + systask_kill(task); +} + +void systask_exit_fatal(systask_t* task, const char* message, const char* file, + int line) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + if (task == NULL) { + bool handler_mode = (__get_IPSR() & IPSR_ISR_Msk) != 0; + task = handler_mode ? &scheduler->kernel_task : scheduler->active_task; + } + + systask_postmortem_t* pminfo = &task->pminfo; + + memset(pminfo, 0, sizeof(systask_postmortem_t)); + pminfo->reason = TASK_TERM_REASON_FATAL; + pminfo->privileged = (task == &scheduler->kernel_task); + + if (message != NULL) { + strncpy(pminfo->fatal.expr, message, sizeof(pminfo->fatal.expr) - 1); + } + + if (file != NULL) { + strncpy(pminfo->fatal.file, file, sizeof(pminfo->fatal.file) - 1); + } + + pminfo->fatal.line = line; + + systask_kill(task); +} + +// Terminate active task from fault/exception handler +__attribute((used)) static void systask_exit_fault(bool privileged, + uint32_t sp) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); + + systask_scheduler_t* scheduler = &g_systask_scheduler; + + systask_t* task = + privileged ? &scheduler->kernel_task : scheduler->active_task; + + systask_postmortem_t* pminfo = &task->pminfo; + + // Do not overwrite the reason if it is already set to fault + // (exception handlers may call this function multiple times, and + // we want to preserve the first reason) + if (pminfo->reason != TASK_TERM_REASON_FAULT) { + pminfo->reason = TASK_TERM_REASON_FAULT; + pminfo->privileged = privileged; + pminfo->fault.sp = sp; +#if !(defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)) + pminfo->fault.sp_lim = task->sp_lim; +#endif + pminfo->fault.irqn = (__get_IPSR() & IPSR_ISR_Msk) - 16; + pminfo->fault.cfsr = SCB->CFSR; + pminfo->fault.mmfar = SCB->MMFAR; + pminfo->fault.bfar = SCB->BFAR; + pminfo->fault.hfsr = SCB->HFSR; + } + + systask_kill(task); + + mpu_restore(mpu_mode); +} + +// C part of PendSV handler that switches tasks +// +// `sp` is the stack pointer of the current task +// `sp_lim` is the stack pointer limit of the current task +// `exc_return` is the execution state of the current task +// +// Returns the context struct of the next task +__attribute((no_stack_protector, used)) static uint32_t scheduler_pendsv( + uint32_t sp, uint32_t sp_lim, uint32_t exc_return) { + systask_scheduler_t* scheduler = &g_systask_scheduler; + + // Save the current task context + systask_t* prev_task = scheduler->active_task; + prev_task->sp = sp; +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + // sp_lim is not valid on ARMv7-M + prev_task->sp_lim = sp_lim; +#endif + prev_task->exc_return = exc_return; + prev_task->mpu_mode = mpu_get_mode(); + + // Switch to the next task + scheduler->active_task = scheduler->waiting_task; + + // Load the scheduled task context + systask_t* next_task = scheduler->active_task; + + // Set task privilege level + uint32_t control = __get_CONTROL(); + if (next_task == &scheduler->kernel_task) { + control &= ~CONTROL_nPRIV_Msk; + } else { + control |= CONTROL_nPRIV_Msk; + } + __set_CONTROL(control); + + // Setup the MPU for the new task + mpu_reconfig(next_task->mpu_mode); + + return (uint32_t)next_task; +} + +__attribute__((naked, no_stack_protector)) void PendSV_Handler(void) { + __asm__ volatile( + "LDR R0, =%[active_task] \n" + "LDR R1, =%[waiting_task]\n" + "CMP R0, R1 \n" + "BEQ 3f \n" // No task switch needed + + "LDR R0, [R0] \n" // R0 = active_task + "LDR R0, [R0, #12] \n" // R0 = active_task->killed + "CMP R0, #0 \n" + "BEQ 1f \n" // =0 => normal processing + + // We are switching from a killed task to the kernel task. + // Since the reason might be a stack overflow, we must not + // attempt to save the task context. + + "LDR R1, = 0xE000EF34 \n" // FPU->FPCCR + "LDR R0, [R1] \n" + "BIC R0, R0, #1 \n" // Clear LSPACT to suppress later lazy + "STR R0, [R1] \n" // stacking to the killed task stack + + "MOV R0, #0 \n" // Skip context save + "MOV R1, R0 \n" // + "MOV R2, R0 \n" // + "B 2f \n" // + + "1: \n" + + // Save the current task context on its stack before switching + + "TST LR, #0x4 \n" // Return stack (1=>PSP, 0=>MSP) + +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + "ITTEE EQ \n" + "MRSEQ R0, MSP \n" // Get current SP + "MRSEQ R1, MSPLIM \n" // Get current SP Limit + "MRSNE R0, PSP \n" + "MRSNE R1, PSPLIM \n" +#else + "ITE EQ \n" + "MRSEQ R0, MSP \n" // Get current SP + "MRSNE R0, PSP \n" + "MOV R1, #0 \n" // (fake SPLIM) +#endif + "IT EQ \n" // If using main stack: + "SUBEQ SP, SP, #0x60 \n" // reserve space for R4-11 and S16-S31 + + "MOV R2, LR \n" // Get current EXC_RETURN + + "STMDB R0!, {R4-R11} \n" // Save R4-R11 to SP Frame Stack + "TST LR, #0x10 \n" // Check EXC_RETURN.Ftype bit to see if + // the current thread has a FP context + "IT EQ \n" + "VSTMDBEQ R0!, {S16-S31} \n" // If so, save S16-S31 FP addition + // context, that will also trigger lazy + // fp context preservation of S0-S15 + "2: \n" + + "BL scheduler_pendsv \n" // Save SP value of current task + "LDR LR, [R0, #8] \n" // Get the EXC_RETURN value + "LDR R1, [R0, #4] \n" // Get the SP_LIM value + "LDR R0, [R0, #0] \n" // Get the SP value + + "TST LR, #0x10 \n" // Check EXC_RETURN.Ftype bit to see if + // the next thread has a FP context + "IT EQ \n" + "VLDMIAEQ R0!, {S16-S31} \n" // If so, restore S16-S31 + "LDMIA R0!, {R4-R11} \n" // Restore R4-R11 + + "TST LR, #0x4 \n" // Return stack (1=>PSP, 0=>MSP) +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + "ITEE EQ \n" + "MSREQ MSP, R0 \n" // Update MSP + "MSRNE PSPLIM, R1 \n" // Update PSPLIM & PSP + "MSRNE PSP, R0 \n" +#else + "ITE EQ \n" + "MSREQ MSP, R0 \n" // Update the MSP + "MSRNE PSP, R0 \n" // Update the PSP +#endif + "3: " + "BX LR \n" + : // No output + : [active_task] "i"(&g_systask_scheduler.active_task), // Input + [waiting_task] "i"(&g_systask_scheduler.waiting_task) // Input + : // Clobber + ); +} + +__attribute__((no_stack_protector, used)) static uint32_t svc_handler( + uint32_t* stack, uint32_t* msp, uint32_t exc_return, uint32_t r4, + uint32_t r5, uint32_t r6) { + uint8_t svc_number = ((uint8_t*)stack[6])[-2]; + +#ifdef SYSCALL_DISPATCH + uint32_t args[6] = {stack[0], stack[1], stack[2], stack[3], r4, r5}; +#endif + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); + + switch (svc_number) { +#ifdef SYSTEM_VIEW + case SVC_GET_DWT_CYCCNT: + cyccnt_cycles = *DWT_CYCCNT_ADDR; + break; +#endif + case SVC_SYSTASK_YIELD: + // Yield to the waiting task + systask_yield(); + break; +#ifdef SYSCALL_DISPATCH + case SVC_SYSCALL: + syscall_handler(args, r6); + stack[0] = args[0]; + stack[1] = args[1]; + break; + case SVC_CALLBACK_RETURN: + // g_return_value = args[0] + // exc_return = return_from_callback; + mpu_restore(mpu_mode); + return_from_app_callback(args[0], msp); + break; +#endif + default: + break; + } + + mpu_restore(mpu_mode); + return exc_return; +} + +__attribute((naked, no_stack_protector)) void SVC_Handler(void) { + __asm__ volatile( + "TST LR, #0x4 \n" // Return stack (1=>PSP, 0=>MSP) + "ITE EQ \n" + "MRSEQ R0, MSP \n" // `stack` argument + "MRSNE R0, PSP \n" + "TST LR, #0x20 \n" + "IT EQ \n" + "ADDEQ R0, R0, #0x40 \n" + "MRS R1, MSP \n" // `msp` argument + "MOV R2, LR \n" // `exc_return` argument + "MOV R3, R4 \n" // 'r4' argument + "PUSH {R5, R6} \n" // 'r5' and 'r6' arguments on stack + "BL svc_handler \n" + "POP {R5, R6} \n" + "BX R0 \n" // Branch to the returned value + ); +} + +__attribute__((naked, no_stack_protector)) void HardFault_Handler(void) { + // A HardFault may also be caused by exception escalation. + // To ensure we have enough space to handle the exception, + // we set the stack pointer to the end of the stack. + + __asm__ volatile( + "MRS R1, MSP \n" // R1 = MSP + "LDR R0, =%[estack] \n" // Reset main stack + "MSR MSP, R0 \n" // + "MOV R0, #1 \n" // R0 = 1 (Privileged) + "B systask_exit_fault \n" // Exit task with fault + : + : [estack] "i"(&_estack) + : "memory"); +} + +__attribute__((naked, no_stack_protector)) void MemManage_Handler(void) { + __asm__ volatile( + "TST LR, #0x4 \n" // Return stack (1=>PSP, 0=>MSP) + "ITTEE EQ \n" + "MOVEQ R0, #1 \n" // R0 = 1 (Privileged) + "MRSEQ R1, MSP \n" // R1 = MSP + "MOVNE R0, #0 \n" // R0 = 0 (Unprivileged) + "MRSNE R1, PSP \n" // R1 = PSP +#if !(defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)) + "CMP R0, #0 \n" + "BEQ 1f \n" // Skip stack ptr checking for PSP + "LDR R2, =%[sstack] \n" + "CMP R1, R2 \n" // Check if PSP is below the stack + "ITT LO \n" // base + "LDRLO R2, =%[estack] \n" + "MSRLO MSP, R2 \n" // Reset MSP + "1: \n" +#endif + "B systask_exit_fault \n" // Exit task with fault + : + : [estack] "i"(&_estack), [sstack] "i"((uint32_t)&_sstack + 256) + : "memory"); +} + +__attribute__((naked, no_stack_protector)) void BusFault_Handler(void) { + __asm__ volatile( + "TST LR, #0x4 \n" // Return stack (1=>PSP, 0=>MSP) + "ITTEE EQ \n" + "MOVEQ R0, #1 \n" // R0 = 1 (Privileged) + "MRSEQ R1, MSP \n" // R1 = MSP + "MOVNE R0, #0 \n" // R0 = 0 (Unprivileged) + "MRSNE R1, PSP \n" // R1 = PSP + "B systask_exit_fault \n" // Exit task with fault + ); +} + +__attribute__((naked, no_stack_protector)) void UsageFault_Handler(void) { + __asm__ volatile( + "TST LR, #0x4 \n" // Return stack (1=>PSP, 0=>MSP) + "ITTT NE \n" + "MOVNE R0, #0 \n" // R0 = 0 (Unprivileged) + "MRSNE R1, PSP \n" // R1 = PSP + "BNE systask_exit_fault \n" // Exit task with fault +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + "MRS R1, MSP \n" // R1 = MSP + "LDR R0, =0xE000ED28 \n" // SCB->CFSR + "LDR R0, [R0] \n" + "TST R0, #0x100000 \n" // STKOF bit set? + "ITT NE \n" + "LDRNE R0, =%[estack] \n" // Reset main stack in case of stack + "MSRNE MSP, R0 \n" // overflow +#endif + "MOV R0, #1 \n" // R0 = 1 (Privileged) + "B systask_exit_fault \n" // Exit task with fault + : + : [estack] "i"(&_estack) + : "memory"); +} + +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) +__attribute__((naked, no_stack_protector)) void SecureFault_Handler(void) { + __asm__ volatile( + "TST LR, #0x4 \n" // Return stack (1=>PSP, 0=>MSP) + "ITTEE EQ \n" + "MOVEQ R0, #1 \n" // R0 = 1 (Privileged) + "MRSEQ R1, MSP \n" // R1 = MSP + "MOVNE R0, #0 \n" // R0 = 0 (Unprivileged) + "MRSNE R1, PSP \n" // R1 = PSP + "B systask_exit_fault \n" // Exit task with fault + ); +} +#endif + +#ifdef STM32U5 +void GTZC_IRQHandler(void) { systask_exit_fault(true, __get_MSP()); } +#endif + +void NMI_Handler(void) { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); +#ifdef STM32U5 + if ((RCC->CIFR & RCC_CIFR_CSSF) != 0) { +#else + if ((RCC->CIR & RCC_CIR_CSSF) != 0) { +#endif + // Clock Security System triggered NMI + systask_exit_fault(true, __get_MSP()); + } + mpu_restore(mpu_mode); +} + +// from util.s +extern void shutdown_privileged(void); + +void PVD_PVM_IRQHandler(void) { + mpu_reconfig(MPU_MODE_DEFAULT); +#ifdef BACKLIGHT_PWM_TIM + // Turn off display backlight + BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; +#endif + shutdown_privileged(); +} + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/system.c b/core/embed/trezorhal/stm32f4/system.c new file mode 100644 index 00000000000..351c359b0b5 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/system.c @@ -0,0 +1,310 @@ +/* + * 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 STM32_HAL_H + +#include "system.h" +#include "bootutils.h" +#include "mpu.h" +#include "systask.h" +#include "systick.h" +#include "systimer.h" + +#ifdef KERNEL_MODE + +void system_init(systask_error_handler_t error_handler) { + mpu_init(); + mpu_reconfig(MPU_MODE_DEFAULT); + systask_scheduler_init(error_handler); + systick_init(); + systimer_init(); +} + +void system_exit(int exitcode) { systask_exit(NULL, exitcode); } + +void system_exit_error(const char* title, const char* message, + const char* footer) { + systask_exit_error(NULL, title, message, footer); +} + +void system_exit_fatal(const char* message, const char* file, int line) { + systask_exit_fatal(NULL, message, file, line); +} + +#endif // KERNEL_MODE + +#ifndef HardFault_IRQn +#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32429xx.h +#endif + +#ifdef STM32U5 +const char* system_fault_message(const system_fault_t* fault) { + switch (fault->irqn) { + case HardFault_IRQn: + return "(HF)"; + case MemoryManagement_IRQn: + return "(MM)"; + case BusFault_IRQn: + return "(BF)"; + case UsageFault_IRQn: + return (fault->cfsr & SCB_CFSR_STKOF_Msk) ? "(SO)" : "(UF)"; + case SecureFault_IRQn: + return "(SF)"; + case GTZC_IRQn: + return "(IA)"; + case NonMaskableInt_IRQn: + return "(CS)"; + default: + return "(FAULT)"; + } +} +#else // STM32U5 +const char* system_fault_message(const system_fault_t* fault) { + switch (fault->irqn) { + case HardFault_IRQn: + return "(HF)"; + case MemoryManagement_IRQn: + return (fault->sp < fault->sp_lim) ? "(SO)" : "(MM)"; + case BusFault_IRQn: + return "(BF)"; + case UsageFault_IRQn: + return "(UF)"; + case NonMaskableInt_IRQn: + return "(CS)"; + default: + return "(FAULT)"; + } +} +#endif // STM32U5 + +__attribute__((used)) static void emergency_reset(void) { + // TODO: reset peripherals (at least DMA, DMA2D) + + // 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); +} + +__attribute((naked, 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 R1, =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" + + "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 + ); +} diff --git a/core/embed/trezorhal/stm32f4/util.S b/core/embed/trezorhal/stm32f4/util.S index defc3c70f96..94eae168aff 100644 --- a/core/embed/trezorhal/stm32f4/util.S +++ b/core/embed/trezorhal/stm32f4/util.S @@ -112,16 +112,4 @@ shutdown_privileged: ldr r0, =0 b . // loop forever - .global MemManage_Handler - .type MemManage_Handler, STT_FUNC -MemManage_Handler: - ldr r2, =_sstack - mrs r1, msp - ldr r0, =_estack - msr msp, r0 - cmp r1, r2 - IT lt - bllt MemManage_Handler_SO - bl MemManage_Handler_MM - .end diff --git a/core/embed/trezorhal/stm32f4/vectortable.S b/core/embed/trezorhal/stm32f4/vectortable.S index 1cfec8c262f..2f07d34fd11 100644 --- a/core/embed/trezorhal/stm32f4/vectortable.S +++ b/core/embed/trezorhal/stm32f4/vectortable.S @@ -132,7 +132,8 @@ vector_table: .section .vector_table, "a" vector_table: - .word main_stack_base // defined in linker script + .word _sstack + .word _stack_size .word reset_handler diff --git a/core/embed/trezorhal/stm32u5/applet.c b/core/embed/trezorhal/stm32u5/applet.c new file mode 120000 index 00000000000..0cdabf36aa6 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/applet.c @@ -0,0 +1 @@ +../stm32f4/applet.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/fault_handlers.c b/core/embed/trezorhal/stm32u5/fault_handlers.c deleted file mode 100644 index 2e4bbc78f83..00000000000 --- a/core/embed/trezorhal/stm32u5/fault_handlers.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "common.h" -#include "mpu.h" - -#ifdef KERNEL_MODE - -void fault_handlers_init(void) { - // Enable BUS fault and USAGE fault handlers - SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk); -} - -void HardFault_Handler(void) { - // A HardFault may also be caused by exception escalation. - // To ensure we have enough space to handle the exception, - // we set the stack pointer to the end of the stack. - extern uint8_t _estack; // linker script symbol - // Fix stack pointer - __set_MSP((uint32_t)&_estack); - - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(HF)"); -} - -void MemManage_Handler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(MM)"); -} - -void BusFault_Handler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(BF)"); -} - -void UsageFault_Handler(void) { - if (SCB->CFSR & SCB_CFSR_STKOF_Msk) { - // Stack overflow - extern uint8_t _estack; // linker script symbol - // Fix stack pointer - __set_MSP((uint32_t)&_estack); - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(SO)"); - } else { - // Other error - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(UF)"); - } -} - -void SecureFault_Handler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(SF)"); -} - -void GTZC_IRQHandler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - error_shutdown("(IA)"); -} - -void NMI_Handler(void) { - mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT); - // Clock Security System triggered NMI - if ((RCC->CIFR & RCC_CIFR_CSSF) != 0) { - error_shutdown("(CS)"); - } - mpu_restore(mpu_mode); -} - -// from util.s -extern void shutdown_privileged(void); - -void PVD_PVM_IRQHandler(void) { - mpu_reconfig(MPU_MODE_DEFAULT); - TIM1->CCR1 = 0; // turn off display backlight - shutdown_privileged(); -} - -#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32u5/systask.c b/core/embed/trezorhal/stm32u5/systask.c new file mode 120000 index 00000000000..7b6c139ae39 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/systask.c @@ -0,0 +1 @@ +../stm32f4/systask.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/system.c b/core/embed/trezorhal/stm32u5/system.c new file mode 120000 index 00000000000..36a84d685ca --- /dev/null +++ b/core/embed/trezorhal/stm32u5/system.c @@ -0,0 +1 @@ +../stm32f4/system.c \ No newline at end of file diff --git a/core/embed/trezorhal/stm32u5/vectortable.S b/core/embed/trezorhal/stm32u5/vectortable.S index 472414caeb9..d4f79d19503 100644 --- a/core/embed/trezorhal/stm32u5/vectortable.S +++ b/core/embed/trezorhal/stm32u5/vectortable.S @@ -180,7 +180,8 @@ vector_table: .section .vector_table, "a" vector_table: - .word main_stack_base // defined in linker script + .word _sstack + .word _stack_size .word reset_handler #endif diff --git a/core/embed/trezorhal/systask.h b/core/embed/trezorhal/systask.h new file mode 100644 index 00000000000..90170fdaf1c --- /dev/null +++ b/core/embed/trezorhal/systask.h @@ -0,0 +1,182 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_SYSTASK_H +#define TREZORHAL_SYSTASK_H + +#include +#include +#include + +#include "mpu.h" + +// Termination reason for the task +typedef enum { + TASK_TERM_REASON_EXIT = 0, + TASK_TERM_REASON_ERROR, + TASK_TERM_REASON_FATAL, + TASK_TERM_REASON_FAULT, + +} systask_term_reason_t; + +typedef struct { + // Fault/exception number (-15..-1) + int irqn; + // Configurable Fault Status Register + // (combined UFSR/BFSR/MMFSR) + uint32_t cfsr; + // Hard Fault Status Register + uint32_t hfsr; + // Address associated with MemManage fault + uint32_t mmfar; + // Address associated with the BusFault + uint32_t bfar; + // Stack pointer at the time of the fault + // (MSP or PSP depending on the privilege level) + uint32_t sp; +#if !(defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)) + // Stack pointer limit (for the stack overflow detection) + uint32_t sp_lim; +#endif + +} system_fault_t; + +// Task post-mortem information +typedef struct { + // Reason for the task termination + systask_term_reason_t reason; + // Whether the error occurred in privileged mode + bool privileged; + + union { + // Argument passed to `systask_exit()` + struct { + int code; + } exit; + + // Fault information catched in `systask_exit_fault()` + system_fault_t fault; + + // Arguments passed to `systask_exit_fatal()` + struct { + uint32_t line; + char file[64]; + char expr[64]; + } fatal; + + // Arguments passed to `systask_exit_error()` + struct { + char title[64]; + char message[64]; + char footer[64]; + } error; + }; + +} systask_postmortem_t; + +// Error handler callback invoke when kernel task terminates. +// +// The purpose of this callbacks display RSOD (Red Screen of Death). +// +// The callback may be called from any context, including interrupt context. +typedef void (*systask_error_handler_t)(const systask_postmortem_t* pminfo); + +#ifdef KERNEL_MODE + +// Task context used by the kernel to save the state of each task +// when switching between them +typedef struct { + // `sp`, `sp_lim`, `exc_return` and `killed` should at the beginning + // and in this order to be compatible with the PendSV_Handler + // Stack pointer value + uint32_t sp; + // Stack pointer limit (ARMv8-M only) + uint32_t sp_lim; + // Exception return value + uint32_t exc_return; + // Set to nonzero, if the task is killed + uint32_t killed; + + // MPU mode the task is running in + mpu_mode_t mpu_mode; + // Task post-mortem information + systask_postmortem_t pminfo; + +} systask_t; + +// Initializes the scheduler for tasks +// +// No other task functions should be called before this function +void systask_scheduler_init(systask_error_handler_t error_handler); + +// Returns the currently running task +systask_t* systask_active(void); + +// Makes the given task the currently running task +void systask_yield_to(systask_t* task); + +// Initializes a task with the given stack pointer, stack size +// +// The task must be not be running when the function is called +void systask_init(systask_t* task, uint32_t stack_ptr, uint32_t stack_size); + +// Pushes data onto the stack of the task +// +// The task must be not be running when the function is called +uint32_t* systask_push_data(systask_t* task, const void* data, size_t size); + +// Pops data from the stack of the task +// +// The task must be not be running when the function is called +void systask_pop_data(systask_t* task, size_t size); + +// Runs the task with the given entrypoint and arguments +// +// The task must be not be running when the function is called +// Return `true` in case of success, `false` otherwise +bool systask_push_call(systask_t* task, void* fn, uint32_t arg1, uint32_t arg2, + uint32_t arg3); + +// Terminates the task with the given exit code +// +// If the task is not specified (NULL), it's automatically determined: +// 1) If the function is called in thread mode, the active task will be +// terminated. +// 2) If the function is called in handler mode, the kernel task will be +// terminated even if it is not the active task. +// +// If the terminated task is unprivileged, the kernel task will be scheduled +// next. +void systask_exit(systask_t* task, int exit_code); + +// Terminates the task with an error message +// +// (see `systask_exit()` for more details) +void systask_exit_error(systask_t* task, const char* title, const char* message, + const char* footer); + +// Terminates the task with a fatal error message +// +// (see `systask_exit()` for more details) +void systask_exit_fatal(systask_t* task, const char* message, const char* file, + int line); + +#endif // KERNEL_MODE + +#endif // TREZORHAL_SYSTASK_H diff --git a/core/embed/trezorhal/system.h b/core/embed/trezorhal/system.h new file mode 100644 index 00000000000..07418111220 --- /dev/null +++ b/core/embed/trezorhal/system.h @@ -0,0 +1,68 @@ +/* + * 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 . + */ + +#ifndef TREZORHAL_SYSTEM_H +#define TREZORHAL_SYSTEM_H + +#include + +// Initializes the fundamental system services +// (MPU, SysTick, systimer and task scheduler). +// +// `error_handler` is a callback that is called when a kernel task terminates +// with an error +void system_init(systask_error_handler_t error_handler); + +// Terminates the current task normally with the given exit code. +// +// If the current task is the kernel task, the error handler is called with the +// postmortem information. If the task is not the kernel task, the task is +// terminated immediately and the kernel task is scheduled. +void system_exit(int exitcode); + +// Terminates the current task with an error message. +// +// See the notes for `system_exit` regarding the behavior of the error handler +void system_exit_error(const char* title, const char* message, + const char* footer); + +// Terminates the current task with a fatal error message. +// +// See the notes for `system_exit` regarding the behavior of the error handler +void system_exit_fatal(const char* message, const char* file, int line); + +// Returns string representation of the system fault. +const char* system_fault_message(const system_fault_t* fault); + +// Calls the error handler in the emergency mode. +// +// This function is called when the system encounters a critical error +// and needs to perform a useful action (such as displaying an error message) +// before it is reset or shut down. +// +// The function may be called from any context, including interrupt context. +// It completely resets stack pointers, clears the .bss segment, reinitializes +// the .data segment, and calls the `error_handler` callback. +// +// The system will be in a state similar to a reset when `main()` is called +// (but with some hardware peripherals still initialized and running). +__attribute__((noreturn)) void system_emergency_rescue( + systask_error_handler_t error_handler, const systask_postmortem_t* pminfo); + +#endif // TREZORHAL_SYSTEM_H diff --git a/core/embed/trezorhal/unix/system.c b/core/embed/trezorhal/unix/system.c new file mode 100644 index 00000000000..728bce47ef6 --- /dev/null +++ b/core/embed/trezorhal/unix/system.c @@ -0,0 +1,107 @@ +/* + * 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 + +#include "bootutils.h" +#include "system.h" +#include "systick.h" +#include "systimer.h" + +systask_error_handler_t g_error_handler = NULL; + +void system_init(systask_error_handler_t error_handler) { + g_error_handler = error_handler; + systick_init(); + systimer_init(); +} + +void system_exit(int exitcode) { + if (g_error_handler != NULL) { + systask_postmortem_t pminfo = {0}; + + pminfo.reason = TASK_TERM_REASON_EXIT; + pminfo.exit.code = exitcode; + + if (g_error_handler != NULL) { + g_error_handler(&pminfo); + } + } + + secure_shutdown(); +} + +void system_exit_error(const char* title, const char* message, + const char* footer) { + fprintf(stderr, "ERROR: %s\n", message); + fflush(stderr); + + if (g_error_handler != NULL) { + systask_postmortem_t pminfo = {0}; + + pminfo.reason = TASK_TERM_REASON_ERROR; + strncpy(pminfo.error.title, title, sizeof(pminfo.error.title) - 1); + strncpy(pminfo.error.message, message, sizeof(pminfo.error.message) - 1); + strncpy(pminfo.error.footer, footer, sizeof(pminfo.error.footer) - 1); + + if (g_error_handler != NULL) { + g_error_handler(&pminfo); + } + } + + secure_shutdown(); +} + +void system_exit_fatal(const char* message, const char* file, int line) { + fprintf(stderr, "ERROR: %s\n", message); + if (file) { + fprintf(stderr, "FILE: %s:%d\n", file, line); + } + fflush(stderr); + + if (g_error_handler != NULL) { + systask_postmortem_t pminfo = {0}; + + pminfo.reason = TASK_TERM_REASON_FATAL; + strncpy(pminfo.fatal.file, file, sizeof(pminfo.fatal.file) - 1); + strncpy(pminfo.fatal.expr, message, sizeof(pminfo.fatal.expr) - 1); + pminfo.fatal.line = line; + + if (g_error_handler != NULL) { + g_error_handler(&pminfo); + } + } + + secure_shutdown(); +} + +const char* system_fault_message(const system_fault_t* fault) { + // Not used in simulator + return "(FAULT)"; +} + +void system_emergency_rescue(systask_error_handler_t error_handler, + const systask_postmortem_t* pminfo) { + error_handler(pminfo); + + // We should never reach this point + exit(0); +} diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index c38b12e01fb..e8e4cb1cd1d 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -40,11 +40,11 @@ def stm32f4_common_files(env, defines, sources, paths): ] sources += [ + "embed/trezorhal/stm32f4/applet.c", "embed/trezorhal/stm32f4/board_capabilities.c", "embed/trezorhal/stm32f4/bootutils.c", "embed/trezorhal/stm32f4/common.c", "embed/trezorhal/stm32f4/entropy.c", - "embed/trezorhal/stm32f4/fault_handlers.c", "embed/trezorhal/stm32f4/flash.c", "embed/trezorhal/stm32f4/flash_otp.c", "embed/trezorhal/stm32f4/fwutils.c", @@ -56,6 +56,8 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/syscall.c", "embed/trezorhal/stm32f4/syscall_dispatch.c", "embed/trezorhal/stm32f4/syscall_stubs.c", + "embed/trezorhal/stm32f4/system.c", + "embed/trezorhal/stm32f4/systask.c", "embed/trezorhal/stm32f4/systick.c", "embed/trezorhal/stm32f4/systimer.c", "embed/trezorhal/stm32f4/time_estimate.c", diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index 0eea378cf68..c62c066fed1 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -49,11 +49,11 @@ def stm32u5_common_files(env, defines, sources, paths): ] sources += [ + "embed/trezorhal/stm32u5/applet.c", "embed/trezorhal/stm32u5/board_capabilities.c", "embed/trezorhal/stm32u5/bootutils.c", "embed/trezorhal/stm32u5/common.c", "embed/trezorhal/stm32u5/entropy.c", - "embed/trezorhal/stm32u5/fault_handlers.c", "embed/trezorhal/stm32u5/flash.c", "embed/trezorhal/stm32u5/flash_otp.c", "embed/trezorhal/stm32u5/fwutils.c", @@ -67,6 +67,8 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/syscall.c", "embed/trezorhal/stm32u5/syscall_dispatch.c", "embed/trezorhal/stm32u5/syscall_stubs.c", + "embed/trezorhal/stm32u5/system.c", + "embed/trezorhal/stm32u5/systask.c", "embed/trezorhal/stm32u5/systick.c", "embed/trezorhal/stm32u5/systimer.c", "embed/trezorhal/stm32u5/random_delays.c", From 5b0dd36aa4b781aa73a7db74712f399e359033b7 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Wed, 4 Sep 2024 11:17:11 +0200 Subject: [PATCH 38/44] refactor(core): combined build of coreapp + kernel, linker scripts refactoring [no changelog] --- Makefile | 10 +- core/Makefile | 11 +- core/SConscript.boardloader | 15 +- core/SConscript.bootloader | 14 +- core/SConscript.bootloader_ci | 15 +- core/SConscript.coreapp | 80 +++++---- core/SConscript.firmware | 24 +-- core/SConscript.kernel | 129 ++++---------- core/SConscript.prodtest | 14 +- core/SConscript.reflash | 15 +- core/embed/boardloader/main.c | 2 +- core/embed/boardloader/memory_stm32u5a.ld | 115 ------------ core/embed/boardloader/startup_stm32u5.s | 107 ----------- core/embed/bootloader/main.c | 4 +- core/embed/bootloader/memory_stm32f4.ld | 79 --------- core/embed/bootloader/memory_stm32u5a.ld | 114 ------------ core/embed/bootloader_ci/memory_stm32u58.ld | 108 ------------ core/embed/bootloader_ci/memory_stm32u5a.ld | 112 ------------ core/embed/coreapp/memory_DISC1.ld | 1 - core/embed/coreapp/memory_DISC2.ld | 130 -------------- core/embed/coreapp/memory_R.ld | 1 - core/embed/coreapp/memory_T3B1.ld | 1 - core/embed/firmware/main.c | 2 +- core/embed/firmware/memory_1.ld | 74 -------- core/embed/firmware/memory_1_min.ld | 74 -------- core/embed/firmware/memory_DISC1.ld | 1 - core/embed/firmware/memory_DISC2.ld | 130 -------------- core/embed/firmware/memory_R.ld | 1 - core/embed/firmware/memory_T3B1.ld | 1 - core/embed/kernel/header.S | 54 ------ core/embed/kernel/main.c | 26 ++- core/embed/kernel/memory_T3T1.ld | 125 ------------- core/embed/kernel/startup_stm32u5.S | 72 -------- core/embed/{firmware => lib}/bl_check.c | 16 +- core/embed/{firmware => lib}/bl_check.h | 0 core/embed/lib/image.h | 6 + core/embed/models/D001/memory.ld | 36 ++++ core/embed/models/D001/model_D001.h | 13 +- core/embed/models/D002/memory.ld | 32 ++++ core/embed/models/D002/model_D002.h | 18 +- core/embed/models/T1B1/memory.ld | 16 ++ core/embed/models/T1B1/model_T1B1.h | 1 + core/embed/models/T2B1/memory.ld | 36 ++++ core/embed/models/T2B1/model_T2B1.h | 13 +- core/embed/models/T2T1/memory.ld | 36 ++++ core/embed/models/T2T1/model_T2T1.h | 13 +- core/embed/models/T3B1/memory.ld | 32 ++++ core/embed/models/T3B1/model_T3B1.h | 17 +- core/embed/models/T3T1/memory.ld | 32 ++++ core/embed/models/T3T1/model_T3T1.h | 18 +- core/embed/prodtest/main.c | 2 +- core/embed/prodtest/memory_stm32u5a.ld | 127 -------------- core/embed/prodtest/startup_stm32f4.s | 46 ----- core/embed/prodtest/startup_stm32u5.s | 72 -------- core/embed/reflash/memory_stm32f4.ld | 81 --------- core/embed/reflash/memory_stm32u58.ld | 125 ------------- core/embed/reflash/memory_stm32u5a.ld | 128 -------------- core/embed/reflash/startup_stm32f4.s | 46 ----- core/embed/reflash/startup_stm32u5.s | 72 -------- core/embed/trezorhal/mpu.h | 5 +- .../trezorhal/stm32f4/consumption_mask.c | 10 +- core/embed/trezorhal/stm32f4/limited_util.S | 25 +-- .../stm32f4/linker/boardloader.ld} | 36 ++-- .../stm32f4/linker/bootloader.ld} | 43 +++-- .../stm32f4/linker/coreapp.ld} | 54 +++--- .../stm32f4/linker/firmware.ld} | 16 +- core/embed/trezorhal/stm32f4/linker/kernel.ld | 113 ++++++++++++ core/embed/trezorhal/stm32f4/linker/memory.ld | 6 + .../stm32f4/linker/prodtest.ld} | 45 ++--- core/embed/trezorhal/stm32f4/mpu.c | 60 +++++-- core/embed/trezorhal/stm32f4/sdram.c | 8 + core/embed/trezorhal/stm32f4/secret.c | 2 +- .../stm32f4/startup_stage_0.s} | 22 +-- .../stm32f4/startup_stage_1.s} | 12 +- .../stm32f4/startup_stage_2.s} | 12 +- .../stm32f4/startup_stage_4.s} | 0 .../trezorhal/stm32f4/syscall_dispatch.c | 12 ++ .../embed/trezorhal/stm32f4/syscall_numbers.h | 4 +- core/embed/trezorhal/stm32f4/syscall_stubs.c | 9 + core/embed/trezorhal/stm32f4/touch/stmpe811.c | 4 + core/embed/trezorhal/stm32f4/util.S | 29 +-- .../stm32f4/xdisplay/st-7789/display_fb.c | 4 +- .../stm32f4/xdisplay/st-7789/display_io.c | 4 +- .../stm32f4/xdisplay/st-7789/display_nofb.c | 4 +- .../stm32f429i-disc1/display_driver.c | 4 + .../stm32f4/xdisplay/vg-2864/display_driver.c | 22 ++- core/embed/trezorhal/stm32u5/limited_util.S | 46 ++--- .../stm32u5/linker/u58/boardloader.ld} | 62 ++++--- .../stm32u5/linker/u58/bootloader.ld} | 60 ++++--- .../stm32u5/linker/u58/coreapp.ld} | 53 ++---- .../stm32u5/linker/u58/firmware.ld} | 55 +++--- .../trezorhal/stm32u5/linker/u58/kernel.ld | 162 +++++++++++++++++ .../trezorhal/stm32u5/linker/u58/memory.ld | 18 ++ .../stm32u5/linker/u58/prodtest.ld} | 75 ++++---- .../stm32u5/linker/u5a/boardloader.ld | 127 ++++++++++++++ .../stm32u5/linker/u5a/bootloader.ld | 128 ++++++++++++++ .../trezorhal/stm32u5/linker/u5a/coreapp.ld | 92 ++++++++++ .../trezorhal/stm32u5/linker/u5a/kernel.ld | 166 ++++++++++++++++++ .../trezorhal/stm32u5/linker/u5a/memory.ld | 18 ++ .../trezorhal/stm32u5/linker/u5a/prodtest.ld | 136 ++++++++++++++ core/embed/trezorhal/stm32u5/mpu.c | 80 +++++++-- .../embed/trezorhal/stm32u5/startup_stage_0.s | 79 +++++++++ .../stm32u5/startup_stage_1.s} | 27 +-- .../stm32u5/startup_stage_2.s} | 27 +-- .../stm32u5/startup_stage_4.s} | 0 core/embed/trezorhal/stm32u5/touch/sitronix.c | 4 + core/embed/trezorhal/stm32u5/util.S | 49 ++---- .../xdisplay/stm32u5a9j-dk/display_driver.c | 19 ++ .../xdisplay/stm32u5a9j-dk/display_fb.c | 4 + .../stm32u5a9j-dk/display_gfxmmu_lut.h | 2 +- .../xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c | 8 + core/site_scons/models/D002/discovery2.py | 2 +- .../models/T3B1/trezor_t3b1_revB.py | 2 +- .../models/T3T1/trezor_t3t1_revE.py | 2 +- core/site_scons/models/T3T1/trezor_t3t1_v4.py | 2 +- core/site_scons/models/stm32f4_common.py | 2 +- core/site_scons/tools.py | 15 +- core/tools/README.md | 5 +- core/tools/pyproject.toml | 3 +- core/tools/trezor_core_tools/common.py | 4 + core/tools/trezor_core_tools/layout_parser.py | 5 + core/tools/trezor_core_tools/lsgen.py | 37 ++++ poetry.lock | 2 +- 123 files changed, 2168 insertions(+), 2670 deletions(-) delete mode 100644 core/embed/boardloader/memory_stm32u5a.ld delete mode 100644 core/embed/boardloader/startup_stm32u5.s delete mode 100644 core/embed/bootloader/memory_stm32f4.ld delete mode 100644 core/embed/bootloader/memory_stm32u5a.ld delete mode 100644 core/embed/bootloader_ci/memory_stm32u58.ld delete mode 100644 core/embed/bootloader_ci/memory_stm32u5a.ld delete mode 120000 core/embed/coreapp/memory_DISC1.ld delete mode 100644 core/embed/coreapp/memory_DISC2.ld delete mode 120000 core/embed/coreapp/memory_R.ld delete mode 120000 core/embed/coreapp/memory_T3B1.ld delete mode 100644 core/embed/firmware/memory_1.ld delete mode 100644 core/embed/firmware/memory_1_min.ld delete mode 120000 core/embed/firmware/memory_DISC1.ld delete mode 100644 core/embed/firmware/memory_DISC2.ld delete mode 120000 core/embed/firmware/memory_R.ld delete mode 120000 core/embed/firmware/memory_T3B1.ld delete mode 100644 core/embed/kernel/header.S delete mode 100644 core/embed/kernel/memory_T3T1.ld delete mode 100644 core/embed/kernel/startup_stm32u5.S rename core/embed/{firmware => lib}/bl_check.c (93%) rename core/embed/{firmware => lib}/bl_check.h (100%) create mode 100644 core/embed/models/D001/memory.ld create mode 100644 core/embed/models/D002/memory.ld create mode 100644 core/embed/models/T1B1/memory.ld create mode 100644 core/embed/models/T2B1/memory.ld create mode 100644 core/embed/models/T2T1/memory.ld create mode 100644 core/embed/models/T3B1/memory.ld create mode 100644 core/embed/models/T3T1/memory.ld delete mode 100644 core/embed/prodtest/memory_stm32u5a.ld delete mode 100644 core/embed/prodtest/startup_stm32f4.s delete mode 100644 core/embed/prodtest/startup_stm32u5.s delete mode 100644 core/embed/reflash/memory_stm32f4.ld delete mode 100644 core/embed/reflash/memory_stm32u58.ld delete mode 100644 core/embed/reflash/memory_stm32u5a.ld delete mode 100644 core/embed/reflash/startup_stm32f4.s delete mode 100644 core/embed/reflash/startup_stm32u5.s rename core/embed/{boardloader/memory_stm32f4.ld => trezorhal/stm32f4/linker/boardloader.ld} (50%) rename core/embed/{bootloader_ci/memory_stm32f4.ld => trezorhal/stm32f4/linker/bootloader.ld} (52%) rename core/embed/{firmware/memory_T.ld => trezorhal/stm32f4/linker/coreapp.ld} (55%) rename core/embed/{coreapp/memory_T.ld => trezorhal/stm32f4/linker/firmware.ld} (82%) create mode 100644 core/embed/trezorhal/stm32f4/linker/kernel.ld create mode 100644 core/embed/trezorhal/stm32f4/linker/memory.ld rename core/embed/{prodtest/memory_stm32f4.ld => trezorhal/stm32f4/linker/prodtest.ld} (53%) rename core/embed/{boardloader/startup_stm32f4.s => trezorhal/stm32f4/startup_stage_0.s} (63%) rename core/embed/{bootloader/startup_stm32f4.s => trezorhal/stm32f4/startup_stage_1.s} (73%) rename core/embed/{bootloader_ci/startup_stm32f4.s => trezorhal/stm32f4/startup_stage_2.s} (69%) rename core/embed/{coreapp/startup_stm32f4.S => trezorhal/stm32f4/startup_stage_4.s} (100%) rename core/embed/{boardloader/memory_stm32u58.ld => trezorhal/stm32u5/linker/u58/boardloader.ld} (51%) rename core/embed/{bootloader/memory_stm32u58.ld => trezorhal/stm32u5/linker/u58/bootloader.ld} (52%) rename core/embed/{coreapp/memory_T3T1.ld => trezorhal/stm32u5/linker/u58/coreapp.ld} (54%) rename core/embed/{firmware/memory_T3T1.ld => trezorhal/stm32u5/linker/u58/firmware.ld} (60%) create mode 100644 core/embed/trezorhal/stm32u5/linker/u58/kernel.ld create mode 100644 core/embed/trezorhal/stm32u5/linker/u58/memory.ld rename core/embed/{prodtest/memory_stm32u58.ld => trezorhal/stm32u5/linker/u58/prodtest.ld} (52%) create mode 100644 core/embed/trezorhal/stm32u5/linker/u5a/boardloader.ld create mode 100644 core/embed/trezorhal/stm32u5/linker/u5a/bootloader.ld create mode 100644 core/embed/trezorhal/stm32u5/linker/u5a/coreapp.ld create mode 100644 core/embed/trezorhal/stm32u5/linker/u5a/kernel.ld create mode 100644 core/embed/trezorhal/stm32u5/linker/u5a/memory.ld create mode 100644 core/embed/trezorhal/stm32u5/linker/u5a/prodtest.ld create mode 100644 core/embed/trezorhal/stm32u5/startup_stage_0.s rename core/embed/{bootloader/startup_stm32u5.s => trezorhal/stm32u5/startup_stage_1.s} (64%) rename core/embed/{bootloader_ci/startup_stm32u5.s => trezorhal/stm32u5/startup_stage_2.s} (61%) rename core/embed/{coreapp/startup_stm32u5.S => trezorhal/stm32u5/startup_stage_4.s} (100%) create mode 100644 core/tools/trezor_core_tools/lsgen.py diff --git a/Makefile b/Makefile index 1daba0dad5b..693d62e4b62 100644 --- a/Makefile +++ b/Makefile @@ -154,6 +154,12 @@ bootloader_hashes: ## generate bootloader hashes bootloader_hashes_check: ## check generated bootloader hashes ./core/tools/bootloader_hashes.py --check -gen: templates mocks icons protobuf ci_docs vendorheader solana_templates bootloader_hashes ## regenerate auto-generated files from sources +lsgen: ## generate linker scripts hashes + lsgen -gen_check: templates_check mocks_check icons_check protobuf_check ci_docs_check vendorheader_check solana_templates_check bootloader_hashes_check ## check validity of auto-generated files +lsgen_check: ## check generated linker scripts + lsgen --check + +gen: templates mocks icons protobuf ci_docs vendorheader solana_templates bootloader_hashes lsgen ## regenerate auto-generated files from sources + +gen_check: templates_check mocks_check icons_check protobuf_check ci_docs_check vendorheader_check solana_templates_check bootloader_hashes_check lsgen_check ## check validity of auto-generated files diff --git a/core/Makefile b/core/Makefile index 4f5703e2b60..31e28b6def9 100644 --- a/core/Makefile +++ b/core/Makefile @@ -277,11 +277,11 @@ build_reflash: ## build reflash firmware + reflash image build_kernel: ## build kernel image $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ - TREZOR_MODEL="$(TREZOR_MODEL)" \ + TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ $(KERNEL_BUILD_DIR)/kernel.bin -build_coreapp: templates build_cross ## build coreapp with frozen modules +build_coreapp: templates build_cross build_kernel ## build coreapp with frozen modules $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \ @@ -372,15 +372,12 @@ flash_bootloader_ci: $(BOOTLOADER_CI_BUILD_DIR)/bootloader.bin ## flash CI bootl flash_prodtest: $(PRODTEST_BUILD_DIR)/prodtest.bin ## flash prodtest using OpenOCD $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_START); exit" -flash_kernel: $(KERNEL_BUILD_DIR)/kernel.bin ## flash kernel using OpenOCD - $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(KERNEL_START); exit" - flash_coreapp: $(COREAPP_BUILD_DIR)/coreapp.bin ## flash coreapp using OpenOCD ifeq ($(MCU),$(filter $(MCU),STM32F4)) - $(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(COREAPP_START); flash write_image erase $<.p2 $(COREAPP_P2_START); exit" + $(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(FIRMWARE_START); flash write_image erase $<.p2 $(FIRMWARE_P2_START); exit" else - $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(COREAPP_START); exit" + $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_START); exit" endif flash_firmware: $(FIRMWARE_BUILD_DIR)/firmware.bin ## flash firmware using OpenOCD diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader index af532a192ca..8afc63e7d46 100644 --- a/core/SConscript.boardloader +++ b/core/SConscript.boardloader @@ -7,6 +7,7 @@ TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) HW_REVISION = ARGUMENTS.get('HW_REVISION', None) NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' +MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) if TREZOR_MODEL in ('1', ): # skip boardloader build @@ -103,15 +104,15 @@ 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'] -LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT'] SOURCE_BOARDLOADER = [ - f"embed/boardloader/startup_{FILE_SUFFIX}.s", + f"embed/trezorhal/{FILE_SUFFIX}/startup_stage_0.s", 'embed/boardloader/main.c', ] env.Replace( + CAT='cat', CP='cp', AS='arm-none-eabi-as', AR='arm-none-eabi-ar', @@ -137,7 +138,7 @@ env.Replace( '-fstack-protector-strong ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS=f"-T embed/boardloader/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/boardloader/boardloader.map -Wl,--warn-common -Wl,--print-memory-usage", + LINKFLAGS="-T build/boardloader/memory.ld -Wl,--gc-sections -Wl,-Map=build/boardloader/boardloader.map -Wl,--warn-common -Wl,--print-memory-usage", CPPPATH=[ 'embed/boardloader', 'embed/lib', @@ -175,6 +176,12 @@ obj_program += env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial- obj_program += env.Object(source=SOURCE_BOARDLOADER) obj_program += env.Object(source=SOURCE_HAL) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='boardloader')], + action='$CAT $SOURCES > $TARGET', +) + program_elf = env.Command( target='boardloader.elf', source=obj_program, @@ -182,6 +189,8 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES -lc_nano -lgcc', ) +env.Depends(program_elf, linkerscript_gen) + BINARY_NAME = f"build/boardloader/boardloader-{models.get_model_identifier(TREZOR_MODEL)}" BINARY_NAME += "-" + tools.get_version('embed/boardloader/version.h') BINARY_NAME += "-" + tools.get_git_revision_short_hash() diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index b8f039bbe75..b0a52822eca 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -9,6 +9,7 @@ BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1' PRODUCTION = 0 if BOOTLOADER_QA else ARGUMENTS.get('PRODUCTION', '0') == '1' HW_REVISION = ARGUMENTS.get('HW_REVISION', None) NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' or TREZOR_MODEL in ('T3T1',) +MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) if TREZOR_MODEL in ('1', ): # skip bootloader build @@ -162,10 +163,9 @@ 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'] -LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT'] SOURCE_BOOTLOADER = [ - f'embed/bootloader/startup_{FILE_SUFFIX}.s', + f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_1.s', 'embed/bootloader/header.S', 'embed/bootloader/bootui.c', 'embed/bootloader/main.c', @@ -176,6 +176,7 @@ SOURCE_BOOTLOADER = [ env.Replace( + CAT='cat', CP='cp', AS='arm-none-eabi-as', AR='arm-none-eabi-ar', @@ -213,7 +214,7 @@ env.Replace( '-fstack-protector-strong ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS=f'-T embed/bootloader/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/bootloader/bootloader.map -Wl,--warn-common -Wl,--print-memory-usage', + LINKFLAGS='-T build/bootloader/memory.ld -Wl,--gc-sections -Wl,-Map=build/bootloader/bootloader.map -Wl,--warn-common -Wl,--print-memory-usage', CPPPATH=ALLPATHS, CPPDEFINES=[ 'BOOTLOADER', @@ -310,6 +311,12 @@ obj_program += env.Object(source=SOURCE_NANOPB) obj_program += env.Object(source=SOURCE_HAL) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='bootloader')], + action='$CAT $SOURCES > $TARGET', +) + program_elf = env.Command( target='bootloader.elf', source=obj_program, @@ -317,6 +324,7 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', ) +env.Depends(program_elf, linkerscript_gen) env.Depends(program_elf, rust) SUFFIX = '_qa' if BOOTLOADER_QA else '' diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci index 841f48b1df4..1963c53600d 100644 --- a/core/SConscript.bootloader_ci +++ b/core/SConscript.bootloader_ci @@ -7,6 +7,7 @@ TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) HW_REVISION = ARGUMENTS.get('HW_REVISION', None) NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' or TREZOR_MODEL in ('T3T1',) +MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) if TREZOR_MODEL in ('1', 'DISC1', 'DISC2'): # skip bootloader_ci build @@ -154,10 +155,9 @@ 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'] -LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT'] SOURCE_BOOTLOADER = [ - f'embed/bootloader_ci/startup_{FILE_SUFFIX}.s', + f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_1.s', 'embed/bootloader_ci/header.S', 'embed/bootloader_ci/bootui.c', 'embed/bootloader_ci/main.c', @@ -167,6 +167,7 @@ SOURCE_BOOTLOADER = [ ] env.Replace( + CAT='cat', CP='cp', AS='arm-none-eabi-as', AR='arm-none-eabi-ar', @@ -192,7 +193,7 @@ env.Replace( '-fstack-protector-strong ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS=f'-T embed/bootloader_ci/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/bootloader_ci/bootloader.map -Wl,--warn-common', + LINKFLAGS=f'-T build/bootloader_ci/memory.ld -Wl,--gc-sections -Wl,-Map=build/bootloader_ci/bootloader.map -Wl,--warn-common', CPPPATH=[ 'embed/bootloader_ci', 'embed/bootloader_ci/nanopb', @@ -241,6 +242,12 @@ obj_program += env.Object(source=SOURCE_BOOTLOADER) obj_program += env.Object(source=SOURCE_NANOPB) obj_program += env.Object(source=SOURCE_HAL) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='bootloader')], + action='$CAT $SOURCES > $TARGET', +) + program_elf = env.Command( target='bootloader.elf', source=obj_program, @@ -248,6 +255,8 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES -lc_nano -lgcc', ) +env.Depends(program_elf, linkerscript_gen) + BINARY_NAME = f"build/bootloader_ci/bootloader_ci-{models.get_model_identifier(TREZOR_MODEL)}" BINARY_NAME += "-" + tools.get_version('embed/bootloader_ci/version.h') BINARY_NAME += "-" + tools.get_git_revision_short_hash() diff --git a/core/SConscript.coreapp b/core/SConscript.coreapp index a65908aac0b..e2587fdaeb8 100644 --- a/core/SConscript.coreapp +++ b/core/SConscript.coreapp @@ -16,7 +16,7 @@ DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1' HW_REVISION = ARGUMENTS.get('HW_REVISION', None) THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' or TREZOR_MODEL in ('T3T1',) - +MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) FEATURE_FLAGS = { "RDI": True, @@ -439,7 +439,7 @@ SOURCE_FIRMWARE = [ 'embed/coreapp/main.c', 'embed/coreapp/mphalport.c', 'embed/coreapp/nlrthumb.c', - f'embed/coreapp/startup_{FILE_SUFFIX}.S', + f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_4.S', ] @@ -478,11 +478,6 @@ env.Replace( env.Replace( TREZOR_MODEL=TREZOR_MODEL,) -if TREZOR_MODEL in ('1',): - LD_VARIANT = '' if EVERYTHING else '_min' -else: - LD_VARIANT = '' - ALLPATHS = [ '.', 'embed/rust', @@ -505,7 +500,7 @@ env.Replace( '-fstack-protector-all ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS='-T embed/coreapp/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/coreapp/coreapp.map -Wl,--warn-common' % LD_VARIANT, + LINKFLAGS='-T build/coreapp/memory.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/coreapp/coreapp.map -Wl,--warn-common', CPPPATH=ALLPATHS, CPPDEFINES=[ 'FIRMWARE', @@ -879,17 +874,33 @@ else: VENDORHEADER = f'embed/models/{MODEL_IDENTIFIER}/vendorheader/vendorheader_{vendor}.bin' -if TREZOR_MODEL not in ('1',): - obj_program.extend( - env.Command( - target='embed/coreapp/vendorheader.o', - source=VENDORHEADER, - action='$OBJCOPY -I binary -O elf32-littlearm -B arm' - ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' - ' $SOURCE $TARGET', )) +obj_program.extend( + env.Command( + target='embed/coreapp/vendorheader.o', + source=VENDORHEADER, + action='$OBJCOPY -I binary -O elf32-littlearm -B arm' + ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' + ' $SOURCE $TARGET', )) + + +tools.embed_raw_binary( + obj_program, + env, + 'kernel', + 'build/kernel/kernel.o', + f'build/kernel/kernel.bin', + ) + + env.Depends(obj_program, qstr_generated) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='coreapp')], + action='$CAT $SOURCES > $TARGET', +) + program_elf = env.Command( target='coreapp.elf', source=obj_program, @@ -897,11 +908,13 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', ) +env.Depends(program_elf, linkerscript_gen) + if CMAKELISTS != 0: env.Depends(program_elf, cmake_gen) env.Depends(program_elf, rust) -BINARY_NAME = f"build/coreapp/coreapp-{models.get_model_identifier(TREZOR_MODEL)}" +BINARY_NAME = f"build/coreapp/coreapp-{MODEL_IDENTIFIER}" if not EVERYTHING: BINARY_NAME += "-btconly" BINARY_NAME += "-" + tools.get_version('embed/coreapp/version.h') @@ -910,30 +923,23 @@ BINARY_NAME += "-dirty" if tools.get_git_modified() else "" BINARY_NAME += ".bin" -if TREZOR_MODEL in ('1'): +if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: action_bin=[ - '$OBJCOPY -O binary -j .header -j .flash -j .data -j .confidential $SOURCE $TARGET', - '../legacy/bootloader/firmware_sign.py -f $TARGET', + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', + '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', + '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', '$CP $TARGET ' + BINARY_NAME, ] -else: - if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', - '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', - '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', - '$CP $TARGET ' + BINARY_NAME, +elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$CP $TARGET ' + BINARY_NAME, ] - elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$CP $TARGET ' + BINARY_NAME, - ] - else: - raise Exception("Unknown MCU") +else: + raise Exception("Unknown MCU") program_bin = env.Command( target='coreapp.bin', diff --git a/core/SConscript.firmware b/core/SConscript.firmware index c201d098b7d..16dc21e2a89 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -221,6 +221,7 @@ CPPPATH_MOD += [ ] SOURCE_MOD += [ 'embed/extmod/modtrezorui/modtrezorui.c', + 'embed/lib/bl_check.c', 'embed/lib/buffers.c', 'embed/lib/colors.c', 'embed/lib/display_utils.c', @@ -450,13 +451,12 @@ FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_ FILE_SUFFIX= env.get('ENV')['SUFFIX'] SOURCE_FIRMWARE = [ - 'embed/firmware/bl_check.c', 'embed/firmware/delay.c', 'embed/firmware/header.S', 'embed/firmware/main.c', 'embed/firmware/mphalport.c', 'embed/firmware/nlrthumb.c', - f'embed/firmware/startup_{FILE_SUFFIX}.S', + f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_4.s', ] @@ -495,11 +495,6 @@ env.Replace( env.Replace( TREZOR_MODEL=TREZOR_MODEL,) -if TREZOR_MODEL in ('1',): - LD_VARIANT = '' if EVERYTHING else '_min' -else: - LD_VARIANT = '' - ALLPATHS = [ '.', 'embed/rust', @@ -522,7 +517,7 @@ env.Replace( '-fstack-protector-all ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS='-T embed/firmware/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/firmware/firmware.map -Wl,--warn-common' % LD_VARIANT, + LINKFLAGS='-T build/firmware/memory.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/firmware/firmware.map -Wl,--warn-common', CPPPATH=ALLPATHS, CPPDEFINES=[ 'FIRMWARE', @@ -906,17 +901,24 @@ if TREZOR_MODEL not in ('1',): ' $SOURCE $TARGET', )) if TREZOR_MODEL not in ('DISC1', 'DISC2'): - tools.embed_binary( + tools.embed_compressed_binary( obj_program, env, 'bootloader', - 'embed/firmware/bootloaders/bootloader.o', + 'embed/bootloaders/bootloader.o', f'embed/models/{MODEL_IDENTIFIER}/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin', + 'firmware' ) env.Depends(obj_program, qstr_generated) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='firmware')], + action='$CAT $SOURCES > $TARGET', +) + program_elf = env.Command( target='firmware.elf', source=obj_program, @@ -924,6 +926,8 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', ) +env.Depends(program_elf, linkerscript_gen) + if CMAKELISTS != 0: env.Depends(program_elf, cmake_gen) env.Depends(program_elf, rust) diff --git a/core/SConscript.kernel b/core/SConscript.kernel index 3b15bac4db2..aff585b0b15 100644 --- a/core/SConscript.kernel +++ b/core/SConscript.kernel @@ -42,38 +42,11 @@ PATH_HAL = [] FROZEN = True -if TREZOR_MODEL in ('1', 'R'): - FONT_NORMAL='Font_PixelOperator_Regular_8' - FONT_DEMIBOLD='Font_Unifont_Bold_16' - FONT_BOLD='Font_PixelOperator_Bold_8' - FONT_MONO='Font_PixelOperatorMono_Regular_8' - FONT_BIG='Font_Unifont_Regular_16' - FONT_NORMAL_UPPER='Font_PixelOperator_Regular_8_upper' - FONT_BOLD_UPPER='Font_PixelOperator_Bold_8_upper' - FONT_SUB=None -elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): - FONT_NORMAL='Font_TTHoves_Regular_21' - FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' - FONT_BOLD=None - FONT_MONO='Font_RobotoMono_Medium_20' - FONT_BIG=None - FONT_NORMAL_UPPER=None - FONT_BOLD_UPPER='Font_TTHoves_Bold_17_upper' - FONT_SUB=None -elif TREZOR_MODEL in ('T3T1',): - FONT_NORMAL='Font_TTSatoshi_DemiBold_21' - FONT_DEMIBOLD='Font_TTSatoshi_DemiBold_21' - FONT_BOLD='Font_TTSatoshi_DemiBold_21' - FONT_MONO='Font_RobotoMono_Medium_21' - FONT_BIG='Font_TTSatoshi_DemiBold_42' - FONT_NORMAL_UPPER=None - FONT_BOLD_UPPER=None - FONT_SUB='Font_TTSatoshi_DemiBold_18' - # modtrezorconfig CPPPATH_MOD += [ 'embed/extmod/modtrezorconfig', 'vendor/trezor-storage', + 'vendor/micropython/lib/uzlib', ] SOURCE_MOD += [ # 'embed/extmod/modtrezorconfig/modtrezorconfig.c', @@ -210,6 +183,7 @@ if FEATURE_FLAGS["AES_GCM"]: ] SOURCE_MOD += [ + 'embed/lib/bl_check.c', # 'embed/lib/buffers.c', # 'embed/lib/colors.c', # 'embed/lib/display_utils.c', @@ -227,6 +201,9 @@ SOURCE_MOD += [ 'embed/lib/translations.c', 'embed/lib/unit_variant.c', 'embed/extmod/modtrezorcrypto/rand.c', + 'vendor/micropython/lib/uzlib/adler32.c', + 'vendor/micropython/lib/uzlib/crc32.c', + 'vendor/micropython/lib/uzlib/tinflate.c', ] if NEW_RENDERING: @@ -241,7 +218,6 @@ else: CPPDEFINES_MOD += [ - 'TREZOR_UI2', 'TRANSLATIONS', ] @@ -282,15 +258,6 @@ if THP: 'vendor/trezor-crypto/elligator2.c', ] -# fonts -tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('DEMIBOLD', FONT_DEMIBOLD, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('MONO', FONT_MONO, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('BIG', FONT_BIG, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('NORMAL_UPPER', FONT_NORMAL_UPPER, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('BOLD_UPPER', FONT_BOLD_UPPER, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('SUB', FONT_SUB, CPPDEFINES_MOD, SOURCE_MOD) env = Environment( ENV=os.environ, @@ -303,24 +270,10 @@ FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_ FILE_SUFFIX= env.get('ENV')['SUFFIX'] SOURCE_FIRMWARE = [ - 'embed/kernel/header.S', 'embed/kernel/main.c', - f'embed/kernel/startup_{FILE_SUFFIX}.S', + f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_2.s', ] - -if TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): - UI_LAYOUT = 'UI_LAYOUT_TT' - ui_layout_feature = 'model_tt' -elif TREZOR_MODEL in ('1', 'R'): - UI_LAYOUT = 'UI_LAYOUT_TR' - ui_layout_feature = 'model_tr' -elif TREZOR_MODEL in ('T3T1',): - UI_LAYOUT = 'UI_LAYOUT_MERCURY' - ui_layout_feature = 'model_mercury' -else: - raise ValueError('Unknown Trezor model') - if 'sd_card' in FEATURES_AVAILABLE: SDCARD = True else: @@ -342,11 +295,6 @@ env.Replace( env.Replace( TREZOR_MODEL=TREZOR_MODEL,) -if TREZOR_MODEL in ('1',): - LD_VARIANT = '' if EVERYTHING else '_min' -else: - LD_VARIANT = '' - ALLPATHS = [ '.', 'embed/firmware', @@ -365,14 +313,13 @@ env.Replace( '-ffreestanding ' '-fstack-protector-all ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, - LINKFLAGS='-T embed/kernel/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/kernel/kernel.map -Wl,--warn-common' % LD_VARIANT, + LINKFLAGS='-T build/kernel/memory.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/kernel/kernel.map -Wl,--warn-common', CPPPATH=ALLPATHS, CPPDEFINES=[ 'KERNEL', 'TREZOR_MODEL_'+TREZOR_MODEL, 'USE_HAL_DRIVER', 'ARM_USER_MODE', - UI_LAYOUT, ] + CPPDEFINES_MOD + CPPDEFINES_HAL, ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], ASPPFLAGS='$CFLAGS $CCFLAGS', @@ -381,8 +328,6 @@ env.Replace( env.Replace( HEADERTOOL='headertool', PYTHON='python', - MAKEVERSIONHDR='$PYTHON vendor/micropython/py/makeversionhdr.py', - MAKEMODULEDEFS='$PYTHON vendor/micropython/py/makemoduledefs.py', MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', ) @@ -433,24 +378,29 @@ else: VENDORHEADER = f'embed/models/{MODEL_IDENTIFIER}/vendorheader/vendorheader_{vendor}.bin' -if TREZOR_MODEL not in ('1',): - obj_program.extend( - env.Command( - target='embed/kernel/vendorheader.o', - source=VENDORHEADER, - action='$OBJCOPY -I binary -O elf32-littlearm -B arm' - ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' - ' $SOURCE $TARGET', )) +obj_program.extend( + env.Command( + target='embed/kernel/vendorheader.o', + source=VENDORHEADER, + action='$OBJCOPY -I binary -O elf32-littlearm -B arm' + ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' + ' $SOURCE $TARGET', )) -if False: # TREZOR_MODEL not in ('DISC1', 'DISC2'): - tools.embed_binary( +if TREZOR_MODEL not in ('DISC1', 'DISC2'): + tools.embed_compressed_binary( obj_program, env, 'bootloader', - 'embed/firmware/bootloaders/bootloader.o', - f'embed/firmware/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin', + 'embed/bootloaders/bootloader.o', + f'embed/models/{MODEL_IDENTIFIER}/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin', + 'kernel' ) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='kernel')], + action='$CAT $SOURCES > $TARGET', +) program_elf = env.Command( target='kernel.elf', @@ -459,6 +409,8 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', ) +env.Depends(program_elf, linkerscript_gen) + if CMAKELISTS != 0: env.Depends(program_elf, cmake_gen) @@ -470,31 +422,10 @@ BINARY_NAME += "-" + tools.get_git_revision_short_hash() BINARY_NAME += "-dirty" if tools.get_git_modified() else "" BINARY_NAME += ".bin" - -if TREZOR_MODEL in ('1'): - action_bin=[ - '$OBJCOPY -O binary -j .header -j .flash -j .data -j .confidential $SOURCE $TARGET', - '../legacy/bootloader/firmware_sign.py -f $TARGET', - '$CP $TARGET ' + BINARY_NAME, - ] -else: - if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', - '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', - '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', - '$CP $TARGET ' + BINARY_NAME, - ] - elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$CP $TARGET ' + BINARY_NAME, - ] - else: - raise Exception("Unknown MCU") +action_bin=[ + '$OBJCOPY -O binary -j .flash -j .uflash -j .data -j .confidential $SOURCE ${TARGET}', + '$CP $TARGET ' + BINARY_NAME, +] program_bin = env.Command( target='kernel.bin', diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index 2302c2658dd..de09bae4b3a 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -153,11 +153,10 @@ 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'] -LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT'] SOURCE_PRODTEST = [ - f'embed/prodtest/startup_{FILE_SUFFIX}.s', + f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_2.s', 'embed/prodtest/header.S', 'embed/prodtest/main.c', 'embed/prodtest/prodtest_common.c', @@ -169,6 +168,7 @@ if 'optiga' in FEATURES_AVAILABLE: ] env.Replace( + CAT='cat', CP='cp', AS='arm-none-eabi-as', AR='arm-none-eabi-ar', @@ -194,7 +194,7 @@ env.Replace( '-fstack-protector-all ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS=f'-T embed/prodtest/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/prodtest/prodtest.map -Wl,--warn-common', + LINKFLAGS=f'-T build/prodtest/memory.ld -Wl,--gc-sections -Wl,-Map=build/prodtest/prodtest.map -Wl,--warn-common', CPPPATH=[ 'embed/prodtest', 'embed/lib', @@ -266,6 +266,12 @@ obj_program.extend( ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' ' $SOURCE $TARGET', )) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='prodtest')], + action='$CAT $SOURCES > $TARGET', +) + program_elf = env.Command( target='prodtest.elf', source=obj_program, @@ -273,6 +279,8 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES -lc_nano -lgcc', ) +env.Depends(program_elf, linkerscript_gen) + BINARY_NAME = f"build/prodtest/prodtest-{models.get_model_identifier(TREZOR_MODEL)}" BINARY_NAME += "-" + tools.get_version('embed/prodtest/version.h') BINARY_NAME += "-" + tools.get_git_revision_short_hash() diff --git a/core/SConscript.reflash b/core/SConscript.reflash index dc6dfc18c53..0a1b3e1ce70 100644 --- a/core/SConscript.reflash +++ b/core/SConscript.reflash @@ -122,22 +122,21 @@ tools.add_font('SUB', FONT_SUB, CPPDEFINES_MOD, SOURCE_MOD) env = Environment( ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0')), - CONSTRAINTS=["limited_util_s"], CPPDEFINES_IMPLICIT=[] ) FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) FILE_SUFFIX= env.get('ENV')['SUFFIX'] -LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT'] SOURCE_REFLASH = [ - f'embed/reflash/startup_{FILE_SUFFIX}.s', + f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_2.s', 'embed/reflash/header.S', 'embed/reflash/main.c', ] env.Replace( + CAT='cat', CP='cp', AS='arm-none-eabi-as', AR='arm-none-eabi-ar', @@ -163,7 +162,7 @@ env.Replace( '-fstack-protector-all ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS=f'-T embed/reflash/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/reflash/reflash.map -Wl,--warn-common', + LINKFLAGS=f'-T build/reflash/memory.ld -Wl,--gc-sections -Wl,-Map=build/reflash/reflash.map -Wl,--warn-common', CPPPATH=[ 'embed/reflash', 'embed/lib', @@ -215,6 +214,12 @@ obj_program.extend( ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' ' $SOURCE $TARGET', )) +linkerscript_gen = env.Command( + target='memory.ld', + source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='prodtest')], + action='$CAT $SOURCES > $TARGET', +) + program_elf = env.Command( target='reflash.elf', source=obj_program, @@ -222,6 +227,8 @@ program_elf = env.Command( '$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES -lc_nano -lgcc', ) +env.Depends(program_elf, linkerscript_gen) + BINARY_NAME = f"build/reflash/reflash-{models.get_model_identifier(TREZOR_MODEL)}" BINARY_NAME += "-" + tools.get_version('embed/reflash/version.h') BINARY_NAME += "-" + tools.get_git_revision_short_hash() diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index 17eb8d4b716..a5cb8c15954 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -324,7 +324,7 @@ int main(void) { // This includes the version of bootloader potentially updated from SD card. write_bootloader_min_version(hdr->monotonic); - display_deinit(DISPLAY_RETAIN_CONTENT); + display_deinit(DISPLAY_JUMP_BEHAVIOR); #ifdef ENSURE_COMPATIBLE_SETTINGS ensure_compatible_settings(); diff --git a/core/embed/boardloader/memory_stm32u5a.ld b/core/embed/boardloader/memory_stm32u5a.ld deleted file mode 100644 index f91099d0068..00000000000 --- a/core/embed/boardloader/memory_stm32u5a.ld +++ /dev/null @@ -1,115 +0,0 @@ -/* Trezor v2 boardloader linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C004000, LENGTH = 48K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K - SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K - SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0K /* 512K on U5G */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -SECTIONS { - .vector_table : ALIGN(1024) { - KEEP(*(.vector_table)); - } >FLASH AT>FLASH - - .text : ALIGN(4) { - *(.text*); - . = ALIGN(4); /* make the section size a multiple of the word size */ - } >FLASH AT>FLASH - - .rodata : ALIGN(4) { - *(.rodata*); - . = ALIGN(4); /* make the section size a multiple of the word size */ - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(8); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(8) { - *(.confidential*); - . = ALIGN(4); - } >SRAM2 AT>FLASH - - .fb1 : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.gfxmmu_table*); - *(.framebuffer_select*); - . = ALIGN(4); - } >SRAM3 - - .fb2 : ALIGN(4) { - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM5 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS - - - /* Hard-coded address for capabilities structure */ - .capabilities 0x0C00FF00 : {KEEP(*(.capabilities_section))} -} diff --git a/core/embed/boardloader/startup_stm32u5.s b/core/embed/boardloader/startup_stm32u5.s deleted file mode 100644 index 3665db2de58..00000000000 --- a/core/embed/boardloader/startup_stm32u5.s +++ /dev/null @@ -1,107 +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: - ldr r0, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - mov r2, r4 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - mov r2, r4 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =sram3_end // r1 - point to byte after the end of SRAM - mov r2, r4 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - mov r2, r4 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram5_start // r0 - point to beginning of SRAM - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM - mov r2, r4 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - mov r2, r4 // r2 - the word-sized value to be written - 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, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =sram3_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram5_start // r0 - point to beginning of SRAM - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - 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/bootloader/main.c b/core/embed/bootloader/main.c index c417d8312dc..73c05962bbc 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -331,7 +331,7 @@ void real_jump_to_firmware(void) { ui_screen_boot_stage_1(false); } - display_deinit(DISPLAY_RETAIN_CONTENT); + display_deinit(DISPLAY_JUMP_BEHAVIOR); #ifdef ENSURE_COMPATIBLE_SETTINGS ensure_compatible_settings(); @@ -369,7 +369,7 @@ int bootloader_main(void) { hash_processor_init(); #endif - display_init(DISPLAY_RETAIN_CONTENT); + display_init(DISPLAY_JUMP_BEHAVIOR); #ifdef USE_DMA2D dma2d_init(); diff --git a/core/embed/bootloader/memory_stm32f4.ld b/core/embed/bootloader/memory_stm32f4.ld deleted file mode 100644 index 392c9a1d8e2..00000000000 --- a/core/embed/bootloader/memory_stm32f4.ld +++ /dev/null @@ -1,79 +0,0 @@ -/* Trezor v2 bootloader linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 128K - CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x1000FF00, LENGTH = 0x100 - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K -} - -main_stack_base = ORIGIN(CCMRAM) + SIZEOF(.stack) ; /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(CCMRAM); -_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); - -/* used by the startup code to wipe memory */ -ccmram_start = ORIGIN(CCMRAM); -ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); - -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data); - -SECTIONS { - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(512) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .stack : ALIGN(8) { - . = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */ - } >CCMRAM - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >CCMRAM AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >CCMRAM - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - *(.no_dma_buffers*); - . = ALIGN(4); - } >SRAM - - .boot_args : ALIGN(8) { - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS - -} diff --git a/core/embed/bootloader/memory_stm32u5a.ld b/core/embed/bootloader/memory_stm32u5a.ld deleted file mode 100644 index e34a7d53e19..00000000000 --- a/core/embed/bootloader/memory_stm32u5a.ld +++ /dev/null @@ -1,114 +0,0 @@ -/* Trezor v2 bootloader linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K - SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K - SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); - -SECTIONS { - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(1024) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - *(.no_dma_buffers*); - . = ALIGN(4); - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb1 : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.gfxmmu_table*); - *(.framebuffer_select*); - . = ALIGN(4); - } >SRAM3 - - .fb2 : ALIGN(4) { - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM5 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/bootloader_ci/memory_stm32u58.ld b/core/embed/bootloader_ci/memory_stm32u58.ld deleted file mode 100644 index 69f2570187b..00000000000 --- a/core/embed/bootloader_ci/memory_stm32u58.ld +++ /dev/null @@ -1,108 +0,0 @@ -/* Trezor v2 bootloader linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 512K - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); - -SECTIONS { - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(512) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K; /* Exactly 16K allocated for stack. Overflow causes Usage fault. */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM3 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/bootloader_ci/memory_stm32u5a.ld b/core/embed/bootloader_ci/memory_stm32u5a.ld deleted file mode 100644 index accf7658614..00000000000 --- a/core/embed/bootloader_ci/memory_stm32u5a.ld +++ /dev/null @@ -1,112 +0,0 @@ -/* Trezor v2 bootloader linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K - SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K - SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); - -SECTIONS { - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(1024) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb1 : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.gfxmmu_table*); - *(.framebuffer_select*); - . = ALIGN(4); - } >SRAM3 - - .fb2 : ALIGN(4) { - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM5 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/coreapp/memory_DISC1.ld b/core/embed/coreapp/memory_DISC1.ld deleted file mode 120000 index 3f68ec99f6c..00000000000 --- a/core/embed/coreapp/memory_DISC1.ld +++ /dev/null @@ -1 +0,0 @@ -memory_T.ld \ No newline at end of file diff --git a/core/embed/coreapp/memory_DISC2.ld b/core/embed/coreapp/memory_DISC2.ld deleted file mode 100644 index ae6d1272926..00000000000 --- a/core/embed/coreapp/memory_DISC2.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* TREZORv2 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K - SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K - SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(1024) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .data_ccm : ALIGN(4) { - *(.no_dma_buffers*); - . = ALIGN(4); - *(.buf*); - . = ALIGN(4); - } >SRAM1 - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb1 : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.gfxmmu_table*); - *(.framebuffer_select*); - . = ALIGN(4); - } >SRAM3 - - .fb2 : ALIGN(4) { - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM5 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/coreapp/memory_R.ld b/core/embed/coreapp/memory_R.ld deleted file mode 120000 index 3f68ec99f6c..00000000000 --- a/core/embed/coreapp/memory_R.ld +++ /dev/null @@ -1 +0,0 @@ -memory_T.ld \ No newline at end of file diff --git a/core/embed/coreapp/memory_T3B1.ld b/core/embed/coreapp/memory_T3B1.ld deleted file mode 120000 index b5bfd3715e0..00000000000 --- a/core/embed/coreapp/memory_T3B1.ld +++ /dev/null @@ -1 +0,0 @@ -memory_T3T1.ld \ No newline at end of file diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 4ac0b79ccf5..aa3224803c8 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -151,7 +151,7 @@ int main(void) { dma2d_init(); #endif - display_init(DISPLAY_RETAIN_CONTENT); + display_init(DISPLAY_JUMP_BEHAVIOR); #ifdef STM32U5 check_oem_keys(); diff --git a/core/embed/firmware/memory_1.ld b/core/embed/firmware/memory_1.ld deleted file mode 100644 index 625c2c64198..00000000000 --- a/core/embed/firmware/memory_1.ld +++ /dev/null @@ -1,74 +0,0 @@ -/* TREZORv1 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 1024K - 64K - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 128K -} - -main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM); -_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); - -/* used by the startup code to wipe memory */ -/* we have no CCMRAM, so erase the first word of SRAM as hack */ -ccmram_start = ORIGIN(SRAM); -ccmram_end = ORIGIN(SRAM) + 4; - -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); -_ram_start = sram_start; -_ram_end = sram_end; - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.exidx); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(512) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - /* exception handling info generated by llvm which should consist of 8 bytes of "cantunwind" */ - .exidx : ALIGN(4) { - *(.ARM.exidx*); - . = ALIGN(4); - } >FLASH AT>FLASH - - .stack : ALIGN(8) { - . = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */ - } >SRAM - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM AT>FLASH - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram_end - 8); /* this explicitly sets the end of the heap, T1 bootloader had 8 bytes reserved at end */ - } >SRAM -} diff --git a/core/embed/firmware/memory_1_min.ld b/core/embed/firmware/memory_1_min.ld deleted file mode 100644 index 625c2c64198..00000000000 --- a/core/embed/firmware/memory_1_min.ld +++ /dev/null @@ -1,74 +0,0 @@ -/* TREZORv1 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 1024K - 64K - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 128K -} - -main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM); -_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); - -/* used by the startup code to wipe memory */ -/* we have no CCMRAM, so erase the first word of SRAM as hack */ -ccmram_start = ORIGIN(SRAM); -ccmram_end = ORIGIN(SRAM) + 4; - -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); -_ram_start = sram_start; -_ram_end = sram_end; - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.exidx); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(512) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - /* exception handling info generated by llvm which should consist of 8 bytes of "cantunwind" */ - .exidx : ALIGN(4) { - *(.ARM.exidx*); - . = ALIGN(4); - } >FLASH AT>FLASH - - .stack : ALIGN(8) { - . = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */ - } >SRAM - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM AT>FLASH - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram_end - 8); /* this explicitly sets the end of the heap, T1 bootloader had 8 bytes reserved at end */ - } >SRAM -} diff --git a/core/embed/firmware/memory_DISC1.ld b/core/embed/firmware/memory_DISC1.ld deleted file mode 120000 index 3f68ec99f6c..00000000000 --- a/core/embed/firmware/memory_DISC1.ld +++ /dev/null @@ -1 +0,0 @@ -memory_T.ld \ No newline at end of file diff --git a/core/embed/firmware/memory_DISC2.ld b/core/embed/firmware/memory_DISC2.ld deleted file mode 100644 index ae6d1272926..00000000000 --- a/core/embed/firmware/memory_DISC2.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* TREZORv2 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K - SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K - SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(1024) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .data_ccm : ALIGN(4) { - *(.no_dma_buffers*); - . = ALIGN(4); - *(.buf*); - . = ALIGN(4); - } >SRAM1 - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb1 : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.gfxmmu_table*); - *(.framebuffer_select*); - . = ALIGN(4); - } >SRAM3 - - .fb2 : ALIGN(4) { - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM5 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/firmware/memory_R.ld b/core/embed/firmware/memory_R.ld deleted file mode 120000 index 3f68ec99f6c..00000000000 --- a/core/embed/firmware/memory_R.ld +++ /dev/null @@ -1 +0,0 @@ -memory_T.ld \ No newline at end of file diff --git a/core/embed/firmware/memory_T3B1.ld b/core/embed/firmware/memory_T3B1.ld deleted file mode 120000 index b5bfd3715e0..00000000000 --- a/core/embed/firmware/memory_T3B1.ld +++ /dev/null @@ -1 +0,0 @@ -memory_T3T1.ld \ No newline at end of file diff --git a/core/embed/kernel/header.S b/core/embed/kernel/header.S deleted file mode 100644 index 3531e239553..00000000000 --- a/core/embed/kernel/header.S +++ /dev/null @@ -1,54 +0,0 @@ - .syntax unified - -#include "version.h" - - .section .header, "a" - - .type g_header, %object - .size g_header, .-g_header - -// Firmware header for both Trezor One and Trezor T. -// Trezor One must have bootloader version >= 1.8.0 (before that version the hdrlen used to be reset vector) - -g_header: - .byte 'T','R','Z','F' // magic - .word g_header_end - g_header // hdrlen -#ifdef TREZOR_MODEL_T - .word 0 // expiry -#else - .word 1 // expiry -#endif - .word _codelen // codelen - .byte VERSION_MAJOR // vmajor - .byte VERSION_MINOR // vminor - .byte VERSION_PATCH // vpatch - .byte VERSION_BUILD // vbuild - .byte FIX_VERSION_MAJOR // fix_vmajor - .byte FIX_VERSION_MINOR // fix_vminor - .byte FIX_VERSION_PATCH // fix_vpatch - .byte FIX_VERSION_BUILD // fix_vbuild - .word HW_MODEL // type of the designated hardware - .byte HW_REVISION // revision of the designated hardware - .byte VERSION_MONOTONIC // monotonic version of the binary - . = . + 2 // reserved - . = . + 512 // hash1 ... hash16 - -#if !defined TREZOR_MODEL_1 -// trezor-core header style - . = . + 415 // reserved - .byte 0 // sigmask - . = . + 64 // sig -#else -// model 1 compatibility header - . = . + 64 // sig1 - . = . + 64 // sig2 - . = . + 64 // sig3 - .byte 0 // sigindex1 - .byte 0 // sigindex2 - .byte 0 // sigindex3 - . = . + 220 // reserved - . = . + 65 // reserved -#endif - -g_header_end: - diff --git a/core/embed/kernel/main.c b/core/embed/kernel/main.c index 7ad6f8ce113..376f3d2dca0 100644 --- a/core/embed/kernel/main.c +++ b/core/embed/kernel/main.c @@ -22,8 +22,11 @@ #include #include "applet.h" +#include "bl_check.h" #include "board_capabilities.h" #include "bootutils.h" +#include "button.h" +#include "consumption_mask.h" #include "display.h" #include "dma2d.h" #include "entropy.h" @@ -92,7 +95,7 @@ void drivers_init() { dma2d_init(); #endif - display_init(DISPLAY_RETAIN_CONTENT); + display_init(DISPLAY_JUMP_BEHAVIOR); #ifdef STM32U5 check_oem_keys(); @@ -114,7 +117,7 @@ void drivers_init() { entropy_init(); #if PRODUCTION || BOOTLOADER_QA - // check_and_replace_bootloader(); + check_and_replace_bootloader(); #endif #ifdef USE_BUTTON @@ -166,17 +169,24 @@ void drivers_init() { #endif } +// defined in linker script +extern uint32_t _codelen; +extern uint32_t _coreapp_clear_ram_0_start; +extern uint32_t _coreapp_clear_ram_0_size; +extern uint32_t _coreapp_clear_ram_1_start; +extern uint32_t _coreapp_clear_ram_1_size; +#define KERNEL_SIZE (uint32_t) & _codelen + // Initializes coreapp applet static void coreapp_init(applet_t *applet) { applet_header_t *coreapp_header = - (applet_header_t *)(COREAPP_START + IMAGE_HEADER_SIZE + 0x0400); + (applet_header_t *)COREAPP_CODE_ALIGN(KERNEL_START + KERNEL_SIZE); applet_layout_t coreapp_layout = { - 0 - /* .data1_start = COREAPP_RAM1_START, - .data1_size = COREAPP_RAM1_SIZE, - .data2_start = COREAPP_RAM2_START, - .data2_size = COREAPP_RAM2_SIZE,*/ + .data1_start = (uint32_t)&_coreapp_clear_ram_0_start, + .data1_size = (uint32_t)&_coreapp_clear_ram_0_size, + .data2_start = (uint32_t)&_coreapp_clear_ram_1_start, + .data2_size = (uint32_t)&_coreapp_clear_ram_1_size, }; applet_init(applet, coreapp_header, &coreapp_layout); diff --git a/core/embed/kernel/memory_T3T1.ld b/core/embed/kernel/memory_T3T1.ld deleted file mode 100644 index 07a90ccc539..00000000000 --- a/core/embed/kernel/memory_T3T1.ld +++ /dev/null @@ -1,125 +0,0 @@ -/* TREZORv2 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 160K - SRAM1 (wal) : ORIGIN = 0x3002C000, LENGTH = 16K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 8K - SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 0x38400 - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(512) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.no_dma_buffers*); - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .stack : ALIGN(8) { - . = 4K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.fb2*); - *(.framebuffer_select*); - __fb_end = .; - . = ALIGN(4); - } >SRAM3 - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - } >SRAM3 - - .heap : ALIGN(4) { - } >SRAM3 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/kernel/startup_stm32u5.S b/core/embed/kernel/startup_stm32u5.S deleted file mode 100644 index db9a204c319..00000000000 --- a/core/embed/kernel/startup_stm32u5.S +++ /dev/null @@ -1,72 +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, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of boot args - ldr r1, =boot_args_end // r1 - point to byte after the end of boot args - bl memset_reg - - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM - 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/firmware/bl_check.c b/core/embed/lib/bl_check.c similarity index 93% rename from core/embed/firmware/bl_check.c rename to core/embed/lib/bl_check.c index c172df62d6a..0274f2aa2f1 100644 --- a/core/embed/firmware/bl_check.c +++ b/core/embed/lib/bl_check.c @@ -26,13 +26,12 @@ #include "image.h" #include "memzero.h" #include "model.h" +#include "mpu.h" #include "uzlib.h" // symbols from bootloader.bin => bootloader.o -extern const void - _binary_embed_firmware_bootloaders_bootloader_bin_deflated_start; -extern const void - _binary_embed_firmware_bootloaders_bootloader_bin_deflated_size; +extern const void _binary_embed_bootloaders_bootloader_bin_deflated_start; +extern const void _binary_embed_bootloaders_bootloader_bin_deflated_size; #define CONCAT_NAME_HELPER(prefix, name, suffix) prefix##name##suffix #define CONCAT_NAME(name, var) CONCAT_NAME_HELPER(BOOTLOADER_, name, var) @@ -82,6 +81,7 @@ static void uzlib_prepare(struct uzlib_uncomp *decomp, uint8_t *window, void check_and_replace_bootloader(void) { #if PRODUCTION || BOOTLOADER_QA + mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTUPDATE); // compute current bootloader hash uint8_t hash[BLAKE2S_DIGEST_LENGTH]; @@ -95,15 +95,16 @@ void check_and_replace_bootloader(void) { // do we have the latest bootloader? if (sectrue == latest_bootloader(hash, BLAKE2S_DIGEST_LENGTH)) { + mpu_reconfig(mode); return; } // replace bootloader with the latest one const uint32_t *data = (const uint32_t - *)&_binary_embed_firmware_bootloaders_bootloader_bin_deflated_start; + *)&_binary_embed_bootloaders_bootloader_bin_deflated_start; const uint32_t len = - (const uint32_t)&_binary_embed_firmware_bootloaders_bootloader_bin_deflated_size; + (const uint32_t)&_binary_embed_bootloaders_bootloader_bin_deflated_size; struct uzlib_uncomp decomp = {0}; uint8_t decomp_window[UZLIB_WINDOW_SIZE] = {0}; @@ -134,6 +135,7 @@ void check_and_replace_bootloader(void) { if (new_bld_hdr->monotonic < current_bld_hdr->monotonic) { // reject downgrade + mpu_reconfig(mode); return; } @@ -180,5 +182,7 @@ void check_and_replace_bootloader(void) { } ensure(flash_lock_write(), NULL); + + mpu_reconfig(mode); #endif } diff --git a/core/embed/firmware/bl_check.h b/core/embed/lib/bl_check.h similarity index 100% rename from core/embed/firmware/bl_check.h rename to core/embed/lib/bl_check.h diff --git a/core/embed/lib/image.h b/core/embed/lib/image.h index bfcfba634b0..f837f7d9690 100644 --- a/core/embed/lib/image.h +++ b/core/embed/lib/image.h @@ -39,6 +39,12 @@ #define IMAGE_CODE_ALIGN(addr) \ ((((uint32_t)(uintptr_t)addr) + (CODE_ALIGNMENT - 1)) & ~(CODE_ALIGNMENT - 1)) +#define COREAPP_ALIGNMENT 512 + +#define COREAPP_CODE_ALIGN(addr) \ + ((((uint32_t)(uintptr_t)addr) + (COREAPP_ALIGNMENT - 1)) & \ + ~(COREAPP_ALIGNMENT - 1)) + typedef struct { uint32_t magic; uint32_t hdrlen; diff --git a/core/embed/models/D001/memory.ld b/core/embed/models/D001/memory.ld new file mode 100644 index 00000000000..abce5a3951c --- /dev/null +++ b/core/embed/models/D001/memory.ld @@ -0,0 +1,36 @@ +/* Auto-generated file, do not edit.*/ + +FLASH_START = 0x8000000; +BOARDLOADER_START = 0x8000000; +BOOTLOADER_START = 0x8020000; +FIRMWARE_START = 0x8040000; +FIRMWARE_P2_START = 0x8120000; +KERNEL_START = 0x8040000; +STORAGE_1_OFFSET = 0x10000; +STORAGE_2_OFFSET = 0x110000; +NORCOW_SECTOR_SIZE = 0x10000; +BOARDLOADER_IMAGE_MAXSIZE = 0xc000; +BOOTLOADER_IMAGE_MAXSIZE = 0x20000; +FIRMWARE_IMAGE_MAXSIZE = 0x1a0000; +FIRMWARE_P1_IMAGE_MAXSIZE = 0xc0000; +FIRMWARE_P2_IMAGE_MAXSIZE = 0xe0000; +KERNEL_IMAGE_MAXSIZE = 0x80000; +BOARDLOADER_SECTOR_START = 0x0; +BOARDLOADER_SECTOR_END = 0x3; +BOOTLOADER_SECTOR_START = 0x5; +BOOTLOADER_SECTOR_END = 0x5; +FIRMWARE_SECTOR_START = 0x6; +FIRMWARE_SECTOR_END = 0xb; +FIRMWARE_P2_SECTOR_START = 0x11; +FIRMWARE_P2_SECTOR_END = 0x17; +STORAGE_1_SECTOR_START = 0x4; +STORAGE_1_SECTOR_END = 0x4; +STORAGE_2_SECTOR_START = 0x10; +STORAGE_2_SECTOR_END = 0x10; +KERNEL_STACK_SIZE = 0x2000; +KERNEL_CCMRAM_SIZE = 0x4000; +KERNEL_FRAMEBUFFER_SIZE = 0x0; +KERNEL_SRAM_SIZE = 0x400; +BOOTARGS_SIZE = 0x100; +BOARD_CAPABILITIES_ADDR = 0x800bf00; +CODE_ALIGNMENT = 0x200; diff --git a/core/embed/models/D001/model_D001.h b/core/embed/models/D001/model_D001.h index c0ed2076876..5f17dcace1f 100644 --- a/core/embed/models/D001/model_D001.h +++ b/core/embed/models/D001/model_D001.h @@ -22,8 +22,7 @@ #define IMAGE_CHUNK_SIZE (128 * 1024) #define IMAGE_HASH_BLAKE2S -#define BOARD_CAPABILITIES_ADDR 0x0800BF00 -#define CODE_ALIGNMENT 0x200 +#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RESET_CONTENT // SHARED WITH MAKEFILE #define FLASH_START 0x08000000 @@ -31,6 +30,7 @@ #define BOOTLOADER_START 0x08020000 #define FIRMWARE_START 0x08040000 #define FIRMWARE_P2_START 0x08120000 +#define KERNEL_START 0x08040000 #define STORAGE_1_OFFSET 0x10000 #define STORAGE_2_OFFSET 0x110000 #define NORCOW_SECTOR_SIZE (1 * 64 * 1024) // 64 kB @@ -39,6 +39,7 @@ #define FIRMWARE_IMAGE_MAXSIZE (13 * 128 * 1024) // 1664 kB #define FIRMWARE_P1_IMAGE_MAXSIZE (6 * 128 * 1024) #define FIRMWARE_P2_IMAGE_MAXSIZE (7 * 128 * 1024) +#define KERNEL_IMAGE_MAXSIZE (4 * 128 * 1024) #define BOARDLOADER_SECTOR_START 0 #define BOARDLOADER_SECTOR_END 3 #define BOOTLOADER_SECTOR_START 5 @@ -51,5 +52,13 @@ #define STORAGE_1_SECTOR_END 4 #define STORAGE_2_SECTOR_START 16 #define STORAGE_2_SECTOR_END 16 +#define KERNEL_STACK_SIZE 8 * 1024 +#define KERNEL_CCMRAM_SIZE 16 * 1024 +#define KERNEL_FRAMEBUFFER_SIZE 0 * 1024 +#define KERNEL_SRAM_SIZE 1 * 1024 + +#define BOOTARGS_SIZE 0x100 +#define BOARD_CAPABILITIES_ADDR 0x0800BF00 +#define CODE_ALIGNMENT 0x200 #endif diff --git a/core/embed/models/D002/memory.ld b/core/embed/models/D002/memory.ld new file mode 100644 index 00000000000..3f5648b562f --- /dev/null +++ b/core/embed/models/D002/memory.ld @@ -0,0 +1,32 @@ +/* Auto-generated file, do not edit.*/ + +FLASH_START = 0xc000000; +BOARDLOADER_START = 0xc004000; +BOOTLOADER_START = 0xc010000; +KERNEL_START = 0xc050000; +FIRMWARE_START = 0xc050000; +STORAGE_1_OFFSET = 0x30000; +STORAGE_2_OFFSET = 0x50000; +NORCOW_SECTOR_SIZE = 0x10000; +BOARDLOADER_IMAGE_MAXSIZE = 0xc000; +BOOTLOADER_IMAGE_MAXSIZE = 0x20000; +FIRMWARE_IMAGE_MAXSIZE = 0x3a0000; +KERNEL_IMAGE_MAXSIZE = 0x80000; +BOARDLOADER_SECTOR_START = 0x2; +BOARDLOADER_SECTOR_END = 0x7; +BOOTLOADER_SECTOR_START = 0x8; +BOOTLOADER_SECTOR_END = 0x17; +FIRMWARE_SECTOR_START = 0x28; +FIRMWARE_SECTOR_END = 0x1f7; +STORAGE_1_SECTOR_START = 0x18; +STORAGE_1_SECTOR_END = 0x1f; +STORAGE_2_SECTOR_START = 0x20; +STORAGE_2_SECTOR_END = 0x27; +KERNEL_U_FLASH_SIZE = 0x200; +KERNEL_U_RAM_SIZE = 0x200; +KERNEL_SRAM1_SIZE = 0x4000; +KERNEL_SRAM2_SIZE = 0x2400; +KERNEL_SRAM3_SIZE = 0xbb800; +BOOTARGS_SIZE = 0x100; +BOARD_CAPABILITIES_ADDR = 0xc00ff00; +CODE_ALIGNMENT = 0x400; diff --git a/core/embed/models/D002/model_D002.h b/core/embed/models/D002/model_D002.h index 6b0712631b3..48c43dad023 100644 --- a/core/embed/models/D002/model_D002.h +++ b/core/embed/models/D002/model_D002.h @@ -25,16 +25,13 @@ #define IMAGE_CHUNK_SIZE SIZE_256K #define IMAGE_HASH_SHA256 -#define BOARD_CAPABILITIES_ADDR 0x0C00FF00 -#define CODE_ALIGNMENT 0x400 +#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RESET_CONTENT -// SHARED WITH MAKEFILE +// SHARED WITH MAKEFILE, LINKER SCRIPT etc. #define FLASH_START 0x0C000000 #define BOARDLOADER_START 0x0C004000 #define BOOTLOADER_START 0x0C010000 #define KERNEL_START 0x0C050000 -#define KERNEL_SIZE 0x00028000 -#define COREAPP_START 0x0C078000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 #define STORAGE_2_OFFSET 0x50000 @@ -42,6 +39,7 @@ #define BOARDLOADER_IMAGE_MAXSIZE (6 * 8 * 1024) // 48 kB #define BOOTLOADER_IMAGE_MAXSIZE (16 * 8 * 1024) // 128 kB #define FIRMWARE_IMAGE_MAXSIZE (464 * 8 * 1024) // 3712 kB +#define KERNEL_IMAGE_MAXSIZE (512 * 1024) // 512 kB #define BOARDLOADER_SECTOR_START 0x2 #define BOARDLOADER_SECTOR_END 0x7 #define BOOTLOADER_SECTOR_START 0x8 @@ -53,4 +51,14 @@ #define STORAGE_2_SECTOR_START 0x20 #define STORAGE_2_SECTOR_END 0x27 +#define KERNEL_U_FLASH_SIZE 512 +#define KERNEL_U_RAM_SIZE 512 +#define KERNEL_SRAM1_SIZE 16 * 1024 +#define KERNEL_SRAM2_SIZE 9 * 1024 +#define KERNEL_SRAM3_SIZE 750 * 1024 + +#define BOOTARGS_SIZE 0x100 +#define BOARD_CAPABILITIES_ADDR 0x0C00FF00 +#define CODE_ALIGNMENT 0x400 + #endif diff --git a/core/embed/models/T1B1/memory.ld b/core/embed/models/T1B1/memory.ld new file mode 100644 index 00000000000..1e78a10394f --- /dev/null +++ b/core/embed/models/T1B1/memory.ld @@ -0,0 +1,16 @@ +/* Auto-generated file, do not edit.*/ + +FLASH_START = 0x8000000; +BOOTLOADER_START = 0x8000000; +FIRMWARE_START = 0x8010000; +NORCOW_SECTOR_SIZE = 0x10000; +BOOTLOADER_IMAGE_MAXSIZE = 0x8000; +FIRMWARE_IMAGE_MAXSIZE = 0xf0000; +BOOTLOADER_SECTOR_START = 0x0; +BOOTLOADER_SECTOR_END = 0x2; +FIRMWARE_SECTOR_START = 0x4; +FIRMWARE_SECTOR_END = 0xb; +STORAGE_1_SECTOR_START = 0x2; +STORAGE_1_SECTOR_END = 0x2; +STORAGE_2_SECTOR_START = 0x3; +STORAGE_2_SECTOR_END = 0x3; diff --git a/core/embed/models/T1B1/model_T1B1.h b/core/embed/models/T1B1/model_T1B1.h index e5006b01e4d..ff007bc7575 100644 --- a/core/embed/models/T1B1/model_T1B1.h +++ b/core/embed/models/T1B1/model_T1B1.h @@ -12,6 +12,7 @@ #define IMAGE_CHUNK_SIZE (64 * 1024) #define IMAGE_HASH_SHA256 #define CODE_ALIGNMENT 0x200 +#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RETAIN_CONTENT // SHARED WITH MAKEFILE #define FLASH_START 0x08000000 diff --git a/core/embed/models/T2B1/memory.ld b/core/embed/models/T2B1/memory.ld new file mode 100644 index 00000000000..3c841039f1d --- /dev/null +++ b/core/embed/models/T2B1/memory.ld @@ -0,0 +1,36 @@ +/* Auto-generated file, do not edit.*/ + +FLASH_START = 0x8000000; +BOARDLOADER_START = 0x8000000; +BOOTLOADER_START = 0x8020000; +FIRMWARE_START = 0x8040000; +FIRMWARE_P2_START = 0x8120000; +KERNEL_START = 0x8040000; +STORAGE_1_OFFSET = 0x10000; +STORAGE_2_OFFSET = 0x110000; +NORCOW_SECTOR_SIZE = 0x10000; +BOARDLOADER_IMAGE_MAXSIZE = 0xc000; +BOOTLOADER_IMAGE_MAXSIZE = 0x20000; +FIRMWARE_IMAGE_MAXSIZE = 0x1a0000; +FIRMWARE_P1_IMAGE_MAXSIZE = 0xc0000; +FIRMWARE_P2_IMAGE_MAXSIZE = 0xe0000; +KERNEL_IMAGE_MAXSIZE = 0x80000; +BOARDLOADER_SECTOR_START = 0x0; +BOARDLOADER_SECTOR_END = 0x3; +BOOTLOADER_SECTOR_START = 0x5; +BOOTLOADER_SECTOR_END = 0x5; +FIRMWARE_SECTOR_START = 0x6; +FIRMWARE_SECTOR_END = 0xb; +FIRMWARE_P2_SECTOR_START = 0x11; +FIRMWARE_P2_SECTOR_END = 0x17; +STORAGE_1_SECTOR_START = 0x4; +STORAGE_1_SECTOR_END = 0x4; +STORAGE_2_SECTOR_START = 0x10; +STORAGE_2_SECTOR_END = 0x10; +KERNEL_STACK_SIZE = 0x2000; +KERNEL_CCMRAM_SIZE = 0x4000; +KERNEL_FRAMEBUFFER_SIZE = 0x2000; +KERNEL_SRAM_SIZE = 0x400; +BOOTARGS_SIZE = 0x100; +BOARD_CAPABILITIES_ADDR = 0x800bf00; +CODE_ALIGNMENT = 0x200; diff --git a/core/embed/models/T2B1/model_T2B1.h b/core/embed/models/T2B1/model_T2B1.h index d82aefc89b0..74632ad2498 100644 --- a/core/embed/models/T2B1/model_T2B1.h +++ b/core/embed/models/T2B1/model_T2B1.h @@ -24,8 +24,7 @@ #define IMAGE_CHUNK_SIZE (128 * 1024) #define IMAGE_HASH_BLAKE2S -#define BOARD_CAPABILITIES_ADDR 0x0800BF00 -#define CODE_ALIGNMENT 0x200 +#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RETAIN_CONTENT // SHARED WITH MAKEFILE #define FLASH_START 0x08000000 @@ -33,6 +32,7 @@ #define BOOTLOADER_START 0x08020000 #define FIRMWARE_START 0x08040000 #define FIRMWARE_P2_START 0x08120000 +#define KERNEL_START 0x08040000 #define STORAGE_1_OFFSET 0x10000 #define STORAGE_2_OFFSET 0x110000 #define NORCOW_SECTOR_SIZE (1 * 64 * 1024) // 64 kB @@ -41,6 +41,7 @@ #define FIRMWARE_IMAGE_MAXSIZE (13 * 128 * 1024) // 1664 kB #define FIRMWARE_P1_IMAGE_MAXSIZE (6 * 128 * 1024) #define FIRMWARE_P2_IMAGE_MAXSIZE (7 * 128 * 1024) +#define KERNEL_IMAGE_MAXSIZE (4 * 128 * 1024) #define BOARDLOADER_SECTOR_START 0 #define BOARDLOADER_SECTOR_END 3 #define BOOTLOADER_SECTOR_START 5 @@ -53,5 +54,13 @@ #define STORAGE_1_SECTOR_END 4 #define STORAGE_2_SECTOR_START 16 #define STORAGE_2_SECTOR_END 16 +#define KERNEL_STACK_SIZE 8 * 1024 +#define KERNEL_CCMRAM_SIZE 16 * 1024 +#define KERNEL_FRAMEBUFFER_SIZE 8 * 1024 +#define KERNEL_SRAM_SIZE 1 * 1024 + +#define BOOTARGS_SIZE 0x100 +#define BOARD_CAPABILITIES_ADDR 0x0800BF00 +#define CODE_ALIGNMENT 0x200 #endif diff --git a/core/embed/models/T2T1/memory.ld b/core/embed/models/T2T1/memory.ld new file mode 100644 index 00000000000..abce5a3951c --- /dev/null +++ b/core/embed/models/T2T1/memory.ld @@ -0,0 +1,36 @@ +/* Auto-generated file, do not edit.*/ + +FLASH_START = 0x8000000; +BOARDLOADER_START = 0x8000000; +BOOTLOADER_START = 0x8020000; +FIRMWARE_START = 0x8040000; +FIRMWARE_P2_START = 0x8120000; +KERNEL_START = 0x8040000; +STORAGE_1_OFFSET = 0x10000; +STORAGE_2_OFFSET = 0x110000; +NORCOW_SECTOR_SIZE = 0x10000; +BOARDLOADER_IMAGE_MAXSIZE = 0xc000; +BOOTLOADER_IMAGE_MAXSIZE = 0x20000; +FIRMWARE_IMAGE_MAXSIZE = 0x1a0000; +FIRMWARE_P1_IMAGE_MAXSIZE = 0xc0000; +FIRMWARE_P2_IMAGE_MAXSIZE = 0xe0000; +KERNEL_IMAGE_MAXSIZE = 0x80000; +BOARDLOADER_SECTOR_START = 0x0; +BOARDLOADER_SECTOR_END = 0x3; +BOOTLOADER_SECTOR_START = 0x5; +BOOTLOADER_SECTOR_END = 0x5; +FIRMWARE_SECTOR_START = 0x6; +FIRMWARE_SECTOR_END = 0xb; +FIRMWARE_P2_SECTOR_START = 0x11; +FIRMWARE_P2_SECTOR_END = 0x17; +STORAGE_1_SECTOR_START = 0x4; +STORAGE_1_SECTOR_END = 0x4; +STORAGE_2_SECTOR_START = 0x10; +STORAGE_2_SECTOR_END = 0x10; +KERNEL_STACK_SIZE = 0x2000; +KERNEL_CCMRAM_SIZE = 0x4000; +KERNEL_FRAMEBUFFER_SIZE = 0x0; +KERNEL_SRAM_SIZE = 0x400; +BOOTARGS_SIZE = 0x100; +BOARD_CAPABILITIES_ADDR = 0x800bf00; +CODE_ALIGNMENT = 0x200; diff --git a/core/embed/models/T2T1/model_T2T1.h b/core/embed/models/T2T1/model_T2T1.h index fc29eaf94c2..a759fad7fc1 100644 --- a/core/embed/models/T2T1/model_T2T1.h +++ b/core/embed/models/T2T1/model_T2T1.h @@ -24,8 +24,7 @@ #define IMAGE_CHUNK_SIZE (128 * 1024) #define IMAGE_HASH_BLAKE2S -#define BOARD_CAPABILITIES_ADDR 0x0800BF00 -#define CODE_ALIGNMENT 0x200 +#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RETAIN_CONTENT // SHARED WITH MAKEFILE #define FLASH_START 0x08000000 @@ -33,6 +32,7 @@ #define BOOTLOADER_START 0x08020000 #define FIRMWARE_START 0x08040000 #define FIRMWARE_P2_START 0x08120000 +#define KERNEL_START 0x08040000 #define STORAGE_1_OFFSET 0x10000 #define STORAGE_2_OFFSET 0x110000 #define NORCOW_SECTOR_SIZE (1 * 64 * 1024) // 64 kB @@ -41,6 +41,7 @@ #define FIRMWARE_IMAGE_MAXSIZE (13 * 128 * 1024) // 1664 kB #define FIRMWARE_P1_IMAGE_MAXSIZE (6 * 128 * 1024) #define FIRMWARE_P2_IMAGE_MAXSIZE (7 * 128 * 1024) +#define KERNEL_IMAGE_MAXSIZE (4 * 128 * 1024) #define BOARDLOADER_SECTOR_START 0 #define BOARDLOADER_SECTOR_END 3 #define BOOTLOADER_SECTOR_START 5 @@ -53,5 +54,13 @@ #define STORAGE_1_SECTOR_END 4 #define STORAGE_2_SECTOR_START 16 #define STORAGE_2_SECTOR_END 16 +#define KERNEL_STACK_SIZE 8 * 1024 +#define KERNEL_CCMRAM_SIZE 16 * 1024 +#define KERNEL_FRAMEBUFFER_SIZE 0 * 1024 +#define KERNEL_SRAM_SIZE 1 * 1024 + +#define BOOTARGS_SIZE 0x100 +#define BOARD_CAPABILITIES_ADDR 0x0800BF00 +#define CODE_ALIGNMENT 0x200 #endif diff --git a/core/embed/models/T3B1/memory.ld b/core/embed/models/T3B1/memory.ld new file mode 100644 index 00000000000..29bfa19521b --- /dev/null +++ b/core/embed/models/T3B1/memory.ld @@ -0,0 +1,32 @@ +/* Auto-generated file, do not edit.*/ + +FLASH_START = 0xc000000; +BOARDLOADER_START = 0xc004000; +BOOTLOADER_START = 0xc010000; +KERNEL_START = 0xc050000; +FIRMWARE_START = 0xc050000; +STORAGE_1_OFFSET = 0x30000; +STORAGE_2_OFFSET = 0x50000; +NORCOW_SECTOR_SIZE = 0x10000; +BOARDLOADER_IMAGE_MAXSIZE = 0xc000; +BOOTLOADER_IMAGE_MAXSIZE = 0x20000; +FIRMWARE_IMAGE_MAXSIZE = 0x1a0000; +KERNEL_IMAGE_MAXSIZE = 0x80000; +BOARDLOADER_SECTOR_START = 0x2; +BOARDLOADER_SECTOR_END = 0x7; +BOOTLOADER_SECTOR_START = 0x8; +BOOTLOADER_SECTOR_END = 0x17; +FIRMWARE_SECTOR_START = 0x28; +FIRMWARE_SECTOR_END = 0xf7; +STORAGE_1_SECTOR_START = 0x18; +STORAGE_1_SECTOR_END = 0x1f; +STORAGE_2_SECTOR_START = 0x20; +STORAGE_2_SECTOR_END = 0x27; +KERNEL_U_FLASH_SIZE = 0x200; +KERNEL_U_RAM_SIZE = 0x200; +KERNEL_SRAM1_SIZE = 0x4000; +KERNEL_SRAM2_SIZE = 0x2000; +KERNEL_SRAM3_SIZE = 0x38400; +BOOTARGS_SIZE = 0x100; +BOARD_CAPABILITIES_ADDR = 0xc00ff00; +CODE_ALIGNMENT = 0x200; diff --git a/core/embed/models/T3B1/model_T3B1.h b/core/embed/models/T3B1/model_T3B1.h index 3e973c8ff57..6dc327e01cb 100644 --- a/core/embed/models/T3B1/model_T3B1.h +++ b/core/embed/models/T3B1/model_T3B1.h @@ -25,13 +25,13 @@ #define IMAGE_CHUNK_SIZE (128 * 1024) #define IMAGE_HASH_SHA256 -#define BOARD_CAPABILITIES_ADDR 0x0C00FF00 -#define CODE_ALIGNMENT 0x200 +#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RETAIN_CONTENT -// SHARED WITH MAKEFILE +// SHARED WITH MAKEFILE, LINKER SCRIPT etc. #define FLASH_START 0x0C000000 #define BOARDLOADER_START 0x0C004000 #define BOOTLOADER_START 0x0C010000 +#define KERNEL_START 0x0C050000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 #define STORAGE_2_OFFSET 0x50000 @@ -39,6 +39,7 @@ #define BOARDLOADER_IMAGE_MAXSIZE (6 * 8 * 1024) // 48 kB #define BOOTLOADER_IMAGE_MAXSIZE (16 * 8 * 1024) // 128 kB #define FIRMWARE_IMAGE_MAXSIZE (208 * 8 * 1024) // 1664 kB +#define KERNEL_IMAGE_MAXSIZE (512 * 1024) // 512 kB #define BOARDLOADER_SECTOR_START 0x2 #define BOARDLOADER_SECTOR_END 0x7 #define BOOTLOADER_SECTOR_START 0x8 @@ -50,4 +51,14 @@ #define STORAGE_2_SECTOR_START 0x20 #define STORAGE_2_SECTOR_END 0x27 +#define KERNEL_U_FLASH_SIZE 512 +#define KERNEL_U_RAM_SIZE 512 +#define KERNEL_SRAM1_SIZE 16 * 1024 +#define KERNEL_SRAM2_SIZE 8 * 1024 +#define KERNEL_SRAM3_SIZE 0x38400 + +#define BOOTARGS_SIZE 0x100 +#define BOARD_CAPABILITIES_ADDR 0x0C00FF00 +#define CODE_ALIGNMENT 0x200 + #endif diff --git a/core/embed/models/T3T1/memory.ld b/core/embed/models/T3T1/memory.ld new file mode 100644 index 00000000000..29bfa19521b --- /dev/null +++ b/core/embed/models/T3T1/memory.ld @@ -0,0 +1,32 @@ +/* Auto-generated file, do not edit.*/ + +FLASH_START = 0xc000000; +BOARDLOADER_START = 0xc004000; +BOOTLOADER_START = 0xc010000; +KERNEL_START = 0xc050000; +FIRMWARE_START = 0xc050000; +STORAGE_1_OFFSET = 0x30000; +STORAGE_2_OFFSET = 0x50000; +NORCOW_SECTOR_SIZE = 0x10000; +BOARDLOADER_IMAGE_MAXSIZE = 0xc000; +BOOTLOADER_IMAGE_MAXSIZE = 0x20000; +FIRMWARE_IMAGE_MAXSIZE = 0x1a0000; +KERNEL_IMAGE_MAXSIZE = 0x80000; +BOARDLOADER_SECTOR_START = 0x2; +BOARDLOADER_SECTOR_END = 0x7; +BOOTLOADER_SECTOR_START = 0x8; +BOOTLOADER_SECTOR_END = 0x17; +FIRMWARE_SECTOR_START = 0x28; +FIRMWARE_SECTOR_END = 0xf7; +STORAGE_1_SECTOR_START = 0x18; +STORAGE_1_SECTOR_END = 0x1f; +STORAGE_2_SECTOR_START = 0x20; +STORAGE_2_SECTOR_END = 0x27; +KERNEL_U_FLASH_SIZE = 0x200; +KERNEL_U_RAM_SIZE = 0x200; +KERNEL_SRAM1_SIZE = 0x4000; +KERNEL_SRAM2_SIZE = 0x2000; +KERNEL_SRAM3_SIZE = 0x38400; +BOOTARGS_SIZE = 0x100; +BOARD_CAPABILITIES_ADDR = 0xc00ff00; +CODE_ALIGNMENT = 0x200; diff --git a/core/embed/models/T3T1/model_T3T1.h b/core/embed/models/T3T1/model_T3T1.h index 35af3e6d203..35643b895f1 100644 --- a/core/embed/models/T3T1/model_T3T1.h +++ b/core/embed/models/T3T1/model_T3T1.h @@ -25,16 +25,13 @@ #define IMAGE_CHUNK_SIZE (128 * 1024) #define IMAGE_HASH_SHA256 -#define BOARD_CAPABILITIES_ADDR 0x0C00FF00 -#define CODE_ALIGNMENT 0x200 +#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RETAIN_CONTENT -// SHARED WITH MAKEFILE +// SHARED WITH MAKEFILE, LINKER SCRIPT etc. #define FLASH_START 0x0C000000 #define BOARDLOADER_START 0x0C004000 #define BOOTLOADER_START 0x0C010000 #define KERNEL_START 0x0C050000 -#define KERNEL_SIZE 0x00028000 -#define COREAPP_START 0x0C078000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 #define STORAGE_2_OFFSET 0x50000 @@ -42,6 +39,7 @@ #define BOARDLOADER_IMAGE_MAXSIZE (6 * 8 * 1024) // 48 kB #define BOOTLOADER_IMAGE_MAXSIZE (16 * 8 * 1024) // 128 kB #define FIRMWARE_IMAGE_MAXSIZE (208 * 8 * 1024) // 1664 kB +#define KERNEL_IMAGE_MAXSIZE (512 * 1024) // 512 kB #define BOARDLOADER_SECTOR_START 0x2 #define BOARDLOADER_SECTOR_END 0x7 #define BOOTLOADER_SECTOR_START 0x8 @@ -53,4 +51,14 @@ #define STORAGE_2_SECTOR_START 0x20 #define STORAGE_2_SECTOR_END 0x27 +#define KERNEL_U_FLASH_SIZE 512 +#define KERNEL_U_RAM_SIZE 512 +#define KERNEL_SRAM1_SIZE 16 * 1024 +#define KERNEL_SRAM2_SIZE 8 * 1024 +#define KERNEL_SRAM3_SIZE 0x38400 + +#define BOOTARGS_SIZE 0x100 +#define BOARD_CAPABILITIES_ADDR 0x0C00FF00 +#define CODE_ALIGNMENT 0x200 + #endif diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 3ff73d873c2..1fa330f2af4 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -786,7 +786,7 @@ void cpuid_read(void) { int main(void) { system_init(&rsod_panic_handler); - display_init(DISPLAY_RETAIN_CONTENT); + display_init(DISPLAY_JUMP_BEHAVIOR); #ifdef STM32U5 secure_aes_init(); diff --git a/core/embed/prodtest/memory_stm32u5a.ld b/core/embed/prodtest/memory_stm32u5a.ld deleted file mode 100644 index fa303b5d4f7..00000000000 --- a/core/embed/prodtest/memory_stm32u5a.ld +++ /dev/null @@ -1,127 +0,0 @@ -/* TREZORv2 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K - SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K - SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(1024) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .data_ccm : ALIGN(4) { - *(.no_dma_buffers*); - . = ALIGN(4); - } >SRAM1 - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb1 : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.gfxmmu_table*); - *(.framebuffer_select*); - . = ALIGN(4); - } >SRAM3 - - .fb2 : ALIGN(4) { - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM5 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/prodtest/startup_stm32f4.s b/core/embed/prodtest/startup_stm32f4.s deleted file mode 100644 index ad8bc096ee3..00000000000 --- a/core/embed/prodtest/startup_stm32f4.s +++ /dev/null @@ -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 r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of BOOT_ARGS - ldr r1, =boot_args_end // r1 - point to byte after the end of BOOT_ARGS - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written - 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/prodtest/startup_stm32u5.s b/core/embed/prodtest/startup_stm32u5.s deleted file mode 100644 index db9a204c319..00000000000 --- a/core/embed/prodtest/startup_stm32u5.s +++ /dev/null @@ -1,72 +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, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of boot args - ldr r1, =boot_args_end // r1 - point to byte after the end of boot args - bl memset_reg - - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM - 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/reflash/memory_stm32f4.ld b/core/embed/reflash/memory_stm32f4.ld deleted file mode 100644 index 718b009385a..00000000000 --- a/core/embed/reflash/memory_stm32f4.ld +++ /dev/null @@ -1,81 +0,0 @@ -/* TREZORv2 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x08040000, LENGTH = 768K - CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x1000FF00, LENGTH = 0x100 - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K -} - -main_stack_base = ORIGIN(SRAM) + LENGTH(SRAM); /* 8-byte aligned full descending 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); - -/* used by the startup code to wipe memory */ -ccmram_start = ORIGIN(CCMRAM); -ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); -_ram_start = sram_start; -_ram_end = sram_end; - -_codelen = SIZEOF(.flash) + SIZEOF(.data); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(512) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM AT>FLASH - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram_end - 16K); /* this explicitly sets the end of the heap effectively giving the stack at most 16K */ - } >SRAM - - .stack : ALIGN(8) { - . = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */ - } >SRAM - - .boot_args : ALIGN(8) { - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/reflash/memory_stm32u58.ld b/core/embed/reflash/memory_stm32u58.ld deleted file mode 100644 index 586970355da..00000000000 --- a/core/embed/reflash/memory_stm32u58.ld +++ /dev/null @@ -1,125 +0,0 @@ -/* TREZORv2 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 512K - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(512) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .data_ccm : ALIGN(4) { - *(.no_dma_buffers*); - . = ALIGN(4); - } >SRAM1 - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K + 0x100; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.fb2*); - *(.framebuffer_select*); - __fb_end = .; - . = ALIGN(4); - } >SRAM3 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/reflash/memory_stm32u5a.ld b/core/embed/reflash/memory_stm32u5a.ld deleted file mode 100644 index e03a321847c..00000000000 --- a/core/embed/reflash/memory_stm32u5a.ld +++ /dev/null @@ -1,128 +0,0 @@ -/* TREZORv2 firmware linker script */ - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K - SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K - SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 512K - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -/* 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash : ALIGN(1024) { - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .data_ccm : ALIGN(4) { - *(.no_dma_buffers*); - . = ALIGN(4); - } >SRAM1 - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ - } >SRAM1 - - .stack : ALIGN(8) { - . = 16K + 0x100; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .fb1 : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.gfxmmu_table*); - *(.framebuffer_select*); - . = ALIGN(4); - } >SRAM3 - - .fb2 : ALIGN(4) { - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM5 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS -} diff --git a/core/embed/reflash/startup_stm32f4.s b/core/embed/reflash/startup_stm32f4.s deleted file mode 100644 index ad8bc096ee3..00000000000 --- a/core/embed/reflash/startup_stm32f4.s +++ /dev/null @@ -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 r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of BOOT_ARGS - ldr r1, =boot_args_end // r1 - point to byte after the end of BOOT_ARGS - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written - 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/reflash/startup_stm32u5.s b/core/embed/reflash/startup_stm32u5.s deleted file mode 100644 index db9a204c319..00000000000 --- a/core/embed/reflash/startup_stm32u5.s +++ /dev/null @@ -1,72 +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, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of boot args - ldr r1, =boot_args_end // r1 - point to byte after the end of boot args - bl memset_reg - - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM - 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/trezorhal/mpu.h b/core/embed/trezorhal/mpu.h index c8486767a3f..895d1331c8c 100644 --- a/core/embed/trezorhal/mpu.h +++ b/core/embed/trezorhal/mpu.h @@ -37,9 +37,10 @@ typedef enum { MPU_MODE_OTP, // + OTP (privileged RW) MPU_MODE_FSMC_REGS, // + FSMC control registers (privileged RW) MPU_MODE_FLASHOB, // + Option bytes mapping (privileged RW) - MPU_MODE_SECRET, // + secret area (priviledeg RW) - MPU_MODE_STORAGE, // + both storage areas (privilehed RW) + MPU_MODE_SECRET, // + secret area (privileged RW) + MPU_MODE_STORAGE, // + both storage areas (privileged RW) MPU_MODE_ASSETS, // + assets (privileged RW) + MPU_MODE_KERNEL_SRAM, // + extra kernel SRAM (STM32F4 Only) (privileged RW) MPU_MODE_UNUSED_FLASH, // + unused flash areas (privileged RW) MPU_MODE_APP, // + unprivileged DMA2D (RW) & Assets (RO) } mpu_mode_t; diff --git a/core/embed/trezorhal/stm32f4/consumption_mask.c b/core/embed/trezorhal/stm32f4/consumption_mask.c index 3252fdaecee..7263377d722 100644 --- a/core/embed/trezorhal/stm32f4/consumption_mask.c +++ b/core/embed/trezorhal/stm32f4/consumption_mask.c @@ -18,6 +18,7 @@ */ #include STM32_HAL_H +#include "mpu.h" #include "rng.h" #ifdef KERNEL_MODE @@ -29,15 +30,16 @@ #error Not implemented for boardloader! #endif -#if defined BOOTLOADER -__attribute__((section(".buf"))) -#endif -uint32_t pwm_data[SAMPLES] = {0}; +__attribute__((section(".buf"))) uint32_t pwm_data[SAMPLES] = {0}; void consumption_mask_randomize() { + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_KERNEL_SRAM); + for (int i = 0; i < SAMPLES; i++) { pwm_data[i] = rng_get() % TIMER_PERIOD; } + + mpu_restore(mpu_mode); } void consumption_mask_init(void) { diff --git a/core/embed/trezorhal/stm32f4/limited_util.S b/core/embed/trezorhal/stm32f4/limited_util.S index 0c2f72f8c16..ba510710b0d 100644 --- a/core/embed/trezorhal/stm32f4/limited_util.S +++ b/core/embed/trezorhal/stm32f4/limited_util.S @@ -10,10 +10,13 @@ memset_reg: // 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 @@ -30,13 +33,12 @@ jump_to: cpsid f // wipe memory at the end of the current stage of code bl clear_otg_hs_memory - ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM - ldr r2, =0 // r2 - the word-sized value to be written + 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, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written + 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) @@ -87,13 +89,12 @@ shutdown_privileged: mov r11, r0 mov r12, r0 ldr lr, =0xffffffff - ldr r0, =ccmram_start - ldr r1, =ccmram_end - // set to value in r2 + + ldr r0, =_shutdown_clear_ram_0_start + ldr r1, =_shutdown_clear_ram_0_end bl memset_reg - ldr r0, =sram_start - ldr r1, =sram_end - // set to value in r2 + 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 diff --git a/core/embed/boardloader/memory_stm32f4.ld b/core/embed/trezorhal/stm32f4/linker/boardloader.ld similarity index 50% rename from core/embed/boardloader/memory_stm32f4.ld rename to core/embed/trezorhal/stm32f4/linker/boardloader.ld index 167d720fba9..6df6bab3c99 100644 --- a/core/embed/boardloader/memory_stm32f4.ld +++ b/core/embed/trezorhal/stm32f4/linker/boardloader.ld @@ -1,30 +1,44 @@ -/* Trezor v2 boardloader linker script */ +INCLUDE "./embed/trezorhal/stm32f4/linker/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 48K - CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K + FLASH (rx) : ORIGIN = BOARDLOADER_START, LENGTH = BOARDLOADER_IMAGE_MAXSIZE + CCMRAM (wal) : ORIGIN = MCU_CCMRAM, LENGTH = MCU_CCMRAM_SIZE + SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE } main_stack_base = ORIGIN(CCMRAM) + LENGTH(CCMRAM); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(CCMRAM); +_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 */ -ccmram_start = ORIGIN(CCMRAM); -ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); +_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 code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); +/* 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; SECTIONS { - .vector_table : ALIGN(512) { + .vector_table : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); } >FLASH AT>FLASH @@ -54,7 +68,7 @@ SECTIONS { } >SRAM /* Hard-coded address for capabilities structure */ - .capabilities 0x0800BF00 : {KEEP(*(.capabilities_section))} + .capabilities BOARD_CAPABILITIES_ADDR : {KEEP(*(.capabilities_section))} .stack : ALIGN(8) { . = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */ diff --git a/core/embed/bootloader_ci/memory_stm32f4.ld b/core/embed/trezorhal/stm32f4/linker/bootloader.ld similarity index 52% rename from core/embed/bootloader_ci/memory_stm32f4.ld rename to core/embed/trezorhal/stm32f4/linker/bootloader.ld index 42eb1cd20c0..4595adfa41e 100644 --- a/core/embed/bootloader_ci/memory_stm32f4.ld +++ b/core/embed/trezorhal/stm32f4/linker/bootloader.ld @@ -1,12 +1,12 @@ -/* Trezor v2 bootloader linker script */ +INCLUDE "./embed/trezorhal/stm32f4/linker/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 128K - CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x1000FF00, LENGTH = 0x100 - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K + FLASH (rx) : ORIGIN = BOOTLOADER_START, LENGTH = BOOTLOADER_IMAGE_MAXSIZE + CCMRAM (wal) : ORIGIN = MCU_CCMRAM, LENGTH = MCU_CCMRAM_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE } main_stack_base = ORIGIN(CCMRAM) + SIZEOF(.stack) ; /* 8-byte aligned full descending stack */ @@ -17,14 +17,26 @@ _estack = main_stack_base; 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 */ -ccmram_start = ORIGIN(CCMRAM); -ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); - -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); +_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); @@ -37,7 +49,7 @@ SECTIONS { KEEP(*(.header)); } >FLASH AT>FLASH - .flash : ALIGN(512) { + .flash : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); @@ -67,6 +79,8 @@ SECTIONS { .buf : ALIGN(4) { *(.buf*); . = ALIGN(4); + *(.no_dma_buffers*); + . = ALIGN(4); } >SRAM .boot_args : ALIGN(8) { @@ -74,9 +88,4 @@ SECTIONS { . = ALIGN(8); } >BOOT_ARGS - .data_ccm : ALIGN(4) { - *(.no_dma_buffers*); - . = ALIGN(4); - } >CCMRAM - } diff --git a/core/embed/firmware/memory_T.ld b/core/embed/trezorhal/stm32f4/linker/coreapp.ld similarity index 55% rename from core/embed/firmware/memory_T.ld rename to core/embed/trezorhal/stm32f4/linker/coreapp.ld index 9affc00a900..ba5dc161ef3 100644 --- a/core/embed/firmware/memory_T.ld +++ b/core/embed/trezorhal/stm32f4/linker/coreapp.ld @@ -1,37 +1,26 @@ -/* TREZORv2 firmware linker script */ +INCLUDE "./embed/trezorhal/stm32f4/linker/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x08040000, LENGTH = 768K - FLASH2 (r) : ORIGIN = 0x08120000, LENGTH = 896K - CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x1000FF00, LENGTH = 0x100 - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K + FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_P1_IMAGE_MAXSIZE + FLASH2 (r) : ORIGIN = FIRMWARE_P2_START, LENGTH = FIRMWARE_P2_IMAGE_MAXSIZE + CCMRAM (wal) : ORIGIN = MCU_CCMRAM + KERNEL_STACK_SIZE, LENGTH = MCU_CCMRAM_SIZE - KERNEL_CCMRAM_SIZE - KERNEL_FRAMEBUFFER_SIZE - KERNEL_STACK_SIZE + SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE - KERNEL_SRAM_SIZE } main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ _sstack = ORIGIN(SRAM); _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); -/* used by the startup code to wipe memory */ -ccmram_start = ORIGIN(CCMRAM); -ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); -_ram_start = sram_start; -_ram_end = sram_end; +bss_start = ADDR(.bss); +bss_end = ADDR(.bss) + SIZEOF(.bss); _codelen = LENGTH(FLASH) - SIZEOF(.vendorheader) - SIZEOF(.header) + SIZEOF(.flash2); _flash_start = ORIGIN(FLASH); @@ -48,12 +37,12 @@ SECTIONS { KEEP(*(.header)); } >FLASH AT>FLASH - .flash2 : ALIGN(512) { - build/firmware/frozen_mpy.o(.rodata*); - build/firmware/vendor/secp256k1-zkp/src/secp256k1.o(.rodata*); - build/firmware/vendor/secp256k1-zkp/src/precomputed_ecmult.o(.rodata*); - build/firmware/vendor/secp256k1-zkp/src/precomputed_ecmult_gen.o(.rodata*); - build/firmware/vendor/trezor-crypto/aes/aestab.o(.rodata*); + .flash2 : ALIGN(CODE_ALIGNMENT) { + build/coreapp/frozen_mpy.o(.rodata*); + build/coreapp/vendor/secp256k1-zkp/src/secp256k1.o(.rodata*); + build/coreapp/vendor/secp256k1-zkp/src/precomputed_ecmult.o(.rodata*); + build/coreapp/vendor/secp256k1-zkp/src/precomputed_ecmult_gen.o(.rodata*); + build/coreapp/vendor/trezor-crypto/aes/aestab.o(.rodata*); . = ALIGN(4); */libtrezor_lib.a:(.text*); . = ALIGN(4); @@ -62,14 +51,14 @@ SECTIONS { } >FLASH2 AT>FLASH2 .flash : ALIGN(512) { + KEEP(*(.kernel)); + . = ALIGN(512); KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); . = ALIGN(4); *(.rodata*); . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); . = ALIGN(512); } >FLASH AT>FLASH @@ -94,7 +83,7 @@ SECTIONS { .heap : ALIGN(4) { . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram_end); /* this explicitly sets the end of the heap */ + . = ABSOLUTE(ORIGIN(SRAM) + LENGTH(SRAM)); /* this explicitly sets the end of the heap */ } >SRAM .data_ccm : ALIGN(4) { @@ -102,8 +91,9 @@ SECTIONS { . = ALIGN(4); } >CCMRAM - .boot_args : ALIGN(8) { - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS + + /DISCARD/ : { + *(.ARM.exidx*); + } + } diff --git a/core/embed/coreapp/memory_T.ld b/core/embed/trezorhal/stm32f4/linker/firmware.ld similarity index 82% rename from core/embed/coreapp/memory_T.ld rename to core/embed/trezorhal/stm32f4/linker/firmware.ld index 9affc00a900..efd26bd488f 100644 --- a/core/embed/coreapp/memory_T.ld +++ b/core/embed/trezorhal/stm32f4/linker/firmware.ld @@ -1,13 +1,13 @@ -/* TREZORv2 firmware linker script */ +INCLUDE "./embed/trezorhal/stm32f4/linker/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x08040000, LENGTH = 768K - FLASH2 (r) : ORIGIN = 0x08120000, LENGTH = 896K - CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x1000FF00, LENGTH = 0x100 - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K + FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_P1_IMAGE_MAXSIZE + FLASH2 (r) : ORIGIN = FIRMWARE_P2_START, LENGTH = FIRMWARE_P2_IMAGE_MAXSIZE + CCMRAM (wal) : ORIGIN = MCU_CCMRAM, LENGTH = MCU_CCMRAM_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE } main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ @@ -18,6 +18,8 @@ _estack = main_stack_base; 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 */ ccmram_start = ORIGIN(CCMRAM); @@ -61,7 +63,7 @@ SECTIONS { . = ALIGN(512); } >FLASH2 AT>FLASH2 - .flash : ALIGN(512) { + .flash : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); diff --git a/core/embed/trezorhal/stm32f4/linker/kernel.ld b/core/embed/trezorhal/stm32f4/linker/kernel.ld new file mode 100644 index 00000000000..6486ce4cc97 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/linker/kernel.ld @@ -0,0 +1,113 @@ +INCLUDE "./embed/trezorhal/stm32f4/linker/memory.ld"; + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = KERNEL_IMAGE_MAXSIZE + CCMRAM_STACK (wal) : ORIGIN = MCU_CCMRAM, LENGTH = KERNEL_STACK_SIZE + CCMRAM_FB (wal) : ORIGIN = MCU_CCMRAM + MCU_CCMRAM_SIZE - KERNEL_CCMRAM_SIZE - KERNEL_FRAMEBUFFER_SIZE, LENGTH = KERNEL_FRAMEBUFFER_SIZE + CCMRAM (wal) : ORIGIN = MCU_CCMRAM + MCU_CCMRAM_SIZE - KERNEL_CCMRAM_SIZE, LENGTH = KERNEL_CCMRAM_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM (wal) : ORIGIN = MCU_SRAM + MCU_SRAM_SIZE - KERNEL_SRAM_SIZE, LENGTH = KERNEL_SRAM_SIZE +} + +main_stack_base = ORIGIN(CCMRAM_STACK) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(CCMRAM_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); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +/* 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; + +/* used by applet cleaning code */ +_coreapp_clear_ram_0_start = MCU_CCMRAM + KERNEL_STACK_SIZE; +_coreapp_clear_ram_0_size = MCU_CCMRAM_SIZE - KERNEL_CCMRAM_SIZE - KERNEL_FRAMEBUFFER_SIZE - KERNEL_STACK_SIZE; +_coreapp_clear_ram_1_start = MCU_SRAM; +_coreapp_clear_ram_1_size = MCU_SRAM_SIZE - KERNEL_SRAM_SIZE; + + +_codelen = SIZEOF(.vendorheader) + SIZEOF(.header) + SIZEOF(.flash) + SIZEOF(.data) ; +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + . = 1K; + . = ALIGN(CODE_ALIGNMENT); + } >FLASH AT>FLASH + + .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .stack : ALIGN(8) { + . = 8K; /* Exactly 6k allocated for stack. Overflow causes MemManage fault (when using MPU). */ + } >CCMRAM_STACK + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >CCMRAM AT>FLASH + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >CCMRAM + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM + + .fb : ALIGN(4) { + *(.fb1*); + . = ALIGN(4); + } >CCMRAM_FB + + .boot_args : ALIGN(8) { + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS + + /DISCARD/ : { + *(.ARM.exidx*); + } + +} diff --git a/core/embed/trezorhal/stm32f4/linker/memory.ld b/core/embed/trezorhal/stm32f4/linker/memory.ld new file mode 100644 index 00000000000..edb57837b69 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/linker/memory.ld @@ -0,0 +1,6 @@ + MCU_FLASH_ORIGIN = 0x08000000; + MCU_FLASH_SIZE = 2M; + MCU_CCMRAM = 0x10000000; + MCU_CCMRAM_SIZE = 64K; + MCU_SRAM = 0x20000000; + MCU_SRAM_SIZE = 192K; diff --git a/core/embed/prodtest/memory_stm32f4.ld b/core/embed/trezorhal/stm32f4/linker/prodtest.ld similarity index 53% rename from core/embed/prodtest/memory_stm32f4.ld rename to core/embed/trezorhal/stm32f4/linker/prodtest.ld index 4553af4e5a6..2d8f15e94dc 100644 --- a/core/embed/prodtest/memory_stm32f4.ld +++ b/core/embed/trezorhal/stm32f4/linker/prodtest.ld @@ -1,12 +1,12 @@ -/* TREZORv2 firmware linker script */ +INCLUDE "./embed/trezorhal/stm32f4/linker/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x08040000, LENGTH = 768K - CCMRAM (wal) : ORIGIN = 0x10000000, LENGTH = 64K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x1000FF00, LENGTH = 0x100 - SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K + FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_P1_IMAGE_MAXSIZE + CCMRAM (wal) : ORIGIN = MCU_CCMRAM, LENGTH = MCU_CCMRAM_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE } main_stack_base = ORIGIN(SRAM) + LENGTH(SRAM); /* 8-byte aligned full descending stack */ @@ -17,26 +17,34 @@ _estack = main_stack_base; 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 */ -ccmram_start = ORIGIN(CCMRAM); -ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); +_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); -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); -_ram_start = sram_start; -_ram_end = sram_end; - _codelen = SIZEOF(.flash) + SIZEOF(.data); _flash_start = ORIGIN(FLASH); _flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); SECTIONS { .vendorheader : ALIGN(4) { @@ -47,7 +55,7 @@ SECTIONS { KEEP(*(.header)); } >FLASH AT>FLASH - .flash : ALIGN(512) { + .flash : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); @@ -70,11 +78,6 @@ SECTIONS { . = ALIGN(4); } >SRAM - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram_end - 16K); /* this explicitly sets the end of the heap effectively giving the stack at most 16K */ - } >SRAM - .stack : ALIGN(8) { . = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */ } >SRAM diff --git a/core/embed/trezorhal/stm32f4/mpu.c b/core/embed/trezorhal/stm32f4/mpu.c index 72f593d7212..281bb26b0f6 100644 --- a/core/embed/trezorhal/stm32f4/mpu.c +++ b/core/embed/trezorhal/stm32f4/mpu.c @@ -69,6 +69,14 @@ mpu_driver_t g_mpu_driver = { .mode = MPU_MODE_DISABLED, }; +#define SRAM_SIZE (192 * 1024) + +#define KERNEL_STACK_START (CCMDATARAM_BASE) +#define KERNEL_CCMRAM_START (CCMDATARAM_END + 1 - KERNEL_CCMRAM_SIZE) +#define KERNEL_SRAM_START (SRAM1_BASE + SRAM_SIZE - KERNEL_SRAM_SIZE) + +#define KERNEL_CCMRAM_FB_START (KERNEL_CCMRAM_START - KERNEL_FRAMEBUFFER_SIZE) + static void mpu_init_fixed_regions(void) { // Regions #0 to #4 are fixed for all targets @@ -121,10 +129,9 @@ static void mpu_init_fixed_regions(void) { // All SRAM (Unprivileged, Read-Write, Non-Executable) // Subregion: 192KB = 256KB except 2/8 at end SET_REGION( 3, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS ); - // Kernel RAM (Privileged, Read-Write, Non-Executable) - // TODO: !@# - // SET_REGION( 4, ..., SIZE_xxx, 0xXX, ATTR_SRAM, PRIV_RW ); - DIS_REGION( 4 ); + // Kernel CCMRAM (Privileged, Read-Write, Non-Executable) + // SubRegion: 8KB at the beginning + 16KB at the end of 64KB CCMRAM + SET_REGION( 4, CCMDATARAM_BASE, SIZE_64KB, 0x3E, SRAM, PRIV_RW ); // clang-format on #endif #ifdef FIRMWARE @@ -266,6 +273,20 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { SET_REGION( 6, 0x1FFEC000, SIZE_1KB, 0x00, FLASH_DATA, PRIV_RO ); break; + case MPU_MODE_STORAGE: + // Storage in the Flash Bank #1 (Privileged, Read-Write, Non-Executable) + SET_REGION( 5, FLASH_BASE + 0x10000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW ); + // Storage in the Flash Bank #2 (Privileged, Read-Write, Non-Executable) + SET_REGION( 6, FLASH_BASE + 0x110000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW ); + break; + + case MPU_MODE_KERNEL_SRAM: + DIS_REGION( 5 ); + // Kernel data in DMA accessible SRAM (Privileged, Read-Write, Non-Executable) + // (overlaps with unprivileged SRAM region) + SET_REGION( 6, SRAM_BASE, SIZE_1KB, 0x00, SRAM, PRIV_RW ); + break; + case MPU_MODE_UNUSED_FLASH: // Unused Flash Area #1 (Privileged, Read-Write, Non-Executable) SET_REGION( 5, FLASH_BASE + 0x00C000, SIZE_16KB, 0x00, FLASH_DATA, PRIV_RW ); @@ -284,14 +305,17 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { case MPU_MODE_ASSETS: DIS_REGION( 5 ); // Assets (Privileged, Read-Write, Non-Executable) - SET_REGION( 6, FLASH_BASE + 0x108000, SIZE_32KB, 0x00, FLASH_DATA, PRIV_RW ); + // Subregion: 32KB = 64KB except 2/8 at start and 2/8 at end + SET_REGION( 6, FLASH_BASE + 0x104000, SIZE_64KB, 0xC3, FLASH_DATA, PRIV_RW ); break; case MPU_MODE_APP: - // Unused (maybe privileged kernel code in the future) - DIS_REGION( 5 ); + // Kernel data in DMA accessible SRAM (Privileged, Read-Write, Non-Executable) + // (overlaps with unprivileged SRAM region) + SET_REGION( 5, SRAM_BASE, SIZE_1KB, 0x00, SRAM, PRIV_RW ); // Assets (Unprivileged, Read-Only, Non-Executable) - SET_REGION( 6, FLASH_BASE + 0x108000, SIZE_32KB, 0x00, FLASH_DATA, PRIV_RO_URO ); + // Subregion: 32KB = 64KB except 2/8 at start and 2/8 at end + SET_REGION( 6, FLASH_BASE + 0x104000, SIZE_64KB, 0xC3, FLASH_DATA, PRIV_RO_URO ); break; #else @@ -304,8 +328,9 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { break; case MPU_MODE_APP: - // Unused (maybe privileged kernel code in the future) - DIS_REGION( 5 ); + // Kernel data in DMA accessible SRAM (Privileged, Read-Write, Non-Executable) + // (overlaps with unprivileged SRAM region) + SET_REGION( 5, SRAM_BASE, SIZE_1KB, 0x00, SRAM, PRIV_RW ); // Assets (Unprivileged, Read-Only, Non-Executable) // Subregion: 48KB = 64KB except 2/8 at end SET_REGION( 6, FLASH_BASE + 0x100000, SIZE_64KB, 0xC0, FLASH_DATA, PRIV_RO_URO ); @@ -313,13 +338,6 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { #endif - case MPU_MODE_STORAGE: - // Storage in the Flash Bank #1 (Privileged, Read-Write, Non-Executable) - SET_REGION( 5, FLASH_BASE + 0x10000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW ); - // Storage in the Flash Bank #2 (Privileged, Read-Write, Non-Executable) - SET_REGION( 6, FLASH_BASE + 0x110000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW ); - break; - default: DIS_REGION( 5 ); DIS_REGION( 6 ); @@ -331,6 +349,13 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { // clang-format off switch (mode) { +#ifdef TREZOR_MODEL_DISC1 + default: + // All Peripherals (Unprivileged, Read-Write, Non-Executable) + // SDRAM + SET_REGION( 7, 0x00000000, SIZE_4GB, 0xBB, SRAM, FULL_ACCESS ); + break; +#else case MPU_MODE_APP: // Dma2D (Unprivileged, Read-Write, Non-Executable) // 3KB = 4KB except 1/4 at end @@ -340,6 +365,7 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { // All Peripherals (Privileged, Read-Write, Non-Executable) SET_REGION( 7, PERIPH_BASE, SIZE_1GB, 0x00, PERIPH, PRIV_RW ); break; +#endif } // clang-format on diff --git a/core/embed/trezorhal/stm32f4/sdram.c b/core/embed/trezorhal/stm32f4/sdram.c index 7c32bb1cf07..3cc9360f4ed 100644 --- a/core/embed/trezorhal/stm32f4/sdram.c +++ b/core/embed/trezorhal/stm32f4/sdram.c @@ -16,10 +16,12 @@ * ****************************************************************************** */ +#ifdef KERNEL_MODE /* Includes ------------------------------------------------------------------*/ #include "sdram.h" #include "irq.h" +#include "mpu.h" /** @addtogroup BSP * @{ @@ -90,6 +92,8 @@ void BSP_SDRAM_MspInit(SDRAM_HandleTypeDef *hsdram, void *Params); void sdram_init(void) { static uint8_t sdramstatus = SDRAM_ERROR; + mpu_mode_t mode = mpu_reconfig(MPU_MODE_FSMC_REGS); + /* SDRAM device configuration */ SdramHandle.Instance = FMC_SDRAM_DEVICE; @@ -137,6 +141,8 @@ void sdram_init(void) { /* SDRAM initialization sequence */ BSP_SDRAM_Initialization_sequence(REFRESH_COUNT); + mpu_restore(mode); + (void)sdramstatus; } @@ -444,3 +450,5 @@ void BSP_SDRAM_MspDeInit(SDRAM_HandleTypeDef *hsdram, void *Params) { /** * @} */ + +#endif diff --git a/core/embed/trezorhal/stm32f4/secret.c b/core/embed/trezorhal/stm32f4/secret.c index 0f6f92ef637..175cb253966 100644 --- a/core/embed/trezorhal/stm32f4/secret.c +++ b/core/embed/trezorhal/stm32f4/secret.c @@ -133,4 +133,4 @@ void secret_prepare_fw(secbool allow_run_with_secret, secbool _trust_all) { #endif } -#endif // KERNEL_MODE \ No newline at end of file +#endif // KERNEL_MODE diff --git a/core/embed/boardloader/startup_stm32f4.s b/core/embed/trezorhal/stm32f4/startup_stage_0.s similarity index 63% rename from core/embed/boardloader/startup_stm32f4.s rename to core/embed/trezorhal/stm32f4/startup_stage_0.s index 9533d932f93..b255baf3723 100644 --- a/core/embed/boardloader/startup_stm32f4.s +++ b/core/embed/trezorhal/stm32f4/startup_stage_0.s @@ -20,25 +20,21 @@ reset_handler: // wipe memory to remove any possible vestiges of sensitive data // use unpredictable value as a defense against side-channels - ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM 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, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - mov r2, r4 // r2 - the word-sized value to be written + 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 r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM - ldr r2, =0 // r2 - the word-sized value to be written + 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, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written + ldr r0, =_startup_clear_ram_1_start + ldr r1, =_startup_clear_ram_1_end bl memset_reg // copy data in from flash diff --git a/core/embed/bootloader/startup_stm32f4.s b/core/embed/trezorhal/stm32f4/startup_stage_1.s similarity index 73% rename from core/embed/bootloader/startup_stm32f4.s rename to core/embed/trezorhal/stm32f4/startup_stage_1.s index 96ad4d3ae6b..72a4cc8fab0 100644 --- a/core/embed/bootloader/startup_stm32f4.s +++ b/core/embed/trezorhal/stm32f4/startup_stage_1.s @@ -6,14 +6,12 @@ .type reset_handler, STT_FUNC reset_handler: // setup environment for subsequent stage of code - ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte where BOOT_ARGS region starts - ldr r2, =0 // r2 - the word-sized value to be written + 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, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written + ldr r0, =_startup_clear_ram_1_start + ldr r1, =_startup_clear_ram_1_end bl memset_reg // copy data in from flash diff --git a/core/embed/bootloader_ci/startup_stm32f4.s b/core/embed/trezorhal/stm32f4/startup_stage_2.s similarity index 69% rename from core/embed/bootloader_ci/startup_stm32f4.s rename to core/embed/trezorhal/stm32f4/startup_stage_2.s index 59a80d3c183..e08f0de48c3 100644 --- a/core/embed/bootloader_ci/startup_stm32f4.s +++ b/core/embed/trezorhal/stm32f4/startup_stage_2.s @@ -6,14 +6,12 @@ .type reset_handler, STT_FUNC reset_handler: // setup environment for subsequent stage of code - ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte where BOOT_ARGS region starts - ldr r2, =0 // r2 - the word-sized value to be written + 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, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written + ldr r0, =_startup_clear_ram_1_start + ldr r1, =_startup_clear_ram_1_end bl memset_reg // copy data in from flash diff --git a/core/embed/coreapp/startup_stm32f4.S b/core/embed/trezorhal/stm32f4/startup_stage_4.s similarity index 100% rename from core/embed/coreapp/startup_stm32f4.S rename to core/embed/trezorhal/stm32f4/startup_stage_4.s diff --git a/core/embed/trezorhal/stm32f4/syscall_dispatch.c b/core/embed/trezorhal/stm32f4/syscall_dispatch.c index c4dafbb3705..6993c2ce418 100644 --- a/core/embed/trezorhal/stm32f4/syscall_dispatch.c +++ b/core/embed/trezorhal/stm32f4/syscall_dispatch.c @@ -19,6 +19,8 @@ #include STM32_HAL_H +#include TREZOR_BOARD + #include "syscall.h" #include "bootutils.h" @@ -162,6 +164,16 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args, case SYSCALL_DISPLAY_WAIT_FOR_SYNC: { display_wait_for_sync(); } break; +#endif + case SYSCALL_DISPLAY_FILL: { + const gfx_bitblt_t *bb = (const gfx_bitblt_t *)args[0]; + display_fill(bb); + } break; +#ifdef USE_RGB_COLORS + case SYSCALL_DISPLAY_COPY_RGB565: { + const gfx_bitblt_t *bb = (const gfx_bitblt_t *)args[0]; + display_copy_rgb565(bb); + } break; #endif case SYSCALL_DISPLAY_REFRESH: { display_refresh(); diff --git a/core/embed/trezorhal/stm32f4/syscall_numbers.h b/core/embed/trezorhal/stm32f4/syscall_numbers.h index 4e602032eeb..2341d02ed7a 100644 --- a/core/embed/trezorhal/stm32f4/syscall_numbers.h +++ b/core/embed/trezorhal/stm32f4/syscall_numbers.h @@ -49,6 +49,8 @@ typedef enum { SYSCALL_DISPLAY_GET_FB_INFO, SYSCALL_DISPLAY_WAIT_FOR_SYNC, SYSCALL_DISPLAY_REFRESH, + SYSCALL_DISPLAY_FILL, + SYSCALL_DISPLAY_COPY_RGB565, SYSCALL_USB_INIT, SYSCALL_USB_DEINIT, @@ -147,4 +149,4 @@ typedef enum { } syscall_number_t; -#endif // SYSCALL_NUMBERS_H \ No newline at end of file +#endif // SYSCALL_NUMBERS_H diff --git a/core/embed/trezorhal/stm32f4/syscall_stubs.c b/core/embed/trezorhal/stm32f4/syscall_stubs.c index 10fc13cd3dc..91f706d4343 100644 --- a/core/embed/trezorhal/stm32f4/syscall_stubs.c +++ b/core/embed/trezorhal/stm32f4/syscall_stubs.c @@ -159,8 +159,17 @@ display_fb_info_t display_get_frame_buffer(void) { void display_wait_for_sync(void) { syscall_invoke0(SYSCALL_DISPLAY_WAIT_FOR_SYNC); } + #endif +void display_fill(const gfx_bitblt_t *bb) { + syscall_invoke1((uint32_t)bb, SYSCALL_DISPLAY_FILL); +} + +void display_copy_rgb565(const gfx_bitblt_t *bb) { + syscall_invoke1((uint32_t)bb, SYSCALL_DISPLAY_COPY_RGB565); +} + void display_refresh(void) { syscall_invoke0(SYSCALL_DISPLAY_REFRESH); } // ============================================================================= diff --git a/core/embed/trezorhal/stm32f4/touch/stmpe811.c b/core/embed/trezorhal/stm32f4/touch/stmpe811.c index 8fc25092b1c..3d3003999ad 100644 --- a/core/embed/trezorhal/stm32f4/touch/stmpe811.c +++ b/core/embed/trezorhal/stm32f4/touch/stmpe811.c @@ -20,6 +20,8 @@ #include STM32_HAL_H #include TREZOR_BOARD +#ifdef KERNEL_MODE + #include #include "common.h" @@ -691,3 +693,5 @@ uint32_t touch_get_event(void) { return event; } + +#endif diff --git a/core/embed/trezorhal/stm32f4/util.S b/core/embed/trezorhal/stm32f4/util.S index 94eae168aff..b01f5ee1a07 100644 --- a/core/embed/trezorhal/stm32f4/util.S +++ b/core/embed/trezorhal/stm32f4/util.S @@ -2,6 +2,8 @@ .text +#ifdef KERNEL_MODE + .global memset_reg .type memset_reg, STT_FUNC memset_reg: @@ -10,10 +12,13 @@ memset_reg: // 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 @@ -42,13 +47,12 @@ jump_to_with_flag: cpsid f // wipe memory at the end of the current stage of code bl clear_otg_hs_memory - ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =boot_args_start // r1 - point to byte after the end of CCMRAM - ldr r2, =0 // r2 - the word-sized value to be written + 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, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written + 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 @@ -98,13 +102,12 @@ shutdown_privileged: mov r11, r0 mov r12, r0 ldr lr, =0xffffffff - ldr r0, =ccmram_start - ldr r1, =ccmram_end - // set to value in r2 + + ldr r0, =_shutdown_clear_ram_0_start + ldr r1, =_shutdown_clear_ram_0_end bl memset_reg - ldr r0, =sram_start - ldr r1, =sram_end - // set to value in r2 + 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 @@ -112,4 +115,6 @@ shutdown_privileged: ldr r0, =0 b . // loop forever +#endif + .end diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c index af3ff91e448..412e359f171 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c @@ -286,8 +286,6 @@ void display_ensure_refreshed(void) { #endif } -#endif // KERNEL_MODE - void display_fill(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); @@ -343,3 +341,5 @@ void display_copy_mono4(const gfx_bitblt_t *bb) { gfx_rgb565_copy_mono4(&bb_new); } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c index 8976f552bca..5f237af58da 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_io.c @@ -24,14 +24,14 @@ #include "irq.h" #include "mpu.h" -#ifdef KERNEL_MODE - __IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS = (__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE); __IO DISP_MEM_TYPE *const DISPLAY_DATA_ADDRESS = (__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE | (DISPLAY_ADDR_SHIFT << DISPLAY_MEMORY_PIN)); +#ifdef KERNEL_MODE + void display_io_init_gpio(void) { // init peripherals __HAL_RCC_GPIOE_CLK_ENABLE(); diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c index c2f4c7e166f..83eba001c84 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_nofb.c @@ -51,8 +51,6 @@ static inline void set_window(const gfx_bitblt_t* bb) { bb->dst_y + bb->height + 1); } -#endif // KERNEL_MODE - // For future notice, if we ever want to do a new model using progressive // rendering. // @@ -122,3 +120,5 @@ void display_copy_mono4(const gfx_bitblt_t* bb) { src_row += bb->src_stride / sizeof(*src_row); } } + +#endif // KERNEL_MODE diff --git a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c index 24e13a99852..1198f897b84 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c @@ -23,6 +23,8 @@ #include TREZOR_BOARD #include STM32_HAL_H +#ifdef KERNEL_MODE + #include "display_internal.h" #include "ili9341_spi.h" #include "xdisplay.h" @@ -198,3 +200,5 @@ void display_copy_mono4(const gfx_bitblt_t *bb) { gfx_rgb565_copy_mono4(&bb_new); } + +#endif diff --git a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c index 40b99e6f74c..bdcf47157b0 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c @@ -31,6 +31,7 @@ #include "consumption_mask.h" #endif +#ifdef KERNEL_MODE #if (DISPLAY_RESX != 128) || (DISPLAY_RESY != 64) #error "Incompatible display resolution" #endif @@ -38,7 +39,9 @@ // This file implements display driver for monochromatic display V-2864KSWEG01 // with 128x64 resolution connected to CPU via SPI interface. // -// This type of display is used with T3T1 model (Trezor TS3) +// This type of display is used with T3B1 model (Trezor TS3) + +__attribute__((section(".fb1"))) uint8_t framebuf[DISPLAY_RESX * DISPLAY_RESY]; // Display driver context. typedef struct { @@ -47,7 +50,7 @@ typedef struct { // SPI driver instance SPI_HandleTypeDef spi; // Frame buffer (8-bit Mono) - uint8_t framebuf[DISPLAY_RESX * DISPLAY_RESY]; + uint8_t *framebuf; // Current display orientation (0 or 180) int orientation_angle; // Current backlight level ranging from 0 to 255 @@ -233,6 +236,7 @@ void display_init(display_content_mode_t mode) { memset(drv, 0, sizeof(display_driver_t)); drv->backlight_level = 255; + drv->framebuf = framebuf; if (mode == DISPLAY_RESET_CONTENT) { OLED_DC_CLK_ENA(); @@ -391,29 +395,31 @@ void display_refresh(void) { } void display_fill(const gfx_bitblt_t *bb) { - display_driver_t *drv = &g_display_driver; + display_fb_info_t fb = display_get_frame_buffer(); - if (!drv->initialized) { + if (fb.ptr == NULL) { return; } gfx_bitblt_t bb_new = *bb; - bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; + bb_new.dst_row = &(((uint8_t *)fb.ptr)[DISPLAY_RESX * bb_new.dst_y]); bb_new.dst_stride = DISPLAY_RESX; gfx_mono8_fill(&bb_new); } void display_copy_mono1p(const gfx_bitblt_t *bb) { - display_driver_t *drv = &g_display_driver; + display_fb_info_t fb = display_get_frame_buffer(); - if (!drv->initialized) { + if (fb.ptr == NULL) { return; } gfx_bitblt_t bb_new = *bb; - bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; + bb_new.dst_row = &(((uint8_t *)fb.ptr)[DISPLAY_RESX * bb_new.dst_y]); bb_new.dst_stride = DISPLAY_RESX; gfx_mono8_copy_mono1p(&bb_new); } + +#endif diff --git a/core/embed/trezorhal/stm32u5/limited_util.S b/core/embed/trezorhal/stm32u5/limited_util.S index c9004fd4f2a..0c7cc3c2efb 100644 --- a/core/embed/trezorhal/stm32u5/limited_util.S +++ b/core/embed/trezorhal/stm32u5/limited_util.S @@ -35,23 +35,14 @@ jump_to: 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, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + ldr r0, =_handoff_clear_ram_0_start + ldr r1, =_handoff_clear_ram_0_end bl memset_reg - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + ldr r0, =_handoff_clear_ram_1_start + ldr r1, =_handoff_clear_ram_1_end bl memset_reg - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + ldr r0, =_handoff_clear_ram_2_start + ldr r1, =_handoff_clear_ram_2_end bl memset_reg mov lr, r4 @@ -104,26 +95,17 @@ shutdown_privileged: mov r12, r0 ldr lr, =0xffffffff - ldr r0, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM + ldr r0, =_shutdown_clear_ram_0_start + ldr r1, =_shutdown_clear_ram_0_end bl memset_reg - ldr r0, =boot_args_start // r0 - point to beginning of boot args - ldr r1, =boot_args_end // r1 - point to byte after the end of boot args + ldr r0, =_shutdown_clear_ram_1_start + ldr r1, =_shutdown_clear_ram_1_end bl memset_reg - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer + ldr r0, =_shutdown_clear_ram_2_start + ldr r1, =_shutdown_clear_ram_2_end bl memset_reg - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + ldr r0, =_shutdown_clear_ram_3_start + ldr r1, =_shutdown_clear_ram_3_end bl memset_reg ldr r0, =1 diff --git a/core/embed/boardloader/memory_stm32u58.ld b/core/embed/trezorhal/stm32u5/linker/u58/boardloader.ld similarity index 51% rename from core/embed/boardloader/memory_stm32u58.ld rename to core/embed/trezorhal/stm32u5/linker/u58/boardloader.ld index 51aa0845c32..ca7bac1ee69 100644 --- a/core/embed/boardloader/memory_stm32u58.ld +++ b/core/embed/trezorhal/stm32u5/linker/u58/boardloader.ld @@ -1,16 +1,16 @@ -/* Trezor v2 boardloader linker script */ +INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x0C004000, LENGTH = 48K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 512K - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K + FLASH (rx) : ORIGIN = BOARDLOADER_START, LENGTH = BOARDLOADER_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE } main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ @@ -21,6 +21,8 @@ _estack = main_stack_base; 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); @@ -28,27 +30,37 @@ confidential_vma = ADDR(.confidential); confidential_size = SIZEOF(.confidential); /* used by the startup code to wipe memory */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); +_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_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 - BOOTARGS_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 = MCU_SRAM6 + MCU_SRAM6_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; /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); SECTIONS { - .vector_table : ALIGN(512) { + .vector_table : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); } >FLASH AT>FLASH @@ -108,5 +120,5 @@ SECTIONS { /* Hard-coded address for capabilities structure */ - .capabilities 0x0C00FF00 : {KEEP(*(.capabilities_section))} + .capabilities BOARD_CAPABILITIES_ADDR : {KEEP(*(.capabilities_section))} } diff --git a/core/embed/bootloader/memory_stm32u58.ld b/core/embed/trezorhal/stm32u5/linker/u58/bootloader.ld similarity index 52% rename from core/embed/bootloader/memory_stm32u58.ld rename to core/embed/trezorhal/stm32u5/linker/u58/bootloader.ld index 6711c5c4b41..e46251e96c4 100644 --- a/core/embed/bootloader/memory_stm32u58.ld +++ b/core/embed/trezorhal/stm32u5/linker/u58/bootloader.ld @@ -1,16 +1,16 @@ -/* Trezor v2 bootloader linker script */ +INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 512K - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K + FLASH (rx) : ORIGIN = BOOTLOADER_START, LENGTH = BOOTLOADER_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE } main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ @@ -21,6 +21,8 @@ _estack = main_stack_base; 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); @@ -28,20 +30,30 @@ confidential_vma = ADDR(.confidential); confidential_size = SIZEOF(.confidential); /* used by the startup code to wipe memory */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); +_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_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 = MCU_SRAM6 + MCU_SRAM6_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; /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); @@ -54,7 +66,7 @@ SECTIONS { KEEP(*(.header)); } >FLASH AT>FLASH - .flash : ALIGN(512) { + .flash : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); diff --git a/core/embed/coreapp/memory_T3T1.ld b/core/embed/trezorhal/stm32u5/linker/u58/coreapp.ld similarity index 54% rename from core/embed/coreapp/memory_T3T1.ld rename to core/embed/trezorhal/stm32u5/linker/u58/coreapp.ld index 810877697d2..1542e781ae4 100644 --- a/core/embed/coreapp/memory_T3T1.ld +++ b/core/embed/trezorhal/stm32u5/linker/u58/coreapp.ld @@ -1,16 +1,15 @@ -/* TREZORv2 firmware linker script */ +INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000 + 0x28000, LENGTH = 1664K - 0x28000 - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 16K - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000 + 8K, LENGTH = 64K - 8K - SRAM3 (wal) : ORIGIN = 0x30040000 + 0x38400, LENGTH = 512K - 0x38400 - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K + FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = FIRMWARE_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - KERNEL_SRAM1_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2 + KERNEL_SRAM2_SIZE, LENGTH = MCU_SRAM2_SIZE - KERNEL_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3 + KERNEL_SRAM3_SIZE, LENGTH = MCU_SRAM3_SIZE - KERNEL_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = 0K /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = 0K /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = 0K /* not allocated to coreapp */ } main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ @@ -22,32 +21,14 @@ _stack_size = SIZEOF(.stack); 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); _flash_end = ORIGIN(FLASH) + LENGTH(FLASH); @@ -61,9 +42,12 @@ SECTIONS { .header : ALIGN(4) { KEEP(*(.header)); + . = ALIGN(CODE_ALIGNMENT); } >FLASH AT>FLASH - .flash : ALIGN(512) { + .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.kernel)); + . = ALIGN(512); KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); @@ -103,13 +87,6 @@ SECTIONS { .heap : ALIGN(4) { . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram3_end); /* this explicitly sets the end of the heap */ + . = ABSOLUTE(ORIGIN(SRAM3) + LENGTH(SRAM3)); /* this explicitly sets the end of the heap */ } >SRAM3 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS } diff --git a/core/embed/firmware/memory_T3T1.ld b/core/embed/trezorhal/stm32u5/linker/u58/firmware.ld similarity index 60% rename from core/embed/firmware/memory_T3T1.ld rename to core/embed/trezorhal/stm32u5/linker/u58/firmware.ld index 9bbf390476d..86d28950350 100644 --- a/core/embed/firmware/memory_T3T1.ld +++ b/core/embed/trezorhal/stm32u5/linker/u58/firmware.ld @@ -1,16 +1,16 @@ -/* TREZORv2 firmware linker script */ +INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 1664K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 512K - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K + FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE } main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ @@ -21,27 +21,32 @@ _estack = main_stack_base; 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 */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); +/* used by the startup/jump code to wipe memory */ +_handoff_clear_ram_0_start = ORIGIN(SRAM1); +_handoff_clear_ram_0_end = ORIGIN(BOOT_ARGS); +_handoff_clear_ram_1_start = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); +_handoff_clear_ram_1_end = ORIGIN(SRAM6)+ LENGTH(SRAM6); +_handoff_clear_ram_2_start = ORIGIN(SRAM4); +_handoff_clear_ram_2_end = ORIGIN(SRAM4) + LENGTH(SRAM4); + +/* used by the shutdown code to wipe memory */ +_shutdown_clear_ram_0_start = ORIGIN(SRAM1); +_shutdown_clear_ram_0_end = ORIGIN(SRAM6)+ LENGTH(SRAM6); +_shutdown_clear_ram_1_start = ORIGIN(SRAM4); +_shutdown_clear_ram_1_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +_shutdown_clear_ram_2_start = 0; +_shutdown_clear_ram_2_end = 0; +_shutdown_clear_ram_3_start = 0; +_shutdown_clear_ram_3_end = 0; + /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); @@ -62,7 +67,7 @@ SECTIONS { KEEP(*(.header)); } >FLASH AT>FLASH - .flash : ALIGN(512) { + .flash : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); diff --git a/core/embed/trezorhal/stm32u5/linker/u58/kernel.ld b/core/embed/trezorhal/stm32u5/linker/u58/kernel.ld new file mode 100644 index 00000000000..2ca5972f28e --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u58/kernel.ld @@ -0,0 +1,162 @@ +INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = KERNEL_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM2 - KERNEL_SRAM1_SIZE, LENGTH = KERNEL_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = KERNEL_SRAM2_SIZE - KERNEL_U_RAM_SIZE + SRAM2_U (wal) : ORIGIN = MCU_SRAM2 + KERNEL_SRAM2_SIZE - KERNEL_U_RAM_SIZE, LENGTH = KERNEL_U_RAM_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = KERNEL_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = 0K /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = 0K /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_estack = main_stack_base; + +ustack_base = ORIGIN(SRAM2_U) + 512; +_sustack = ORIGIN(SRAM2_U) + 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; +_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_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 = MCU_SRAM6 + MCU_SRAM6_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; + +/* used by applet cleaning code */ +_coreapp_clear_ram_0_start = MCU_SRAM2 + KERNEL_SRAM2_SIZE; +_coreapp_clear_ram_0_size = MCU_SRAM2_SIZE - KERNEL_SRAM2_SIZE; +_coreapp_clear_ram_1_start = MCU_SRAM3 + KERNEL_SRAM3_SIZE; +_coreapp_clear_ram_1_size = MCU_SRAM3_SIZE - KERNEL_SRAM3_SIZE; + +sram_u_start = ORIGIN(SRAM2_U); +sram_u_end = ORIGIN(SRAM2_U) + LENGTH(SRAM2_U); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = SIZEOF(.vendorheader) + SIZEOF(.header) + SIZEOF(.flash) + SIZEOF(.uflash) + SIZEOF(.data) + SIZEOF(.confidential); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); + +_uflash_start = ADDR(.uflash); +_uflash_end = ADDR(.uflash) + SIZEOF(.uflash); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + . = 1K; + . = ALIGN(CODE_ALIGNMENT); + } >FLASH AT>FLASH + + .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.no_dma_buffers*); + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .stack : ALIGN(8) { + . = 6K; /* Overflow causes UsageFault */ + } >SRAM2 + + /* unprivileged data and stack for SAES */ + .udata : ALIGN(512) { + *(.udata*); + . = ALIGN(256); + . = 256; /* Overflow causes UsageFault */ + } >SRAM2_U + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(CODE_ALIGNMENT); + } >SRAM2 AT>FLASH + + .uflash : ALIGN(512) { + *(.uflash*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .fb : ALIGN(4) { + __fb_start = .; + *(.fb1*); + *(.fb2*); + *(.framebuffer_select*); + __fb_end = .; + . = ALIGN(4); + } >SRAM3 + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM3 + + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/trezorhal/stm32u5/linker/u58/memory.ld b/core/embed/trezorhal/stm32u5/linker/u58/memory.ld new file mode 100644 index 00000000000..59826546fa4 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u58/memory.ld @@ -0,0 +1,18 @@ + + +MCU_FLASH_S_ORIGIN = 0x0C000000; +MCU_FLASH_ORIGIN = 0x08000000; +MCU_FLASH_SIZE = 2M; + +MCU_SRAM1 = 0x30000000; +MCU_SRAM1_SIZE = 192K; +MCU_SRAM2 = 0x30030000; +MCU_SRAM2_SIZE = 64K; +MCU_SRAM3 = 0x30040000; +MCU_SRAM3_SIZE = 512K; +MCU_SRAM4 = 0x38000000; +MCU_SRAM4_SIZE = 16K; +MCU_SRAM5 = 0x30080000; +MCU_SRAM5_SIZE = 0K; /* SRAM5 is not available */ +MCU_SRAM6 = 0x30080000; +MCU_SRAM6_SIZE = 0K ; /* SRAM6 is not available */ diff --git a/core/embed/prodtest/memory_stm32u58.ld b/core/embed/trezorhal/stm32u5/linker/u58/prodtest.ld similarity index 52% rename from core/embed/prodtest/memory_stm32u58.ld rename to core/embed/trezorhal/stm32u5/linker/u58/prodtest.ld index 53c52168659..6cabe9cb558 100644 --- a/core/embed/prodtest/memory_stm32u58.ld +++ b/core/embed/trezorhal/stm32u5/linker/u58/prodtest.ld @@ -1,16 +1,16 @@ -/* TREZORv2 firmware linker script */ +INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 1664K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 0x100 - BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 - SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 64K - SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 512K - SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K + FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE } main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ @@ -21,6 +21,9 @@ _estack = main_stack_base; 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); @@ -28,20 +31,30 @@ confidential_vma = ADDR(.confidential); confidential_size = SIZEOF(.confidential); /* used by the startup code to wipe memory */ -sram1_start = ORIGIN(SRAM1); -sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); -sram2_start = ORIGIN(SRAM2); -sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); -sram3_start = ORIGIN(SRAM3); -sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); -sram4_start = ORIGIN(SRAM4); -sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -sram5_start = ORIGIN(SRAM5); -sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); -sram6_start = ORIGIN(SRAM6); -sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); -bss_start = ADDR(.bss); -bss_end = ADDR(.bss) + SIZEOF(.bss); +_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; +_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_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 = MCU_SRAM6 + MCU_SRAM6_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; /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); @@ -50,8 +63,6 @@ boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); _flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); SECTIONS { .vendorheader : ALIGN(4) { @@ -62,7 +73,7 @@ SECTIONS { KEEP(*(.header)); } >FLASH AT>FLASH - .flash : ALIGN(512) { + .flash : ALIGN(CODE_ALIGNMENT) { KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); @@ -84,20 +95,11 @@ SECTIONS { } .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .data_ccm : ALIGN(4) { *(.no_dma_buffers*); + *(.bss*); . = ALIGN(4); } >SRAM1 - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ - } >SRAM1 - .stack : ALIGN(8) { . = 16K; /* Overflow causes UsageFault */ } >SRAM2 @@ -111,7 +113,6 @@ SECTIONS { __fb_start = .; *(.fb1*); *(.fb2*); - *(.framebuffer_select*); __fb_end = .; . = ALIGN(4); } >SRAM3 diff --git a/core/embed/trezorhal/stm32u5/linker/u5a/boardloader.ld b/core/embed/trezorhal/stm32u5/linker/u5a/boardloader.ld new file mode 100644 index 00000000000..6c455e2641c --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u5a/boardloader.ld @@ -0,0 +1,127 @@ +INCLUDE "./embed/trezorhal/stm32u5/linker/u5a/memory.ld"; + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = BOARDLOADER_START, LENGTH = BOARDLOADER_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_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_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 - BOOTARGS_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 = ORIGIN(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 = ORIGIN(SRAM6)+ LENGTH(SRAM6); +_shutdown_clear_ram_3_start = ORIGIN(SRAM4); +_shutdown_clear_ram_3_end = ORIGIN(SRAM4) + LENGTH(SRAM4); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +SECTIONS { + .vector_table : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.vector_table)); + } >FLASH AT>FLASH + + .text : ALIGN(4) { + *(.text*); + . = ALIGN(4); /* make the section size a multiple of the word size */ + } >FLASH AT>FLASH + + .rodata : ALIGN(4) { + *(.rodata*); + . = ALIGN(4); /* make the section size a multiple of the word size */ + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(8); + } >SRAM5 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM5 + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM5 + + .stack : ALIGN(8) { + . = 16K; /* Overflow causes UsageFault */ + } >SRAM2 + + .confidential : ALIGN(8) { + *(.confidential*); + . = ALIGN(4); + } >SRAM2 AT>FLASH + + .fb1 : ALIGN(4) { + *(.fb1*); + . = ALIGN(4); + } >SRAM1 + + .fb2 : ALIGN(4) { + *(.fb2*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + . = ALIGN(4); + } >SRAM3 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS + + + /* Hard-coded address for capabilities structure */ + .capabilities BOARD_CAPABILITIES_ADDR : {KEEP(*(.capabilities_section))} +} diff --git a/core/embed/trezorhal/stm32u5/linker/u5a/bootloader.ld b/core/embed/trezorhal/stm32u5/linker/u5a/bootloader.ld new file mode 100644 index 00000000000..e031a7062a8 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u5a/bootloader.ld @@ -0,0 +1,128 @@ +INCLUDE "./embed/trezorhal/stm32u5/linker/u5a/memory.ld"; + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = BOOTLOADER_START, LENGTH = BOOTLOADER_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_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_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 = ORIGIN(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 = ORIGIN(SRAM6)+ LENGTH(SRAM6); +_shutdown_clear_ram_3_start = ORIGIN(SRAM4); +_shutdown_clear_ram_3_end = ORIGIN(SRAM4) + LENGTH(SRAM4); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); + +SECTIONS { + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM5 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM5 + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + *(.no_dma_buffers*); + . = ALIGN(4); + } >SRAM5 + + .stack : ALIGN(8) { + . = 16K; /* Overflow causes UsageFault */ + } >SRAM2 + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .fb1 : ALIGN(4) { + __fb_start = .; + *(.fb1*); + . = ALIGN(4); + } >SRAM1 + + .fb2 : ALIGN(4) { + *(.fb2*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + __fb_end = .; + . = ALIGN(4); + } >SRAM3 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/trezorhal/stm32u5/linker/u5a/coreapp.ld b/core/embed/trezorhal/stm32u5/linker/u5a/coreapp.ld new file mode 100644 index 00000000000..73af99e7050 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u5a/coreapp.ld @@ -0,0 +1,92 @@ +INCLUDE "./embed/trezorhal/stm32u5/linker/u5a/memory.ld"; + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = FIRMWARE_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = 0K /* not allocated to coreapp */ + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = 0K /* not allocated to coreapp */ + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = 0K /* not allocated to coreapp */ + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = 0K /* not allocated to coreapp */ + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = 0K /* not allocated to coreapp */ +} + +main_stack_base = ORIGIN(SRAM5) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM5); +_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); + +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.kernel)); + . = ALIGN(512); + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .stack : ALIGN(8) { + . = 32K; /* Overflow causes UsageFault */ + } >SRAM5 + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM5 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.no_dma_buffers*); + *(.bss*); + . = ALIGN(4); + } >SRAM5 + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(512); + } >SRAM5 AT>FLASH + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM5 + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(ORIGIN(SRAM5) + LENGTH(SRAM5)); /* this explicitly sets the end of the heap */ + } >SRAM5 + +} diff --git a/core/embed/trezorhal/stm32u5/linker/u5a/kernel.ld b/core/embed/trezorhal/stm32u5/linker/u5a/kernel.ld new file mode 100644 index 00000000000..31c7652ccf3 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u5a/kernel.ld @@ -0,0 +1,166 @@ +INCLUDE "./embed/trezorhal/stm32u5/linker/u5a/memory.ld"; + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = KERNEL_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE - KERNEL_U_RAM_SIZE + SRAM3_U (wal) : ORIGIN = MCU_SRAM3 + MCU_SRAM3_SIZE - KERNEL_U_RAM_SIZE, LENGTH = KERNEL_U_RAM_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_estack = main_stack_base; + +ustack_base = ORIGIN(SRAM3_U) + 512; +_sustack = ORIGIN(SRAM3_U) + 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; +_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_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 = ORIGIN(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 = ORIGIN(SRAM6)+ LENGTH(SRAM6); +_shutdown_clear_ram_3_start = ORIGIN(SRAM4); +_shutdown_clear_ram_3_end = ORIGIN(SRAM4) + LENGTH(SRAM4); + +/* used by appleet cleaning code */ +_coreapp_clear_ram_0_start = MCU_SRAM5; +_coreapp_clear_ram_0_size = MCU_SRAM5_SIZE; +_coreapp_clear_ram_1_start = 0; +_coreapp_clear_ram_1_size = 0; + + +sram_u_start = ORIGIN(SRAM3_U); +sram_u_end = ORIGIN(SRAM3_U) + LENGTH(SRAM3_U); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = SIZEOF(.vendorheader) + SIZEOF(.header) + SIZEOF(.flash) + SIZEOF(.uflash) + SIZEOF(.data) + SIZEOF(.confidential); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); + +_uflash_start = ADDR(.uflash); +_uflash_end = ADDR(.uflash) + SIZEOF(.uflash); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + . = 1K; + . = ALIGN(CODE_ALIGNMENT); + } >FLASH AT>FLASH + + .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .stack : ALIGN(8) { + . = 12K; /* Overflow causes UsageFault */ + } >SRAM2 + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.no_dma_buffers*); + *(.bss*); + . = ALIGN(4); + } >SRAM2 + + /* unprivileged data and stack for SAES */ + .udata : ALIGN(512) { + *(.udata*); + . = ALIGN(256); + . = 256; /* Overflow causes UsageFault */ + } >SRAM3_U + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .uflash : ALIGN(512) { + *(.uflash*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .fb1 : ALIGN(4) { + *(.fb1*); + . = ALIGN(4); + } >SRAM1 + + .fb2 : ALIGN(4) { + *(.fb2*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + . = ALIGN(4); + } >SRAM3 + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM2 + + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/trezorhal/stm32u5/linker/u5a/memory.ld b/core/embed/trezorhal/stm32u5/linker/u5a/memory.ld new file mode 100644 index 00000000000..157833f9654 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u5a/memory.ld @@ -0,0 +1,18 @@ + + +MCU_FLASH_S_ORIGIN = 0x0C000000; +MCU_FLASH_ORIGIN = 0x08000000; +MCU_FLASH_SIZE = 4M; + +MCU_SRAM1 = 0x30000000; +MCU_SRAM1_SIZE = 768K; +MCU_SRAM2 = 0x300C0000; +MCU_SRAM2_SIZE = 64K; +MCU_SRAM3 = 0x300D0000; +MCU_SRAM3_SIZE = 832K; +MCU_SRAM4 = 0x38000000; +MCU_SRAM4_SIZE = 16K; +MCU_SRAM5 = 0x301A0000; +MCU_SRAM5_SIZE = 832K; +MCU_SRAM6 = 0x30270000; +MCU_SRAM6_SIZE = 0K ; diff --git a/core/embed/trezorhal/stm32u5/linker/u5a/prodtest.ld b/core/embed/trezorhal/stm32u5/linker/u5a/prodtest.ld new file mode 100644 index 00000000000..9fc58c604e9 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/linker/u5a/prodtest.ld @@ -0,0 +1,136 @@ +INCLUDE "./embed/trezorhal/stm32u5/linker/u5a/memory.ld"; + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = KERNEL_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE + BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_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; +_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_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 = ORIGIN(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 = ORIGIN(SRAM6)+ LENGTH(SRAM6); +_shutdown_clear_ram_3_start = ORIGIN(SRAM4); +_shutdown_clear_ram_3_end = ORIGIN(SRAM4) + LENGTH(SRAM4); + + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + . = ALIGN(CODE_ALIGNMENT); + } >FLASH AT>FLASH + + .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .stack : ALIGN(8) { + . = 12K; /* Overflow causes UsageFault */ + } >SRAM2 + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.no_dma_buffers*); + *(.bss*); + . = ALIGN(4); + } >SRAM2 + + .confidential : ALIGN(512) { + *(.confidential*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .fb1 : ALIGN(4) { + *(.fb1*); + . = ALIGN(4); + } >SRAM1 + + .fb2 : ALIGN(4) { + *(.fb2*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + . = ALIGN(4); + } >SRAM3 + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM2 + + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/trezorhal/stm32u5/mpu.c b/core/embed/trezorhal/stm32u5/mpu.c index e0ab0adf1bd..69b3e818569 100644 --- a/core/embed/trezorhal/stm32u5/mpu.c +++ b/core/embed/trezorhal/stm32u5/mpu.c @@ -115,20 +115,19 @@ static void mpu_set_attributes(void) { #define SECRET_START FLASH_BASE #define SECRET_SIZE SIZE_16K -#define BOARDLOADER_SIZE SIZE_48K +#define BOARDLOADER_SIZE BOARDLOADER_IMAGE_MAXSIZE #define BOOTLOADER_SIZE BOOTLOADER_IMAGE_MAXSIZE #define FIRMWARE_SIZE FIRMWARE_IMAGE_MAXSIZE -#define COREAPP_SIZE (FIRMWARE_IMAGE_MAXSIZE - KERNEL_SIZE) #define STORAGE_START \ (FLASH_BASE + SECRET_SIZE + BOARDLOADER_SIZE + BOOTLOADER_SIZE) #define STORAGE_SIZE NORCOW_SECTOR_SIZE* STORAGE_AREAS_COUNT #if defined STM32U5A9xx -#define SRAM_SIZE SIZE_2496K +#define SRAM_SIZE SRAM1_SIZE + SRAM2_SIZE + SRAM3_SIZE + SRAM5_SIZE #elif defined STM32U5G9xx -#define SRAM_SIZE (SIZE_2496K + SIZE_512K) +#define SRAM_SIZE SRAM1_SIZE + SRAM2_SIZE + SRAM3_SIZE + SRAM5_SIZE + SRAM6_SIZE #elif defined STM32U585xx -#define SRAM_SIZE SIZE_768K +#define SRAM_SIZE SRAM1_SIZE + SRAM2_SIZE + SRAM3_SIZE #else #error "Unknown MCU" #endif @@ -150,14 +149,49 @@ static void mpu_set_attributes(void) { // clang-format on -#define KERNEL_RAM_START (SRAM2_BASE - SIZE_16K) -#define KERNEL_RAM_SIZE (SIZE_24K) +#ifdef STM32U585xx +#define KERNEL_RAM_START (SRAM2_BASE - KERNEL_SRAM1_SIZE) +#define KERNEL_RAM_SIZE \ + ((KERNEL_SRAM1_SIZE + KERNEL_SRAM2_SIZE) - KERNEL_U_RAM_SIZE) +#else +#define KERNEL_RAM_START (SRAM1_BASE) +#define KERNEL_RAM_SIZE \ + (SRAM1_SIZE + SRAM2_SIZE + SRAM3_SIZE - KERNEL_U_RAM_SIZE) +#endif + +#ifdef SYSCALL_DISPATCH +extern uint32_t _uflash_start; +extern uint32_t _uflash_end; +#define KERNEL_RAM_U_START (KERNEL_RAM_START + KERNEL_RAM_SIZE) +#define KERNEL_RAM_U_SIZE KERNEL_U_RAM_SIZE +#define KERNEL_FLASH_U_START (uint32_t) & _uflash_start +#define KERNEL_FLASH_U_SIZE ((uint32_t) & _uflash_end - KERNEL_FLASH_U_START) +#else +#define KERNEL_RAM_U_START 0 +#define KERNEL_RAM_U_SIZE 0 +#define KERNEL_FLASH_U_START 0 +#define KERNEL_FLASH_U_SIZE 0 +#endif +extern uint32_t _codelen; +#define KERNEL_SIZE (uint32_t) & _codelen + +#define KERNEL_FLASH_START KERNEL_START +#define KERNEL_FLASH_SIZE (KERNEL_SIZE - KERNEL_U_FLASH_SIZE) + +#define COREAPP_FLASH_START (KERNEL_FLASH_START + KERNEL_SIZE) +#define COREAPP_FLASH_SIZE (FIRMWARE_IMAGE_MAXSIZE - KERNEL_SIZE) + +#ifdef STM32U585xx #define COREAPP_RAM1_START SRAM1_BASE -#define COREAPP_RAM1_SIZE (SIZE_192K - SIZE_16K) +#define COREAPP_RAM1_SIZE (SRAM1_SIZE - KERNEL_SRAM1_SIZE) -#define COREAPP_RAM2_START (SRAM2_BASE + SIZE_8K) -#define COREAPP_RAM2_SIZE (SRAM_SIZE - (SIZE_192K + SIZE_8K)) +#define COREAPP_RAM2_START (SRAM2_BASE + KERNEL_SRAM2_SIZE) +#define COREAPP_RAM2_SIZE (SRAM_SIZE - (SRAM1_SIZE + KERNEL_SRAM2_SIZE)) +#else +#define COREAPP_RAM1_START SRAM5_BASE +#define COREAPP_RAM1_SIZE SRAM5_SIZE +#endif typedef struct { // Set if the driver is initialized @@ -196,12 +230,16 @@ static void mpu_init_fixed_regions(void) { #endif #if defined(KERNEL) // REGION ADDRESS SIZE TYPE WRITE UNPRIV - SET_REGION( 0, KERNEL_START, KERNEL_SIZE, FLASH_CODE, NO, NO ); - SET_REGION( 1, KERNEL_RAM_START, KERNEL_RAM_SIZE, SRAM, YES, NO ); - SET_REGION( 2, COREAPP_START, COREAPP_SIZE, FLASH_CODE, NO, YES ); - SET_REGION( 3, COREAPP_RAM1_START, COREAPP_RAM1_SIZE, SRAM, YES, YES ); - SET_REGION( 4, COREAPP_RAM2_START, COREAPP_RAM2_SIZE, SRAM, YES, YES ); - SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); + SET_REGION( 0, KERNEL_FLASH_START, KERNEL_FLASH_SIZE, FLASH_CODE, NO, NO ); // Kernel Code + SET_REGION( 1, KERNEL_RAM_START, KERNEL_RAM_SIZE, SRAM, YES, NO ); // Kernel RAM + SET_REGION( 2, COREAPP_FLASH_START, COREAPP_FLASH_SIZE, FLASH_CODE, NO, YES ); // CoreApp Code + SET_REGION( 3, COREAPP_RAM1_START, COREAPP_RAM1_SIZE, SRAM, YES, YES ); // CoraApp RAM +#ifdef STM32U585xx + SET_REGION( 4, COREAPP_RAM2_START, COREAPP_RAM2_SIZE, SRAM, YES, YES ); // CoraAPP RAM2 +#else + DIS_REGION( 4 ); +#endif + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface #endif #if defined(FIRMWARE) // REGION ADDRESS SIZE TYPE WRITE UNPRIV @@ -272,6 +310,16 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { HAL_MPU_Disable(); + // Region #5 is banked + + // clang-format off + switch (mode) { + default: + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Peripherals + break; + } + // clang-format on + // Region #6 is banked // clang-format off diff --git a/core/embed/trezorhal/stm32u5/startup_stage_0.s b/core/embed/trezorhal/stm32u5/startup_stage_0.s new file mode 100644 index 00000000000..e237fe57e9b --- /dev/null +++ b/core/embed/trezorhal/stm32u5/startup_stage_0.s @@ -0,0 +1,79 @@ + .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/bootloader/startup_stm32u5.s b/core/embed/trezorhal/stm32u5/startup_stage_1.s similarity index 64% rename from core/embed/bootloader/startup_stm32u5.s rename to core/embed/trezorhal/stm32u5/startup_stage_1.s index ad97873e613..53ba794d391 100644 --- a/core/embed/bootloader/startup_stm32u5.s +++ b/core/embed/trezorhal/stm32u5/startup_stage_1.s @@ -12,29 +12,14 @@ reset_handler: // setup environment for subsequent stage of code ldr r2, =0 // r2 - the word-sized value to be written - - ldr r0, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + ldr r0, =_startup_clear_ram_0_start + ldr r1, =_startup_clear_ram_0_end bl memset_reg - - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + ldr r0, =_startup_clear_ram_1_start + ldr r1, =_startup_clear_ram_1_end bl memset_reg - - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + ldr r0, =_startup_clear_ram_2_start + ldr r1, =_startup_clear_ram_2_end bl memset_reg // copy data in from flash diff --git a/core/embed/bootloader_ci/startup_stm32u5.s b/core/embed/trezorhal/stm32u5/startup_stage_2.s similarity index 61% rename from core/embed/bootloader_ci/startup_stm32u5.s rename to core/embed/trezorhal/stm32u5/startup_stage_2.s index 707b7a320cf..7813166f8ce 100644 --- a/core/embed/bootloader_ci/startup_stm32u5.s +++ b/core/embed/trezorhal/stm32u5/startup_stage_2.s @@ -12,29 +12,14 @@ reset_handler: // setup environment for subsequent stage of code ldr r2, =0 // r2 - the word-sized value to be written - - ldr r0, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + ldr r0, =_startup_clear_ram_0_start + ldr r1, =_startup_clear_ram_0_end bl memset_reg - - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + ldr r0, =_startup_clear_ram_1_start + ldr r1, =_startup_clear_ram_1_end bl memset_reg - - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + ldr r0, =_startup_clear_ram_2_start + ldr r1, =_startup_clear_ram_2_end bl memset_reg // copy data in from flash diff --git a/core/embed/coreapp/startup_stm32u5.S b/core/embed/trezorhal/stm32u5/startup_stage_4.s similarity index 100% rename from core/embed/coreapp/startup_stm32u5.S rename to core/embed/trezorhal/stm32u5/startup_stage_4.s diff --git a/core/embed/trezorhal/stm32u5/touch/sitronix.c b/core/embed/trezorhal/stm32u5/touch/sitronix.c index 4da2aeb1bd6..eb4d127cfca 100644 --- a/core/embed/trezorhal/stm32u5/touch/sitronix.c +++ b/core/embed/trezorhal/stm32u5/touch/sitronix.c @@ -1,6 +1,8 @@ #include STM32_HAL_H #include TREZOR_BOARD +#ifdef KERNEL_MODE + #include "common.h" #include "i2c_bus.h" #include "irq.h" @@ -1314,3 +1316,5 @@ uint32_t touch_get_event(void) { return event; } + +#endif diff --git a/core/embed/trezorhal/stm32u5/util.S b/core/embed/trezorhal/stm32u5/util.S index 06258ded409..65fe4f94d0b 100644 --- a/core/embed/trezorhal/stm32u5/util.S +++ b/core/embed/trezorhal/stm32u5/util.S @@ -37,26 +37,14 @@ jump_to: 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, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + ldr r0, =_handoff_clear_ram_0_start + ldr r1, =_handoff_clear_ram_0_end bl memset_reg - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + ldr r0, =_handoff_clear_ram_1_start + ldr r1, =_handoff_clear_ram_1_end bl memset_reg - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =boot_args_start // r0 - point to beginning of boot args - ldr r1, =boot_args_end // r1 - point to byte after the end of boot args - bl memset_reg - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + ldr r0, =_handoff_clear_ram_2_start + ldr r1, =_handoff_clear_ram_2_end bl memset_reg mov lr, r4 @@ -109,26 +97,17 @@ shutdown_privileged: mov r12, r0 ldr lr, =0xffffffff - ldr r0, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM + ldr r0, =_shutdown_clear_ram_0_start + ldr r1, =_shutdown_clear_ram_0_end bl memset_reg - ldr r0, =boot_args_start // r0 - point to beginning of boot args - ldr r1, =boot_args_end // r1 - point to byte after the end of boot args + ldr r0, =_shutdown_clear_ram_1_start + ldr r1, =_shutdown_clear_ram_1_end bl memset_reg - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer + ldr r0, =_shutdown_clear_ram_2_start + ldr r1, =_shutdown_clear_ram_2_end bl memset_reg - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + ldr r0, =_shutdown_clear_ram_3_start + ldr r1, =_shutdown_clear_ram_3_end bl memset_reg ldr r0, =1 diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c index f39df353c09..714f6ae30f8 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c @@ -30,6 +30,8 @@ #error "Incompatible display resolution" #endif +#ifdef KERNEL_MODE + // Display driver instance display_driver_t g_display_driver = { .initialized = false, @@ -43,6 +45,13 @@ void display_init(display_content_mode_t mode) { } if (mode == DISPLAY_RESET_CONTENT) { + __HAL_RCC_DSI_FORCE_RESET(); + __HAL_RCC_LTDC_FORCE_RESET(); + __HAL_RCC_GFXMMU_FORCE_RESET(); + __HAL_RCC_DSI_RELEASE_RESET(); + __HAL_RCC_LTDC_RELEASE_RESET(); + __HAL_RCC_GFXMMU_RELEASE_RESET(); + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; // Initializes the common periph clock @@ -84,6 +93,14 @@ void display_deinit(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; if (!drv->initialized) { + if (mode == DISPLAY_RESET_CONTENT) { + __HAL_RCC_DSI_FORCE_RESET(); + __HAL_RCC_LTDC_FORCE_RESET(); + __HAL_RCC_GFXMMU_FORCE_RESET(); + __HAL_RCC_DSI_RELEASE_RESET(); + __HAL_RCC_LTDC_RELEASE_RESET(); + __HAL_RCC_GFXMMU_RELEASE_RESET(); + } return; } @@ -198,3 +215,5 @@ void display_copy_mono4(const gfx_bitblt_t *bb) { gfx_rgba8888_copy_mono4(&bb_new); } + +#endif diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c index 598dfc464df..7d96ea80a6f 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c @@ -26,6 +26,8 @@ #include #include "display_internal.h" +#ifdef KERNEL_MODE + // Physical frame buffers in internal SRAM memory __attribute__((section(".fb1"))) ALIGN_32BYTES(uint32_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE]); @@ -91,3 +93,5 @@ void display_refresh(void) { sizeof(physical_frame_buffer_1)); } } + +#endif diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_gfxmmu_lut.h b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_gfxmmu_lut.h index 86528b9d9a4..ac502356d4c 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_gfxmmu_lut.h +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_gfxmmu_lut.h @@ -29,7 +29,7 @@ extern "C" { #define GFXMMU_LUT_LAST 479 #define GFXMMU_LUT_SIZE 480 -uint32_t gfxmmu_lut[2 * GFXMMU_LUT_SIZE] = { +static const uint32_t gfxmmu_lut_config[2 * GFXMMU_LUT_SIZE] = { 0x00413601, // GFXMMU_LUT0L 0x003FFCA0, // GFXMMU_LUT0H 0x00433401, // GFXMMU_LUT1L diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c index 3cac3760f75..e2964798134 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_ltdc_dsi.c @@ -68,6 +68,8 @@ #include "display_internal.h" #include "irq.h" +#ifdef KERNEL_MODE + /* Common Error codes */ #define BSP_ERROR_NONE 0 #define BSP_ERROR_NO_INIT -1 @@ -166,6 +168,9 @@ LTDC_HandleTypeDef hlcd_ltdc = {0}; DSI_HandleTypeDef hlcd_dsi = {0}; static DSI_VidCfgTypeDef DSIVidCfg = {0}; +__attribute__((section(".gfxmmu_table"))) +uint32_t gfxmmu_lut[2 * GFXMMU_LUT_SIZE]; + /** * @} */ @@ -206,6 +211,7 @@ int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation) { memset(&hlcd_ltdc, 0, sizeof(hlcd_ltdc)); memset(&hlcd_dsi, 0, sizeof(hlcd_dsi)); memset(&DSIVidCfg, 0, sizeof(DSIVidCfg)); + memcpy(gfxmmu_lut, gfxmmu_lut_config, sizeof(gfxmmu_lut)); int32_t status = BSP_ERROR_NONE; @@ -1557,3 +1563,5 @@ int32_t BSP_LCD_Reinit(uint32_t Instance) { return status; } + +#endif diff --git a/core/site_scons/models/D002/discovery2.py b/core/site_scons/models/D002/discovery2.py index f6a4272bf76..9a71eaa294f 100644 --- a/core/site_scons/models/D002/discovery2.py +++ b/core/site_scons/models/D002/discovery2.py @@ -18,7 +18,7 @@ def configure( hw_revision = 0 mcu = "STM32U5A9xx" - linker_script = "stm32u5a" + linker_script = """embed/trezorhal/stm32u5/linker/u5a/{target}.ld""" stm32u5_common_files(env, defines, sources, paths) diff --git a/core/site_scons/models/T3B1/trezor_t3b1_revB.py b/core/site_scons/models/T3B1/trezor_t3b1_revB.py index e26b52c71a8..c20b056b737 100644 --- a/core/site_scons/models/T3B1/trezor_t3b1_revB.py +++ b/core/site_scons/models/T3B1/trezor_t3b1_revB.py @@ -23,7 +23,7 @@ def configure( features_available.append("display_mono") mcu = "STM32U585xx" - linker_script = "stm32u58" + linker_script = """embed/trezorhal/stm32u5/linker/u58/{target}.ld""" stm32u5_common_files(env, defines, sources, paths) diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py index 2e68dacc1f8..1195a7143bf 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py @@ -27,7 +27,7 @@ def configure( defines += ["XFRAMEBUFFER"] mcu = "STM32U585xx" - linker_script = "stm32u58" + linker_script = """embed/trezorhal/stm32u5/linker/u58/{target}.ld""" stm32u5_common_files(env, defines, sources, paths) diff --git a/core/site_scons/models/T3T1/trezor_t3t1_v4.py b/core/site_scons/models/T3T1/trezor_t3t1_v4.py index a2f1c7ceee3..63e26c69936 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_v4.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_v4.py @@ -27,7 +27,7 @@ def configure( defines += ["XFRAMEBUFFER"] mcu = "STM32U585xx" - linker_script = "stm32u58" + linker_script = """embed/trezorhal/stm32u5/linker/u58/{target}.ld""" stm32u5_common_files(env, defines, sources, paths) diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index e8e4cb1cd1d..c90b334f155 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -79,4 +79,4 @@ def stm32f4_common_files(env, defines, sources, paths): ] env.get("ENV")["SUFFIX"] = "stm32f4" - env.get("ENV")["LINKER_SCRIPT"] = "stm32f4" + env.get("ENV")["LINKER_SCRIPT"] = """embed/trezorhal/stm32f4/linker/{target}.ld""" diff --git a/core/site_scons/tools.py b/core/site_scons/tools.py index 315ca5cef76..85ac138eb12 100644 --- a/core/site_scons/tools.py +++ b/core/site_scons/tools.py @@ -99,12 +99,12 @@ def get_bindgen_defines( return ",".join(rest_defs) -def embed_binary(obj_program, env, section, target_, file): +def embed_compressed_binary(obj_program, env, section, target_, file, build): _in = f"embedded_{section}.bin.deflated" def redefine_sym(name): src = ( - "_binary_build_firmware_" + f"_binary_build_{build}_" + _in.replace("/", "_").replace(".", "_") + "_" + name @@ -140,3 +140,14 @@ def compress_action(target, source, env): ) env.Depends(obj_program, compress) + + +def embed_raw_binary(obj_program, env, section, target_, file): + obj_program.extend( + env.Command( + target=target_, + source=file, + action="$OBJCOPY -I binary -O elf32-littlearm -B arm" + f" --rename-section .data=.{section}" + " $SOURCE $TARGET", + ) + ) diff --git a/core/tools/README.md b/core/tools/README.md index 14fb0baf735..be1f263054c 100644 --- a/core/tools/README.md +++ b/core/tools/README.md @@ -76,8 +76,9 @@ A Python package that exposes certain functionalities as CLI commands. `headertool` and `combine_firmware` live here, more may be moved or added. -One additional tool is `layout_parser`, which is used to extract memory layout -information from a model `.h` file. +Additional tools are `layout_parser`, which is used to extract memory layout +information from a model `.h` file, and related tool `lsgen` to generate linker script files +from the model `.h`. ### `alloc.py` diff --git a/core/tools/pyproject.toml b/core/tools/pyproject.toml index 125aaf6dd21..ece3ebf6c95 100644 --- a/core/tools/pyproject.toml +++ b/core/tools/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "trezor_core_tools" -version = "0.1.0" +version = "0.1.1" description = "Collection of CLI tools for trezor-core development" authors = ["matejcik "] license = "GPLv3+" @@ -17,4 +17,5 @@ build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] headertool = "trezor_core_tools.headertool:cli" layout_parser = "trezor_core_tools.layout_parser:main" +lsgen = "trezor_core_tools.lsgen:main" combine_firmware = "trezor_core_tools.combine_firmware:main" diff --git a/core/tools/trezor_core_tools/common.py b/core/tools/trezor_core_tools/common.py index 7a4f2f5be7f..74fdb6f6348 100644 --- a/core/tools/trezor_core_tools/common.py +++ b/core/tools/trezor_core_tools/common.py @@ -19,3 +19,7 @@ def get_layout_for_model(model: str) -> Path: model = MODELS_DICT.get(model, model) return MODELS_DIR / model / f"model_{model}.h" + +def get_linkerscript_for_model(model: str) -> Path: + model = MODELS_DICT.get(model, model) + return MODELS_DIR / model / f"memory.ld" diff --git a/core/tools/trezor_core_tools/layout_parser.py b/core/tools/trezor_core_tools/layout_parser.py index 13b2e433039..aec22a1e1ec 100644 --- a/core/tools/trezor_core_tools/layout_parser.py +++ b/core/tools/trezor_core_tools/layout_parser.py @@ -19,7 +19,12 @@ def find_all_values(model: str) -> dict[str, int]: layout = get_layout_for_model(model) values = {} + begin = False for line in open(layout): + if not begin: + if line.startswith("// SHARED"): + begin = True + continue match = re.match(SEARCH_PATTERN, line) if match is not None: name, value = match.groups() diff --git a/core/tools/trezor_core_tools/lsgen.py b/core/tools/trezor_core_tools/lsgen.py new file mode 100644 index 00000000000..36d7d7e7229 --- /dev/null +++ b/core/tools/trezor_core_tools/lsgen.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import click + +from .common import get_linkerscript_for_model, MODELS_DIR +from .layout_parser import find_all_values + + +warning = """/* Auto-generated file, do not edit.*/ + +""" + +@click.command() +@click.option("--check", is_flag=True) +def main(check: bool) -> None: + + models = list(MODELS_DIR.iterdir()) + models = [model for model in models if model.is_dir()] + + for model in models: + values = find_all_values(model.name) + content = warning + input = get_linkerscript_for_model(model.name) + print(f"Processing {input}") + for name, value in values.items(): + content += f"{name} = {hex(value)};\n" + if not check: + input.write_text(content) + else: + actual = input.read_text() + if content != actual: + raise click.ClickException(f"{input} differs from expected") + + +if __name__ == "__main__": + main() diff --git a/poetry.lock b/poetry.lock index 74500faa4f5..4ffb20f24de 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1583,7 +1583,7 @@ url = "python" [[package]] name = "trezor-core-tools" -version = "0.1.0" +version = "0.1.1" description = "Collection of CLI tools for trezor-core development" optional = false python-versions = "^3.8" From 36140cdb5a1fa599e2190801e456c502c594f9bb Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Wed, 4 Sep 2024 11:18:25 +0200 Subject: [PATCH 39/44] fix(core): use secure-unprivileged SAES XOR key for storage encryption [no changelog] --- core/embed/trezorhal/mpu.h | 1 + core/embed/trezorhal/secure_aes.h | 6 +- core/embed/trezorhal/stm32f4/syscall.c | 67 +++++++- core/embed/trezorhal/stm32f4/syscall.h | 11 +- core/embed/trezorhal/stm32u5/mpu.c | 21 ++- core/embed/trezorhal/stm32u5/secret.c | 5 +- core/embed/trezorhal/stm32u5/secure_aes.c | 189 +++++++++++++++++++--- storage/storage.c | 4 +- 8 files changed, 266 insertions(+), 38 deletions(-) diff --git a/core/embed/trezorhal/mpu.h b/core/embed/trezorhal/mpu.h index 895d1331c8c..8729c62e8c7 100644 --- a/core/embed/trezorhal/mpu.h +++ b/core/embed/trezorhal/mpu.h @@ -40,6 +40,7 @@ typedef enum { MPU_MODE_SECRET, // + secret area (privileged RW) MPU_MODE_STORAGE, // + both storage areas (privileged RW) MPU_MODE_ASSETS, // + assets (privileged RW) + MPU_MODE_SAES, // + unprivileged SAES code MPU_MODE_KERNEL_SRAM, // + extra kernel SRAM (STM32F4 Only) (privileged RW) MPU_MODE_UNUSED_FLASH, // + unused flash areas (privileged RW) MPU_MODE_APP, // + unprivileged DMA2D (RW) & Assets (RO) diff --git a/core/embed/trezorhal/secure_aes.h b/core/embed/trezorhal/secure_aes.h index 69eac50dc6c..9849e68c037 100644 --- a/core/embed/trezorhal/secure_aes.h +++ b/core/embed/trezorhal/secure_aes.h @@ -24,10 +24,12 @@ #include #include +// only some of the keys are supported depending on execution environment typedef enum { - SECURE_AES_KEY_DHUK, + SECURE_AES_KEY_DHUK_SP, // secure-privileged SECURE_AES_KEY_BHK, - SECURE_AES_KEY_XORK, + SECURE_AES_KEY_XORK_SP, // secure-privileged + SECURE_AES_KEY_XORK_SN, // secure-nonprivileged } secure_aes_keysel_t; // Initializes secure AES module diff --git a/core/embed/trezorhal/stm32f4/syscall.c b/core/embed/trezorhal/stm32f4/syscall.c index 2846ba68e66..eadac852453 100644 --- a/core/embed/trezorhal/stm32f4/syscall.c +++ b/core/embed/trezorhal/stm32f4/syscall.c @@ -23,7 +23,7 @@ #ifdef SYSCALL_DISPATCH __attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback( - uint32_t arg1, uint32_t arg2, uint32_t arg3, void* callback) { + uint32_t arg1, uint32_t arg2, uint32_t arg3, void *callback) { __asm__ volatile( "push {r1-r12, lr} \n" @@ -71,7 +71,7 @@ __attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback( } uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3, - void* callback) { + void *callback) { mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_APP); uint32_t retval = _invoke_app_callback(args1, arg2, arg3, callback); mpu_reconfig(mpu_mode); @@ -79,7 +79,7 @@ uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3, } __attribute__((naked, no_stack_protector)) void return_from_app_callback( - uint32_t retval, uint32_t* msp) { + uint32_t retval, uint32_t *msp) { __asm__ volatile( "MSR MSP, R1 \n" "POP {R1} \n" @@ -98,4 +98,65 @@ __attribute__((naked, no_stack_protector)) void return_from_app_callback( "BX LR \n"); } +__attribute__((naked, no_stack_protector)) static uint32_t _invoke_unpriv( + uint32_t stack_addr, uint32_t stack_lim, void *callback) { + __asm__ volatile( + "push {r1-r12, lr} \n" + +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) + "mrs r12, PSPLIM \n" // Backup unprivileged stack limit + "push {r12} \n" +#endif + "mrs r12, PSP \n" // Backup unprivileged stack pointer + "push {r12} \n" + + "mov r12, r0 \n" // setup stack for unprivileged call inside + // kernel + "sub r12, r12, #32 \n" + "msr PSP, r12 \n" + "msr PSPLIM, r1 \n" + + "mov r3, #0 \n" + + "mov r4, r3 \n" // Clear registers r4-r11 + "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" + + "str r3, [r12, #0] \n" // r0 + "str r3, [r12, #4] \n" // r1" + "str r3, [r12, #8] \n" // r2" + "str r3, [r12, #12] \n" // r3" + "str r3, [r12, #16] \n" // r12" + "str r3, [r12, #20] \n" // lr" + + "bic r3, r2, #1 \n" + "str r3, [r12, #24] \n" // return address + + "ldr r1, = 0x01000000 \n" + "str r1, [r12, #28] \n" // xPSR + + "vmov r0, s0 \n" // Use FPU instruction to ensure lazy + // stacking + + // return to Secure Thread mode (use Secure PSP) + "ldr lr, = 0xFFFFFFFD \n" + "bx lr \n"); +} + +extern const void _eustack; +extern const void _sustack; + +uint32_t invoke_unpriv(void *func) { + uint32_t *stack = (uint32_t *)&_eustack; + uint32_t *stack_lim = (uint32_t *)&_sustack; + + uint32_t retval = _invoke_unpriv((uint32_t)stack, (uint32_t)stack_lim, func); + return retval; +} + #endif // SYSCALL_DISPATCH diff --git a/core/embed/trezorhal/stm32f4/syscall.h b/core/embed/trezorhal/stm32f4/syscall.h index de64aaa906c..944cd2981df 100644 --- a/core/embed/trezorhal/stm32f4/syscall.h +++ b/core/embed/trezorhal/stm32f4/syscall.h @@ -57,6 +57,13 @@ uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3, // the stack pointer and returns control to the privileged caller. void return_from_app_callback(uint32_t retval, uint32_t* msp); +// Invokes an unprivileged function from privileged mode. +// +// This is a *temporary* helper function used to control the STM32 SAES +// peripheral from unprivileged mode for backward compatibility (due to +// different hardware keys being used in privileged and unprivileged modes). +uint32_t invoke_unpriv(void* func); + #else // KERNEL_MODE static inline uint32_t __attribute__((no_stack_protector)) @@ -199,6 +206,8 @@ syscall_invoke6(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, return ret; } +#endif // KERNEL_MODE + static inline void __attribute__((no_stack_protector)) syscall_return_from_callback(uint32_t retval) { register uint32_t r0 __asm__("r0") = retval; @@ -208,6 +217,4 @@ syscall_return_from_callback(uint32_t retval) { : "memory"); } -#endif // KERNEL_MODE - #endif // TREZORHAL_SYSCALL_H diff --git a/core/embed/trezorhal/stm32u5/mpu.c b/core/embed/trezorhal/stm32u5/mpu.c index 69b3e818569..7cdd1894878 100644 --- a/core/embed/trezorhal/stm32u5/mpu.c +++ b/core/embed/trezorhal/stm32u5/mpu.c @@ -217,7 +217,6 @@ static void mpu_init_fixed_regions(void) { SET_REGION( 2, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_DATA, YES, NO ); SET_REGION( 3, FIRMWARE_START, FIRMWARE_SIZE, FLASH_DATA, YES, NO ); DIS_REGION( 4 ); - SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); #endif #if defined(BOOTLOADER) // REGION ADDRESS SIZE TYPE WRITE UNPRIV @@ -226,7 +225,6 @@ static void mpu_init_fixed_regions(void) { SET_REGION( 2, FIRMWARE_START, FIRMWARE_SIZE, FLASH_DATA, YES, NO ); DIS_REGION( 3 ); DIS_REGION( 4 ); - SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); #endif #if defined(KERNEL) // REGION ADDRESS SIZE TYPE WRITE UNPRIV @@ -239,7 +237,6 @@ static void mpu_init_fixed_regions(void) { #else DIS_REGION( 4 ); #endif - SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface #endif #if defined(FIRMWARE) // REGION ADDRESS SIZE TYPE WRITE UNPRIV @@ -248,7 +245,6 @@ static void mpu_init_fixed_regions(void) { DIS_REGION( 2 ); DIS_REGION( 3 ); DIS_REGION( 4 ); - SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); #endif #if defined(TREZOR_PRODTEST) SET_REGION( 0, FIRMWARE_START, 1024, FLASH_DATA, YES, NO ); @@ -256,11 +252,11 @@ static void mpu_init_fixed_regions(void) { SET_REGION( 2, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); DIS_REGION( 3 ); DIS_REGION( 4 ); - SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); #endif // Regions #6 and #7 are banked + DIS_REGION( 5 ); DIS_REGION( 6 ); DIS_REGION( 7 ); // clang-format on @@ -314,9 +310,12 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { // clang-format off switch (mode) { + case MPU_MODE_SAES: + SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals - SAES, TAMP + break; default: - SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Peripherals - break; + SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface + break; } // clang-format on @@ -349,6 +348,9 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { case MPU_MODE_ASSETS: SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, NO ); break; + case MPU_MODE_SAES: + SET_REGION( 6, KERNEL_FLASH_U_START, KERNEL_FLASH_U_SIZE,FLASH_CODE, NO, YES ); // Unprivileged kernal flash + break; case MPU_MODE_APP: SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, NO, YES ); break; @@ -362,8 +364,11 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) { // clang-format off switch (mode) { - case MPU_MODE_APP: // REGION ADDRESS SIZE TYPE WRITE UNPRIV + case MPU_MODE_SAES: + SET_REGION( 7, KERNEL_RAM_U_START, KERNEL_RAM_U_SIZE, SRAM, YES, YES ); // Unprivileged kernel SRAM + break; + case MPU_MODE_APP: // DMA2D peripherals (Unprivileged, Read-Write, Non-Executable) SET_REGION( 7, 0x5002B000, SIZE_3K, PERIPHERAL, YES, YES ); break; diff --git a/core/embed/trezorhal/stm32u5/secret.c b/core/embed/trezorhal/stm32u5/secret.c index 47602e50b86..f6b3a2d4f53 100644 --- a/core/embed/trezorhal/stm32u5/secret.c +++ b/core/embed/trezorhal/stm32u5/secret.c @@ -252,7 +252,8 @@ static void secret_optiga_cache(void) { secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) { uint8_t secret_enc[SECRET_OPTIGA_KEY_LEN] = {0}; if (sectrue != secure_aes_ecb_encrypt_hw(secret, sizeof(secret_enc), - secret_enc, SECURE_AES_KEY_DHUK)) { + secret_enc, + SECURE_AES_KEY_DHUK_SP)) { return secfalse; } secret_write(secret_enc, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN); @@ -279,7 +280,7 @@ secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) { } secbool res = secure_aes_ecb_decrypt_hw( - (uint8_t *)secret, SECRET_OPTIGA_KEY_LEN, dest, SECURE_AES_KEY_DHUK); + (uint8_t *)secret, SECRET_OPTIGA_KEY_LEN, dest, SECURE_AES_KEY_DHUK_SP); memzero(secret, sizeof(secret)); return res; diff --git a/core/embed/trezorhal/stm32u5/secure_aes.c b/core/embed/trezorhal/stm32u5/secure_aes.c index 94f8afe5c8c..036c3958a38 100644 --- a/core/embed/trezorhal/stm32u5/secure_aes.c +++ b/core/embed/trezorhal/stm32u5/secure_aes.c @@ -17,33 +17,24 @@ * along with this program. If not, see . */ +#include #include #include STM32_HAL_H #include #include #include -#include "memzero.h" +#include "model.h" +#include "syscall.h" -#ifdef KERNEL_MODE +#include "memzero.h" +#define SAES_DATA_SIZE_WITH_UPRIV_KEY 32 #define AES_BLOCK_SIZE 16 -secbool secure_aes_init(void) { - RCC_OscInitTypeDef osc_init_def = {0}; - osc_init_def.OscillatorType = RCC_OSCILLATORTYPE_SHSI; - osc_init_def.SHSIState = RCC_SHSI_ON; - - // Enable SHSI clock - if (HAL_RCC_OscConfig(&osc_init_def) != HAL_OK) { - return secfalse; - } - - // Enable SAES peripheral clock - __HAL_RCC_SAES_CLK_ENABLE(); +#ifdef KERNEL_MODE - return sectrue; -} +#include "irq.h" static void secure_aes_load_bhk(void) { TAMP->BKP0R; @@ -58,19 +49,159 @@ static void secure_aes_load_bhk(void) { static uint32_t get_keysel(secure_aes_keysel_t key) { switch (key) { - case SECURE_AES_KEY_DHUK: + case SECURE_AES_KEY_DHUK_SP: return CRYP_KEYSEL_HW; case SECURE_AES_KEY_BHK: return CRYP_KEYSEL_SW; - case SECURE_AES_KEY_XORK: + case SECURE_AES_KEY_XORK_SP: + case SECURE_AES_KEY_XORK_SN: return CRYP_KEYSEL_HSW; default: return 0; } } +static secbool is_key_supported(secure_aes_keysel_t key) { + switch (key) { + case SECURE_AES_KEY_DHUK_SP: + case SECURE_AES_KEY_BHK: + case SECURE_AES_KEY_XORK_SP: + return sectrue; + default: + return secfalse; + } +} + +#ifdef SYSCALL_DISPATCH + +__attribute__((section(".udata"))) +uint32_t saes_input[SAES_DATA_SIZE_WITH_UPRIV_KEY / sizeof(uint32_t)]; + +__attribute__((section(".udata"))) +uint32_t saes_output[SAES_DATA_SIZE_WITH_UPRIV_KEY / sizeof(uint32_t)]; + +__attribute__((section(".uflash"), used, naked, no_stack_protector)) uint32_t +saes_invoke(void) { + // reset the key loaded in SAES + MODIFY_REG(SAES->CR, AES_CR_KEYSEL, CRYP_KEYSEL_NORMAL); + + while (HAL_IS_BIT_SET(SAES->SR, CRYP_FLAG_BUSY)) { + } + while (HAL_IS_BIT_SET(SAES->ISR, CRYP_FLAG_RNGEIF)) { + } + + MODIFY_REG(SAES->CR, + AES_CR_KMOD | AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD | + AES_CR_KEYSEL | AES_CR_KEYPROT, + CRYP_KEYMODE_NORMAL | CRYP_NO_SWAP | CRYP_KEYSIZE_256B | + CRYP_AES_ECB | CRYP_KEYSEL_HSW | CRYP_KEYPROT_DISABLE); + + TAMP->BKP0R; + TAMP->BKP1R; + TAMP->BKP2R; + TAMP->BKP3R; + TAMP->BKP4R; + TAMP->BKP5R; + TAMP->BKP6R; + TAMP->BKP7R; + +#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U /*!< Encryption mode(Mode 1) */ + + /* Set the operating mode and normal key selection */ + MODIFY_REG(SAES->CR, AES_CR_MODE | AES_CR_KMOD, + CRYP_OPERATINGMODE_ENCRYPT | CRYP_KEYMODE_NORMAL); + + SAES->CR |= AES_CR_EN; + + for (int j = 0; j < SAES_DATA_SIZE_WITH_UPRIV_KEY / AES_BLOCK_SIZE; j++) { + /* Write the input block in the IN FIFO */ + SAES->DINR = saes_input[j * 4 + 0]; + SAES->DINR = saes_input[j * 4 + 1]; + SAES->DINR = saes_input[j * 4 + 2]; + SAES->DINR = saes_input[j * 4 + 3]; + + while (HAL_IS_BIT_CLR(SAES->ISR, AES_ISR_CCF)) { + } + + /* Clear CCF Flag */ + SET_BIT(SAES->ICR, CRYP_CLEAR_CCF); + + /* Read the output block from the output FIFO */ + for (int i = 0U; i < 4U; i++) { + saes_output[j * 4 + i] = SAES->DOUTR; + } + } + + SAES->CR &= ~AES_CR_EN; + + // reset the key loaded in SAES + MODIFY_REG(SAES->CR, AES_CR_KEYSEL, CRYP_KEYSEL_NORMAL); + + syscall_return_from_callback(sectrue); + return 0; +} + +extern uint32_t sram_u_start; +extern uint32_t sram_u_end; + +secbool unpriv_encrypt(const uint8_t* input, size_t size, uint8_t* output, + secure_aes_keysel_t key) { + if (size != SAES_DATA_SIZE_WITH_UPRIV_KEY) { + return secfalse; + } + + if (key != SECURE_AES_KEY_XORK_SN) { + return secfalse; + } + + uint32_t prev_svc_prio = NVIC_GetPriority(SVCall_IRQn); + NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_HIGHEST); + uint32_t basepri = __get_BASEPRI(); + __set_BASEPRI(IRQ_PRI_HIGHEST + 1); + + mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SAES); + + memset(&sram_u_start, 0, &sram_u_end - &sram_u_start); + memcpy(saes_input, input, size); + + SAES->CR |= AES_CR_KEYSEL_0; + + __HAL_RCC_SAES_CLK_DISABLE(); + __HAL_RCC_SAES_FORCE_RESET(); + __HAL_RCC_SAES_RELEASE_RESET(); + __HAL_RCC_SAES_CLK_ENABLE(); + + secbool retval = invoke_unpriv(saes_invoke); + + __HAL_RCC_SAES_CLK_DISABLE(); + __HAL_RCC_SAES_FORCE_RESET(); + __HAL_RCC_SAES_RELEASE_RESET(); + __HAL_RCC_SAES_CLK_ENABLE(); + + memcpy(output, saes_output, size); + memset(&sram_u_start, 0, &sram_u_end - &sram_u_start); + + mpu_reconfig(mpu_mode); + + __set_BASEPRI(basepri); + NVIC_SetPriority(SVCall_IRQn, prev_svc_prio); + + return retval; +} +#endif + secbool secure_aes_ecb_encrypt_hw(const uint8_t* input, size_t size, uint8_t* output, secure_aes_keysel_t key) { +#ifdef SYSCALL_DISPATCH + if (key == SECURE_AES_KEY_XORK_SN) { + return unpriv_encrypt(input, size, output, key); + } +#endif + + if (sectrue != is_key_supported(key)) { + return secfalse; + } + CRYP_HandleTypeDef hcryp = {0}; uint32_t iv[] = {0, 0, 0, 0}; @@ -138,6 +269,10 @@ secbool secure_aes_ecb_encrypt_hw(const uint8_t* input, size_t size, secbool secure_aes_ecb_decrypt_hw(const uint8_t* input, size_t size, uint8_t* output, secure_aes_keysel_t key) { + if (sectrue != is_key_supported(key)) { + return secfalse; + } + CRYP_HandleTypeDef hcryp = {0}; uint32_t iv[] = {0, 0, 0, 0}; @@ -202,4 +337,20 @@ secbool secure_aes_ecb_decrypt_hw(const uint8_t* input, size_t size, return sectrue; } -#endif // KERNEL_MODE \ No newline at end of file +secbool secure_aes_init(void) { + RCC_OscInitTypeDef osc_init_def = {0}; + osc_init_def.OscillatorType = RCC_OSCILLATORTYPE_SHSI; + osc_init_def.SHSIState = RCC_SHSI_ON; + + // Enable SHSI clock + if (HAL_RCC_OscConfig(&osc_init_def) != HAL_OK) { + return secfalse; + } + + // Enable SAES peripheral clock + __HAL_RCC_SAES_CLK_ENABLE(); + + return sectrue; +} + +#endif diff --git a/storage/storage.c b/storage/storage.c index fe36b52e063..cff331cfb3d 100644 --- a/storage/storage.c +++ b/storage/storage.c @@ -557,7 +557,7 @@ static void derive_kek_v4(const uint8_t *pin, size_t pin_len, uint8_t pre_kek[SHA256_DIGEST_LENGTH] = {0}; pbkdf2_hmac_sha256_Final(&ctx, pre_kek); ensure(secure_aes_ecb_encrypt_hw(pre_kek, SHA256_DIGEST_LENGTH, kek, - SECURE_AES_KEY_XORK), + SECURE_AES_KEY_XORK_SN), "secure_aes derive kek failed"); memzero(pre_kek, sizeof(pre_kek)); #else @@ -615,7 +615,7 @@ static void stretch_pin(const uint8_t *pin, size_t pin_len, uint8_t stretched_pin_tmp[SHA256_DIGEST_LENGTH] = {0}; pbkdf2_hmac_sha256_Final(&ctx, stretched_pin_tmp); ensure(secure_aes_ecb_encrypt_hw(stretched_pin_tmp, SHA256_DIGEST_LENGTH, - stretched_pin, SECURE_AES_KEY_XORK), + stretched_pin, SECURE_AES_KEY_XORK_SN), "secure_aes pin stretch failed"); memzero(stretched_pin_tmp, sizeof(stretched_pin_tmp)); #else From 924904f2aab599ed5575c2337b808213dd12c23b Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Thu, 12 Sep 2024 15:44:19 +0200 Subject: [PATCH 40/44] fix(core): fix storage offsets [no changelog] --- core/embed/models/D002/memory.ld | 2 +- core/embed/models/D002/model_D002.h | 2 +- core/embed/models/T3B1/memory.ld | 2 +- core/embed/models/T3B1/model_T3B1.h | 2 +- core/embed/models/T3T1/memory.ld | 2 +- core/embed/models/T3T1/model_T3T1.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/embed/models/D002/memory.ld b/core/embed/models/D002/memory.ld index 3f5648b562f..aa927f05298 100644 --- a/core/embed/models/D002/memory.ld +++ b/core/embed/models/D002/memory.ld @@ -6,7 +6,7 @@ BOOTLOADER_START = 0xc010000; KERNEL_START = 0xc050000; FIRMWARE_START = 0xc050000; STORAGE_1_OFFSET = 0x30000; -STORAGE_2_OFFSET = 0x50000; +STORAGE_2_OFFSET = 0x40000; NORCOW_SECTOR_SIZE = 0x10000; BOARDLOADER_IMAGE_MAXSIZE = 0xc000; BOOTLOADER_IMAGE_MAXSIZE = 0x20000; diff --git a/core/embed/models/D002/model_D002.h b/core/embed/models/D002/model_D002.h index 48c43dad023..25ec69810bc 100644 --- a/core/embed/models/D002/model_D002.h +++ b/core/embed/models/D002/model_D002.h @@ -34,7 +34,7 @@ #define KERNEL_START 0x0C050000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 -#define STORAGE_2_OFFSET 0x50000 +#define STORAGE_2_OFFSET 0x40000 #define NORCOW_SECTOR_SIZE (8 * 8 * 1024) // 64 kB #define BOARDLOADER_IMAGE_MAXSIZE (6 * 8 * 1024) // 48 kB #define BOOTLOADER_IMAGE_MAXSIZE (16 * 8 * 1024) // 128 kB diff --git a/core/embed/models/T3B1/memory.ld b/core/embed/models/T3B1/memory.ld index 29bfa19521b..7a1ecab277b 100644 --- a/core/embed/models/T3B1/memory.ld +++ b/core/embed/models/T3B1/memory.ld @@ -6,7 +6,7 @@ BOOTLOADER_START = 0xc010000; KERNEL_START = 0xc050000; FIRMWARE_START = 0xc050000; STORAGE_1_OFFSET = 0x30000; -STORAGE_2_OFFSET = 0x50000; +STORAGE_2_OFFSET = 0x40000; NORCOW_SECTOR_SIZE = 0x10000; BOARDLOADER_IMAGE_MAXSIZE = 0xc000; BOOTLOADER_IMAGE_MAXSIZE = 0x20000; diff --git a/core/embed/models/T3B1/model_T3B1.h b/core/embed/models/T3B1/model_T3B1.h index 6dc327e01cb..d50bb4decde 100644 --- a/core/embed/models/T3B1/model_T3B1.h +++ b/core/embed/models/T3B1/model_T3B1.h @@ -34,7 +34,7 @@ #define KERNEL_START 0x0C050000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 -#define STORAGE_2_OFFSET 0x50000 +#define STORAGE_2_OFFSET 0x40000 #define NORCOW_SECTOR_SIZE (8 * 8 * 1024) // 64 kB #define BOARDLOADER_IMAGE_MAXSIZE (6 * 8 * 1024) // 48 kB #define BOOTLOADER_IMAGE_MAXSIZE (16 * 8 * 1024) // 128 kB diff --git a/core/embed/models/T3T1/memory.ld b/core/embed/models/T3T1/memory.ld index 29bfa19521b..7a1ecab277b 100644 --- a/core/embed/models/T3T1/memory.ld +++ b/core/embed/models/T3T1/memory.ld @@ -6,7 +6,7 @@ BOOTLOADER_START = 0xc010000; KERNEL_START = 0xc050000; FIRMWARE_START = 0xc050000; STORAGE_1_OFFSET = 0x30000; -STORAGE_2_OFFSET = 0x50000; +STORAGE_2_OFFSET = 0x40000; NORCOW_SECTOR_SIZE = 0x10000; BOARDLOADER_IMAGE_MAXSIZE = 0xc000; BOOTLOADER_IMAGE_MAXSIZE = 0x20000; diff --git a/core/embed/models/T3T1/model_T3T1.h b/core/embed/models/T3T1/model_T3T1.h index 35643b895f1..c5424a7757d 100644 --- a/core/embed/models/T3T1/model_T3T1.h +++ b/core/embed/models/T3T1/model_T3T1.h @@ -34,7 +34,7 @@ #define KERNEL_START 0x0C050000 #define FIRMWARE_START 0x0C050000 #define STORAGE_1_OFFSET 0x30000 -#define STORAGE_2_OFFSET 0x50000 +#define STORAGE_2_OFFSET 0x40000 #define NORCOW_SECTOR_SIZE (8 * 8 * 1024) // 64 kB #define BOARDLOADER_IMAGE_MAXSIZE (6 * 8 * 1024) // 48 kB #define BOOTLOADER_IMAGE_MAXSIZE (16 * 8 * 1024) // 128 kB From 686861a824378468fc46d26f6b8b51f2ae87d154 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Thu, 12 Sep 2024 14:33:25 +0200 Subject: [PATCH 41/44] chore(core): remove flash otp interface from python [no changelog] --- core/mocks/generated/trezorio/__init__.pyi | 30 ---------------------- 1 file changed, 30 deletions(-) diff --git a/core/mocks/generated/trezorio/__init__.pyi b/core/mocks/generated/trezorio/__init__.pyi index bd360425ab7..1828d18f3f5 100644 --- a/core/mocks/generated/trezorio/__init__.pyi +++ b/core/mocks/generated/trezorio/__init__.pyi @@ -1,36 +1,6 @@ from typing import * -# extmod/modtrezorio/modtrezorio-flash.h -class FlashOTP: - """ - """ - - def __init__(self) -> None: - """ - """ - - def write(self, block: int, offset: int, data: bytes) -> None: - """ - Writes data to OTP flash - """ - - def read(self, block: int, offset: int, data: bytearray) -> None: - """ - Reads data from OTP flash - """ - - def lock(self, block: int) -> None: - """ - Lock OTP flash block - """ - - def is_locked(self, block: int) -> bool: - """ - Is OTP flash block locked? - """ - - # extmod/modtrezorio/modtrezorio-hid.h class HID: """ From 9750b70768f45c260c082da3117cd546f79cec7b Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Thu, 12 Sep 2024 16:41:26 +0200 Subject: [PATCH 42/44] fix(core): support 32 bit colors in terminal [no changelog] --- core/embed/lib/terminal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/embed/lib/terminal.c b/core/embed/lib/terminal.c index 0891fcbedf3..74ce9d7cb1d 100644 --- a/core/embed/lib/terminal.c +++ b/core/embed/lib/terminal.c @@ -81,8 +81,8 @@ static void term_redraw_rows(int start_row, int row_count) { .src_x = 0, .src_y = 0, .src_stride = 8, - .src_fg = terminal_fgcolor, - .src_bg = terminal_bgcolor, + .src_fg = gfx_color16_to_color(terminal_fgcolor), + .src_bg = gfx_color16_to_color(terminal_bgcolor), }; for (int y = start_row; y < start_row + row_count; y++) { @@ -159,9 +159,9 @@ void term_print(const char *text, int textlen) { } const uint8_t *g = Font_Bitmap + (5 * (c - ' ')); if (k < 5 && (g[k] & (1 << j))) { - PIXELDATA(terminal_fgcolor); + PIXELDATA(gfx_color16_to_color(terminal_fgcolor)); } else { - PIXELDATA(terminal_bgcolor); + PIXELDATA(gfx_color16_to_color(terminal_bgcolor)); } } display_pixeldata_dirty(); From 97b3836184f8c49dba519c29046e60ed32f8b744 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Mon, 16 Sep 2024 14:12:51 +0200 Subject: [PATCH 43/44] refactor(core): migrate coreapp into firmware [no changelog] --- core/Makefile | 24 +- core/SConscript.coreapp | 948 ------------------ core/SConscript.firmware | 91 +- core/SConstruct | 1 - core/embed/coreapp/header.S | 54 - core/embed/coreapp/main.c | 117 --- core/embed/coreapp/mpconfigport.h | 224 ----- core/embed/coreapp/mphalport.c | 57 -- core/embed/coreapp/mphalport.h | 24 - core/embed/coreapp/nlrthumb.c | 166 --- core/embed/coreapp/version.h | 11 - core/embed/firmware/delay.c | 101 -- core/embed/firmware/firmware_flash.jlink | 8 - core/embed/firmware/firmware_flash_t1.jlink | 7 - core/embed/firmware/main.c | 196 +--- core/embed/firmware/mphalport.c | 10 + core/embed/firmware/startup_stm32f4.S | 69 -- core/embed/firmware/startup_stm32u5.S | 72 -- .../embed/trezorhal/stm32f4/linker/coreapp.ld | 99 -- .../trezorhal/stm32f4/linker/firmware.ld | 40 +- .../trezorhal/stm32u5/linker/u58/coreapp.ld | 92 -- .../trezorhal/stm32u5/linker/u58/firmware.ld | 62 +- .../linker/u5a/{coreapp.ld => firmware.ld} | 0 23 files changed, 77 insertions(+), 2396 deletions(-) delete mode 100644 core/SConscript.coreapp delete mode 100644 core/embed/coreapp/header.S delete mode 100644 core/embed/coreapp/main.c delete mode 100644 core/embed/coreapp/mpconfigport.h delete mode 100644 core/embed/coreapp/mphalport.c delete mode 100644 core/embed/coreapp/mphalport.h delete mode 100644 core/embed/coreapp/nlrthumb.c delete mode 100644 core/embed/coreapp/version.h delete mode 100644 core/embed/firmware/delay.c delete mode 100644 core/embed/firmware/firmware_flash.jlink delete mode 100644 core/embed/firmware/firmware_flash_t1.jlink delete mode 100644 core/embed/firmware/startup_stm32f4.S delete mode 100644 core/embed/firmware/startup_stm32u5.S delete mode 100644 core/embed/trezorhal/stm32f4/linker/coreapp.ld delete mode 100644 core/embed/trezorhal/stm32u5/linker/u58/coreapp.ld rename core/embed/trezorhal/stm32u5/linker/u5a/{coreapp.ld => firmware.ld} (100%) diff --git a/core/Makefile b/core/Makefile index 31e28b6def9..f89b0821812 100644 --- a/core/Makefile +++ b/core/Makefile @@ -19,7 +19,6 @@ BOOTLOADER_EMU_BUILD_DIR = $(BUILD_DIR)/bootloader_emu PRODTEST_BUILD_DIR = $(BUILD_DIR)/prodtest REFLASH_BUILD_DIR = $(BUILD_DIR)/reflash KERNEL_BUILD_DIR = $(BUILD_DIR)/kernel -COREAPP_BUILD_DIR = $(BUILD_DIR)/coreapp FIRMWARE_BUILD_DIR = $(BUILD_DIR)/firmware UNIX_BUILD_DIR = $(BUILD_DIR)/unix RUST_BUILD_DIR = $(BUILD_DIR)/rust @@ -81,8 +80,6 @@ FLASH_START = $(shell layout_parser ${TREZOR_MODEL} FLASH_START) BOARDLOADER_START = $(shell layout_parser ${TREZOR_MODEL} BOARDLOADER_START) BOOTLOADER_START = $(shell layout_parser ${TREZOR_MODEL} BOOTLOADER_START) KERNEL_START = $(shell layout_parser ${TREZOR_MODEL} KERNEL_START) -COREAPP_START = $(shell layout_parser ${TREZOR_MODEL} COREAPP_START) -COREAPP_P2_START = $(shell layout_parser ${TREZOR_MODEL} COREAPP_P2_START) FIRMWARE_START = $(shell layout_parser ${TREZOR_MODEL} FIRMWARE_START) FIRMWARE_P2_START = $(shell layout_parser ${TREZOR_MODEL} FIRMWARE_P2_START) STORAGE_1_OFFSET = $(shell layout_parser ${TREZOR_MODEL} STORAGE_1_OFFSET) @@ -281,15 +278,7 @@ build_kernel: ## build kernel image BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ $(KERNEL_BUILD_DIR)/kernel.bin -build_coreapp: templates build_cross build_kernel ## build coreapp with frozen modules - $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ - TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ - PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \ - BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ - DISABLE_OPTIGA="$(DISABLE_OPTIGA)" THP="$(THP)" NEW_RENDERING="$(NEW_RENDERING)" \ - $(COREAPP_BUILD_DIR)/coreapp.bin - -build_firmware: templates build_cross ## build firmware with frozen modules +build_firmware: templates build_cross build_kernel ## build firmware with frozen modules $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \ @@ -344,9 +333,6 @@ clean_reflash: ## clean reflash build clean_kernel: ## clean kernel build rm -rf $(KERNEL_BUILD_DIR) -clean_coreapp: ## clean coreapp build - rm -rf $(COREAPP_BUILD_DIR) $(RUST_BUILD_DIR) - clean_firmware: ## clean firmware build rm -rf $(FIRMWARE_BUILD_DIR) $(RUST_BUILD_DIR) @@ -372,14 +358,6 @@ flash_bootloader_ci: $(BOOTLOADER_CI_BUILD_DIR)/bootloader.bin ## flash CI bootl flash_prodtest: $(PRODTEST_BUILD_DIR)/prodtest.bin ## flash prodtest using OpenOCD $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_START); exit" -flash_coreapp: $(COREAPP_BUILD_DIR)/coreapp.bin ## flash coreapp using OpenOCD -ifeq ($(MCU),$(filter $(MCU),STM32F4)) - $(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(FIRMWARE_START); flash write_image erase $<.p2 $(FIRMWARE_P2_START); exit" - -else - $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_START); exit" -endif - flash_firmware: $(FIRMWARE_BUILD_DIR)/firmware.bin ## flash firmware using OpenOCD ifeq ($(MCU),$(filter $(MCU),STM32F4)) $(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(FIRMWARE_START); flash write_image erase $<.p2 $(FIRMWARE_P2_START); exit" diff --git a/core/SConscript.coreapp b/core/SConscript.coreapp deleted file mode 100644 index e2587fdaeb8..00000000000 --- a/core/SConscript.coreapp +++ /dev/null @@ -1,948 +0,0 @@ -# pylint: disable=E0602 -# fmt: off - -import os -import tools, models - -BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0') -PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1' -BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1' -BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' -EVERYTHING = BITCOIN_ONLY != '1' -TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') -CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) -PYOPT = ARGUMENTS.get('PYOPT', '1') -DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1' -HW_REVISION = ARGUMENTS.get('HW_REVISION', None) -THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol -NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' or TREZOR_MODEL in ('T3T1',) -MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) - -FEATURE_FLAGS = { - "RDI": True, - "SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) - "AES_GCM": False, -} - -FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"] -if DISABLE_OPTIGA and PYOPT == '0': - FEATURES_WANTED.remove("optiga") -if NEW_RENDERING: - FEATURES_WANTED.append("new_rendering") - -CCFLAGS_MOD = '' -CPPPATH_MOD = [] -CPPDEFINES_MOD = [] -SOURCE_MOD = [] -SOURCE_MOD_CRYPTO = [] -CPPDEFINES_HAL = [] -SOURCE_HAL = [] -PATH_HAL = [] - -FROZEN = True - -if TREZOR_MODEL in ('1', 'R', 'T3B1'): - FONT_NORMAL='Font_PixelOperator_Regular_8' - FONT_DEMIBOLD='Font_Unifont_Bold_16' - FONT_BOLD='Font_PixelOperator_Bold_8' - FONT_MONO='Font_PixelOperatorMono_Regular_8' - FONT_BIG='Font_Unifont_Regular_16' - FONT_NORMAL_UPPER='Font_PixelOperator_Regular_8_upper' - FONT_BOLD_UPPER='Font_PixelOperator_Bold_8_upper' - FONT_SUB=None -elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): - FONT_NORMAL='Font_TTHoves_Regular_21' - FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' - FONT_BOLD=None - FONT_MONO='Font_RobotoMono_Medium_20' - FONT_BIG=None - FONT_NORMAL_UPPER=None - FONT_BOLD_UPPER='Font_TTHoves_Bold_17_upper' - FONT_SUB=None -elif TREZOR_MODEL in ('T3T1',): - FONT_NORMAL='Font_TTSatoshi_DemiBold_21' - FONT_DEMIBOLD='Font_TTSatoshi_DemiBold_21' - FONT_BOLD='Font_TTSatoshi_DemiBold_21' - FONT_MONO='Font_RobotoMono_Medium_21' - FONT_BIG='Font_TTSatoshi_DemiBold_42' - FONT_NORMAL_UPPER=None - FONT_BOLD_UPPER=None - FONT_SUB='Font_TTSatoshi_DemiBold_18' - -# modtrezorconfig -CPPPATH_MOD += [ - 'embed/extmod/modtrezorconfig', - 'vendor/trezor-storage', -] -SOURCE_MOD += [ - 'embed/extmod/modtrezorconfig/modtrezorconfig.c', - 'vendor/trezor-storage/norcow.c', - 'vendor/trezor-storage/storage.c', - 'vendor/trezor-storage/storage_utils.c', - 'vendor/trezor-storage/flash_area.c', -] - -# modtrezorcrypto -CCFLAGS_MOD += '-Wno-sequence-point ' -CPPPATH_MOD += [ - 'vendor/trezor-crypto', -] -CPPDEFINES_MOD += [ - 'AES_128', - 'AES_192', - ('USE_BIP32_CACHE', '0'), - ('USE_KECCAK', '1'), - ('USE_ETHEREUM', '1' if EVERYTHING else '0'), - ('USE_MONERO', '1' if EVERYTHING else '0'), - ('USE_CARDANO', '1' if EVERYTHING else '0'), - ('USE_NEM', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'), - ('USE_EOS', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'), -] -SOURCE_MOD += [ - 'embed/extmod/trezorobj.c', - 'embed/extmod/modtrezorcrypto/crc.c', - 'embed/extmod/modtrezorcrypto/modtrezorcrypto.c', - 'embed/extmod/modtrezorcrypto/rand.c', -] -SOURCE_MOD_CRYPTO += [ - 'vendor/trezor-crypto/address.c', - 'vendor/trezor-crypto/aes/aes_modes.c', - 'vendor/trezor-crypto/aes/aesccm.c', - 'vendor/trezor-crypto/aes/aescrypt.c', - 'vendor/trezor-crypto/aes/aeskey.c', - 'vendor/trezor-crypto/aes/aestab.c', - 'vendor/trezor-crypto/base32.c', - 'vendor/trezor-crypto/base58.c', - 'vendor/trezor-crypto/bignum.c', - 'vendor/trezor-crypto/bip32.c', - 'vendor/trezor-crypto/bip39.c', - 'vendor/trezor-crypto/bip39_english.c', - 'vendor/trezor-crypto/blake256.c', - 'vendor/trezor-crypto/blake2b.c', - 'vendor/trezor-crypto/blake2s.c', - 'vendor/trezor-crypto/buffer.c', - 'vendor/trezor-crypto/chacha20poly1305/chacha20poly1305.c', - 'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c', - 'vendor/trezor-crypto/chacha20poly1305/poly1305-donna.c', - 'vendor/trezor-crypto/chacha20poly1305/rfc7539.c', - 'vendor/trezor-crypto/chacha_drbg.c', - 'vendor/trezor-crypto/curves.c', - 'vendor/trezor-crypto/der.c', - 'vendor/trezor-crypto/ecdsa.c', - 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c', - 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c', - 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c', - 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-32bit-tables.c', - 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-basepoint-table.c', - 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-impl-base.c', - 'vendor/trezor-crypto/ed25519-donna/ed25519-keccak.c', - 'vendor/trezor-crypto/ed25519-donna/ed25519-sha3.c', - 'vendor/trezor-crypto/ed25519-donna/ed25519.c', - 'vendor/trezor-crypto/ed25519-donna/modm-donna-32bit.c', - 'vendor/trezor-crypto/groestl.c', - 'vendor/trezor-crypto/hasher.c', - 'vendor/trezor-crypto/hmac.c', - 'vendor/trezor-crypto/hmac_drbg.c', - 'vendor/trezor-crypto/memzero.c', - 'vendor/trezor-crypto/nem.c', - 'vendor/trezor-crypto/nist256p1.c', - 'vendor/trezor-crypto/pbkdf2.c', - 'vendor/trezor-crypto/rand.c', - 'vendor/trezor-crypto/rfc6979.c', - 'vendor/trezor-crypto/ripemd160.c', - 'vendor/trezor-crypto/secp256k1.c', - 'vendor/trezor-crypto/segwit_addr.c', - 'vendor/trezor-crypto/sha2.c', - 'vendor/trezor-crypto/sha3.c', - 'vendor/trezor-crypto/shamir.c', - 'vendor/trezor-crypto/slip39.c', - 'vendor/trezor-crypto/slip39_english.c', - 'vendor/trezor-crypto/tls_prf.c', -] -if EVERYTHING: - SOURCE_MOD_CRYPTO += [ - 'vendor/trezor-crypto/cardano.c', - 'vendor/trezor-crypto/monero/base58.c', - 'vendor/trezor-crypto/monero/serialize.c', - 'vendor/trezor-crypto/monero/xmr.c', - ] - -# libsecp256k1-zkp -if FEATURE_FLAGS["SECP256K1_ZKP"]: - CPPPATH_MOD += [ - 'vendor/secp256k1-zkp', - 'vendor/secp256k1-zkp/src', - 'vendor/secp256k1-zkp/include', - ] - CPPDEFINES_MOD += [ - 'USE_SECP256K1_ZKP', - 'USE_SECP256K1_ZKP_ECDSA', - ('SECP256K1_CONTEXT_SIZE', '180'), - 'USE_ASM_ARM', - 'USE_EXTERNAL_ASM', - 'USE_EXTERNAL_DEFAULT_CALLBACKS', - ('ECMULT_GEN_PREC_BITS', '2'), - ('ECMULT_WINDOW_SIZE', '2'), - 'ENABLE_MODULE_GENERATOR', - 'ENABLE_MODULE_RECOVERY', - 'ENABLE_MODULE_SCHNORRSIG', - 'ENABLE_MODULE_EXTRAKEYS', - 'ENABLE_MODULE_ECDH', - ] - SOURCE_MOD_SECP256K1_ZKP = [ - 'vendor/secp256k1-zkp/src/secp256k1.c', - 'vendor/secp256k1-zkp/src/precomputed_ecmult.c', - 'vendor/secp256k1-zkp/src/precomputed_ecmult_gen.c', - 'vendor/secp256k1-zkp/src/asm/field_10x26_arm.s' - ] - SOURCE_MOD_CRYPTO += [ - 'vendor/trezor-crypto/zkp_context.c', - 'vendor/trezor-crypto/zkp_ecdsa.c', - 'vendor/trezor-crypto/zkp_bip340.c', - ] - -# AES-GCM -if FEATURE_FLAGS["AES_GCM"]: - CPPDEFINES_MOD += [ - 'USE_AES_GCM', - 'AES_VAR', - ] - SOURCE_MOD_CRYPTO += [ - 'vendor/trezor-crypto/aes/gf128mul.c', - 'vendor/trezor-crypto/aes/aesgcm.c', - ] - -# modtrezorio -SOURCE_MOD += [ - 'embed/extmod/modtrezorio/modtrezorio.c', -] - -# modtrezorui -CPPPATH_MOD += [ - 'vendor/micropython/lib/uzlib', -] -SOURCE_MOD += [ - 'embed/extmod/modtrezorui/modtrezorui.c', - 'embed/lib/buffers.c', - 'embed/lib/colors.c', - 'embed/lib/display_utils.c', - 'embed/lib/error_handling.c', - 'embed/lib/fonts/font_bitmap.c', - 'embed/lib/fonts/fonts.c', - 'embed/lib/gfx_color.c', - 'embed/lib/gfx_bitblt_rgb565.c', - 'embed/lib/gfx_bitblt_rgba8888.c', - 'embed/lib/gfx_bitblt_mono8.c', - 'embed/lib/image.c', - 'embed/lib/mini_printf.c', - 'embed/lib/rsod.c', - 'embed/lib/terminal.c', - 'embed/lib/translations.c', - 'embed/lib/unit_variant.c', - 'vendor/micropython/lib/uzlib/adler32.c', - 'vendor/micropython/lib/uzlib/crc32.c', - 'vendor/micropython/lib/uzlib/tinflate.c', -] - -if NEW_RENDERING: - CPPDEFINES_MOD += ['NEW_RENDERING'] - SOURCE_MOD += [ - 'embed/lib/gfx_draw.c', - ] -else: - SOURCE_MOD += [ - 'embed/lib/display_draw.c', - ] - - -CPPDEFINES_MOD += [ - 'TREZOR_UI2', - 'TRANSLATIONS', -] - -if TREZOR_MODEL not in ('1', ): - CPPDEFINES_MOD += [ - 'FANCY_FATAL_ERROR', - ] - -# modtrezorutils -SOURCE_MOD += [ - 'embed/extmod/modtrezorutils/modtrezorutils.c', -] - -# rust mods -SOURCE_MOD += [ - 'embed/extmod/rustmods.c', -] - -# modutime -SOURCE_MOD += [ - 'embed/extmod/modutime.c', -] - -SOURCE_MICROPYTHON = [ - 'vendor/micropython/extmod/modubinascii.c', - 'vendor/micropython/extmod/moductypes.c', - 'vendor/micropython/extmod/moduheapq.c', - 'vendor/micropython/extmod/modutimeq.c', - 'vendor/micropython/extmod/utime_mphal.c', - 'vendor/micropython/shared/libc/abort_.c', - 'vendor/micropython/shared/libc/printf.c', - 'vendor/micropython/shared/runtime/gchelper_m3.s', - 'vendor/micropython/shared/runtime/gchelper_native.c', - 'vendor/micropython/shared/runtime/interrupt_char.c', - 'vendor/micropython/shared/runtime/pyexec.c', - 'vendor/micropython/shared/runtime/stdout_helpers.c', - 'vendor/micropython/shared/timeutils/timeutils.c', - 'vendor/micropython/ports/stm32/gccollect.c', - 'vendor/micropython/py/argcheck.c', - 'vendor/micropython/py/asmarm.c', - 'vendor/micropython/py/asmbase.c', - 'vendor/micropython/py/asmthumb.c', - 'vendor/micropython/py/asmx64.c', - 'vendor/micropython/py/asmx86.c', - 'vendor/micropython/py/asmxtensa.c', - 'vendor/micropython/py/bc.c', - 'vendor/micropython/py/binary.c', - 'vendor/micropython/py/builtinevex.c', - 'vendor/micropython/py/builtinhelp.c', - 'vendor/micropython/py/builtinimport.c', - 'vendor/micropython/py/compile.c', - 'vendor/micropython/py/emitbc.c', - 'vendor/micropython/py/emitcommon.c', - 'vendor/micropython/py/emitglue.c', - 'vendor/micropython/py/emitinlinethumb.c', - 'vendor/micropython/py/emitinlinextensa.c', - 'vendor/micropython/py/formatfloat.c', - 'vendor/micropython/py/frozenmod.c', - 'vendor/micropython/py/lexer.c', - 'vendor/micropython/py/malloc.c', - 'vendor/micropython/py/map.c', - 'vendor/micropython/py/modarray.c', - 'vendor/micropython/py/modbuiltins.c', - 'vendor/micropython/py/modgc.c', - 'vendor/micropython/py/modmath.c', - 'vendor/micropython/py/modmicropython.c', - 'vendor/micropython/py/modstruct.c', - 'vendor/micropython/py/modsys.c', - 'vendor/micropython/py/mpprint.c', - 'vendor/micropython/py/mpstate.c', - 'vendor/micropython/py/mpz.c', - 'vendor/micropython/py/nativeglue.c', - 'vendor/micropython/py/obj.c', - 'vendor/micropython/py/objarray.c', - 'vendor/micropython/py/objattrtuple.c', - 'vendor/micropython/py/objbool.c', - 'vendor/micropython/py/objboundmeth.c', - 'vendor/micropython/py/objcell.c', - 'vendor/micropython/py/objclosure.c', - 'vendor/micropython/py/objcomplex.c', - 'vendor/micropython/py/objdict.c', - 'vendor/micropython/py/objenumerate.c', - 'vendor/micropython/py/objexcept.c', - 'vendor/micropython/py/objfilter.c', - 'vendor/micropython/py/objfloat.c', - 'vendor/micropython/py/objfun.c', - 'vendor/micropython/py/objgenerator.c', - 'vendor/micropython/py/objgetitemiter.c', - 'vendor/micropython/py/objint.c', - 'vendor/micropython/py/objint_longlong.c', - 'vendor/micropython/py/objint_mpz.c', - 'vendor/micropython/py/objlist.c', - 'vendor/micropython/py/objmap.c', - 'vendor/micropython/py/objmodule.c', - 'vendor/micropython/py/objnamedtuple.c', - 'vendor/micropython/py/objnone.c', - 'vendor/micropython/py/objobject.c', - 'vendor/micropython/py/objpolyiter.c', - 'vendor/micropython/py/objproperty.c', - 'vendor/micropython/py/objrange.c', - 'vendor/micropython/py/objreversed.c', - 'vendor/micropython/py/objset.c', - 'vendor/micropython/py/objsingleton.c', - 'vendor/micropython/py/objslice.c', - 'vendor/micropython/py/objstr.c', - 'vendor/micropython/py/objstringio.c', - 'vendor/micropython/py/objstrunicode.c', - 'vendor/micropython/py/objtuple.c', - 'vendor/micropython/py/objtype.c', - 'vendor/micropython/py/objzip.c', - 'vendor/micropython/py/opmethods.c', - 'vendor/micropython/py/pairheap.c', - 'vendor/micropython/py/parse.c', - 'vendor/micropython/py/parsenum.c', - 'vendor/micropython/py/parsenumbase.c', - 'vendor/micropython/py/persistentcode.c', - 'vendor/micropython/py/qstr.c', - 'vendor/micropython/py/reader.c', - 'vendor/micropython/py/repl.c', - 'vendor/micropython/py/runtime.c', - 'vendor/micropython/py/runtime_utils.c', - 'vendor/micropython/py/scheduler.c', - 'vendor/micropython/py/scope.c', - 'vendor/micropython/py/sequence.c', - 'vendor/micropython/py/showbc.c', - 'vendor/micropython/py/smallint.c', - 'vendor/micropython/py/stackctrl.c', - 'vendor/micropython/py/stream.c', - 'vendor/micropython/py/unicode.c', - 'vendor/micropython/py/vstr.c', - 'vendor/micropython/py/warning.c', -] - -SOURCE_MICROPYTHON_SPEED = [ - 'vendor/micropython/py/gc.c', - 'vendor/micropython/py/pystack.c', - 'vendor/micropython/py/vm.c', -] - -CPPDEFINES_MOD += ['USE_SVC_SHUTDOWN'] - -if FEATURE_FLAGS["RDI"]: - CPPDEFINES_MOD += ['RDI'] - -TRANSLATION_DATA = [ - "translations/en.json", - "translations/order.json", -] - -if THP: - CPPDEFINES_MOD += ['USE_THP'] - SOURCE_MOD += [ - 'vendor/trezor-crypto/elligator2.c', - ] - -# fonts -tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('DEMIBOLD', FONT_DEMIBOLD, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('MONO', FONT_MONO, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('BIG', FONT_BIG, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('NORMAL_UPPER', FONT_NORMAL_UPPER, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('BOLD_UPPER', FONT_BOLD_UPPER, CPPDEFINES_MOD, SOURCE_MOD) -tools.add_font('SUB', FONT_SUB, CPPDEFINES_MOD, SOURCE_MOD) - -SOURCE_QSTR = SOURCE_MOD + SOURCE_MICROPYTHON + SOURCE_MICROPYTHON_SPEED - -env = Environment( - ENV=os.environ, - CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODUCTION={int(PRODUCTION)} -DPYOPT={PYOPT} -DBOOTLOADER_QA={int(BOOTLOADER_QA)} -DBITCOIN_ONLY={BITCOIN_ONLY}", - CPPDEFINES_IMPLICIT=[] - ) - -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/coreapp/header.S', - 'embed/coreapp/main.c', - 'embed/coreapp/mphalport.c', - 'embed/coreapp/nlrthumb.c', - f'embed/trezorhal/{FILE_SUFFIX}/startup_stage_4.S', -] - - -if TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): - UI_LAYOUT = 'UI_LAYOUT_TT' - ui_layout_feature = 'model_tt' -elif TREZOR_MODEL in ('1', 'R', 'T3B1'): - UI_LAYOUT = 'UI_LAYOUT_TR' - ui_layout_feature = 'model_tr' -elif TREZOR_MODEL in ('T3T1',): - UI_LAYOUT = 'UI_LAYOUT_MERCURY' - ui_layout_feature = 'model_mercury' -else: - raise ValueError('Unknown Trezor model') - -if 'sd_card' in FEATURES_AVAILABLE: - SDCARD = True -else: - SDCARD = False - -env.Tool('micropython') - -env.Replace( - CAT='cat', - DD='dd', - CP='cp', - SED='sed', - AS='arm-none-eabi-as', - AR='arm-none-eabi-ar', - CC='arm-none-eabi-gcc', - LINK='arm-none-eabi-gcc', - SIZE='arm-none-eabi-size', - STRIP='arm-none-eabi-strip', - OBJCOPY='arm-none-eabi-objcopy', ) - -env.Replace( - TREZOR_MODEL=TREZOR_MODEL,) - -ALLPATHS = [ - '.', - 'embed/rust', - 'embed/coreapp', - 'embed/lib', - 'embed/models', - 'embed/trezorhal', - 'embed/extmod/modtrezorui', - 'vendor/micropython', - ] + CPPPATH_MOD + PATH_HAL - -env.Replace( - COPT=env.get('ENV').get('OPTIMIZE', '-Os'), - CCFLAGS='$COPT ' - '-g3 ' - '-nostdlib ' - '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -fno-common ' - '-fsingle-precision-constant -fdata-sections -ffunction-sections ' - '-ffreestanding ' - '-fstack-protector-all ' - + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, - CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', - LINKFLAGS='-T build/coreapp/memory.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/coreapp/coreapp.map -Wl,--warn-common', - CPPPATH=ALLPATHS, - CPPDEFINES=[ - 'FIRMWARE', - 'TREZOR_MODEL_'+TREZOR_MODEL, - 'USE_HAL_DRIVER', - 'ARM_USER_MODE', - UI_LAYOUT, - ] + CPPDEFINES_MOD + CPPDEFINES_HAL, - ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], - ASPPFLAGS='$CFLAGS $CCFLAGS', - ) - -env.Replace( - HEADERTOOL='headertool', - PYTHON='python', - MAKEQSTRDATA='$PYTHON vendor/micropython/py/makeqstrdata.py', - MAKEVERSIONHDR='$PYTHON vendor/micropython/py/makeversionhdr.py', - MAKEMODULEDEFS='$PYTHON vendor/micropython/py/makemoduledefs.py', - MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', - MPY_TOOL='$PYTHON vendor/micropython/tools/mpy-tool.py', - MPY_CROSS='vendor/micropython/mpy-cross/mpy-cross -O' + PYOPT, - PB2PY='$PYTHON ../common/protob/pb2py', -) - -# -# Qstrings -# - -PROTO_SOURCES_DIR = '../../../common/protob/' -PROTO_SOURCES = Glob(PROTO_SOURCES_DIR + '*.proto', - exclude=[PROTO_SOURCES_DIR + 'messages-bootloader.proto'] -) -qstr_protobuf = env.Command( - target=[ - 'genhdr/qstrdefs.protobuf.h', - ], - source=PROTO_SOURCES, - action='$PB2PY $SOURCES --qstr-out ${TARGET} --bitcoin-only=%s' % BITCOIN_ONLY, -) - -qstr_micropython = 'vendor/micropython/py/qstrdefs.h' - -micropy_defines = env.MicroPyDefines(source=SOURCE_QSTR) - -qstr_collected = env.CollectQstr( - target='genhdr/qstrdefs.collected.h', source=micropy_defines) - -qstr_preprocessed = env.PreprocessQstr( - target='genhdr/qstrdefs.preprocessed.h', - source=[qstr_micropython, qstr_protobuf, qstr_collected]) - -qstr_generated = env.GenerateQstrDefs( - target='genhdr/qstrdefs.generated.h', source=qstr_preprocessed) - -env.Ignore(qstr_collected, qstr_generated) - -# -# Micropython module declarations -# - -moduledefs_collected = env.CollectModules( - target='genhdr/moduledefs.collected.h', source=micropy_defines) - -hdr_moduledefs = env.Command( - target='genhdr/moduledefs.h', - source=moduledefs_collected, - action='$MAKEMODULEDEFS $SOURCE > $TARGET', ) - -env.Ignore(micropy_defines, micropy_defines) -env.Ignore(micropy_defines, qstr_generated) -env.Ignore(micropy_defines, hdr_moduledefs) - -# -# Micropython version -# - -hdr_version = env.Command( - target='genhdr/mpversion.h', - source='', - action='$MAKEVERSIONHDR $TARGET', ) - -env.Ignore(hdr_moduledefs, hdr_moduledefs) -env.Ignore(hdr_moduledefs, qstr_collected) -env.Ignore(hdr_moduledefs, qstr_preprocessed) -env.Ignore(hdr_moduledefs, qstr_generated) - -# -# Frozen modules -# - -if FROZEN: - SOURCE_PY_DIR = 'src/' - - SOURCE_PY = Glob(SOURCE_PY_DIR + '*.py') - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/*.py', - exclude=[ - SOURCE_PY_DIR + 'trezor/sdcard.py', - ] if not SDCARD else [] - )) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/crypto/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/*.py')) - - # UI layouts - common files and then model-specific. Exclude FIDO when BTC-only. - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/*.py', - exclude=[ - SOURCE_PY_DIR + 'trezor/ui/layouts/fido.py', - ] if not EVERYTHING else [] - )) - if UI_LAYOUT == 'UI_LAYOUT_TT': - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/*.py', - exclude=[ - SOURCE_PY_DIR + 'trezor/ui/layouts/tt/fido.py', - ] if not EVERYTHING else [] - )) - elif UI_LAYOUT == 'UI_LAYOUT_TR': - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tr/*.py', - exclude=[ - SOURCE_PY_DIR + 'trezor/ui/layouts/tr/fido.py', - ] if not EVERYTHING else [] - )) - elif UI_LAYOUT == 'UI_LAYOUT_MERCURY': - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/mercury/*.py', - exclude=[ - SOURCE_PY_DIR + 'trezor/ui/layouts/mercury/fido.py', - ] if not EVERYTHING else [] - )) - else: - raise ValueError('Unknown layout') - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/wire/*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'storage/*.py', - exclude=[ - SOURCE_PY_DIR + 'storage/sd_salt.py', - ] if not SDCARD else [] - )) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/messages/__init__.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/*.py', - exclude=[ - SOURCE_PY_DIR + 'trezor/enums/Binance*.py', - SOURCE_PY_DIR + 'trezor/enums/Cardano*.py', - SOURCE_PY_DIR + 'trezor/enums/DebugMonero*.py', - SOURCE_PY_DIR + 'trezor/enums/Eos*.py', - SOURCE_PY_DIR + 'trezor/enums/Ethereum*.py', - SOURCE_PY_DIR + 'trezor/enums/Monero*.py', - SOURCE_PY_DIR + 'trezor/enums/NEM*.py', - SOURCE_PY_DIR + 'trezor/enums/Ripple*.py', - SOURCE_PY_DIR + 'trezor/enums/Solana*.py', - SOURCE_PY_DIR + 'trezor/enums/Stellar*.py', - SOURCE_PY_DIR + 'trezor/enums/Tezos*.py', - SOURCE_PY_DIR + 'trezor/enums/Zcash*.py', - ]) - ) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/common/*.py', - exclude=[ - SOURCE_PY_DIR + 'apps/common/sdcard.py', - ] if not SDCARD else [] - )) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/debug/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/homescreen/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py', - exclude=[ - SOURCE_PY_DIR + 'apps/management/sd_protect.py', - ] if not SDCARD else []) - ) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*/*.py', - exclude=[ - SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py', - SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py', - SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash_v4.py', - ]) - ) - - if EVERYTHING: - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/binance/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Binance*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/cardano/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/cardano/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Cardano*.py')) - - if TREZOR_MODEL == "T": - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/eos/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/eos/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Eos*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ethereum/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Ethereum*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/monero/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/monero/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/monero/*/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/DebugMonero*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Monero*.py')) - - if TREZOR_MODEL == "T": - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/nem/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/nem/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/NEM*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ripple/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Ripple*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/solana/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/solana/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Solana*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/stellar/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/stellar/*/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Stellar*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/tezos/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Tezos*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/zcash/*.py')) - - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py')) - - if TREZOR_MODEL == "T": - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash_v4.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Zcash*.py')) - - source_mpy = env.FrozenModule( - source=SOURCE_PY, - source_dir=SOURCE_PY_DIR, - bitcoin_only=BITCOIN_ONLY, - backlight='backlight' in FEATURES_AVAILABLE, - optiga='optiga' in FEATURES_AVAILABLE, - ui_layout=UI_LAYOUT, - thp=THP, - ) - - source_mpyc = env.FrozenCFile( - target='frozen_mpy.c', source=source_mpy, qstr_header=qstr_preprocessed) - - env.Depends(source_mpyc, qstr_generated) - - -# -# Program objects -# - -source_files = SOURCE_MOD + SOURCE_MOD_CRYPTO + SOURCE_FIRMWARE + SOURCE_MICROPYTHON + SOURCE_MICROPYTHON_SPEED + SOURCE_HAL -obj_program = [] -obj_program.extend(env.Object(source=SOURCE_MOD)) -obj_program.extend(env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-auto-var-init=zero')) -if FEATURE_FLAGS["SECP256K1_ZKP"]: - obj_program.extend(env.Object(source=SOURCE_MOD_SECP256K1_ZKP, CCFLAGS='$CCFLAGS -Wno-unused-function')) - source_files.extend(SOURCE_MOD_SECP256K1_ZKP) -obj_program.extend(env.Object(source=SOURCE_FIRMWARE)) -obj_program.extend(env.Object(source=SOURCE_MICROPYTHON)) -obj_program.extend(env.Object(source=SOURCE_MICROPYTHON_SPEED, COPT='-O3')) -obj_program.extend(env.Object(source=SOURCE_HAL)) -if FROZEN: - obj_program.extend(env.Object(source=source_mpyc)) - -env.Replace( - ALLSOURCES=source_files, - ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'] + env['CPPDEFINES_IMPLICIT'] + [f"PRODUCTION={int(PRODUCTION)}", f"BOOTLOADER_QA={int(BOOTLOADER_QA)}", f"PYOPT={PYOPT}", f"BITCOIN_ONLY={BITCOIN_ONLY}"])) - - -cmake_gen = env.Command( - target='CMakeLists.txt', - source='', - action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', -) - -# -# Rust library -# - -protobuf_blobs = env.Command( - target=[ - 'rust/proto_enums.data', - 'rust/proto_msgs.data', - 'rust/proto_names.data', - 'rust/proto_wire.data', - ], - source=PROTO_SOURCES, - action='$PB2PY --bitcoin-only=%s --blob-outdir ${TARGET.dir} $SOURCES --qstr-defs build/coreapp/genhdr/qstrdefs.generated.h' % BITCOIN_ONLY, -) -env.Depends(protobuf_blobs, qstr_generated) - -RUST_PROFILE = 'release' -RUST_LIB = 'trezor_lib' -RUST_LIBDIR = f'build/coreapp/rust/{env.get("ENV")["RUST_TARGET"]}/{RUST_PROFILE}' -RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a' - -def cargo_build(): - # Determine the profile build flags. - if RUST_PROFILE == 'release': - profile = '--release' - else: - profile = '' - - features = ['micropython', 'protobuf', ui_layout_feature] - if EVERYTHING: - features.append('universal_fw') - features.append('ui') - features.append('translations') - - if NEW_RENDERING: - features.append('new_rendering') - - if PYOPT == '0': - features.append('debug') - features.append('ui_debug') - if TREZOR_MODEL in ('T', 'T3T1', 'DISC1', 'DISC2'): - features.append('ui_blurring') - features.append('ui_jpeg_decoder') - - if NEW_RENDERING and TREZOR_MODEL in ('T3T1', 'DISC2'): - features.append('ui_image_buffer') - features.append('ui_overlay') - - features.extend(FEATURES_AVAILABLE) - - cargo_opts = [ - f'--target={env.get("ENV")["RUST_TARGET"]}', - f'--target-dir=../../build/coreapp/rust', - '--no-default-features', - '--features ' + ','.join(features), - '-Z build-std=core', - '-Z build-std-features=panic_immediate_abort', - ] - - env.get('ENV')['TREZOR_MODEL'] = TREZOR_MODEL - - bindgen_macros = tools.get_bindgen_defines(env.get("CPPDEFINES"), ALLPATHS) - build_dir = str(Dir('.').abspath) - - return f'export BINDGEN_MACROS=\'{bindgen_macros}\'; export BUILD_DIR=\'{build_dir}\'; cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts) - -rust = env.Command( - target=RUST_LIBPATH, - source='', - action=cargo_build(), ) -env.Depends(rust, protobuf_blobs) -env.Depends(rust, TRANSLATION_DATA) - -env.Append(LINKFLAGS=f' -L{RUST_LIBDIR}') -env.Append(LINKFLAGS=f' -l{RUST_LIB}') - - -MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) -BOOTLOADER_SUFFIX = MODEL_IDENTIFIER -if BOOTLOADER_QA or BOOTLOADER_DEVEL: - BOOTLOADER_SUFFIX += '_qa' - -# select vendor header -if BOOTLOADER_QA or BOOTLOADER_DEVEL: - vendor = "dev_DO_NOT_SIGN_signed_dev" -elif not PRODUCTION: - vendor = "unsafe_signed_prod" -else: - if TREZOR_MODEL in ('T',): - vendor = "satoshilabs_signed_prod" - elif BITCOIN_ONLY == '1': - vendor = "trezor_btconly_signed_prod" - else: - vendor = "trezor_signed_prod" - -VENDORHEADER = f'embed/models/{MODEL_IDENTIFIER}/vendorheader/vendorheader_{vendor}.bin' - - -obj_program.extend( - env.Command( - target='embed/coreapp/vendorheader.o', - source=VENDORHEADER, - action='$OBJCOPY -I binary -O elf32-littlearm -B arm' - ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' - ' $SOURCE $TARGET', )) - - -tools.embed_raw_binary( - obj_program, - env, - 'kernel', - 'build/kernel/kernel.o', - f'build/kernel/kernel.bin', - ) - - - -env.Depends(obj_program, qstr_generated) - -linkerscript_gen = env.Command( - target='memory.ld', - source=[f'embed/models/{MODEL_IDENTIFIER}/memory.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='coreapp')], - action='$CAT $SOURCES > $TARGET', -) - -program_elf = env.Command( - target='coreapp.elf', - source=obj_program, - action= - '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', -) - -env.Depends(program_elf, linkerscript_gen) - -if CMAKELISTS != 0: - env.Depends(program_elf, cmake_gen) -env.Depends(program_elf, rust) - -BINARY_NAME = f"build/coreapp/coreapp-{MODEL_IDENTIFIER}" -if not EVERYTHING: - BINARY_NAME += "-btconly" -BINARY_NAME += "-" + tools.get_version('embed/coreapp/version.h') -BINARY_NAME += "-" + tools.get_git_revision_short_hash() -BINARY_NAME += "-dirty" if tools.get_git_modified() else "" -BINARY_NAME += ".bin" - - -if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', - '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', - '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', - '$CP $TARGET ' + BINARY_NAME, - ] -elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$CP $TARGET ' + BINARY_NAME, - ] -else: - raise Exception("Unknown MCU") - -program_bin = env.Command( - target='coreapp.bin', - source=program_elf, - action=action_bin, -) diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 16dc21e2a89..652a21f518b 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -16,12 +16,11 @@ DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1' HW_REVISION = ARGUMENTS.get('HW_REVISION', None) THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1' - +MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL) FEATURE_FLAGS = { "RDI": True, "SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) - "SYSTEM_VIEW": False, "AES_GCM": False, } @@ -85,7 +84,6 @@ CPPPATH_MOD += [ 'vendor/trezor-crypto', ] CPPDEFINES_MOD += [ - 'KERNEL_MODE', 'AES_128', 'AES_192', ('USE_BIP32_CACHE', '0'), @@ -221,12 +219,10 @@ CPPPATH_MOD += [ ] SOURCE_MOD += [ 'embed/extmod/modtrezorui/modtrezorui.c', - 'embed/lib/bl_check.c', 'embed/lib/buffers.c', 'embed/lib/colors.c', 'embed/lib/display_utils.c', 'embed/lib/error_handling.c', - 'embed/lib/flash_utils.c', 'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/fonts.c', 'embed/lib/gfx_color.c', @@ -401,22 +397,6 @@ CPPDEFINES_MOD += ['USE_SVC_SHUTDOWN'] if FEATURE_FLAGS["RDI"]: CPPDEFINES_MOD += ['RDI'] -if FEATURE_FLAGS["SYSTEM_VIEW"]: - SOURCE_FIRMWARE += [ - 'embed/segger/SEGGER/SEGGER_SYSVIEW_Config_NoOS.c', - 'embed/segger/SEGGER/SEGGER_SYSVIEW.c', - 'embed/segger/SEGGER/SEGGER_RTT.c', - 'embed/segger/SEGGER/SEGGER_RTT_ASM_ARMv7M.S', - 'embed/segger/SEGGER/Syscalls/SEGGER_RTT_Syscalls_GCC.c', - 'embed/firmware/systemview.c', - ] - CPPPATH_MOD += [ - 'embed/segger/SEGGER/', - 'embed/segger/Config/', - ] - CPPDEFINES_MOD += ['SYSTEM_VIEW'] - CCFLAGS_MOD += '-DSYSTEM_VIEW ' - TRANSLATION_DATA = [ "translations/en.json", "translations/order.json", @@ -451,7 +431,6 @@ FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_ FILE_SUFFIX= env.get('ENV')['SUFFIX'] SOURCE_FIRMWARE = [ - 'embed/firmware/delay.c', 'embed/firmware/header.S', 'embed/firmware/main.c', 'embed/firmware/mphalport.c', @@ -891,24 +870,23 @@ else: VENDORHEADER = f'embed/models/{MODEL_IDENTIFIER}/vendorheader/vendorheader_{vendor}.bin' -if TREZOR_MODEL not in ('1',): - obj_program.extend( - env.Command( - target='embed/firmware/vendorheader.o', - source=VENDORHEADER, - action='$OBJCOPY -I binary -O elf32-littlearm -B arm' - ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' - ' $SOURCE $TARGET', )) +obj_program.extend( + env.Command( + target='embed/firmware/vendorheader.o', + source=VENDORHEADER, + action='$OBJCOPY -I binary -O elf32-littlearm -B arm' + ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' + ' $SOURCE $TARGET', )) + + +tools.embed_raw_binary( + obj_program, + env, + 'kernel', + 'build/kernel/kernel.o', + f'build/kernel/kernel.bin', + ) -if TREZOR_MODEL not in ('DISC1', 'DISC2'): - tools.embed_compressed_binary( - obj_program, - env, - 'bootloader', - 'embed/bootloaders/bootloader.o', - f'embed/models/{MODEL_IDENTIFIER}/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin', - 'firmware' - ) env.Depends(obj_program, qstr_generated) @@ -932,7 +910,7 @@ if CMAKELISTS != 0: env.Depends(program_elf, cmake_gen) env.Depends(program_elf, rust) -BINARY_NAME = f"build/firmware/firmware-{models.get_model_identifier(TREZOR_MODEL)}" +BINARY_NAME = f"build/firmware/firmware-{MODEL_IDENTIFIER}" if not EVERYTHING: BINARY_NAME += "-btconly" BINARY_NAME += "-" + tools.get_version('embed/firmware/version.h') @@ -941,30 +919,23 @@ BINARY_NAME += "-dirty" if tools.get_git_modified() else "" BINARY_NAME += ".bin" -if TREZOR_MODEL in ('1'): +if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: action_bin=[ - '$OBJCOPY -O binary -j .header -j .flash -j .data -j .confidential $SOURCE $TARGET', - '../legacy/bootloader/firmware_sign.py -f $TARGET', + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', + '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', + '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', '$CP $TARGET ' + BINARY_NAME, ] -else: - if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential --pad-to 0x08100000 $SOURCE ${TARGET}.p1', - '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', - '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', - '$CP $TARGET ' + BINARY_NAME, +elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$CP $TARGET ' + BINARY_NAME, ] - elif 'STM32U5A9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL: - action_bin=[ - '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .confidential $SOURCE ${TARGET}', - '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), - '$CP $TARGET ' + BINARY_NAME, - ] - else: - raise Exception("Unknown MCU") +else: + raise Exception("Unknown MCU") program_bin = env.Command( target='firmware.bin', diff --git a/core/SConstruct b/core/SConstruct index 4bca3b7423a..6446691cf3e 100644 --- a/core/SConstruct +++ b/core/SConstruct @@ -8,7 +8,6 @@ SConscript('SConscript.bootloader', variant_dir='build/bootloader', duplicate=Fa SConscript('SConscript.bootloader_ci', variant_dir='build/bootloader_ci', duplicate=False) SConscript('SConscript.bootloader_emu', variant_dir='build/bootloader_emu', duplicate=False) SConscript('SConscript.kernel', variant_dir='build/kernel', duplicate=False) -SConscript('SConscript.coreapp', variant_dir='build/coreapp', duplicate=False) SConscript('SConscript.firmware', variant_dir='build/firmware', duplicate=False) SConscript('SConscript.prodtest', variant_dir='build/prodtest', duplicate=False) SConscript('SConscript.reflash', variant_dir='build/reflash', duplicate=False) diff --git a/core/embed/coreapp/header.S b/core/embed/coreapp/header.S deleted file mode 100644 index 3531e239553..00000000000 --- a/core/embed/coreapp/header.S +++ /dev/null @@ -1,54 +0,0 @@ - .syntax unified - -#include "version.h" - - .section .header, "a" - - .type g_header, %object - .size g_header, .-g_header - -// Firmware header for both Trezor One and Trezor T. -// Trezor One must have bootloader version >= 1.8.0 (before that version the hdrlen used to be reset vector) - -g_header: - .byte 'T','R','Z','F' // magic - .word g_header_end - g_header // hdrlen -#ifdef TREZOR_MODEL_T - .word 0 // expiry -#else - .word 1 // expiry -#endif - .word _codelen // codelen - .byte VERSION_MAJOR // vmajor - .byte VERSION_MINOR // vminor - .byte VERSION_PATCH // vpatch - .byte VERSION_BUILD // vbuild - .byte FIX_VERSION_MAJOR // fix_vmajor - .byte FIX_VERSION_MINOR // fix_vminor - .byte FIX_VERSION_PATCH // fix_vpatch - .byte FIX_VERSION_BUILD // fix_vbuild - .word HW_MODEL // type of the designated hardware - .byte HW_REVISION // revision of the designated hardware - .byte VERSION_MONOTONIC // monotonic version of the binary - . = . + 2 // reserved - . = . + 512 // hash1 ... hash16 - -#if !defined TREZOR_MODEL_1 -// trezor-core header style - . = . + 415 // reserved - .byte 0 // sigmask - . = . + 64 // sig -#else -// model 1 compatibility header - . = . + 64 // sig1 - . = . + 64 // sig2 - . = . + 64 // sig3 - .byte 0 // sigindex1 - .byte 0 // sigindex2 - .byte 0 // sigindex3 - . = . + 220 // reserved - . = . + 65 // reserved -#endif - -g_header_end: - diff --git a/core/embed/coreapp/main.c b/core/embed/coreapp/main.c deleted file mode 100644 index 6a51611729e..00000000000 --- a/core/embed/coreapp/main.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 STM32_HAL_H - -#include -#include -#include - -#include "py/builtin.h" -#include "py/compile.h" -#include "py/gc.h" -#include "py/mperrno.h" -#include "py/nlr.h" -#include "py/repl.h" -#include "py/runtime.h" -#include "py/stackctrl.h" -#include "shared/runtime/pyexec.h" - -#include "ports/stm32/gccollect.h" -#include "ports/stm32/pendsv.h" - -#include "error_handling.h" -#include "rsod.h" -#include "rust_ui_common.h" -#include "secbool.h" -#include "systask.h" -#include "system.h" - -#ifdef USE_SECP256K1_ZKP -#include "zkp_context.h" -#endif - -int main(uint32_t cmd, void *arg) { - if (cmd == 1) { - systask_postmortem_t *info = (systask_postmortem_t *)arg; - rsod_gui(info); - system_exit(0); - } - - screen_boot_stage_2(); - - // uint32_t *p = 0; - // *p = 0; - -#ifdef USE_SECP256K1_ZKP - ensure(sectrue * (zkp_context_init() == 0), NULL); -#endif - - 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); - -#if MICROPY_ENABLE_PYSTACK - static mp_obj_t pystack[1024]; - mp_pystack_init(pystack, &pystack[MP_ARRAY_SIZE(pystack)]); -#endif - - // GC init - printf("CORE: Starting GC\n"); - gc_init(&_heap_start, &_heap_end); - - // Interpreter init - printf("CORE: Starting interpreter\n"); - mp_init(); - mp_obj_list_init(mp_sys_argv, 0); - mp_obj_list_init(mp_sys_path, 0); - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen)); - - // Execute the main script - printf("CORE: Executing main script\n"); - pyexec_frozen_module("main.py"); - - // Clean up - printf("CORE: Main script finished, cleaning up\n"); - mp_deinit(); - - // Python code shouldn't ever exit, avoid black screen if it does - error_shutdown("(PE)"); - - return 0; -} - -// MicroPython default exception handler - -void __attribute__((noreturn)) nlr_jump_fail(void *val) { - error_shutdown("(UE)"); -} - -// MicroPython builtin stubs - -mp_import_stat_t mp_import_stat(const char *path) { - return MP_IMPORT_STAT_NO_EXIST; -} - -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); diff --git a/core/embed/coreapp/mpconfigport.h b/core/embed/coreapp/mpconfigport.h deleted file mode 100644 index 0e9e990b1b6..00000000000 --- a/core/embed/coreapp/mpconfigport.h +++ /dev/null @@ -1,224 +0,0 @@ -// clang-format off - -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013-2017 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Options to control how MicroPython is built for this port, -// overriding defaults in py/mpconfig.h. - -#pragma once -#ifndef __INCLUDED_MPCONFIGPORT_H -#define __INCLUDED_MPCONFIGPORT_H - -// frozen modules -#define MICROPY_MODULE_FROZEN_MPY (1) -#define MICROPY_QSTR_EXTRA_POOL (mp_qstr_frozen_const_pool) - -// memory allocation policies -#define MICROPY_ALLOC_PATH_MAX (128) -#define MICROPY_ENABLE_PYSTACK (1) -#define MICROPY_LOADED_MODULES_DICT_SIZE (160) - -// emitters -#define MICROPY_PERSISTENT_CODE_LOAD (0) -#define MICROPY_EMIT_THUMB (0) -#define MICROPY_EMIT_INLINE_THUMB (0) - -// compiler configuration -#define MICROPY_ENABLE_COMPILER (0) -#define MICROPY_COMP_MODULE_CONST (1) -#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) -#define MICROPY_COMP_RETURN_IF_EXPR (1) - -// optimisations -#define MICROPY_OPT_COMPUTED_GOTO (1) -#define MICROPY_OPT_MPZ_BITWISE (1) -#define MICROPY_OPT_MATH_FACTORIAL (0) -#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (1) -#define MICROPY_OPT_MAP_LOOKUP_CACHE (1) - -#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) - -// Python internal features -#define MICROPY_READER_VFS (0) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_STACK_CHECK (1) -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) -#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_REPL_EMACS_KEYS (1) -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_ENABLE_SOURCE_LINE (1) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) -#define MICROPY_STREAMS_NON_BLOCK (1) -#define MICROPY_MODULE_WEAK_LINKS (1) -#define MICROPY_CAN_OVERRIDE_BUILTINS (0) -#define MICROPY_USE_INTERNAL_ERRNO (1) -#define MICROPY_ENABLE_SCHEDULER (0) -#define MICROPY_SCHEDULER_DEPTH (0) -#define MICROPY_VFS (0) - -// control over Python builtins -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_DESCRIPTORS (0) -#define MICROPY_PY_DELATTR_SETATTR (0) -#define MICROPY_PY_BUILTINS_STR_UNICODE (1) -#define MICROPY_PY_BUILTINS_STR_CENTER (1) -#define MICROPY_PY_BUILTINS_STR_PARTITION (1) -#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_BUILTINS_FROZENSET (0) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) -#define MICROPY_PY_BUILTINS_SLICE_INDICES (0) -#define MICROPY_PY_BUILTINS_ROUND_INT (0) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) -#define MICROPY_PY_ALL_SPECIAL_METHODS (0) -#define MICROPY_PY_BUILTINS_COMPILE (MICROPY_ENABLE_COMPILER) -#define MICROPY_PY_BUILTINS_EXECFILE (MICROPY_ENABLE_COMPILER) -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_BUILTINS_INPUT (0) -#define MICROPY_PY_BUILTINS_POW3 (0) -#define MICROPY_PY_BUILTINS_HELP (0) -#define MICROPY_PY_BUILTINS_HELP_TEXT stm32_help_text -#define MICROPY_PY_BUILTINS_HELP_MODULES (0) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) -#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_COLLECTIONS_DEQUE (0) -#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) -#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) -#define MICROPY_PY_MATH_ISCLOSE (0) -#define MICROPY_PY_MATH_FACTORIAL (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_IO (0) -#define MICROPY_PY_IO_IOBASE (0) -#define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT) // because mp_type_fileio/textio point to fatfs impl -#define MICROPY_PY_SYS_MAXSIZE (0) -#define MICROPY_PY_SYS_EXIT (0) -#define MICROPY_PY_SYS_STDFILES (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_SYS_PLATFORM "trezor" -#define MICROPY_PY_UERRNO (0) -#define MICROPY_PY_THREAD (0) -#define MICROPY_PY_FSTRINGS (1) - -// extended modules -#define MICROPY_PY_UCTYPES (1) -#define MICROPY_PY_UZLIB (0) -#define MICROPY_PY_UJSON (0) -#define MICROPY_PY_UOS (0) -#define MICROPY_PY_URE (0) -#define MICROPY_PY_URE_SUB (0) -#define MICROPY_PY_UHEAPQ (0) -#define MICROPY_PY_UHASHLIB (0) -#define MICROPY_PY_UHASHLIB_MD5 (0) -#define MICROPY_PY_UHASHLIB_SHA1 (0) -#define MICROPY_PY_UCRYPTOLIB (0) -#define MICROPY_PY_UBINASCII (1) -#define MICROPY_PY_UBINASCII_CRC32 (0) -#define MICROPY_PY_URANDOM (0) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) -#define MICROPY_PY_USELECT (0) -#define MICROPY_PY_UTIME (1) -#define MICROPY_PY_UTIMEQ (1) -#define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_OS_DUPTERM (0) -#define MICROPY_PY_LWIP_SOCK_RAW (0) -#define MICROPY_PY_MACHINE (0) -#define MICROPY_PY_UWEBSOCKET (0) -#define MICROPY_PY_WEBREPL (0) -#define MICROPY_PY_FRAMEBUF (0) -#define MICROPY_PY_USOCKET (0) -#define MICROPY_PY_NETWORK (0) - -#define MICROPY_PY_TREZORCONFIG (1) -#define MICROPY_PY_TREZORCRYPTO (1) -#define MICROPY_PY_TREZORIO (1) -#define MICROPY_PY_TREZORUI (1) -#define MICROPY_PY_TREZORUTILS (1) -#define MICROPY_PY_TREZORPROTO (1) -#define MICROPY_PY_TREZORTRANSLATE (1) -#define MICROPY_PY_TREZORUI2 (1) - -#ifdef SYSTEM_VIEW -#define MP_PLAT_PRINT_STRN(str, len) segger_print(str, len) -// uncomment DEST_RTT and comment DEST_SYSTEMVIEW -// if you want to print to RTT instead of SystemView -// OpenOCD supports only the RTT output method -// #define SYSTEMVIEW_DEST_RTT (1) -#define SYSTEMVIEW_DEST_SYSTEMVIEW (1) -#endif - -#define MP_STATE_PORT MP_STATE_VM - -// ============= this ends common config section =================== - - -// type definitions for the specific machine - -#define BYTES_PER_WORD (4) - -#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) - -#define MP_SSIZE_MAX (0x0fffffff) - -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -typedef long mp_off_t; - -#include "irq.h" - -#define MICROPY_BEGIN_ATOMIC_SECTION() irq_lock() -#define MICROPY_END_ATOMIC_SECTION(state) irq_unlock(state) -#define MICROPY_EVENT_POLL_HOOK \ - do { \ - extern void mp_handle_pending(bool); \ - mp_handle_pending(true); \ - __WFI(); \ - } while (0); - -#define MICROPY_HW_BOARD_NAME "TREZORv2" -#define MICROPY_HW_MCU_NAME "STM32F427xx" -#define MICROPY_HW_HAS_SDCARD 1 - -// There is no classical C heap in bare-metal ports, only Python -// garbage-collected heap. For completeness, emulate C heap via -// GC heap. Note that MicroPython core never uses malloc() and friends, -// so these defines are mostly to help extension module writers. -#define malloc(n) m_malloc(n) -#define free(p) m_free(p) -#define realloc(p, n) m_realloc(p, n) - -#define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t trezorconfig_ui_wait_callback; \ - -// We need to provide a declaration/definition of alloca() -#include - -#endif // __INCLUDED_MPCONFIGPORT_H diff --git a/core/embed/coreapp/mphalport.c b/core/embed/coreapp/mphalport.c deleted file mode 100644 index 9509ca37d55..00000000000 --- a/core/embed/coreapp/mphalport.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 "common.h" -#include "py/mphal.h" - -#include "systick.h" -#include "usb.h" - -static int vcp_iface_num = -1; - -int mp_hal_stdin_rx_chr(void) { - ensure(sectrue * (vcp_iface_num >= 0), "vcp stdio is not configured"); - uint8_t c = 0; - int r = usb_vcp_read_blocking(vcp_iface_num, &c, 1, -1); - (void)r; - return c; -} - -void mp_hal_stdout_tx_strn(const char *str, size_t len) { - if (vcp_iface_num >= 0) { - // The write timeout is set to 0, because otherwise when the VCP receive - // buffer on the host gets full, the timeout will block device operation. - int r = usb_vcp_write_blocking(vcp_iface_num, (const uint8_t *)str, len, 0); - (void)r; - } -} - -void mp_hal_set_vcp_iface(int iface_num) { vcp_iface_num = iface_num; } - -// Dummy implementation required by ports/stm32/gccollect.c. -// The normal version requires MICROPY_ENABLE_SCHEDULER which we don't use. -void soft_timer_gc_mark_all(void) {} - -void mp_hal_delay_ms(mp_uint_t Delay) { systick_delay_ms(Delay); } - -void mp_hal_delay_us(mp_uint_t usec) { systick_delay_us(usec); } - -mp_uint_t mp_hal_ticks_ms(void) { return systick_ms(); } - -mp_uint_t mp_hal_ticks_us(void) { return systick_ms() * 1000; } diff --git a/core/embed/coreapp/mphalport.h b/core/embed/coreapp/mphalport.h deleted file mode 100644 index 8954eec6312..00000000000 --- a/core/embed/coreapp/mphalport.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 "shared/runtime/interrupt_char.h" - -static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; } - -void mp_hal_set_vcp_iface(int iface_num); diff --git a/core/embed/coreapp/nlrthumb.c b/core/embed/coreapp/nlrthumb.c deleted file mode 100644 index 8fdaba88b20..00000000000 --- a/core/embed/coreapp/nlrthumb.c +++ /dev/null @@ -1,166 +0,0 @@ -// clang-format off - -/* - * 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 . - */ - -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013-2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma GCC optimize("no-stack-protector") // applies to all functions in this file - -#include "py/mpstate.h" -#include "py/nlr.h" - -#if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) - -#undef nlr_push - -// We only need the functions here if we are on arm/thumb, and we are not -// using setjmp/longjmp. -// -// For reference, arm/thumb callee save regs are: -// r4-r11, r13=sp - -__attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { - - __asm volatile ( - "str r4, [r0, #12] \n" // store r4 into nlr_buf - "str r5, [r0, #16] \n" // store r5 into nlr_buf - "str r6, [r0, #20] \n" // store r6 into nlr_buf - "str r7, [r0, #24] \n" // store r7 into nlr_buf - -#if defined(__ARM_ARCH_6M__) - "mov r1, r8 \n" - "str r1, [r0, #28] \n" // store r8 into nlr_buf - "mov r1, r9 \n" - "str r1, [r0, #32] \n" // store r9 into nlr_buf - "mov r1, r10 \n" - "str r1, [r0, #36] \n" // store r10 into nlr_buf - "mov r1, r11 \n" - "str r1, [r0, #40] \n" // store r11 into nlr_buf - "mov r1, r13 \n" - "str r1, [r0, #44] \n" // store r13=sp into nlr_buf - "mov r1, lr \n" - "str r1, [r0, #8] \n" // store lr into nlr_buf -#else - "str r8, [r0, #28] \n" // store r8 into nlr_buf - "str r9, [r0, #32] \n" // store r9 into nlr_buf - "str r10, [r0, #36] \n" // store r10 into nlr_buf - "str r11, [r0, #40] \n" // store r11 into nlr_buf - "str r13, [r0, #44] \n" // store r13=sp into nlr_buf - "str lr, [r0, #8] \n" // store lr into nlr_buf -#endif - -#if defined(__ARM_ARCH_6M__) - "ldr r1, nlr_push_tail_var \n" - "bx r1 \n" // do the rest in C - ".align 2 \n" - "nlr_push_tail_var: .word nlr_push_tail \n" -#else - "b nlr_push_tail \n" // do the rest in C -#endif - ); - - return 0; // needed to silence compiler warning -} - -__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - nlr->prev = *top; - *top = nlr; - return 0; // normal return -} - -void nlr_pop(void) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - *top = (*top)->prev; -} - -NORETURN __attribute__((naked)) void nlr_jump(void *val) { - nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); - nlr_buf_t *top = *top_ptr; - if (top == NULL) { - nlr_jump_fail(val); - } - - top->ret_val = val; - *top_ptr = top->prev; - - __asm volatile ( - "mov r0, %0 \n" // r0 points to nlr_buf - "ldr r4, [r0, #12] \n" // load r4 from nlr_buf - "ldr r5, [r0, #16] \n" // load r5 from nlr_buf - "ldr r6, [r0, #20] \n" // load r6 from nlr_buf - "ldr r7, [r0, #24] \n" // load r7 from nlr_buf - -#if defined(__ARM_ARCH_6M__) - "ldr r1, [r0, #28] \n" // load r8 from nlr_buf - "mov r8, r1 \n" - "ldr r1, [r0, #32] \n" // load r9 from nlr_buf - "mov r9, r1 \n" - "ldr r1, [r0, #36] \n" // load r10 from nlr_buf - "mov r10, r1 \n" - "ldr r1, [r0, #40] \n" // load r11 from nlr_buf - "mov r11, r1 \n" - "ldr r1, [r0, #44] \n" // load r13=sp from nlr_buf - "mov r13, r1 \n" - "ldr r1, [r0, #8] \n" // load lr from nlr_buf - "mov lr, r1 \n" -#else - "ldr r8, [r0, #28] \n" // load r8 from nlr_buf - "ldr r9, [r0, #32] \n" // load r9 from nlr_buf - "ldr r10, [r0, #36] \n" // load r10 from nlr_buf - "ldr r11, [r0, #40] \n" // load r11 from nlr_buf - "ldr r13, [r0, #44] \n" // load r13=sp from nlr_buf - "ldr lr, [r0, #8] \n" // load lr from nlr_buf -#endif - "movs r0, #1 \n" // return 1, non-local return - "bx lr \n" // return - : // output operands - : "r"(top) // input operands - : // clobbered registers - ); - - for (;;); // needed to silence compiler warning -} - -#endif // (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) diff --git a/core/embed/coreapp/version.h b/core/embed/coreapp/version.h deleted file mode 100644 index b1b21300ce3..00000000000 --- a/core/embed/coreapp/version.h +++ /dev/null @@ -1,11 +0,0 @@ -#define VERSION_MAJOR 2 -#define VERSION_MINOR 8 -#define VERSION_PATCH 2 -#define VERSION_BUILD 0 - -#define FIX_VERSION_MAJOR 2 -#define FIX_VERSION_MINOR 8 -#define FIX_VERSION_PATCH 0 -#define FIX_VERSION_BUILD 0 - -#define VERSION_MONOTONIC 1 diff --git a/core/embed/firmware/delay.c b/core/embed/firmware/delay.c deleted file mode 100644 index 037b0665bf8..00000000000 --- a/core/embed/firmware/delay.c +++ /dev/null @@ -1,101 +0,0 @@ -// clang-format off - -/* - * 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 . - */ - -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/runtime.h" -#include "py/mphal.h" -#include "irq.h" -#include "systick.h" - -extern __IO uint32_t uwTick; - -// Core delay function that does an efficient sleep and may switch thread context. -// If IRQs are enabled then we must have the GIL. -void mp_hal_delay_ms(mp_uint_t Delay) { - if (IS_IRQ_ENABLED(query_irq())) { - // IRQs enabled, so can use systick counter to do the delay - uint32_t start = uwTick; - // Wraparound of tick is taken care of by 2's complement arithmetic. - while (uwTick - start < Delay) { - // This macro will execute the necessary idle behaviour. It may - // raise an exception, switch threads or enter sleep mode (waiting for - // (at least) the SysTick interrupt). - MICROPY_EVENT_POLL_HOOK - } - } else { - // IRQs disabled, so need to use a busy loop for the delay. - // To prevent possible overflow of the counter we use a double loop. - const uint32_t count_1ms = HAL_RCC_GetSysClockFreq() / 4000; - for (int i = 0; i < Delay; i++) { - for (uint32_t count = 0; ++count <= count_1ms;) { - } - } - } -} - -// delay for given number of microseconds -void mp_hal_delay_us(mp_uint_t usec) { - if (IS_IRQ_ENABLED(query_irq())) { - // IRQs enabled, so can use systick counter to do the delay - uint32_t start = mp_hal_ticks_us(); - while (mp_hal_ticks_us() - start < usec) { - } - } else { - // IRQs disabled, so need to use a busy loop for the delay - // sys freq is always a multiple of 2MHz, so division here won't lose precision - const uint32_t ucount = HAL_RCC_GetSysClockFreq() / 2000000 * usec / 2; - for (uint32_t count = 0; ++count <= ucount;) { - } - } -} - -mp_uint_t mp_hal_ticks_ms(void) { - return systick_ms(); -} - -mp_uint_t mp_hal_ticks_us(void) { - return systick_ms() * 1000; -} diff --git a/core/embed/firmware/firmware_flash.jlink b/core/embed/firmware/firmware_flash.jlink deleted file mode 100644 index 8292e2f66e9..00000000000 --- a/core/embed/firmware/firmware_flash.jlink +++ /dev/null @@ -1,8 +0,0 @@ -device stm32f427vi -if swd -speed 50000 -loadbin build/firmware/firmware.bin.p1.bin 0x08040000 -loadbin build/firmware/firmware.bin.p2.bin 0x08120000 -r -g -exit diff --git a/core/embed/firmware/firmware_flash_t1.jlink b/core/embed/firmware/firmware_flash_t1.jlink deleted file mode 100644 index 14f786c3ec8..00000000000 --- a/core/embed/firmware/firmware_flash_t1.jlink +++ /dev/null @@ -1,7 +0,0 @@ -device STM32F205RG -if swd -speed 50000 -loadbin build/firmware/firmware.bin 0x08010000 -r -g -exit diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index aa3224803c8..99c29dba3d6 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -36,204 +36,26 @@ #include "ports/stm32/gccollect.h" #include "ports/stm32/pendsv.h" -#include "bl_check.h" -#include "board_capabilities.h" -#include "common.h" -#include "compiler_traits.h" -#include "display.h" -#include "entropy.h" -#include "flash.h" -#include "image.h" -#include "memzero.h" -#include "model.h" -#include "mpu.h" -#include "random_delays.h" +#include "error_handling.h" #include "rsod.h" -#include "rust_ui.h" -#include "secure_aes.h" +#include "rust_ui_common.h" +#include "secbool.h" +#include "systask.h" #include "system.h" -#include "systimer.h" -#include TREZOR_BOARD - -#ifdef USE_RGB_LED -#include "rgb_led.h" -#endif -#ifdef USE_CONSUMPTION_MASK -#include "consumption_mask.h" -#endif -#ifdef USE_DMA2D -#ifdef NEW_RENDERING -#include "dma2d_bitblt.h" -#else -#include "dma2d.h" -#endif -#endif - -#ifdef USE_BUTTON -#include "button.h" -#endif -#ifdef USE_TOUCH -#include "touch.h" -#endif -#ifdef USE_SD_CARD -#include "sdcard.h" -#endif -#ifdef USE_HASH_PROCESSOR -#include "hash_processor.h" -#endif - -#ifdef USE_OPTIGA -#include "optiga_commands.h" -#include "optiga_transport.h" -#endif -#if defined USE_OPTIGA | defined STM32U5 -#include "secret.h" -#endif - -#include "unit_variant.h" - -#ifdef SYSTEM_VIEW -#include "systemview.h" -#endif -#include "platform.h" -#include "rng.h" #ifdef USE_SECP256K1_ZKP #include "zkp_context.h" #endif -#ifdef USE_HAPTIC -#include "haptic.h" -#endif -#ifdef USE_OPTIGA -#if !PYOPT -#include -#if 1 // color log -#define OPTIGA_LOG_FORMAT \ - "%" PRIu32 " \x1b[35moptiga\x1b[0m \x1b[32mDEBUG\x1b[0m %s: " -#else -#define OPTIGA_LOG_FORMAT "%" PRIu32 " optiga DEBUG %s: " -#endif -static void optiga_log_hex(const char *prefix, const uint8_t *data, - size_t data_size) { - printf(OPTIGA_LOG_FORMAT, hal_ticks_ms() * 1000, prefix); - for (size_t i = 0; i < data_size; i++) { - printf("%02x", data[i]); +int main(uint32_t cmd, void *arg) { + if (cmd == 1) { + systask_postmortem_t *info = (systask_postmortem_t *)arg; + rsod_gui(info); + system_exit(0); } - printf("\n"); -} -#endif -#endif - -int main(void) { - system_init(&rsod_gui); - - rdi_init(); - -#ifdef RDI - rdi_start(); -#endif - - // reinitialize HAL for Trezor One -#if defined TREZOR_MODEL_1 - HAL_Init(); -#endif - -#ifdef SYSTEM_VIEW - enable_systemview(); -#endif - -#ifdef USE_HASH_PROCESSOR - hash_processor_init(); -#endif - -#ifdef USE_DMA2D - dma2d_init(); -#endif - - display_init(DISPLAY_JUMP_BEHAVIOR); - -#ifdef STM32U5 - check_oem_keys(); -#endif screen_boot_stage_2(); -#if !defined TREZOR_MODEL_1 - parse_boardloader_capabilities(); - - unit_variant_init(); - -#ifdef STM32U5 - secure_aes_init(); -#endif - -#ifdef USE_OPTIGA - uint8_t secret[SECRET_OPTIGA_KEY_LEN] = {0}; - secbool secret_ok = secret_optiga_get(secret); -#endif - - entropy_init(); - -#if PRODUCTION || BOOTLOADER_QA - check_and_replace_bootloader(); -#endif - -#endif - - // Init peripherals - -#if defined TREZOR_MODEL_T - set_core_clock(CLOCK_180_MHZ); -#endif - -#ifdef USE_BUTTON - button_init(); -#endif - -#ifdef USE_RGB_LED - rgb_led_init(); -#endif - -#ifdef USE_CONSUMPTION_MASK - consumption_mask_init(); -#endif - -#ifdef USE_TOUCH - touch_init(); -#endif - -#ifdef USE_SD_CARD - sdcard_init(); -#endif - -#ifdef USE_HAPTIC - haptic_init(); -#endif - -#ifdef USE_OPTIGA - -#if !PYOPT - // command log is relatively quiet so we enable it in debug builds - optiga_command_set_log_hex(optiga_log_hex); - // transport log can be spammy, uncomment if you want it: - // optiga_transport_set_log_hex(optiga_log_hex); -#endif - - optiga_init(); - if (sectrue == secret_ok) { - // If the shielded connection cannot be established, reset Optiga and - // continue without it. In this case, OID_KEY_FIDO and OID_KEY_DEV cannot be - // used, which means device and FIDO attestation will not work. - if (optiga_sec_chan_handshake(secret, sizeof(secret)) != OPTIGA_SUCCESS) { - optiga_soft_reset(); - } - } - memzero(secret, sizeof(secret)); - ensure(sectrue * (optiga_open_application() == OPTIGA_SUCCESS), - "Cannot initialize optiga."); -#endif - #ifdef USE_SECP256K1_ZKP ensure(sectrue * (zkp_context_init() == 0), NULL); #endif diff --git a/core/embed/firmware/mphalport.c b/core/embed/firmware/mphalport.c index 4c9d2a97f57..9509ca37d55 100644 --- a/core/embed/firmware/mphalport.c +++ b/core/embed/firmware/mphalport.c @@ -19,6 +19,8 @@ #include "common.h" #include "py/mphal.h" + +#include "systick.h" #include "usb.h" static int vcp_iface_num = -1; @@ -45,3 +47,11 @@ void mp_hal_set_vcp_iface(int iface_num) { vcp_iface_num = iface_num; } // Dummy implementation required by ports/stm32/gccollect.c. // The normal version requires MICROPY_ENABLE_SCHEDULER which we don't use. void soft_timer_gc_mark_all(void) {} + +void mp_hal_delay_ms(mp_uint_t Delay) { systick_delay_ms(Delay); } + +void mp_hal_delay_us(mp_uint_t usec) { systick_delay_us(usec); } + +mp_uint_t mp_hal_ticks_ms(void) { return systick_ms(); } + +mp_uint_t mp_hal_ticks_us(void) { return systick_ms() * 1000; } diff --git a/core/embed/firmware/startup_stm32f4.S b/core/embed/firmware/startup_stm32f4.S deleted file mode 100644 index 7d0fadf2cda..00000000000 --- a/core/embed/firmware/startup_stm32f4.S +++ /dev/null @@ -1,69 +0,0 @@ - .syntax unified - - .text - - .global reset_handler - .type reset_handler, STT_FUNC -reset_handler: - -// The following loading of VTOR address only works if T1 bootloader was built with PRODUCTION=0 -// or the firmware was properly signed. All other variants end up in hard fault due to MPU -// (cf mpu_config_firmware in legacy bootloader) - -#if defined TREZOR_MODEL_1 - cpsid if - ldr r0, =0xE000ED08 // r0 = VTOR address - ldr r1, =0x08010400 // r1 = FLASH_APP_START - str r1, [r0] // assign - - ldr r0, =_estack // r0 = stack pointer - msr msp, r0 // set stack pointer - dsb - isb -#endif - - // setup environment for subsequent stage of code - ldr r0, =ccmram_start // r0 - point to beginning of CCMRAM - ldr r1, =ccmram_end // r1 - point to byte after the end of CCMRAM - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of BOOT_ARGS - ldr r1, =boot_args_end // r1 - point to byte after the end of BOOT_ARGS - ldr r2, =0 // r2 - the word-sized value to be written - bl memset_reg - - ldr r0, =sram_start // r0 - point to beginning of SRAM - ldr r1, =sram_end // r1 - point to byte after the end of SRAM - ldr r2, =0 // r2 - the word-sized value to be written - 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." -#if defined STM32F405xx - cpsie if -#elif defined STM32F427xx || defined STM32F429xx - cpsie f -#else - #error "Unknown MCU" -#endif - - // enter the application code - bl main - - b shutdown_privileged - - .end diff --git a/core/embed/firmware/startup_stm32u5.S b/core/embed/firmware/startup_stm32u5.S deleted file mode 100644 index db9a204c319..00000000000 --- a/core/embed/firmware/startup_stm32u5.S +++ /dev/null @@ -1,72 +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, =sram1_start // r0 - point to beginning of SRAM - ldr r1, =sram1_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram2_start // r0 - point to beginning of SRAM - ldr r1, =sram2_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram4_start // r0 - point to beginning of SRAM - ldr r1, =sram4_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =sram6_start // r0 - point to beginning of SRAM - ldr r1, =sram6_end // r1 - point to byte after the end of SRAM - bl memset_reg - - ldr r0, =boot_args_start // r0 - point to beginning of boot args - ldr r1, =boot_args_end // r1 - point to byte after the end of boot args - bl memset_reg - - ldr r0, =sram3_start // r0 - point to beginning of SRAM - ldr r1, =__fb_start // r1 - point to beginning of framebuffer - bl memset_reg - - ldr r0, =__fb_end // r0 - point to end of framebuffer - ldr r1, =sram5_end // r1 - point to byte after the end of SRAM - 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/trezorhal/stm32f4/linker/coreapp.ld b/core/embed/trezorhal/stm32f4/linker/coreapp.ld deleted file mode 100644 index ba5dc161ef3..00000000000 --- a/core/embed/trezorhal/stm32f4/linker/coreapp.ld +++ /dev/null @@ -1,99 +0,0 @@ -INCLUDE "./embed/trezorhal/stm32f4/linker/memory.ld"; - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_P1_IMAGE_MAXSIZE - FLASH2 (r) : ORIGIN = FIRMWARE_P2_START, LENGTH = FIRMWARE_P2_IMAGE_MAXSIZE - CCMRAM (wal) : ORIGIN = MCU_CCMRAM + KERNEL_STACK_SIZE, LENGTH = MCU_CCMRAM_SIZE - KERNEL_CCMRAM_SIZE - KERNEL_FRAMEBUFFER_SIZE - KERNEL_STACK_SIZE - SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE - KERNEL_SRAM_SIZE -} - -main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM); -_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); - -_codelen = LENGTH(FLASH) - SIZEOF(.vendorheader) - SIZEOF(.header) + SIZEOF(.flash2); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - } >FLASH AT>FLASH - - .flash2 : ALIGN(CODE_ALIGNMENT) { - build/coreapp/frozen_mpy.o(.rodata*); - build/coreapp/vendor/secp256k1-zkp/src/secp256k1.o(.rodata*); - build/coreapp/vendor/secp256k1-zkp/src/precomputed_ecmult.o(.rodata*); - build/coreapp/vendor/secp256k1-zkp/src/precomputed_ecmult_gen.o(.rodata*); - build/coreapp/vendor/trezor-crypto/aes/aestab.o(.rodata*); - . = ALIGN(4); - */libtrezor_lib.a:(.text*); - . = ALIGN(4); - */libtrezor_lib.a:(.rodata*); - . = ALIGN(512); - } >FLASH2 AT>FLASH2 - - .flash : ALIGN(512) { - KEEP(*(.kernel)); - . = ALIGN(512); - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(4); - . = ALIGN(512); - } >FLASH AT>FLASH - - .stack : ALIGN(8) { - . = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */ - } >SRAM - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM AT>FLASH - - .bss : ALIGN(4) { - *(.bss*); - . = ALIGN(4); - } >SRAM - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - } >SRAM - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(ORIGIN(SRAM) + LENGTH(SRAM)); /* this explicitly sets the end of the heap */ - } >SRAM - - .data_ccm : ALIGN(4) { - *(.no_dma_buffers*); - . = ALIGN(4); - } >CCMRAM - - - /DISCARD/ : { - *(.ARM.exidx*); - } - -} diff --git a/core/embed/trezorhal/stm32f4/linker/firmware.ld b/core/embed/trezorhal/stm32f4/linker/firmware.ld index efd26bd488f..64c8b2d11d2 100644 --- a/core/embed/trezorhal/stm32f4/linker/firmware.ld +++ b/core/embed/trezorhal/stm32f4/linker/firmware.ld @@ -5,36 +5,23 @@ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_P1_IMAGE_MAXSIZE FLASH2 (r) : ORIGIN = FIRMWARE_P2_START, LENGTH = FIRMWARE_P2_IMAGE_MAXSIZE - CCMRAM (wal) : ORIGIN = MCU_CCMRAM, LENGTH = MCU_CCMRAM_SIZE - BOOTARGS_SIZE - BOOT_ARGS (wal) : ORIGIN = MCU_CCMRAM + MCU_CCMRAM_SIZE - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE - SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE + CCMRAM (wal) : ORIGIN = MCU_CCMRAM + KERNEL_STACK_SIZE, LENGTH = MCU_CCMRAM_SIZE - KERNEL_CCMRAM_SIZE - KERNEL_FRAMEBUFFER_SIZE - KERNEL_STACK_SIZE + SRAM (wal) : ORIGIN = MCU_SRAM, LENGTH = MCU_SRAM_SIZE - KERNEL_SRAM_SIZE } main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ _sstack = ORIGIN(SRAM); _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 wipe memory */ -ccmram_start = ORIGIN(CCMRAM); -ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - -/* used by the startup code to wipe memory */ -sram_start = ORIGIN(SRAM); -sram_end = ORIGIN(SRAM) + LENGTH(SRAM); -_ram_start = sram_start; -_ram_end = sram_end; - _codelen = LENGTH(FLASH) - SIZEOF(.vendorheader) - SIZEOF(.header) + SIZEOF(.flash2); _flash_start = ORIGIN(FLASH); _flash_end = ORIGIN(FLASH) + LENGTH(FLASH); @@ -50,7 +37,7 @@ SECTIONS { KEEP(*(.header)); } >FLASH AT>FLASH - .flash2 : ALIGN(512) { + .flash2 : ALIGN(CODE_ALIGNMENT) { build/firmware/frozen_mpy.o(.rodata*); build/firmware/vendor/secp256k1-zkp/src/secp256k1.o(.rodata*); build/firmware/vendor/secp256k1-zkp/src/precomputed_ecmult.o(.rodata*); @@ -63,15 +50,15 @@ SECTIONS { . = ALIGN(512); } >FLASH2 AT>FLASH2 - .flash : ALIGN(CODE_ALIGNMENT) { + .flash : ALIGN(512) { + KEEP(*(.kernel)); + . = ALIGN(512); KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); . = ALIGN(4); *(.rodata*); . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); . = ALIGN(512); } >FLASH AT>FLASH @@ -96,7 +83,7 @@ SECTIONS { .heap : ALIGN(4) { . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram_end); /* this explicitly sets the end of the heap */ + . = ABSOLUTE(ORIGIN(SRAM) + LENGTH(SRAM)); /* this explicitly sets the end of the heap */ } >SRAM .data_ccm : ALIGN(4) { @@ -104,8 +91,9 @@ SECTIONS { . = ALIGN(4); } >CCMRAM - .boot_args : ALIGN(8) { - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS + + /DISCARD/ : { + *(.ARM.exidx*); + } + } diff --git a/core/embed/trezorhal/stm32u5/linker/u58/coreapp.ld b/core/embed/trezorhal/stm32u5/linker/u58/coreapp.ld deleted file mode 100644 index 1542e781ae4..00000000000 --- a/core/embed/trezorhal/stm32u5/linker/u58/coreapp.ld +++ /dev/null @@ -1,92 +0,0 @@ -INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; - -ENTRY(reset_handler) - -MEMORY { - FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = FIRMWARE_IMAGE_MAXSIZE - SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - KERNEL_SRAM1_SIZE - SRAM2 (wal) : ORIGIN = MCU_SRAM2 + KERNEL_SRAM2_SIZE, LENGTH = MCU_SRAM2_SIZE - KERNEL_SRAM2_SIZE - SRAM3 (wal) : ORIGIN = MCU_SRAM3 + KERNEL_SRAM3_SIZE, LENGTH = MCU_SRAM3_SIZE - KERNEL_SRAM3_SIZE - SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = 0K /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = 0K /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = 0K /* not allocated to coreapp */ -} - -main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ -_sstack = ORIGIN(SRAM2); -_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); - -_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); -_flash_start = ORIGIN(FLASH); -_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); -_heap_start = ADDR(.heap); -_heap_end = ADDR(.heap) + SIZEOF(.heap); - -SECTIONS { - .vendorheader : ALIGN(4) { - KEEP(*(.vendorheader)) - } >FLASH AT>FLASH - - .header : ALIGN(4) { - KEEP(*(.header)); - . = ALIGN(CODE_ALIGNMENT); - } >FLASH AT>FLASH - - .flash : ALIGN(CODE_ALIGNMENT) { - KEEP(*(.kernel)); - . = ALIGN(512); - KEEP(*(.vector_table)); - . = ALIGN(4); - *(.text*); - . = ALIGN(4); - *(.rodata*); - . = ALIGN(512); - } >FLASH AT>FLASH - - .data : ALIGN(4) { - *(.data*); - . = ALIGN(512); - } >SRAM1 AT>FLASH - - /DISCARD/ : { - *(.ARM.exidx*); - } - - .bss : ALIGN(4) { - *(.no_dma_buffers*); - *(.bss*); - . = ALIGN(4); - } >SRAM1 - - .stack : ALIGN(8) { - . = 32K; /* Overflow causes UsageFault */ - } >SRAM2 - - .confidential : ALIGN(512) { - *(.confidential*); - . = ALIGN(512); - } >SRAM2 AT>FLASH - - .buf : ALIGN(4) { - *(.buf*); - . = ALIGN(4); - } >SRAM3 - - .heap : ALIGN(4) { - . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(ORIGIN(SRAM3) + LENGTH(SRAM3)); /* this explicitly sets the end of the heap */ - } >SRAM3 -} diff --git a/core/embed/trezorhal/stm32u5/linker/u58/firmware.ld b/core/embed/trezorhal/stm32u5/linker/u58/firmware.ld index 86d28950350..1542e781ae4 100644 --- a/core/embed/trezorhal/stm32u5/linker/u58/firmware.ld +++ b/core/embed/trezorhal/stm32u5/linker/u58/firmware.ld @@ -3,19 +3,19 @@ INCLUDE "./embed/trezorhal/stm32u5/linker/u58/memory.ld"; ENTRY(reset_handler) MEMORY { - FLASH (rx) : ORIGIN = FIRMWARE_START, LENGTH = FIRMWARE_IMAGE_MAXSIZE - SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - BOOTARGS_SIZE - BOOT_ARGS (wal) : ORIGIN = MCU_SRAM2 - BOOTARGS_SIZE, LENGTH = BOOTARGS_SIZE - SRAM2 (wal) : ORIGIN = MCU_SRAM2, LENGTH = MCU_SRAM2_SIZE - SRAM3 (wal) : ORIGIN = MCU_SRAM3, LENGTH = MCU_SRAM3_SIZE - SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = MCU_SRAM5_SIZE /* SRAM5 is not available */ - SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = MCU_SRAM6_SIZE /* SRAM6 is not available */ - SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = MCU_SRAM4_SIZE + FLASH (rx) : ORIGIN = KERNEL_START, LENGTH = FIRMWARE_IMAGE_MAXSIZE + SRAM1 (wal) : ORIGIN = MCU_SRAM1, LENGTH = MCU_SRAM1_SIZE - KERNEL_SRAM1_SIZE + SRAM2 (wal) : ORIGIN = MCU_SRAM2 + KERNEL_SRAM2_SIZE, LENGTH = MCU_SRAM2_SIZE - KERNEL_SRAM2_SIZE + SRAM3 (wal) : ORIGIN = MCU_SRAM3 + KERNEL_SRAM3_SIZE, LENGTH = MCU_SRAM3_SIZE - KERNEL_SRAM3_SIZE + SRAM5 (wal) : ORIGIN = MCU_SRAM5, LENGTH = 0K /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = MCU_SRAM6, LENGTH = 0K /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = MCU_SRAM4, LENGTH = 0K /* not allocated to coreapp */ } main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ _sstack = ORIGIN(SRAM2); _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); @@ -29,29 +29,6 @@ confidential_lma = LOADADDR(.confidential); confidential_vma = ADDR(.confidential); confidential_size = SIZEOF(.confidential); -/* used by the startup/jump code to wipe memory */ -_handoff_clear_ram_0_start = ORIGIN(SRAM1); -_handoff_clear_ram_0_end = ORIGIN(BOOT_ARGS); -_handoff_clear_ram_1_start = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -_handoff_clear_ram_1_end = ORIGIN(SRAM6)+ LENGTH(SRAM6); -_handoff_clear_ram_2_start = ORIGIN(SRAM4); -_handoff_clear_ram_2_end = ORIGIN(SRAM4) + LENGTH(SRAM4); - -/* used by the shutdown code to wipe memory */ -_shutdown_clear_ram_0_start = ORIGIN(SRAM1); -_shutdown_clear_ram_0_end = ORIGIN(SRAM6)+ LENGTH(SRAM6); -_shutdown_clear_ram_1_start = ORIGIN(SRAM4); -_shutdown_clear_ram_1_end = ORIGIN(SRAM4) + LENGTH(SRAM4); -_shutdown_clear_ram_2_start = 0; -_shutdown_clear_ram_2_end = 0; -_shutdown_clear_ram_3_start = 0; -_shutdown_clear_ram_3_end = 0; - - -/* reserve 256 bytes for bootloader arguments */ -boot_args_start = ORIGIN(BOOT_ARGS); -boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); - _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential); _flash_start = ORIGIN(FLASH); _flash_end = ORIGIN(FLASH) + LENGTH(FLASH); @@ -65,17 +42,17 @@ SECTIONS { .header : ALIGN(4) { KEEP(*(.header)); + . = ALIGN(CODE_ALIGNMENT); } >FLASH AT>FLASH .flash : ALIGN(CODE_ALIGNMENT) { + KEEP(*(.kernel)); + . = ALIGN(512); KEEP(*(.vector_table)); . = ALIGN(4); *(.text*); . = ALIGN(4); *(.rodata*); - . = ALIGN(4); - KEEP(*(.bootloader)); - *(.bootloader*); . = ALIGN(512); } >FLASH AT>FLASH @@ -103,14 +80,6 @@ SECTIONS { . = ALIGN(512); } >SRAM2 AT>FLASH - .fb : ALIGN(4) { - __fb_start = .; - *(.fb1*); - *(.fb2*); - __fb_end = .; - . = ALIGN(4); - } >SRAM3 - .buf : ALIGN(4) { *(.buf*); . = ALIGN(4); @@ -118,13 +87,6 @@ SECTIONS { .heap : ALIGN(4) { . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ - . = ABSOLUTE(sram3_end); /* this explicitly sets the end of the heap */ + . = ABSOLUTE(ORIGIN(SRAM3) + LENGTH(SRAM3)); /* this explicitly sets the end of the heap */ } >SRAM3 - - .boot_args : ALIGN(8) { - *(.boot_command*); - . = ALIGN(8); - *(.boot_args*); - . = ALIGN(8); - } >BOOT_ARGS } diff --git a/core/embed/trezorhal/stm32u5/linker/u5a/coreapp.ld b/core/embed/trezorhal/stm32u5/linker/u5a/firmware.ld similarity index 100% rename from core/embed/trezorhal/stm32u5/linker/u5a/coreapp.ld rename to core/embed/trezorhal/stm32u5/linker/u5a/firmware.ld From 23ff195b39e030cd16f34b6cb5303aa0a6bde22e Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 19 Sep 2024 16:52:18 +0200 Subject: [PATCH 44/44] fix(core/embed): fix firmware invalidation [no changelog] --- core/embed/trezorhal/stm32f4/fwutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/embed/trezorhal/stm32f4/fwutils.c b/core/embed/trezorhal/stm32f4/fwutils.c index e2a6a5a39d8..e0d4ad36946 100644 --- a/core/embed/trezorhal/stm32f4/fwutils.c +++ b/core/embed/trezorhal/stm32f4/fwutils.c @@ -105,7 +105,7 @@ void firmware_invalidate_header(void) { // erase start of the firmware (metadata) -> invalidate FW ensure(flash_unlock_write(), NULL); - for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i += FLASH_BLOCK_SIZE) { + for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i++) { flash_block_t data = {0}; ensure(flash_area_write_block(&FIRMWARE_AREA, i * FLASH_BLOCK_SIZE, data), NULL);