From bcfb4232c2abf25f380e233f4c497bfa3104a07d Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Fri, 9 Jan 2026 18:53:59 +0100 Subject: [PATCH 01/12] Added 'emu-test-apps' + test.sh script for m33mu --- .gitignore | 3 + Makefile | 3 + test-app/emu-test-apps/Makefile | 85 ++++++ test-app/emu-test-apps/common/emu_app.h | 10 + test-app/emu-test-apps/common/emu_hal.c | 111 ++++++++ test-app/emu-test-apps/common/emu_ivt.c | 38 +++ test-app/emu-test-apps/common/emu_startup.c | 32 +++ test-app/emu-test-apps/common/emu_syscalls.c | 127 +++++++++ test-app/emu-test-apps/common/emu_update.c | 267 ++++++++++++++++++ test-app/emu-test-apps/mcxw71/Makefile | 37 +++ test-app/emu-test-apps/mcxw71/target.h | 12 + test-app/emu-test-apps/mcxw71/target.ld | 64 +++++ test-app/emu-test-apps/mcxw71/uart.c | 46 +++ test-app/emu-test-apps/nrf5340/Makefile | 33 +++ test-app/emu-test-apps/nrf5340/target.h | 12 + test-app/emu-test-apps/nrf5340/target.ld | 69 +++++ test-app/emu-test-apps/nrf5340/uart.c | 63 +++++ test-app/emu-test-apps/stm32h563/Makefile | 33 +++ test-app/emu-test-apps/stm32h563/target.h | 13 + test-app/emu-test-apps/stm32h563/target.ld | 64 +++++ test-app/emu-test-apps/stm32h563/target_v8.ld | 64 +++++ test-app/emu-test-apps/stm32h563/tmp_server | Bin 0 -> 23480 bytes test-app/emu-test-apps/stm32h563/uart.c | 93 ++++++ test-app/emu-test-apps/stm32l552/Makefile | 33 +++ test-app/emu-test-apps/stm32l552/target.h | 13 + test-app/emu-test-apps/stm32l552/target.ld | 64 +++++ test-app/emu-test-apps/stm32l552/uart.c | 93 ++++++ test-app/emu-test-apps/stm32u585/Makefile | 33 +++ test-app/emu-test-apps/stm32u585/target.h | 13 + test-app/emu-test-apps/stm32u585/target.ld | 64 +++++ test-app/emu-test-apps/stm32u585/uart.c | 93 ++++++ test-app/emu-test-apps/test.sh | 266 +++++++++++++++++ tools/test-update-server/server.c | 12 +- 33 files changed, 1962 insertions(+), 1 deletion(-) create mode 100644 test-app/emu-test-apps/Makefile create mode 100644 test-app/emu-test-apps/common/emu_app.h create mode 100644 test-app/emu-test-apps/common/emu_hal.c create mode 100644 test-app/emu-test-apps/common/emu_ivt.c create mode 100644 test-app/emu-test-apps/common/emu_startup.c create mode 100644 test-app/emu-test-apps/common/emu_syscalls.c create mode 100644 test-app/emu-test-apps/common/emu_update.c create mode 100644 test-app/emu-test-apps/mcxw71/Makefile create mode 100644 test-app/emu-test-apps/mcxw71/target.h create mode 100644 test-app/emu-test-apps/mcxw71/target.ld create mode 100644 test-app/emu-test-apps/mcxw71/uart.c create mode 100644 test-app/emu-test-apps/nrf5340/Makefile create mode 100644 test-app/emu-test-apps/nrf5340/target.h create mode 100644 test-app/emu-test-apps/nrf5340/target.ld create mode 100644 test-app/emu-test-apps/nrf5340/uart.c create mode 100644 test-app/emu-test-apps/stm32h563/Makefile create mode 100644 test-app/emu-test-apps/stm32h563/target.h create mode 100644 test-app/emu-test-apps/stm32h563/target.ld create mode 100644 test-app/emu-test-apps/stm32h563/target_v8.ld create mode 100755 test-app/emu-test-apps/stm32h563/tmp_server create mode 100644 test-app/emu-test-apps/stm32h563/uart.c create mode 100644 test-app/emu-test-apps/stm32l552/Makefile create mode 100644 test-app/emu-test-apps/stm32l552/target.h create mode 100644 test-app/emu-test-apps/stm32l552/target.ld create mode 100644 test-app/emu-test-apps/stm32l552/uart.c create mode 100644 test-app/emu-test-apps/stm32u585/Makefile create mode 100644 test-app/emu-test-apps/stm32u585/target.h create mode 100644 test-app/emu-test-apps/stm32u585/target.ld create mode 100644 test-app/emu-test-apps/stm32u585/uart.c create mode 100755 test-app/emu-test-apps/test.sh diff --git a/.gitignore b/.gitignore index 61451464e0..06b9a225b2 100644 --- a/.gitignore +++ b/.gitignore @@ -91,6 +91,9 @@ tools/delta/bmpatch # otp-keystore-gen binary tools/keytools/otp/otp-keystore-gen +# test-server binary +test-app/emu-test-apps/*/test-update-server + # Vim swap files .*.swp diff --git a/Makefile b/Makefile index bb62d3d320..e604bc8f08 100644 --- a/Makefile +++ b/Makefile @@ -340,6 +340,9 @@ hal/$(TARGET).o: keytools_check: keytools +test-emu: + $(MAKE) -C test-app/emu-test-apps WOLFBOOT_ROOT="$(CURDIR)" test-emu + # Generate the initial signing key (only if not using user-provided keys) # - Creates wolfboot_signing_private_key.der when USER_PRIVATE_KEY is not set # - If CERT_CHAIN_VERIFY is enabled and USER_CERT_CHAIN not provided, also generates cert chain with leaf key diff --git a/test-app/emu-test-apps/Makefile b/test-app/emu-test-apps/Makefile new file mode 100644 index 0000000000..52a79ea165 --- /dev/null +++ b/test-app/emu-test-apps/Makefile @@ -0,0 +1,85 @@ +-include ../../.config +include ../../tools/config.mk +include ../../options.mk +include ../../tools/test.mk + +ifneq ($(wildcard $(WOLFBOOT_ROOT)/lib/wolfssl/wolfcrypt/src/asn.c),) + WOLFBOOT_LIB_WOLFSSL:=$(WOLFBOOT_ROOT)/lib/wolfssl +else ifneq ($(wildcard $(WOLFBOOT_ROOT)/../wolfssl/wolfcrypt/src/asn.c),) + WOLFBOOT_LIB_WOLFSSL:=$(WOLFBOOT_ROOT)/../wolfssl +endif +export WOLFBOOT_LIB_WOLFSSL + +WOLFBOOT_ROOT?=$(abspath ../..) + +EMU_VERSION?=1 +EMU_EXPECT_VERSION?=$(EMU_VERSION) +PRIVATE_KEY?=$(WOLFBOOT_ROOT)/wolfboot_signing_private_key.der + +M33MU?=$(WOLFBOOT_ROOT)/../m33mu/build/m33mu + +ifeq ($(TARGET),stm32h563) + EMU_DIR=stm32h563 + EMU_CPU=stm32h563 +else ifeq ($(TARGET),stm32h5) + EMU_DIR=stm32h563 + EMU_CPU=stm32h563 +else ifeq ($(TARGET),stm32u585) + EMU_DIR=stm32u585 + EMU_CPU=stm32u585 +else ifeq ($(TARGET),stm32u5) + EMU_DIR=stm32u585 + EMU_CPU=stm32u585 +else ifeq ($(TARGET),stm32l552) + EMU_DIR=stm32l552 + EMU_CPU=stm32l552 +else ifeq ($(TARGET),stm32l5) + EMU_DIR=stm32l552 + EMU_CPU=stm32l552 +else ifeq ($(TARGET),nrf5340) + EMU_DIR=nrf5340 + EMU_CPU=nrf5340 +else ifeq ($(TARGET),mcxw) + EMU_DIR=mcxw71 + EMU_CPU=mcxw71c +else ifeq ($(TARGET),mcxw71) + EMU_DIR=mcxw71 + EMU_CPU=mcxw71c +else + EMU_DIR= + EMU_CPU= +endif + +ifeq ($(strip $(EMU_DIR)),) + $(error Unsupported or unset TARGET=$(TARGET). Use TARGET=stm32h563|stm32h5|stm32u585|stm32u5|stm32l552|stm32l5|nrf5340|mcxw) +endif + +EMU_PATH=$(WOLFBOOT_ROOT)/test-app/emu-test-apps/$(EMU_DIR) + +.PHONY: all clean test-emu sign-emu run-emu + +all: + $(MAKE) -C $(EMU_PATH) clean app.bin + +sign-emu: all $(WOLFBOOT_ROOT)/wolfboot_signing_private_key.der + @cp $(EMU_PATH)/app.bin $(EMU_PATH)/image.bin + $(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) $(EMU_PATH)/image.bin $(PRIVATE_KEY) $(EMU_VERSION) + +run-emu: sign-emu + @echo "[EMU] CPU=$(EMU_CPU) VERSION=$(EMU_VERSION)" + @$(M33MU) --cpu $(EMU_CPU) --uart-stdout --no-tz --boot-offset=$(IMAGE_HEADER_SIZE) \ + $(EMU_PATH)/image_v$(EMU_VERSION)_signed.bin --timeout 2 \ + | tee $(EMU_PATH)/emu_uart.log + @grep -q "get_version=$(EMU_EXPECT_VERSION)" $(EMU_PATH)/emu_uart.log + +# Entry point for top-level make test-emu +# Builds, signs, runs, and validates UART output. + +test-emu: run-emu + +clean: + $(MAKE) -C $(EMU_PATH) clean + @rm -f $(EMU_PATH)/image.bin $(EMU_PATH)/image_v*_signed.bin $(EMU_PATH)/emu_uart.log + +$(WOLFBOOT_ROOT)/wolfboot_signing_private_key.der: + $(MAKE) -C $(WOLFBOOT_ROOT) WOLFBOOT_LIB_WOLFSSL="$(WOLFBOOT_LIB_WOLFSSL)" wolfboot_signing_private_key.der diff --git a/test-app/emu-test-apps/common/emu_app.h b/test-app/emu-test-apps/common/emu_app.h new file mode 100644 index 0000000000..a081bca088 --- /dev/null +++ b/test-app/emu-test-apps/common/emu_app.h @@ -0,0 +1,10 @@ +#ifndef EMU_APP_H +#define EMU_APP_H + +#include + +void emu_uart_init(void); +int emu_uart_read(uint8_t *c); +void emu_uart_write(uint8_t c); + +#endif /* EMU_APP_H */ diff --git a/test-app/emu-test-apps/common/emu_hal.c b/test-app/emu-test-apps/common/emu_hal.c new file mode 100644 index 0000000000..64249b1563 --- /dev/null +++ b/test-app/emu-test-apps/common/emu_hal.c @@ -0,0 +1,111 @@ +#include +#include +#include "target.h" +#include "hal.h" + +#if defined(EMU_STM32) +#define FLASH_BASE 0x40022000u +#define FLASH_NSKEYR (*(volatile uint32_t *)(FLASH_BASE + 0x004u)) +#define FLASH_NSCR (*(volatile uint32_t *)(FLASH_BASE + 0x028u)) +#define FLASH_KEY1 0x45670123u +#define FLASH_KEY2 0xCDEF89ABu +#define FLASH_CR_LOCK (1u << 0) +#define FLASH_CR_PG (1u << 1) +#define FLASH_CR_SER (1u << 2) +#define FLASH_CR_STRT (1u << 5) +#define FLASH_CR_SNB_SHIFT 6 +#define FLASH_CR_SNB_MASK (0x7fu << FLASH_CR_SNB_SHIFT) +#endif + +#if defined(EMU_NRF5340) +#define NVMC_BASE 0x40039000u +#define NVMC_CONFIG (*(volatile uint32_t *)(NVMC_BASE + 0x504u)) +#endif + +void hal_init(void) +{ +} + +void hal_prepare_boot(void) +{ +} + +int hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + if (data == 0 || len <= 0) { + return 0; + } + memcpy((void *)address, data, (size_t)len); + return 0; +} + +int hal_flash_erase(uint32_t address, int len) +{ +#if defined(EMU_NRF5340) + (void)address; + (void)len; + return 0; +#else + uint32_t end; +#if defined(EMU_STM32) + uint32_t base = WOLFBOOT_PARTITION_BOOT_ADDRESS; + uint32_t sector = EMU_FLASH_SECTOR_SIZE; + uint32_t start_sector; + uint32_t end_sector; + uint32_t snb; + static uint32_t last_erase_sector = 0xFFFFFFFFu; +#endif + if (len <= 0) { + return 0; + } +#if defined(EMU_STM32) + if (sector == 0u) { + return 0; + } + if (address < base) { + return 0; + } + end = address + (uint32_t)len; + start_sector = (address - base) / sector; + end_sector = ((end - 1u) - base) / sector; + for (snb = start_sector; snb <= end_sector; ++snb) { + if (snb == last_erase_sector) { + continue; + } + uint32_t cr = FLASH_NSCR & ~FLASH_CR_SNB_MASK; + cr |= FLASH_CR_SER | (snb << FLASH_CR_SNB_SHIFT); + FLASH_NSCR = cr; + FLASH_NSCR = cr | FLASH_CR_STRT; + last_erase_sector = snb; + } + FLASH_NSCR &= ~FLASH_CR_SER; +#else + end = address + (uint32_t)len; + memset((void *)address, 0xFF, (size_t)(end - address)); +#endif + return 0; +#endif +} + +void hal_flash_unlock(void) +{ +#if defined(EMU_STM32) + if ((FLASH_NSCR & FLASH_CR_LOCK) != 0u) { + FLASH_NSKEYR = FLASH_KEY1; + FLASH_NSKEYR = FLASH_KEY2; + } + FLASH_NSCR |= FLASH_CR_PG; +#elif defined(EMU_NRF5340) + NVMC_CONFIG = 1u; +#endif +} + +void hal_flash_lock(void) +{ +#if defined(EMU_STM32) + FLASH_NSCR &= ~FLASH_CR_PG; + FLASH_NSCR |= FLASH_CR_LOCK; +#elif defined(EMU_NRF5340) + NVMC_CONFIG = 0u; +#endif +} diff --git a/test-app/emu-test-apps/common/emu_ivt.c b/test-app/emu-test-apps/common/emu_ivt.c new file mode 100644 index 0000000000..6a30fd9250 --- /dev/null +++ b/test-app/emu-test-apps/common/emu_ivt.c @@ -0,0 +1,38 @@ +#include + +extern void Reset_Handler(void); +extern unsigned long _estack; + +static void default_handler(void) +{ + while (1) { + } +} + +void NMI_Handler(void) __attribute__((weak, alias("default_handler"))); +void HardFault_Handler(void) __attribute__((weak, alias("default_handler"))); +void MemManage_Handler(void) __attribute__((weak, alias("default_handler"))); +void BusFault_Handler(void) __attribute__((weak, alias("default_handler"))); +void UsageFault_Handler(void) __attribute__((weak, alias("default_handler"))); +void SVC_Handler(void) __attribute__((weak, alias("default_handler"))); +void DebugMon_Handler(void) __attribute__((weak, alias("default_handler"))); +void PendSV_Handler(void) __attribute__((weak, alias("default_handler"))); +void SysTick_Handler(void) __attribute__((weak, alias("default_handler"))); + +__attribute__((section(".isr_vector"))) +const uint32_t vector_table[16 + 48] = { + [0] = (uint32_t)&_estack, + [1] = (uint32_t)&Reset_Handler, + [2] = (uint32_t)&NMI_Handler, + [3] = (uint32_t)&HardFault_Handler, + [4] = (uint32_t)&MemManage_Handler, + [5] = (uint32_t)&BusFault_Handler, + [6] = (uint32_t)&UsageFault_Handler, + [7] = 0, [8] = 0, [9] = 0, [10] = 0, + [11] = (uint32_t)&SVC_Handler, + [12] = (uint32_t)&DebugMon_Handler, + [13] = 0, + [14] = (uint32_t)&PendSV_Handler, + [15] = (uint32_t)&SysTick_Handler, + [16 ... 63] = (uint32_t)&default_handler +}; diff --git a/test-app/emu-test-apps/common/emu_startup.c b/test-app/emu-test-apps/common/emu_startup.c new file mode 100644 index 0000000000..6a78c052e0 --- /dev/null +++ b/test-app/emu-test-apps/common/emu_startup.c @@ -0,0 +1,32 @@ +#include + +extern uint32_t _sidata; +extern uint32_t _sdata; +extern uint32_t _edata; +extern uint32_t _sbss; +extern uint32_t _ebss; +extern void __libc_init_array(void); + +int main(void); + +void Reset_Handler(void) +{ + uint32_t *src; + uint32_t *dst; + + src = &_sidata; + for (dst = &_sdata; dst < &_edata; ) { + *dst++ = *src++; + } + + for (dst = &_sbss; dst < &_ebss; ) { + *dst++ = 0u; + } + + __libc_init_array(); + (void)main(); + + while (1) { + __asm volatile("wfi"); + } +} diff --git a/test-app/emu-test-apps/common/emu_syscalls.c b/test-app/emu-test-apps/common/emu_syscalls.c new file mode 100644 index 0000000000..2828b52c77 --- /dev/null +++ b/test-app/emu-test-apps/common/emu_syscalls.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include +#include + +extern uint32_t _ebss; +extern uint32_t _estack; +extern volatile uint32_t systick_ms; +void emu_uart_putc(char c); + +static char *heap_end; + +int _write(int file, const char *ptr, int len) +{ + int i; + (void)file; + for (i = 0; i < len; ++i) { + emu_uart_putc(ptr[i]); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + +int _fstat(int file, struct stat *st) +{ + (void)file; + if (st == 0) { + errno = EINVAL; + return -1; + } + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _read(int file, char *ptr, int len) +{ + (void)file; + (void)ptr; + (void)len; + return 0; +} + +void *_sbrk(ptrdiff_t incr) +{ + char *prev; + if (heap_end == 0) { + heap_end = (char *)&_ebss; + } + prev = heap_end; + if ((heap_end + incr) >= (char *)&_estack) { + errno = ENOMEM; + return (void *)-1; + } + heap_end += incr; + return prev; +} + +int _gettimeofday(struct timeval *tv, void *tzvp) +{ + (void)tzvp; + if (tv == 0) { + errno = EINVAL; + return -1; + } + tv->tv_sec = (time_t)(systick_ms / 1000u); + tv->tv_usec = (suseconds_t)((systick_ms % 1000u) * 1000u); + return 0; +} + +time_t time(time_t *t) +{ + time_t now = (time_t)(systick_ms / 1000u); + if (t != 0) { + *t = now; + } + return now; +} + +void _exit(int status) +{ + (void)status; + while (1) { + __asm volatile("wfi"); + } +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +int _getpid(void) +{ + return 1; +} + +void _init(void) +{ +} + +void _fini(void) +{ +} diff --git a/test-app/emu-test-apps/common/emu_update.c b/test-app/emu-test-apps/common/emu_update.c new file mode 100644 index 0000000000..fd790e72a0 --- /dev/null +++ b/test-app/emu-test-apps/common/emu_update.c @@ -0,0 +1,267 @@ +#include +#include +#include +#include + +#include "emu_app.h" +#include "target.h" +#include "hal.h" +#include "wolfboot/wolfboot.h" + +#define MSGSIZE 16 +#define PAGESIZE 256 + +volatile uint32_t systick_ms = 0; + +static uint8_t page[PAGESIZE]; +static uint8_t msg[MSGSIZE]; + +static const uint8_t ERR = '!'; +static const uint8_t START = '*'; +static const uint8_t ACK = '#'; + +static uint32_t emu_im2n(uint32_t val) +{ +#ifdef BIG_ENDIAN_ORDER + val = (((val & 0x000000FFu) << 24) | + ((val & 0x0000FF00u) << 8) | + ((val & 0x00FF0000u) >> 8) | + ((val & 0xFF000000u) >> 24)); +#endif + return val; +} + +static uint8_t emu_read_u8(uintptr_t addr) +{ + uint8_t v; + __asm volatile("ldrb %0, [%1]" : "=r"(v) : "r"(addr) : "memory"); + return v; +} + +static uint32_t emu_read_u32(uintptr_t addr) +{ + uint32_t v; + __asm volatile("ldr %0, [%1]" : "=r"(v) : "r"(addr) : "memory"); + return v; +} + +static uint32_t emu_get_blob_version_addr(uintptr_t base) +{ + uintptr_t p = base + IMAGE_HEADER_OFFSET; + uintptr_t max_p = base + IMAGE_HEADER_SIZE; + uint32_t magic = emu_read_u32(base); + + if (magic != WOLFBOOT_MAGIC) { + return 0; + } + + while ((p + 4u) <= max_p) { + uint16_t htype = (uint16_t)(emu_read_u8(p) | (emu_read_u8(p + 1u) << 8)); + uint16_t len; + + if (htype == 0u) { + break; + } + if ((emu_read_u8(p) == HDR_PADDING) || ((p & 1u) != 0u)) { + p++; + continue; + } + + len = (uint16_t)(emu_read_u8(p + 2u) | (emu_read_u8(p + 3u) << 8)); + if ((4u + len) > (uint16_t)(IMAGE_HEADER_SIZE - IMAGE_HEADER_OFFSET)) { + break; + } + if (p + 4u + len > max_p) { + break; + } + + p += 4u; + if (htype == HDR_VERSION) { + return emu_im2n(emu_read_u32(p)); + } + p += len; + } + return 0; +} + +static uint32_t emu_current_version(void) +{ + uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS; + + if (addr == 0u) { + return emu_get_blob_version_addr(0u); + } + return wolfBoot_get_blob_version((uint8_t *)addr); +} + +void emu_uart_putc(char c) +{ + emu_uart_write((uint8_t)c); +} + +static void uart_write_buf(const uint8_t *buf, uint32_t len) +{ + uint32_t i; + for (i = 0; i < len; ++i) { + emu_uart_write(buf[i]); + } +} + +static uint8_t uart_read_blocking(void) +{ + uint8_t c = 0; + while (!emu_uart_read(&c)) { + __asm volatile("nop"); + } + return c; +} + +static void ack(uint32_t off) +{ + uint8_t *bytes = (uint8_t *)&off; + uint32_t i; + emu_uart_write(ACK); + for (i = 0; i < 4; i++) { + emu_uart_write(bytes[i]); + } +} + +static int check(uint8_t *pkt, int size) +{ + int i; + uint16_t c = 0; + uint16_t c_rx = *((uint16_t *)(pkt + 2)); + uint16_t *p = (uint16_t *)(pkt + 4); + for (i = 0; i < ((size - 4) >> 1); i++) { + c += p[i]; + } + if (c == c_rx) { + return 0; + } + return -1; +} + +static void wait_for_update(uint32_t version) +{ + uint32_t tlen = 0; + uint32_t recv_seq = 0; + uint32_t r_total = 0; + uint32_t tot_len = 0; + uint32_t next_seq = 0; + uint8_t *v_array = (uint8_t *)&version; + int i; + + memset(page, 0xFF, PAGESIZE); + + hal_flash_unlock(); + + emu_uart_write(START); + for (i = 3; i >= 0; i--) { + emu_uart_write(v_array[i]); + } + + while (1) { + r_total = 0; + do { + while (r_total < 2) { + msg[r_total++] = uart_read_blocking(); + if ((r_total == 2) && ((msg[0] != 0xA5) || (msg[1] != 0x5A))) { + r_total = 0; + continue; + } + } + msg[r_total++] = uart_read_blocking(); + if ((tot_len == 0) && r_total == 2 + sizeof(uint32_t)) { + break; + } + if ((r_total > 8) && (tot_len <= ((r_total - 8) + next_seq))) { + break; + } + } while (r_total < MSGSIZE); + + if (tot_len == 0) { + tlen = msg[2] + (msg[3] << 8) + (msg[4] << 16) + (msg[5] << 24); + if (tlen > WOLFBOOT_PARTITION_SIZE - 8) { + emu_uart_write(ERR); + emu_uart_write(ERR); + emu_uart_write(ERR); + emu_uart_write(ERR); + emu_uart_write(START); + recv_seq = 0; + tot_len = 0; + continue; + } + tot_len = tlen; + ack(0); + continue; + } + + if (check(msg, r_total) < 0) { + ack(next_seq); + continue; + } + + recv_seq = msg[4] + (msg[5] << 8) + (msg[6] << 16) + (msg[7] << 24); + if (recv_seq == next_seq) { + int psize = r_total - 8; + int page_idx = (int)(recv_seq % PAGESIZE); + memcpy(&page[page_idx], msg + 8, psize); + page_idx += psize; + if ((page_idx == PAGESIZE) || (next_seq + (uint32_t)psize >= tot_len)) { + uint32_t dst = (WOLFBOOT_PARTITION_UPDATE_ADDRESS + recv_seq + (uint32_t)psize) - (uint32_t)page_idx; + if ((dst % WOLFBOOT_SECTOR_SIZE) == 0u) { + hal_flash_erase(dst, WOLFBOOT_SECTOR_SIZE); + } + hal_flash_write(dst, page, PAGESIZE); + memset(page, 0xFF, PAGESIZE); + } + next_seq += (uint32_t)psize; + } + ack(next_seq); + if (next_seq >= tot_len) { + wolfBoot_update_trigger(); + __asm volatile("bkpt #0x47"); + break; + } + } + + hal_flash_lock(); + + while (1) { + __asm volatile("wfi"); + } +} + +int main(void) +{ + uint32_t version; + + emu_uart_init(); + + version = emu_current_version(); + printf("get_version=%lu\n", (unsigned long)version); + + if (version == 4u) { + wolfBoot_success(); + __asm volatile("bkpt #0x4A"); + while (1) { + __asm volatile("wfi"); + } + } + if (version == 3u) { + __asm volatile("bkpt #0x4B"); + while (1) { + __asm volatile("wfi"); + } + } + if (version == 8u) { + wolfBoot_success(); + __asm volatile("bkpt #0x4E"); + while (1) { + __asm volatile("wfi"); + } + } + + wait_for_update(version); + return 0; +} diff --git a/test-app/emu-test-apps/mcxw71/Makefile b/test-app/emu-test-apps/mcxw71/Makefile new file mode 100644 index 0000000000..4bb98e7970 --- /dev/null +++ b/test-app/emu-test-apps/mcxw71/Makefile @@ -0,0 +1,37 @@ +CC=arm-none-eabi-gcc +OBJCOPY ?= arm-none-eabi-objcopy + +CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb +MCXW71_SDK ?= ../../../../MCXW71 +CFLAGS += -I. -I../common -I../../../include +CFLAGS += -DCPU_MCXW716CMFPA +CFLAGS += -I$(MCXW71_SDK)/devices/MCXW716C -I$(MCXW71_SDK)/devices/MCXW716C/periph2 +CFLAGS += -I$(MCXW71_SDK)/CMSIS/Core/Include +LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections +LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group + +VPATH := ../common + +COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c +LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c +SRCS := $(COMMON_SRCS) uart.c +OBJS := $(SRCS:.c=.o) libwolfboot.o + +all: app.bin + +app.elf: $(OBJS) target.ld + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) -o $@ + +app.bin: app.elf + $(OBJCOPY) -O binary $< $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libwolfboot.o: $(LIBWOLFBOOT_SRC) + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) app.elf app.bin + +.PHONY: all clean diff --git a/test-app/emu-test-apps/mcxw71/target.h b/test-app/emu-test-apps/mcxw71/target.h new file mode 100644 index 0000000000..965b03f8f7 --- /dev/null +++ b/test-app/emu-test-apps/mcxw71/target.h @@ -0,0 +1,12 @@ +#ifndef H_TARGETS_TARGET_ +#define H_TARGETS_TARGET_ + +#define WOLFBOOT_FIXED_PARTITIONS + +#define WOLFBOOT_SECTOR_SIZE 0x1000u +#define WOLFBOOT_PARTITION_SIZE 0x00020000u +#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x00000000u +#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x00020000u +#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x00040000u + +#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/mcxw71/target.ld b/test-app/emu-test-apps/mcxw71/target.ld new file mode 100644 index 0000000000..3f81a1769c --- /dev/null +++ b/test-app/emu-test-apps/mcxw71/target.ld @@ -0,0 +1,64 @@ +/* Minimal linker script for MCXW716C memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000100, LENGTH = 0x000FFF00 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0001C000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/mcxw71/uart.c b/test-app/emu-test-apps/mcxw71/uart.c new file mode 100644 index 0000000000..9e528f7b0c --- /dev/null +++ b/test-app/emu-test-apps/mcxw71/uart.c @@ -0,0 +1,46 @@ +#include +#include "fsl_device_registers.h" +#include "emu_app.h" + +/* MRCC */ +#define MRCC_BASE 0x4001C000u +#define MRCC_LPUART0 0xE0u + +static inline void mrcc_enable(uint32_t off) +{ + volatile uint32_t *reg = (volatile uint32_t *)(MRCC_BASE + off); + *reg = (1u << 31) | (1u << 30) | 1u; +} + +/* LPUART0 */ +#define LPUART0_BASE 0x40038000u +#define LPUART_STAT(b) (*(volatile uint32_t *)((b) + 0x14u)) +#define LPUART_CTRL(b) (*(volatile uint32_t *)((b) + 0x18u)) +#define LPUART_DATA(b) (*(volatile uint32_t *)((b) + 0x1Cu)) + +#define LPUART_STAT_TDRE (1u << 23) +#define LPUART_STAT_RDRF (1u << 21) +#define LPUART_CTRL_RE (1u << 18) +#define LPUART_CTRL_TE (1u << 19) + +void emu_uart_init(void) +{ + mrcc_enable(MRCC_LPUART0); + LPUART_CTRL(LPUART0_BASE) = LPUART_CTRL_TE | LPUART_CTRL_RE; +} + +void emu_uart_write(uint8_t c) +{ + while ((LPUART_STAT(LPUART0_BASE) & LPUART_STAT_TDRE) == 0u) { + } + LPUART_DATA(LPUART0_BASE) = (uint32_t)c; +} + +int emu_uart_read(uint8_t *c) +{ + if ((LPUART_STAT(LPUART0_BASE) & LPUART_STAT_RDRF) == 0u) { + return 0; + } + *c = (uint8_t)LPUART_DATA(LPUART0_BASE); + return 1; +} diff --git a/test-app/emu-test-apps/nrf5340/Makefile b/test-app/emu-test-apps/nrf5340/Makefile new file mode 100644 index 0000000000..1b7a1074e4 --- /dev/null +++ b/test-app/emu-test-apps/nrf5340/Makefile @@ -0,0 +1,33 @@ +CC=arm-none-eabi-gcc +OBJCOPY ?= arm-none-eabi-objcopy + +CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb +CFLAGS += -I. -I../common -I../../../include -DEMU_NRF5340 +LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections +LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group + +VPATH := ../common + +COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c +LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c +SRCS := $(COMMON_SRCS) uart.c +OBJS := $(SRCS:.c=.o) libwolfboot.o + +all: app.bin + +app.elf: $(OBJS) target.ld + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) -o $@ + +app.bin: app.elf + $(OBJCOPY) -O binary $< $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libwolfboot.o: $(LIBWOLFBOOT_SRC) + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) app.elf app.bin + +.PHONY: all clean diff --git a/test-app/emu-test-apps/nrf5340/target.h b/test-app/emu-test-apps/nrf5340/target.h new file mode 100644 index 0000000000..965b03f8f7 --- /dev/null +++ b/test-app/emu-test-apps/nrf5340/target.h @@ -0,0 +1,12 @@ +#ifndef H_TARGETS_TARGET_ +#define H_TARGETS_TARGET_ + +#define WOLFBOOT_FIXED_PARTITIONS + +#define WOLFBOOT_SECTOR_SIZE 0x1000u +#define WOLFBOOT_PARTITION_SIZE 0x00020000u +#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x00000000u +#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x00020000u +#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x00040000u + +#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/nrf5340/target.ld b/test-app/emu-test-apps/nrf5340/target.ld new file mode 100644 index 0000000000..de88a7e0f8 --- /dev/null +++ b/test-app/emu-test-apps/nrf5340/target.ld @@ -0,0 +1,69 @@ +/* Minimal linker script for nRF5340 (application core) memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000100, LENGTH = 0x000FFF00 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00080000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM + + .testpage ORIGIN(FLASH) + LENGTH(FLASH) - 0x1000 : + { + KEEP(*(.testpage*)) + } > FLASH +} diff --git a/test-app/emu-test-apps/nrf5340/uart.c b/test-app/emu-test-apps/nrf5340/uart.c new file mode 100644 index 0000000000..7a7492a243 --- /dev/null +++ b/test-app/emu-test-apps/nrf5340/uart.c @@ -0,0 +1,63 @@ +#include +#include "emu_app.h" + +#define UARTE0_BASE 0x40008000u +#define CLOCK_BASE 0x40005000u +#define CLOCK_TASKS_HFCLKSTART (*(volatile uint32_t *)((CLOCK_BASE) + 0x000u)) +#define UARTE_TASKS_STARTRX(b) (*(volatile uint32_t *)((b) + 0x000u)) +#define UARTE_TASKS_STOPRX(b) (*(volatile uint32_t *)((b) + 0x004u)) +#define UARTE_TASKS_STARTTX(b) (*(volatile uint32_t *)((b) + 0x008u)) +#define UARTE_EVENTS_ENDRX(b) (*(volatile uint32_t *)((b) + 0x110u)) +#define UARTE_EVENTS_ENDTX(b) (*(volatile uint32_t *)((b) + 0x120u)) +#define UARTE_ENABLE(b) (*(volatile uint32_t *)((b) + 0x500u)) +#define UARTE_PSEL_TXD(b) (*(volatile uint32_t *)((b) + 0x50Cu)) +#define UARTE_PSEL_RXD(b) (*(volatile uint32_t *)((b) + 0x514u)) +#define UARTE_BAUDRATE(b) (*(volatile uint32_t *)((b) + 0x524u)) +#define UARTE_RXD_PTR(b) (*(volatile uint32_t *)((b) + 0x534u)) +#define UARTE_RXD_MAXCNT(b) (*(volatile uint32_t *)((b) + 0x538u)) +#define UARTE_TXD_PTR(b) (*(volatile uint32_t *)((b) + 0x544u)) +#define UARTE_TXD_MAXCNT(b) (*(volatile uint32_t *)((b) + 0x548u)) + +static volatile uint8_t uart_tx_byte; +static volatile uint8_t uart_rx_byte; + +static void uarte0_start_rx(void) +{ + UARTE_RXD_PTR(UARTE0_BASE) = (uint32_t)&uart_rx_byte; + UARTE_RXD_MAXCNT(UARTE0_BASE) = 1u; + UARTE_EVENTS_ENDRX(UARTE0_BASE) = 0u; + UARTE_TASKS_STARTRX(UARTE0_BASE) = 1u; +} + +void emu_uart_init(void) +{ + CLOCK_TASKS_HFCLKSTART = 1u; + UARTE_ENABLE(UARTE0_BASE) = 0u; + UARTE_PSEL_TXD(UARTE0_BASE) = 0u; + UARTE_PSEL_RXD(UARTE0_BASE) = 0u; + UARTE_BAUDRATE(UARTE0_BASE) = 0x01D7E000u; /* 115200 */ + UARTE_ENABLE(UARTE0_BASE) = 8u; + uarte0_start_rx(); +} + +void emu_uart_write(uint8_t c) +{ + uart_tx_byte = c; + UARTE_TXD_PTR(UARTE0_BASE) = (uint32_t)&uart_tx_byte; + UARTE_TXD_MAXCNT(UARTE0_BASE) = 1u; + UARTE_EVENTS_ENDTX(UARTE0_BASE) = 0u; + UARTE_TASKS_STARTTX(UARTE0_BASE) = 1u; + while (UARTE_EVENTS_ENDTX(UARTE0_BASE) == 0u) { + } +} + +int emu_uart_read(uint8_t *c) +{ + if (UARTE_EVENTS_ENDRX(UARTE0_BASE) == 0u) { + return 0; + } + UARTE_EVENTS_ENDRX(UARTE0_BASE) = 0u; + *c = uart_rx_byte; + uarte0_start_rx(); + return 1; +} diff --git a/test-app/emu-test-apps/stm32h563/Makefile b/test-app/emu-test-apps/stm32h563/Makefile new file mode 100644 index 0000000000..5cd0ca9c0b --- /dev/null +++ b/test-app/emu-test-apps/stm32h563/Makefile @@ -0,0 +1,33 @@ +CC=arm-none-eabi-gcc +OBJCOPY ?= arm-none-eabi-objcopy + +CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb +CFLAGS += -I. -I../common -I../../../include -DEMU_STM32 +LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections +LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group + +VPATH := ../common + +COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c +LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c +SRCS := $(COMMON_SRCS) uart.c +OBJS := $(SRCS:.c=.o) libwolfboot.o + +all: app.bin + +app.elf: $(OBJS) target.ld + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) -o $@ + +app.bin: app.elf + $(OBJCOPY) -O binary $< $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libwolfboot.o: $(LIBWOLFBOOT_SRC) + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) app.elf app.bin + +.PHONY: all clean diff --git a/test-app/emu-test-apps/stm32h563/target.h b/test-app/emu-test-apps/stm32h563/target.h new file mode 100644 index 0000000000..5da0027169 --- /dev/null +++ b/test-app/emu-test-apps/stm32h563/target.h @@ -0,0 +1,13 @@ +#ifndef H_TARGETS_TARGET_ +#define H_TARGETS_TARGET_ + +#define WOLFBOOT_FIXED_PARTITIONS + +#define WOLFBOOT_SECTOR_SIZE 0x1000u +#define EMU_FLASH_SECTOR_SIZE 0x4000u +#define WOLFBOOT_PARTITION_SIZE 0x00020000u +#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08000000u +#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08020000u +#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08040000u + +#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/stm32h563/target.ld b/test-app/emu-test-apps/stm32h563/target.ld new file mode 100644 index 0000000000..1aa5595856 --- /dev/null +++ b/test-app/emu-test-apps/stm32h563/target.ld @@ -0,0 +1,64 @@ +/* Minimal linker script for STM32H563 memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000100, LENGTH = 0x001FFF00 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x000A0000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/stm32h563/target_v8.ld b/test-app/emu-test-apps/stm32h563/target_v8.ld new file mode 100644 index 0000000000..dfae293cd4 --- /dev/null +++ b/test-app/emu-test-apps/stm32h563/target_v8.ld @@ -0,0 +1,64 @@ +/* Minimal linker script for STM32H563 memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x8060100, LENGTH = 0x001FFF00 + RAM (rwx) : ORIGIN = 0x8060100, LENGTH = 0x000A0000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/stm32h563/tmp_server b/test-app/emu-test-apps/stm32h563/tmp_server new file mode 100755 index 0000000000000000000000000000000000000000..331da841958f76f440fed9f27bec38392484903c GIT binary patch literal 23480 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 literal 0 HcmV?d00001 diff --git a/test-app/emu-test-apps/stm32h563/uart.c b/test-app/emu-test-apps/stm32h563/uart.c new file mode 100644 index 0000000000..a981f94327 --- /dev/null +++ b/test-app/emu-test-apps/stm32h563/uart.c @@ -0,0 +1,93 @@ +#include +#include "emu_app.h" + +#define SYSCLK_HZ 64000000u + +/* RCC */ +#define RCC_BASE 0x44020C00u +#define RCC_AHB2ENR (*(volatile uint32_t *)(RCC_BASE + 0x8Cu)) +#define RCC_APB1LENR (*(volatile uint32_t *)(RCC_BASE + 0x9Cu)) + +/* GPIOA/GPIOB/GPIOD */ +#define GPIOA_BASE 0x42020000u +#define GPIOB_BASE 0x42020400u +#define GPIOD_BASE 0x42020C00u +#define GPIO_MODER(x) (*(volatile uint32_t *)((x) + 0x00u)) +#define GPIO_OTYPER(x) (*(volatile uint32_t *)((x) + 0x04u)) +#define GPIO_OSPEEDR(x) (*(volatile uint32_t *)((x) + 0x08u)) +#define GPIO_PUPDR(x) (*(volatile uint32_t *)((x) + 0x0Cu)) +#define GPIO_AFRH(x) (*(volatile uint32_t *)((x) + 0x24u)) + +/* USART3 */ +#define USART3_BASE 0x40004800u +#define USART_CR1(b) (*(volatile uint32_t *)((b) + 0x00u)) +#define USART_CR2(b) (*(volatile uint32_t *)((b) + 0x04u)) +#define USART_CR3(b) (*(volatile uint32_t *)((b) + 0x08u)) +#define USART_BRR(b) (*(volatile uint32_t *)((b) + 0x0Cu)) +#define USART_ISR(b) (*(volatile uint32_t *)((b) + 0x1Cu)) +#define USART_RDR(b) (*(volatile uint32_t *)((b) + 0x24u)) +#define USART_TDR(b) (*(volatile uint32_t *)((b) + 0x28u)) + +static void gpio_config_usart3_pd8_pd9(void) +{ + uint32_t v; + RCC_AHB2ENR |= (1u << 3); + + v = GPIO_MODER(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (2u << (8u * 2u)) | (2u << (9u * 2u)); + GPIO_MODER(GPIOD_BASE) = v; + + v = GPIO_OTYPER(GPIOD_BASE); + v &= ~((1u << 8) | (1u << 9)); + GPIO_OTYPER(GPIOD_BASE) = v; + + v = GPIO_OSPEEDR(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (2u << (8u * 2u)) | (2u << (9u * 2u)); + GPIO_OSPEEDR(GPIOD_BASE) = v; + + v = GPIO_PUPDR(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (1u << (9u * 2u)); + GPIO_PUPDR(GPIOD_BASE) = v; + + v = GPIO_AFRH(GPIOD_BASE); + v &= ~((0xFu << ((8u - 8u) * 4u)) | (0xFu << ((9u - 8u) * 4u))); + v |= (7u << ((8u - 8u) * 4u)) | (7u << ((9u - 8u) * 4u)); + GPIO_AFRH(GPIOD_BASE) = v; +} + +static void usart3_init_115200(void) +{ + uint32_t brr; + RCC_APB1LENR |= (1u << 18); + USART_CR1(USART3_BASE) = 0; + USART_CR2(USART3_BASE) = 0; + USART_CR3(USART3_BASE) = 0; + brr = SYSCLK_HZ / 115200u; + USART_BRR(USART3_BASE) = brr; + USART_CR1(USART3_BASE) = (1u << 0) | (1u << 2) | (1u << 3); +} + +void emu_uart_init(void) +{ + gpio_config_usart3_pd8_pd9(); + usart3_init_115200(); +} + +void emu_uart_write(uint8_t c) +{ + while ((USART_ISR(USART3_BASE) & (1u << 7)) == 0u) { + } + USART_TDR(USART3_BASE) = (uint32_t)c; +} + +int emu_uart_read(uint8_t *c) +{ + if ((USART_ISR(USART3_BASE) & (1u << 5)) == 0u) { + return 0; + } + *c = (uint8_t)USART_RDR(USART3_BASE); + return 1; +} diff --git a/test-app/emu-test-apps/stm32l552/Makefile b/test-app/emu-test-apps/stm32l552/Makefile new file mode 100644 index 0000000000..5cd0ca9c0b --- /dev/null +++ b/test-app/emu-test-apps/stm32l552/Makefile @@ -0,0 +1,33 @@ +CC=arm-none-eabi-gcc +OBJCOPY ?= arm-none-eabi-objcopy + +CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb +CFLAGS += -I. -I../common -I../../../include -DEMU_STM32 +LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections +LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group + +VPATH := ../common + +COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c +LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c +SRCS := $(COMMON_SRCS) uart.c +OBJS := $(SRCS:.c=.o) libwolfboot.o + +all: app.bin + +app.elf: $(OBJS) target.ld + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) -o $@ + +app.bin: app.elf + $(OBJCOPY) -O binary $< $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libwolfboot.o: $(LIBWOLFBOOT_SRC) + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) app.elf app.bin + +.PHONY: all clean diff --git a/test-app/emu-test-apps/stm32l552/target.h b/test-app/emu-test-apps/stm32l552/target.h new file mode 100644 index 0000000000..83cb4647fe --- /dev/null +++ b/test-app/emu-test-apps/stm32l552/target.h @@ -0,0 +1,13 @@ +#ifndef H_TARGETS_TARGET_ +#define H_TARGETS_TARGET_ + +#define WOLFBOOT_FIXED_PARTITIONS + +#define WOLFBOOT_SECTOR_SIZE 0x1000u +#define EMU_FLASH_SECTOR_SIZE 0x1000u +#define WOLFBOOT_PARTITION_SIZE 0x00020000u +#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08000000u +#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08020000u +#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08040000u + +#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/stm32l552/target.ld b/test-app/emu-test-apps/stm32l552/target.ld new file mode 100644 index 0000000000..a9e5366223 --- /dev/null +++ b/test-app/emu-test-apps/stm32l552/target.ld @@ -0,0 +1,64 @@ +/* Minimal linker script for STM32L552 memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000100, LENGTH = 0x0007FF00 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/stm32l552/uart.c b/test-app/emu-test-apps/stm32l552/uart.c new file mode 100644 index 0000000000..caab44694d --- /dev/null +++ b/test-app/emu-test-apps/stm32l552/uart.c @@ -0,0 +1,93 @@ +#include +#include "emu_app.h" + +#define SYSCLK_HZ 64000000u + +/* RCC */ +#define RCC_BASE 0x40021000u +#define RCC_AHB2ENR (*(volatile uint32_t *)(RCC_BASE + 0x4Cu)) +#define RCC_APB1LENR (*(volatile uint32_t *)(RCC_BASE + 0x58u)) + +/* GPIOA/GPIOB/GPIOD */ +#define GPIOA_BASE 0x42020000u +#define GPIOB_BASE 0x42020400u +#define GPIOD_BASE 0x42020C00u +#define GPIO_MODER(x) (*(volatile uint32_t *)((x) + 0x00u)) +#define GPIO_OTYPER(x) (*(volatile uint32_t *)((x) + 0x04u)) +#define GPIO_OSPEEDR(x) (*(volatile uint32_t *)((x) + 0x08u)) +#define GPIO_PUPDR(x) (*(volatile uint32_t *)((x) + 0x0Cu)) +#define GPIO_AFRH(x) (*(volatile uint32_t *)((x) + 0x24u)) + +/* USART3 */ +#define USART3_BASE 0x40004800u +#define USART_CR1(b) (*(volatile uint32_t *)((b) + 0x00u)) +#define USART_CR2(b) (*(volatile uint32_t *)((b) + 0x04u)) +#define USART_CR3(b) (*(volatile uint32_t *)((b) + 0x08u)) +#define USART_BRR(b) (*(volatile uint32_t *)((b) + 0x0Cu)) +#define USART_ISR(b) (*(volatile uint32_t *)((b) + 0x1Cu)) +#define USART_RDR(b) (*(volatile uint32_t *)((b) + 0x24u)) +#define USART_TDR(b) (*(volatile uint32_t *)((b) + 0x28u)) + +static void gpio_config_usart3_pd8_pd9(void) +{ + uint32_t v; + RCC_AHB2ENR |= (1u << 3); + + v = GPIO_MODER(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (2u << (8u * 2u)) | (2u << (9u * 2u)); + GPIO_MODER(GPIOD_BASE) = v; + + v = GPIO_OTYPER(GPIOD_BASE); + v &= ~((1u << 8) | (1u << 9)); + GPIO_OTYPER(GPIOD_BASE) = v; + + v = GPIO_OSPEEDR(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (2u << (8u * 2u)) | (2u << (9u * 2u)); + GPIO_OSPEEDR(GPIOD_BASE) = v; + + v = GPIO_PUPDR(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (1u << (9u * 2u)); + GPIO_PUPDR(GPIOD_BASE) = v; + + v = GPIO_AFRH(GPIOD_BASE); + v &= ~((0xFu << ((8u - 8u) * 4u)) | (0xFu << ((9u - 8u) * 4u))); + v |= (7u << ((8u - 8u) * 4u)) | (7u << ((9u - 8u) * 4u)); + GPIO_AFRH(GPIOD_BASE) = v; +} + +static void usart3_init_115200(void) +{ + uint32_t brr; + RCC_APB1LENR |= (1u << 18); + USART_CR1(USART3_BASE) = 0; + USART_CR2(USART3_BASE) = 0; + USART_CR3(USART3_BASE) = 0; + brr = SYSCLK_HZ / 115200u; + USART_BRR(USART3_BASE) = brr; + USART_CR1(USART3_BASE) = (1u << 0) | (1u << 2) | (1u << 3); +} + +void emu_uart_init(void) +{ + gpio_config_usart3_pd8_pd9(); + usart3_init_115200(); +} + +void emu_uart_write(uint8_t c) +{ + while ((USART_ISR(USART3_BASE) & (1u << 7)) == 0u) { + } + USART_TDR(USART3_BASE) = (uint32_t)c; +} + +int emu_uart_read(uint8_t *c) +{ + if ((USART_ISR(USART3_BASE) & (1u << 5)) == 0u) { + return 0; + } + *c = (uint8_t)USART_RDR(USART3_BASE); + return 1; +} diff --git a/test-app/emu-test-apps/stm32u585/Makefile b/test-app/emu-test-apps/stm32u585/Makefile new file mode 100644 index 0000000000..5cd0ca9c0b --- /dev/null +++ b/test-app/emu-test-apps/stm32u585/Makefile @@ -0,0 +1,33 @@ +CC=arm-none-eabi-gcc +OBJCOPY ?= arm-none-eabi-objcopy + +CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb +CFLAGS += -I. -I../common -I../../../include -DEMU_STM32 +LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections +LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group + +VPATH := ../common + +COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c +LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c +SRCS := $(COMMON_SRCS) uart.c +OBJS := $(SRCS:.c=.o) libwolfboot.o + +all: app.bin + +app.elf: $(OBJS) target.ld + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) -o $@ + +app.bin: app.elf + $(OBJCOPY) -O binary $< $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libwolfboot.o: $(LIBWOLFBOOT_SRC) + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) app.elf app.bin + +.PHONY: all clean diff --git a/test-app/emu-test-apps/stm32u585/target.h b/test-app/emu-test-apps/stm32u585/target.h new file mode 100644 index 0000000000..5da0027169 --- /dev/null +++ b/test-app/emu-test-apps/stm32u585/target.h @@ -0,0 +1,13 @@ +#ifndef H_TARGETS_TARGET_ +#define H_TARGETS_TARGET_ + +#define WOLFBOOT_FIXED_PARTITIONS + +#define WOLFBOOT_SECTOR_SIZE 0x1000u +#define EMU_FLASH_SECTOR_SIZE 0x4000u +#define WOLFBOOT_PARTITION_SIZE 0x00020000u +#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08000000u +#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08020000u +#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08040000u + +#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/stm32u585/target.ld b/test-app/emu-test-apps/stm32u585/target.ld new file mode 100644 index 0000000000..07f6835a1d --- /dev/null +++ b/test-app/emu-test-apps/stm32u585/target.ld @@ -0,0 +1,64 @@ +/* Minimal linker script for STM32U585 memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000100, LENGTH = 0x001FFF00 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x000C0000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/stm32u585/uart.c b/test-app/emu-test-apps/stm32u585/uart.c new file mode 100644 index 0000000000..09bf2dd353 --- /dev/null +++ b/test-app/emu-test-apps/stm32u585/uart.c @@ -0,0 +1,93 @@ +#include +#include "emu_app.h" + +#define SYSCLK_HZ 64000000u + +/* RCC */ +#define RCC_BASE 0x46020C00u +#define RCC_AHB2ENR (*(volatile uint32_t *)(RCC_BASE + 0x8Cu)) +#define RCC_APB1LENR (*(volatile uint32_t *)(RCC_BASE + 0x9Cu)) + +/* GPIOA/GPIOB/GPIOD */ +#define GPIOA_BASE 0x42020000u +#define GPIOB_BASE 0x42020400u +#define GPIOD_BASE 0x42020C00u +#define GPIO_MODER(x) (*(volatile uint32_t *)((x) + 0x00u)) +#define GPIO_OTYPER(x) (*(volatile uint32_t *)((x) + 0x04u)) +#define GPIO_OSPEEDR(x) (*(volatile uint32_t *)((x) + 0x08u)) +#define GPIO_PUPDR(x) (*(volatile uint32_t *)((x) + 0x0Cu)) +#define GPIO_AFRH(x) (*(volatile uint32_t *)((x) + 0x24u)) + +/* USART3 */ +#define USART3_BASE 0x40004800u +#define USART_CR1(b) (*(volatile uint32_t *)((b) + 0x00u)) +#define USART_CR2(b) (*(volatile uint32_t *)((b) + 0x04u)) +#define USART_CR3(b) (*(volatile uint32_t *)((b) + 0x08u)) +#define USART_BRR(b) (*(volatile uint32_t *)((b) + 0x0Cu)) +#define USART_ISR(b) (*(volatile uint32_t *)((b) + 0x1Cu)) +#define USART_RDR(b) (*(volatile uint32_t *)((b) + 0x24u)) +#define USART_TDR(b) (*(volatile uint32_t *)((b) + 0x28u)) + +static void gpio_config_usart3_pd8_pd9(void) +{ + uint32_t v; + RCC_AHB2ENR |= (1u << 3); + + v = GPIO_MODER(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (2u << (8u * 2u)) | (2u << (9u * 2u)); + GPIO_MODER(GPIOD_BASE) = v; + + v = GPIO_OTYPER(GPIOD_BASE); + v &= ~((1u << 8) | (1u << 9)); + GPIO_OTYPER(GPIOD_BASE) = v; + + v = GPIO_OSPEEDR(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (2u << (8u * 2u)) | (2u << (9u * 2u)); + GPIO_OSPEEDR(GPIOD_BASE) = v; + + v = GPIO_PUPDR(GPIOD_BASE); + v &= ~((3u << (8u * 2u)) | (3u << (9u * 2u))); + v |= (1u << (9u * 2u)); + GPIO_PUPDR(GPIOD_BASE) = v; + + v = GPIO_AFRH(GPIOD_BASE); + v &= ~((0xFu << ((8u - 8u) * 4u)) | (0xFu << ((9u - 8u) * 4u))); + v |= (7u << ((8u - 8u) * 4u)) | (7u << ((9u - 8u) * 4u)); + GPIO_AFRH(GPIOD_BASE) = v; +} + +static void usart3_init_115200(void) +{ + uint32_t brr; + RCC_APB1LENR |= (1u << 18); + USART_CR1(USART3_BASE) = 0; + USART_CR2(USART3_BASE) = 0; + USART_CR3(USART3_BASE) = 0; + brr = SYSCLK_HZ / 115200u; + USART_BRR(USART3_BASE) = brr; + USART_CR1(USART3_BASE) = (1u << 0) | (1u << 2) | (1u << 3); +} + +void emu_uart_init(void) +{ + gpio_config_usart3_pd8_pd9(); + usart3_init_115200(); +} + +void emu_uart_write(uint8_t c) +{ + while ((USART_ISR(USART3_BASE) & (1u << 7)) == 0u) { + } + USART_TDR(USART3_BASE) = (uint32_t)c; +} + +int emu_uart_read(uint8_t *c) +{ + if ((USART_ISR(USART3_BASE) & (1u << 5)) == 0u) { + return 0; + } + *c = (uint8_t)USART_RDR(USART3_BASE); + return 1; +} diff --git a/test-app/emu-test-apps/test.sh b/test-app/emu-test-apps/test.sh new file mode 100755 index 0000000000..400197664f --- /dev/null +++ b/test-app/emu-test-apps/test.sh @@ -0,0 +1,266 @@ +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WOLFBOOT_ROOT="${WOLFBOOT_ROOT:-$(cd "$script_dir/../.." && pwd)}" +EMU_APPS="$WOLFBOOT_ROOT/test-app/emu-test-apps" +M33MU="${M33MU:-$(command -v m33mu || true)}" +UPDATE_SERVER_SRC="$WOLFBOOT_ROOT/tools/test-update-server/server.c" + +die() { + echo "error: $*" >&2 + exit 1 +} + +log() { + echo "==> $*" +} + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || die "missing required command: $1" +} + +if [[ -z "${TARGET:-}" && -f "$WOLFBOOT_ROOT/.config" ]]; then + TARGET="$(grep -m1 '^TARGET' "$WOLFBOOT_ROOT/.config" 2>/dev/null | sed -E 's/^TARGET[?]*=//' || true)" +fi +TARGET="${TARGET:-}" +[[ -n "${TARGET}" ]] || die "TARGET not set (export TARGET=... or set in .config)" + +EMU_DIR="" +EMU_CPU="" +UART_BASE="" + +get_m33mu_target() { + case "$1" in + stm32h563|stm32h5) echo "stm32h563" ;; + stm32u585|stm32u5) echo "stm32u585" ;; + stm32l552|stm32l5) echo "stm32l552" ;; + nrf5340) echo "nrf5340" ;; + mcxw|mcxw71) echo "mcxw71c" ;; + *) echo "" ;; + esac +} +case "$TARGET" in + stm32h563|stm32h5) EMU_DIR=stm32h563; UART_BASE=40004800 ;; + stm32u585|stm32u5) EMU_DIR=stm32u585; UART_BASE=40004800 ;; + stm32l552|stm32l5) EMU_DIR=stm32l552; UART_BASE=40004800 ;; + nrf5340) EMU_DIR=nrf5340; UART_BASE=40008000 ;; + mcxw|mcxw71) EMU_DIR=mcxw71; UART_BASE=40038000 ;; + *) die "unsupported TARGET=$TARGET" ;; +esac +EMU_CPU="$(get_m33mu_target "$TARGET")" +[[ -n "$EMU_CPU" ]] || die "unsupported TARGET=$TARGET (no m33mu mapping)" + +need_cmd "$M33MU" +need_cmd make +need_cmd grep +need_cmd python3 +need_cmd gcc + +EMU_IMAGE_HEADER_SIZE="${EMU_IMAGE_HEADER_SIZE:-256}" +IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" +WOLFBOOT_BIN="$WOLFBOOT_ROOT/wolfboot.bin" + +EMU_PATH="$EMU_APPS/$EMU_DIR" +FACTORY_IMAGE="$EMU_PATH/image_v1_signed.bin" +FACTORY_IMAGE_BASE="$EMU_PATH/image_v1_factory.bin" +UPDATE_IMAGE_V4="$EMU_PATH/image_v4_signed.bin" +UPDATE_IMAGE_V3="$EMU_PATH/image_v3_signed.bin" +UPDATE_IMAGE_V8="$EMU_PATH/image_v8_signed.bin" + +STDBUF="" +if command -v stdbuf >/dev/null 2>&1; then + STDBUF="stdbuf -o0 -e0" +fi + +make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=1 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu +make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=3 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu +make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=4 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu +make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=8 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu +UPDATE_SERVER_BIN="$EMU_PATH/test-update-server" + +cp -f "$FACTORY_IMAGE" "$FACTORY_IMAGE_BASE" + +reset_factory_image() { + cp -f "$FACTORY_IMAGE_BASE" "$FACTORY_IMAGE" +} + +build_update_server() { + local uart_dev="$1" + gcc -Wall -g -ggdb -DUART_DEV="\"$uart_dev\"" -o "$UPDATE_SERVER_BIN" "$UPDATE_SERVER_SRC" -lpthread +} + +log "Scenario A: factory boot" +reset_factory_image +factory_log="$EMU_PATH/factory.log" +log "factory run: boot image v1, expect UART get_version=1" +set +e +$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ + --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 --expect-bkpt=0x00 \ + "$FACTORY_IMAGE" >"$factory_log" 2>&1 +factory_rc=$? +set -e +grep -q "get_version=1" "$factory_log" || die "factory run: expected get_version=1" +if [[ $factory_rc -ne 0 && $factory_rc -ne 127 ]]; then + die "factory run: m33mu exited with $factory_rc" +fi +log "factory run: ok (version=1)" + +wait_for_pts() { + local log="$1" + local base="$2" + local pts="" + local i + for i in $(seq 1 100); do + pts="$(grep "\\[UART\\] ${base} attached to" "$log" | tail -n1 | sed 's/.* //' || true)" + if [[ -n "$pts" ]]; then + echo "$pts" + return 0 + fi + sleep 0.05 + done + return 1 +} + +check_update_version_in_image() { + local image="$1" + local expected="$2" + local target_h="$EMU_PATH/target.h" + local boot_addr + local update_addr + boot_addr="$(grep -m1 'WOLFBOOT_PARTITION_BOOT_ADDRESS' "$target_h" | sed 's/.*0x/0x/' | cut -d'u' -f1)" + update_addr="$(grep -m1 'WOLFBOOT_PARTITION_UPDATE_ADDRESS' "$target_h" | sed 's/.*0x/0x/' | cut -d'u' -f1)" + python3 - "$image" "$boot_addr" "$update_addr" "$IMAGE_HEADER_SIZE" "$expected" <<'PY' +import sys, struct +path, boot_s, update_s, hdr_s, expected_s = sys.argv[1:6] +boot = int(boot_s, 16) +update = int(update_s, 16) +hdr = int(hdr_s, 0) +expected = int(expected_s, 0) +off = update - boot +data = open(path, "rb").read() +if off + 8 > len(data): + print("0") + sys.exit(1) +magic, = struct.unpack_from(" (hdr - IMAGE_HEADER_OFFSET): + break + if p + 4 + length > max_p: + break + p += 4 + if htype == HDR_VERSION: + version, = struct.unpack_from(""$update_log" + check_pty_available || die "no PTY devices available (needed for ufserver)" +UPDATE_TIMEOUT="${UPDATE_TIMEOUT:-120}" + log "$label: start emulator (expect BKPT 0x47 when update is accepted)" + $STDBUF "$M33MU" --cpu "$EMU_CPU" --no-tz --persist \ + --boot-offset="$IMAGE_HEADER_SIZE" --timeout "$UPDATE_TIMEOUT" --expect-bkpt=0x47 \ + "$FACTORY_IMAGE" >"$update_log" 2>&1 & + emu_pid=$! + + pts="$(wait_for_pts "$update_log" "$UART_BASE")" || die "$label: failed to detect UART PTY" + log "$label: UART attached at $pts" + build_update_server "$pts" + if [[ -n "$STDBUF" ]]; then + log "$label: transferring update image (v$expected_version) over UART" + $STDBUF "$UPDATE_SERVER_BIN" "$update_image" >"$server_log" 2>&1 & + else + log "$label: transferring update image (v$expected_version) over UART" + "$UPDATE_SERVER_BIN" "$update_image" >"$server_log" 2>&1 & + fi + server_pid=$! + + set +e + wait "$emu_pid" + emu_rc=$? + set -e + kill "$server_pid" >/dev/null 2>&1 || true + wait "$server_pid" >/dev/null 2>&1 || true + [[ $emu_rc -eq 0 ]] || die "$label: m33mu exited with $emu_rc" + grep -q "\\[EXPECT BKPT\\] Success" "$update_log" || die "$label: expected BKPT 0x47" + log "$label: BKPT 0x47 hit (update accepted)" + check_update_version_in_image "$FACTORY_IMAGE" "$expected_version" || die "$label: update partition version mismatch" + log "$label: update partition version=$expected_version" +} + +log "Scenario B: successful update from v1 to v4" +reset_factory_image +run_update_scenario "scenario_b_update" "$UPDATE_IMAGE_V4" 4 + +for i in 1 2; do + run_log="$EMU_PATH/reboot_v4_${i}.log" + log "Scenario B: reboot run $i: boot updated image v4, expect BKPT 0x4A (success)" + $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ + --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 --expect-bkpt=0x4a \ + "$UPDATE_IMAGE_V4" >"$run_log" 2>&1 || die "reboot v4 run $i: m33mu failed" + grep -q "\\[EXPECT BKPT\\] Success" "$run_log" || die "reboot v4 run $i: expected BKPT 0x4A" + log "Scenario B: reboot run $i: BKPT 0x4A hit" +done + +log "Scenario C: update to v3 then fallback (no wolfBoot_success)" +reset_factory_image +run_update_scenario "scenario_c_update" "$UPDATE_IMAGE_V3" 3 + +log "Scenario C: reboot into v3 (expect BKPT 0x4B, no success call)" +run_log_v3="$EMU_PATH/reboot_v3.log" +$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ + --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 --expect-bkpt=0x4b \ + "$UPDATE_IMAGE_V3" >"$run_log_v3" 2>&1 || die "reboot v3 run: m33mu failed" +grep -q "\\[EXPECT BKPT\\] Success" "$run_log_v3" || die "reboot v3 run: expected BKPT 0x4B" +log "Scenario C: reboot v3: BKPT 0x4B hit" + +log "Scenario C: reboot after fallback (expect v1)" +run_log_fallback="$EMU_PATH/reboot_fallback_v1.log" +set +e +$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ + --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 \ + "$FACTORY_IMAGE" >"$run_log_fallback" 2>&1 +fallback_rc=$? +set -e +grep -q "get_version=1" "$run_log_fallback" || die "fallback run: expected get_version=1" +if [[ $fallback_rc -ne 0 && $fallback_rc -ne 127 ]]; then + die "fallback run: m33mu exited with $fallback_rc" +fi +log "Scenario C: fallback ok (version=1)" + +log "ok: $TARGET emu tests passed" diff --git a/tools/test-update-server/server.c b/tools/test-update-server/server.c index 15c2eb700b..6ba617a7bc 100644 --- a/tools/test-update-server/server.c +++ b/tools/test-update-server/server.c @@ -129,7 +129,17 @@ int main(int argc, char** argv) struct stat st; union usb_ack ack; struct termios tty; - sigset(SIGALRM, alarm_handler); + { + struct sigaction sa; + sigset_t mask; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = alarm_handler; + sigemptyset(&sa.sa_mask); + (void)sigaction(SIGALRM, &sa, NULL); + sigemptyset(&mask); + sigaddset(&mask, SIGALRM); + (void)sigprocmask(SIG_UNBLOCK, &mask, NULL); + } if (argc != 2) { printf("Usage: %s firmware_filename\n", argv[0]); From 46055b36e5b2856601bf63dc4e9e4c6fba2e3d92 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Fri, 9 Jan 2026 19:28:00 +0100 Subject: [PATCH 02/12] Minor log message rewords in emu-test --- test-app/emu-test-apps/test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test-app/emu-test-apps/test.sh b/test-app/emu-test-apps/test.sh index 400197664f..1293140672 100755 --- a/test-app/emu-test-apps/test.sh +++ b/test-app/emu-test-apps/test.sh @@ -237,11 +237,11 @@ for i in 1 2; do log "Scenario B: reboot run $i: BKPT 0x4A hit" done -log "Scenario C: update to v3 then fallback (no wolfBoot_success)" +log "Scenario C: update from v1 to v3, then fallback (no wolfBoot_success is called)" reset_factory_image run_update_scenario "scenario_c_update" "$UPDATE_IMAGE_V3" 3 -log "Scenario C: reboot into v3 (expect BKPT 0x4B, no success call)" +log "Scenario C: first boot after update: reboot into v3 (expect BKPT 0x4B, no success call)" run_log_v3="$EMU_PATH/reboot_v3.log" $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 --expect-bkpt=0x4b \ @@ -249,7 +249,7 @@ $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ grep -q "\\[EXPECT BKPT\\] Success" "$run_log_v3" || die "reboot v3 run: expected BKPT 0x4B" log "Scenario C: reboot v3: BKPT 0x4B hit" -log "Scenario C: reboot after fallback (expect v1)" +log "Scenario C: second reboot, expect v1 after fallback" run_log_fallback="$EMU_PATH/reboot_fallback_v1.log" set +e $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ From 385e13e4252696f4f9980cd1f19100a700bd6122 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 13:01:09 +0100 Subject: [PATCH 03/12] Fix handling rollback when ARMORED=1 and FLASH_TOP --- hal/stm32_tz.c | 18 ++++++++++++------ src/update_flash.c | 47 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/hal/stm32_tz.c b/hal/stm32_tz.c index fd2d0c8c1d..d9dc1139eb 100644 --- a/hal/stm32_tz.c +++ b/hal/stm32_tz.c @@ -301,11 +301,18 @@ void hal_tz_sau_init(void) sau_init_region(0, WOLFBOOT_NSC_ADDRESS, WOLFBOOT_NSC_ADDRESS + WOLFBOOT_NSC_SIZE - 1, 1); - /* Secure: application flash area (first bank) */ - sau_init_region(1, WOLFBOOT_PARTITION_BOOT_ADDRESS, FLASH_BANK2_BASE - 1, 0); - - /* Secure: application flash area (second bank) */ - sau_init_region(2, WOLFBOOT_PARTITION_UPDATE_ADDRESS, FLASH_TOP, 0); + /* Non-secure flash alias (entire NS flash window) */ + sau_init_region(1, 0x08000000, FLASH_TOP, 0); + + /* Secure: update partition in secure alias (use matching FLASH_TOP base) */ + uint32_t flash_top_secure = FLASH_TOP; + if ((WOLFBOOT_PARTITION_UPDATE_ADDRESS & 0xFF000000u) != + (FLASH_TOP & 0xFF000000u)) { + flash_top_secure = + (WOLFBOOT_PARTITION_UPDATE_ADDRESS & 0xFF000000u) | + (FLASH_TOP & 0x00FFFFFFu); + } + sau_init_region(2, WOLFBOOT_PARTITION_UPDATE_ADDRESS, flash_top_secure, 1); /* Secure RAM regions in SRAM1/SRAM2 */ sau_init_region(3, 0x30000000, 0x3004FFFF, 1); @@ -435,4 +442,3 @@ int hal_trng_get_entropy(unsigned char *out, unsigned len) } #endif - diff --git a/src/update_flash.c b/src/update_flash.c index b51f400a97..e257dc846b 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -686,6 +686,11 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) int inverse = 0; #endif int fallback_image = 0; +#ifndef DISABLE_BACKUP + int rollback = 0; + int bootStateRet = -1; + uint8_t bootState = 0; +#endif #if defined(DISABLE_BACKUP) && defined(EXT_ENCRYPTED) uint8_t key[ENCRYPT_KEY_SIZE]; uint8_t nonce[ENCRYPT_NONCE_SIZE]; @@ -748,6 +753,13 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) cur_ver = wolfBoot_current_firmware_version(); upd_ver = wolfBoot_update_firmware_version(); +#ifndef DISABLE_BACKUP + bootStateRet = wolfBoot_get_partition_state(PART_BOOT, &bootState); + if ((bootStateRet == 0) && (bootState == IMG_STATE_TESTING) && + (fallback_allowed != 0) && (cur_ver >= upd_ver)) { + rollback = 1; + } +#endif wolfBoot_get_update_sector_flag(0, &flag); /* Check the first sector to detect interrupted update */ @@ -787,9 +799,9 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) cur_ver, upd_ver); #ifndef ALLOW_DOWNGRADE - if ( ((fallback_allowed==1) && - (~(uint32_t)fallback_allowed == 0xFFFFFFFE)) || - (cur_ver < upd_ver) ) { + if (fallback_allowed != 0) { + /* Fallback path skips redundant version checks. */ + } else if (cur_ver < upd_ver) { VERIFY_VERSION_ALLOWED(fallback_allowed); } else { wolfBoot_printf("Update version not allowed\n"); @@ -973,6 +985,19 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) /* start re-entrant final erase, return code is only for resumption in * wolfBoot_start */ wolfBoot_swap_and_final_erase(0); +#ifndef DISABLE_BACKUP + if (rollback) { + hal_flash_unlock(); +#ifdef EXT_FLASH + ext_flash_unlock(); +#endif + wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_SUCCESS); +#ifdef EXT_FLASH + ext_flash_lock(); +#endif + hal_flash_lock(); + } +#endif #else /* Mark boot partition as TESTING - this tells bootloader to fallback if update fails */ wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_TESTING); @@ -1201,13 +1226,27 @@ void RAMFUNCTION wolfBoot_start(void) #if !defined(DISABLE_BACKUP) && !defined(CUSTOM_PARTITION_TRAILER) /* resume the final erase in case the power failed before it finished */ resumedFinalErase = wolfBoot_swap_and_final_erase(1); - if (resumedFinalErase != 0) + if ((resumedFinalErase != 0) || + ((bootRet == 0) && (bootState == IMG_STATE_TESTING))) #endif { /* Check if the BOOT partition is still in TESTING, * to trigger fallback. */ if ((bootRet == 0) && (bootState == IMG_STATE_TESTING)) { + if (updateRet != 0) { + hal_flash_unlock(); +#ifdef EXT_FLASH + ext_flash_unlock(); +#endif + wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_UPDATING); +#ifdef EXT_FLASH + ext_flash_lock(); +#endif + hal_flash_lock(); + updateRet = 0; + updateState = IMG_STATE_UPDATING; + } wolfBoot_update(1); } From d9713d70b20a72af05f6149e8cdcd9b13e0ec2fc Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 14:52:32 +0100 Subject: [PATCH 04/12] [ARMORED] Improved redundancy of verification --- include/image.h | 245 ++++++++++++++++++++++++++------------------- src/image.c | 40 +++++++- src/update_flash.c | 10 +- 3 files changed, 187 insertions(+), 108 deletions(-) diff --git a/include/image.h b/include/image.h index 6aa56da3f0..3d42b71bc1 100644 --- a/include/image.h +++ b/include/image.h @@ -419,15 +419,27 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ + asm volatile("mvn r3, r2":::"r3"); \ + asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ + asm volatile("bne nope"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ + asm volatile("mvn r3, r2":::"r3"); \ + asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ + asm volatile("bne nope"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ + asm volatile("mvn r3, r2":::"r3"); \ + asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ + asm volatile("bne nope"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ + asm volatile("mvn r3, r2":::"r3"); \ + asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ + asm volatile("bne nope"); \ /* Confirm that the signature is OK */ \ wolfBoot_image_confirm_signature_ok(img); \ asm volatile("nope:"); \ @@ -460,15 +472,27 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( "ldr r2, [%0]\n" \ "cmp r2, #1\n" \ "bne 1f\n" \ + "mvn r3, r2\n" \ + "cmp r3, #0xFFFFFFFE\n" \ + "bne 1f\n" \ "ldr r2, [%0]\n" \ "cmp r2, #1\n" \ "bne 1f\n" \ + "mvn r3, r2\n" \ + "cmp r3, #0xFFFFFFFE\n" \ + "bne 1f\n" \ "ldr r2, [%0]\n" \ "cmp r2, #1\n" \ "bne 1f\n" \ + "mvn r3, r2\n" \ + "cmp r3, #0xFFFFFFFE\n" \ + "bne 1f\n" \ "ldr r2, [%0]\n" \ "cmp r2, #1\n" \ "bne 1f\n" \ + "mvn r3, r2\n" \ + "cmp r3, #0xFFFFFFFE\n" \ + "bne 1f\n" \ /* Load 'img' into r0 (first argument to the function) */ \ "mov r0, %1\n" \ /* Load the function pointer into r3 */ \ @@ -480,7 +504,7 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( "2:\n" \ : /* No output operands */ \ : "r"(p_res), "r"(img), "r"(confirm_func) /* Input operands */ \ - : "r0", "r2", "lr" /* Clobbered registers */ \ + : "r0", "r2", "r3", "lr" /* Clobbered registers */ \ ); \ } while (0) #endif @@ -507,93 +531,94 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( #if defined(__GNUC__) #define VERIFY_VERSION_ALLOWED(fb_ok) \ - /* Stash the registry values */ \ - asm volatile("push {r4, r5, r6, r7}"); \ - /* Redundant initialization with 'failure' values */ \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r4, #1":::"r4"); \ - asm volatile("mov r5, #0":::"r5"); \ - asm volatile("mov r6, #2":::"r6"); \ - asm volatile("mov r7, #0":::"r7"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r4, #1":::"r4"); \ - asm volatile("mov r5, #0":::"r5"); \ - asm volatile("mov r6, #2":::"r6"); \ - asm volatile("mov r7, #0":::"r7"); \ - /* Read the fb_ok flag, jump to end_check \ - * if proven fb_ok == 1 */ \ - asm volatile("mov r0, %0" ::"r"(fb_ok):"r0"); \ - asm volatile("cmp r0, #1":::"cc"); \ - asm volatile("bne do_check"); \ - asm volatile("cmp r0, #1":::"cc"); \ - asm volatile("bne do_check"); \ - asm volatile("cmp r0, #1":::"cc"); \ - asm volatile("bne do_check"); \ - asm volatile("b end_check"); \ - /* Do the actual version check: */ \ - asm volatile("do_check:"); \ - /* Read update versions to reg r5 and r7 */ \ - asm volatile("mov r0, #1":::"r0"); \ - asm volatile("mov r0, #1":::"r0"); \ - asm volatile("mov r0, #1":::"r0"); \ - asm volatile("bl wolfBoot_get_image_version"); \ - asm volatile("mov r5, r0":::"r5"); \ - asm volatile("mov r5, r0":::"r5"); \ - asm volatile("mov r5, r0":::"r5"); \ - asm volatile("mov r0, #1":::"r0"); \ - asm volatile("mov r0, #1":::"r0"); \ - asm volatile("mov r0, #1":::"r0"); \ - asm volatile("bl wolfBoot_get_image_version"); \ - asm volatile("mov r7, r0":::"r7"); \ - asm volatile("mov r7, r0":::"r7"); \ - asm volatile("mov r7, r0":::"r7"); \ - /* Compare r5 and r7, if not equal, something went very wrong, */ \ - asm volatile("cmp r5, r7":::"cc"); \ - asm volatile("bne ."); \ - asm volatile("cmp r5, r7":::"cc"); \ - asm volatile("bne .-4"); \ - asm volatile("cmp r5, r7":::"cc"); \ - asm volatile("bne .-8"); \ - asm volatile("cmp r5, r7":::"cc"); \ - asm volatile("bne .-12"); \ - /* Read current versions to reg r4 and r6 */ \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("bl wolfBoot_get_image_version"); \ - asm volatile("mov r4, r0":::"r4"); \ - asm volatile("mov r4, r0":::"r4"); \ - asm volatile("mov r4, r0":::"r4"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("bl wolfBoot_get_image_version"); \ - asm volatile("mov r6, r0":::"r6"); \ - asm volatile("mov r6, r0":::"r6"); \ - asm volatile("mov r6, r0":::"r6"); \ - asm volatile("cmp r4, r6":::"cc"); \ - asm volatile("bne ."); \ - asm volatile("cmp r4, r6":::"cc"); \ - asm volatile("bne .-4"); \ - asm volatile("cmp r4, r6":::"cc"); \ - asm volatile("bne .-8"); \ - asm volatile("cmp r4, r6":::"cc"); \ - asm volatile("bne .-12"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r0, #0":::"r0"); \ - asm volatile("mov r0, #0":::"r0"); \ - /* Compare the two versions in registries */ \ - asm volatile("cmp r4, r5":::"cc"); \ - asm volatile("bge ."); \ - asm volatile("cmp r6, r7":::"cc"); \ - asm volatile("bge .-4"); \ - asm volatile("cmp r4, r5":::"cc"); \ - asm volatile("bge .-8"); \ - asm volatile("cmp r6, r7":::"cc"); \ - asm volatile("bge .-12"); \ - asm volatile("end_check:"); \ - /* Restore previously saved registry values */ \ - asm volatile("pop {r4, r5, r6, r7}":::"r4", "r5", "r6", "r7") + asm volatile( \ + "push {r4, r5, r6, r7}\n" \ + "mov r0, #0\n" \ + "mov r4, #1\n" \ + "mov r5, #0\n" \ + "mov r6, #2\n" \ + "mov r7, #0\n" \ + "mov r0, #0\n" \ + "mov r4, #1\n" \ + "mov r5, #0\n" \ + "mov r6, #2\n" \ + "mov r7, #0\n" \ + "mov r0, %0\n" \ + "mov r4, %0\n" \ + "cmp r0, #1\n" \ + "bne do_check\n" \ + "cmp r4, #1\n" \ + "bne do_check\n" \ + "cmp r0, r4\n" \ + "bne do_check\n" \ + "cmp r0, #1\n" \ + "bne do_check\n" \ + "b end_check\n" \ + "do_check:\n" \ + "mov r0, #1\n" \ + "mov r0, #1\n" \ + "mov r0, #1\n" \ + "bl wolfBoot_get_image_version\n" \ + "mov r5, r0\n" \ + "mov r5, r0\n" \ + "mov r5, r0\n" \ + "mov r0, #1\n" \ + "mov r0, #1\n" \ + "mov r0, #1\n" \ + "bl wolfBoot_get_image_version\n" \ + "mov r7, r0\n" \ + "mov r7, r0\n" \ + "mov r7, r0\n" \ + "cmp r5, r7\n" \ + "bne ver_panic\n" \ + "cmp r5, r7\n" \ + "bne ver_panic\n" \ + "cmp r5, r7\n" \ + "bne ver_panic\n" \ + "cmp r5, r7\n" \ + "bne ver_panic\n" \ + "mov r0, #0\n" \ + "mov r0, #0\n" \ + "mov r0, #0\n" \ + "bl wolfBoot_get_image_version\n" \ + "mov r4, r0\n" \ + "mov r4, r0\n" \ + "mov r4, r0\n" \ + "mov r0, #0\n" \ + "mov r0, #0\n" \ + "mov r0, #0\n" \ + "bl wolfBoot_get_image_version\n" \ + "mov r6, r0\n" \ + "mov r6, r0\n" \ + "mov r6, r0\n" \ + "cmp r4, r6\n" \ + "bne ver_panic\n" \ + "cmp r4, r6\n" \ + "bne ver_panic\n" \ + "cmp r4, r6\n" \ + "bne ver_panic\n" \ + "cmp r4, r6\n" \ + "bne ver_panic\n" \ + "mov r0, #0\n" \ + "mov r0, #0\n" \ + "mov r0, #0\n" \ + "cmp r4, r5\n" \ + "bhs ver_panic\n" \ + "cmp r6, r7\n" \ + "bhs ver_panic\n" \ + "cmp r4, r5\n" \ + "bhs ver_panic\n" \ + "cmp r6, r7\n" \ + "bhs ver_panic\n" \ + "b end_check\n" \ + "ver_panic:\n" \ + "b .\n" \ + "end_check:\n" \ + "pop {r4, r5, r6, r7}\n" \ + : \ + : "r"(fb_ok) \ + : "r0", "r4", "r5", "r6", "r7", "lr", "cc", "memory" \ + ) #elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__) @@ -612,10 +637,25 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( "mov r6, #2\n" \ "mov r7, #0\n" \ "mov r0, %0\n" \ + "mov r4, %0\n" \ + "cmp r0, #0\n" \ + "beq 4f\n" \ "cmp r0, #1\n" \ - "bne 1f\n" \ + "beq 4f\n" \ + "bkpt 0xE1\n" \ + "4:\n" \ + "cmp r4, #0\n" \ + "beq 5f\n" \ + "cmp r4, #1\n" \ + "beq 5f\n" \ + "bkpt 0xE1\n" \ + "5:\n" \ "cmp r0, #1\n" \ "bne 1f\n" \ + "cmp r4, #1\n" \ + "bne 1f\n" \ + "cmp r0, r4\n" \ + "bne 1f\n" \ "cmp r0, #1\n" \ "bne 1f\n" \ "b 2f\n" \ @@ -635,13 +675,13 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( "mov r7, r0\n" \ "mov r7, r0\n" \ "cmp r5, r7\n" \ - "bne .\n" \ + "bne 3f\n" \ "cmp r5, r7\n" \ - "bne .-4\n" \ + "bne 3f\n" \ "cmp r5, r7\n" \ - "bne .-8\n" \ + "bne 3f\n" \ "cmp r5, r7\n" \ - "bne .-12\n" \ + "bne 3f\n" \ "mov r0, #0\n" \ "mov r0, #0\n" \ "mov r0, #0\n" \ @@ -657,24 +697,27 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( "mov r6, r0\n" \ "mov r6, r0\n" \ "cmp r4, r6\n" \ - "bne .\n" \ + "bne 3f\n" \ "cmp r4, r6\n" \ - "bne .-4\n" \ + "bne 3f\n" \ "cmp r4, r6\n" \ - "bne .-8\n" \ + "bne 3f\n" \ "cmp r4, r6\n" \ - "bne .-12\n" \ + "bne 3f\n" \ "mov r0, #0\n" \ "mov r0, #0\n" \ "mov r0, #0\n" \ "cmp r4, r5\n" \ - "bge .\n" \ + "bhs 3f\n" \ "cmp r6, r7\n" \ - "bge .-4\n" \ + "bhs 3f\n" \ "cmp r4, r5\n" \ - "bge .-8\n" \ + "bhs 3f\n" \ "cmp r6, r7\n" \ - "bge .-12\n" \ + "bhs 3f\n" \ + "b 2f\n" \ + "3:\n" \ + "b .\n" \ "2:\n" \ "pop {r4, r5, r6, r7}\n" \ : /* No output operands */ \ diff --git a/src/image.c b/src/image.c index a3ce62cfc0..55a9dcfb9b 100644 --- a/src/image.c +++ b/src/image.c @@ -803,6 +803,26 @@ static void wolfBoot_verify_signature_ml_dsa(uint8_t key_slot, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res); + #ifdef WOLFBOOT_ARMORED + if (ret == 0) { + uint32_t v = (uint32_t)verify_res; + uint32_t v_inv = ~v; + if ((v == 1U) && (v_inv == 0xFFFFFFFEU) && + (v == (uint32_t)verify_res) && + (v_inv == ~(uint32_t)verify_res)) { + wolfBoot_printf("info: wc_MlDsaKey_Verify returned OK\n"); + wolfBoot_image_confirm_signature_ok(img); + } + else { + wolfBoot_printf("error: wc_MlDsaKey_Verify returned: ret=%d, " + "res=%d\n", ret, verify_res); + } + } + else { + wolfBoot_printf("error: wc_MlDsaKey_Verify returned: ret=%d, " + "res=%d\n", ret, verify_res); + } + #else if (ret == 0 && verify_res == 1) { wolfBoot_printf("info: wc_MlDsaKey_Verify returned OK\n"); wolfBoot_image_confirm_signature_ok(img); @@ -811,6 +831,7 @@ static void wolfBoot_verify_signature_ml_dsa(uint8_t key_slot, wolfBoot_printf("error: wc_MlDsaKey_Verify returned: ret=%d, " "res=%d\n", ret, verify_res); } + #endif } wc_MlDsaKey_Free(&ml_dsa); @@ -2150,8 +2171,15 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) wolfBoot_verify_signature_primary(key_slot, img, stored_signature); (void)stored_signature_size; +#ifdef WOLFBOOT_ARMORED +#define SIG_OK(imgp) (((imgp)->signature_ok == 1) && \ + ((imgp)->not_signature_ok == ~(uint32_t)1)) +#else +#define SIG_OK(imgp) ((imgp)->signature_ok == 1) +#endif + #ifdef SIGN_HYBRID - if (img->signature_ok == 1) { + if (SIG_OK(img)) { uint8_t *stored_secondary_signature; uint16_t stored_secondary_signature_size; /* Invalidate the signature_ok flag */ @@ -2177,10 +2205,18 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) } } #endif - if (img->signature_ok == 1) { +#ifdef WOLFBOOT_ARMORED + if (SIG_OK(img)) { return 0; } return -2; +#else + if (SIG_OK(img)) { + return 0; + } + return -2; +#endif +#undef SIG_OK } #endif diff --git a/src/update_flash.c b/src/update_flash.c index e257dc846b..726281a077 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -799,11 +799,11 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) cur_ver, upd_ver); #ifndef ALLOW_DOWNGRADE - if (fallback_allowed != 0) { - /* Fallback path skips redundant version checks. */ - } else if (cur_ver < upd_ver) { - VERIFY_VERSION_ALLOWED(fallback_allowed); - } else { + { + uint32_t fb_ok = (fallback_allowed == 1); + VERIFY_VERSION_ALLOWED(fb_ok); + } + if ((fallback_allowed == 0) && (cur_ver >= upd_ver)) { wolfBoot_printf("Update version not allowed\n"); return -1; } From afa4b729a948bc421285e69c04529f974b854bc8 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 13:03:08 +0100 Subject: [PATCH 05/12] Fixed test to work in trustzone --- .gitignore | 1 + test-app/emu-test-apps/common/emu_hal.c | 4 + test-app/emu-test-apps/common/emu_update.c | 38 ++ test-app/emu-test-apps/mcxw71/Makefile | 10 +- test-app/emu-test-apps/mcxw71/target.h | 12 - test-app/emu-test-apps/mcxw71/target.ld.in | 64 +++ test-app/emu-test-apps/nrf5340/Makefile | 10 +- test-app/emu-test-apps/nrf5340/target.h | 12 - test-app/emu-test-apps/nrf5340/target.ld.in | 69 +++ test-app/emu-test-apps/stm32h563/Makefile | 10 +- test-app/emu-test-apps/stm32h563/target.h | 13 - test-app/emu-test-apps/stm32h563/target.ld | 80 ++- test-app/emu-test-apps/stm32h563/target.ld.in | 64 +++ test-app/emu-test-apps/stm32l552/Makefile | 10 +- test-app/emu-test-apps/stm32l552/target.h | 13 - test-app/emu-test-apps/stm32l552/target.ld.in | 64 +++ test-app/emu-test-apps/stm32u585/Makefile | 10 +- test-app/emu-test-apps/stm32u585/target.h | 13 - test-app/emu-test-apps/stm32u585/target.ld.in | 64 +++ test-app/emu-test-apps/test.sh | 462 +++++++++++++----- 20 files changed, 782 insertions(+), 241 deletions(-) delete mode 100644 test-app/emu-test-apps/mcxw71/target.h create mode 100644 test-app/emu-test-apps/mcxw71/target.ld.in delete mode 100644 test-app/emu-test-apps/nrf5340/target.h create mode 100644 test-app/emu-test-apps/nrf5340/target.ld.in delete mode 100644 test-app/emu-test-apps/stm32h563/target.h create mode 100644 test-app/emu-test-apps/stm32h563/target.ld.in delete mode 100644 test-app/emu-test-apps/stm32l552/target.h create mode 100644 test-app/emu-test-apps/stm32l552/target.ld.in delete mode 100644 test-app/emu-test-apps/stm32u585/target.h create mode 100644 test-app/emu-test-apps/stm32u585/target.ld.in diff --git a/.gitignore b/.gitignore index 06b9a225b2..42556e40b6 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ *.idb *.pdb *.gdb +*.log # automatically generated keys *.der diff --git a/test-app/emu-test-apps/common/emu_hal.c b/test-app/emu-test-apps/common/emu_hal.c index 64249b1563..b3a3b58276 100644 --- a/test-app/emu-test-apps/common/emu_hal.c +++ b/test-app/emu-test-apps/common/emu_hal.c @@ -3,6 +3,10 @@ #include "target.h" #include "hal.h" +#ifndef EMU_FLASH_SECTOR_SIZE +#define EMU_FLASH_SECTOR_SIZE WOLFBOOT_SECTOR_SIZE +#endif + #if defined(EMU_STM32) #define FLASH_BASE 0x40022000u #define FLASH_NSKEYR (*(volatile uint32_t *)(FLASH_BASE + 0x004u)) diff --git a/test-app/emu-test-apps/common/emu_update.c b/test-app/emu-test-apps/common/emu_update.c index fd790e72a0..5cc59b367a 100644 --- a/test-app/emu-test-apps/common/emu_update.c +++ b/test-app/emu-test-apps/common/emu_update.c @@ -88,10 +88,14 @@ static uint32_t emu_current_version(void) { uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS; +#ifdef WOLFCRYPT_SECURE_MODE + return wolfBoot_nsc_current_firmware_version(); +#else if (addr == 0u) { return emu_get_blob_version_addr(0u); } return wolfBoot_get_blob_version((uint8_t *)addr); +#endif } void emu_uart_putc(char c) @@ -153,7 +157,9 @@ static void wait_for_update(uint32_t version) memset(page, 0xFF, PAGESIZE); +#ifndef WOLFCRYPT_SECURE_MODE hal_flash_unlock(); +#endif emu_uart_write(START); for (i = 3; i >= 0; i--) { @@ -209,23 +215,47 @@ static void wait_for_update(uint32_t version) page_idx += psize; if ((page_idx == PAGESIZE) || (next_seq + (uint32_t)psize >= tot_len)) { uint32_t dst = (WOLFBOOT_PARTITION_UPDATE_ADDRESS + recv_seq + (uint32_t)psize) - (uint32_t)page_idx; + uint32_t dst_off = (recv_seq + (uint32_t)psize) - (uint32_t)page_idx; +#ifdef WOLFCRYPT_SECURE_MODE + if ((dst_off % WOLFBOOT_SECTOR_SIZE) == 0u) { + wolfBoot_nsc_erase_update(dst_off, WOLFBOOT_SECTOR_SIZE); + } + wolfBoot_nsc_write_update(dst_off, page, PAGESIZE); +#else if ((dst % WOLFBOOT_SECTOR_SIZE) == 0u) { hal_flash_erase(dst, WOLFBOOT_SECTOR_SIZE); } hal_flash_write(dst, page, PAGESIZE); +#endif memset(page, 0xFF, PAGESIZE); } next_seq += (uint32_t)psize; } ack(next_seq); if (next_seq >= tot_len) { + uint32_t update_ver; +#ifdef WOLFCRYPT_SECURE_MODE + update_ver = wolfBoot_nsc_update_firmware_version(); +#else + update_ver = wolfBoot_get_blob_version((uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS); +#endif + if (update_ver == 7u) { + __asm volatile("bkpt #0x4D"); + break; + } +#ifdef WOLFCRYPT_SECURE_MODE + wolfBoot_nsc_update_trigger(); +#else wolfBoot_update_trigger(); +#endif __asm volatile("bkpt #0x47"); break; } } +#ifndef WOLFCRYPT_SECURE_MODE hal_flash_lock(); +#endif while (1) { __asm volatile("wfi"); @@ -242,7 +272,11 @@ int main(void) printf("get_version=%lu\n", (unsigned long)version); if (version == 4u) { +#ifdef WOLFCRYPT_SECURE_MODE + wolfBoot_nsc_success(); +#else wolfBoot_success(); +#endif __asm volatile("bkpt #0x4A"); while (1) { __asm volatile("wfi"); @@ -255,7 +289,11 @@ int main(void) } } if (version == 8u) { +#ifdef WOLFCRYPT_SECURE_MODE + wolfBoot_nsc_success(); +#else wolfBoot_success(); +#endif __asm volatile("bkpt #0x4E"); while (1) { __asm volatile("wfi"); diff --git a/test-app/emu-test-apps/mcxw71/Makefile b/test-app/emu-test-apps/mcxw71/Makefile index 4bb98e7970..9644beb281 100644 --- a/test-app/emu-test-apps/mcxw71/Makefile +++ b/test-app/emu-test-apps/mcxw71/Makefile @@ -4,18 +4,24 @@ OBJCOPY ?= arm-none-eabi-objcopy CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb MCXW71_SDK ?= ../../../../MCXW71 CFLAGS += -I. -I../common -I../../../include +CFLAGS += -DIMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE) CFLAGS += -DCPU_MCXW716CMFPA CFLAGS += -I$(MCXW71_SDK)/devices/MCXW716C -I$(MCXW71_SDK)/devices/MCXW716C/periph2 CFLAGS += -I$(MCXW71_SDK)/CMSIS/Core/Include LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group +NSC_OBJ := +ifeq ($(TZEN),1) + CFLAGS += -DWOLFCRYPT_SECURE_MODE + NSC_OBJ := ../../../src/wc_secure_calls.o +endif VPATH := ../common COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c SRCS := $(COMMON_SRCS) uart.c -OBJS := $(SRCS:.c=.o) libwolfboot.o +OBJS := $(SRCS:.c=.o) libwolfboot.o $(NSC_OBJ) all: app.bin @@ -32,6 +38,6 @@ libwolfboot.o: $(LIBWOLFBOOT_SRC) $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(OBJS) app.elf app.bin + rm -f $(SRCS:.c=.o) libwolfboot.o app.elf app.bin .PHONY: all clean diff --git a/test-app/emu-test-apps/mcxw71/target.h b/test-app/emu-test-apps/mcxw71/target.h deleted file mode 100644 index 965b03f8f7..0000000000 --- a/test-app/emu-test-apps/mcxw71/target.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef H_TARGETS_TARGET_ -#define H_TARGETS_TARGET_ - -#define WOLFBOOT_FIXED_PARTITIONS - -#define WOLFBOOT_SECTOR_SIZE 0x1000u -#define WOLFBOOT_PARTITION_SIZE 0x00020000u -#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x00000000u -#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x00020000u -#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x00040000u - -#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/mcxw71/target.ld.in b/test-app/emu-test-apps/mcxw71/target.ld.in new file mode 100644 index 0000000000..edc05193f6 --- /dev/null +++ b/test-app/emu-test-apps/mcxw71/target.ld.in @@ -0,0 +1,64 @@ +/* Minimal linker script for MCXW716C memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000FFF00 + RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x0001C000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/nrf5340/Makefile b/test-app/emu-test-apps/nrf5340/Makefile index 1b7a1074e4..23bd250fdd 100644 --- a/test-app/emu-test-apps/nrf5340/Makefile +++ b/test-app/emu-test-apps/nrf5340/Makefile @@ -3,15 +3,21 @@ OBJCOPY ?= arm-none-eabi-objcopy CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb CFLAGS += -I. -I../common -I../../../include -DEMU_NRF5340 +CFLAGS += -DIMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE) LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group +NSC_OBJ := +ifeq ($(TZEN),1) + CFLAGS += -DWOLFCRYPT_SECURE_MODE + NSC_OBJ := ../../../src/wc_secure_calls.o +endif VPATH := ../common COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c SRCS := $(COMMON_SRCS) uart.c -OBJS := $(SRCS:.c=.o) libwolfboot.o +OBJS := $(SRCS:.c=.o) libwolfboot.o $(NSC_OBJ) all: app.bin @@ -28,6 +34,6 @@ libwolfboot.o: $(LIBWOLFBOOT_SRC) $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(OBJS) app.elf app.bin + rm -f $(SRCS:.c=.o) libwolfboot.o app.elf app.bin .PHONY: all clean diff --git a/test-app/emu-test-apps/nrf5340/target.h b/test-app/emu-test-apps/nrf5340/target.h deleted file mode 100644 index 965b03f8f7..0000000000 --- a/test-app/emu-test-apps/nrf5340/target.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef H_TARGETS_TARGET_ -#define H_TARGETS_TARGET_ - -#define WOLFBOOT_FIXED_PARTITIONS - -#define WOLFBOOT_SECTOR_SIZE 0x1000u -#define WOLFBOOT_PARTITION_SIZE 0x00020000u -#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x00000000u -#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x00020000u -#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x00040000u - -#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/nrf5340/target.ld.in b/test-app/emu-test-apps/nrf5340/target.ld.in new file mode 100644 index 0000000000..62c25bfe90 --- /dev/null +++ b/test-app/emu-test-apps/nrf5340/target.ld.in @@ -0,0 +1,69 @@ +/* Minimal linker script for nRF5340 (application core) memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000FFF00 + RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x00080000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM + + .testpage ORIGIN(FLASH) + LENGTH(FLASH) - 0x1000 : + { + KEEP(*(.testpage*)) + } > FLASH +} diff --git a/test-app/emu-test-apps/stm32h563/Makefile b/test-app/emu-test-apps/stm32h563/Makefile index 5cd0ca9c0b..838979fb09 100644 --- a/test-app/emu-test-apps/stm32h563/Makefile +++ b/test-app/emu-test-apps/stm32h563/Makefile @@ -3,15 +3,21 @@ OBJCOPY ?= arm-none-eabi-objcopy CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb CFLAGS += -I. -I../common -I../../../include -DEMU_STM32 +CFLAGS += -DIMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE) LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group +NSC_OBJ := +ifeq ($(TZEN),1) + CFLAGS += -DWOLFCRYPT_SECURE_MODE + NSC_OBJ := ../../../src/wc_secure_calls.o +endif VPATH := ../common COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c SRCS := $(COMMON_SRCS) uart.c -OBJS := $(SRCS:.c=.o) libwolfboot.o +OBJS := $(SRCS:.c=.o) libwolfboot.o $(NSC_OBJ) all: app.bin @@ -28,6 +34,6 @@ libwolfboot.o: $(LIBWOLFBOOT_SRC) $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(OBJS) app.elf app.bin + rm -f $(SRCS:.c=.o) libwolfboot.o app.elf app.bin .PHONY: all clean diff --git a/test-app/emu-test-apps/stm32h563/target.h b/test-app/emu-test-apps/stm32h563/target.h deleted file mode 100644 index 5da0027169..0000000000 --- a/test-app/emu-test-apps/stm32h563/target.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef H_TARGETS_TARGET_ -#define H_TARGETS_TARGET_ - -#define WOLFBOOT_FIXED_PARTITIONS - -#define WOLFBOOT_SECTOR_SIZE 0x1000u -#define EMU_FLASH_SECTOR_SIZE 0x4000u -#define WOLFBOOT_PARTITION_SIZE 0x00020000u -#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08000000u -#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08020000u -#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08040000u - -#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/stm32h563/target.ld b/test-app/emu-test-apps/stm32h563/target.ld index 1aa5595856..a4afef0ad1 100644 --- a/test-app/emu-test-apps/stm32h563/target.ld +++ b/test-app/emu-test-apps/stm32h563/target.ld @@ -1,64 +1,62 @@ -/* Minimal linker script for STM32H563 memory map */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000100, LENGTH = 0x001FFF00 - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x000A0000 + FLASH (rx) : ORIGIN = 0x8060400, LENGTH = 0x9fc00 + RAM (rwx) : ORIGIN = 0x20050000, LENGTH = 0x40000 } -_estack = ORIGIN(RAM) + LENGTH(RAM); -_sidata = LOADADDR(.data); - SECTIONS { - .isr_vector : - { - KEEP(*(.isr_vector)) - } > FLASH - .text : { + _start_text = .; + . = ALIGN(8); + KEEP(*(.isr_vector)) + . = ALIGN(8); + *(.init) + *(.fini) *(.text*) *(.rodata*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - *(.glue_7) - *(.glue_7t) - *(.eh_frame) + . = ALIGN(8); + _end_text = .; } > FLASH - .preinit_array : + .edidx : { - __preinit_array_start = .; - KEEP(*(.preinit_array*)) - __preinit_array_end = .; + . = ALIGN(4); + *(.ARM.exidx*) } > FLASH - .init_array : - { - __init_array_start = .; - KEEP(*(.init_array*)) - __init_array_end = .; - } > FLASH - - .fini_array : - { - __fini_array_start = .; - KEEP(*(.fini_array*)) - __fini_array_end = .; - } > FLASH + _stored_data = .; - .data : + .data : AT (_stored_data) { - _sdata = .; - *(.data*) - _edata = .; - } > RAM AT > FLASH + _start_data = .; + KEEP(*(.data*)) + . = ALIGN(8); + KEEP(*(.ramcode)) + . = ALIGN(8); + _end_data = .; + } > RAM - .bss (NOLOAD) : + .bss : { - _sbss = .; + _start_bss = .; *(.bss*) *(COMMON) - _ebss = .; + . = ALIGN(8); + _end_bss = .; + _end = .; } > RAM } + +PROVIDE(_start_heap = _end); +PROVIDE(_heap_size = 4K); +PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM)); + +/* Emu app startup expects these symbols. */ +_estack = _end_stack; +_sidata = _stored_data; +_sdata = _start_data; +_edata = _end_data; +_sbss = _start_bss; +_ebss = _end_bss; diff --git a/test-app/emu-test-apps/stm32h563/target.ld.in b/test-app/emu-test-apps/stm32h563/target.ld.in new file mode 100644 index 0000000000..c20e2ce966 --- /dev/null +++ b/test-app/emu-test-apps/stm32h563/target.ld.in @@ -0,0 +1,64 @@ +/* Minimal linker script for STM32H563 memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x001FFF00 + RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000A0000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/stm32l552/Makefile b/test-app/emu-test-apps/stm32l552/Makefile index 5cd0ca9c0b..838979fb09 100644 --- a/test-app/emu-test-apps/stm32l552/Makefile +++ b/test-app/emu-test-apps/stm32l552/Makefile @@ -3,15 +3,21 @@ OBJCOPY ?= arm-none-eabi-objcopy CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb CFLAGS += -I. -I../common -I../../../include -DEMU_STM32 +CFLAGS += -DIMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE) LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group +NSC_OBJ := +ifeq ($(TZEN),1) + CFLAGS += -DWOLFCRYPT_SECURE_MODE + NSC_OBJ := ../../../src/wc_secure_calls.o +endif VPATH := ../common COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c SRCS := $(COMMON_SRCS) uart.c -OBJS := $(SRCS:.c=.o) libwolfboot.o +OBJS := $(SRCS:.c=.o) libwolfboot.o $(NSC_OBJ) all: app.bin @@ -28,6 +34,6 @@ libwolfboot.o: $(LIBWOLFBOOT_SRC) $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(OBJS) app.elf app.bin + rm -f $(SRCS:.c=.o) libwolfboot.o app.elf app.bin .PHONY: all clean diff --git a/test-app/emu-test-apps/stm32l552/target.h b/test-app/emu-test-apps/stm32l552/target.h deleted file mode 100644 index 83cb4647fe..0000000000 --- a/test-app/emu-test-apps/stm32l552/target.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef H_TARGETS_TARGET_ -#define H_TARGETS_TARGET_ - -#define WOLFBOOT_FIXED_PARTITIONS - -#define WOLFBOOT_SECTOR_SIZE 0x1000u -#define EMU_FLASH_SECTOR_SIZE 0x1000u -#define WOLFBOOT_PARTITION_SIZE 0x00020000u -#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08000000u -#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08020000u -#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08040000u - -#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/stm32l552/target.ld.in b/test-app/emu-test-apps/stm32l552/target.ld.in new file mode 100644 index 0000000000..4d4aa48b6e --- /dev/null +++ b/test-app/emu-test-apps/stm32l552/target.ld.in @@ -0,0 +1,64 @@ +/* Minimal linker script for STM32L552 memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x0007FF00 + RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x00040000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/stm32u585/Makefile b/test-app/emu-test-apps/stm32u585/Makefile index 5cd0ca9c0b..838979fb09 100644 --- a/test-app/emu-test-apps/stm32u585/Makefile +++ b/test-app/emu-test-apps/stm32u585/Makefile @@ -3,15 +3,21 @@ OBJCOPY ?= arm-none-eabi-objcopy CFLAGS := -mcpu=cortex-m33 -mthumb -mcmse -Os -ffreestanding -fdata-sections -ffunction-sections -g -ggdb CFLAGS += -I. -I../common -I../../../include -DEMU_STM32 +CFLAGS += -DIMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE) LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections LDLIBS := -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group +NSC_OBJ := +ifeq ($(TZEN),1) + CFLAGS += -DWOLFCRYPT_SECURE_MODE + NSC_OBJ := ../../../src/wc_secure_calls.o +endif VPATH := ../common COMMON_SRCS := emu_ivt.c emu_startup.c emu_syscalls.c emu_update.c emu_hal.c LIBWOLFBOOT_SRC := ../../../src/libwolfboot.c SRCS := $(COMMON_SRCS) uart.c -OBJS := $(SRCS:.c=.o) libwolfboot.o +OBJS := $(SRCS:.c=.o) libwolfboot.o $(NSC_OBJ) all: app.bin @@ -28,6 +34,6 @@ libwolfboot.o: $(LIBWOLFBOOT_SRC) $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(OBJS) app.elf app.bin + rm -f $(SRCS:.c=.o) libwolfboot.o app.elf app.bin .PHONY: all clean diff --git a/test-app/emu-test-apps/stm32u585/target.h b/test-app/emu-test-apps/stm32u585/target.h deleted file mode 100644 index 5da0027169..0000000000 --- a/test-app/emu-test-apps/stm32u585/target.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef H_TARGETS_TARGET_ -#define H_TARGETS_TARGET_ - -#define WOLFBOOT_FIXED_PARTITIONS - -#define WOLFBOOT_SECTOR_SIZE 0x1000u -#define EMU_FLASH_SECTOR_SIZE 0x4000u -#define WOLFBOOT_PARTITION_SIZE 0x00020000u -#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08000000u -#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08020000u -#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08040000u - -#endif /* H_TARGETS_TARGET_ */ diff --git a/test-app/emu-test-apps/stm32u585/target.ld.in b/test-app/emu-test-apps/stm32u585/target.ld.in new file mode 100644 index 0000000000..6097ac1baa --- /dev/null +++ b/test-app/emu-test-apps/stm32u585/target.ld.in @@ -0,0 +1,64 @@ +/* Minimal linker script for STM32U585 memory map */ +MEMORY +{ + FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x001FFF00 + RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000C0000 +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +SECTIONS +{ + .isr_vector : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + _sdata = .; + *(.data*) + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + _sbss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > RAM +} diff --git a/test-app/emu-test-apps/test.sh b/test-app/emu-test-apps/test.sh index 1293140672..f1f10eed19 100755 --- a/test-app/emu-test-apps/test.sh +++ b/test-app/emu-test-apps/test.sh @@ -6,28 +6,35 @@ WOLFBOOT_ROOT="${WOLFBOOT_ROOT:-$(cd "$script_dir/../.." && pwd)}" EMU_APPS="$WOLFBOOT_ROOT/test-app/emu-test-apps" M33MU="${M33MU:-$(command -v m33mu || true)}" UPDATE_SERVER_SRC="$WOLFBOOT_ROOT/tools/test-update-server/server.c" +BIN_ASSEMBLE="$WOLFBOOT_ROOT/tools/bin-assemble/bin-assemble" + +log() { + echo "==> $*" +} die() { echo "error: $*" >&2 exit 1 } -log() { - echo "==> $*" -} - need_cmd() { command -v "$1" >/dev/null 2>&1 || die "missing required command: $1" } +cfg_get() { + local key="$1" + local val + val="$(grep -m1 -E "^${key}[?]*[:]*=" "$WOLFBOOT_ROOT/.config" 2>/dev/null | sed -E "s/^${key}[?]*[:]*=//" || true)" + echo "${val}" +} + if [[ -z "${TARGET:-}" && -f "$WOLFBOOT_ROOT/.config" ]]; then - TARGET="$(grep -m1 '^TARGET' "$WOLFBOOT_ROOT/.config" 2>/dev/null | sed -E 's/^TARGET[?]*=//' || true)" + TARGET="$(cfg_get TARGET)" fi TARGET="${TARGET:-}" -[[ -n "${TARGET}" ]] || die "TARGET not set (export TARGET=... or set in .config)" +[[ -n "$TARGET" ]] || die "TARGET not set (export TARGET=... or set in .config)" EMU_DIR="" -EMU_CPU="" UART_BASE="" get_m33mu_target() { @@ -40,14 +47,16 @@ get_m33mu_target() { *) echo "" ;; esac } + case "$TARGET" in stm32h563|stm32h5) EMU_DIR=stm32h563; UART_BASE=40004800 ;; stm32u585|stm32u5) EMU_DIR=stm32u585; UART_BASE=40004800 ;; stm32l552|stm32l5) EMU_DIR=stm32l552; UART_BASE=40004800 ;; - nrf5340) EMU_DIR=nrf5340; UART_BASE=40008000 ;; + nrf5340) EMU_DIR=nrf5340; UART_BASE=40008000 ;; mcxw|mcxw71) EMU_DIR=mcxw71; UART_BASE=40038000 ;; *) die "unsupported TARGET=$TARGET" ;; -esac + esac + EMU_CPU="$(get_m33mu_target "$TARGET")" [[ -n "$EMU_CPU" ]] || die "unsupported TARGET=$TARGET (no m33mu mapping)" @@ -56,211 +65,410 @@ need_cmd make need_cmd grep need_cmd python3 need_cmd gcc +need_cmd sed +need_cmd cut +need_cmd tac -EMU_IMAGE_HEADER_SIZE="${EMU_IMAGE_HEADER_SIZE:-256}" -IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" -WOLFBOOT_BIN="$WOLFBOOT_ROOT/wolfboot.bin" +IMAGE_HEADER_SIZE="$(cfg_get IMAGE_HEADER_SIZE)" +IMAGE_HEADER_SIZE="${IMAGE_HEADER_SIZE:-256}" +ARCH_OFFSET="$(cfg_get ARCH_OFFSET)" +ARCH_OFFSET="${ARCH_OFFSET:-0}" +BOOT_ADDR="$(cfg_get WOLFBOOT_PARTITION_BOOT_ADDRESS)" +UPDATE_ADDR="$(cfg_get WOLFBOOT_PARTITION_UPDATE_ADDRESS)" +PART_SIZE="$(cfg_get WOLFBOOT_PARTITION_SIZE)" +SECTOR_SIZE="$(cfg_get WOLFBOOT_SECTOR_SIZE)" +RAM_CODE="$(cfg_get RAM_CODE)" +TZEN="$(cfg_get TZEN)" -EMU_PATH="$EMU_APPS/$EMU_DIR" -FACTORY_IMAGE="$EMU_PATH/image_v1_signed.bin" -FACTORY_IMAGE_BASE="$EMU_PATH/image_v1_factory.bin" -UPDATE_IMAGE_V4="$EMU_PATH/image_v4_signed.bin" -UPDATE_IMAGE_V3="$EMU_PATH/image_v3_signed.bin" -UPDATE_IMAGE_V8="$EMU_PATH/image_v8_signed.bin" +[[ -n "$BOOT_ADDR" && -n "$UPDATE_ADDR" && -n "$PART_SIZE" && -n "$SECTOR_SIZE" ]] || \ + die "missing required config values (boot/update addr, partition/sector size)" + +# If ARCH_OFFSET is unset/0 but partitions are in 0x0800_0000 (STM32), use that +# as the base so bin-assemble offsets stay within the flash image. +if [[ "$ARCH_OFFSET" == "0" || "$ARCH_OFFSET" == "0x0" ]]; then + if (( BOOT_ADDR >= 0x08000000 )); then + ARCH_OFFSET=0x08000000 + fi +fi + +BOOT_OFFSET=$((BOOT_ADDR - ARCH_OFFSET)) +UPDATE_OFFSET=$((UPDATE_ADDR - ARCH_OFFSET)) +BOOT_OFFSET_HEX=$(printf "0x%x" "$BOOT_OFFSET") +UPDATE_OFFSET_HEX=$(printf "0x%x" "$UPDATE_OFFSET") + +M33MU_TZ_ARGS=(--no-tz) +if [[ "${TZEN}" == "1" ]]; then + M33MU_TZ_ARGS=() +fi STDBUF="" if command -v stdbuf >/dev/null 2>&1; then STDBUF="stdbuf -o0 -e0" fi -make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=1 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu -make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=3 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu -make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=4 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu -make -C "$EMU_APPS" TARGET="$TARGET" EMU_VERSION=8 IMAGE_HEADER_SIZE="$EMU_IMAGE_HEADER_SIZE" sign-emu +EMU_PATH="$EMU_APPS/$EMU_DIR" +WOLFBOOT_BIN="$WOLFBOOT_ROOT/wolfboot.bin" +FACTORY_FLASH="$EMU_PATH/factory.bin" UPDATE_SERVER_BIN="$EMU_PATH/test-update-server" -cp -f "$FACTORY_IMAGE" "$FACTORY_IMAGE_BASE" +UPDATE_IMAGE_V1="$EMU_PATH/image_v1_signed.bin" +UPDATE_IMAGE_V3="$EMU_PATH/image_v3_signed.bin" +UPDATE_IMAGE_V4="$EMU_PATH/image_v4_signed.bin" +UPDATE_IMAGE_V7="$EMU_PATH/image_v7_signed.bin" +UPDATE_IMAGE_V8="$EMU_PATH/image_v8_signed.bin" -reset_factory_image() { - cp -f "$FACTORY_IMAGE_BASE" "$FACTORY_IMAGE" -} +BOOT_TIMEOUT="${BOOT_TIMEOUT:-10}" +UPDATE_TIMEOUT="${UPDATE_TIMEOUT:-10}" +REBOOT_TIMEOUT="${REBOOT_TIMEOUT:-10}" -build_update_server() { - local uart_dev="$1" - gcc -Wall -g -ggdb -DUART_DEV="\"$uart_dev\"" -o "$UPDATE_SERVER_BIN" "$UPDATE_SERVER_SRC" -lpthread +write_target_ld() { + local tpl="" + local base="" + local addr + local size + addr=$((BOOT_ADDR + IMAGE_HEADER_SIZE)) + size=$((PART_SIZE - IMAGE_HEADER_SIZE)) + + case "$TARGET" in + stm32h563|stm32h5) base="ARM-stm32h5" ;; + stm32u585|stm32u5) base="ARM-stm32u5" ;; + stm32l552|stm32l5) base="ARM-stm32l5" ;; + nrf5340) base="ARM-nrf5340" ;; + mcxw|mcxw71) base="ARM-mcxw" ;; + *) die "unsupported TARGET for linker template: $TARGET" ;; + esac + + if [[ "${TZEN}" == "1" && -f "$WOLFBOOT_ROOT/test-app/${base}-ns.ld" ]]; then + tpl="$WOLFBOOT_ROOT/test-app/${base}-ns.ld" + else + tpl="$WOLFBOOT_ROOT/test-app/${base}.ld" + fi + + [[ -f "$tpl" ]] || die "missing linker template: $tpl" + + sed -e "s/@WOLFBOOT_TEST_APP_ADDRESS@/0x$(printf '%x' "$addr")/g" \ + -e "s/@WOLFBOOT_TEST_APP_SIZE@/0x$(printf '%x' "$size")/g" \ + "$tpl" > "$EMU_PATH/target.ld" + cat <<'SYM' >> "$EMU_PATH/target.ld" + +/* Emu app startup expects these symbols. */ +_estack = _end_stack; +_sidata = _stored_data; +_sdata = _start_data; +_edata = _end_data; +_sbss = _start_bss; +_ebss = _end_bss; +SYM } -log "Scenario A: factory boot" -reset_factory_image -factory_log="$EMU_PATH/factory.log" -log "factory run: boot image v1, expect UART get_version=1" -set +e -$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ - --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 --expect-bkpt=0x00 \ - "$FACTORY_IMAGE" >"$factory_log" 2>&1 -factory_rc=$? -set -e -grep -q "get_version=1" "$factory_log" || die "factory run: expected get_version=1" -if [[ $factory_rc -ne 0 && $factory_rc -ne 127 ]]; then - die "factory run: m33mu exited with $factory_rc" -fi -log "factory run: ok (version=1)" +check_pty_available() { + python3 - <<'PY' +import pty, os +m, s = pty.openpty() +os.close(m) +os.close(s) +PY +} wait_for_pts() { - local log="$1" + local log_file="$1" local base="$2" + local pid="$3" local pts="" local i - for i in $(seq 1 100); do - pts="$(grep "\\[UART\\] ${base} attached to" "$log" | tail -n1 | sed 's/.* //' || true)" + for i in $(seq 1 2000); do + pts="$(grep "\\[UART\\] ${base} attached to" "$log_file" | tail -n1 | sed 's/.* //' || true)" if [[ -n "$pts" ]]; then echo "$pts" return 0 fi + kill -0 "$pid" >/dev/null 2>&1 || break sleep 0.05 done return 1 } -check_update_version_in_image() { - local image="$1" - local expected="$2" - local target_h="$EMU_PATH/target.h" - local boot_addr - local update_addr - boot_addr="$(grep -m1 'WOLFBOOT_PARTITION_BOOT_ADDRESS' "$target_h" | sed 's/.*0x/0x/' | cut -d'u' -f1)" - update_addr="$(grep -m1 'WOLFBOOT_PARTITION_UPDATE_ADDRESS' "$target_h" | sed 's/.*0x/0x/' | cut -d'u' -f1)" - python3 - "$image" "$boot_addr" "$update_addr" "$IMAGE_HEADER_SIZE" "$expected" <<'PY' +build_update_server() { + local uart_dev="$1" + gcc -Wall -g -ggdb -DUART_DEV="\"$uart_dev\"" -o "$UPDATE_SERVER_BIN" \ + "$UPDATE_SERVER_SRC" -lpthread +} + +assemble_factory() { + log "Assembling factory.bin from wolfboot.bin + image_v1_signed.bin" + "$BIN_ASSEMBLE" "$FACTORY_FLASH" \ + 0 "$WOLFBOOT_BIN" \ + "$BOOT_OFFSET_HEX" "$UPDATE_IMAGE_V1" >/dev/null +} + +print_partition_flags() { + local label="$1" + python3 - "$FACTORY_FLASH" "$BOOT_ADDR" "$UPDATE_ADDR" "$PART_SIZE" "$SECTOR_SIZE" <<'PY' | sed "s/^/==> ${label}: /" +import sys +path, boot_s, update_s, size_s, sect_s = sys.argv[1:6] +boot = int(boot_s, 0) +update = int(update_s, 0) +size = int(size_s, 0) +sect = int(sect_s, 0) + +def decode(state): + if state is None: + return "MISSING" + if state == 0xFF: + return "NEW(0xFF)" + if state == 0x70: + return "UPDATING(0x70)" + if state == 0x10: + return "TESTING(0x10)" + if state == 0x00: + return "SUCCESS(0x00)" + return f"0x{state:02x}" + +def read_state(addr): + try: + with open(path, "rb") as f: + f.seek(addr + size - 4) + magic = f.read(4) + if magic != b"BOOT": + return None + f.seek(addr + size - 5) + b = f.read(1) + if not b: + return None + return b[0] + except Exception: + return None + +def read_state_alt(addr): + try: + with open(path, "rb") as f: + f.seek(addr + size - sect - 4) + magic = f.read(4) + if magic != b"BOOT": + return None + f.seek(addr + size - sect - 5) + b = f.read(1) + if not b: + return None + return b[0] + except Exception: + return None + +bs0 = read_state(boot) +bs1 = read_state_alt(boot) +us0 = read_state(update) +us1 = read_state_alt(update) +print(f"boot_flags=[S0:{decode(bs0)} S1:{decode(bs1)}] update_flags=[S0:{decode(us0)} S1:{decode(us1)}]") +PY +} + +print_partition_versions() { + local label="$1" + local boot_ver + local update_ver + boot_ver="$(python3 - "$FACTORY_FLASH" "$BOOT_OFFSET_HEX" "$IMAGE_HEADER_SIZE" <<'PY' import sys, struct -path, boot_s, update_s, hdr_s, expected_s = sys.argv[1:6] -boot = int(boot_s, 16) -update = int(update_s, 16) +path, off_s, hdr_s = sys.argv[1], sys.argv[2], sys.argv[3] +off = int(off_s, 16) hdr = int(hdr_s, 0) -expected = int(expected_s, 0) -off = update - boot data = open(path, "rb").read() if off + 8 > len(data): - print("0") - sys.exit(1) + print("NA") + sys.exit(0) magic, = struct.unpack_from(" (hdr - IMAGE_HEADER_OFFSET): + t = struct.unpack_from(" end: break - if p + 4 + length > max_p: + if t == 1: + ver = struct.unpack_from(" len(data): + print("NA") + sys.exit(0) +magic, = struct.unpack_from(" end: break - p += length -print(version) -sys.exit(0 if version == expected else 1) -PY -} - -check_pty_available() { - python3 - <<'PY' -import pty, os -m, s = pty.openpty() -os.close(m) -os.close(s) + if t == 1: + ver = struct.unpack_from(""$update_log" - check_pty_available || die "no PTY devices available (needed for ufserver)" -UPDATE_TIMEOUT="${UPDATE_TIMEOUT:-120}" - log "$label: start emulator (expect BKPT 0x47 when update is accepted)" - $STDBUF "$M33MU" --cpu "$EMU_CPU" --no-tz --persist \ - --boot-offset="$IMAGE_HEADER_SIZE" --timeout "$UPDATE_TIMEOUT" --expect-bkpt=0x47 \ - "$FACTORY_IMAGE" >"$update_log" 2>&1 & + check_pty_available || die "no PTY devices available (needed for test-update-server)" + print_partition_flags "$label: flags before" + log "$label: start emulator (expect BKPT $expected_bkpt when update completes)" + $STDBUF "$M33MU" --cpu "$EMU_CPU" "${M33MU_TZ_ARGS[@]}" --persist \ + --timeout "$UPDATE_TIMEOUT" --expect-bkpt="$expected_bkpt" --quit-on-faults \ + "$FACTORY_FLASH" >"$update_log" 2>&1 & emu_pid=$! - pts="$(wait_for_pts "$update_log" "$UART_BASE")" || die "$label: failed to detect UART PTY" + pts="$(wait_for_pts "$update_log" "$UART_BASE" "$emu_pid")" || { + tail -n 60 "$update_log" | sed 's/^/ | /' + die "$label: failed to detect UART PTY" + } log "$label: UART attached at $pts" build_update_server "$pts" - if [[ -n "$STDBUF" ]]; then - log "$label: transferring update image (v$expected_version) over UART" - $STDBUF "$UPDATE_SERVER_BIN" "$update_image" >"$server_log" 2>&1 & - else - log "$label: transferring update image (v$expected_version) over UART" - "$UPDATE_SERVER_BIN" "$update_image" >"$server_log" 2>&1 & - fi + + log "$label: transferring update image (v$expected_version) over UART" + $STDBUF "$UPDATE_SERVER_BIN" "$update_image" >"$server_log" 2>&1 & server_pid=$! set +e wait "$emu_pid" emu_rc=$? set -e + kill "$server_pid" >/dev/null 2>&1 || true wait "$server_pid" >/dev/null 2>&1 || true - [[ $emu_rc -eq 0 ]] || die "$label: m33mu exited with $emu_rc" - grep -q "\\[EXPECT BKPT\\] Success" "$update_log" || die "$label: expected BKPT 0x47" - log "$label: BKPT 0x47 hit (update accepted)" - check_update_version_in_image "$FACTORY_IMAGE" "$expected_version" || die "$label: update partition version mismatch" - log "$label: update partition version=$expected_version" + + if ! grep -q "\\[EXPECT BKPT\\] Success" "$update_log"; then + tail -n 80 "$update_log" | sed 's/^/ | /' + die "$label: expected BKPT $expected_bkpt" + fi + + log "$label: BKPT $expected_bkpt hit" + print_partition_flags "$label: flags after" + + if [[ $emu_rc -ne 0 && $emu_rc -ne 127 ]]; then + die "$label: m33mu exited with $emu_rc" + fi } +log "Rebuilding wolfboot.bin (TZEN=${TZEN:-0})" +make -C "$WOLFBOOT_ROOT" clean wolfboot.bin + +log "Building emu-test-apps images" +write_target_ld +make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=1 IMAGE_HEADER_SIZE="$IMAGE_HEADER_SIZE" sign-emu +make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=3 IMAGE_HEADER_SIZE="$IMAGE_HEADER_SIZE" sign-emu +make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=4 IMAGE_HEADER_SIZE="$IMAGE_HEADER_SIZE" sign-emu +make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=7 IMAGE_HEADER_SIZE="$IMAGE_HEADER_SIZE" sign-emu +make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=8 IMAGE_HEADER_SIZE="$IMAGE_HEADER_SIZE" sign-emu + +assemble_factory + +log "Scenario A: factory boot" +print_partition_flags "Scenario A: flags before factory run" +log "factory run: boot image v1, expect UART get_version=1" +set +e +$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ + --timeout "$BOOT_TIMEOUT" --quit-on-faults \ + "$FACTORY_FLASH" >"$EMU_PATH/factory.log" 2>&1 +factory_rc=$? +set -e +if ! grep -q "get_version=1" "$EMU_PATH/factory.log"; then + tail -n 80 "$EMU_PATH/factory.log" | sed 's/^/ | /' + die "factory run: expected get_version=1" +fi +if [[ $factory_rc -ne 0 && $factory_rc -ne 127 ]]; then + die "factory run: m33mu exited with $factory_rc" +fi +log "factory run: ok (version=1)" + +log "Scenario A: receive v7 update without trigger (expect BKPT 0x4D, stay on v1)" +assemble_factory +run_update_scenario "scenario_a_update_v7" "$UPDATE_IMAGE_V7" 7 0x4d +print_partition_versions "Scenario A: v7 update stored, version remains 1" + log "Scenario B: successful update from v1 to v4" -reset_factory_image -run_update_scenario "scenario_b_update" "$UPDATE_IMAGE_V4" 4 +assemble_factory +print_partition_flags "Scenario B: flags before update" +run_update_scenario "scenario_b_update" "$UPDATE_IMAGE_V4" 4 0x47 for i in 1 2; do run_log="$EMU_PATH/reboot_v4_${i}.log" log "Scenario B: reboot run $i: boot updated image v4, expect BKPT 0x4A (success)" - $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ - --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 --expect-bkpt=0x4a \ - "$UPDATE_IMAGE_V4" >"$run_log" 2>&1 || die "reboot v4 run $i: m33mu failed" + $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ + --timeout "$REBOOT_TIMEOUT" --expect-bkpt=0x4a --quit-on-faults \ + "$FACTORY_FLASH" >"$run_log" 2>&1 || die "reboot v4 run $i: m33mu failed" grep -q "\\[EXPECT BKPT\\] Success" "$run_log" || die "reboot v4 run $i: expected BKPT 0x4A" log "Scenario B: reboot run $i: BKPT 0x4A hit" -done + done log "Scenario C: update from v1 to v3, then fallback (no wolfBoot_success is called)" -reset_factory_image -run_update_scenario "scenario_c_update" "$UPDATE_IMAGE_V3" 3 +assemble_factory +print_partition_flags "Scenario C: flags before update" +run_update_scenario "scenario_c_update" "$UPDATE_IMAGE_V3" 3 0x47 log "Scenario C: first boot after update: reboot into v3 (expect BKPT 0x4B, no success call)" run_log_v3="$EMU_PATH/reboot_v3.log" -$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ - --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 --expect-bkpt=0x4b \ - "$UPDATE_IMAGE_V3" >"$run_log_v3" 2>&1 || die "reboot v3 run: m33mu failed" +print_partition_flags "Scenario C: flags before v3 reboot" +$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ + --timeout "$REBOOT_TIMEOUT" --expect-bkpt=0x4b --persist --quit-on-faults \ + "$FACTORY_FLASH" >"$run_log_v3" 2>&1 || die "reboot v3 run: m33mu failed" grep -q "\\[EXPECT BKPT\\] Success" "$run_log_v3" || die "reboot v3 run: expected BKPT 0x4B" log "Scenario C: reboot v3: BKPT 0x4B hit" +print_partition_flags "Scenario C: flags after v3 reboot" log "Scenario C: second reboot, expect v1 after fallback" run_log_fallback="$EMU_PATH/reboot_fallback_v1.log" set +e -$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout --no-tz \ - --boot-offset="$IMAGE_HEADER_SIZE" --timeout 2 \ - "$FACTORY_IMAGE" >"$run_log_fallback" 2>&1 +$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ + --timeout "$UPDATE_TIMEOUT" --persist --quit-on-faults \ + "$FACTORY_FLASH" >"$run_log_fallback" 2>&1 fallback_rc=$? set -e -grep -q "get_version=1" "$run_log_fallback" || die "fallback run: expected get_version=1" +print_partition_flags "Scenario C: flags after fallback run" +print_partition_versions "Scenario C: versions after fallback run" +if ! grep -q "get_version=1" "$run_log_fallback"; then + tail -n 80 "$run_log_fallback" | sed 's/^/ | /' + die "fallback run: expected get_version=1" +fi if [[ $fallback_rc -ne 0 && $fallback_rc -ne 127 ]]; then die "fallback run: m33mu exited with $fallback_rc" fi log "Scenario C: fallback ok (version=1)" +if [[ "$RAM_CODE" == "1" ]]; then + log "Scenario S: self-update enabled (RAM_CODE=1)" + log "Scenario S: not enabled in this script yet" +fi + log "ok: $TARGET emu tests passed" From dbcea534b0b3a77c58ff58341bc2016776a745f8 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 14:51:13 +0100 Subject: [PATCH 06/12] Improved test, added scenario separation --- test-app/emu-test-apps/test.sh | 213 ++++++++++++++++++++------------- 1 file changed, 132 insertions(+), 81 deletions(-) diff --git a/test-app/emu-test-apps/test.sh b/test-app/emu-test-apps/test.sh index f1f10eed19..bb0ca99d72 100755 --- a/test-app/emu-test-apps/test.sh +++ b/test-app/emu-test-apps/test.sh @@ -91,11 +91,42 @@ if [[ "$ARCH_OFFSET" == "0" || "$ARCH_OFFSET" == "0x0" ]]; then fi fi -BOOT_OFFSET=$((BOOT_ADDR - ARCH_OFFSET)) -UPDATE_OFFSET=$((UPDATE_ADDR - ARCH_OFFSET)) +normalize_flash_addr() { + local addr="$1" + if [[ "$ARCH_OFFSET" == "0x08000000" ]]; then + if (( addr >= 0x0c000000 && addr < 0x10000000 )); then + addr=$((addr - 0x04000000)) + fi + fi + echo "$addr" +} + +BOOT_ADDR_NORM="$(normalize_flash_addr "$BOOT_ADDR")" +UPDATE_ADDR_NORM="$(normalize_flash_addr "$UPDATE_ADDR")" + +BOOT_OFFSET=$((BOOT_ADDR_NORM - ARCH_OFFSET)) +UPDATE_OFFSET=$((UPDATE_ADDR_NORM - ARCH_OFFSET)) BOOT_OFFSET_HEX=$(printf "0x%x" "$BOOT_OFFSET") UPDATE_OFFSET_HEX=$(printf "0x%x" "$UPDATE_OFFSET") +get_check_config_val() { + local key="$1" + local val + make -C "$WOLFBOOT_ROOT/tools/check_config" check_config RAM_CODE=0 >/dev/null + val="$("$WOLFBOOT_ROOT/tools/check_config/check_config" | grep -m1 "^${key}" | sed 's/.*: *//')" + [[ -n "$val" ]] || die "missing ${key} from tools/check_config output" + echo "0x$val" +} + +BOOT_FLAGS_ADDR="$(get_check_config_val PART_BOOT_ENDFLAGS)" +UPDATE_FLAGS_ADDR="$(get_check_config_val PART_UPDATE_ENDFLAGS)" +BOOT_FLAGS_ADDR_NORM="$(normalize_flash_addr "$BOOT_FLAGS_ADDR")" +UPDATE_FLAGS_ADDR_NORM="$(normalize_flash_addr "$UPDATE_FLAGS_ADDR")" +BOOT_FLAGS_OFFSET=$((BOOT_FLAGS_ADDR_NORM - ARCH_OFFSET)) +UPDATE_FLAGS_OFFSET=$((UPDATE_FLAGS_ADDR_NORM - ARCH_OFFSET)) +BOOT_FLAGS_OFFSET_HEX=$(printf "0x%x" "$BOOT_FLAGS_OFFSET") +UPDATE_FLAGS_OFFSET_HEX=$(printf "0x%x" "$UPDATE_FLAGS_OFFSET") + M33MU_TZ_ARGS=(--no-tz) if [[ "${TZEN}" == "1" ]]; then M33MU_TZ_ARGS=() @@ -106,6 +137,17 @@ if command -v stdbuf >/dev/null 2>&1; then STDBUF="stdbuf -o0 -e0" fi +SCENARIOS_RAW="${SCENARIOS:-}" +SCENARIOS_UP="$(echo "$SCENARIOS_RAW" | tr '[:lower:]' '[:upper:]' | tr -d ' ' | sed -e 's/,,*/,/g' -e 's/^,//' -e 's/,$//')" + +want_scenario() { + local s="$1" + if [[ -z "$SCENARIOS_UP" ]]; then + return 0 + fi + echo "$SCENARIOS_UP" | grep -Eq "(^|,)$s(,|$)" +} + EMU_PATH="$EMU_APPS/$EMU_DIR" WOLFBOOT_BIN="$WOLFBOOT_ROOT/wolfboot.bin" FACTORY_FLASH="$EMU_PATH/factory.bin" @@ -203,12 +245,11 @@ assemble_factory() { print_partition_flags() { local label="$1" - python3 - "$FACTORY_FLASH" "$BOOT_ADDR" "$UPDATE_ADDR" "$PART_SIZE" "$SECTOR_SIZE" <<'PY' | sed "s/^/==> ${label}: /" + python3 - "$FACTORY_FLASH" "$BOOT_FLAGS_OFFSET_HEX" "$UPDATE_FLAGS_OFFSET_HEX" "$SECTOR_SIZE" <<'PY' | sed "s/^/==> ${label}: /" import sys -path, boot_s, update_s, size_s, sect_s = sys.argv[1:6] +path, boot_s, update_s, sect_s = sys.argv[1:5] boot = int(boot_s, 0) update = int(update_s, 0) -size = int(size_s, 0) sect = int(sect_s, 0) def decode(state): @@ -224,14 +265,14 @@ def decode(state): return "SUCCESS(0x00)" return f"0x{state:02x}" -def read_state(addr): +def read_state(endflags): try: with open(path, "rb") as f: - f.seek(addr + size - 4) + f.seek(endflags - 4) magic = f.read(4) if magic != b"BOOT": return None - f.seek(addr + size - 5) + f.seek(endflags - 5) b = f.read(1) if not b: return None @@ -239,14 +280,14 @@ def read_state(addr): except Exception: return None -def read_state_alt(addr): +def read_state_alt(endflags): try: with open(path, "rb") as f: - f.seek(addr + size - sect - 4) + f.seek(endflags - sect - 4) magic = f.read(4) if magic != b"BOOT": return None - f.seek(addr + size - sect - 5) + f.seek(endflags - sect - 5) b = f.read(1) if not b: return None @@ -392,83 +433,93 @@ make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=4 IMAGE_HEADE make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=7 IMAGE_HEADER_SIZE="$IMAGE_HEADER_SIZE" sign-emu make -C "$EMU_APPS" TARGET="$TARGET" TZEN="${TZEN:-0}" EMU_VERSION=8 IMAGE_HEADER_SIZE="$IMAGE_HEADER_SIZE" sign-emu -assemble_factory - -log "Scenario A: factory boot" -print_partition_flags "Scenario A: flags before factory run" -log "factory run: boot image v1, expect UART get_version=1" -set +e -$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ - --timeout "$BOOT_TIMEOUT" --quit-on-faults \ - "$FACTORY_FLASH" >"$EMU_PATH/factory.log" 2>&1 -factory_rc=$? -set -e -if ! grep -q "get_version=1" "$EMU_PATH/factory.log"; then - tail -n 80 "$EMU_PATH/factory.log" | sed 's/^/ | /' - die "factory run: expected get_version=1" -fi -if [[ $factory_rc -ne 0 && $factory_rc -ne 127 ]]; then - die "factory run: m33mu exited with $factory_rc" +if want_scenario "A"; then + assemble_factory + + log "Scenario A: factory boot" + print_partition_flags "Scenario A: flags before factory run" + log "factory run: boot image v1, expect UART get_version=1" + set +e + $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ + --timeout "$BOOT_TIMEOUT" --quit-on-faults \ + "$FACTORY_FLASH" >"$EMU_PATH/factory.log" 2>&1 + factory_rc=$? + set -e + if ! grep -q "get_version=1" "$EMU_PATH/factory.log"; then + tail -n 80 "$EMU_PATH/factory.log" | sed 's/^/ | /' + die "factory run: expected get_version=1" + fi + if [[ $factory_rc -ne 0 && $factory_rc -ne 127 ]]; then + die "factory run: m33mu exited with $factory_rc" + fi + log "factory run: ok (version=1)" + + log "Scenario A: receive v7 update without trigger (expect BKPT 0x4D, stay on v1)" + assemble_factory + run_update_scenario "scenario_a_update_v7" "$UPDATE_IMAGE_V7" 7 0x4d + print_partition_versions "Scenario A: v7 update stored, version remains 1" fi -log "factory run: ok (version=1)" -log "Scenario A: receive v7 update without trigger (expect BKPT 0x4D, stay on v1)" -assemble_factory -run_update_scenario "scenario_a_update_v7" "$UPDATE_IMAGE_V7" 7 0x4d -print_partition_versions "Scenario A: v7 update stored, version remains 1" +if want_scenario "B"; then + log "Scenario B: successful update from v1 to v4" + assemble_factory + print_partition_flags "Scenario B: flags before update" + run_update_scenario "scenario_b_update" "$UPDATE_IMAGE_V4" 4 0x47 + + for i in 1 2; do + run_log="$EMU_PATH/reboot_v4_${i}.log" + log "Scenario B: reboot run $i: boot updated image v4, expect BKPT 0x4A (success)" + $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ + --timeout "$REBOOT_TIMEOUT" --expect-bkpt=0x4a --quit-on-faults \ + "$FACTORY_FLASH" >"$run_log" 2>&1 || die "reboot v4 run $i: m33mu failed" + grep -q "\\[EXPECT BKPT\\] Success" "$run_log" || die "reboot v4 run $i: expected BKPT 0x4A" + log "Scenario B: reboot run $i: BKPT 0x4A hit" + done +fi -log "Scenario B: successful update from v1 to v4" -assemble_factory -print_partition_flags "Scenario B: flags before update" -run_update_scenario "scenario_b_update" "$UPDATE_IMAGE_V4" 4 0x47 +if want_scenario "C"; then + log "Scenario C: update from v1 to v3, then fallback (no wolfBoot_success is called)" + assemble_factory + print_partition_flags "Scenario C: flags before update" + run_update_scenario "scenario_c_update" "$UPDATE_IMAGE_V3" 3 0x47 -for i in 1 2; do - run_log="$EMU_PATH/reboot_v4_${i}.log" - log "Scenario B: reboot run $i: boot updated image v4, expect BKPT 0x4A (success)" + log "Scenario C: first boot after update: reboot into v3 (expect BKPT 0x4B, no success call)" + run_log_v3="$EMU_PATH/reboot_v3.log" + print_partition_flags "Scenario C: flags before v3 reboot" $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ - --timeout "$REBOOT_TIMEOUT" --expect-bkpt=0x4a --quit-on-faults \ - "$FACTORY_FLASH" >"$run_log" 2>&1 || die "reboot v4 run $i: m33mu failed" - grep -q "\\[EXPECT BKPT\\] Success" "$run_log" || die "reboot v4 run $i: expected BKPT 0x4A" - log "Scenario B: reboot run $i: BKPT 0x4A hit" - done - -log "Scenario C: update from v1 to v3, then fallback (no wolfBoot_success is called)" -assemble_factory -print_partition_flags "Scenario C: flags before update" -run_update_scenario "scenario_c_update" "$UPDATE_IMAGE_V3" 3 0x47 - -log "Scenario C: first boot after update: reboot into v3 (expect BKPT 0x4B, no success call)" -run_log_v3="$EMU_PATH/reboot_v3.log" -print_partition_flags "Scenario C: flags before v3 reboot" -$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ - --timeout "$REBOOT_TIMEOUT" --expect-bkpt=0x4b --persist --quit-on-faults \ - "$FACTORY_FLASH" >"$run_log_v3" 2>&1 || die "reboot v3 run: m33mu failed" -grep -q "\\[EXPECT BKPT\\] Success" "$run_log_v3" || die "reboot v3 run: expected BKPT 0x4B" -log "Scenario C: reboot v3: BKPT 0x4B hit" -print_partition_flags "Scenario C: flags after v3 reboot" - -log "Scenario C: second reboot, expect v1 after fallback" -run_log_fallback="$EMU_PATH/reboot_fallback_v1.log" -set +e -$STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ - --timeout "$UPDATE_TIMEOUT" --persist --quit-on-faults \ - "$FACTORY_FLASH" >"$run_log_fallback" 2>&1 -fallback_rc=$? -set -e -print_partition_flags "Scenario C: flags after fallback run" -print_partition_versions "Scenario C: versions after fallback run" -if ! grep -q "get_version=1" "$run_log_fallback"; then - tail -n 80 "$run_log_fallback" | sed 's/^/ | /' - die "fallback run: expected get_version=1" -fi -if [[ $fallback_rc -ne 0 && $fallback_rc -ne 127 ]]; then - die "fallback run: m33mu exited with $fallback_rc" + --timeout "$REBOOT_TIMEOUT" --expect-bkpt=0x4b --persist --quit-on-faults \ + "$FACTORY_FLASH" >"$run_log_v3" 2>&1 || die "reboot v3 run: m33mu failed" + grep -q "\\[EXPECT BKPT\\] Success" "$run_log_v3" || die "reboot v3 run: expected BKPT 0x4B" + log "Scenario C: reboot v3: BKPT 0x4B hit" + print_partition_flags "Scenario C: flags after v3 reboot" + + log "Scenario C: second reboot, expect v1 after fallback" + run_log_fallback="$EMU_PATH/reboot_fallback_v1.log" + set +e + $STDBUF "$M33MU" --cpu "$EMU_CPU" --uart-stdout "${M33MU_TZ_ARGS[@]}" \ + --timeout "$UPDATE_TIMEOUT" --persist --quit-on-faults \ + "$FACTORY_FLASH" >"$run_log_fallback" 2>&1 + fallback_rc=$? + set -e + print_partition_flags "Scenario C: flags after fallback run" + print_partition_versions "Scenario C: versions after fallback run" + if ! grep -q "get_version=1" "$run_log_fallback"; then + tail -n 80 "$run_log_fallback" | sed 's/^/ | /' + die "fallback run: expected get_version=1" + fi + if [[ $fallback_rc -ne 0 && $fallback_rc -ne 127 ]]; then + die "fallback run: m33mu exited with $fallback_rc" + fi + log "Scenario C: fallback ok (version=1)" fi -log "Scenario C: fallback ok (version=1)" -if [[ "$RAM_CODE" == "1" ]]; then - log "Scenario S: self-update enabled (RAM_CODE=1)" - log "Scenario S: not enabled in this script yet" +if want_scenario "S"; then + if [[ "$RAM_CODE" == "1" ]]; then + log "Scenario S: self-update enabled (RAM_CODE=1)" + log "Scenario S: not enabled in this script yet" + else + log "Scenario S: RAM_CODE disabled, skipping" + fi fi log "ok: $TARGET emu tests passed" From 76af4af2ecfdec323217de7fa45231b5f24e4dfe Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 16:16:51 +0100 Subject: [PATCH 07/12] Added github workflow for m33mu-based tests --- .github/workflows/emu-test-stm32h5.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/emu-test-stm32h5.yml diff --git a/.github/workflows/emu-test-stm32h5.yml b/.github/workflows/emu-test-stm32h5.yml new file mode 100644 index 0000000000..4b68a6bf92 --- /dev/null +++ b/.github/workflows/emu-test-stm32h5.yml @@ -0,0 +1,24 @@ +name: emu-test-stm32h5 + +on: + push: + pull_request: + +jobs: + emu-test-stm32h5: + runs-on: ubuntu-latest + container: + image: ghcr.io/danielinux/m33mu-ci:testing + steps: + - uses: actions/checkout@v4 + + - name: Configure stm32h5 (TZ) and build wolfboot + working-directory: wolfboot + run: | + cp config/examples/stm32h5-tz.config .config + make wolfboot.bin + + - name: Run emu test (stm32h5) + working-directory: wolfboot/test-app/emu-test-apps + run: | + SCENARIOS=C ./test.sh From e9f13084f450e724509ec0977459749ca02fcf4d Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 16:44:55 +0100 Subject: [PATCH 08/12] Silencing compiler warning --- src/update_flash.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/update_flash.c b/src/update_flash.c index 726281a077..8f2e053605 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -802,6 +802,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) { uint32_t fb_ok = (fallback_allowed == 1); VERIFY_VERSION_ALLOWED(fb_ok); + (void)fb_ok; } if ((fallback_allowed == 0) && (cur_ver >= upd_ver)) { wolfBoot_printf("Update version not allowed\n"); From 8177535eac28bfd71e33b6ccdd0eaba197f1f392 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 16:52:36 +0100 Subject: [PATCH 09/12] Fix path in workflow --- .github/workflows/emu-test-stm32h5.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/emu-test-stm32h5.yml b/.github/workflows/emu-test-stm32h5.yml index 4b68a6bf92..870075643e 100644 --- a/.github/workflows/emu-test-stm32h5.yml +++ b/.github/workflows/emu-test-stm32h5.yml @@ -13,12 +13,11 @@ jobs: - uses: actions/checkout@v4 - name: Configure stm32h5 (TZ) and build wolfboot - working-directory: wolfboot run: | cp config/examples/stm32h5-tz.config .config make wolfboot.bin - name: Run emu test (stm32h5) - working-directory: wolfboot/test-app/emu-test-apps + working-directory: test-app/emu-test-apps run: | SCENARIOS=C ./test.sh From 69311fd1f14fe772c9d62f3656b0c82063b17047 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 16:55:58 +0100 Subject: [PATCH 10/12] Added submodule init in new workflow --- .github/workflows/emu-test-stm32h5.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/emu-test-stm32h5.yml b/.github/workflows/emu-test-stm32h5.yml index 870075643e..d91c7a05a3 100644 --- a/.github/workflows/emu-test-stm32h5.yml +++ b/.github/workflows/emu-test-stm32h5.yml @@ -12,6 +12,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Init submodules + run: git submodule update --init --single-branch + - name: Configure stm32h5 (TZ) and build wolfboot run: | cp config/examples/stm32h5-tz.config .config From 32c8e138e36f7028a6710a8f4fdb147b2b0258c7 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 17:00:40 +0100 Subject: [PATCH 11/12] updated wolfPSA module url --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e528d9353a..6cd81662fe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,4 +12,4 @@ url = https://github.com/wolfssl/wolfhsm.git [submodule "lib/wolfPSA"] path = lib/wolfPSA - url = git@github.com:wolfSSL/wolfPSA.git + url = https://github.com/wolfSSL/wolfPSA.git From c3192b3864e1f912269854e28d35736416f73053 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Sun, 11 Jan 2026 17:01:30 +0100 Subject: [PATCH 12/12] Added safe.directory for workspace --- .github/workflows/emu-test-stm32h5.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/emu-test-stm32h5.yml b/.github/workflows/emu-test-stm32h5.yml index d91c7a05a3..6745f6580b 100644 --- a/.github/workflows/emu-test-stm32h5.yml +++ b/.github/workflows/emu-test-stm32h5.yml @@ -13,7 +13,9 @@ jobs: - uses: actions/checkout@v4 - name: Init submodules - run: git submodule update --init --single-branch + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + git submodule update --init --single-branch - name: Configure stm32h5 (TZ) and build wolfboot run: |