Skip to content

Conversation

@SebastianBoe
Copy link
Contributor

Add a sample that demonstrates how to protect periphconf using PROTECTEDMEM.

Copilot AI review requested due to automatic review settings November 7, 2025 13:46
@SebastianBoe SebastianBoe marked this pull request as ready for review November 7, 2025 13:46
@SebastianBoe SebastianBoe requested review from a team as code owners November 7, 2025 13:46
@NordicBuilder NordicBuilder added doc-required PR must not be merged without tech writer approval. changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added. labels Nov 7, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new sample demonstrating UICR.PROTECTEDMEM functionality for protecting memory regions on IronSide SE devices. The sample showcases how modifications to protected memory trigger integrity check failures that prevent normal boot and instead launch secondary firmware.

  • Adds a complete sample with main and secondary firmware applications
  • Configures PROTECTEDMEM to cover cpuapp_boot_partition and periphconf_partition
  • Demonstrates integrity violation detection through automated testing

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
samples/ironside_se/protectedmem_periphconf/sysbuild/uicr.conf Configures PROTECTEDMEM size and enables secondary firmware
samples/ironside_se/protectedmem_periphconf/sysbuild.cmake Sets up sysbuild for secondary firmware and applies device tree overlay
samples/ironside_se/protectedmem_periphconf/src/main.c Main application that writes to protected memory and triggers reboot
samples/ironside_se/protectedmem_periphconf/secondary/src/main.c Secondary firmware that boots on integrity failure
samples/ironside_se/protectedmem_periphconf/secondary/prj.conf Configuration for secondary image
samples/ironside_se/protectedmem_periphconf/secondary/app.overlay Device tree overlay for secondary partition
samples/ironside_se/protectedmem_periphconf/secondary/CMakeLists.txt Build configuration for secondary firmware
samples/ironside_se/protectedmem_periphconf/sample.yaml Test configuration with expected console output patterns
samples/ironside_se/protectedmem_periphconf/prj.conf Main application configuration
samples/ironside_se/protectedmem_periphconf/app.overlay Device tree overlay relocating periphconf_partition
samples/ironside_se/protectedmem_periphconf/README.rst Comprehensive documentation of the sample
samples/ironside_se/protectedmem_periphconf/CMakeLists.txt Main application build configuration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@NordicBuilder
Copy link
Contributor

NordicBuilder commented Nov 7, 2025

CI Information

To view the history of this post, click the 'edited' button above
Build number: 4

Inputs:

Sources:

sdk-nrf: PR head: 2f11738ae32c4740a6d7ad858c73514bf226b948

more details

sdk-nrf:

PR head: 2f11738ae32c4740a6d7ad858c73514bf226b948
merge base: 6ec8b0e7508839ce63947fbf3cfd144882f4403c
target head (main): cc64cfd895ed36d493dc0d9ab20834d738cc6163
Diff

Github labels

Enabled Name Description
ci-disabled Disable the ci execution
ci-all-test Run all of ci, no test spec filtering will be done
ci-force-downstream Force execution of downstream even if twister fails
ci-run-twister Force run twister
ci-run-zephyr-twister Force run zephyr twister
List of changed files detected by CI (12)
samples
│  ├── ironside_se
│  │  ├── protectedmem_periphconf
│  │  │  ├── CMakeLists.txt
│  │  │  ├── README.rst
│  │  │  ├── app.overlay
│  │  │  ├── prj.conf
│  │  │  ├── sample.yaml
│  │  │  ├── secondary
│  │  │  │  ├── CMakeLists.txt
│  │  │  │  ├── app.overlay
│  │  │  │  ├── prj.conf
│  │  │  │  ├── src
│  │  │  │  │  │ main.c
│  │  │  ├── src
│  │  │  │  │ main.c
│  │  │  ├── sysbuild.cmake
│  │  │  ├── sysbuild
│  │  │  │  │ uicr.conf

Outputs:

Toolchain

Version: df3cc9d822
Build docker image: docker-dtr.nordicsemi.no/sw-production/ncs-build:df3cc9d822_e595b21c39

