From 177358e88debde95bd50ac1cca4e93131ba11faa Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Wed, 29 Oct 2025 00:06:19 +0100 Subject: [PATCH] Update H5 app to use new NSC API - Make the update and swap partitions secure and inaccessible from the app except via NSC API - Add a couple of necessary new NSC functions - Update the app to only use NSC API - Fix hal_flash_erase to account for secure addresses - Fix some bugs in xmodem implementation --- .../stm32h5-tz-dualbank-otp-lms.config | 2 +- .../examples/stm32h5-tz-dualbank-otp.config | 2 +- config/examples/stm32h5-tz.config | 4 +- config/examples/stm32h5.config | 4 +- hal/stm32h5.c | 33 ++++----- hal/stm32h5.h | 1 + include/wolfboot/wolfboot.h | 11 ++- src/libwolfboot.c | 27 ++++++- test-app/app_stm32h5.c | 73 +++++++++++-------- 9 files changed, 101 insertions(+), 56 deletions(-) diff --git a/config/examples/stm32h5-tz-dualbank-otp-lms.config b/config/examples/stm32h5-tz-dualbank-otp-lms.config index 7f76f6af..7ffe9ccd 100644 --- a/config/examples/stm32h5-tz-dualbank-otp-lms.config +++ b/config/examples/stm32h5-tz-dualbank-otp-lms.config @@ -21,7 +21,7 @@ DUALBANK_SWAP?=1 WOLFBOOT_PARTITION_SIZE?=0xA0000 WOLFBOOT_SECTOR_SIZE?=0x2000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08160000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C160000 WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFFFFFF FLAGS_HOME=0 DISABLE_BACKUP=0 diff --git a/config/examples/stm32h5-tz-dualbank-otp.config b/config/examples/stm32h5-tz-dualbank-otp.config index b09b08fb..af7421ef 100644 --- a/config/examples/stm32h5-tz-dualbank-otp.config +++ b/config/examples/stm32h5-tz-dualbank-otp.config @@ -21,7 +21,7 @@ DUALBANK_SWAP?=1 WOLFBOOT_PARTITION_SIZE?=0xA0000 WOLFBOOT_SECTOR_SIZE?=0x2000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08160000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C160000 WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFFFFFF FLAGS_HOME=0 DISABLE_BACKUP=0 diff --git a/config/examples/stm32h5-tz.config b/config/examples/stm32h5-tz.config index 66c1bae7..aeb4d6a5 100644 --- a/config/examples/stm32h5-tz.config +++ b/config/examples/stm32h5-tz.config @@ -21,8 +21,8 @@ DUALBANK_SWAP?=0 WOLFBOOT_PARTITION_SIZE?=0xA0000 WOLFBOOT_SECTOR_SIZE?=0x2000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08100000 -WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x081A0000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C100000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x0C1A0000 FLAGS_HOME=0 DISABLE_BACKUP=0 WOLFCRYPT_TZ=1 diff --git a/config/examples/stm32h5.config b/config/examples/stm32h5.config index 61a340fd..54feaa14 100644 --- a/config/examples/stm32h5.config +++ b/config/examples/stm32h5.config @@ -21,8 +21,8 @@ DUALBANK_SWAP?=0 WOLFBOOT_PARTITION_SIZE?=0xA0000 WOLFBOOT_SECTOR_SIZE?=0x2000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08100000 -WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x081A0000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C100000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x0C1A0000 FLAGS_HOME=0 DISABLE_BACKUP=0 IMAGE_HEADER_SIZE?=1024 diff --git a/hal/stm32h5.c b/hal/stm32h5.c index 179f0659..fe60a72b 100644 --- a/hal/stm32h5.c +++ b/hal/stm32h5.c @@ -32,21 +32,14 @@ #define PLL_SRC_HSE 1 #if TZ_SECURE() - static int is_flash_nonsecure(uint32_t address) { -#ifndef DUALBANK_SWAP - if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) { + if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS && + address < WOLFBOOT_PARTITION_BOOT_ADDRESS + + WOLFBOOT_PARTITION_SIZE) { return 1; } return 0; -#else - uint32_t in_bank_offset = (address & 0x000FFFFF); - if (in_bank_offset >= (WOLFBOOT_PARTITION_BOOT_ADDRESS - FLASHMEM_ADDRESS_SPACE)) { - return 1; - } - return 0; -#endif } #endif @@ -204,9 +197,15 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) return -1; #if TZ_SECURE() - start_address = address | FLASH_SECURE_MMAP_BASE; - if (is_flash_nonsecure(address)) { - hal_tz_claim_nonsecure_area(address, len); + if (address & FLASH_SECURE_MMAP_BIT) { + /* Get address in non-secure address space */ + start_address = address & ~FLASH_SECURE_MMAP_BIT; + } + else { + if (is_flash_nonsecure(address)) { + hal_tz_claim_nonsecure_area(address, len); + } + start_address = address; } #else start_address = address; @@ -218,8 +217,8 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) uint32_t base; uint32_t bnksel = 0; base = FLASHMEM_ADDRESS_SPACE; - reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_BER)); - if(p >= (FLASH_BANK2_BASE) && (p <= (FLASH_TOP) )) + reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | FLASH_CR_BER | FLASH_CR_PG | FLASH_CR_MER | FLASH_CR_BKSEL)); + if (p >= FLASH_BANK2_BASE && p <= FLASH_TOP) { base = FLASH_BANK2_BASE; bnksel = 1; @@ -231,13 +230,13 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) FLASH_CR = reg; ISB(); FLASH_CR |= FLASH_CR_STRT; - hal_flash_wait_complete(0); + hal_flash_wait_complete(bnksel); } /* If the erase operation is completed, disable the associated bits */ FLASH_CR &= ~FLASH_CR_SER ; #if TZ_SECURE() - if (is_flash_nonsecure(address)) { + if (!(address & FLASH_SECURE_MMAP_BIT) && is_flash_nonsecure(address)) { hal_tz_release_nonsecure_area(); } #endif diff --git a/hal/stm32h5.h b/hal/stm32h5.h index 95e203eb..d80add07 100644 --- a/hal/stm32h5.h +++ b/hal/stm32h5.h @@ -49,6 +49,7 @@ #endif #define FLASH_SECURE_MMAP_BASE (0x0C000000) +#define FLASH_SECURE_MMAP_BIT (0x04000000) #define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00)) /* RM0481 - Table 108 */ #define RCC_CR_PLL3RDY (1 << 29) /* RM0481 - Table 108 */ diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index f51b3806..09a14fb2 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -420,7 +420,6 @@ int wolfBoot_erase_encrypt_key(void); */ /* Call wolfBoot_success from non-secure application */ - __attribute__((cmse_nonsecure_entry)) void wolfBoot_nsc_success(void); @@ -428,6 +427,16 @@ void wolfBoot_nsc_success(void); __attribute__((cmse_nonsecure_entry)) void wolfBoot_nsc_update_trigger(void); +/* Call wolfBoot_get_image_version from non-secure application */ +__attribute__((cmse_nonsecure_entry)) +uint32_t wolfBoot_nsc_get_image_version(uint8_t part); +#define wolfBoot_nsc_current_firmware_version() wolfBoot_nsc_get_image_version(PART_BOOT) +#define wolfBoot_nsc_update_firmware_version() wolfBoot_nsc_get_image_version(PART_UPDATE) + +/* Call wolfBoot_get_partition_state from non-secure application */ +__attribute__((cmse_nonsecure_entry)) +int wolfBoot_nsc_get_partition_state(uint8_t part, uint8_t *st); + /* Erase one or more sectors in the update partition. * - address: offset within the update partition ('0' corresponds to PARTITION_UPDATE_ADDRESS) * - len: size, in bytes diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 6c08380d..a94434bc 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -2051,25 +2051,48 @@ void wolfBoot_nsc_update_trigger(void) wolfBoot_update_trigger(); } +__attribute__((cmse_nonsecure_entry)) +uint32_t wolfBoot_nsc_get_image_version(uint8_t part) +{ + return wolfBoot_get_image_version(part); +} + +__attribute__((cmse_nonsecure_entry)) +int wolfBoot_nsc_get_partition_state(uint8_t part, uint8_t *st) +{ + return wolfBoot_get_partition_state(part, st); +} + __attribute__((cmse_nonsecure_entry)) int wolfBoot_nsc_erase_update(uint32_t address, uint32_t len) { + int ret; + if (address > WOLFBOOT_PARTITION_SIZE) return -1; if (address + len > WOLFBOOT_PARTITION_SIZE) return -1; - return hal_flash_erase(address + WOLFBOOT_PARTITION_UPDATE_ADDRESS, len); + hal_flash_unlock(); + ret = hal_flash_erase(address + WOLFBOOT_PARTITION_UPDATE_ADDRESS, len); + hal_flash_lock(); + return ret; } __attribute__((cmse_nonsecure_entry)) int wolfBoot_nsc_write_update(uint32_t address, const uint8_t *buf, uint32_t len) { + int ret; + if (address > WOLFBOOT_PARTITION_SIZE) return -1; if (address + len > WOLFBOOT_PARTITION_SIZE) return -1; - return hal_flash_write(address + WOLFBOOT_PARTITION_UPDATE_ADDRESS, buf, len); + + hal_flash_unlock(); + ret = hal_flash_write(address + WOLFBOOT_PARTITION_UPDATE_ADDRESS, buf, len); + hal_flash_lock(); + return ret; } #endif diff --git a/test-app/app_stm32h5.c b/test-app/app_stm32h5.c index f6749c69..48ce7a96 100644 --- a/test-app/app_stm32h5.c +++ b/test-app/app_stm32h5.c @@ -267,21 +267,22 @@ static int cmd_update_xmodem(const char *args) { int ret = -1; uint8_t xpkt[XMODEM_PACKET_SIZE]; - uint32_t dst_flash = (uint32_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS; + uint32_t dst_offset = 0; uint8_t pkt_num = 0, pkt_num_expected=0xFF; uint32_t pkt_size = XMODEM_PACKET_SIZE; + uint32_t t_size = 0; uint32_t update_ver = 0; uint32_t now = jiffies; uint32_t i = 0; uint8_t pkt_num_inv; uint8_t crc, calc_crc; int transfer_started = 0; + int eot_expected = 0; printf("Erasing update partition..."); fflush(stdout); - hal_flash_unlock(); - hal_flash_erase(dst_flash, WOLFBOOT_PARTITION_SIZE); + wolfBoot_nsc_erase_update(dst_offset, WOLFBOOT_PARTITION_SIZE); printf("Done.\r\n"); printf("Waiting for XMODEM transfer...\r\n"); @@ -303,6 +304,8 @@ static int cmd_update_xmodem(const char *args) } } else { now = jiffies; + if (i == 0 && xpkt[0] == XEOT) + break; i += ret; } } @@ -313,6 +316,12 @@ static int cmd_update_xmodem(const char *args) extra_led_on(); break; } + else if (eot_expected) { + ret = 1; + uart_tx(XNAK); + break; + } + if (xpkt[0] != XSOH) { continue; } @@ -335,10 +344,9 @@ static int cmd_update_xmodem(const char *args) crc = xpkt[XMODEM_PACKET_SIZE - 1]; calc_crc = crc8(xpkt, XMODEM_PACKET_SIZE - 1); if (crc == calc_crc) { - uint32_t t_size; /* CRC is valid */ memcpy(xpkt_payload, xpkt + 3, XMODEM_PAYLOAD_SIZE); - ret = hal_flash_write(dst_flash, xpkt_payload, XMODEM_PAYLOAD_SIZE); + ret = wolfBoot_nsc_write_update(dst_offset, xpkt_payload, XMODEM_PAYLOAD_SIZE); if (ret != 0) { xcancel(); printf("Error writing to flash\r\n"); @@ -347,15 +355,16 @@ static int cmd_update_xmodem(const char *args) uart_tx(XACK); pkt_num++; pkt_num_expected++; - dst_flash += XMODEM_PAYLOAD_SIZE; - t_size = *((uint32_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 4)); - t_size += IMAGE_HEADER_SIZE; - if ((uint32_t)dst_flash >= (WOLFBOOT_PARTITION_UPDATE_ADDRESS + t_size)) { - ret = 0; - extra_led_off(); - break; + dst_offset += XMODEM_PAYLOAD_SIZE; + if (t_size == 0) { + /* At first packet, save expected partition size */ + t_size = *(uint32_t *)(xpkt_payload + 4); + t_size += IMAGE_HEADER_SIZE; } - uart_tx(XACK); + if (dst_offset >= t_size) { + eot_expected = 1; + } + /*uart_tx(XACK);*/ } else { uart_tx(XNAK); } @@ -367,17 +376,22 @@ static int cmd_update_xmodem(const char *args) uart_tx('\r'); printf("End of transfer. ret: %d\r\n", ret); - update_ver = wolfBoot_update_firmware_version(); - if (update_ver != 0) { - printf("New firmware version: 0x%lx\r\n", update_ver); - printf("Triggering update...\r\n"); - wolfBoot_update_trigger(); - printf("Update completed successfully.\r\n"); - } else { - printf("No valid image in update partition\r\n"); + if (ret != 0) { + printf("Transfer failed\r\n"); + } + else { + printf("Transfer succeeded\r\n"); + update_ver = wolfBoot_nsc_update_firmware_version(); + if (update_ver != 0) { + printf("New firmware version: 0x%lx\r\n", update_ver); + printf("Triggering update...\r\n"); + wolfBoot_nsc_update_trigger(); + printf("Update written successfully. Reboot to apply.\r\n"); + } else { + printf("No valid image in update partition\r\n"); + } } - hal_flash_lock(); return ret; } @@ -427,17 +441,17 @@ static int cmd_info(const char *args) uint16_t hdrSz; uint8_t boot_part_state = IMG_STATE_NEW, update_part_state = IMG_STATE_NEW; - cur_fw_version = wolfBoot_current_firmware_version(); - update_fw_version = wolfBoot_update_firmware_version(); + cur_fw_version = wolfBoot_nsc_current_firmware_version(); + update_fw_version = wolfBoot_nsc_update_firmware_version(); - wolfBoot_get_partition_state(PART_BOOT, &boot_part_state); - wolfBoot_get_partition_state(PART_UPDATE, &update_part_state); + wolfBoot_nsc_get_partition_state(PART_BOOT, &boot_part_state); + wolfBoot_nsc_get_partition_state(PART_UPDATE, &update_part_state); printf("\r\n"); printf("System information\r\n"); printf("====================================\r\n"); printf("Flash banks are %sswapped.\r\n", ((FLASH_OPTSR_CUR & (FLASH_OPTSR_SWAP_BANK)) == 0)?"not ":""); - printf("Firmware version : 0x%lx\r\n", wolfBoot_current_firmware_version()); + printf("Firmware version : 0x%lx\r\n", cur_fw_version); printf("Current firmware state: %s\r\n", part_state_name(boot_part_state)); if (update_fw_version != 0) { if (update_part_state == IMG_STATE_UPDATING) @@ -482,7 +496,7 @@ static int cmd_info(const char *args) static int cmd_success(const char *args) { - wolfBoot_success(); + wolfBoot_nsc_success(); printf("update success confirmed.\r\n"); return 0; } @@ -741,14 +755,13 @@ void main(void) int ret; uint32_t app_version; - /* Turn on boot LED */ boot_led_on(); /* Enable SysTick */ systick_enable(); - app_version = wolfBoot_current_firmware_version(); + app_version = wolfBoot_nsc_current_firmware_version(); nvic_irq_setprio(NVIC_USART3_IRQN, 0); nvic_irq_enable(NVIC_USART3_IRQN);