Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
85 changes: 85 additions & 0 deletions test-app/emu-test-apps/Makefile
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions test-app/emu-test-apps/common/emu_app.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef EMU_APP_H
#define EMU_APP_H

#include <stdint.h>

void emu_uart_init(void);
int emu_uart_read(uint8_t *c);
void emu_uart_write(uint8_t c);

#endif /* EMU_APP_H */
111 changes: 111 additions & 0 deletions test-app/emu-test-apps/common/emu_hal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#include <stdint.h>
#include <string.h>
#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
}
38 changes: 38 additions & 0 deletions test-app/emu-test-apps/common/emu_ivt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <stdint.h>

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
};
32 changes: 32 additions & 0 deletions test-app/emu-test-apps/common/emu_startup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <stdint.h>

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");
}
}
Loading