From 2ce4b889805dc7238b20d287db6e5235ea010e3e Mon Sep 17 00:00:00 2001 From: "Peter D. Gray" Date: Fri, 21 May 2021 13:55:34 -0400 Subject: [PATCH] runs --- stm32/mk4-bootloader/Makefile | 6 + stm32/mk4-bootloader/ae.c | 17 ++- stm32/mk4-bootloader/clocks.c | 50 +++++-- stm32/mk4-bootloader/clocks.h | 2 + stm32/mk4-bootloader/console.c | 35 +++++ stm32/mk4-bootloader/dispatch.c | 20 ++- stm32/mk4-bootloader/firewall.c | 5 +- stm32/mk4-bootloader/gpio.c | 38 ++++- stm32/mk4-bootloader/hal_glue.c | 137 ++++++++++++++++++ stm32/mk4-bootloader/main.c | 20 ++- stm32/mk4-bootloader/mk-sigheader.py | 1 + stm32/mk4-bootloader/oled.c | 20 ++- stm32/mk4-bootloader/pins.c | 5 +- stm32/mk4-bootloader/psram.c | 29 ++-- stm32/mk4-bootloader/sigheader.h | 1 + stm32/mk4-bootloader/sigheader.py | 1 + stm32/mk4-bootloader/startup.S | 4 +- stm32/mk4-bootloader/stm32l4xx_hal_firewall.c | 48 +++--- stm32/mk4-bootloader/verify.c | 2 + 19 files changed, 360 insertions(+), 81 deletions(-) create mode 120000 stm32/mk4-bootloader/mk-sigheader.py create mode 120000 stm32/mk4-bootloader/sigheader.h create mode 120000 stm32/mk4-bootloader/sigheader.py diff --git a/stm32/mk4-bootloader/Makefile b/stm32/mk4-bootloader/Makefile index c15fa580..b289bc80 100644 --- a/stm32/mk4-bootloader/Makefile +++ b/stm32/mk4-bootloader/Makefile @@ -50,6 +50,8 @@ BL_FLASH_BASE = 0x08000000 BL_FLASH_SIZE = 0xe000 BL_FLASH_LAST = 0x0800e000 +MPY_FLASH_BASE = 0x08010000 + # Final 8k bytes of flash reserved for secret data (not code) # - must be page-aligned, contains pairing secret BL_NVROM_BASE = 0x0800e000 # = BL_FLASH_LAST @@ -100,6 +102,7 @@ LDFLAGS += -Wl,-Map=$(TARGET_NAME).map ASFLAGS += -Wa,--defsym,BL_FLASH_BASE=$(BL_FLASH_BASE) -Wa,--defsym,BL_FLASH_SIZE=$(BL_FLASH_SIZE) ASFLAGS += -Wa,--defsym,BL_SRAM_BASE=$(BL_SRAM_BASE) -Wa,--defsym,BL_SRAM_SIZE=$(BL_SRAM_SIZE) +ASFLAGS += -Wa,--defsym,MPY_FLASH_BASE=$(MPY_FLASH_BASE) TARGET_ELF = $(TARGET_NAME).elf @@ -152,8 +155,11 @@ dfu-slow: $(TARGET_NAME).dfu dfu-util -d 0483:df11 -a 0 -D $< dfu: $(TARGET_NAME).dfu + echo 'dfu' | nc localhost 4444 $(PYTHON_DO_DFU) -u $< +up: dfu + # upload current production version (or latest release version anyway) latest: $(PYTHON_DO_DFU) -u `ls -t1 releases/*/bootloader.dfu | head -1` diff --git a/stm32/mk4-bootloader/ae.c b/stm32/mk4-bootloader/ae.c index 17d46e3b..0dedd58e 100644 --- a/stm32/mk4-bootloader/ae.c +++ b/stm32/mk4-bootloader/ae.c @@ -3,6 +3,7 @@ */ #include "basics.h" #include "ae.h" +#include "clocks.h" #include "rng.h" #include "delay.h" #include "faster_sha256.h" @@ -12,6 +13,7 @@ #include "stm32l4xx_hal.h" #include "ae_config.h" #include "oled.h" +#include "console.h" #include #include @@ -24,6 +26,11 @@ # define ERR(msg) # define ERRV(val, msg) #endif +#if 0 +// affects timing +# define ERR(msg) puts(msg) +# define ERRV(val, msg) do { puts2(msg); puts2(": "); puthex2(val); putchar('\n'); } while(0) +#endif // Must be exactly 32 chars: static const char *copyright_msg = "Copyright 2018- by Coinkite Inc."; @@ -367,7 +374,13 @@ ae_setup(void) MY_UART->RTOR = 24; // timeout in bit periods: 3 chars or so MY_UART->CR2 = USART_CR2_RTOEN; // rx timeout enable MY_UART->CR3 = USART_CR3_HDSEL | USART_CR3_ONEBIT; - MY_UART->BRR = 0x0000015b; // 230400 bps +#if HCLK_FREQUENCY == 80000000 + MY_UART->BRR = 0x0000015b; // 230400 bps @ 80 Mhz SYSCLK +#elif HCLK_FREQUENCY == 120000000 + MY_UART->BRR = 521; // 230400 bps @ 120 Mhz SYSCLK +#else +# error "needs math" +#endif // clear rx timeout flag MY_UART->ICR = USART_ICR_RTOCF; @@ -375,7 +388,7 @@ ae_setup(void) // finally enable UART MY_UART->CR1 |= USART_CR1_UE; - // configure pin A0 to be AF8_UART4, PULL_NONE + // configure pin A0 to be AFx_UARTy, PULL_NONE gpio_setup(); // mark it as ready diff --git a/stm32/mk4-bootloader/clocks.c b/stm32/mk4-bootloader/clocks.c index eddd72fd..59d458cd 100644 --- a/stm32/mk4-bootloader/clocks.c +++ b/stm32/mk4-bootloader/clocks.c @@ -31,18 +31,34 @@ #include "stm32l4xx_hal.h" // HSE is used and is 8MHz -// - not doing a complete setup here, but enough -// - expect mainline code to refine this more +// - doing a complete setup here, and not changing in MicroPython anymore // - this chip is well made and can handle later changes to clocks +// - lots of internal RC osc we can use as well... HSI, MSI and HSI48 -#define CKCC_CLK_PLLN (40) -#define CKCC_CLK_PLLM (2) -#define CKCC_CLK_PLLR (2) -#define CKCC_CLK_PLLP (7) -#define CKCC_CLK_PLLQ (4) +#if HCLK_FREQUENCY == 80000000 +// To get 80Mhz for SYSCLK... +// 8Mhz (HSE) => /2 (M) *40 (N) /2 (R) => 80Mhz -// expected value of HAL_RCC_GetHCLKFreq(): 80Mhz -#define HCLK_FREQUENCY 80000000 +# define CKCC_CLK_PLLM (2) +# define CKCC_CLK_PLLN (40) +# define CKCC_CLK_PLLR (2) +# define CKCC_CLK_PLLP (7) +# define CKCC_CLK_PLLQ (4) +#endif + + +#if HCLK_FREQUENCY == 120000000 +// For for 120Mhz SYSCLK... +// 8Mhz (HSE) => /2 (M) *60 (N) /2 (R) => 120Mhz +// R output => main sysclk (target 120) +// Q output => should be 48Mhz for RNG and OCTOSPI maybe + +# define CKCC_CLK_PLLM (2) +# define CKCC_CLK_PLLN (60) +# define CKCC_CLK_PLLR (2) +# define CKCC_CLK_PLLP (7) +# define CKCC_CLK_PLLQ (5) +#endif // systick_setup() // @@ -64,6 +80,9 @@ clocks_setup(void) RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; + // setup power supplies + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); + // Configure LSE Drive Capability __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); @@ -95,7 +114,7 @@ clocks_setup(void) HAL_RCC_OscConfig(&RCC_OscInitStruct); - HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); // DIS-able MSI-Hardware auto calibration mode with LSE CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN); @@ -112,7 +131,7 @@ clocks_setup(void) PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1; PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1; - PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; // XXX wrong? PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1; PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; @@ -128,10 +147,17 @@ clocks_setup(void) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); __HAL_RCC_RTC_ENABLE(); - __HAL_RCC_HASH_CLK_ENABLE(); + __HAL_RCC_HASH_CLK_ENABLE(); // for SHA256 + __HAL_RCC_SPI1_CLK_ENABLE(); // for OLED + __HAL_RCC_SPI2_CLK_ENABLE(); // for SPI flash + //__HAL_RCC_DMA1_CLK_ENABLE(); // for SPI from mpy + //__HAL_RCC_DMA2_CLK_ENABLE(); // might not need + __HAL_RCC_DMAMUX1_CLK_ENABLE(); // because code missing in mpy? // setup SYSTICK, but we don't have the irq hooked up and not using HAL + // but we use it in polling mode for delay_ms() systick_setup(); + } // EOF diff --git a/stm32/mk4-bootloader/clocks.h b/stm32/mk4-bootloader/clocks.h index 007e1efc..e4d4edd2 100644 --- a/stm32/mk4-bootloader/clocks.h +++ b/stm32/mk4-bootloader/clocks.h @@ -3,6 +3,8 @@ */ #pragma once +#define HCLK_FREQUENCY 120000000 + // call once at startup void clocks_setup(void); diff --git a/stm32/mk4-bootloader/console.c b/stm32/mk4-bootloader/console.c index ac5470b5..10598a11 100644 --- a/stm32/mk4-bootloader/console.c +++ b/stm32/mk4-bootloader/console.c @@ -212,6 +212,16 @@ hex_dump(const void *d, int len) #define USART_TEACK_REACK_TIMEOUT 1000U /*!< USART TX or RX enable acknowledge time-out value */ #define USART_DUMMY_DATA ((uint16_t) 0xFFFF) /*!< USART transmitted dummy data */ +// WaitOnFlag() +// + static void +WaitOnFlag(uint32_t Flag, FlagStatus Status) +{ + while((((MY_UART->ISR & Flag) == Flag) ? SET : RESET) == Status) { + ; + } +} + /** * @brief Handle USART Communication Timeout. * @param husart USART handle. @@ -481,6 +491,30 @@ HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart) */ HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size, uint32_t Timeout) { + while(Size > 0U) { + while(!(MY_UART->ISR & UART_FLAG_TXE)) { + // wait to be able send + } + + MY_UART->TDR = *pTxData; + pTxData++; + Size --; + } + + while(!(MY_UART->ISR & UART_FLAG_TC)) { + // wait for final byte to be sent + } + + // Clear Transmission Complete Flag + MY_UART->ICR = USART_CLEAR_TCF; + + // Clear overrun flag and discard the received data + MY_UART->ICR = USART_CLEAR_OREF; + MY_UART->RQR = USART_RXDATA_FLUSH_REQUEST; + MY_UART->RQR = USART_TXDATA_FLUSH_REQUEST; + + return HAL_OK; +#if 0 uint8_t *ptxdata8bits; uint16_t *ptxdata16bits; uint32_t tickstart; @@ -562,6 +596,7 @@ HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, uint8_t *pTxDa { return HAL_BUSY; } +#endif } diff --git a/stm32/mk4-bootloader/dispatch.c b/stm32/mk4-bootloader/dispatch.c index f901ef5e..2501bd9c 100644 --- a/stm32/mk4-bootloader/dispatch.c +++ b/stm32/mk4-bootloader/dispatch.c @@ -40,16 +40,19 @@ good_addr(const uint8_t *b, int minlen, int len, bool readonly) { uint32_t x = (uint32_t)b; - // XXX needs changes for mk4 - if(minlen) { if(!b) return EFAULT; // gave no buffer if(len < minlen) return ERANGE; // too small } + // mk4 is different + STATIC_ASSERT(SRAM1_BASE == BL_SRAM_BASE); - if((x >= SRAM1_BASE) && ((x-SRAM1_BASE) < SRAM1_SIZE_MAX)) { - // inside SRAM1, okay + const uint32_t sram_start = BL_SRAM_BASE + BL_SRAM_SIZE; + const uint32_t sram_end = SRAM3_BASE + SRAM3_SIZE; + + if((x >= sram_start) && ((x+len) <= sram_end)) { + // inside the 3 SRAM areas return 0; } @@ -97,7 +100,7 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, int rv = 0; -#if 0 +#if 1 // TODO: re-enable this; causing crash now. // in case the caller didn't already, but would just lead to a crash anyway __disable_irq(); @@ -169,17 +172,21 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, rv = EPERM; goto fail; } + puts("Die: DFU"); scr = screen_dfu; break; case 1: // in case some way for Micropython to detect it. scr = screen_downgrade; + puts("Die: Downgrade"); break; case 2: scr = screen_blankish; + puts("Die: Blankish"); break; case 3: scr = screen_brick; + puts("Die: Brick"); secure = true; // no point going into DFU, if even possible break; } @@ -188,6 +195,7 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, oled_show(scr); wipe_all_sram(); + psram_wipe(); if(secure) { // just die with that message shown; can't start DFU @@ -232,6 +240,8 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, // NOT-REACHED (but ok if it does) } + psram_wipe(); + // wait for an interrupt which will never happen (ie. sleep) LOCKUP_FOREVER() break; diff --git a/stm32/mk4-bootloader/firewall.c b/stm32/mk4-bootloader/firewall.c index b8bdef15..eedcf21c 100644 --- a/stm32/mk4-bootloader/firewall.c +++ b/stm32/mk4-bootloader/firewall.c @@ -50,7 +50,7 @@ firewall_setup(void) uint32_t start = (uint32_t)&firewall_starts; uint32_t len = BL_FLASH_SIZE - (start - BL_FLASH_BASE); -#if 0 +#if 1 ASSERT(start); ASSERT(!(start & 0xff)); ASSERT(len>256); @@ -65,14 +65,13 @@ firewall_setup(void) // - many of the bits in these registers are not-implemented and are forced to zero // - that prevents the firewall being used for things like protecting OTP area // - (Mk1-3) volatile data is SRAM1 only, so doesn't help us, since we're using SRAM2 + // - (Mk4) we are in SRAM1, so we could protect all our RAM ... but errata 2.4.2 fucks that // - on-chip DFU will erase up to start (0x300), which borks the reset vector // but sensitive stuff is still there (which would allow bypass) // - so it's important to enable option bytes to set write-protect on entire bootloader // - to disable debug and complete protection, must enable write-protect "level 2" // - // XXX TODO: protect part SRAM1 for us to use? - FIREWALL_InitTypeDef init = { .CodeSegmentStartAddress = start, .CodeSegmentLength = len, diff --git a/stm32/mk4-bootloader/gpio.c b/stm32/mk4-bootloader/gpio.c index f814e05f..1e0fe08c 100644 --- a/stm32/mk4-bootloader/gpio.c +++ b/stm32/mk4-bootloader/gpio.c @@ -25,11 +25,14 @@ gpio_setup(void) // - try not to limit PCB changes for future revs; leave unused unchanged. // - oled_setup() uses pins on PA4 thru PA8 - // enable clock to that part of chip + // enable clock to GPIO's ... we will be using them all at some point __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(); - { // Onewire bus pins used for ATECC508A comms + { // Onewire bus pins used for ATECC608 comms GPIO_InitTypeDef setup = { .Pin = ONEWIRE_PIN, .Mode = GPIO_MODE_AF_OD, @@ -45,8 +48,11 @@ gpio_setup(void) HAL_GPIO_Init(ONEWIRE_PORT, &setup); } - // debug console: USART1 = PA9=Tx & PA10=Rx - { GPIO_InitTypeDef setup = { + // Bugfix: re-init of console port pins seems to wreck + // the mpy uart code, so avoid after first time. + if(USART1->BRR == 0) { + // debug console: USART1 = PA9=Tx & PA10=Rx + GPIO_InitTypeDef setup = { .Pin = GPIO_PIN_9, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_NOPULL, @@ -70,9 +76,30 @@ gpio_setup(void) }; HAL_GPIO_Init(GPIOC, &setup); - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, 1); // turn on + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, 0); // turn LED off } + +#if 0 + // TEST CODE -- keep + // enable MCO=PA8 for clock watching. Conflicts w/ OLED normal use. + GPIO_InitTypeDef mco_setup = { + .Pin = GPIO_PIN_8, + .Mode = GPIO_MODE_AF_PP, + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_VERY_HIGH, + .Alternate = GPIO_AF0_MCO, + }; + HAL_GPIO_Init(GPIOA, &mco_setup); + + // select a signal to view here. + // RCC_MCO1SOURCE_SYSCLK => 120Mhz (correct) + // RCC_MCO1SOURCE_PLLCLK (PLL R output) => (same os SYSCLK) + // RCC_MCO1SOURCE_HSI48 => 48Mhz + // RCC_MCO1SOURCE_HSE => 8Mhz (correct) + __HAL_RCC_MCO1_CONFIG(RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1); +#endif + #if 0 __HAL_RCC_GPIOB_CLK_ENABLE(); @@ -94,4 +121,5 @@ gpio_setup(void) #endif } + // EOF diff --git a/stm32/mk4-bootloader/hal_glue.c b/stm32/mk4-bootloader/hal_glue.c index 3be4cdf4..df09a8a2 100644 --- a/stm32/mk4-bootloader/hal_glue.c +++ b/stm32/mk4-bootloader/hal_glue.c @@ -34,6 +34,7 @@ uint32_t HAL_PWREx_GetVoltageRange(void) } else { + // NOTE: this is expected value for this project. return PWR_REGULATOR_VOLTAGE_SCALE1_BOOST; } #else @@ -42,4 +43,140 @@ uint32_t HAL_PWREx_GetVoltageRange(void) } +/** + * @brief Configure the main internal regulator output voltage. + * @param VoltageScaling specifies the regulator output voltage to achieve + * a tradeoff between performance and power consumption. + * This parameter can be one of the following values: + @if STM32L4S9xx + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when available, Regulator voltage output range 1 boost mode, + * typical output voltage at 1.2 V, + * system frequency up to 120 MHz. + @endif + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, + * typical output voltage at 1.2 V, + * system frequency up to 80 MHz. + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode, + * typical output voltage at 1.0 V, + * system frequency up to 26 MHz. + * @note When moving from Range 1 to Range 2, the system frequency must be decreased to + * a value below 26 MHz before calling HAL_PWREx_ControlVoltageScaling() API. + * When moving from Range 2 to Range 1, the system frequency can be increased to + * a value up to 80 MHz after calling HAL_PWREx_ControlVoltageScaling() API. For + * some devices, the system frequency can be increased up to 120 MHz. + * @note When moving from Range 2 to Range 1, the API waits for VOSF flag to be + * cleared before returning the status. If the flag is not cleared within + * 50 microseconds, HAL_TIMEOUT status is reported. + * @retval HAL Status + */ +#define PWR_FLAG_SETTING_DELAY_US 50UL /*!< Time out value for REGLPF and VOSF flags setting */ +HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling) +{ + uint32_t wait_loop_index; + + assert_param(IS_PWR_VOLTAGE_SCALING_RANGE(VoltageScaling)); + +#if defined(PWR_CR5_R1MODE) + if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) + { + /* If current range is range 2 */ + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Make sure Range 1 Boost is enabled */ + CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE); + + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = ((PWR_FLAG_SETTING_DELAY_US * SystemCoreClock) / 1000000U) + 1; + while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) && (wait_loop_index != 0U)) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + /* If current range is range 1 normal or boost mode */ + else + { + /* Enable Range 1 Boost (no issue if bit already reset) */ + CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE); + } + } + else if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1) + { + /* If current range is range 2 */ + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Make sure Range 1 Boost is disabled */ + SET_BIT(PWR->CR5, PWR_CR5_R1MODE); + + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = ((PWR_FLAG_SETTING_DELAY_US * SystemCoreClock) / 1000000U) + 1; + while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) && (wait_loop_index != 0U)) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + /* If current range is range 1 normal or boost mode */ + else + { + /* Disable Range 1 Boost (no issue if bit already set) */ + SET_BIT(PWR->CR5, PWR_CR5_R1MODE); + } + } + else + { + /* Set Range 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2); + /* No need to wait for VOSF to be cleared for this transition */ + /* PWR_CR5_R1MODE bit setting has no effect in Range 2 */ + } + +#else + + /* If Set Range 1 */ + if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1) + { + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE1) + { + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = ((PWR_FLAG_SETTING_DELAY_US * SystemCoreClock) / 1000000U) + 1U; + while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) && (wait_loop_index != 0U)) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + } + else + { + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Set Range 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2); + /* No need to wait for VOSF to be cleared for this transition */ + } + } +#endif + + return HAL_OK; +} + diff --git a/stm32/mk4-bootloader/main.c b/stm32/mk4-bootloader/main.c index 92eb0754..1751983f 100644 --- a/stm32/mk4-bootloader/main.c +++ b/stm32/mk4-bootloader/main.c @@ -50,8 +50,8 @@ reboot_seed_setup(void) // can only do this once, and might be done already if(SYSCFG->SWPR != (1<<31)) { - ASSERT(((uint32_t)reboot_seed) == 0x10007c00); - ASSERT(((uint32_t)hdr_copy) == RAM_HEADER_BASE); + ASSERT(((uint32_t)reboot_seed) == 0x20007c00); + ASSERT(((uint32_t)hdr_copy) == RAM_HEADER_BASE_MK4); // populate seed w/ noise memset(reboot_seed, 0x55, 1024); @@ -149,12 +149,24 @@ system_startup(void) // wipe all of SRAM (except our own memory, which was already wiped) wipe_all_sram(); - puts("AE setup start"); + puts2("AE setup: "); // secure element setup ae_setup(); ae_set_gpio(0); // not checking return on purpose - puts("AE setup done"); + puts("done"); + +#if 0 + { uint8_t config[128] = {0}; + int x = ae_config_read(config); + if(x == 0) { + puts("config[128]:"); + hex_dump(config, 128); + } else { + puts("config read fail"); + } + } +#endif // protect our flash, and/or check it's protected // - and pick pairing secret if we don't already have one diff --git a/stm32/mk4-bootloader/mk-sigheader.py b/stm32/mk4-bootloader/mk-sigheader.py new file mode 120000 index 00000000..a9b21c73 --- /dev/null +++ b/stm32/mk4-bootloader/mk-sigheader.py @@ -0,0 +1 @@ +../bootloader/mk-sigheader.py \ No newline at end of file diff --git a/stm32/mk4-bootloader/oled.c b/stm32/mk4-bootloader/oled.c index 1206ca97..12a89325 100644 --- a/stm32/mk4-bootloader/oled.c +++ b/stm32/mk4-bootloader/oled.c @@ -3,12 +3,13 @@ */ #include "oled.h" #include "delay.h" -#include "stm32l4xx_hal_gpio.h" -#include "stm32l4xx_hal_rcc.h" -#include "stm32l4xx_hal_dma.h" -#include "stm32l4xx_hal_spi.h" +#include "console.h" +#include "stm32l4xx_hal.h" #include +// OLED pins block use of MCO for testing +#undef DISABLE_OLED + // Reset and config sequence. // // As measured! No attempt to understand them here. @@ -48,17 +49,20 @@ static const uint8_t before_show[] = { #define SPI_SCK GPIO_PIN_5 #define SPI_MOSI GPIO_PIN_7 -HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout); +#ifndef DISABLE_OLED static SPI_HandleTypeDef spi_port; +#endif // write_bytes() // static inline void write_bytes(int len, const uint8_t *buf) { +#ifndef DISABLE_OLED // send via SPI(1) HAL_SPI_Transmit(&spi_port, (uint8_t *)buf, len, HAL_MAX_DELAY); +#endif } // oled_write_cmd() @@ -106,6 +110,7 @@ oled_write_data(int len, const uint8_t *pixels) void oled_spi_setup(void) { +#ifndef DISABLE_OLED // might already be setup if(spi_port.Instance == SPI1) return; @@ -126,6 +131,7 @@ oled_spi_setup(void) spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; HAL_SPI_Init(&spi_port); +#endif } // oled_setup() @@ -135,6 +141,10 @@ oled_spi_setup(void) void oled_setup(void) { +#ifdef DISABLE_OLED + puts("oled disabled");return; // disable so I can use MCO +#endif + static uint32_t inited; if(inited == 0x238a572F) { diff --git a/stm32/mk4-bootloader/pins.c b/stm32/mk4-bootloader/pins.c index c55f0526..34fe2225 100644 --- a/stm32/mk4-bootloader/pins.c +++ b/stm32/mk4-bootloader/pins.c @@ -291,7 +291,6 @@ pin_prefix_words(const char *pin_prefix, int prefix_len, uint32_t *result) static void _hmac_attempt(const pinAttempt_t *args, uint8_t result[32]) { - SHA256_CTX ctx; sha256_init(&ctx); @@ -307,9 +306,7 @@ _hmac_attempt(const pinAttempt_t *args, uint8_t result[32]) sha256_final(&ctx, result); // and a second-sha256 on that, just in case. - sha256_init(&ctx); - sha256_update(&ctx, result, 32); - sha256_final(&ctx, result); + sha256_single(result, 32, result); } // _validate_attempt() diff --git a/stm32/mk4-bootloader/psram.c b/stm32/mk4-bootloader/psram.c index 630cb02a..46340661 100644 --- a/stm32/mk4-bootloader/psram.c +++ b/stm32/mk4-bootloader/psram.c @@ -10,6 +10,7 @@ */ #include "psram.h" #include "oled.h" +#include "clocks.h" #include "assets/screens.h" #include #include "delay.h" @@ -19,9 +20,13 @@ #include "faster_sha256.h" #include "misc.h" +#undef INCL_SELFTEST + uint8_t psram_chip_eid[8]; -//static void psram_memtest(bool simple); +#ifdef INCL_SELFTEST +static void psram_memtest(bool simple); +#endif // psram_send_byte() // @@ -82,7 +87,13 @@ psram_setup(void) qh.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE; // maybe? qh.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE; // required! qh.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0; // low clock between ops (required, see errata) +#if HCLK_FREQUENCY == 80000000 qh.Init.ClockPrescaler = 1; // prescaler (1=>80Mhz, 2=>40Mhz, etc) +#elif HCLK_FREQUENCY == 120000000 + qh.Init.ClockPrescaler = 2; // prescaler (1=>120Mhz, 2=>60Mhz, etc) +#else +# error "testing needed" +#endif qh.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED; // dont need it? // ESP-PSRAM64H calls for max of 8us w/ CS low. Needs it for refresh time. @@ -185,13 +196,10 @@ psram_setup(void) if(rv != HAL_OK) goto fail; } -#if 0 - while(1) { - psram_memtest(1); - psram_memtest(0); - } -#endif - +#ifdef INCL_SELFTEST + psram_memtest(1); + psram_memtest(0); +#else // Only a quick operational check only here. Non-destructive. { __IO uint32_t *ptr = (uint32_t *)(PSRAM_BASE+PSRAM_SIZE-4); uint32_t tmp; @@ -201,6 +209,7 @@ psram_setup(void) if(*ptr != 0x55aa1234) goto fail; *ptr = tmp; } +#endif return; @@ -218,12 +227,14 @@ fail: void psram_wipe(void) { + if(OCTOSPI1->CR == 0) return; // PSRAM not enabled (yet?) + puts2("PSRAM Wipe: "); memset4((uint32_t *)PSRAM_BASE, rng_sample(), PSRAM_SIZE); puts("done"); } -#if 0 +#ifdef INCL_SELFTEST // psram_memtest() // static void diff --git a/stm32/mk4-bootloader/sigheader.h b/stm32/mk4-bootloader/sigheader.h new file mode 120000 index 00000000..ac2f4cb0 --- /dev/null +++ b/stm32/mk4-bootloader/sigheader.h @@ -0,0 +1 @@ +../bootloader/sigheader.h \ No newline at end of file diff --git a/stm32/mk4-bootloader/sigheader.py b/stm32/mk4-bootloader/sigheader.py new file mode 120000 index 00000000..4cfde4f7 --- /dev/null +++ b/stm32/mk4-bootloader/sigheader.py @@ -0,0 +1 @@ +../bootloader/sigheader.py \ No newline at end of file diff --git a/stm32/mk4-bootloader/startup.S b/stm32/mk4-bootloader/startup.S index 5e177644..15d076b9 100644 --- a/stm32/mk4-bootloader/startup.S +++ b/stm32/mk4-bootloader/startup.S @@ -89,8 +89,8 @@ reset_entry: bl callgate_entry0 // get a ptr to real code - // load R1 with 0x08008000 value: start of firmware's area - movw r1, (0x08008000 >> 12) + // load R1 with first byte of firmware's area + movw r1, (MPY_FLASH_BASE >> 12) lsl r1, 12 // set stack pointer to their preference diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_firewall.c b/stm32/mk4-bootloader/stm32l4xx_hal_firewall.c index beb2092d..3eee0289 100644 --- a/stm32/mk4-bootloader/stm32l4xx_hal_firewall.c +++ b/stm32/mk4-bootloader/stm32l4xx_hal_firewall.c @@ -2,8 +2,6 @@ ****************************************************************************** * @file stm32l4xx_hal_firewall.c * @author MCD Application Team - * @version V1.7.2 - * @date 16-June-2017 * @brief FIREWALL HAL module driver. * This file provides firmware functions to manage the Firewall * Peripheral initialization and enabling. @@ -34,29 +32,13 @@ ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2017 STMicroelectronics

