From 438c250288b0e0b24a8f71b1f848d756789f1902 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Thu, 22 Jan 2026 18:30:54 +0100 Subject: [PATCH] MCXN non-TrustZone + TrustZone port --- CMakeLists.txt | 1 + arch.mk | 39 +++- config/examples/mcxn-tz.config | 55 ++++++ config/examples/mcxn.config | 46 +++++ hal/mcxn-ns.ld | 54 ++++++ hal/mcxn.c | 331 +++++++++++++++++++++++++++++++++ hal/mcxn.ld | 75 ++++++++ test-app/ARM-mcxn-ns.ld | 58 ++++++ test-app/ARM-mcxn.ld | 58 ++++++ test-app/Makefile | 20 ++ test-app/app_mcxn.c | 122 ++++++++++++ 11 files changed, 858 insertions(+), 1 deletion(-) create mode 100644 config/examples/mcxn-tz.config create mode 100644 config/examples/mcxn.config create mode 100644 hal/mcxn-ns.ld create mode 100644 hal/mcxn.c create mode 100644 hal/mcxn.ld create mode 100644 test-app/ARM-mcxn-ns.ld create mode 100644 test-app/ARM-mcxn.ld create mode 100644 test-app/app_mcxn.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 210bedf4..cc924d03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -390,6 +390,7 @@ if(NOT DEFINED ARM_TARGETS) lpc54606j512 mcxa mcxw + mcxn nrf52 nrf52840 nrf5340 diff --git a/arch.mk b/arch.mk index d4467bf8..da526591 100644 --- a/arch.mk +++ b/arch.mk @@ -339,7 +339,7 @@ else ifeq ($(WOLFCRYPT_TZ),1) CORTEXM_ARM_EXTRA_OBJS= CORTEXM_ARM_EXTRA_CFLAGS= - SECURE_OBJS+=./src/wc_callable.o + SECURE_OBJS+=./src/wc_callable.o $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/random.o CFLAGS+=-DWOLFCRYPT_SECURE_MODE SECURE_LDFLAGS+=-Wl,--cmse-implib -Wl,--out-implib=./src/wc_secure_calls.o endif @@ -732,6 +732,43 @@ ifeq ($(TARGET),mcxw) $(MCUXPRESSO_DRIVERS)/drivers/fsl_romapi.o endif +ifeq ($(TARGET),mcxn) + CORTEX_M33=1 + ifneq ($(TZEN),1) + LSCRIPT_IN=hal/$(TARGET)-ns.ld + endif + CFLAGS+=\ + -I$(MCUXPRESSO_DRIVERS) \ + -I$(MCUXPRESSO_DRIVERS)/drivers \ + -I$(MCUXPRESSO_DRIVERS)/drivers/romapi/flash \ + -I$(MCUXPRESSO_DRIVERS)/../periph \ + -I$(MCUXPRESSO) \ + -I$(MCUXPRESSO)/drivers \ + -I$(MCUXPRESSO)/drivers/gpio \ + -I$(MCUXPRESSO)/drivers/port \ + -I$(MCUXPRESSO)/drivers/common \ + -I$(MCUXPRESSO)/drivers/lpflexcomm \ + -I$(MCUXPRESSO)/drivers/lpuart \ + -I$(MCUXPRESSO_PROJECT_TEMPLATE) \ + -I$(MCUXPRESSO_CMSIS)/Include \ + -I$(MCUXPRESSO_CMSIS)/Core/Include + CFLAGS+=-DCPU_$(MCUXPRESSO_CPU) -DDEBUG_CONSOLE_ASSERT_DISABLE=1 + CFLAGS+=-Wno-old-style-declaration + CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33 -U__ARM_FEATURE_DSP + LDFLAGS+=-mcpu=cortex-m33 + OBJS+=\ + $(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \ + $(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o \ + $(MCUXPRESSO_DRIVERS)/drivers/romapi/flash/src/fsl_flash.o + + ifeq ($(DEBUG_UART),1) + OBJS+=\ + $(MCUXPRESSO)/drivers/lpflexcomm/fsl_lpflexcomm.o \ + $(MCUXPRESSO)/drivers/lpuart/fsl_lpuart.o \ + $(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o + endif +endif + ifeq ($(TARGET),nrf5340) ifneq ($(TZEN), 1) LSCRIPT_IN=hal/$(TARGET)-ns.ld diff --git a/config/examples/mcxn-tz.config b/config/examples/mcxn-tz.config new file mode 100644 index 00000000..9818286e --- /dev/null +++ b/config/examples/mcxn-tz.config @@ -0,0 +1,55 @@ +ARCH?=ARM +TZEN?=1 +TARGET?=mcxn +SIGN?=ECC384 +HASH?=SHA384 +MCUXSDK?=1 +MCUXPRESSO?=$(PWD)/../NXP/mcuxsdk/mcuxsdk +MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS +MCUXPRESSO_CPU?=MCXN947VDF_cm33_core0 +MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/MCX/MCXN/MCXN947 +MCUXPRESSO_PROJECT_TEMPLATE?=$(MCUXPRESSO)/examples/_boards/frdmmcxn947/project_template +DEBUG?=0 +DEBUG_UART?=1 +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 +WOLFCRYPT_TZ?=1 + +# 8KB sectors +WOLFBOOT_SECTOR_SIZE?=0x2000 + +# Default configuration +# 64KB boot, 80KB keyvault, 8KB NSC, 60KB partitions, 8KB swap +WOLFBOOT_KEYVAULT_ADDRESS?=0x10000 +WOLFBOOT_KEYVAULT_SIZE?=0x14000 +WOLFBOOT_NSC_ADDRESS?=0x24000 +WOLFBOOT_NSC_SIZE?=0x2000 +WOLFBOOT_PARTITION_SIZE?=0xF000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x26000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x35000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x44000 + +# Alternate larger configuration for debugging or ARMASM +# 128KB boot, 80KB keyvault, 8KB NSC, 60KB partitions, 8KB swap +#WOLFBOOT_KEYVAULT_ADDRESS?=0x20000 +#WOLFBOOT_KEYVAULT_SIZE?=0x14000 +#WOLFBOOT_NSC_ADDRESS?=0x34000 +#WOLFBOOT_NSC_SIZE?=0x2000 +#WOLFBOOT_PARTITION_SIZE?=0xF000 +#WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x36000 +#WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x45000 +#WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x54000 diff --git a/config/examples/mcxn.config b/config/examples/mcxn.config new file mode 100644 index 00000000..2d3662ae --- /dev/null +++ b/config/examples/mcxn.config @@ -0,0 +1,46 @@ +ARCH?=ARM +TZEN?=0 +TARGET?=mcxn +SIGN?=ECC384 +HASH?=SHA384 +MCUXSDK?=1 +MCUXPRESSO?=$(PWD)/../NXP/mcuxsdk/mcuxsdk +MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS +MCUXPRESSO_CPU?=MCXN947VDF_cm33_core0 +MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/MCX/MCXN/MCXN947 +MCUXPRESSO_PROJECT_TEMPLATE?=$(MCUXPRESSO)/examples/_boards/frdmmcxn947/project_template +DEBUG?=0 +DEBUG_UART?=1 +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 +# 40KB boot, 44KB partitions, 8KB swap +WOLFBOOT_PARTITION_SIZE?=0xB000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xA000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x15000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x20000 + +# Alternate larger configuration for debugging or ARMASM +# 64KB boot, 64KB partitions, 8KB swap +#WOLFBOOT_PARTITION_SIZE?=0x10000 +#WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x12000 +#WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x22000 +#WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x32000 diff --git a/hal/mcxn-ns.ld b/hal/mcxn-ns.ld new file mode 100644 index 00000000..723276d3 --- /dev/null +++ b/hal/mcxn-ns.ld @@ -0,0 +1,54 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = @BOOTLOADER_PARTITION_SIZE@ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K +} + +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/mcxn.c b/hal/mcxn.c new file mode 100644 index 00000000..e91d20e8 --- /dev/null +++ b/hal/mcxn.c @@ -0,0 +1,331 @@ +/* mcxn.c + * + * Copyright (C) 2025 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include +#include "fsl_common.h" +#include "image.h" + +#include "clock_config.h" +#include "fsl_clock.h" +#include "fsl_flash.h" +#include "fsl_gpio.h" +#include "fsl_lpflexcomm.h" +#include "fsl_lpuart.h" +#include "fsl_port.h" +#include "fsl_reset.h" +#include "loader.h" +#include "PERI_AHBSC.h" + +#ifdef TZEN +#include "hal/armv8m_tz.h" +#endif + +static flash_config_t pflash; +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 (boot partition) */ + sau_init_region(1, WOLFBOOT_PARTITION_BOOT_ADDRESS, + WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - 1, + 0); + + /* Non-secure RAM */ + sau_init_region(2, 0x20020000, 0x20025FFF, 0); + + /* Peripherals */ + sau_init_region(3, 0x40000000, 0x4005FFFF, 0); + sau_init_region(4, 0x40080000, 0x400DFFFF, 0); + sau_init_region(5, 0x40100000, 0x4013FFFF, 0); + + /* Enable SAU */ + SAU_CTRL = SAU_INIT_CTRL_ENABLE; + + /* Enable securefault handler */ + SCB_SHCSR |= SCB_SHCSR_SECUREFAULT_EN; +} + +static void periph_unsecure(void) +{ + CLOCK_EnableClock(kCLOCK_Gpio0); + CLOCK_EnableClock(kCLOCK_Gpio1); + CLOCK_EnableClock(kCLOCK_Port0); + CLOCK_EnableClock(kCLOCK_Port1); + + GPIO_EnablePinControlNonSecure(GPIO0, (1UL << 10) | (1UL << 27)); + GPIO_EnablePinControlNonSecure(GPIO1, (1UL << 2) | (1UL << 8) | (1UL << 9)); +} +#endif + +void hal_init(void) +{ +#ifdef __WOLFBOOT + /* Single-byte RAM writes unpredictably fail when ECC is enabled */ + SYSCON->ECC_ENABLE_CTRL = 0; + BOARD_InitBootClocks(); +#ifdef DEBUG_UART + uart_init(); +#endif +#endif + +#if defined(__WOLFBOOT) || !defined(TZEN) + memset(&pflash, 0, sizeof(pflash)); + FLASH_Init(&pflash); + FLASH_GetProperty(&pflash, kFLASH_PropertyPflashSectorSize, + &pflash_sector_size); +#endif + +#if defined(TZEN) && !defined(NONSECURE_APP) + hal_sau_init(); +#endif +} + +#ifdef __WOLFBOOT +/* Assert hook needed by SDK assert() macro. */ +void __assert_func(const char *a, int b, const char *c, const char *d) +{ + (void)a; + (void)b; + (void)c; + (void)d; + while (1) { + } +} + +void hal_prepare_boot(void) +{ +#ifdef TZEN + periph_unsecure(); +#endif +} +#endif + +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + const uint32_t word_size = 4U; + int written = 0; + + while (len > 0) { + if ((address & (word_size - 1U)) || (len < (int)word_size)) { + uint32_t aligned = address & ~(word_size - 1U); + uint32_t word; + uint32_t offset = address - aligned; + uint32_t copy = word_size - offset; + + if (copy > (uint32_t)len) { + copy = (uint32_t)len; + } + + memcpy(&word, (void *)aligned, word_size); + memcpy(((uint8_t *)&word) + offset, data + written, copy); + if (FLASH_Program(&pflash, aligned, (uint8_t *)&word, word_size) != + kStatus_FLASH_Success) { + return -1; + } + + address += copy; + len -= (int)copy; + written += (int)copy; + } + else { + uint32_t chunk = (uint32_t)len & ~(word_size - 1U); + + if (FLASH_Program(&pflash, address, (uint8_t *)data + written, + chunk) != kStatus_FLASH_Success) { + return -1; + } + + address += chunk; + len -= (int)chunk; + written += (int)chunk; + } + } + + return 0; +} + +void RAMFUNCTION hal_flash_unlock(void) +{ +} + +void RAMFUNCTION hal_flash_lock(void) +{ +} + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + uint32_t sector_size = pflash_sector_size; + + if (sector_size == 0U) { + sector_size = WOLFBOOT_SECTOR_SIZE; + } + + if ((address % sector_size) != 0U) { + address -= address % sector_size; + } + + while (len > 0) { + if (FLASH_Erase(&pflash, address, sector_size, + kFLASH_ApiEraseKey) != kStatus_FLASH_Success) { + return -1; + } + if (FLASH_VerifyErase(&pflash, address, sector_size) != + kStatus_FLASH_Success) { + return -1; + } + address += sector_size; + len -= (int)sector_size; + } + + return 0; +} + +#ifdef WOLFCRYPT_SECURE_MODE +/* These functions are stubs for now, because the MCUXpresso SDK doesn't + * implement drivers for the MCXN's TRNG. */ +void hal_trng_init(void) +{ +} + +void hal_trng_fini(void) +{ +} + +int hal_trng_get_entropy(unsigned char *out, unsigned int len) +{ + (void)out; + (void)len; + return -1; +} +#endif + +void uart_init(void) +{ + lpuart_config_t config; + const port_pin_config_t uart_rx = { + .pullSelect = kPORT_PullUp, +#if defined(FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE) && FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE + .pullValueSelect = kPORT_LowPullResistor, +#endif +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE + .slewRate = kPORT_FastSlewRate, +#endif +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER + .passiveFilterEnable = kPORT_PassiveFilterDisable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN + .openDrainEnable = kPORT_OpenDrainDisable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH + .driveStrength = kPORT_LowDriveStrength, +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1 + .driveStrength1 = kPORT_NormalDriveStrength, +#endif + .mux = kPORT_MuxAlt2, +#if defined(FSL_FEATURE_PORT_HAS_INPUT_BUFFER) && FSL_FEATURE_PORT_HAS_INPUT_BUFFER + .inputBuffer = kPORT_InputBufferEnable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_INVERT_INPUT) && FSL_FEATURE_PORT_HAS_INVERT_INPUT + .invertInput = kPORT_InputNormal, +#endif +#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK + .lockRegister = kPORT_UnlockRegister +#endif + }; + const port_pin_config_t uart_tx = { + .pullSelect = kPORT_PullDisable, +#if defined(FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE) && FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE + .pullValueSelect = kPORT_LowPullResistor, +#endif +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE + .slewRate = kPORT_FastSlewRate, +#endif +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER + .passiveFilterEnable = kPORT_PassiveFilterDisable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN + .openDrainEnable = kPORT_OpenDrainDisable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH + .driveStrength = kPORT_LowDriveStrength, +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1 + .driveStrength1 = kPORT_NormalDriveStrength, +#endif + .mux = kPORT_MuxAlt2, +#if defined(FSL_FEATURE_PORT_HAS_INPUT_BUFFER) && FSL_FEATURE_PORT_HAS_INPUT_BUFFER + .inputBuffer = kPORT_InputBufferEnable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_INVERT_INPUT) && FSL_FEATURE_PORT_HAS_INVERT_INPUT + .invertInput = kPORT_InputNormal, +#endif +#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK + .lockRegister = kPORT_UnlockRegister +#endif + }; + + CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1U); + CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); + CLOCK_EnableClock(kCLOCK_LPFlexComm4); + RESET_ClearPeripheralReset(kFC4_RST_SHIFT_RSTn); + CLOCK_EnableClock(kCLOCK_Port1); + + PORT_SetPinConfig(PORT1, 8U, &uart_rx); + PORT_SetPinConfig(PORT1, 9U, &uart_tx); + + (void)LP_FLEXCOMM_Init(4U, LP_FLEXCOMM_PERIPH_LPUART); + LPUART_GetDefaultConfig(&config); + config.baudRate_Bps = 115200U; + config.enableTx = true; + config.enableRx = true; + (void)LPUART_Init(LPUART4, &config, 12000000U); +} + +void uart_write(const char *buf, unsigned int sz) +{ + const char *line; + unsigned int line_sz; + + while (sz > 0) { + line = memchr(buf, '\n', sz); + if (line == NULL) { + (void)LPUART_WriteBlocking(LPUART4, (const uint8_t *)buf, sz); + break; + } + line_sz = (unsigned int)(line - buf); + if (line_sz > sz - 1U) { + line_sz = sz - 1U; + } + (void)LPUART_WriteBlocking(LPUART4, (const uint8_t *)buf, line_sz); + (void)LPUART_WriteBlocking(LPUART4, (const uint8_t *)"\r\n", 2U); + buf = line + 1; + sz -= line_sz + 1U; + } +} diff --git a/hal/mcxn.ld b/hal/mcxn.ld new file mode 100644 index 00000000..97db19c4 --- /dev/null +++ b/hal/mcxn.ld @@ -0,0 +1,75 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = @WOLFBOOT_KEYVAULT_ADDRESS@ - @ARCH_FLASH_OFFSET@ + RAM (rwx) : ORIGIN = 0x30000000, LENGTH = 0x10000 /* 64K */ + RAM_HEAP (rwx) : ORIGIN = 0x30010000, LENGTH = 0xC000 /* 48K */ + RAM_KV (rwx) : ORIGIN = 0x3001C000, 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-mcxn-ns.ld b/test-app/ARM-mcxn-ns.ld new file mode 100644 index 00000000..f07640c2 --- /dev/null +++ b/test-app/ARM-mcxn-ns.ld @@ -0,0 +1,58 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + RAM (rwx) : ORIGIN = 0x20020000, 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/ARM-mcxn.ld b/test-app/ARM-mcxn.ld new file mode 100644 index 00000000..f1b38724 --- /dev/null +++ b/test-app/ARM-mcxn.ld @@ -0,0 +1,58 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K +} + +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 d2e39d21..ccd8e27b 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -372,6 +372,26 @@ ifeq ($(TARGET),mcxw) LDFLAGS+=--specs=nosys.specs endif +ifeq ($(TARGET),mcxn) + ifeq ($(TZEN),1) + LSCRIPT_TEMPLATE=ARM-mcxn-ns.ld + CFLAGS:=$(filter-out -mcmse, $(CFLAGS)) + else + LSCRIPT_TEMPLATE=ARM-mcxn.ld + endif + APP_OBJS+=\ + $(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o \ + $(MCUXPRESSO)/drivers/gpio/fsl_gpio.o \ + $(MCUXPRESSO)/drivers/lpflexcomm/fsl_lpflexcomm.o \ + $(MCUXPRESSO)/drivers/lpuart/fsl_lpuart.o \ + $(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o \ + $(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \ + $(MCUXPRESSO_DRIVERS)/drivers/romapi/flash/src/fsl_flash.o + ifeq (,$(findstring nosys.specs,$(LDFLAGS))) + LDFLAGS+=--specs=nosys.specs + endif +endif + ifeq ($(TARGET),imx_rt) LDFLAGS+=\ -mcpu=cortex-m7 -Wall --specs=nosys.specs -fno-common -ffunction-sections -fdata-sections \ diff --git a/test-app/app_mcxn.c b/test-app/app_mcxn.c new file mode 100644 index 00000000..9a0a97f8 --- /dev/null +++ b/test-app/app_mcxn.c @@ -0,0 +1,122 @@ +/* app_mcxn.c + * + * Minimal test application scaffold for NXP MCXN targets. + * + * Copyright (C) 2025 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include "fsl_clock.h" +#include "fsl_gpio.h" +#include "fsl_port.h" + +#include "target.h" +#include "wolfboot/wolfboot.h" +#include "printf.h" + +extern void hal_init(void); + +static void gpio_init_output(GPIO_Type *gpio, PORT_Type *port, + clock_ip_name_t gpio_clock, + clock_ip_name_t port_clock, uint32_t pin, + uint8_t initial_level) +{ + const port_pin_config_t pin_config = { + .pullSelect = kPORT_PullDisable, +#if defined(FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE) && FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE + .pullValueSelect = kPORT_LowPullResistor, +#endif +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE + .slewRate = kPORT_FastSlewRate, +#endif +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER + .passiveFilterEnable = kPORT_PassiveFilterDisable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN + .openDrainEnable = kPORT_OpenDrainDisable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH + .driveStrength = kPORT_LowDriveStrength, +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1 + .driveStrength1 = kPORT_LowDriveStrength, +#endif + .mux = kPORT_MuxAlt0, +#if defined(FSL_FEATURE_PORT_HAS_INPUT_BUFFER) && FSL_FEATURE_PORT_HAS_INPUT_BUFFER + .inputBuffer = kPORT_InputBufferEnable, +#endif +#if defined(FSL_FEATURE_PORT_HAS_INVERT_INPUT) && FSL_FEATURE_PORT_HAS_INVERT_INPUT + .invertInput = kPORT_InputNormal, +#endif +#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK + .lockRegister = kPORT_UnlockRegister +#endif + }; + const gpio_pin_config_t gpio_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = initial_level, + }; + + CLOCK_EnableClock(gpio_clock); + CLOCK_EnableClock(port_clock); + GPIO_PinInit(gpio, pin, &gpio_config); + PORT_SetPinConfig(port, pin, &pin_config); +} + +void main(void) +{ + uint32_t boot_ver; + + hal_init(); + +#ifdef WOLFCRYPT_SECURE_MODE + boot_ver = wolfBoot_nsc_current_firmware_version(); +#else + boot_ver = wolfBoot_current_firmware_version(); +#endif + + wolfBoot_printf("Hello from firmware version %d\n", boot_ver); + + if (boot_ver == 1) { + /* Red off */ + gpio_init_output(GPIO0, PORT0, kCLOCK_Gpio0, kCLOCK_Port0, 10U, 1U); + /* Green off */ + gpio_init_output(GPIO0, PORT0, kCLOCK_Gpio0, kCLOCK_Port0, 27U, 1U); + /* Blue on */ + gpio_init_output(GPIO1, PORT1, kCLOCK_Gpio1, kCLOCK_Port1, 2U, 0U); + } + else { + /* Red off */ + gpio_init_output(GPIO0, PORT0, kCLOCK_Gpio0, kCLOCK_Port0, 10U, 1U); + /* Green on */ + gpio_init_output(GPIO0, PORT0, kCLOCK_Gpio0, kCLOCK_Port0, 27U, 0U); + /* Blue off */ + gpio_init_output(GPIO1, PORT1, kCLOCK_Gpio1, kCLOCK_Port1, 2U, 1U); + +#ifdef WOLFCRYPT_SECURE_MODE + wolfBoot_nsc_success(); +#else + wolfBoot_success(); +#endif + } + + while (1) { + __asm__ volatile ("wfi"); + } +}