Test Spec & Results: ✅ Success; ❌ Failure; 🟠 Queued; 🟡 Progress; ◻️ Skipped; ⚠️ Quarantine

  • ◻️ Toolchain - Skipped: existing toolchain is used
  • ✅ Build twister
    • sdk-nrf test count: 1
  • ✅ Integration tests
Disabled integration tests
    • test-fw-nrfconnect-nrf_lrcs_positioning
    • desktop52_verification
    • test_ble_nrf_config
    • test-fw-nrfconnect-apps
    • test-fw-nrfconnect-ble_mesh
    • test-fw-nrfconnect-ble_samples
    • test-fw-nrfconnect-chip
    • test-fw-nrfconnect-fem
    • test-fw-nrfconnect-nfc
    • test-fw-nrfconnect-nrf-iot_libmodem-nrf
    • test-fw-nrfconnect-nrf-iot_lwm2m
    • test-fw-nrfconnect-nrf-iot_samples
    • test-fw-nrfconnect-nrf-iot_thingy91
    • test-fw-nrfconnect-nrf-iot_zephyr_lwm2m
    • test-fw-nrfconnect-nrf_crypto
    • test-fw-nrfconnect-ps-main
    • test-fw-nrfconnect-rpc
    • test-fw-nrfconnect-rs
    • test-fw-nrfconnect-tfm
    • test-fw-nrfconnect-thread-main
    • test-low-level
    • test-sdk-audio
    • test-sdk-dfu
    • test-sdk-find-my
    • test-sdk-mcuboot
    • test-sdk-wifi
    • test-secdom-samples-public

Note: This message is automatically posted and updated by the CI

@github-actions
Copy link

github-actions bot commented Nov 7, 2025

You can find the documentation preview for this PR here.

Preview links for modified nRF Connect SDK documents:

https://ncsdoc.z6.web.core.windows.net/PR-25482/nrf/samples/ironside_se/protectedmem_periphconf/README.html

Copy link
Contributor

@hakonfam hakonfam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I would prefer if there was less output, less duplication of information, and less inline file contents in the rst.

CONFIG_USE_DT_CODE_PARTITION=y

# NB: app.overlay sets zephyr,code-partition to secondary_partition

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

?

I thought this would be a compliance issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

zephyr,code-partition = &secondary_partition;
};
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there blank new lines one almost all the files?

Suggested change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


# Enable secondary firmware that boots on integrity failure
CONFIG_GEN_UICR_SECONDARY=y

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, at least its consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


return 0;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines 15 to 26
/* Get periphconf_partition address and size from device tree */
#define PERIPHCONF_PARTITION_ADDRESS DT_FIXED_PARTITION_ADDR(DT_NODELABEL(periphconf_partition))
#define PERIPHCONF_PARTITION_SIZE DT_REG_SIZE(DT_NODELABEL(periphconf_partition))

/* Write to the last 4 bytes in a 16-byte aligned area within periphconf */
/* Find the last 16-byte aligned area within the partition */
#define MRAM_16BYTE_ALIGN 16
#define PARTITION_END (PERIPHCONF_PARTITION_ADDRESS + PERIPHCONF_PARTITION_SIZE)
/* Find the start of the last 16-byte aligned area (round down to 16-byte boundary) */
#define LAST_16BYTE_AREA_START ((PARTITION_END - MRAM_16BYTE_ALIGN) & ~(MRAM_16BYTE_ALIGN - 1))
/* Write to the last 4 bytes of that 16-byte aligned area */
#define TEST_WRITE_ADDRESS (LAST_16BYTE_AREA_START + MRAM_16BYTE_ALIGN - sizeof(uint32_t))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are any of these comments needed? IMO the macro names are self-explanatory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

* How to relocate the ``periphconf_partition`` using a device tree overlay to be placed right after ``cpuapp_boot_partition``
* How to configure the PROTECTEDMEM size in Kconfig to cover both ``cpuapp_boot_partition`` and ``periphconf_partition``
* How to configure a secondary firmware that boots when PROTECTEDMEM integrity check fails
* How the protected memory region prevents unauthorized modifications by causing the secondary firmware to boot when integrity is violated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* How the protected memory region prevents unauthorized modifications by causing the secondary firmware to boot when integrity is violated
* How the protected memory region prevents unauthorized modifications by causing the secondary firmware to boot when integrity is violated.

