From 23ba33140eea700d8e9a6f2f988c46549b8e9214 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Fri, 5 Dec 2025 01:25:32 +0100 Subject: [PATCH] MCXW TrustZone support --- .github/workflows/test-configs.yml | 6 ++ arch.mk | 3 + config/examples/mcxw-tz.config | 52 +++++++++++ hal/mcxw-ns.ld | 54 ++++++++++++ hal/mcxw.c | 133 ++++++++++++++++++++++------- hal/mcxw.ld | 129 ++++++++++++++++------------ test-app/ARM-mcxw-ns.ld | 58 +++++++++++++ test-app/Makefile | 7 +- test-app/app_mcxw.c | 7 +- 9 files changed, 360 insertions(+), 89 deletions(-) create mode 100644 config/examples/mcxw-tz.config create mode 100644 hal/mcxw-ns.ld create mode 100644 test-app/ARM-mcxw-ns.ld diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 5d7495f6b9..b552544d83 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -201,6 +201,12 @@ jobs: arch: arm config-file: ./config/examples/mcxw.config + nxp_mcxw_tz_test: + uses: ./.github/workflows/test-build-mcux-sdk.yml + with: + arch: arm + config-file: ./config/examples/mcxw-tz.config + raspi3_test: uses: ./.github/workflows/test-build.yml with: diff --git a/arch.mk b/arch.mk index 8c470fdb11..460f57d21d 100644 --- a/arch.mk +++ b/arch.mk @@ -661,6 +661,9 @@ endif ifeq ($(TARGET),mcxw) CORTEX_M33=1 + ifneq ($(TZEN),1) + LSCRIPT_IN=hal/$(TARGET)-ns.ld + endif CFLAGS+=\ -I$(MCUXPRESSO_DRIVERS) \ -I$(MCUXPRESSO_DRIVERS)/drivers \ diff --git a/config/examples/mcxw-tz.config b/config/examples/mcxw-tz.config new file mode 100644 index 0000000000..1c90e39fe5 --- /dev/null +++ b/config/examples/mcxw-tz.config @@ -0,0 +1,52 @@ +ARCH?=ARM +TZEN?=1 +TARGET?=mcxw +SIGN?=ECC256 +HASH?=SHA256 +MCUXSDK?=1 +MCUXPRESSO?=$(PWD)/../NXP/mcux-sdk +MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS +MCUXPRESSO_CPU?=MCXW716CMFTA +MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/MCXW716C +DEBUG?=0 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=1 +NO_ARM_ASM=1 +WOLFBOOT_VERSION?=0 +V?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=0 +PKA?=1 + +# 8KB sectors +WOLFBOOT_SECTOR_SIZE?=0x2000 + +# Default configuration +# 32KB boot, 80KB keyvault, 16KB NSC, 60KB partitions, 8KB swap +WOLFBOOT_KEYVAULT_ADDRESS?=0x8000 +WOLFBOOT_KEYVAULT_SIZE?=0x14000 +WOLFBOOT_NSC_ADDRESS?=0x1C000 +WOLFBOOT_NSC_SIZE?=0x4000 +WOLFBOOT_PARTITION_SIZE?=0xF000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x2F000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x3E000 + +# Alternate larger configuration for debugging or ARMASM +# 40KB boot, 80KB keyvault, 8KB NSC, 60KB partitions, 8KB swap +#WOLFBOOT_KEYVAULT_ADDRESS?=0xA000 +#WOLFBOOT_KEYVAULT_SIZE?=0x14000 +#WOLFBOOT_NSC_ADDRESS?=0x1E000 +#WOLFBOOT_NSC_SIZE?=0x2000 +#WOLFBOOT_PARTITION_SIZE?=0xF000 +#WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20000 +#WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x2F000 +#WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x3E000 diff --git a/hal/mcxw-ns.ld b/hal/mcxw-ns.ld new file mode 100644 index 0000000000..9b63118b64 --- /dev/null +++ b/hal/mcxw-ns.ld @@ -0,0 +1,54 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = @BOOTLOADER_PARTITION_SIZE@ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K +} + +SECTIONS +{ + + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + . = 0x200; + *(.keystore*) + *(.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/mcxw.c b/hal/mcxw.c index 1627ac37c6..7fb26b039b 100644 --- a/hal/mcxw.c +++ b/hal/mcxw.c @@ -37,6 +37,8 @@ #include "fsl_flash_api.h" #include "fsl_ccm32k.h" +#include "hal/armv8m_tz.h" + #define FLASH FMU0 /*!< Core clock frequency: 48000000Hz */ @@ -46,6 +48,41 @@ static uint32_t pflash_sector_size = WOLFBOOT_SECTOR_SIZE; uint32_t SystemCoreClock; +#ifdef TZEN +static void hal_sau_init(void) +{ + /* Non-secure callable area */ + sau_init_region(0, WOLFBOOT_NSC_ADDRESS, + WOLFBOOT_NSC_ADDRESS + WOLFBOOT_NSC_SIZE - 1, 1); + + /* Non-secure: application flash area */ + sau_init_region(1, WOLFBOOT_PARTITION_BOOT_ADDRESS, + WOLFBOOT_PARTITION_BOOT_ADDRESS + 2 * WOLFBOOT_PARTITION_SIZE - 1, + 0); + + /* ROM bootloader API */ + sau_init_region(2, 0x14800000, 0x14817FFF, 0); + + /* Non-secure RAM */ + sau_init_region(3, 0x20010000, 0x20015FFF, 0); + + /* Peripherals */ + sau_init_region(4, 0x40000000, 0x4007FFFF, 0); + sau_init_region(5, 0x48000000, 0x48FFFFFF, 0); + + /* Enable SAU */ + SAU_CTRL = SAU_INIT_CTRL_ENABLE; + + /* Enable securefault handler */ + SCB_SHCSR |= SCB_SHCSR_SECUREFAULT_EN; +} + +static void periph_unsecure(void) +{ + GPIOA->PCNS = 0xFFFFFFFF; + GPIOA->ICNS = 0xFFFFFFFF; +} +#endif #ifdef __WOLFBOOT @@ -63,7 +100,9 @@ void __assert_func(const char *a, int b, const char *c, const char *d) void hal_prepare_boot(void) { - +#ifdef TZEN + periph_unsecure(); +#endif } #endif @@ -80,11 +119,39 @@ void hal_init(void) FLASH_Init(&pflash); FLASH_GetProperty(&pflash, kFLASH_PropertyPflash0SectorSize, &pflash_sector_size); + +#if defined(TZEN) && !defined(NONSECURE_APP) + hal_sau_init(); +#endif +} + +static void write_flash_qword(uint32_t *dst, const uint32_t *src) +{ + /* Wait for non-busy */ + while (!(FMU0->FSTAT & 0x00000080)) {} + /* Clear errors */ + FMU0->FSTAT = 0x74; + /* Set command "program phrase" */ + FMU0->FCCOB[0] = 0x24; + /* Start command */ + FMU0->FSTAT = 0x80; + /* Wait for write enabled */ + while (!(FMU0->FSTAT & 0x01000000)) {} + /* Write the 4 words */ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + /* Wait for operation ready to execute */ + while (!(FMU0->FSTAT & 0x80000000)) {} + /* Start operation */ + FMU0->FSTAT = 0x80000000; + /* Wait for completion */ + while (!(FMU0->FSTAT & 0x00000080)) {} } int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) { - int ret; int w = 0; const uint32_t flash_word_size = 16; const uint32_t empty_qword[4] = { @@ -103,33 +170,24 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) ((uint8_t *)aligned_qword)[i] = data[w++]; } if (memcmp(aligned_qword, empty_qword, flash_word_size) != 0) { - ret = FLASH_Program(&pflash, FLASH, address_align, aligned_qword, - flash_word_size); - if (ret != kStatus_Success) - return -1; + write_flash_qword((uint32_t *)address_align, aligned_qword); } address += i; len -= i; } else { + uint32_t i; uint32_t len_align = len - (len & 0x0F); - if (((uint32_t)data + w) & 0x0F) { - uint32_t __attribute__((aligned(16))) aligned_data[4]; - memcpy(aligned_data, (void*)((uint32_t)data + w), len_align); - ret = FLASH_Program(&pflash, FLASH, address, (uint32_t*)data + w, - len_align); - } - else - { - ret = FLASH_Program(&pflash, FLASH, address, (uint32_t*)data + w, - len_align); + + for (i = 0; i < len_align; i += 16) { + write_flash_qword((uint32_t *)(address + i), + (const uint32_t *)(data + w + i)); } - if (ret != kStatus_Success) - return -1; len -= len_align; address += len_align; } } + return 0; } @@ -141,23 +199,38 @@ void RAMFUNCTION hal_flash_lock(void) { } +static void erase_flash_sector(uint32_t *dst) { + /* Wait for non-busy */ + while (!(FMU0->FSTAT & 0x00000080)) {} + /* Clear errors */ + FMU0->FSTAT = 0x74; + /* Set command "erase sector" */ + FMU0->FCCOB[0] = 0x42; + /* Start command */ + FMU0->FSTAT = 0x80; + /* Wait for write enabled */ + while (!(FMU0->FSTAT & 0x01000000)) {} + /* Write 4 words to specify sector to erase */ + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + /* Wait for operation ready to execute */ + while (!(FMU0->FSTAT & 0x80000000)) {} + /* Start operation */ + FMU0->FSTAT = 0x80000000; + /* Wait for completion */ + while (!(FMU0->FSTAT & 0x00000080)) {} +} + int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { - status_t result; if (address % pflash_sector_size) address -= address % pflash_sector_size; while (len > 0) { - result = FLASH_Erase(&pflash, FLASH, address, pflash_sector_size, - kFLASH_ApiEraseKey); - if (kStatus_FLASH_Success != result) - return -1; - - /* Verify sector if it's been erased. */ - result = FLASH_VerifyEraseSector(&pflash, FLASH, address, - pflash_sector_size); - if (kStatus_FLASH_Success != result) - return -1; - len -= pflash_sector_size; + erase_flash_sector((uint32_t *)address); + address += WOLFBOOT_SECTOR_SIZE; + len -= WOLFBOOT_SECTOR_SIZE; } return 0; } diff --git a/hal/mcxw.ld b/hal/mcxw.ld index 0de30f3239..21fbedb68f 100644 --- a/hal/mcxw.ld +++ b/hal/mcxw.ld @@ -1,54 +1,75 @@ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = @BOOTLOADER_PARTITION_SIZE@ - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K -} - -SECTIONS -{ - - .text : - { - _start_text = .; - KEEP(*(.isr_vector)) - . = 0x200; - *(.keystore*) - *(.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); +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = @WOLFBOOT_KEYVAULT_ADDRESS@ - @ARCH_FLASH_OFFSET@ + RAM (rwx) : ORIGIN = 0x30000000, LENGTH = 0x6000 /* 24K */ + RAM_HEAP (rwx) : ORIGIN = 0x30006000, LENGTH = 0x6000 /* 24K */ + RAM_KV (rwx) : ORIGIN = 0x3000C000, 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 +{ + + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + . = 0x200; + *(.keystore*) + *(.text*) + *(.rodata*) + *(.init*) + *(.fini*) + . = ALIGN(4); + _end_text = .; + } > FLASH + + .edidx : + { + . = ALIGN(4); + *(.ARM.exidx*) + } > FLASH + + .gnu.sgstubs : + { + . += 0x400; + . = ALIGN(4); + *(.gnu.sgstubs*) /* Secure Gateway Stubs */ + . = ALIGN(4); + } > FLASH_NSC + + _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); + +_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/test-app/ARM-mcxw-ns.ld b/test-app/ARM-mcxw-ns.ld new file mode 100644 index 0000000000..4a22e1d3ec --- /dev/null +++ b/test-app/ARM-mcxw-ns.ld @@ -0,0 +1,58 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 24K +} + +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 = _end); +PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/test-app/Makefile b/test-app/Makefile index ac8f2dd4b0..65d6f7ce96 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -348,7 +348,12 @@ ifeq ($(TARGET),mcxa) endif ifeq ($(TARGET),mcxw) - LSCRIPT_TEMPLATE=ARM-mcxw.ld + ifeq ($(TZEN),1) + LSCRIPT_TEMPLATE=ARM-mcxw-ns.ld + CFLAGS:=$(filter-out -mcmse, $(CFLAGS)) + else + LSCRIPT_TEMPLATE=ARM-mcxw.ld + endif APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o APP_OBJS+=$(MCUXPRESSO)/drivers/gpio/fsl_gpio.o APP_OBJS+=$(MCUXPRESSO)/drivers/spc/fsl_spc.o diff --git a/test-app/app_mcxw.c b/test-app/app_mcxw.c index 6738fad4c1..ad209376c2 100644 --- a/test-app/app_mcxw.c +++ b/test-app/app_mcxw.c @@ -75,17 +75,16 @@ void main(void) gpio_portA_init(19); gpio_portA_init(20); - hal_init(); if (bootVer == 1) { + wolfBoot_update_trigger(); /* Blue LED ON, GPIOA port A pin 20 */ GPIO_PinWrite(GPIOA, 20, 0); - wolfBoot_update_trigger(); } else { - /* Green LED ON, GPIOA port A pin 19 */ - GPIO_PinWrite(GPIOA, 19, 0); /* mark boot successful */ wolfBoot_success(); + /* Green LED ON, GPIOA port A pin 19 */ + GPIO_PinWrite(GPIOA, 19, 0); } /* busy wait */