+ *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -137,19 +119,24 @@ HAL_StatusTypeDef HAL_FIREWALL_Config(FIREWALL_InitTypeDef * fw_init) /* Check Firewall configuration addresses and lengths when segment is protected */ /* Code segment */ - if (fw_init->CodeSegmentLength != 0) + if (fw_init->CodeSegmentLength != 0U) { assert_param(IS_FIREWALL_CODE_SEGMENT_ADDRESS(fw_init->CodeSegmentStartAddress)); assert_param(IS_FIREWALL_CODE_SEGMENT_LENGTH(fw_init->CodeSegmentStartAddress, fw_init->CodeSegmentLength)); + /* Make sure that NonVDataSegmentLength is properly set to prevent code segment access */ + if (fw_init->NonVDataSegmentLength < 0x100U) + { + return HAL_ERROR; + } } /* Non volatile data segment */ - if (fw_init->NonVDataSegmentLength != 0) + if (fw_init->NonVDataSegmentLength != 0U) { assert_param(IS_FIREWALL_NONVOLATILEDATA_SEGMENT_ADDRESS(fw_init->NonVDataSegmentStartAddress)); assert_param(IS_FIREWALL_NONVOLATILEDATA_SEGMENT_LENGTH(fw_init->NonVDataSegmentStartAddress, fw_init->NonVDataSegmentLength)); } /* Volatile data segment */ - if (fw_init->VDataSegmentLength != 0) + if (fw_init->VDataSegmentLength != 0U) { assert_param(IS_FIREWALL_VOLATILEDATA_SEGMENT_ADDRESS(fw_init->VDataSegmentStartAddress)); assert_param(IS_FIREWALL_VOLATILEDATA_SEGMENT_LENGTH(fw_init->VDataSegmentStartAddress, fw_init->VDataSegmentLength)); @@ -159,21 +146,22 @@ HAL_StatusTypeDef HAL_FIREWALL_Config(FIREWALL_InitTypeDef * fw_init) assert_param(IS_FIREWALL_VOLATILEDATA_EXECUTE(fw_init->VolatileDataExecution)); assert_param(IS_FIREWALL_VOLATILEDATA_SHARE(fw_init->VolatileDataShared)); + /* Configuration */ /* Protected code segment start address configuration */ WRITE_REG(FIREWALL->CSSA, (FW_CSSA_ADD & fw_init->CodeSegmentStartAddress)); - /* Protected code segment length configuration */ + /* Protected code segment length configuration */ WRITE_REG(FIREWALL->CSL, (FW_CSL_LENG & fw_init->CodeSegmentLength)); /* Protected non volatile data segment start address configuration */ WRITE_REG(FIREWALL->NVDSSA, (FW_NVDSSA_ADD & fw_init->NonVDataSegmentStartAddress)); - /* Protected non volatile data segment length configuration */ + /* Protected non volatile data segment length configuration */ WRITE_REG(FIREWALL->NVDSL, (FW_NVDSL_LENG & fw_init->NonVDataSegmentLength)); /* Protected volatile data segment start address configuration */ WRITE_REG(FIREWALL->VDSSA, (FW_VDSSA_ADD & fw_init->VDataSegmentStartAddress)); - /* Protected volatile data segment length configuration */ + /* Protected volatile data segment length configuration */ WRITE_REG(FIREWALL->VDSL, (FW_VDSL_LENG & fw_init->VDataSegmentLength)); /* Set Firewall Configuration Register VDE and VDS bits diff --git a/stm32/mk4-bootloader/verify.c b/stm32/mk4-bootloader/verify.c index ac0c01a6..23b5cc90 100644 --- a/stm32/mk4-bootloader/verify.c +++ b/stm32/mk4-bootloader/verify.c @@ -237,11 +237,13 @@ verify_firmware(void) // but only if we arrived at same hash before. It decides. int not_green = ae_set_gpio_secure(world_check); +#if 0 // XXX change this, no more dev key // maybe show big warning if not an "approved" key if(not_green) { check_factory_key(FW_HDR->pubkey_num); } +#endif puts("good firmware"); oled_show_progress(screen_verify, 100);