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
73 changes: 73 additions & 0 deletions .github/workflows/mcxn-emulator-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: mcxn-emulator-tests

on:
push:
pull_request:

jobs:
# Boot, update and rollback on the m33mu MCXN947 model with the
# TrustZone secure-application (wolfTrust) handoff config.
mcxn-emulator-tests:
runs-on: ubuntu-latest
container:
image: ghcr.io/wolfssl/wolfboot-ci-m33mu:latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
config: [mcxn-tz-wolftrust]
steps:
- uses: actions/checkout@v4

- name: Init submodules
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git submodule update --init --single-branch

- uses: actions/checkout@v4
with:
repository: nxp-mcuxpresso/CMSIS_5
path: CMSIS_5

- name: Cache MCUXpresso SDK
id: cache-mcuxpresso
uses: actions/cache@v4
with:
path: |
mcuxpresso-sdk
venv
key: mcuxpresso-sdk-frdmmcxn947-emu-${{ hashFiles('.github/workflows/mcxn-emulator-tests.yml') }}

- name: Setup MCUXpresso SDK
if: steps.cache-mcuxpresso.outputs.cache-hit != 'true'
run: |
python3 -m venv venv
. venv/bin/activate
pip install west
west init -m https://github.com/nxp-mcuxpresso/mcuxsdk-manifests.git mcuxpresso-sdk
cd mcuxpresso-sdk
sed -i '/se_hostlib\|emwin/d' manifests/boards/frdmmcxn947.yml
west update_board --set board frdmmcxn947

- name: Use the MCUXpresso SDK for the wolfBoot build
run: |
echo "MCUXSDK=1" >> "$GITHUB_ENV"
echo "MCUXPRESSO=$GITHUB_WORKSPACE/mcuxpresso-sdk/mcuxsdk" >> "$GITHUB_ENV"
echo "MCUXPRESSO_CMSIS=$GITHUB_WORKSPACE/CMSIS_5/CMSIS" >> "$GITHUB_ENV"

- name: Configure ${{ matrix.config }} and build wolfboot
run: |
cp config/examples/${{ matrix.config }}.config .config
make wolfboot.bin

- name: Run emu test (${{ matrix.config }})
working-directory: test-app/emu-test-apps
run: |
BOOT_TIMEOUT=30 UPDATE_TIMEOUT=60 REBOOT_TIMEOUT=30 ./test.sh

- name: Upload emulator logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: mcxn-emu-logs-${{ matrix.config }}
path: test-app/emu-test-apps/mcxn947/*.log
7 changes: 7 additions & 0 deletions .github/workflows/test-configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,13 @@ jobs:
config-file: ./config/examples/mcxn-tz-psa-hw.config
board-name: frdmmcxn947

nxp_mcxn_tz_wolftrust_test:
uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml
with:
arch: arm
config-file: ./config/examples/mcxn-tz-wolftrust.config
board-name: frdmmcxn947

nxp_rw612_test:
uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml
with:
Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,14 @@ ifeq ($(TARGET),imx_rt7xx)
MAIN_TARGET:=wolfboot.bin test-app/image_v1_signed.bin
endif
endif

ifeq ($(TARGET),mcxn)
# The secure-app partitions sit at the Secure flash alias, 256MB above the
# flash offsets, and the payload is a Secure runtime rather than a test app.
ifeq ($(WOLFBOOT_SECURE_APP),1)
MAIN_TARGET:=wolfboot.bin
endif
endif
endif # TZEN=1

ifeq ($(TARGET),pic32cz)
Expand Down
48 changes: 48 additions & 0 deletions config/examples/mcxn-tz-wolftrust.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
ARCH?=ARM
TZEN?=1
TARGET?=mcxn
SIGN?=ECC256
HASH?=SHA256
MCUXSDK?=1
MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/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
IMAGE_HEADER_SIZE?=1024
WOLFCRYPT_TZ?=0

WOLFBOOT_SECURE_APP?=1
WOLFBOOT_SECURE_HANDOFF_ADDRESS?=0x30030000

# 8KB sectors
WOLFBOOT_SECTOR_SIZE?=0x2000

# 256KB wolfBoot region (bootloader + empty NSC), partitions at the Secure
# flash alias: 256KB boot, 256KB update in bank 1, 8KB swap
BOOTLOADER_PARTITION_SIZE?=0x40000
WOLFBOOT_KEYVAULT_ADDRESS?=0x20000
WOLFBOOT_KEYVAULT_SIZE?=0
WOLFBOOT_NSC_ADDRESS?=0x20000
WOLFBOOT_NSC_SIZE?=0x2000
WOLFBOOT_PARTITION_SIZE?=0x40000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x10040000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x10180000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x101C0000
7 changes: 6 additions & 1 deletion docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -7567,14 +7567,19 @@ cp config/examples/mcxn.config .config`
make
```

We provide three configuration files:
We provide these configuration files:
- `mcxn.config`: basic configuration file; both wolfBoot and your application
run in secure world.
- `mcxn-tz.config`: wolfBoot runs in secure world, your application runs in
non-secure world.
- `mcxn-wolfcrypt-tz.config`: same as above, but also includes a non-secure
callable (NSC) wolfPKCS11 API to perform crypto operations via wolfCrypt and
access a secure keyvault provided by wolfBoot.
- `mcxn-tz-wolftrust.config`: wolfBoot hands off to a signed secure application
(for example wolfTrust) that stays in the secure world, with the measured-boot
record at `0x30030000` (see [Secure Application Handoff](secure_app_handoff.md)).
The partitions are at the secure flash alias (`0x10040000` boot, `0x10180000`
update).

### MCX N: Loading the firmware

Expand Down
8 changes: 8 additions & 0 deletions docs/secure_app_handoff.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ derives the PSA lifecycle from the flash product state and the debug
authentication status (`hal/stm32h5_lifecycle.h`), and `hal/stm32_tz.c` keeps
the whole SRAM1 window and the secure app flash Secure across the handoff.

## MCXN947

`config/examples/mcxn-tz-wolftrust.config` puts the record at `0x30030000` and
the partitions at the Secure flash alias. `hal/mcxn.c` uses the shared
`hal_sau_init()` (no Non-secure regions), leaves every peripheral Secure, and
reports the lifecycle through the weak default. `mcxn-emulator-tests.yml` runs
boot, update and rollback on the m33mu MCXN947 model.

## Tests

- `tools/unit-tests/unit-secure-handoff.c` — record layout, the builder, and the
Expand Down
23 changes: 21 additions & 2 deletions hal/mcxn.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <target.h>
#include "fsl_common.h"
#include "image.h"
#include "hal.h"

#include "clock_config.h"
#include "fsl_clock.h"
Expand Down Expand Up @@ -172,7 +173,23 @@ static flash_config_t pflash;
static uint32_t pflash_sector_size = WOLFBOOT_SECTOR_SIZE;
uint32_t SystemCoreClock;

#ifdef TZEN
#define MCXN_FLASH_S_ALIAS 0x10000000U
#define MCXN_FLASH_SIZE 0x00200000U

/* Partitions may be linked at the Secure flash alias; the ROM flash API
* takes the flash offset. */
static uint32_t RAMFUNCTION mcxn_flash_offset(uint32_t address)
{
if ((address >= MCXN_FLASH_S_ALIAS) &&
(address < (MCXN_FLASH_S_ALIAS + MCXN_FLASH_SIZE))) {
address -= MCXN_FLASH_S_ALIAS;
}
return address;
}

