From 02bfe8a6a1c9f12e89a8293aa668a04d1e10c68c Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Tue, 14 May 2024 18:02:37 +0200 Subject: [PATCH] Added OTP support for STM32H5 --- hal/stm32h5.c | 96 ++++++++++++++++++++++-- hal/stm32h5.h | 13 +++- include/keystore.h | 4 +- include/otp_keystore.h | 2 + include/wolfboot/wolfboot.h | 4 + src/flash_otp_keystore.c | 2 +- tools/keytools/otp/Makefile | 7 +- tools/keytools/otp/otp-keystore-primer.c | 4 + 8 files changed, 118 insertions(+), 14 deletions(-) diff --git a/hal/stm32h5.c b/hal/stm32h5.c index 08f126e2..2dd704f8 100644 --- a/hal/stm32h5.c +++ b/hal/stm32h5.c @@ -37,7 +37,7 @@ static void RAMFUNCTION flash_set_waitstates(unsigned int waitstates) while ((FLASH_ACR & FLASH_ACR_LATENCY_MASK) != waitstates); } -void RAMFUNCTION hal_flash_wait_complete(uint8_t bank) +static void RAMFUNCTION hal_flash_wait_complete(void) { while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY) ; @@ -48,6 +48,17 @@ void RAMFUNCTION hal_flash_wait_complete(uint8_t bank) } +static void RAMFUNCTION hal_flash_wait_buffer_empty(void) +{ + while ((FLASH_SR & FLASH_SR_DBNE) == FLASH_SR_DBNE) + ; +#if (TZ_SECURE()) + while ((FLASH_NS_SR & FLASH_SR_DBNE) == FLASH_SR_DBNE) + ; +#endif + +} + void RAMFUNCTION hal_flash_clear_errors(uint8_t bank) { FLASH_CCR |= ( FLASH_CCR_CLR_WBNE | FLASH_CCR_CLR_DBNE | FLASH_CCR_CLR_INCE| @@ -85,7 +96,7 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) dst[i >> 2] = dword[0]; ISB(); dst[(i >> 2) + 1] = dword[1]; - hal_flash_wait_complete(0); + hal_flash_wait_complete(); if ((*sr & FLASH_SR_EOP) != 0) *sr |= FLASH_SR_EOP; *cr &= ~FLASH_CR_PG; @@ -99,7 +110,7 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) void RAMFUNCTION hal_flash_unlock(void) { - hal_flash_wait_complete(0); + hal_flash_wait_complete(); if ((FLASH_CR & FLASH_CR_LOCK) != 0) { FLASH_KEYR = FLASH_KEY1; DMB(); @@ -112,14 +123,14 @@ void RAMFUNCTION hal_flash_unlock(void) void RAMFUNCTION hal_flash_lock(void) { - hal_flash_wait_complete(0); + hal_flash_wait_complete(); if ((FLASH_CR & FLASH_CR_LOCK) == 0) FLASH_CR |= FLASH_CR_LOCK; } void RAMFUNCTION hal_flash_opt_unlock(void) { - hal_flash_wait_complete(0); + hal_flash_wait_complete(); if ((FLASH_OPTCR & FLASH_OPTCR_OPTLOCK) != 0) { FLASH_OPTKEYR = FLASH_OPTKEY1; DMB(); @@ -134,7 +145,7 @@ void RAMFUNCTION hal_flash_opt_unlock(void) void RAMFUNCTION hal_flash_opt_lock(void) { FLASH_OPTCR |= FLASH_OPTCR_OPTSTRT; - hal_flash_wait_complete(0); + hal_flash_wait_complete(); if ((FLASH_OPTCR & FLASH_OPTCR_OPTLOCK) == 0) FLASH_OPTCR |= FLASH_OPTCR_OPTLOCK; } @@ -149,7 +160,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) if (len == 0) return -1; - if (address < ARCH_FLASH_OFFSET) + if (address < 0x08000000) return -1; end_address = address + len - 1; @@ -176,7 +187,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) FLASH_CR = reg; DMB(); FLASH_CR |= FLASH_CR_STRT; - hal_flash_wait_complete(0); + hal_flash_wait_complete(); } /* If the erase operation is completed, disable the associated bits */ FLASH_CR &= ~FLASH_CR_SER ; @@ -421,3 +432,72 @@ void hal_prepare_boot(void) #endif } +#ifdef FLASH_OTP_ROT + +/* Public API */ + +int hal_flash_otp_write(uint32_t flashAddress, const void* data, uint16_t length) +{ + volatile uint16_t tmp; + uint16_t *pdata = (uint16_t *)data; + uint16_t idx = 0, len_align; + uint16_t last_word; + if (!(flashAddress >= FLASH_OTP_BASE && flashAddress <= FLASH_OTP_END)) { + return -1; + } + + hal_flash_wait_complete(); + hal_flash_wait_buffer_empty(); + hal_flash_unlock(); + hal_flash_clear_errors(0); + + + /* Truncate to 2B alignment */ + length = (length / 2 * 2); + + while (idx < length && flashAddress <= FLASH_OTP_END-1) { + hal_flash_wait_complete(); + /* Set PG bit */ + FLASH_CR |= FLASH_CR_PG; + /* Program an OTP word (32 bits) */ + *(volatile uint16_t*)flashAddress = *pdata; + ISB(); + DSB(); + /* Read it back */ + tmp = *(volatile uint16_t*)flashAddress; + if (tmp != *pdata) { + /* Provisioning failed. OTP already programmed? */ + while(1) + ; + } + + /* Clear PG bit */ + FLASH_CR &= ~FLASH_CR_PG; + flashAddress += sizeof(uint16_t); + pdata++; + idx += sizeof(uint16_t); + } + + hal_flash_lock(); + return 0; +} + +int hal_flash_otp_read(uint32_t flashAddress, void* data, uint32_t length) +{ + uint16_t i; + uint16_t *pdata = (uint16_t *)data; + if (!(flashAddress >= FLASH_OTP_BASE && flashAddress <= FLASH_OTP_END)) { + return -1; + } + for (i = 0; + (i < length) && (flashAddress <= (FLASH_OTP_END-1)); + i += sizeof(uint16_t)) + { + *pdata = *(volatile uint16_t*)flashAddress; + flashAddress += sizeof(uint16_t); + pdata++; + } + return 0; +} + +#endif /* FLASH_OTP_ROT */ diff --git a/hal/stm32h5.h b/hal/stm32h5.h index 16a69863..5e64222a 100644 --- a/hal/stm32h5.h +++ b/hal/stm32h5.h @@ -355,18 +355,25 @@ #define RCC_APB2_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0xA4)) #define UART1_APB2_CLOCK_ER_VAL (1 << 14) + +/* OTP FLASH AREA */ +#define FLASH_OTP_BASE 0x08FFF000 +#define FLASH_OTP_END 0x08FFF7FF +#define OTP_SIZE 2048 +#define OTP_BLOCKS 32 + +/* UART1 pin configuration */ #define UART1_PIN_AF 8 #define UART1_RX_PIN 8 #define UART1_TX_PIN 7 +/* GPIO secure configuration */ #define GPIO_SECCFGR(base) (*(volatile uint32_t *)(base + 0x30)) - - - #define LED_AHB2_ENABLE (GPIOG_AHB2_CLOCK_ER | GPIOB_AHB2_CLOCK_ER | \ GPIOF_AHB2_CLOCK_ER) #define LED_BOOT_PIN (4) /* PG4 - Nucleo board - Orange Led */ #define LED_USR_PIN (0) /* PB0 - Nucleo board - Green Led */ #define LED_EXTRA_PIN (4) /* PF4 - Nucleo board - Blue Led */ + #endif /* STM32H5_DEF_INCLUDED */ diff --git a/include/keystore.h b/include/keystore.h index a2cfc91e..12882579 100644 --- a/include/keystore.h +++ b/include/keystore.h @@ -35,6 +35,7 @@ extern "C" { #define KEYSTORE_PUBKEY_SIZE 576 /* Max is RSA 4096 */ #endif + struct keystore_slot { uint32_t slot_id; uint32_t key_type; @@ -43,7 +44,8 @@ struct keystore_slot { uint8_t pubkey[KEYSTORE_PUBKEY_SIZE]; }; -#define SIZEOF_KEYSTORE_SLOT (32 + KEYSTORE_PUBKEY_SIZE) +#define KEYSTORE_HDR_SIZE 16 +#define SIZEOF_KEYSTORE_SLOT (KEYSTORE_HDR_SIZE + KEYSTORE_PUBKEY_SIZE) /* KeyStore API */ int keystore_num_pubkeys(void); diff --git a/include/otp_keystore.h b/include/otp_keystore.h index 2f8a4703..6a549970 100644 --- a/include/otp_keystore.h +++ b/include/otp_keystore.h @@ -32,6 +32,8 @@ */ #ifdef TARGET_stm32h7 #include "hal/stm32h7.h" +#elif defined TARGET_stm32h5 + #include "hal/stm32h5.h" #else #error "Unsupported target for OTP" #endif diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index e6be66fd..529b9840 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -175,6 +175,10 @@ extern "C" { #endif #endif +#endif + +#if defined __WOLFBOOT || defined __FLASH_OTP_PRIMER + /* Authentication configuration */ #if defined(WOLFBOOT_NO_SIGN) # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_NONE diff --git a/src/flash_otp_keystore.c b/src/flash_otp_keystore.c index b5cca0b0..d7db6811 100644 --- a/src/flash_otp_keystore.c +++ b/src/flash_otp_keystore.c @@ -45,7 +45,7 @@ int keystore_num_pubkeys(void) return hdr->item_count; } -static uint16_t otp_slot_item_cache[SIZEOF_KEYSTORE_SLOT/2]; +static uint8_t otp_slot_item_cache[SIZEOF_KEYSTORE_SLOT]; uint8_t *keystore_get_buffer(int id) { diff --git a/tools/keytools/otp/Makefile b/tools/keytools/otp/Makefile index 5141c61a..0d91e57b 100644 --- a/tools/keytools/otp/Makefile +++ b/tools/keytools/otp/Makefile @@ -9,7 +9,7 @@ CROSS_COMPILE?=arm-none-eabi- CFLAGS+=-O0 -ggdb CFLAGS+=-I. -I../../../ -I../../../include CFLAGS+=-I./wcs -CFLAGS+=-DFLASH_OTP_ROT +CFLAGS+=-DFLASH_OTP_ROT -D__FLASH_OTP_PRIMER OBJS+=startup.o otp-keystore-primer.o ../../../src/keystore.o LSCRIPT=target.ld LDFLAGS+=$(CFLAGS) -T$(LSCRIPT) -lc -Wl,-Map=otp-keystore-primer.map @@ -19,6 +19,11 @@ ifeq ($(TARGET),stm32h7) CFLAGS+=-mcpu=cortex-m7 -ffunction-sections -fdata-sections -fno-common -ffreestanding -nostartfiles OBJS+=../../../hal/stm32h7.o endif +ifeq ($(TARGET),stm32h5) + CFLAGS+=-DTARGET_stm32h5 + CFLAGS+=-mcpu=cortex-m33 -ffunction-sections -fdata-sections -fno-common -ffreestanding -nostartfiles + OBJS+=../../../hal/stm32h5.o +endif CC=$(CROSS_COMPILE)gcc OBJCOPY?=$(CROSS_COMPILE)objcopy SIZE?=$(CROSS_COMPILE)size diff --git a/tools/keytools/otp/otp-keystore-primer.c b/tools/keytools/otp/otp-keystore-primer.c index fc4a31d3..d64f2ebb 100644 --- a/tools/keytools/otp/otp-keystore-primer.c +++ b/tools/keytools/otp/otp-keystore-primer.c @@ -23,6 +23,7 @@ */ #include #include +#include "wolfboot/wolfboot.h" #include "hal.h" #include "otp_keystore.h" @@ -33,6 +34,9 @@ void main(void) int n_keys = keystore_num_pubkeys(); int i; struct wolfBoot_otp_hdr hdr; + + hal_init(); + memcpy(hdr.keystore_hdr_magic, KEYSTORE_HDR_MAGIC, 8); hdr.item_count = n_keys; hdr.flags = 0;