These are sentences, they should end with a period.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed to be less verbose

1. The application writes a test pattern to the protected memory region
2. The application then reboots
3. On the next boot, the IronSide SE performs an integrity check of the protected memory region
4. If the integrity check fails (because the memory was modified), IronSide SE automatically boots the secondary firmware instead of the main application
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know that it will fail.

Suggested change
4. If the integrity check fails (because the memory was modified), IronSide SE automatically boots the secondary firmware instead of the main application
4. The integrity check fails since the memory was modified, and IronSide SE automatically boots the secondary firmware instead of the main application

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed to be less verbose

2. The application then reboots
3. On the next boot, the IronSide SE performs an integrity check of the protected memory region
4. If the integrity check fails (because the memory was modified), IronSide SE automatically boots the secondary firmware instead of the main application
5. The secondary firmware prints a message indicating that the PROTECTEDMEM integrity check failed, demonstrating that unauthorized modifications are detected and prevented
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this information needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed to be less verbose

Comment on lines 71 to 75
[00:00:00.123,457] periphconf_partition address: 0x0e040000
[00:00:00.123,458] periphconf_partition size: 0x2000 bytes
[00:00:00.123,459] Last 16-byte aligned area start: 0x0e041ff0
[00:00:00.123,460] Test write address (last 4 bytes): 0x0e041ffc
[00:00:00.123,461] Current value at protected address: 0xffffffff
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated elsewhere we should compress the output of this sample.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed to be less verbose

The ``app.overlay`` file relocates the ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition``.
The ``sysbuild.cmake`` file applies this same overlay to the UICR image so both images see the same partition layout:

.. code-block:: dts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to repeat the entire file contents in the doc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed to be less verbose

Copilot AI review requested due to automatic review settings November 10, 2025 15:15
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 8 to 10
integrity check fails on boot, preventing the device from booting into the primary image when the periphconf partition is tampered with.
protected memory is modified.

Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 8-9 contain redundant and fragmented text. The phrase "when the periphconf partition is tampered with. protected memory is modified" appears to be duplicative or incomplete. Consider consolidating to: "integrity check fails on boot, preventing the device from booting into the primary image when protected memory is modified."

Suggested change
integrity check fails on boot, preventing the device from booting into the primary image when the periphconf partition is tampered with.
protected memory is modified.
integrity check fails on boot, preventing the device from booting into the primary image when protected memory is modified.

Copilot uses AI. Check for mistakes.
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.13.1)
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent CMake minimum version requirements across the sample. The main CMakeLists.txt requires 3.13.1 while secondary/CMakeLists.txt requires 3.20.0. Consider standardizing both to the same version (preferably 3.20.0 to match the secondary firmware and other recent samples).

Suggested change
cmake_minimum_required(VERSION 3.13.1)
cmake_minimum_required(VERSION 3.20.0)

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 13
/ {
/* Move periphconf_partition to be right after cpuapp_boot_partition */
};
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Empty root node serves no functional purpose. Consider removing this empty block as the comment alone doesn't justify the empty node structure.

Suggested change
/ {
/* Move periphconf_partition to be right after cpuapp_boot_partition */
};
/* Move periphconf_partition to be right after cpuapp_boot_partition */

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@hakonfam hakonfam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments did not get included as part of my previous review for some reason.

Add a sample that demonstrates how to protect periphconf using
PROTECTEDMEM.

Signed-off-by: Sebastian Bøe <sebastian.boe@nordicsemi.no>
@SebastianBoe
Copy link
Contributor Author

@hakonfam please reassess

# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.13.1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update to 3.20.0


project(protectedmem_periphconf)

