diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 866f3ad1b9..6c5bee2c63 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -24,6 +24,7 @@ FEATURES_WANTED = [ "secure_domain", "tropic", "usb", + "iwdg", ] if TREZOR_MODEL in ('T3W1', ): diff --git a/core/embed/sec/iwdg/inc/sec/iwdg.h b/core/embed/sec/iwdg/inc/sec/iwdg.h new file mode 100644 index 0000000000..d4d3942454 --- /dev/null +++ b/core/embed/sec/iwdg/inc/sec/iwdg.h @@ -0,0 +1,37 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#define IWDG_MAX_TIME (60 * 60 * 4) // 4 hours + +/** + * @brief Start the Independent Watchdog, to enforce reset after specified time + * elapsed. + * + * The IWDG is clocked from LSI, which is expected to be set to 250 Hz. + * The IWDG prescaler is set to 1024, which means that the watchdog + * will tick every 4.096 s. The time is floored to the nearest multiple of 4.096 + * s. + * + * @param time_s Watchdog timeout in seconds. Time is ceiled to IWDG_MAX_TIME. + */ +void iwdg_start(uint32_t time_s); diff --git a/core/embed/sec/iwdg/stm32/iwdg.c b/core/embed/sec/iwdg/stm32/iwdg.c new file mode 100644 index 0000000000..c4d69e442d --- /dev/null +++ b/core/embed/sec/iwdg/stm32/iwdg.c @@ -0,0 +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 . + */ +#ifdef SECURE_MODE + +#include +#include + +#include + +_Static_assert(LSI_VALUE == 250, "LSI_VALUE must be defined to 250 Hz"); + +void iwdg_start(uint32_t time_s) { + if (time_s > IWDG_MAX_TIME) { + // Limit the maximum watchdog timeout to 4 hours + time_s = IWDG_MAX_TIME; + } + + // Set the reload value based on the desired time in seconds + uint32_t reload_value = ((time_s * LSI_VALUE) / 1024) - 1; + + IWDG_HandleTypeDef hiwdg = {0}; + + hiwdg.Instance = IWDG; + hiwdg.Init.Prescaler = IWDG_PRESCALER_1024; + hiwdg.Init.Reload = reload_value; + hiwdg.Init.Window = 0xFFF; + hiwdg.Init.EWI = 0; + + // Configure the IWDG + HAL_IWDG_Init(&hiwdg); +} + +#endif diff --git a/core/embed/sys/bsp/stm32u5/stm32u5xx_hal_conf.h b/core/embed/sys/bsp/stm32u5/stm32u5xx_hal_conf.h index f213c6446e..0d98c93979 100644 --- a/core/embed/sys/bsp/stm32u5/stm32u5xx_hal_conf.h +++ b/core/embed/sys/bsp/stm32u5/stm32u5xx_hal_conf.h @@ -60,7 +60,7 @@ extern "C" { #define HAL_HASH_MODULE_ENABLED /*#define HAL_HRTIM_MODULE_ENABLED */ /*#define HAL_IRDA_MODULE_ENABLED */ -/*#define HAL_IWDG_MODULE_ENABLED */ +#define HAL_IWDG_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED /*#define HAL_I2S_MODULE_ENABLED */ #define HAL_LPTIM_MODULE_ENABLED diff --git a/core/embed/sys/startup/stm32u5/startup_init.c b/core/embed/sys/startup/stm32u5/startup_init.c index 1233fc8b43..9fc66a5b9f 100644 --- a/core/embed/sys/startup/stm32u5/startup_init.c +++ b/core/embed/sys/startup/stm32u5/startup_init.c @@ -91,7 +91,15 @@ void lsi_init(void) { uint32_t bdcr_temp = RCC->BDCR; - if (RCC_LSI_DIV1 != (bdcr_temp & RCC_BDCR_LSIPREDIV)) { +#if LSI_VALUE == 32000 + uint32_t lsi_div = RCC_LSI_DIV1; +#elif LSI_VALUE == 250 + uint32_t lsi_div = RCC_LSI_DIV128; +#else +#error Unsupported LSI frequency +#endif + + if (lsi_div != (bdcr_temp & RCC_BDCR_LSIPREDIV)) { if (((bdcr_temp & RCC_BDCR_LSIRDY) == RCC_BDCR_LSIRDY) && ((bdcr_temp & RCC_BDCR_LSION) != RCC_BDCR_LSION)) { // If LSIRDY is set while LSION is not enabled, LSIPREDIV can't be updated @@ -110,7 +118,7 @@ void lsi_init(void) { } // Set LSI division factor - MODIFY_REG(RCC->BDCR, RCC_BDCR_LSIPREDIV, 0); + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSIPREDIV, lsi_div); } // Enable the Internal Low Speed oscillator (LSI) @@ -254,7 +262,9 @@ void SystemInit(void) { #ifdef USE_LSE lse_init(); -#else +#endif + +#if defined(USE_LSI) || !defined(USE_LSE) lsi_init(); #endif diff --git a/core/embed/sys/trustzone/stm32u5/trustzone.c b/core/embed/sys/trustzone/stm32u5/trustzone.c index f8457e969c..c1b1406018 100644 --- a/core/embed/sys/trustzone/stm32u5/trustzone.c +++ b/core/embed/sys/trustzone/stm32u5/trustzone.c @@ -517,6 +517,10 @@ void tz_init(void) { HAL_GTZC_TZSC_ConfigPeriphAttributes( GTZC_PERIPH_SAES, GTZC_TZSC_PERIPH_SEC | GTZC_TZSC_PERIPH_PRIV); + // Set IWDG as secure & privileged + HAL_GTZC_TZSC_ConfigPeriphAttributes( + GTZC_PERIPH_IWDG, GTZC_TZSC_PERIPH_SEC | GTZC_TZSC_PERIPH_PRIV); + // Set all interrupts as non-secure for (int i = 0; i < 512; i++) { NVIC_SetTargetState(i);