Skip to content

Commit a3bc806

Browse files
SebastianBoenordicjm
authored andcommitted
samples: ironside_se: Add sample that protects periphconf
Add a sample that demonstrates how to protect periphconf using PROTECTEDMEM. Signed-off-by: Sebastian Bøe <[email protected]>
1 parent 649ebf2 commit a3bc806

File tree

12 files changed

+272
-0
lines changed

12 files changed

+272
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.20.0)
8+
9+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
10+
11+
project(protectedmem_periphconf)
12+
13+
target_sources(app PRIVATE src/main.c)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
.. _protectedmem_periphconf_sample:
2+
3+
Protected Memory with PERIPHCONF Partition
4+
##########################################
5+
6+
.. contents::
7+
:local:
8+
:depth: 2
9+
10+
This sample demonstrates how to protect the PERIPHCONF Partition using UICR.PROTECTEDMEM.
11+
12+
Requirements
13+
************
14+
15+
The sample supports the following development kit:
16+
17+
.. table-from-sample-yaml::
18+
19+
Overview
20+
********
21+
22+
The sample relocates the ``periphconf_partition`` right after ``cpuapp_boot_partition`` and configures PROTECTEDMEM to cover both partitions.
23+
When protected memory is modified, the integrity check fails on the next boot, causing |ISE| to boot the secondary firmware instead of the main application.
24+
25+
Building and running
26+
*********************
27+
28+
.. |sample path| replace:: :file:`samples/ironside_se/protectedmem_periphconf`
29+
30+
.. include:: /includes/build_and_run.txt
31+
32+
Testing
33+
*******
34+
35+
After programming the sample to your development kit, complete the following steps to test it:
36+
37+
1. |connect_terminal|
38+
#. Reset the development kit.
39+
40+
The application writes a test pattern to protected memory and then reboots.
41+
On the next boot, if protection works correctly, the secondary firmware boots instead of the main application, indicating that the integrity check detected the modification.
42+
43+
Configuration
44+
*************
45+
46+
The sample uses the following key configurations:
47+
48+
Device Tree Overlay
49+
The ``app.overlay`` file relocates the ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition`` at offset 0x40000.
50+
The ``sysbuild.cmake`` file applies this same overlay to the UICR image so both images see the same partition layout.
51+
52+
Kconfig Configuration
53+
The ``sysbuild/uicr.conf`` file configures the PROTECTEDMEM size to 72KB (73728 bytes) to cover both ``cpuapp_boot_partition`` (64KB) and ``periphconf_partition`` (8KB).
54+
55+
Secondary Firmware
56+
The sample includes a secondary firmware (in the ``secondary/`` directory) that boots automatically when the PROTECTEDMEM integrity check fails.
57+
The secondary firmware is enabled via ``CONFIG_GEN_UICR_SECONDARY=y`` in ``sysbuild/uicr.conf`` and is built as part of the sysbuild process (configured in ``sysbuild.cmake``).
58+
59+
Dependencies
60+
************
61+
62+
This sample uses the following |NCS| subsystems:
63+
64+
* UICR generation - Configures UICR.PROTECTEDMEM to protect the memory region and UICR.SECONDARY to enable secondary firmware boot
65+
* Sysbuild - Enables building the UICR image and secondary firmware with the protected memory configuration
66+
67+
In addition, it uses the following Zephyr subsystems:
68+
69+
* :ref:`Kernel <kernel>` - Provides basic system functionality and threading
70+
* :ref:`Console <console>` - Enables UART console output for debugging and user interaction
71+
* Devicetree - Defines the partition layout
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/* Delete the original partitions before redefining them */
8+
/delete-node/ &cpuapp_slot0_partition;
9+
/delete-node/ &periphconf_partition;
10+
11+
&mram1x {
12+
partitions {
13+
/* cpuapp_boot_partition is at 0x30000 with size 64KB (0x10000) */
14+
/* Move periphconf_partition to 0x40000 (right after cpuapp_boot_partition) */
15+
periphconf_partition: partition@40000 {
16+
reg = <0x40000 DT_SIZE_K(8)>;
17+
};
18+
19+
/* Move cpuapp_slot0_partition to start after periphconf_partition */
20+
/* periphconf_partition ends at 0x42000, so slot0 starts there */
21+
cpuapp_slot0_partition: partition@42000 {
22+
reg = <0x42000 DT_SIZE_K(328)>;
23+
};
24+
};
25+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
# Disable MPU to allow writing to protected memory region for demonstration
8+
CONFIG_ARM_MPU=n
9+
10+
# Note: UICR configuration (GEN_UICR_PROTECTEDMEM, etc.) is done in sysbuild/uicr.conf
11+
# for the UICR image, not in the main application's prj.conf
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
sample:
2+
name: Protected Memory PERIPHCONF Sample
3+
description: |
4+
Sample demonstrating UICR.PROTECTEDMEM protection of the periphconf_partition.
5+
The sample relocates periphconf_partition to be right after
6+
cpuapp_boot_partition and configures PROTECTEDMEM to protect both partitions.
7+
The sample writes to the protected area, reboots, and demonstrates that the
8+
integrity check fails on boot, preventing the device from booting when the
9+
protected memory is modified.
10+
11+
common:
12+
sysbuild: true
13+
harness: console
14+
harness_config:
15+
type: multi_line
16+
ordered: true
17+
regex:
18+
- "=== Protected Memory Demo ==="
19+
- "Attempting to write test pattern"
20+
- "Write successful \\(in current boot\\)\\."
21+
- "Rebooting\\.\\.\\."
22+
# When PROTECTEDMEM integrity check fails, secondary firmware boots
23+
- "=== Secondary Firmware Booted ==="
24+
- "PROTECTEDMEM integrity check FAILED"
25+
26+
tests:
27+
samples.protectedmem_periphconf.nrf54h20dk:
28+
tags:
29+
- sysbuild
30+
- ci_samples_sdfw
31+
platform_allow:
32+
- nrf54h20dk/nrf54h20/cpuapp
33+
integration_platforms:
34+
- nrf54h20dk/nrf54h20/cpuapp
35+
timeout: 7
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
3+
4+
cmake_minimum_required(VERSION 3.20.0)
5+
6+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
7+
project(secondary)
8+
9+
target_sources(app PRIVATE src/main.c)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/ {
8+
chosen {
9+
zephyr,code-partition = &secondary_partition;
10+
};
11+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
CONFIG_IS_IRONSIDE_SE_SECONDARY_IMAGE=y
8+
9+
# Use the devicetree chosen code-partition to determine flash load offset
10+
CONFIG_USE_DT_CODE_PARTITION=y
11+
12+
# NB: app.overlay sets zephyr,code-partition to secondary_partition
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA.
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/sys/printk.h>
9+
10+
int main(void)
11+
{
12+
printk("PROTECTEDMEM integrity check failed - secondary firmware booted\n");
13+
14+
while (1) {
15+
k_msleep(1000);
16+
}
17+
18+
return 0;
19+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA.
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/sys/printk.h>
9+
#include <zephyr/devicetree.h>
10+
#include <zephyr/arch/cpu.h>
11+
12+
#define PERIPHCONF_PARTITION_ADDRESS DT_FIXED_PARTITION_ADDR(DT_NODELABEL(periphconf_partition))
13+
#define PERIPHCONF_PARTITION_SIZE DT_REG_SIZE(DT_NODELABEL(periphconf_partition))
14+
#define MRAM_16BYTE_ALIGN 16
15+
#define PARTITION_END (PERIPHCONF_PARTITION_ADDRESS + PERIPHCONF_PARTITION_SIZE)
16+
#define LAST_16BYTE_AREA_START ((PARTITION_END - MRAM_16BYTE_ALIGN) & ~(MRAM_16BYTE_ALIGN - 1))
17+
#define TEST_WRITE_ADDRESS (LAST_16BYTE_AREA_START + MRAM_16BYTE_ALIGN - sizeof(uint32_t))
18+
#define TEST_PATTERN 0xDEADBEEFUL
19+
20+
int main(void)
21+
{
22+
printk("Writing test pattern to protected memory...\n");
23+
24+
*(volatile uint32_t *)TEST_WRITE_ADDRESS = TEST_PATTERN;
25+
26+
printk("Rebooting. Secondary firmware should boot if protection is working.\n");
27+
28+
k_msleep(50);
29+
NVIC_SystemReset();
30+
31+
CODE_UNREACHABLE;
32+
}

0 commit comments

Comments
 (0)