You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
9.2 KiB
265 lines
9.2 KiB
4 years ago
|
// SPDX-FileCopyrightText: 2020 Foundation Devices, Inc. <hello@foundationdevices.com>
|
||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
//
|
||
|
// SPDX-FileCopyrightText: 2018 Coinkite, Inc. <coldcardwallet.com>
|
||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||
|
//
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "../stm32h7xx_hal_conf.h"
|
||
|
|
||
|
#include "stm32h7xx_ll_cortex.h"
|
||
|
|
||
|
#include "pprng.h"
|
||
|
#include "secrets.h"
|
||
|
#include "se.h"
|
||
|
#include "se-atecc608a.h"
|
||
|
#include "utils.h"
|
||
|
|
||
|
#include "flash.h"
|
||
|
#include "verify.h"
|
||
|
#include "update.h"
|
||
|
|
||
|
void SysTick_Handler(void)
|
||
|
{
|
||
|
HAL_IncTick();
|
||
|
}
|
||
|
|
||
|
static void SystemClock_Config(void)
|
||
|
{
|
||
|
HAL_StatusTypeDef rc;
|
||
|
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||
|
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||
|
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||
|
|
||
|
/*!< Supply configuration update enable */
|
||
|
rc = HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
|
||
|
if (rc != HAL_OK)
|
||
|
return;
|
||
|
|
||
|
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||
|
|
||
|
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
|
||
|
|
||
|
/* Enable HSE Oscillator and activate PLL with HSE as source */
|
||
|
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI48;
|
||
|
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||
|
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
|
||
|
RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
|
||
|
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
|
||
|
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||
|
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||
|
|
||
|
RCC_OscInitStruct.PLL.PLLM = 1;
|
||
|
RCC_OscInitStruct.PLL.PLLN = 120;
|
||
|
RCC_OscInitStruct.PLL.PLLP = 2;
|
||
|
RCC_OscInitStruct.PLL.PLLQ = 120;
|
||
|
RCC_OscInitStruct.PLL.PLLR = 2;
|
||
|
RCC_OscInitStruct.PLL.PLLFRACN = 0;
|
||
|
|
||
|
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
|
||
|
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
|
||
|
rc = HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||
|
if (rc != HAL_OK)
|
||
|
{
|
||
|
while(1) { ; }
|
||
|
}
|
||
|
|
||
|
PeriphClkInitStruct.PeriphClockSelection =
|
||
|
RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_RNG;
|
||
|
PeriphClkInitStruct.PLL2.PLL2M = 1;
|
||
|
PeriphClkInitStruct.PLL2.PLL2N = 18;
|
||
|
PeriphClkInitStruct.PLL2.PLL2P = 1;
|
||
|
PeriphClkInitStruct.PLL2.PLL2Q = 2;
|
||
|
PeriphClkInitStruct.PLL2.PLL2R = 2;
|
||
|
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
|
||
|
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOMEDIUM;
|
||
|
PeriphClkInitStruct.PLL2.PLL2FRACN = 6144;
|
||
|
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
|
||
|
PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_HSI48;
|
||
|
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
|
||
|
rc = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||
|
if (rc != HAL_OK)
|
||
|
{
|
||
|
while(1) { ; }
|
||
|
}
|
||
|
|
||
|
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | \
|
||
|
RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_D3PCLK1);
|
||
|
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||
|
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
|
||
|
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
|
||
|
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
|
||
|
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
|
||
|
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
|
||
|
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
|
||
|
rc = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
|
||
|
if (rc != HAL_OK)
|
||
|
{
|
||
|
while(1) { ; }
|
||
|
}
|
||
|
|
||
|
__HAL_RCC_CSI_ENABLE() ;
|
||
|
__HAL_RCC_SYSCFG_CLK_ENABLE() ;
|
||
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||
|
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||
|
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||
|
__HAL_RCC_D2SRAM1_CLK_ENABLE();
|
||
|
__HAL_RCC_D2SRAM2_CLK_ENABLE();
|
||
|
__HAL_RCC_D2SRAM3_CLK_ENABLE();
|
||
|
}
|
||
|
|
||
|
void MPU_Config(void)
|
||
|
{
|
||
|
MPU_Region_InitTypeDef MPU_InitStruct;
|
||
|
|
||
|
/* Disable MPU */
|
||
|
HAL_MPU_Disable();
|
||
|
|
||
|
/* Configure AXI SRAM region as non-executable */
|
||
|
memset(&MPU_InitStruct, 0, sizeof(MPU_InitStruct));
|
||
|
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||
|
MPU_InitStruct.BaseAddress = 0x24000000;
|
||
|
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
|
||
|
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||
|
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||
|
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
|
||
|
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
|
||
|
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
|
||
|
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||
|
MPU_InitStruct.SubRegionDisable = 0x00;
|
||
|
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||
|
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||
|
|
||
|
/* Configure SRAM1 region as non-executable */
|
||
|
memset(&MPU_InitStruct, 0, sizeof(MPU_InitStruct));
|
||
|
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||
|
MPU_InitStruct.BaseAddress = 0x30000000;
|
||
|
MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
|
||
|
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||
|
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||
|
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
|
||
|
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
|
||
|
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
|
||
|
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||
|
MPU_InitStruct.SubRegionDisable = 0x00;
|
||
|
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||
|
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||
|
|
||
|
/* Configure SRAM2 region as non-executable */
|
||
|
memset(&MPU_InitStruct, 0, sizeof(MPU_InitStruct));
|
||
|
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||
|
MPU_InitStruct.BaseAddress = 0x30020000;
|
||
|
MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
|
||
|
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||
|
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||
|
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
|
||
|
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
|
||
|
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
|
||
|
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||
|
MPU_InitStruct.SubRegionDisable = 0x00;
|
||
|
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||
|
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||
|
|
||
|
/* Configure SRAM3 region as non-executable */
|
||
|
memset(&MPU_InitStruct, 0, sizeof(MPU_InitStruct));
|
||
|
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||
|
MPU_InitStruct.BaseAddress = 0x30040000;
|
||
|
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
|
||
|
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||
|
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||
|
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
|
||
|
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
|
||
|
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
|
||
|
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||
|
MPU_InitStruct.SubRegionDisable = 0x00;
|
||
|
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||
|
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||
|
|
||
|
#if 0 /* FIXME...enabling this causes an IACCVIOL! */
|
||
|
/* Configure SRAM4 region as non-executable */
|
||
|
memset(&MPU_InitStruct, 0, sizeof(MPU_InitStruct));
|
||
|
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||
|
MPU_InitStruct.BaseAddress = 0x38000000;
|
||
|
MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;
|
||
|
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||
|
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||
|
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
|
||
|
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
|
||
|
MPU_InitStruct.Number = MPU_REGION_NUMBER4;
|
||
|
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||
|
MPU_InitStruct.SubRegionDisable = 0x00;
|
||
|
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||
|
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||
|
#endif
|
||
|
|
||
|
/* Configure ITCM region as non-executable */
|
||
|
memset(&MPU_InitStruct, 0, sizeof(MPU_InitStruct));
|
||
|
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||
|
MPU_InitStruct.BaseAddress = 0x00000000;
|
||
|
MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;
|
||
|
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||
|
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||
|
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
|
||
|
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
|
||
|
MPU_InitStruct.Number = MPU_REGION_NUMBER5;
|
||
|
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||
|
MPU_InitStruct.SubRegionDisable = 0x00;
|
||
|
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||
|
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||
|
|
||
|
|
||
|
/* Enable MPU */
|
||
|
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
|
||
|
|
||
|
}
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
HAL_StatusTypeDef rc;
|
||
|
|
||
|
SystemInit();
|
||
|
|
||
|
rc = HAL_Init();
|
||
|
if (rc != HAL_OK)
|
||
|
{
|
||
|
while(1) { ; }
|
||
|
}
|
||
|
#if 0 /* This is interfering with firmware boot after an update. It
|
||
|
* appears that the data cache is getting in the way of the
|
||
|
* reset handler properly copying over the data section into SRAM.
|
||
|
*/
|
||
|
SCB_EnableICache();
|
||
|
SCB_EnableDCache();
|
||
|
#endif
|
||
|
SystemClock_Config();
|
||
|
|
||
|
rng_setup();
|
||
|
se_setup();
|
||
|
|
||
|
/* Check for first-boot condition */
|
||
|
if (!flash_is_programmed())
|
||
|
flash_first_boot();
|
||
|
|
||
|
/* Validate our pairing secret */
|
||
|
if (!se_valid_secret(rom_secrets->pairing_secret))
|
||
|
LOCKUP_FOREVER();
|
||
|
|
||
|
/* Validate the internal firmware */
|
||
|
if (!verify_current_firmware())
|
||
|
LOCKUP_FOREVER();
|
||
|
|
||
|
/* Check for firmware update */
|
||
|
if (is_firmware_update_present())
|
||
|
update_firmware();
|
||
|
|
||
|
/* Setup MPU */
|
||
|
MPU_Config();
|
||
|
|
||
|
/* From here we'll boot to Micropython */
|
||
|
}
|