/* A secure application stays Secure across the jump: it uses the shared
* hal_sau_init() (no Non-secure regions) and keeps every peripheral Secure. */
#if defined(TZEN) && !defined(WOLFBOOT_SECURE_APP)
static void hal_sau_init(void)
{
/* Non-secure callable area */
Expand Down Expand Up @@ -249,7 +266,7 @@ void __assert_func(const char *a, int b, const char *c, const char *d)

void hal_prepare_boot(void)
{
#ifdef TZEN
#if defined(TZEN) && !defined(WOLFBOOT_SECURE_APP)
periph_unsecure();
#endif
}
Expand All @@ -260,6 +277,7 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
const uint32_t word_size = 4U;
int written = 0;

address = mcxn_flash_offset(address);
while (len > 0) {
if ((address & (word_size - 1U)) || (len < (int)word_size)) {
uint32_t aligned = address & ~(word_size - 1U);
Expand Down Expand Up @@ -316,6 +334,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
sector_size = WOLFBOOT_SECTOR_SIZE;
}

address = mcxn_flash_offset(address);
/* Drive the loop from the end of the requested range so the tail is
* erased when the start address is rounded back to a sector. */
end = address + (uint32_t)len;
Expand Down
23 changes: 19 additions & 4 deletions test-app/emu-test-apps/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,27 +85,42 @@ else ifeq ($(TARGET),m2354)
else ifeq ($(TARGET),imx_rt7xx)
EMU_DIR=imxrt700
EMU_CPU=imxrt700
else ifeq ($(TARGET),mcxn)
EMU_DIR=mcxn947
EMU_CPU=mcxn947
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|m2354|imx_rt7xx)
$(error Unsupported or unset TARGET=$(TARGET). Use TARGET=stm32h563|stm32h5|stm32u585|stm32u5|stm32l552|stm32l5|nrf5340|mcxw|m2354|imx_rt7xx|mcxn)
endif

EMU_PATH=$(WOLFBOOT_ROOT)/test-app/emu-test-apps/$(EMU_DIR)

.PHONY: all clean test-emu sign-emu run-emu
.PHONY: all clean test-emu sign-emu run-emu check-standalone

ifeq ($(WOLFBOOT_SECURE_APP),1)
EMU_SUB_ARGS=SECURE_HANDOFF_ADDRESS=$(WOLFBOOT_SECURE_HANDOFF_ADDRESS)
endif

all:
$(MAKE) -C $(EMU_PATH) clean app.bin
$(MAKE) -C $(EMU_PATH) clean app.bin $(EMU_SUB_ARGS)

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
# run-emu boots the signed app without wolfBoot; a secure-app payload needs
# wolfBoot's UART setup and handoff record, so it only runs under test.sh.
check-standalone:
ifeq ($(WOLFBOOT_SECURE_APP),1)
@echo "run-emu: secure-app configs boot through wolfBoot; use test.sh" >&2
@exit 1
endif

run-emu: check-standalone 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 \
Expand Down
Loading
Loading