target_sources(app PRIVATE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put on 1 line


&mram1x {
partitions {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Copy link
Contributor

@hakonfam hakonfam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look good. We need to ensure that the correct rst is uncleded in the docs


.. |sample path| replace:: :file:`samples/ironside_se/protectedmem_periphconf`

.. include:: /includes/build_and_run_ns.txt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is "_ns" used? Have we checked that this is correct?


.. code-block:: console

west flash --recover
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know that --recover is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, using PROTECTEDMEM results in changes to MRAM that are not erased by "west flash".

Overview
********

This sample demonstrates how to protect the ``periphconf_partition`` using UICR.PROTECTEDMEM.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This sample demonstrates how to protect the ``periphconf_partition`` using UICR.PROTECTEDMEM.

.. contents::
:local:
:depth: 2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This sample demonstrates how to protect the PERIPHCONF Partition using UICR.PROTECTEDMEM.

********

This sample demonstrates how to protect the ``periphconf_partition`` using UICR.PROTECTEDMEM.
The sample relocates ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition`` and configures PROTECTEDMEM to cover both partitions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The sample relocates ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition`` and configures PROTECTEDMEM to cover both partitions.
The sample relocates the ``periphconf_partition`` right after ``cpuapp_boot_partition`` and configures PROTECTEDMEM to cover both partitions.


This sample demonstrates how to protect the ``periphconf_partition`` using UICR.PROTECTEDMEM.
The sample relocates ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition`` and configures PROTECTEDMEM to cover both partitions.
When protected memory is modified, the integrity check fails on the next boot, causing IronSide SE to boot a secondary firmware instead of the main application.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When protected memory is modified, the integrity check fails on the next boot, causing IronSide SE to boot a secondary firmware instead of the main application.
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.

After programming the sample to your development kit, complete the following steps to test it:

1. |connect_terminal|
#. Reset the kit.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#. Reset the kit.
#. Reset the development kit.

#. Reset the kit.

The application writes a test pattern to protected memory and then reboots.
On the next boot, if protection is working correctly, the secondary firmware will boot instead of the main application, indicating that the integrity check detected the modification.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
On the next boot, if protection is working correctly, the secondary firmware will boot instead of the main application, indicating that the integrity check detected the modification.
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.

Comment on lines +59 to +74
Device Tree Overlay
===================

The ``app.overlay`` file relocates the ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition`` at offset 0x40000.
The ``sysbuild.cmake`` file applies this same overlay to the UICR image so both images see the same partition layout.

Kconfig Configuration
=====================

The ``sysbuild/uicr.conf`` file configures the PROTECTEDMEM size to 72KB (73728 bytes) to cover both ``cpuapp_boot_partition`` (64KB) and ``periphconf_partition`` (8KB).

Secondary Firmware
==================

The sample includes a secondary firmware (in the ``secondary/`` directory) that boots automatically when the PROTECTEDMEM integrity check fails.
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``).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Device Tree Overlay
===================
The ``app.overlay`` file relocates the ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition`` at offset 0x40000.
The ``sysbuild.cmake`` file applies this same overlay to the UICR image so both images see the same partition layout.
Kconfig Configuration
=====================
The ``sysbuild/uicr.conf`` file configures the PROTECTEDMEM size to 72KB (73728 bytes) to cover both ``cpuapp_boot_partition`` (64KB) and ``periphconf_partition`` (8KB).
Secondary Firmware
==================
The sample includes a secondary firmware (in the ``secondary/`` directory) that boots automatically when the PROTECTEDMEM integrity check fails.
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``).
Device Tree Overlay
The ``app.overlay`` file relocates the ``periphconf_partition`` to be placed right after ``cpuapp_boot_partition`` at offset 0x40000.
The ``sysbuild.cmake`` file applies this same overlay to the UICR image so both images see the same partition layout.
Kconfig Configuration
The ``sysbuild/uicr.conf`` file configures the PROTECTEDMEM size to 72KB (73728 bytes) to cover both ``cpuapp_boot_partition`` (64KB) and ``periphconf_partition`` (8KB).
Secondary Firmware
The sample includes a secondary firmware (in the ``secondary/`` directory) that boots automatically when the PROTECTEDMEM integrity check fails.
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``).


* :ref:`Kernel <kernel>` - Provides basic system functionality and threading
* :ref:`Console <console>` - Enables UART console output for debugging and user interaction
* Device Tree - Defines the partition layout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Device Tree - Defines the partition layout
* Devicetree - Defines the partition layout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added. doc-required PR must not be merged without tech writer approval.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants