From 5fb5b4b6ea112a9caddf3a5551e4423bf6103579 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Tue, 25 Nov 2025 03:01:03 +0100 Subject: [PATCH 1/4] nRF5340 TrustZone port --- arch.mk | 6 ++ config/examples/nrf5340-tz.config | 73 +++++++++++++++++++++ docs/Targets.md | 9 ++- hal/nrf5340-ns.ld | 53 +++++++++++++++ hal/nrf5340.c | 97 +++++++++++++++++++++++++-- hal/nrf5340.h | 98 ++++++++++++++++++++++------ hal/nrf5340.ld | 27 +++++++- options.mk | 2 +- test-app/ARM-nrf5340-ns.ld | 57 ++++++++++++++++ test-app/Makefile | 8 +++ test-app/app_nrf5340.c | 7 +- test-app/app_nrf5340_net.c | 2 +- tools/scripts/nrf5340/build_flash.sh | 14 +++- 13 files changed, 419 insertions(+), 34 deletions(-) create mode 100644 config/examples/nrf5340-tz.config create mode 100644 hal/nrf5340-ns.ld create mode 100644 test-app/ARM-nrf5340-ns.ld diff --git a/arch.mk b/arch.mk index 2fb3cec93d..cde222483c 100644 --- a/arch.mk +++ b/arch.mk @@ -690,6 +690,12 @@ ifeq ($(TARGET),mcxw) $(MCUXPRESSO_DRIVERS)/drivers/fsl_romapi.o endif +ifeq ($(TARGET),nrf5340) + ifneq ($(TZEN), 1) + LSCRIPT_IN=hal/$(TARGET)-ns.ld + endif +endif + ifeq ($(TARGET),nrf5340_net) # Net core doesn't support DSP and FP CFLAGS+=-mcpu=cortex-m33+nodsp+nofp diff --git a/config/examples/nrf5340-tz.config b/config/examples/nrf5340-tz.config new file mode 100644 index 0000000000..112708a668 --- /dev/null +++ b/config/examples/nrf5340-tz.config @@ -0,0 +1,73 @@ +ARCH?=ARM +TZEN?=1 +TARGET?=nrf5340 +SIGN?=ECC384 +HASH?=SHA384 +WOLFBOOT_VERSION?=1 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=0 +DELTA_UPDATES?=1 + +SPMATH?=1 +RAM_CODE?=1 + +DUALBANK_SWAP?=0 +FLAGS_HOME=0 +DISABLE_BACKUP=0 +EXT_FLASH?=1 +SPI_FLASH?=0 +QSPI_FLASH?=1 + +# Flash is 4KB pages (app) +WOLFBOOT_SECTOR_SIZE?=0x1000 + +# Flash keyvault: 112K +WOLFBOOT_KEYVAULT_ADDRESS?=0x20000 +WOLFBOOT_KEYVAULT_SIZE?=0x1C000 + +# Flash NSC: 16K +WOLFBOOT_NSC_ADDRESS?=0x3C000 +WOLFBOOT_NSC_SIZE?=0x04000 + +# Application offset (reserve 256K for wolfBoot + keyvault + NSC) +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x40000 + +# Application Partition Size (768KB) +WOLFBOOT_PARTITION_SIZE?=0xC0000 + +# External Flash offset for application update (1MB) +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0 + +# External Flash offset for network update at 0x100000 (size=256KB) + +# External Flash offset for swap (4KB) +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x140000 + +V?=0 +DEBUG?=0 +DEBUG_UART?=1 +USE_GCC=1 +OPTIMIZATION_LEVEL=2 + +# Optionally wait for network core to boot before starting application core +CFLAGS_EXTRA+=-DNRF_SYNC_CORES + +# Use larger block size for swapping sectors (performance improvement) +CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 + +# Enable optional power control pin (active low) P1.00 +#CFLAGS_EXTRA+=-DQSPI_PWR_CTRL_PORT=1 -DQSPI_PWR_CTRL_PIN=0 + +# Use UART0 on P0.22 +#CFLAGS_EXTRA+=-DUART_PORT=0 -DUART_PIN=22 + +#CFLAGS_EXTRA+=-DDEBUG_FLASH +#CFLAGS_EXTRA+=-DDEBUG_QSPI=1 + +# Hard fault debugging +#CFLAGS_EXTRA+=-DDEBUG_HARDFAULT diff --git a/docs/Targets.md b/docs/Targets.md index 12e4f7c5bf..42558d1f50 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -2425,7 +2425,7 @@ c NXP MCXW716 is a Cortex-M33 microcontroller running at 96MHz. The support has been tested using FRDM-MCXW716 with the onboard MCU-Link configured in JLink mode. -This requires the MCXW SDK from the NXP MCUXpresso SDK Builder. We tested using [mcux-sdk](https://github.com/nxp-mcuxpresso/mcux-sdk) and [CMSIS_5](https://github.com/nxp-mcuxpresso/CMSIS_5)` +This requires the MCXW SDK from the NXP MCUXpresso SDK Builder. We tested using [mcux-sdk](https://github.com/nxp-mcuxpresso/mcux-sdk) and [CMSIS_5](https://github.com/nxp-mcuxpresso/CMSIS_5) placed under "../NXP". Adjust the MCUXPRESSO and MCUXPRESSO_CMSIS variables in your .config file according to your paths. ### MCX W: Configuring and compiling @@ -2549,6 +2549,13 @@ Tested with the Nordic nRF5340-DK. This device has two cores: 1) Application core: Cortex-M33 at 128MHz, w/TrustZone, 1MB flash, 512KB RAM 2) Network core: Cortex-M33 at 64MHz, 256KB Flash and 64KB RAM +Three different configurations are available at `config/examples`: +- `nrf5340.config`: for the app core; does not make use of TrustZone, i.e. it + always runs in secure mode. +- `nrf5340-tz.config`: for the app core; makes use of TrustZone, i.e. boots the + application as non-secure code. +- `nrf5340_net.config`: for the net core. + The DK board has two virtual COM ports. Application core and Network core will each output to different VCOM ports. The cores communicate firmware updates using shared memory hosted on application core. diff --git a/hal/nrf5340-ns.ld b/hal/nrf5340-ns.ld new file mode 100644 index 0000000000..c65e9c5748 --- /dev/null +++ b/hal/nrf5340-ns.ld @@ -0,0 +1,53 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @ARCH_FLASH_OFFSET@, LENGTH = @BOOTLOADER_PARTITION_SIZE@ + FLASH_NET (rx) : ORIGIN = 0x01000000, LENGTH = 256K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K +} + +SECTIONS +{ + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + *(.boot*) + *(.text*) + *(.rodata*) + *(.init*) + *(.fini*) + . = ALIGN(4); + _end_text = .; + } > FLASH + + .edidx : + { + . = ALIGN(4); + *(.ARM.exidx*) + } > FLASH + + _stored_data = .; + + .data : AT (_stored_data) + { + _start_data = .; + KEEP(*(.data*)) + . = ALIGN(4); + _end_data = .; + } > RAM + + .bss (NOLOAD) : + { + _start_bss = .; + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + __bss_end__ = .; + _end = .; + } > RAM + . = ALIGN(4); +} + +END_STACK = ORIGIN(RAM) + LENGTH(RAM); diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 7de476041d..c49ff337d6 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -29,6 +29,8 @@ #include "printf.h" #include "nrf5340.h" #include "spi_flash.h" +#include "hal/armv8m_tz.h" +#include "target.h" /* TODO: * Key Storage: See 7.1.18.4.2 Key storage: @@ -133,6 +135,50 @@ static SharedMem_t* shm = (SharedMem_t*)&shm_shadow; #endif #endif +#ifdef TZEN +static void hal_spu_init(void) { + uint8_t nsc_size_index; + uint8_t region; + uint8_t start_region; + uint8_t end_region; + + /* Make sure SAU is disabled, configure everything through SPU */ + SAU_CTRL = SAU_INIT_CTRL_ALLNS; + + /* Flash: Non-Secure Callable */ + nsc_size_index = (WOLFBOOT_NSC_SIZE > 2048) ? 8 : + (WOLFBOOT_NSC_SIZE > 1024) ? 7 : + (WOLFBOOT_NSC_SIZE > 512) ? 6 : + (WOLFBOOT_NSC_SIZE > 256) ? 5 : + (WOLFBOOT_NSC_SIZE > 128) ? 4 : + (WOLFBOOT_NSC_SIZE > 64) ? 3 : + (WOLFBOOT_NSC_SIZE > 32) ? 2 : + (WOLFBOOT_NSC_SIZE > 0) ? 1 : 0; + + SPU_FLASHNSC_REGION(0) = ((WOLFBOOT_NSC_ADDRESS / SPU_FLASH_BLOCK_SIZE) & + SPU_FLASHNSC_REGION_MASK) | SPU_FLASHNSC_REGION_LOCK; + SPU_FLASHNSC_SIZE(0) = nsc_size_index | SPU_FLASHNSC_SIZE_LOCK; + + /* Flash: non-secure application area */ + start_region = WOLFBOOT_PARTITION_BOOT_ADDRESS / SPU_FLASH_BLOCK_SIZE; + end_region = (WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE) / SPU_FLASH_BLOCK_SIZE; + + for (region = start_region; region < end_region; region++) { + SPU_FLASHREGION_PERM(region) = (SPU_FLASHREGION_PERM(region) & + ~SPU_FLASHREGION_PERM_SECATTR) | SPU_FLASHREGION_PERM_LOCK; + } + + /* RAM: non-secure application area */ + start_region = 0x20000 / SPU_RAM_BLOCK_SIZE; + end_region = 0x24000 / SPU_RAM_BLOCK_SIZE; + + for (region = start_region; region < end_region; region++) { + SPU_RAMREGION_PERM(region) = (SPU_RAMREGION_PERM(region) & + ~SPU_RAMREGION_PERM_SECATTR) | SPU_RAMREGION_PERM_LOCK; + } +} +#endif + void uart_init(void) { /* nRF5340-DK: (P0.20 or P1.01) @@ -220,8 +266,9 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) ((((uint32_t)data) + i) & 0x03) == 0)) { src = (uint32_t *)data; dst = (uint32_t *)address; - /* set both secure and non-secure registers */ +#if TZ_SECURE() || defined(TARGET_nrf5340_net) NVMC_CONFIG = NVMC_CONFIG_WEN; +#endif NVMC_CONFIGNS = NVMC_CONFIG_WEN; while (NVMC_READY == 0); dst[i >> 2] = src[i >> 2]; @@ -234,8 +281,9 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) dst = (uint32_t *)(address - off); val = dst[i >> 2]; vbytes[off] = data[i]; - /* set both secure and non-secure registers */ +#if TZ_SECURE() || defined(TARGET_nrf5340_net) NVMC_CONFIG = NVMC_CONFIG_WEN; +#endif NVMC_CONFIGNS = NVMC_CONFIG_WEN; while (NVMC_READY == 0); dst[i >> 2] = val; @@ -257,7 +305,9 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) address &= ~(FLASH_PAGE_SIZE-1); for (p = address; p <= end; p += FLASH_PAGE_SIZE) { /* set both secure and non-secure registers */ +#if TZ_SECURE() || defined(TARGET_nrf5340_net) NVMC_CONFIG = NVMC_CONFIG_EEN; +#endif NVMC_CONFIGNS = NVMC_CONFIG_EEN; while (NVMC_READY == 0); *(volatile uint32_t *)p = 0xFFFFFFFF; @@ -716,6 +766,10 @@ void hal_init(void) hal_net_check_version(); #endif + +#ifdef TZEN + hal_spu_init(); +#endif } #ifdef __WOLFBOOT @@ -733,8 +787,8 @@ int hal_flash_protect(uint32_t start, uint32_t len) if (start + len > FLASH_SIZE) len = FLASH_SIZE - start; - region = (start / SPU_BLOCK_SIZE); - n = (len / SPU_BLOCK_SIZE); + region = (start / SPU_FLASH_BLOCK_SIZE); + n = (len / SPU_FLASH_BLOCK_SIZE); for (i = 0; i < n; i++) { /* do not allow write to this region and lock till next reset */ @@ -749,6 +803,25 @@ int hal_flash_protect(uint32_t start, uint32_t len) return 0; } +#ifdef TZEN +static void periph_unsecure() { + /* Unsecure both GPIO ports */ + SPU_PERIPHID_PERM(GPIO_PERIPHID) &= ~SPU_PERIPHID_PERM_SECATTR; + //SPU_GPIOPORT_PERM(0) = (1 << 29); + SPU_GPIOPORT_PERM(0) = 0; + SPU_GPIOPORT_PERM(1) = 0; + + /* Unsecure UARTE0 */ + SPU_PERIPHID_PERM(SERIAL0_PERIPHID) &= ~SPU_PERIPHID_PERM_SECATTR; + + /* Unsecure NVMC */ + SPU_PERIPHID_PERM(KMU_NVMC_PERIPHID) &= ~SPU_PERIPHID_PERM_SECATTR; + + /* Unsecure RTC0 */ + SPU_PERIPHID_PERM(RTC0_PERIPHID) &= ~SPU_PERIPHID_PERM_SECATTR; +} +#endif + void hal_prepare_boot(void) { /* Write protect bootloader region of flash */ @@ -771,16 +844,28 @@ void hal_prepare_boot(void) #endif #if defined(TARGET_nrf5340_app) && defined(NRF_SYNC_CORES) - /* if core synchronization enabled, - * then wait for update_done or do_boot (5 seconds, 30 for update) */ + /* If core synchronization enabled, + * then wait for update_done or do_boot (5 seconds, 30 for update). + * Longer wait in DEBUG mode because the net core boots much + * slower. */ wolfBoot_printf("Waiting for network core...\n"); +#ifndef DEBUG (void)hal_shm_status_wait(&shm->core.net, (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), doUpdateNet ? 30*1000 : 5*1000); +#else + (void)hal_shm_status_wait(&shm->core.net, + (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), + doUpdateNet ? 45*1000 : 20*1000); +#endif #endif } hal_shm_cleanup(); + +#ifdef TZEN + periph_unsecure(); +#endif } #endif /* __WOLFBOOT */ diff --git a/hal/nrf5340.h b/hal/nrf5340.h index 397cd250a5..eda2ba14a8 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -22,6 +22,12 @@ #ifndef _HAL_NRF5340_H_ #define _HAL_NRF5340_H_ +#if !defined(TARGET_nRF5340_net) && !(defined(TZEN) && defined(NONSECURE_APP)) +# define TZ_SECURE() (1) +#else +# define TZ_SECURE() (0) +#endif + /* Build-time gate for secure or non-secure peripherals. * At boot-time peripherals are secure */ #ifdef TARGET_nrf5340_net @@ -32,10 +38,6 @@ /* Application core */ #define TARGET_nrf5340_app #define CORE_STR "app" - #ifndef TZEN - /* at reset/power on wolfBoot is using secure bases */ - #define TZEN - #endif #endif /* Clock */ @@ -77,7 +79,7 @@ void sleep_us(uint32_t usec); /* Domain Configuration */ #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define DCNF_BASE (0x50000000) #else #define DCNF_BASE (0x40000000) @@ -97,6 +99,7 @@ void sleep_us(uint32_t usec); #ifdef TARGET_nrf5340_app /* SPU */ #define SPU_BASE 0x50003000UL + #define SPU_EXTDOMAIN_PERM(n) *((volatile uint32_t *)(SPU_BASE + 0x440 + (((n) & 0x0) * 0x4))) #define SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE 0 #define SPU_EXTDOMAIN_PERM_SECATTR_SECURE (1 << 4) @@ -104,13 +107,56 @@ void sleep_us(uint32_t usec); #define SPU_EXTDOMAIN_PERM_LOCK (1 << 8) #define SPU_EXTDOMAIN_PERM_SECUREMAPPING_MASK (0x3) - #define SPU_BLOCK_SIZE (16 * 1024) - #define SPU_FLASHREGION_PERM(n) *((volatile uint32_t *)(SPU_BASE + 0x600 + (((n) & 0x3F) * 0x4))) + #define SPU_GPIOPORT_PERM(n) (*(volatile uint32_t *)(SPU_BASE + 0x4C0 + ((n) & 0x1) * 0x8)) + #define SPU_GPIOPORT_LOCK(n) (*(volatile uint32_t *)(SPU_BASE + 0x4C4 + ((n) & 0x1) * 0x8)) + + #define SPU_FLASH_BLOCK_SIZE (16 * 1024) + #define SPU_RAM_BLOCK_SIZE (8 * 1024) + + #define SPU_FLASHNSC_REGION(n) (*(volatile uint32_t *)(SPU_BASE + 0x500 + ((n) & 0x1) * 0x8)) + #define SPU_FLASHNSC_REGION_MASK 0x0000003F + #define SPU_FLASHNSC_REGION_LOCK (1 << 8) + + #define SPU_FLASHNSC_SIZE(n) (*(volatile uint32_t *)(SPU_BASE + 0x504 + ((n) & 0x1) * 0x8)) + #define SPU_FLASHNSC_SIZE_MASK 0x0000000F + #define SPU_FLASHNSC_SIZE_LOCK (1 << 8) + + #define SPU_RAMNSC_REGION(n) (*(volatile uint32_t *)(SPU_BASE + 0x540 + ((n) & 0x1) * 0x8)) + #define SPU_RAMNSC_REGION_MASK 0x0000003F + #define SPU_RAMNSC_REGION_LOCK (1 << 8) + + #define SPU_RAMNSC_SIZE(n) (*(volatile uint32_t *)(SPU_BASE + 0x544 + ((n) & 0x1) * 0x8)) + #define SPU_RAMNSC_SIZE_MASK 0x0000000F + #define SPU_RAMNSC_SIZE_LOCK (1 << 8) + + #define SPU_FLASHREGION_PERM(n) (*(volatile uint32_t *)(SPU_BASE + 0x600 + ((n) & 0x3F) * 0x4)) #define SPU_FLASHREGION_PERM_EXEC (1 << 0) /* Allow instruction fetches from flash region */ #define SPU_FLASHREGION_PERM_WRITE (1 << 1) /* Allow write operation to region */ #define SPU_FLASHREGION_PERM_READ (1 << 2) /* Allow read operation from flash region */ #define SPU_FLASHREGION_PERM_SECATTR (1 << 4) /* Flash region n security attribute is secure */ #define SPU_FLASHREGION_PERM_LOCK (1 << 8) /* The content of this register can't be changed until the next reset */ + + #define SPU_RAMREGION_PERM(n) (*(volatile uint32_t *)(SPU_BASE + 0x700 + ((n) & 0x3F) * 0x4)) + #define SPU_RAMREGION_PERM_EXEC (1 << 0) /* Allow instruction fetches from flash region */ + #define SPU_RAMREGION_PERM_WRITE (1 << 1) /* Allow write operation to region */ + #define SPU_RAMREGION_PERM_READ (1 << 2) /* Allow read operation from flash region */ + #define SPU_RAMREGION_PERM_SECATTR (1 << 4) /* Flash region n security attribute is secure */ + #define SPU_RAMREGION_PERM_LOCK (1 << 8) /* The content of this register can't be changed until the next reset */ + + #define SPU_PERIPHID_PERM(n) (*(volatile uint32_t *)(SPU_BASE + 0x800 + ((n) & 0xFF) * 0x4)) + #define SPU_PERIPHID_PERM_SECUREMAPPING_MASK 0x00000003 + #define SPU_PERIPHID_PERM_SECUREMAPPING_NONSECURE (0 << 0) + #define SPU_PERIPHID_PERM_SECUREMAPPING_SECURE (1 << 0) + #define SPU_PERIPHID_PERM_SECUREMAPPING_USERSEL (2 << 0) + #define SPU_PERIPHID_PERM_SECUREMAPPING_SPLIT (3 << 0) + #define SPU_PERIPHID_PERM_DMA_MASK 0x0000000C + #define SPU_PERIPHID_PERM_DMA_NODMA (0 << 2) + #define SPU_PERIPHID_PERM_DMA_NOSEPATTR (1 << 2) + #define SPU_PERIPHID_PERM_DMA_SEPATTR (2 << 2) + #define SPU_PERIPHID_PERM_SECATTR (1 << 4) + #define SPU_PERIPHID_PERM_DMASEC (1 << 5) + #define SPU_PERIPHID_PERM_LOCK (1 << 8) + #define SPU_PERIPHID_PERM_PRESENT (1 << 31) #endif /* UICR */ @@ -130,14 +176,14 @@ void sleep_us(uint32_t usec); #else #define CTRLAP_BASE (0x41006000) #endif -#define CTRLAP_APPROTECT_LOCK (*(volatile uint32_t *)(CTRLAP_BASE 0x540)) -#define CTRLAP_APPROTECT_DISABLE (*(volatile uint32_t *)(CTRLAP_BASE 0x544)) -#define CTRLAP_SECUREAPPROTECT_LOCK (*(volatile uint32_t *)(CTRLAP_BASE 0x548)) -#define CTRLAP_SECUREAPPROTECT_DISABLE (*(volatile uint32_t *)(CTRLAP_BASE 0x54C)) +#define CTRLAP_APPROTECT_LOCK (*(volatile uint32_t *)(CTRLAP_BASE + 0x540)) +#define CTRLAP_APPROTECT_DISABLE (*(volatile uint32_t *)(CTRLAP_BASE + 0x544)) +#define CTRLAP_SECUREAPPROTECT_LOCK (*(volatile uint32_t *)(CTRLAP_BASE + 0x548)) +#define CTRLAP_SECUREAPPROTECT_DISABLE (*(volatile uint32_t *)(CTRLAP_BASE + 0x54C)) /* Reset */ #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define RESET_BASE (0x50005000) #else #define RESET_BASE (0x40005000) @@ -158,8 +204,10 @@ void sleep_us(uint32_t usec); /* Non-volatile memory controller */ +#define KMU_NVMC_PERIPHID 57 + #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define NVMC_BASE (0x50039000) #else #define NVMC_BASE (0x40039000) @@ -183,7 +231,7 @@ void sleep_us(uint32_t usec); /* Clock control */ #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define CLOCK_BASE (0x50005000) #else #define CLOCK_BASE (0x40005000) @@ -223,8 +271,10 @@ void sleep_us(uint32_t usec); /* GPIO Port (0-1) */ +#define GPIO_PERIPHID 66 + #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define GPIO_BASE(n) (0x50842500 + (((n) & 0x1) * 0x300)) #else #define GPIO_BASE(n) (0x40842500 + (((n) & 0x1) * 0x300)) @@ -251,8 +301,13 @@ void sleep_us(uint32_t usec); #define GPIO_CNF_MCUSEL(n) (((n) & 0x7) << 28) /* UART (0-1) */ +#define SERIAL0_PERIPHID 8 +#define SERIAL1_PERIPHID 9 +#define SERIAL2_PERIPHID 11 +#define SERIAL3_PERIPHID 12 + #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define UART_BASE(n) (0x50008000 + (((n) & 0x1) * 0x1000)) #else #define UART_BASE(n) (0x40008000 + (((n) & 0x1) * 0x1000)) @@ -279,7 +334,7 @@ void uart_write_sz(const char* c, unsigned int sz); /* SPI (0-2) */ #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define SPI_BASE(n) (0x50008000 + (((n) & 0x3) * 0x1000)) #else #define SPI_BASE(n) (0x40008000 + (((n) & 0x3) * 0x1000)) @@ -316,7 +371,7 @@ void uart_write_sz(const char* c, unsigned int sz); /* QSPI */ #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define QSPI_BASE (0x5002B000) #else #define QSPI_BASE (0x4002B000) @@ -398,7 +453,7 @@ void uart_write_sz(const char* c, unsigned int sz); /* interprocessor communication (IPC) peripheral */ #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define IPC_BASE (0x5002A000) #else #define IPC_BASE (0x4002A000) @@ -415,8 +470,11 @@ void uart_write_sz(const char* c, unsigned int sz); #define IPC_GPMEM(n) *((volatile uint32_t *)(IPC_BASE + 0x610 + (((n) & 0x1) * 0x4))) /* RTC - uses LFCLK - 24-bit counter/compare */ +#define RTC0_PERIPHID 20 +#define RTC1_PERIPHID 21 + #ifdef TARGET_nrf5340_app - #ifdef TZEN + #if TZ_SECURE() #define RTC_BASE(n) ((0x50014000) + (((n) & 0x1) * 0x1000)) #else #define RTC_BASE(n) ((0x40014000) + (((n) & 0x1) * 0x1000)) diff --git a/hal/nrf5340.ld b/hal/nrf5340.ld index c65e9c5748..8edb29fe5b 100644 --- a/hal/nrf5340.ld +++ b/hal/nrf5340.ld @@ -1,8 +1,12 @@ MEMORY { - FLASH (rx) : ORIGIN = @ARCH_FLASH_OFFSET@, LENGTH = @BOOTLOADER_PARTITION_SIZE@ - FLASH_NET (rx) : ORIGIN = 0x01000000, LENGTH = 256K - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + FLASH (rx) : ORIGIN = @ARCH_FLASH_OFFSET@, LENGTH = @WOLFBOOT_KEYVAULT_ADDRESS@ - @ARCH_FLASH_OFFSET@ + FLASH_NET (rx) : ORIGIN = 0x01000000, LENGTH = 0x40000 /* 256K */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 /* 64K */ + RAM_HEAP (rw) : ORIGIN = 0x20010000, LENGTH = 0xc000 /* 48K */ + RAM_KV (rw) : ORIGIN = 0x2001c000, LENGTH = 0x2000 /* 8K */ + FLASH_KEYVAULT (rw) : ORIGIN = @WOLFBOOT_KEYVAULT_ADDRESS@, LENGTH = @WOLFBOOT_KEYVAULT_SIZE@ + FLASH_NSC(rx) : ORIGIN = @WOLFBOOT_NSC_ADDRESS@, LENGTH = @WOLFBOOT_NSC_SIZE@ } SECTIONS @@ -26,6 +30,14 @@ SECTIONS *(.ARM.exidx*) } > FLASH + .gnu.sgstubs : + { + . += 0x400; + . = ALIGN(4); + *(.gnu.sgstubs*) /* Secure Gateway Stubs */ + . = ALIGN(4); + } > FLASH_NSC + _stored_data = .; .data : AT (_stored_data) @@ -51,3 +63,12 @@ SECTIONS } END_STACK = ORIGIN(RAM) + LENGTH(RAM); + +_keyvault_origin = ORIGIN(RAM_KV); +_keyvault_size = LENGTH(RAM_KV); + +_flash_keyvault = ORIGIN(FLASH_KEYVAULT); +_flash_keyvault_size = LENGTH(FLASH_KEYVAULT); + +_start_heap = ORIGIN(RAM_HEAP); +_heap_size = LENGTH(RAM_HEAP); diff --git a/options.mk b/options.mk index 9ccc779191..3db37b4bb5 100644 --- a/options.mk +++ b/options.mk @@ -596,7 +596,7 @@ endif # allow elf inclusion of debug symbols even with optimizations enabled # make DEBUG_SYMBOLS=1 ifeq ($(DEBUG_SYMBOLS),1) - CFLAGS+=-g + CFLAGS+=-g -DDEBUG_SYMBOLS ifeq ($(USE_GCC),1) CFLAGS+=-ggdb3 else ifneq ($(ARCH),AURIX_TC3) diff --git a/test-app/ARM-nrf5340-ns.ld b/test-app/ARM-nrf5340-ns.ld new file mode 100644 index 0000000000..4bbb443fde --- /dev/null +++ b/test-app/ARM-nrf5340-ns.ld @@ -0,0 +1,57 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 16K /* Run in lowmem */ +} + +SECTIONS +{ + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + *(.init) + *(.fini) + *(.text*) + KEEP(*(.rodata*)) + . = ALIGN(4); + _end_text = .; + } > FLASH + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > FLASH + + _stored_data = .; + + .data : AT (_stored_data) + { + _start_data = .; + KEEP(*(.data*)) + . = ALIGN(4); + KEEP(*(.ramcode)) + . = ALIGN(4); + _end_data = .; + } > RAM + + .bss : + { + _start_bss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + _end = .; + } > RAM +} + +_wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@; +_wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@; +_wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@; +_wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@; + +PROVIDE(_start_heap = _end); +PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/test-app/Makefile b/test-app/Makefile index b58cba2cfe..ac8f2dd4b0 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -234,6 +234,14 @@ ifeq ($(TARGET),stm32u5) LDFLAGS+=-mcpu=cortex-m33 endif +ifeq ($(TARGET),nrf5340) + ifeq ($(TZEN),1) + LSCRIPT_TEMPLATE=ARM-nrf5340-ns.ld + else + LSCRIPT_TEMPLATE=ARM.ld + endif +endif + ifeq ($(TARGET),nrf5340_net) CFLAGS+=-mcpu=cortex-m33+nodsp+nofp LDFLAGS+=-mcpu=cortex-m33+nodsp+nofp diff --git a/test-app/app_nrf5340.c b/test-app/app_nrf5340.c index 12700672c3..222f5cf733 100644 --- a/test-app/app_nrf5340.c +++ b/test-app/app_nrf5340.c @@ -56,10 +56,15 @@ void main(void) wolfBoot_printf("========================\n"); wolfBoot_printf("nRF5340 wolfBoot (app core)\n"); - wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); + wolfBoot_printf("Copyright 2025 wolfSSL Inc\n"); wolfBoot_printf("GPL v3\n"); wolfBoot_printf("Version : 0x%lx\n", app_version); wolfBoot_printf("Compiled: " __DATE__ ":" __TIME__ "\n"); +#ifdef TZEN + wolfBoot_printf("TrustZone enabled: yes\n"); +#else + wolfBoot_printf("TrustZone enabled: no\n"); +#endif wolfBoot_printf("========================\n"); /* mark boot successful */ diff --git a/test-app/app_nrf5340_net.c b/test-app/app_nrf5340_net.c index 497b6ac1ca..c643fe2dad 100644 --- a/test-app/app_nrf5340_net.c +++ b/test-app/app_nrf5340_net.c @@ -54,7 +54,7 @@ void main(void) wolfBoot_printf("========================\n"); wolfBoot_printf("nRF5340 wolfBoot (net core)\n"); - wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); + wolfBoot_printf("Copyright 2025 wolfSSL Inc\n"); wolfBoot_printf("GPL v3\n"); wolfBoot_printf("Version : 0x%lx\n", app_version); wolfBoot_printf("Compiled: " __DATE__ ":" __TIME__ "\n"); diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index b5731bed53..175bcbb1fd 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -57,6 +57,7 @@ while test $# -gt 0; do echo "-h, --help show brief help" echo "-c, --clean cleanup build artifacts" echo "-b, --build build release with symbols" + echo "-tz, --trustzone" use TrustZone configuration echo "-d, --debug build debug" echo "-v, --verbose build verbose" echo "--version use custom version" @@ -80,6 +81,11 @@ while test $# -gt 0; do echo "Build release with symbols" shift ;; + -tz|--trustzone) + DO_TRUSTZONE=1 + echo "Build with TrustZone config" + shift + ;; -d|--debug) DO_BUILD=1 MAKE_ARGS+=" DEBUG=1" @@ -167,6 +173,12 @@ fi if [[ $DO_BUILD == 1 ]]; then # Build internal flash images for both cores + + if [[ $DO_TRUSTZONE == 1 ]]; then + config_app=config/examples/nrf5340-tz.config + else + config_app=config/examples/nrf5340.config + fi # Build net cp config/examples/nrf5340_net.config .config @@ -181,7 +193,7 @@ if [[ $DO_BUILD == 1 ]]; then fi # Build app - cp config/examples/nrf5340.config .config + cp "$config_app" .config make clean make $MAKE_ARGS cp test-app/image.bin tools/scripts/nrf5340/image_app.bin From 63aa160c9612df77318bf466ce1dc7dec8f330d2 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Tue, 25 Nov 2025 03:03:23 +0100 Subject: [PATCH 2/4] Fix comments --- hal/nrf5340.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hal/nrf5340.h b/hal/nrf5340.h index eda2ba14a8..83aaee167f 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -137,10 +137,10 @@ void sleep_us(uint32_t usec); #define SPU_FLASHREGION_PERM_LOCK (1 << 8) /* The content of this register can't be changed until the next reset */ #define SPU_RAMREGION_PERM(n) (*(volatile uint32_t *)(SPU_BASE + 0x700 + ((n) & 0x3F) * 0x4)) - #define SPU_RAMREGION_PERM_EXEC (1 << 0) /* Allow instruction fetches from flash region */ + #define SPU_RAMREGION_PERM_EXEC (1 << 0) /* Allow instruction fetches from RAM region */ #define SPU_RAMREGION_PERM_WRITE (1 << 1) /* Allow write operation to region */ - #define SPU_RAMREGION_PERM_READ (1 << 2) /* Allow read operation from flash region */ - #define SPU_RAMREGION_PERM_SECATTR (1 << 4) /* Flash region n security attribute is secure */ + #define SPU_RAMREGION_PERM_READ (1 << 2) /* Allow read operation from RAM region */ + #define SPU_RAMREGION_PERM_SECATTR (1 << 4) /* RAM region n security attribute is secure */ #define SPU_RAMREGION_PERM_LOCK (1 << 8) /* The content of this register can't be changed until the next reset */ #define SPU_PERIPHID_PERM(n) (*(volatile uint32_t *)(SPU_BASE + 0x800 + ((n) & 0xFF) * 0x4)) From 9c4732ee8378382171965fe27e87ed32baa87afa Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Tue, 25 Nov 2025 03:18:43 +0100 Subject: [PATCH 3/4] Add new config to GitHub workflows --- .github/workflows/test-configs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 2ed917edef..2260582b5e 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -136,6 +136,12 @@ jobs: arch: arm config-file: ./config/examples/nrf5340.config + nrf5340_app_tz_test: + uses: ./.github/workflows/test-build.yml + with: + arch: arm + config-file: ./config/examples/nrf5340-tz.config + nrf5340_net_test: uses: ./.github/workflows/test-build.yml with: From df49fbf7f56e986dc1af9a036861eca0f3acb344 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Tue, 25 Nov 2025 05:22:33 +0100 Subject: [PATCH 4/4] Fix GPIO pin assignment --- hal/nrf5340.c | 5 ++++- test-app/app_nrf5340.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hal/nrf5340.c b/hal/nrf5340.c index c49ff337d6..282c324417 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -807,10 +807,13 @@ int hal_flash_protect(uint32_t start, uint32_t len) static void periph_unsecure() { /* Unsecure both GPIO ports */ SPU_PERIPHID_PERM(GPIO_PERIPHID) &= ~SPU_PERIPHID_PERM_SECATTR; - //SPU_GPIOPORT_PERM(0) = (1 << 29); SPU_GPIOPORT_PERM(0) = 0; SPU_GPIOPORT_PERM(1) = 0; + /* Assign LED2 GPIO pin to net core; cannot be done by app because MCUSEL + * is only accessible from secure code */ + GPIO_PIN_CNF(0, 29) = (GPIO_CNF_OUT | GPIO_CNF_MCUSEL(1)); + /* Unsecure UARTE0 */ SPU_PERIPHID_PERM(SERIAL0_PERIPHID) &= ~SPU_PERIPHID_PERM_SECATTR; diff --git a/test-app/app_nrf5340.c b/test-app/app_nrf5340.c index 222f5cf733..a75b45cac9 100644 --- a/test-app/app_nrf5340.c +++ b/test-app/app_nrf5340.c @@ -47,8 +47,10 @@ void main(void) uint32_t app_version; GPIO_PIN_CNF(port, pin) = GPIO_CNF_OUT; +#ifndef TZEN /* Allow network core access to P0.29 GPIO */ GPIO_PIN_CNF(0, 29) = (GPIO_CNF_OUT | GPIO_CNF_MCUSEL(1)); +#endif app_version = wolfBoot_current_firmware_version();