Platform: RP2350: Add RP2350 porting
Change-Id: I8359f2a0ccea6a5afade57fc651aa90dae678307
Signed-off-by: William Vinnicombe <william.vinnicombe@raspberrypi.com>
diff --git a/docs/contributing/maintainers.rst b/docs/contributing/maintainers.rst
index 2f62afb..65d49e4 100644
--- a/docs/contributing/maintainers.rst
+++ b/docs/contributing/maintainers.rst
@@ -183,6 +183,13 @@
:email: `Jidong.Mei@armchina.com <Jidong.Mei@armchina.com>`__
:github: `JidongMei <https://github.com/JidongMei>`__
+Raspberry Pi Platform:
+~~~~~~~~~~~~~~~~~~~~~~
+
+William Vinnicombe
+ :email: `William.Vinnicombe@raspberrypi.com <william.vinnicombe@raspberrypi.com>`__
+ :github: `Raspberry Pi <https://github.com/raspberrypi>`__
+
=============
.. _Project Maintenance Process: https://trusted-firmware-docs.readthedocs.io/en/latest/generic_processes/project_maintenance_process.html
diff --git a/docs/platform/index.rst b/docs/platform/index.rst
index 0aeca26..ada5921 100644
--- a/docs/platform/index.rst
+++ b/docs/platform/index.rst
@@ -14,8 +14,9 @@
Nordic <nordic_nrf/index>
Nuvoton <nuvoton/index>
NXP <nxp/index>
+ Raspberry Pi <rpi/index>
STMICROELECTRONICS <stm/index>
--------------
-*Copyright (c) 2020-2023, Arm Limited. All rights reserved.*
+*Copyright (c) 2020-2024, Arm Limited. All rights reserved.*
diff --git a/docs/platform/rpi/index.rst b/docs/platform/rpi/index.rst
new file mode 100644
index 0000000..6ad40a6
--- /dev/null
+++ b/docs/platform/rpi/index.rst
@@ -0,0 +1,14 @@
+######################
+Raspberry Pi platforms
+######################
+
+.. toctree::
+ :maxdepth: 1
+ :titlesonly:
+
+ RP2350 <rp2350/readme.rst>
+
+--------------
+
+ *SPDX-License-Identifier: BSD-3-Clause*
+ *SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors*
diff --git a/docs/platform/rpi/rp2350/readme.rst b/docs/platform/rpi/rp2350/readme.rst
new file mode 100644
index 0000000..176aba2
--- /dev/null
+++ b/docs/platform/rpi/rp2350/readme.rst
@@ -0,0 +1,139 @@
+RP2350
+======
+
+Introduction
+------------
+
+RP2350 features a dual-core Arm Cortex-M33 processor with 520 kiB on-chip SRAM,
+support for up to 16MB of off-chip flash and a wide range of flexible I/O option
+including I2C, SPI, and - uniquely - Programmable I/O (PIO). With its security
+features RP2350 offers significant enhancements over RP2040.
+
+This platform port supports TF-M regression tests (Secure and Non-secure)
+with Isolation Level 1 and 2.
+
+.. note::
+
+ Only GNU toolchain is supported.
+
+Building TF-M
+-------------
+
+Follow the instructions in :doc:`Building instructions </building/tfm_build_instruction>`.
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Build instructions with platform name: rpi/rp2350
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+``-DTFM_PLATFORM=rpi/rp2350``
+
+.. note::
+
+ This platform port relies on
+ `Raspberry Pi Pico SDK <https://github.com/raspberrypi/pico-sdk>`__
+ Make sure it is either cloned locally or available to download during build.
+ SDK version used for testing: SDK 2.0.0 release
+
+.. note::
+
+ Building the default platform configuration requires the board to be
+ provisioned. For this the provision bundle needs to be built and run on the
+ board with ``-DPLATFORM_DEFAULT_PROVISIONING=OFF``. The binary must be
+ placed in flash at the address defined by ``PROVISIONING_BUNDLE_START``. One
+ way to do this is to generate a .uf2 file containing the bundle at the start
+ address and copy it to the board. There is an example in the provided
+ pico_uf2.sh script and in the description below.
+
+ If ``-DPLATFORM_DEFAULT_PROVISIONING=OFF`` and
+ ``-DTFM_DUMMY_PROVISIONING=ON`` then the keys in the
+ ``tf-m/platform/ext/common/provisioning_bundle/provisioning_config.cmake``
+ and the default MCUBoot signing keys will be used for provisioning.
+
+ If ``-DPLATFORM_DEFAULT_PROVISIONING=OFF`` and
+ ``-DTFM_DUMMY_PROVISIONING=OFF`` are set then unique values can be used for
+ provisioning. The keys and seeds can be changed by passing the new values to
+ the build command, or by setting the ``-DPROVISIONING_KEYS_CONFIG`` flag to a
+ .cmake file that contains the keys. An example config cmake file can be seen
+ at
+ ``tf-m/platform/ext/common/provisioning_bundle/provisioning_config.cmake``.
+ Otherwise new random values are going to be generated and used. For the image
+ signing the ${MCUBOOT_KEY_S} and ${MCUBOOT_KEY_NS} will be used. These
+ variables should point to .pem files that contain the code signing private
+ keys. The public keys are going to be generated from these private keys and
+ will be used for provisioning. The hash of the public key is going to be
+ written into the ``provisioning_data.c`` automatically.
+
+ If ``-DMCUBOOT_GENERATE_SIGNING_KEYPAIR=ON`` is set then a new mcuboot
+ signing public and private keypair is going to be generated and it's going to
+ be used to sign the S and NS binaries.
+
+ The new generated keypair can be found in the ``<build dir>/bin`` folder or
+ in the ``<install directory>/image_signing/keys`` after installation.
+ The generated provisioning_data.c file can be found at
+ ``<build directory>/platform/target/provisioning/provisioning_data.c``
+
+.. note::
+
+ The provisioning bundle generation depends on pyelftools that's have to be
+ installed::
+
+ pip3 install pyelftools
+
+Example build instructions for regression tests with dummy keys:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Building Secure side with provisioning bundle:
+
+.. note::
+
+ Add -DTFM_MULTI_CORE_TOPOLOGY=ON to the above for multicore support
+
+
+.. code-block:: bash
+
+ cmake -S <TF-M tests source dir>/tests_reg/spe \
+ -B <TF-M tests source dir>/tests_reg/spe/build_rpi_myns_single \
+ -DTFM_PLATFORM=rpi/rp2350 \
+ -DTFM_TOOLCHAIN_FILE=<TF-M source dir>/toolchain_GNUARM.cmake \
+ -DCONFIG_TFM_SOURCE_PATH=<TF-M source dir> \
+ -DTFM_PROFILE=profile_medium -DPLATFORM_DEFAULT_PROVISIONING=OFF \
+ -DTEST_S=ON -DTEST_NS=ON
+
+.. code-block:: bash
+
+ cmake --build <TF-M tests source dir>/tests_reg/spe/build_rpi_myns_single \
+ -- -j8 install
+
+
+Building Non-Secure side:
+
+.. code-block:: bash
+
+ cmake -S <TF-M tests source dir>/tests_reg \
+ -B <TF-M tests source dir>/tests_reg/build_rpi_myns_single \
+ -DCONFIG_SPE_PATH=<TF-M tests source dir>/tests_reg/spe/build_rpi_myns_single/api_ns \
+ -DTFM_TOOLCHAIN_FILE=<TF-M tests source dir>/tests_reg/spe/build_rpi_myns_single/api_ns/cmake/toolchain_ns_GNUARM.cmake
+ cmake --build <TF-M tests source dir>/tests_reg/build_rpi_myns_single -- -j8
+
+Binaries need to be converted with a small script pico_uf2.sh
+It uses uf2conv.py from here:
+https://github.com/microsoft/uf2/blob/master/utils/uf2conv.py
+It depends on:
+https://github.com/microsoft/uf2/blob/master/utils/uf2families.json
+The tool takes the combined and signed S and NS images in .bin format, and
+outputs .uf2. It also generates the .uf2 for the bootloader (bl2.uf2) and the
+provisioning bundle.
+
+.. code-block:: bash
+
+ pico_uf2.sh <TF-M tests source dir> build_rpi_myns_single
+
+Then just copy the bl2.uf and tfm_s_ns_signed.bin.uf2 files to the board. It
+will run the BL2, S and NS tests and print the results to the UART (Baudrate
+115200).
+If the board needs provisioning, the .uf2 file containing the provisioning
+bundle needs to be copied before tfm_s_ns_signed.bin.uf2. It only needs to be
+done once.
+
+-------------
+
+ *SPDX-License-Identifier: BSD-3-Clause*
+ *SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors*
diff --git a/platform/ext/target/rpi/pico_uf2.sh b/platform/ext/target/rpi/pico_uf2.sh
new file mode 100644
index 0000000..fed78a5
--- /dev/null
+++ b/platform/ext/target/rpi/pico_uf2.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+tfm_tests_dir=$1
+build_dir=$2
+spe_bin="${tfm_tests_dir}/tests_reg/spe/${build_dir}/bin"
+ns_bin="${tfm_tests_dir}/tests_reg/${build_dir}/bin"
+uf2conv.py "${spe_bin}/bl2.bin" --base 0x10000000 --convert --output "${spe_bin}/bl2.uf2" --family 0xe48bff59
+uf2conv.py "${ns_bin}/../tfm_s_ns_signed.bin" --base 0x10011000 --convert --output "${spe_bin}/tfm_s_ns_signed.uf2" --family 0xe48bff59
+uf2conv.py "${spe_bin}/provisioning_bundle.bin" --base 0x100F5000 --convert --output "${spe_bin}/provisioning_bundle.uf2" --family 0xe48bff59
\ No newline at end of file
diff --git a/platform/ext/target/rpi/rp2350/CMakeLists.txt b/platform/ext/target/rpi/rp2350/CMakeLists.txt
new file mode 100644
index 0000000..388859d
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/CMakeLists.txt
@@ -0,0 +1,324 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#
+#-------------------------------------------------------------------------------
+
+
+# initialize pico-sdk from GIT
+set(PICO_SDK_FETCH_FROM_GIT on)
+set(PICO_PLATFORM rp2350-arm-s)
+set(SKIP_BOOT_STAGE2 1)
+
+# initialize the Raspberry Pi Pico SDK
+include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_import.cmake)
+pico_sdk_init()
+
+get_target_property(pico_link_options pico_standard_link INTERFACE_LINK_OPTIONS)
+list(FILTER pico_link_options EXCLUDE REGEX "LINKER.*--script")
+list(APPEND pico_link_options "--entry=_entry_point")
+set_target_properties(pico_standard_link PROPERTIES INTERFACE_LINK_OPTIONS "${pico_link_options}")
+set_target_properties(pico_runtime PROPERTIES INTERFACE_LINK_OPTIONS "")
+
+target_compile_options(cmsis_core
+ INTERFACE
+ ${COMPILER_CMSE_FLAG}
+)
+
+cmake_policy(SET CMP0076 NEW)
+set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+set(STATIC_ASSERT_OVERRIDE_HEADER "${CMAKE_CURRENT_LIST_DIR}/static_assert_override.h")
+add_library(static_assert_override INTERFACE)
+target_compile_options(static_assert_override
+ INTERFACE
+ "$<$<C_COMPILER_ID:Armclang>:SHELL:-include ${STATIC_ASSERT_OVERRIDE_HEADER}>"
+ "$<$<C_COMPILER_ID:GNU>:SHELL:-include ${STATIC_ASSERT_OVERRIDE_HEADER}>"
+ "$<$<C_COMPILER_ID:IAR>:SHELL:--preinclude ${STATIC_ASSERT_OVERRIDE_HEADER}>"
+)
+
+#========================= Platform region defs ===============================#
+
+add_library(platform_s_init INTERFACE)
+target_sources(platform_s_init
+ INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/extra_init.c
+)
+
+target_link_libraries(platform_s_init
+ INTERFACE
+ pico_runtime_init
+ pico_runtime_headers
+ pico_bootrom_headers
+)
+
+target_link_options(tfm_s
+ PUBLIC
+ "--entry=_entry_point"
+)
+
+target_include_directories(platform_region_defs
+ INTERFACE
+ partition
+)
+
+target_link_libraries(platform_region_defs
+ INTERFACE
+ tfm_fih_headers
+ hardware_regs_headers
+ static_assert_override
+)
+
+target_compile_definitions(platform_region_defs
+ INTERFACE
+ PROVISIONING_CODE_PADDED_SIZE=${PROVISIONING_CODE_PADDED_SIZE}
+ PROVISIONING_VALUES_PADDED_SIZE=${PROVISIONING_VALUES_PADDED_SIZE}
+ PROVISIONING_DATA_PADDED_SIZE=${PROVISIONING_DATA_PADDED_SIZE}
+)
+
+if(NOT PLATFORM_DEFAULT_PROVISIONING)
+ add_subdirectory(${PLATFORM_DIR}/ext/common/provisioning_bundle provisioning)
+
+ if(NOT PLATFORM_DEFAULT_PROV_LINKER_SCRIPT)
+ target_add_scatter_file(provisioning_bundle
+ linker_provisioning.ld
+ )
+
+ target_compile_definitions(provisioning_bundle_scatter
+ PRIVATE
+ # u modifier in scatter file is not valid
+ NO_U_MODIFIER=1
+ )
+ endif()
+endif()
+
+if(TFM_PARTITION_CRYPTO)
+ target_include_directories(platform_crypto_keys
+ PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR}
+ )
+endif()
+
+#========================= Platform common defs ===============================#
+
+# Specify the location of platform specific build dependencies.
+target_add_scatter_file(tfm_s
+ $<$<C_COMPILER_ID:ARMClang>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_common_s.sct>
+ linker_s.ld
+ $<$<C_COMPILER_ID:IAR>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/iar/tfm_common_s.icf>
+)
+target_compile_definitions(tfm_s_scatter
+ PRIVATE
+ # u modifier in scatter file is not valid
+ NO_U_MODIFIER=1
+)
+target_compile_options(tfm_s_scatter
+ PUBLIC
+ ${COMPILER_CMSE_FLAG}
+)
+
+if(BL2)
+ # Pico startup and runtime init
+ target_link_libraries(bl2
+ PUBLIC
+ pico_runtime
+ )
+ target_add_scatter_file(bl2
+ $<$<C_COMPILER_ID:ARMClang>:${PLATFORM_DIR}/ext/common/armclang/tfm_common_bl2.sct>
+ linker_bl2.ld
+ $<$<C_COMPILER_ID:IAR>:${PLATFORM_DIR}/ext/common/iar/tfm_common_bl2.icf>
+ )
+ target_compile_definitions(bl2_scatter
+ PRIVATE
+ # u modifier in scatter file is not valid
+ NO_U_MODIFIER=1
+ )
+
+ target_compile_options(bl2_scatter
+ PUBLIC
+ ${COMPILER_CMSE_FLAG}
+ )
+endif()
+
+#========================= Platform Secure ====================================#
+
+target_include_directories(platform_s
+ PUBLIC
+ .
+ cmsis_drivers
+ partition
+ device/config
+ ${PLATFORM_DIR}/..
+)
+
+target_link_libraries(platform_s
+ PUBLIC
+ cmsis_core_headers
+ hardware_uart_headers
+ platform_s_init
+ PRIVATE
+ pico_crt0
+ pico_rand
+ pico_multicore
+ hardware_regs
+ hardware_flash
+ hardware_uart
+ cmsis_core
+)
+
+target_sources(platform_s
+ INTERFACE
+ $<$<STREQUAL:"${TFM_FIH_PROFILE}","HIGH">:${PLATFORM_DIR}/ext/common/template/tfm_fih_rng.c>
+ PRIVATE
+ cmsis_drivers/Driver_Flash_RPI.c
+ cmsis_drivers/Driver_USART_RPI.c
+
+ tfm_peripherals_def.c
+
+ rpi_trng.c
+
+ $<$<OR:$<BOOL:${TFM_S_REG_TEST}>,$<BOOL:${TFM_NS_REG_TEST}>>:${CMAKE_CURRENT_SOURCE_DIR}/plat_test.c>
+ $<$<BOOL:${TFM_PARTITION_PLATFORM}>:${CMAKE_CURRENT_SOURCE_DIR}/services/src/tfm_platform_system.c>
+ $<$<AND:$<BOOL:${ITS_ENCRYPTION}>,$<BOOL:${TFM_PARTITION_INTERNAL_TRUSTED_STORAGE}>>:${PLATFORM_DIR}/ext/common/template/tfm_hal_its_encryption.c>
+ $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_OTP}>>:${CMAKE_CURRENT_SOURCE_DIR}/rp2350_otp.c>
+ $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_NV_COUNTERS}>>:${CMAKE_CURRENT_SOURCE_DIR}/nv_counters.c>
+ $<$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>:${CMAKE_CURRENT_SOURCE_DIR}/tfm_hal_multi_core.c>
+ $<$<BOOL:${TFM_NS_MAILBOX_API}>:${CMAKE_CURRENT_SOURCE_DIR}/tfm_hal_mailbox.c>
+)
+
+target_compile_options(platform_s
+ PUBLIC
+ ${COMPILER_CMSE_FLAG}
+)
+
+target_compile_definitions(platform_s
+ PUBLIC
+ CMSIS_device_header=<RP2350.h>
+ PICO_UART_DEFAULT_CRLF=1
+ $<$<BOOL:${TEST_NS_FPU}>:TEST_NS_FPU>
+ $<$<BOOL:${TEST_S_FPU}>:TEST_S_FPU>
+ $<$<BOOL:${ITS_ENCRYPTION}>:ITS_ENCRYPTION>
+ $<$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>:TFM_MULTI_CORE_TOPOLOGY>
+)
+
+target_link_options(platform_s INTERFACE "LINKER:--no-warn-rwx-segments")
+
+#========================= Platform BL2 =======================================#
+
+if(BL2)
+ target_sources(platform_bl2
+ PRIVATE
+ cmsis_drivers/Driver_Flash_RPI_bl2.c
+ cmsis_drivers/Driver_USART_RPI.c
+ $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_OTP}>>:${CMAKE_CURRENT_SOURCE_DIR}/rp2350_otp.c>
+ $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_NV_COUNTERS}>>:${CMAKE_CURRENT_SOURCE_DIR}/nv_counters.c>
+ )
+
+ target_link_libraries(platform_bl2
+ PUBLIC
+ cmsis_core_headers
+ hardware_uart_headers
+ PRIVATE
+ pico_runtime_headers
+ pico_runtime_init
+ hardware_regs
+ hardware_flash
+ hardware_uart
+ cmsis_core
+ )
+
+ target_link_options(platform_bl2 INTERFACE "LINKER:--no-warn-rwx-segments")
+
+ target_include_directories(platform_bl2
+ PUBLIC
+ partition
+ retarget
+ device/config
+ device/include
+ .
+ )
+
+ target_compile_definitions(platform_bl2
+ PUBLIC
+ PICO_UART_DEFAULT_CRLF=1
+ CMSIS_device_header=<RP2350.h>
+ )
+
+ target_include_directories(bl2
+ PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+
+endif()
+
+#========================= tfm_spm ============================================#
+
+target_sources(tfm_spm
+ PRIVATE
+ target_cfg.c
+ tfm_hal_platform.c
+ tfm_hal_isolation_rp2350.c
+ $<$<OR:$<BOOL:${CONFIG_TFM_FLIH_API}>,$<BOOL:${CONFIG_TFM_SLIH_API}>>:${PLATFORM_DIR}/ext/common/tfm_interrupts.c>
+)
+
+target_link_libraries(tfm_spm
+ PRIVATE
+ pico_bootrom_headers
+)
+
+#========================= Platform Crypto Keys ===============================#
+
+if (TFM_PARTITION_CRYPTO)
+ target_sources(platform_crypto_keys
+ PRIVATE
+ crypto_keys.c
+ )
+ target_link_libraries(platform_crypto_keys
+ PRIVATE
+ platform_s
+ )
+endif()
+
+#========================= Files for building NS platform =====================#
+
+install(FILES ${PLATFORM_DIR}/ext/common/test_interrupt.c
+ ${TARGET_PLATFORM_PATH}/cmsis_drivers/Driver_USART_RPI.c
+ ${TARGET_PLATFORM_PATH}/pico-sdk.patch
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR})
+
+install(DIRECTORY ${TARGET_PLATFORM_PATH}/device
+ ${TARGET_PLATFORM_PATH}/cmsis_drivers
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR})
+
+install(DIRECTORY ${PLATFORM_DIR}/ext/target/arm/drivers
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR}/ext/target/arm)
+
+install(FILES ${TARGET_PLATFORM_PATH}/partition/region_defs.h
+ ${TARGET_PLATFORM_PATH}/partition/flash_layout.h
+ ${TARGET_PLATFORM_PATH}/target_cfg.h
+ ${TARGET_PLATFORM_PATH}/tfm_peripherals_def.h
+ ${TARGET_PLATFORM_PATH}/platform_multicore.h
+ ${TARGET_PLATFORM_PATH}/tfm_builtin_key_ids.h
+ ${PLATFORM_DIR}/include/tfm_plat_defs.h
+ ${CMAKE_SOURCE_DIR}/lib/fih/inc/fih.h
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR}/include)
+
+install(FILES ${TARGET_PLATFORM_PATH}/linker_ns.ld
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR}/linker_scripts)
+
+# copy all files from active platform directory
+install(DIRECTORY ${TARGET_PLATFORM_PATH}/ns/
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR})
+
+install(FILES ${TARGET_PLATFORM_PATH}/cpuarch.cmake
+ ${TARGET_PLATFORM_PATH}/pico_sdk_import.cmake
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR})
+
+# Copy the platform specific config
+install(FILES ${TARGET_PLATFORM_PATH}/config.cmake
+ ${STATIC_ASSERT_OVERRIDE_HEADER}
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR})
+
+# Install test configs
+install(DIRECTORY ${TARGET_PLATFORM_PATH}/tests
+ DESTINATION ${INSTALL_PLATFORM_NS_DIR})
diff --git a/platform/ext/target/rpi/rp2350/check_config.cmake b/platform/ext/target/rpi/rp2350/check_config.cmake
new file mode 100644
index 0000000..6a7fc73
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/check_config.cmake
@@ -0,0 +1,8 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#
+#-------------------------------------------------------------------------------
+
+## The platform specific NV counters require OTP usage
+tfm_invalid_config((NOT PLATFORM_DEFAULT_OTP) EQUAL PLATFORM_DEFAULT_NV_COUNTERS)
diff --git a/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI.c b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI.c
new file mode 100644
index 0000000..3bf56cc
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI.c
@@ -0,0 +1,190 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_hal_device_header.h"
+#include "Driver_Flash_RPI.h"
+#include "RTE_Device.h"
+
+#include "armv8m_mpu.h"
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+#include "platform_multicore.h"
+#include "hardware/structs/sio.h"
+#endif
+
+#if (RTE_FLASH0)
+
+#define RP2350_FLASH_PAGE_SIZE 0x100 /* 256B */
+#define RP2350_FLASH_SECTOR_SIZE 0x1000 /* 4KB */
+#define RP2350_FLASH_SIZE PICO_FLASH_SIZE_BYTES
+#define RP2350_FLASH_ERASE_VALUE 0xFF
+
+static ARM_FLASH_INFO RP2350_FLASH_DEV_DATA = {
+ .sector_info = NULL, /* Uniform sector layout */
+ .sector_count = RP2350_FLASH_SIZE/ RP2350_FLASH_SECTOR_SIZE,
+ .sector_size = RP2350_FLASH_SECTOR_SIZE,
+ .page_size = RP2350_FLASH_PAGE_SIZE,
+ .program_unit = RP2350_FLASH_PAGE_SIZE, /* page aligned, page multipled */
+ .erased_value = RP2350_FLASH_ERASE_VALUE
+};
+
+#define MPU_REGION_NUMBER 8
+#define SEC_STATE_NUM 2
+
+struct mpu_state_save {
+ uint32_t mpu;
+ uint32_t shcsr;
+ uint32_t mair[2];
+ ARM_MPU_Region_t mpu_table[MPU_REGION_NUMBER];
+};
+
+static struct mpu_state_save mpu_state[SEC_STATE_NUM];
+static uint32_t irq_state = 0;
+MPU_Type* mpu_p[SEC_STATE_NUM] = {MPU, MPU_NS};
+SCB_Type* scb_p[SEC_STATE_NUM] = {SCB, SCB_NS};
+
+static inline uint32_t __save_disable_irq(void)
+{
+ uint32_t result = 0;
+
+ /* Claim lock of Flash */
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ while(!*FLASH_SPINLOCK);
+#endif
+ __ASM volatile ("mrs %0, primask \n cpsid i" : "=r" (result) :: "memory");
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ /* Signal Core1 to wait for flash */
+ sio_hw->doorbell_out_set = FLASH_DOORBELL_MASK;
+ if (CORE1_RUNNING)
+ {
+ /* Wait for Core1 to clear doorbell */
+ while(sio_hw->doorbell_out_set & FLASH_DOORBELL_MASK);
+ }
+#endif
+ return result;
+}
+
+static inline void __restore_irq(uint32_t status)
+{
+ __ASM volatile ("msr primask, %0" :: "r" (status) : "memory");
+ /* Release lock of Flash */
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ *FLASH_SPINLOCK = 0x1;
+#endif
+}
+
+/* This function must be placed in RAM, so when MPU configuration is saved and
+ flash is protected by a non-executable region MemManageFault is avoided.
+ Since PRIVDEFENA is set the system memory map is enabled for privileged code
+ and execution from RAM is available */
+static void __not_in_flash_func(mpu_state_save)
+ (struct rp2350_flash_dev_t* flash_dev)
+{
+ static const uint8_t mpu_attr_num = 0;
+ uint32_t memory_base = flash_dev->base;
+ uint32_t memory_limit = flash_dev->base + flash_dev->size -1;
+
+ irq_state = __save_disable_irq();
+
+ for(int i=0; i<SEC_STATE_NUM; i++) {
+
+ mpu_state[i].shcsr = scb_p[i]->SHCSR;
+ mpu_state[i].mpu = mpu_p[i]->CTRL;
+
+ if(mpu_p[i] == MPU) {
+ ARM_MPU_Disable();
+ } else {
+ ARM_MPU_Disable_NS();
+ }
+
+ for(uint8_t j = 0; j < MPU_REGION_NUMBER; j++) {
+ mpu_p[i]->RNR = j;
+ mpu_state[i].mpu_table[j].RBAR = mpu_p[i]->RBAR;
+ mpu_state[i].mpu_table[j].RLAR = mpu_p[i]->RLAR;
+ mpu_p[i]->RBAR = 0;
+ mpu_p[i]->RLAR = 0;
+ }
+
+ mpu_state[i].mair[0] = mpu_p[i]->MAIR[0];
+ mpu_state[i].mair[1] = mpu_p[i]->MAIR[1];
+
+ mpu_p[i]->MAIR[0] = 0;
+ mpu_p[i]->MAIR[1] = 0;
+
+ /* Attr0 : Device memory, nGnRE */
+ if(mpu_p[i] == MPU) {
+ ARM_MPU_SetMemAttr(mpu_attr_num,
+ ARM_MPU_ATTR(ARM_MPU_ATTR_DEVICE,
+ ARM_MPU_ATTR_DEVICE_nGnRE));
+ } else {
+ ARM_MPU_SetMemAttr_NS(mpu_attr_num,
+ ARM_MPU_ATTR(ARM_MPU_ATTR_DEVICE,
+ ARM_MPU_ATTR_DEVICE_nGnRE));
+ }
+
+ mpu_p[i]->RNR = 0;
+ mpu_p[i]->RBAR = ARM_MPU_RBAR(memory_base,
+ ARM_MPU_SH_NON,
+ 1,
+ 0,
+ 1);
+ #ifdef TFM_PXN_ENABLE
+ mpu_p[i]->RLAR = ARM_MPU_RLAR_PXN(memory_limit, 1, mpu_attr_num);
+ #else
+ mpu_p[i]->RLAR = ARM_MPU_RLAR(memory_limit, mpu_attr_num);
+ #endif
+
+ if(mpu_p[i] == MPU) {
+ ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
+ } else {
+ ARM_MPU_Enable_NS(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
+ }
+ }
+}
+
+static void __not_in_flash_func(mpu_state_restore)(void)
+{
+ for(int i=0; i<SEC_STATE_NUM; i++) {
+
+ if(mpu_p[i] == MPU) {
+ ARM_MPU_Disable();
+ } else {
+ ARM_MPU_Disable_NS();
+ }
+
+ for(uint8_t j = 0; j < MPU_REGION_NUMBER; j++) {
+ mpu_p[i]->RNR = j;
+ mpu_p[i]->RBAR = mpu_state[i].mpu_table[j].RBAR;
+ mpu_p[i]->RLAR = mpu_state[i].mpu_table[j].RLAR;
+ }
+
+ mpu_p[i]->MAIR[0] = mpu_state[i].mair[0];
+ mpu_p[i]->MAIR[1] = mpu_state[i].mair[1];
+
+ __DMB();
+ mpu_p[i]->CTRL = mpu_state[i].mpu;
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ scb_p[i]->SHCSR = mpu_state[i].shcsr;
+#endif
+ __DSB();
+ __ISB();
+
+ }
+
+ __restore_irq(irq_state);
+}
+
+static rp2350_flash_dev_t RP2350_FLASH_DEV = {
+ .data = &RP2350_FLASH_DEV_DATA,
+ .base = XIP_BASE,
+ .size = RP2350_FLASH_SIZE,
+ .save_mpu_state = mpu_state_save,
+ .restore_mpu_state = mpu_state_restore
+};
+
+
+RPI_RP2350_FLASH(RP2350_FLASH_DEV, RP2350_FLASH);
+#endif /* RTE_FLASH0 */
diff --git a/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI.h b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI.h
new file mode 100644
index 0000000..3664758
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI.h
@@ -0,0 +1,209 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __DRIVER_FLASH_RPI_H__
+#define __DRIVER_FLASH_RPI_H__
+
+#include "Driver_Flash.h"
+#include "hardware/flash.h"
+#include <string.h>
+
+#ifndef ARG_UNUSED
+#define ARG_UNUSED(arg) ((void)arg)
+#endif
+
+/* Driver version */
+#define ARM_FLASH_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0)
+
+static const ARM_DRIVER_VERSION DriverVersion = {
+ ARM_FLASH_API_VERSION, /* Defined in the CMSIS Flash Driver header file */
+ ARM_FLASH_DRV_VERSION
+};
+
+/**
+ * Data width values for ARM_FLASH_CAPABILITIES::data_width
+ * \ref ARM_FLASH_CAPABILITIES
+ */
+ enum {
+ DATA_WIDTH_8BIT = 0u,
+ DATA_WIDTH_16BIT,
+ DATA_WIDTH_32BIT,
+ DATA_WIDTH_ENUM_SIZE
+};
+
+/* Flash Status */
+static ARM_FLASH_STATUS FlashStatus = {0, 0, 0};
+
+/**
+ * \brief Flash driver capability macro definitions \ref ARM_FLASH_CAPABILITIES
+ */
+/* Flash Ready event generation capability values */
+#define EVENT_READY_NOT_AVAILABLE (0u)
+#define EVENT_READY_AVAILABLE (1u)
+
+/* Chip erase capability values */
+#define CHIP_ERASE_NOT_SUPPORTED (0u)
+#define CHIP_ERASE_SUPPORTED (1u)
+
+static inline ARM_DRIVER_VERSION ARM_Flash_GetVersion(void)
+{
+ return DriverVersion;
+}
+
+/* Driver Capabilities */
+static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
+ EVENT_READY_NOT_AVAILABLE,
+ DATA_WIDTH_8BIT,
+ CHIP_ERASE_NOT_SUPPORTED
+};
+
+/*
+ * ARM FLASH device structure
+ */
+typedef struct rp2350_flash_dev_t{
+ ARM_FLASH_INFO* data; /* FLASH data */
+ uint32_t base; /* Flash base address, used for flash
+ reads */
+ uint32_t size; /* Flash size */
+ void (*save_mpu_state)(struct rp2350_flash_dev_t* dev);
+ /*!< Function to save MPU settings */
+ void (*restore_mpu_state)(void);
+ /*!< Function to restore MPU settings */
+} rp2350_flash_dev_t;
+
+/* Driver Capabilities */
+static const ARM_FLASH_CAPABILITIES PicoDriverCapabilities = {
+ 0, /* event_ready */
+ 0, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
+ 0, /* erase_chip */
+ 0, /* reserved */
+};
+
+static inline ARM_FLASH_CAPABILITIES Pico_Driver_GetCapabilities(void)
+{
+ return PicoDriverCapabilities;
+}
+
+static inline int32_t ARM_Flash_Uninitialize(void)
+{
+ /* Nothing to be done */
+ return ARM_DRIVER_OK;
+}
+
+static inline int32_t ARM_Flash_PowerControl(ARM_POWER_STATE state)
+{
+ switch (state) {
+ case ARM_POWER_FULL:
+ /* Nothing to be done */
+ return ARM_DRIVER_OK;
+ break;
+
+ case ARM_POWER_OFF:
+ case ARM_POWER_LOW:
+ default:
+ return ARM_DRIVER_ERROR_UNSUPPORTED;
+ }
+}
+
+static inline ARM_FLASH_STATUS ARM_Flash_GetStatus(void)
+{
+ return FlashStatus;
+}
+
+/*
+ * \brief Macro for Pico Flash Driver
+ *
+ * \param[out] FLASH_DRIVER_NAME Resulting Driver name
+ */
+#define RPI_RP2350_FLASH(FLASH_DEV, FLASH_DRIVER_NAME) \
+ \
+static int32_t FLASH_DRIVER_NAME##_Initialize( \
+ ARM_Flash_SignalEvent_t cb_event) \
+{ \
+ ARG_UNUSED(cb_event); \
+ return ARM_DRIVER_OK; \
+} \
+ \
+static int32_t FLASH_DRIVER_NAME##_ReadData(uint32_t addr, \
+ void *data, \
+ uint32_t cnt) \
+{ \
+ if ((addr+cnt) >= FLASH_DEV.size) { \
+ return ARM_DRIVER_ERROR_PARAMETER; \
+ } \
+ \
+ memcpy(data, (void *)(addr + FLASH_DEV.base), cnt); \
+ \
+ return ARM_DRIVER_OK; \
+} \
+ \
+static int32_t FLASH_DRIVER_NAME##_ProgramData(uint32_t addr, \
+ const void *data, \
+ uint32_t cnt) \
+{ \
+ if ((addr+cnt) >= FLASH_DEV.size) { \
+ return ARM_DRIVER_ERROR_PARAMETER; \
+ } \
+ \
+ if ((cnt < FLASH_DEV.data->program_unit) || \
+ (cnt % FLASH_DEV.data->program_unit) || \
+ (addr % FLASH_DEV.data->page_size)) { \
+ return ARM_DRIVER_ERROR_PARAMETER; \
+ } \
+ \
+ FLASH_DEV.save_mpu_state(&FLASH_DEV); \
+ \
+ flash_range_program(addr, data, cnt); \
+ \
+ FLASH_DEV.restore_mpu_state(); \
+ \
+ return ARM_DRIVER_OK; \
+} \
+ \
+static int32_t FLASH_DRIVER_NAME##_EraseSector(uint32_t addr) \
+{ \
+ if (addr >= FLASH_DEV.size) { \
+ return ARM_DRIVER_ERROR_PARAMETER; \
+ } \
+ \
+ if (addr % FLASH_DEV.data->sector_size) { \
+ return ARM_DRIVER_ERROR_PARAMETER; \
+ } \
+ \
+ FLASH_DEV.save_mpu_state(&FLASH_DEV); \
+ \
+ flash_range_erase(addr, FLASH_DEV.data->sector_size); \
+ \
+ FLASH_DEV.restore_mpu_state(); \
+ \
+ return ARM_DRIVER_OK; \
+} \
+ \
+static int32_t FLASH_DRIVER_NAME##_EraseChip(void) \
+{ \
+ return ARM_DRIVER_ERROR_UNSUPPORTED; \
+} \
+ \
+static ARM_FLASH_INFO * FLASH_DRIVER_NAME##_GetInfo(void) \
+{ \
+ return FLASH_DEV.data; \
+} \
+ \
+ARM_DRIVER_FLASH FLASH_DRIVER_NAME = { \
+ ARM_Flash_GetVersion, \
+ Pico_Driver_GetCapabilities, \
+ FLASH_DRIVER_NAME##_Initialize, \
+ ARM_Flash_Uninitialize, \
+ ARM_Flash_PowerControl, \
+ FLASH_DRIVER_NAME##_ReadData, \
+ FLASH_DRIVER_NAME##_ProgramData, \
+ FLASH_DRIVER_NAME##_EraseSector, \
+ FLASH_DRIVER_NAME##_EraseChip, \
+ ARM_Flash_GetStatus, \
+ FLASH_DRIVER_NAME##_GetInfo \
+};
+
+#endif /* __DRIVER_FLASH_RPI_H__ */
diff --git a/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI_bl2.c b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI_bl2.c
new file mode 100644
index 0000000..5878a48
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_Flash_RPI_bl2.c
@@ -0,0 +1,61 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_hal_device_header.h"
+#include "Driver_Flash_RPI.h"
+#include "RTE_Device.h"
+
+#if (RTE_FLASH0)
+
+#define RP2350_FLASH_PAGE_SIZE 0x100 /* 256B */
+#define RP2350_FLASH_SECTOR_SIZE 0x1000 /* 4KB */
+#define RP2350_FLASH_SIZE PICO_FLASH_SIZE_BYTES
+#define RP2350_FLASH_ERASE_VALUE 0xFF
+
+static ARM_FLASH_INFO RP2350_FLASH_DEV_DATA = {
+ .sector_info = NULL, /* Uniform sector layout */
+ .sector_count = RP2350_FLASH_SIZE/ RP2350_FLASH_SECTOR_SIZE,
+ .sector_size = RP2350_FLASH_SECTOR_SIZE,
+ .page_size = RP2350_FLASH_PAGE_SIZE,
+ .program_unit = RP2350_FLASH_PAGE_SIZE, /* page aligned, page multipled */
+ .erased_value = RP2350_FLASH_ERASE_VALUE
+};
+
+static uint32_t irq_state = 0;
+
+static inline uint32_t __save_disable_irq(void)
+{
+ uint32_t result = 0;
+
+ __ASM volatile ("mrs %0, primask \n cpsid i" : "=r" (result) :: "memory");
+ return result;
+}
+
+static inline void __restore_irq(uint32_t status)
+{
+ __ASM volatile ("msr primask, %0" :: "r" (status) : "memory");
+}
+
+/* No need to save and restore MPU configuration for bl2 */
+static void dummy_save(struct rp2350_flash_dev_t* flash_dev){
+ ARG_UNUSED(flash_dev);
+ irq_state = __save_disable_irq();
+}
+static void dummy_restore(void){
+ __restore_irq(irq_state);
+}
+
+static rp2350_flash_dev_t RP2350_FLASH_DEV = {
+ .data = &RP2350_FLASH_DEV_DATA,
+ .base = XIP_BASE,
+ .size = RP2350_FLASH_SIZE,
+ .save_mpu_state = dummy_save,
+ .restore_mpu_state = dummy_restore
+};
+
+
+RPI_RP2350_FLASH(RP2350_FLASH_DEV, RP2350_FLASH);
+#endif /* RTE_FLASH0 */
diff --git a/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_USART_RPI.c b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_USART_RPI.c
new file mode 100644
index 0000000..46360d4
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_USART_RPI.c
@@ -0,0 +1,16 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "Driver_USART_RPI.h"
+#include "RTE_Device.h"
+
+
+#if (defined (RTE_USART0) && (RTE_USART0 == 1))
+#define UART_TX_PIN 0
+#define UART_RX_PIN 1
+
+ARM_DRIVER_USART_RP2350((uart_inst_t *)UART0_BASE, driver_usart0, UART_RX_PIN, UART_TX_PIN);
+#endif /* RTE_USART0 */
diff --git a/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_USART_RPI.h b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_USART_RPI.h
new file mode 100644
index 0000000..09a591a
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/cmsis_drivers/Driver_USART_RPI.h
@@ -0,0 +1,380 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __DRIVER_USART_RPI_H__
+#define __DRIVER_USART_RPI_H__
+
+#include "Driver_USART.h"
+#include "hardware/gpio.h"
+#include "hardware/uart.h"
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+#include "platform_multicore.h"
+#include "hardware/structs/sio.h"
+#endif
+
+#ifndef ARG_UNUSED
+#define ARG_UNUSED(arg) (void)arg
+#endif
+
+#define ARM_USART_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0) /* driver version */
+
+/* Driver Version */
+static const ARM_DRIVER_VERSION DriverVersion = {
+ ARM_USART_API_VERSION,
+ ARM_USART_DRV_VERSION
+};
+
+/* Driver Capabilities */
+static const ARM_USART_CAPABILITIES DriverCapabilities = {
+ 1, /* supports UART (Asynchronous) mode */
+ 0, /* supports Synchronous Master mode */
+ 0, /* supports Synchronous Slave mode */
+ 0, /* supports UART Single-wire mode */
+ 0, /* supports UART IrDA mode */
+ 0, /* supports UART Smart Card mode */
+ 0, /* Smart Card Clock generator available */
+ 0, /* RTS Flow Control available */
+ 0, /* CTS Flow Control available */
+ 0, /* Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE */
+ 0, /* Signal receive character timeout event: \ref ARM_USART_EVENT_RX_TIMEOUT */
+ 0, /* RTS Line: 0=not available, 1=available */
+ 0, /* CTS Line: 0=not available, 1=available */
+ 0, /* DTR Line: 0=not available, 1=available */
+ 0, /* DSR Line: 0=not available, 1=available */
+ 0, /* DCD Line: 0=not available, 1=available */
+ 0, /* RI Line: 0=not available, 1=available */
+ 0, /* Signal CTS change event: \ref ARM_USART_EVENT_CTS */
+ 0, /* Signal DSR change event: \ref ARM_USART_EVENT_DSR */
+ 0, /* Signal DCD change event: \ref ARM_USART_EVENT_DCD */
+ 0, /* Signal RI change event: \ref ARM_USART_EVENT_RI */
+ 0 /* Reserved (must be zero) */
+};
+
+
+typedef struct {
+ uart_inst_t *dev; /* UART device */
+ uint32_t tx_nbr_bytes; /* Number of bytes transfered */
+ uint32_t rx_nbr_bytes; /* Number of bytes recevied */
+ uint32_t default_baudrate; /* UART default baudrate */
+ uint8_t rx_pin_num; /* RX pin number for GPIO config */
+ uint8_t tx_pin_num; /* TX pin number for GPIO config */
+ ARM_USART_SignalEvent_t cb_event; /* Callback function for events */
+} UARTx_Resources;
+//
+// Functions
+//
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+static inline void spinlock_claim()
+{
+ /* Reading a spinlock register attempts to claim it, returning nonzero
+ * if the claim was successful and 0 if unsuccessful */
+ while(!*UART_SPINLOCK);
+}
+
+static inline void spinlock_release()
+{
+ /* Writing to a spinlock register releases it */
+ *UART_SPINLOCK = 0x1u;
+}
+#endif
+
+static ARM_DRIVER_VERSION ARM_USART_GetVersion(void)
+{
+ return DriverVersion;
+}
+
+static ARM_USART_CAPABILITIES ARM_USART_GetCapabilities(void)
+{
+ return DriverCapabilities;
+}
+
+static inline int32_t ARM_USARTx_Initialize(UARTx_Resources *uart_dev)
+{
+ gpio_set_function(uart_dev->rx_pin_num, GPIO_FUNC_UART);
+ gpio_set_function(uart_dev->tx_pin_num, GPIO_FUNC_UART);
+ uart_init(uart_dev->dev, uart_dev->default_baudrate);
+
+ return ARM_DRIVER_OK;
+}
+
+static inline int32_t ARM_USARTx_Uninitialize(UARTx_Resources *uart_dev)
+{
+ uart_deinit(uart_dev->dev);
+
+ return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_USARTx_PowerControl(UARTx_Resources *uart_dev, ARM_POWER_STATE state)
+{
+ ARG_UNUSED(uart_dev);
+
+ switch (state) {
+ case ARM_POWER_OFF:
+ case ARM_POWER_LOW:
+ return ARM_DRIVER_ERROR_UNSUPPORTED;
+ case ARM_POWER_FULL:
+ /* Nothing to be done */
+ return ARM_DRIVER_OK;
+ /* default: The default is not defined intentionally to force the
+ * compiler to check that all the enumeration values are
+ * covered in the switch.*/
+ }
+}
+
+static inline int32_t ARM_USARTx_Send(UARTx_Resources *uart_dev,
+ const void *data,
+ uint32_t num)
+{
+ const uint8_t *p_data;
+
+ if ((data == NULL) || (num == 0U)) {
+ /* Invalid parameters */
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ spinlock_claim();
+#endif
+
+ p_data = (const uint8_t *)data;
+
+ /* Resets previous TX counter */
+ uart_dev->tx_nbr_bytes = 0;
+
+ while (uart_dev->tx_nbr_bytes != num) {
+ /* Waits until UART is ready to transmit */
+ while (!uart_is_writable(uart_dev->dev)) {
+ }
+ /* As UART is ready to transmit at this point, the write function can
+ * not return any transmit error */
+ uart_putc(uart_dev->dev, *p_data);
+
+ uart_dev->tx_nbr_bytes++;
+ p_data++;
+ }
+ uart_tx_wait_blocking(uart_dev->dev);
+
+ if (uart_dev->cb_event != NULL) {
+ uart_dev->cb_event(ARM_USART_EVENT_SEND_COMPLETE);
+ }
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ spinlock_release();
+#endif
+
+ return ARM_DRIVER_OK;
+}
+
+static inline int32_t ARM_USARTx_Receive(UARTx_Resources *uart_dev,
+ void *data, uint32_t num)
+{
+ uint8_t *p_data;
+
+ if ((data == NULL) || (num == 0U)) {
+ // Invalid parameters
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ spinlock_claim();
+#endif
+
+ p_data = (uint8_t *)data;
+
+ /* Resets previous RX counter */
+ uart_dev->rx_nbr_bytes = 0;
+
+ while (uart_dev->rx_nbr_bytes != num) {
+ /* Waits until one character is received */
+ while (uart_is_readable(uart_dev->dev)) {
+ *p_data = uart_getc(uart_dev->dev);
+
+ uart_dev->rx_nbr_bytes++;
+ p_data++;
+ }
+ }
+
+ if (uart_dev->cb_event != NULL) {
+ uart_dev->cb_event(ARM_USART_EVENT_RECEIVE_COMPLETE);
+ }
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ spinlock_release();
+#endif
+ return ARM_DRIVER_OK;
+}
+
+static inline uint32_t ARM_USARTx_GetTxCount(UARTx_Resources *uart_dev)
+{
+ return uart_dev->tx_nbr_bytes;
+}
+
+static inline uint32_t ARM_USARTx_GetRxCount(UARTx_Resources *uart_dev)
+{
+ return uart_dev->rx_nbr_bytes;
+}
+
+static inline int32_t ARM_USARTx_Control(UARTx_Resources *uart_dev,
+ uint32_t control,
+ uint32_t arg)
+{
+ switch (control & ARM_USART_CONTROL_Msk) {
+#ifdef UART_TX_RX_CONTROL_ENABLED
+ case ARM_USART_CONTROL_TX:
+ if (arg == 0) {
+ uart_get_hw(uart)->cr &= ~UART_UARTCR_TXE_BITS;
+ } else if (arg == 1) {
+ uart_get_hw(uart)->cr |= UART_UARTCR_TXE_BITS;
+ } else {
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+ break;
+ case ARM_USART_CONTROL_RX:
+ if (arg == 0) {
+ uart_get_hw(uart)->cr &= ~UART_UARTCR_RXE_BITS;
+ } else if (arg == 1) {
+ uart_get_hw(uart)->cr |= UART_UARTCR_RXE_BITS;
+ } else {
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+ break;
+#endif
+ case ARM_USART_MODE_ASYNCHRONOUS:
+ uart_set_baudrate(uart_dev->dev, arg);
+ break;
+ /* Unsupported command */
+ default:
+ return ARM_DRIVER_ERROR_UNSUPPORTED;
+ }
+
+ /* UART Data bits */
+ if (control & ARM_USART_DATA_BITS_Msk) {
+ /* Data bit is not configurable */
+ return ARM_DRIVER_ERROR_UNSUPPORTED;
+ }
+
+ /* UART Parity */
+ if (control & ARM_USART_PARITY_Msk) {
+ /* Parity is not configurable */
+ return ARM_USART_ERROR_PARITY;
+ }
+
+ /* USART Stop bits */
+ if (control & ARM_USART_STOP_BITS_Msk) {
+ /* Stop bit is not configurable */
+ return ARM_USART_ERROR_STOP_BITS;
+ }
+
+ return ARM_DRIVER_OK;
+}
+
+/*
+ * \brief Macro for USART Driver
+ *
+ * \param[in] USART_DEV uart_inst_t pointer
+ * \param[out] USART_DRIVER_NAME Resulting Driver name
+ */
+#define ARM_DRIVER_USART_RP2350(USART_DEV, USART_DRIVER_NAME, RX_PIN, TX_PIN) \
+static UARTx_Resources USART_DRIVER_NAME##_DEV = { \
+ .dev = USART_DEV, \
+ .default_baudrate = 115200, \
+ .tx_nbr_bytes = 0, \
+ .rx_nbr_bytes = 0, \
+ .rx_pin_num = RX_PIN, \
+ .tx_pin_num = TX_PIN, \
+ .cb_event = NULL, \
+}; \
+ \
+static int32_t USART_DRIVER_NAME##_Initialize( \
+ ARM_USART_SignalEvent_t cb_event) \
+{ \
+ USART_DRIVER_NAME##_DEV.cb_event = cb_event; \
+ \
+ return ARM_USARTx_Initialize(&USART_DRIVER_NAME##_DEV); \
+} \
+ \
+static int32_t USART_DRIVER_NAME##_Uninitialize(void) \
+{ \
+ return ARM_USARTx_Uninitialize(&USART_DRIVER_NAME##_DEV); \
+} \
+ \
+static int32_t USART_DRIVER_NAME##_PowerControl(ARM_POWER_STATE state) \
+{ \
+ return ARM_USARTx_PowerControl(&USART_DRIVER_NAME##_DEV, state); \
+} \
+ \
+static int32_t USART_DRIVER_NAME##_Send(const void *data, uint32_t num) \
+{ \
+ return ARM_USARTx_Send(&USART_DRIVER_NAME##_DEV, data, num); \
+} \
+ \
+static int32_t USART_DRIVER_NAME##_Receive(void *data, uint32_t num) \
+{ \
+ return ARM_USARTx_Receive(&USART_DRIVER_NAME##_DEV, data, num); \
+} \
+ \
+static int32_t USART_DRIVER_NAME##_Transfer(const void *data_out, \
+ void *data_in, \
+ uint32_t num) \
+{ \
+ ARG_UNUSED(data_out); \
+ ARG_UNUSED(data_in); \
+ ARG_UNUSED(num); \
+ \
+ return ARM_DRIVER_ERROR_UNSUPPORTED; \
+} \
+ \
+static uint32_t USART_DRIVER_NAME##_GetTxCount(void) \
+{ \
+ return ARM_USARTx_GetTxCount(&USART_DRIVER_NAME##_DEV); \
+} \
+ \
+static uint32_t USART_DRIVER_NAME##_GetRxCount(void) \
+{ \
+ return ARM_USARTx_GetRxCount(&USART_DRIVER_NAME##_DEV); \
+} \
+static int32_t USART_DRIVER_NAME##_Control(uint32_t control, uint32_t arg) \
+{ \
+ return ARM_USARTx_Control(&USART_DRIVER_NAME##_DEV, control, arg); \
+} \
+ \
+static ARM_USART_STATUS USART_DRIVER_NAME##_GetStatus(void) \
+{ \
+ ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0}; \
+ return status; \
+} \
+ \
+static int32_t USART_DRIVER_NAME##_SetModemControl( \
+ ARM_USART_MODEM_CONTROL control) \
+{ \
+ ARG_UNUSED(control); \
+ return ARM_DRIVER_ERROR_UNSUPPORTED; \
+} \
+ \
+static ARM_USART_MODEM_STATUS USART_DRIVER_NAME##_GetModemStatus(void) \
+{ \
+ ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0}; \
+ return modem_status; \
+} \
+ \
+extern ARM_DRIVER_USART USART_DRIVER_NAME; \
+ARM_DRIVER_USART USART_DRIVER_NAME = { \
+ ARM_USART_GetVersion, \
+ ARM_USART_GetCapabilities, \
+ USART_DRIVER_NAME##_Initialize, \
+ USART_DRIVER_NAME##_Uninitialize, \
+ USART_DRIVER_NAME##_PowerControl, \
+ USART_DRIVER_NAME##_Send, \
+ USART_DRIVER_NAME##_Receive, \
+ USART_DRIVER_NAME##_Transfer, \
+ USART_DRIVER_NAME##_GetTxCount, \
+ USART_DRIVER_NAME##_GetRxCount, \
+ USART_DRIVER_NAME##_Control, \
+ USART_DRIVER_NAME##_GetStatus, \
+ USART_DRIVER_NAME##_SetModemControl, \
+ USART_DRIVER_NAME##_GetModemStatus \
+}
+
+#endif /* __DRIVER_USART_RPI_H__ */
diff --git a/platform/ext/target/rpi/rp2350/cmsis_drivers/RTE_Device.h b/platform/ext/target/rpi/rp2350/cmsis_drivers/RTE_Device.h
new file mode 100644
index 0000000..5624bbd
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/cmsis_drivers/RTE_Device.h
@@ -0,0 +1,24 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
+
+#ifndef __RTE_DEVICE_H
+#define __RTE_DEVICE_H
+
+// <q> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
+// <i> Configuration settings for Driver_USART0 in component ::Drivers:USART
+#define RTE_USART0 1
+
+// <q> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
+// <i> Configuration settings for Driver_USART1 in component ::Drivers:USART
+#define RTE_USART1 0
+
+// <q> Flash device emulated in SRAM [Driver_Flash0]
+// <i> Configuration settings for Driver_Flash0 in component ::Drivers:Flash
+#define RTE_FLASH0 1
+
+#endif /* __RTE_DEVICE_H */
\ No newline at end of file
diff --git a/platform/ext/target/rpi/rp2350/config.cmake b/platform/ext/target/rpi/rp2350/config.cmake
new file mode 100644
index 0000000..342f996
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/config.cmake
@@ -0,0 +1,48 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#
+#-------------------------------------------------------------------------------
+
+set(PROVISIONING_KEYS_CONFIG "" CACHE FILEPATH "The config file which has the keys and seeds for provisioning")
+
+if(BL2)
+ set(BL2_TRAILER_SIZE 0x800 CACHE STRING "Trailer size")
+else()
+ #No header if no bootloader, but keep IMAGE_CODE_SIZE the same
+ set(BL2_TRAILER_SIZE 0xC00 CACHE STRING "Trailer size")
+endif()
+
+# Platform-specific configurations
+set(TFM_MULTI_CORE_TOPOLOGY OFF CACHE BOOL "Enable Multicore topology")
+if (TFM_MULTI_CORE_TOPOLOGY)
+ set(TFM_NS_MAILBOX_API ON)
+ set(TFM_PARTITION_NS_AGENT_MAILBOX ON)
+ set(TFM_NS_CUSTOM_API ON)
+else()
+ set(TFM_NS_MAILBOX_API OFF)
+ set(TFM_PARTITION_NS_AGENT_MAILBOX OFF)
+ set(TFM_NS_CUSTOM_API OFF)
+endif()
+
+set(CONFIG_TFM_USE_TRUSTZONE ON)
+set(MCUBOOT_USE_PSA_CRYPTO ON CACHE BOOL "Enable the cryptographic abstraction layer to use PSA Crypto APIs")
+set(MCUBOOT_SIGNATURE_TYPE "EC-P256" CACHE STRING "Algorithm to use for signature validation [RSA-2048, RSA-3072, EC-P256, EC-P384]")
+set(MCUBOOT_HW_KEY OFF CACHE BOOL "Whether to embed the entire public key in the image metadata instead of the hash only")
+set(MCUBOOT_BUILTIN_KEY ON CACHE BOOL "Use builtin key(s) for validation, no public key data is embedded into the image metadata")
+
+set(PROVISIONING_CODE_PADDED_SIZE "0x2000" CACHE STRING "")
+set(PROVISIONING_VALUES_PADDED_SIZE "0x400" CACHE STRING "")
+set(PROVISIONING_DATA_PADDED_SIZE "0x400" CACHE STRING "")
+
+set(PICO_SDK_FETCH_FROM_GIT_TAG "2.0.0" CACHE STRING "Use the define Pico SDK tag for the build")
+
+set(TFM_MBEDCRYPTO_PLATFORM_EXTRA_CONFIG_PATH ${CMAKE_CURRENT_LIST_DIR}/mbedtls_extra_config.h CACHE PATH "Config to append to standard Mbed Crypto config, used by platforms to cnfigure feature support")
+
+set(PLATFORM_DEFAULT_PROV_LINKER_SCRIPT OFF CACHE BOOL "Use default provisioning linker script")
+set(ITS_ENCRYPTION ON CACHE BOOL "Enable authenticated encryption of ITS files using platform specific APIs")
+set(PLATFORM_DEFAULT_NV_SEED OFF CACHE BOOL "Use default NV seed implementation.")
+set(PLATFORM_DEFAULT_OTP OFF CACHE BOOL "Use trusted on-chip flash to implement OTP memory")
+set(PLATFORM_DEFAULT_NV_COUNTERS OFF CACHE BOOL "Use default nv counter implementation.")
+
+set(PLATFORM_DEFAULT_CRYPTO_KEYS OFF CACHE BOOL "Use default crypto keys implementation.")
diff --git a/platform/ext/target/rpi/rp2350/config_tfm_target.h b/platform/ext/target/rpi/rp2350/config_tfm_target.h
new file mode 100644
index 0000000..dc90516
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/config_tfm_target.h
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __CONFIG_TFM_TARGET_H__
+#define __CONFIG_TFM_TARGET_H__
+
+/* Use stored NV seed to provide entropy */
+#define CRYPTO_NV_SEED 0
+
+/* Use external RNG to provide entropy */
+#define CRYPTO_EXT_RNG 1
+
+/* Run the scheduler after handling a secure interrupt if the NSPE was pre-empted */
+#define CONFIG_TFM_SCHEDULE_WHEN_NS_INTERRUPTED 1
+
+#endif /* __CONFIG_TFM_TARGET_H__ */
diff --git a/platform/ext/target/rpi/rp2350/cpuarch.cmake b/platform/ext/target/rpi/rp2350/cpuarch.cmake
new file mode 100644
index 0000000..d049ea2
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/cpuarch.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#
+#-------------------------------------------------------------------------------
+
+# Set architecture and CPU
+set(TFM_SYSTEM_PROCESSOR cortex-m33)
+set(TFM_SYSTEM_ARCHITECTURE armv8-m.main)
+
+set(TFM_SYSTEM_DSP OFF)
+set(CONFIG_TFM_FP_ARCH "fpv5-d16")
+set(CONFIG_TFM_FP_ARCH_ASM "FPv5_D16")
diff --git a/platform/ext/target/rpi/rp2350/crypto_keys.c b/platform/ext/target/rpi/rp2350/crypto_keys.c
new file mode 100644
index 0000000..4ea25be
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/crypto_keys.c
@@ -0,0 +1,155 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include <string.h>
+#include "tfm_plat_crypto_keys.h"
+#include "tfm_builtin_key_ids.h"
+#include "tfm_plat_otp.h"
+#include "psa_manifest/pid.h"
+#include "tfm_builtin_key_loader.h"
+
+#define NUMBER_OF_ELEMENTS_OF(x) sizeof(x)/sizeof(*x)
+#define MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID -0x3c000000
+#define TFM_NS_PARTITION_ID MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID
+#define MAPPED_RSE_MBOX_NS_AGENT_DEFAULT_CLIENT_ID -0x04000000
+#define TFM_NS_MAILBOX_PARTITION_ID MAPPED_RSE_MBOX_NS_AGENT_DEFAULT_CLIENT_ID
+
+static enum tfm_plat_err_t tfm_plat_get_huk(uint8_t *buf, size_t buf_len,
+ size_t *key_len,
+ psa_key_bits_t *key_bits,
+ psa_algorithm_t *algorithm,
+ psa_key_type_t *type)
+{
+ enum tfm_plat_err_t err;
+
+ err = tfm_plat_otp_read(PLAT_OTP_ID_HUK, buf_len, buf);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ err = tfm_plat_otp_get_size(PLAT_OTP_ID_HUK, key_len);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ *key_bits = *key_len * 8;
+ *algorithm = PSA_ALG_HKDF(PSA_ALG_SHA_256);
+ *type = PSA_KEY_TYPE_DERIVE;
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+static enum tfm_plat_err_t tfm_plat_get_iak(uint8_t *buf, size_t buf_len,
+ size_t *key_len,
+ psa_key_bits_t *key_bits,
+ psa_algorithm_t *algorithm,
+ psa_key_type_t *type)
+{
+ enum tfm_plat_err_t err;
+#ifndef SYMMETRIC_INITIAL_ATTESTATION
+ psa_ecc_family_t curve_type;
+#endif /* SYMMETRIC_INITIAL_ATTESTATION */
+
+ err = tfm_plat_otp_read(PLAT_OTP_ID_IAK_LEN,
+ sizeof(size_t), (uint8_t*)key_len);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+ *key_bits = *key_len * 8;
+
+ if (buf_len < *key_len) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+#ifdef SYMMETRIC_INITIAL_ATTESTATION
+ err = tfm_plat_otp_read(PLAT_OTP_ID_IAK_TYPE,
+ sizeof(psa_algorithm_t), (uint8_t*)algorithm);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ *type = PSA_KEY_TYPE_HMAC;
+#else /* SYMMETRIC_INITIAL_ATTESTATION */
+ err = tfm_plat_otp_read(PLAT_OTP_ID_IAK_TYPE, sizeof(psa_ecc_family_t),
+ &curve_type);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ *algorithm = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
+ *type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_type);
+#endif /* SYMMETRIC_INITIAL_ATTESTATION */
+
+ return tfm_plat_otp_read(PLAT_OTP_ID_IAK, *key_len, buf);
+}
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+/**
+ * @brief Table describing per-user key policy for the IAK
+ *
+ */
+static const tfm_plat_builtin_key_per_user_policy_t g_iak_per_user_policy[] = {
+ {.user = TFM_SP_INITIAL_ATTESTATION,
+#ifdef SYMMETRIC_INITIAL_ATTESTATION
+ .usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT,
+#else
+ .usage = PSA_KEY_USAGE_SIGN_HASH,
+#endif /* SYMMETRIC_INITIAL_ATTESTATION */
+ },
+#ifdef TEST_S_ATTESTATION
+ {.user = TFM_SP_SECURE_TEST_PARTITION, .usage = PSA_KEY_USAGE_VERIFY_HASH},
+#endif /* TEST_S_ATTESTATION */
+#ifdef TEST_NS_ATTESTATION
+ {.user = TFM_NS_PARTITION_ID, .usage = PSA_KEY_USAGE_VERIFY_HASH},
+ {.user = TFM_NS_MAILBOX_PARTITION_ID, .usage = PSA_KEY_USAGE_VERIFY_HASH},
+#endif /* TEST_NS_ATTESTATION */
+};
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+/**
+ * @brief Table describing per-key user policies
+ *
+ */
+static const tfm_plat_builtin_key_policy_t g_builtin_keys_policy[] = {
+ {.key_id = TFM_BUILTIN_KEY_ID_HUK, .per_user_policy = 0, .usage = PSA_KEY_USAGE_DERIVE},
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+ {.key_id = TFM_BUILTIN_KEY_ID_IAK,
+ .per_user_policy = NUMBER_OF_ELEMENTS_OF(g_iak_per_user_policy),
+ .policy_ptr = g_iak_per_user_policy},
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+};
+
+/**
+ * @brief Table describing the builtin-in keys (plaform keys) available in the platform. Note
+ * that to bind the keys to the tfm_builtin_key_loader driver, the lifetime must be
+ * explicitly set to the one associated to the driver, i.e. TFM_BUILTIN_KEY_LOADER_LIFETIME
+ */
+static const tfm_plat_builtin_key_descriptor_t g_builtin_keys_desc[] = {
+ {.key_id = TFM_BUILTIN_KEY_ID_HUK,
+ .slot_number = TFM_BUILTIN_KEY_SLOT_HUK,
+ .lifetime = TFM_BUILTIN_KEY_LOADER_LIFETIME,
+ .loader_key_func = tfm_plat_get_huk},
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+ {.key_id = TFM_BUILTIN_KEY_ID_IAK,
+ .slot_number = TFM_BUILTIN_KEY_SLOT_IAK,
+ .lifetime = TFM_BUILTIN_KEY_LOADER_LIFETIME,
+ .loader_key_func = tfm_plat_get_iak},
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+};
+
+size_t tfm_plat_builtin_key_get_policy_table_ptr(const tfm_plat_builtin_key_policy_t *desc_ptr[])
+{
+ *desc_ptr = &g_builtin_keys_policy[0];
+ return NUMBER_OF_ELEMENTS_OF(g_builtin_keys_policy);
+}
+
+size_t tfm_plat_builtin_key_get_desc_table_ptr(const tfm_plat_builtin_key_descriptor_t *desc_ptr[])
+{
+ *desc_ptr = &g_builtin_keys_desc[0];
+ return NUMBER_OF_ELEMENTS_OF(g_builtin_keys_desc);
+}
diff --git a/platform/ext/target/rpi/rp2350/device/config/device_cfg.h b/platform/ext/target/rpi/rp2350/device/config/device_cfg.h
new file mode 100644
index 0000000..f83e8d5
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/device/config/device_cfg.h
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __DEVICE_CFG_H__
+#define __DEVICE_CFG_H__
+
+/**
+ * \file device_cfg.h
+ * \brief Configurations for peripherals defined in
+ * platform's device definition
+ */
+
+#define DEFAULT_UART_CONTROL 0
+#define DEFAULT_UART_BAUDRATE 115200
+
+#endif /* __DEVICE_CFG_H__ */
diff --git a/platform/ext/target/rpi/rp2350/extra_init.c b/platform/ext/target/rpi/rp2350/extra_init.c
new file mode 100644
index 0000000..bda0fbc
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/extra_init.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "pico/runtime.h"
+#include "pico/runtime_init.h"
+#include "hardware/structs/scb.h"
+#ifdef PSA_API_TEST_CRYPTO
+#include "hardware/ticks.h"
+#include "hardware/clocks.h"
+#endif
+
+#include "stdint.h"
+
+/* Do not use __cmsis_start */
+#define __PROGRAM_START
+#include "tfm_hal_device_header.h"
+
+void copy_zero_tables(void) {
+ typedef struct {
+ uint32_t const* src;
+ uint32_t* dest;
+ uint32_t wlen;
+ } __copy_table_t;
+
+ typedef struct {
+ uint32_t* dest;
+ uint32_t wlen;
+ } __zero_table_t;
+
+ extern const __copy_table_t __copy_table_start__;
+ extern const __copy_table_t __copy_table_end__;
+ extern const __zero_table_t __zero_table_start__;
+ extern const __zero_table_t __zero_table_end__;
+
+ for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) {
+ for(uint32_t i=0u; i<pTable->wlen; ++i) {
+ pTable->dest[i] = pTable->src[i];
+ }
+ }
+
+ for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
+ for(uint32_t i=0u; i<pTable->wlen; ++i) {
+ pTable->dest[i] = 0u;
+ }
+ }
+}
+
+void hard_assertion_failure(void) {
+ SPM_ASSERT(0);
+}
+
+static void runtime_run_initializers_from(uintptr_t *from) {
+
+ /* Start and end points of the constructor list, defined by the linker script. */
+ extern uintptr_t __preinit_array_end;
+
+ /* Call each function in the list, based on the mask
+ We have to take the address of the symbols, as __preinit_array_start *is*
+ the first function value, not the address of it. */
+ for (uintptr_t *p = from; p < &__preinit_array_end; p++) {
+ uintptr_t val = *p;
+ ((void (*)(void))val)();
+ }
+}
+
+void runtime_run_initializers(void) {
+ extern uintptr_t __preinit_array_start;
+ runtime_run_initializers_from(&__preinit_array_start);
+}
+
+/* We keep the per-core initializers in the standard __preinit_array so a standard C library
+ initialization will fo the core 0 initialization, however we also want to be able to find
+ them after the fact so that we can run them on core 1. Per core initializers have sections
+ __preinit_array.ZZZZZ.nnnnn i.e. the ZZZZZ sorts below all the standard __preinit_array.nnnnn
+ values, and then we sort within the ZZZZZ.
+
+ We create a dummy initializer in __preinit_array.YYYYY (between the standard initializers
+ and the per core initializers), so we find the first per core initializer. Whilst we could
+ have done this via an entry in the linker script, we want to preserve backwards compatibility
+ with RP2040 custom linker scripts. */
+static void first_per_core_initializer(void) {}
+PICO_RUNTIME_INIT_FUNC(first_per_core_initializer, "YYYYY");
+
+void runtime_run_per_core_initializers(void) {
+ runtime_run_initializers_from(&__pre_init_first_per_core_initializer);
+}
+
+extern uint32_t __vectors_start__;
+extern uint32_t __INITIAL_SP;
+extern uint32_t __STACK_LIMIT;
+extern uint64_t __STACK_SEAL;
+
+void runtime_init(void) {
+ scb_hw->vtor = (uintptr_t) &__vectors_start__;
+ copy_zero_tables();
+
+ __disable_irq();
+ __set_PSP((uint32_t)(&__INITIAL_SP));
+
+ __set_MSPLIM((uint32_t)(&__STACK_LIMIT));
+ __set_PSPLIM((uint32_t)(&__STACK_LIMIT));
+
+ __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL));
+
+ runtime_run_initializers();
+
+#ifdef PSA_API_TEST_CRYPTO
+ /* RSA Key generation test takes very long. Use 4 times slower WD
+ reference tick when it is enabled. */
+ tick_start(TICK_WATCHDOG, 4 * clock_get_hz(clk_ref) / MHZ);
+#endif
+
+ SystemInit();
+}
diff --git a/platform/ext/target/rpi/rp2350/linker_bl2.ld b/platform/ext/target/rpi/rp2350/linker_bl2.ld
new file mode 100644
index 0000000..5dfd04c
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/linker_bl2.ld
@@ -0,0 +1,284 @@
+;/*
+; * SPDX-License-Identifier: BSD-3-Clause
+; * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+; *
+; */
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+#include "region_defs.h"
+MEMORY
+{
+ FLASH (rx) : ORIGIN = BL2_CODE_START, LENGTH = BL2_CODE_SIZE
+ RAM (rwx) : ORIGIN = BL2_DATA_START, LENGTH = BL2_DATA_SIZE
+#ifdef __ENABLE_SCRATCH__
+ SCRATCH_X(rwx) : ORIGIN = SCRATCH_X_START, LENGTH = SCRATCH_X_SIZE
+ SCRATCH_Y(rwx) : ORIGIN = SCRATCH_Y_START, LENGTH = SCRATCH_Y_SIZE
+#endif
+}
+__heap_size__ = BL2_HEAP_SIZE;
+__msp_stack_size__ = BL2_MSP_STACK_SIZE;
+ENTRY(Reset_Handler)
+SECTIONS
+{
+ .flash_begin : {
+ __flash_binary_start = .;
+ } > FLASH
+ .text (READONLY) :
+ {
+ __logical_binary_start = .;
+ __Vectors_Start = .;
+ KEEP(*(.vectors))
+ __Vectors_End = .;
+ __Vectors_Size = __Vectors_End - __Vectors_Start;
+ KEEP (*(.binary_info_header))
+ __binary_info_header_end = .;
+ KEEP (*(.embedded_block))
+ __embedded_block_end = .;
+ KEEP (*(.reset))
+ __end__ = .;
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(SORT(.preinit_array.*)))
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ /* .copy.table */
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+#ifdef CODE_SHARING
+ LONG (LOADADDR(.tfm_shared_symbols))
+ LONG (ADDR(.tfm_shared_symbols))
+ LONG (SIZEOF(.tfm_shared_symbols) / 4)
+#endif
+ LONG (LOADADDR(.data))
+ LONG (ADDR(.data))
+ LONG (SIZEOF(.data) / 4)
+ __copy_table_end__ = .;
+ /* .zero.table */
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ LONG (ADDR(.bss))
+ LONG (SIZEOF(.bss) / 4)
+ __zero_table_end__ = .;
+ KEEP(*(.init))
+ *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
+ KEEP(*(.fini))
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+ *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
+ *(.srodata*)
+ . = ALIGN(4);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
+ . = ALIGN(4);
+ KEEP(*(.eh_frame*))
+ . = ALIGN(4);
+ } > FLASH
+ /* Note the boot2 section is optional, and should be discarded if there is
+ no reference to it *inside* the binary, as it is not called by the
+ bootrom. (The bootrom performs a simple best-effort XIP setup and
+ leaves it to the binary to do anything more sophisticated.) However
+ there is still a size limit of 256 bytes, to ensure the boot2 can be
+ stored in boot RAM.
+ Really this is a "XIP setup function" -- the name boot2 is historic and
+ refers to its dual-purpose on RP2040, where it also handled vectoring
+ from the bootrom into the user image.
+ */
+ .boot2 : {
+ __boot2_start__ = .;
+ *(.boot2)
+ __boot2_end__ = .;
+ } > FLASH
+ ASSERT(__boot2_end__ - __boot2_start__ <= 256,
+ "ERROR: Pico second stage bootloader must be no more than 256 bytes in size")
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+ /* Machine inspectable binary information */
+ . = ALIGN(4);
+ __binary_info_start = .;
+ .binary_info :
+ {
+ KEEP(*(.binary_info.keep.*))
+ *(.binary_info.*)
+ } > FLASH
+ __binary_info_end = .;
+#ifdef CODE_SHARING
+ /* The code sharing between bootloader and runtime firmware requires to
+ * share the global variables. Section size must be equal with
+ * SHARED_SYMBOL_AREA_SIZE defined in region_defs.h
+ */
+ .tfm_shared_symbols : ALIGN(4)
+ {
+ *(.data.mbedtls_calloc_func)
+ *(.data.mbedtls_free_func)
+ *(.data.mbedtls_exit)
+ *(.data.memset_func)
+ . = ALIGN(SHARED_SYMBOL_AREA_SIZE);
+ } > RAM AT > FLASH
+ ASSERT(SHARED_SYMBOL_AREA_SIZE % 4 == 0, "SHARED_SYMBOL_AREA_SIZE must be divisible by 4")
+#endif
+ .tfm_bl2_shared_data : ALIGN(32)
+ {
+ . += BOOT_TFM_SHARED_DATA_SIZE;
+ } > RAM
+ Image$$SHARED_DATA$$RW$$Base = ADDR(.tfm_bl2_shared_data);
+ Image$$SHARED_DATA$$RW$$Limit = ADDR(.tfm_bl2_shared_data) + SIZEOF(.tfm_bl2_shared_data);
+ . = ALIGN(4);
+ .ram_vector_table (NOLOAD): {
+ *(.ram_vector_table)
+ } > RAM
+ .data : ALIGN(4)
+ {
+ __data_start__ = .;
+ *(vtable)
+ *(.time_critical*)
+ /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
+ *(.text*)
+ . = ALIGN(4);
+ *(.rodata*)
+ . = ALIGN(4);
+ *(.data*)
+ *(.sdata*)
+ . = ALIGN(4);
+ *(.after_data.*)
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__mutex_array_start = .);
+ KEEP(*(SORT(.mutex_array.*)))
+ KEEP(*(.mutex_array))
+ PROVIDE_HIDDEN (__mutex_array_end = .);
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+ } > RAM AT > FLASH
+ __etext = LOADADDR(.data);
+ Image$$ER_DATA$$Base = ADDR(.data);
+ .uninitialized_data (NOLOAD): {
+ . = ALIGN(4);
+ *(.uninitialized_data*)
+ } > RAM
+ .bss : ALIGN(4)
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
+ *(COMMON)
+ PROVIDE(__global_pointer$ = . + 2K);
+ *(.sbss*)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ .msp_stack ALIGN(32) :
+ {
+ . += __msp_stack_size__ - 0x8;
+ } > RAM
+ Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
+ Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
+ .msp_stack_seal_res :
+ {
+ . += 0x8;
+ } > RAM
+ __StackSeal = ADDR(.msp_stack_seal_res);
+#else
+ .msp_stack ALIGN(32) :
+ {
+ . += __msp_stack_size__;
+ } > RAM
+ Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
+ Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+#ifdef __ENABLE_SCRATCH__
+ /* Start and end symbols must be word-aligned */
+ .scratch_x : {
+ __scratch_x_start__ = .;
+ *(.scratch_x.*)
+ . = ALIGN(4);
+ __scratch_x_end__ = .;
+ } > SCRATCH_X AT > FLASH
+ __scratch_x_source__ = LOADADDR(.scratch_x);
+ .scratch_y : {
+ __scratch_y_start__ = .;
+ *(.scratch_y.*)
+ . = ALIGN(4);
+ __scratch_y_end__ = .;
+ } > SCRATCH_Y AT > FLASH
+ __scratch_y_source__ = LOADADDR(.scratch_y);
+#endif
+ .heap (NOLOAD): ALIGN(8)
+ {
+ . = ALIGN(8);
+ __end__ = .;
+ PROVIDE(end = .);
+ __HeapBase = .;
+ KEEP(*(.heap*))
+ . += __heap_size__;
+ __HeapLimit = .;
+ __heap_limit = .; /* Add for _sbrk */
+ } > RAM
+ Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap);
+ /* .stack*_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later
+ *
+ * stack1 section may be empty/missing if platform_launch_core1 is not used */
+ /* by default we put core 0 stack at the end of scratch Y, so that if core 1
+ * stack is not used then all of SCRATCH_X is free.
+ */
+#ifdef __ENABLE_SCRATCH__
+ .stack1_dummy (NOLOAD):
+ {
+ *(.stack1*)
+ } > SCRATCH_X
+ .stack_dummy (NOLOAD):
+ {
+ KEEP(*(.stack*))
+ } > SCRATCH_Y
+#endif
+ .flash_end : {
+ PROVIDE(__flash_binary_end = .);
+ } > FLASH =0xaa
+ PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
+#ifdef __ENABLE_SCRATCH__
+ /* stack limit is poorly named, but historically is maximum heap ptr */
+ __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
+ __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
+ __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
+ __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
+ __StackBottom = __StackTop - SIZEOF(.stack_dummy);
+ /* Check if data + heap + stack exceeds RAM limit */
+ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
+#endif
+ ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
+ /* todo assert on extra code */
+}
diff --git a/platform/ext/target/rpi/rp2350/linker_ns.ld b/platform/ext/target/rpi/rp2350/linker_ns.ld
new file mode 100644
index 0000000..3e27443
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/linker_ns.ld
@@ -0,0 +1,242 @@
+;/*
+; * SPDX-License-Identifier: BSD-3-Clause
+; * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+; *
+; */
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+#include "region_defs.h"
+/* Include file with definitions for section alignments.
+ * Note: it should be included after region_defs.h to let platform define
+ * default values if needed. */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = NS_CODE_START, LENGTH = NS_CODE_SIZE
+ RAM (rwx) : ORIGIN = NS_DATA_START, LENGTH = NS_DATA_SIZE
+#ifdef __ENABLE_SCRATCH__
+ SCRATCH_X(rwx) : ORIGIN = SRAM_SCRATCH_X_BASE, LENGTH = SCRATCH_X_SIZE
+ SCRATCH_Y(rwx) : ORIGIN = SRAM_SCRATCH_Y_BASE, LENGTH = SCRATCH_Y_SIZE
+#endif
+}
+
+__heap_size__ = NS_HEAP_SIZE;
+__stack_size__ = NS_STACK_SIZE;
+ENTRY(_entry_point)
+SECTIONS
+{
+ .vectors :
+ {
+ __logical_binary_start = .;
+ __Vectors_Start__ = .;
+ KEEP(*(.vectors))
+ __Vectors_End = .;
+ __Vectors_Size = __Vectors_End - __Vectors_Start__;
+ __end__ = .;
+ } > FLASH
+
+#if defined(NS_VECTOR_ALLOCATED_SIZE)
+ ASSERT(. <= ADDR(.vectors) + NS_VECTOR_ALLOCATED_SIZE, ".vectors section size overflow.")
+ . = ADDR(.vectors) + NS_VECTOR_ALLOCATED_SIZE;
+#endif
+
+ .CORE1_ENTRY : ALIGN(4)
+ {
+ KEEP (*(.core1_ns_entry*))
+ }
+
+ .PICO_RESET : ALIGN(4)
+ {
+ KEEP (*(.binary_info_header))
+ __binary_info_header_end = .;
+ KEEP (*(.embedded_block))
+ __embedded_block_end = .;
+ KEEP (*(.reset))
+ } > FLASH
+
+ .text (READONLY) :
+ {
+ *(.text*)
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__mutex_array_start = .);
+ KEEP(*(SORT(.mutex_array.*)))
+ KEEP(*(.mutex_array))
+ PROVIDE_HIDDEN (__mutex_array_end = .);
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(SORT(.preinit_array.*)))
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ /* .copy.table */
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+ LONG (__etext)
+ LONG (__data_start__)
+ LONG ((__data_end__ - __data_start__) / 4)
+ LONG (__etext2)
+ LONG (__data2_start__)
+ LONG ((__data2_end__ - __data2_start__) / 4)
+ __copy_table_end__ = .;
+
+ /* .zero.table */
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ LONG (__bss_start__)
+ LONG ((__bss_end__ - __bss_start__) / 4)
+ LONG (__bss2_start__)
+ LONG ((__bss2_end__ - __bss2_start__) / 4)
+ __zero_table_end__ = .;
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ /* Machine inspectable binary information */
+ . = ALIGN(4);
+ __binary_info_start = .;
+ .binary_info :
+ {
+ KEEP(*(.binary_info.keep.*))
+ *(.binary_info.*)
+ } > FLASH
+ __binary_info_end = .;
+
+ __etext2 = ALIGN(4);
+
+ .data : AT (__etext2)
+ {
+ __data2_start__ = .;
+ *(vtable)
+ *(.data*)
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+ __data2_end__ = .;
+ } > RAM
+
+ /* Pico crt0.S copies the __data_start__-__data_end__ region, but we handle
+ * that in our runtime_init */
+ __etext = 0;
+ __data_start__ = 0;
+ __data_end__ = 0;
+
+ .ram_vector_table (NOLOAD): ALIGN(256) {
+ *(.ram_vector_table)
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss2_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss2_end__ = .;
+ } > RAM
+
+ /* Pico crt0.S zeros the __bss_start__-__bss_end__ region, but we handle
+ * that in our runtime_init */
+ __bss_start__ = 0;
+ __bss_end__ = 0;
+
+ bss_size = __bss2_end__ - __bss2_start__;
+
+ .heap : ALIGN(8)
+ {
+ . = ALIGN(8);
+ __end__ = .;
+ PROVIDE(end = .);
+ __HeapBase = .;
+ . += __heap_size__;
+ __HeapLimit = .;
+ __heap_limit = .; /* Add for _sbrk */
+ } > RAM
+
+ #ifdef __ENABLE_SCRATCH__
+ /* Start and end symbols must be word-aligned */
+ .scratch_x : {
+ __scratch_x_start__ = .;
+ *(.scratch_x.*)
+ . = ALIGN(4);
+ __scratch_x_end__ = .;
+ } > SCRATCH_X AT > FLASH
+ __scratch_x_source__ = LOADADDR(.scratch_x);
+ .scratch_y : {
+ __scratch_y_start__ = .;
+ *(.scratch_y.*)
+ . = ALIGN(4);
+ __scratch_y_end__ = .;
+ } > SCRATCH_Y AT > FLASH
+ __scratch_y_source__ = LOADADDR(.scratch_y);
+
+ .stack1_dummy (NOLOAD):
+ {
+ *(.stack1*)
+ } > SCRATCH_X
+ .stack_dummy (NOLOAD):
+ {
+ KEEP(*(.stack*))
+ } > SCRATCH_Y
+
+ /* stack limit is poorly named, but historically is maximum heap ptr */
+ __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
+ __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
+ __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
+ __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
+ __StackBottom = __StackTop - SIZEOF(.stack_dummy);
+ /* Check if data + heap + stack exceeds RAM limit */
+ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
+ PROVIDE(__stack = __StackTop);
+#endif
+
+ ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
+}
diff --git a/platform/ext/target/rpi/rp2350/linker_provisioning.ld b/platform/ext/target/rpi/rp2350/linker_provisioning.ld
new file mode 100644
index 0000000..a613940
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/linker_provisioning.ld
@@ -0,0 +1,50 @@
+;/*
+; * SPDX-License-Identifier: BSD-3-Clause
+; * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+; *
+; */
+
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+
+#include "region_defs.h"
+
+MEMORY
+{
+ CODE (rx) : ORIGIN = PROVISIONING_BUNDLE_CODE_START, LENGTH = PROVISIONING_BUNDLE_CODE_SIZE
+ DATA (rw) : ORIGIN = PROVISIONING_BUNDLE_DATA_START, LENGTH = PROVISIONING_BUNDLE_DATA_SIZE
+ VALUES (r) : ORIGIN = PROVISIONING_BUNDLE_VALUES_START, LENGTH = PROVISIONING_BUNDLE_VALUES_SIZE
+}
+
+ENTRY(do_provisioning)
+
+SECTIONS
+{
+ CODE :
+ {
+ *provisioning_code.o(DO_PROVISION)
+ *(.text*)
+ *(.time_critical*)
+ } > CODE
+
+ RW_DATA :
+ {
+ *(COMMON .data*)
+ } > DATA
+
+ RO_DATA :
+ {
+ *(EXCLUDE_FILE (*provisioning_data.o) .rodata*)
+ } > DATA
+
+ BSS_DATA :
+ {
+ *(.bss*)
+ } > DATA
+
+ VALUES :
+ {
+ *provisioning_data.o(.rodata.data)
+ } > VALUES
+
+}
diff --git a/platform/ext/target/rpi/rp2350/linker_s.ld b/platform/ext/target/rpi/rp2350/linker_s.ld
new file mode 100644
index 0000000..084b1fc
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/linker_s.ld
@@ -0,0 +1,576 @@
+;/*
+; * SPDX-License-Identifier: BSD-3-Clause
+; * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+; *
+; */
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+#include "region_defs.h"
+/* Include file with definitions for section alignments.
+ * Note: it should be included after region_defs.h to let platform define
+ * default values if needed. */
+#include "tfm_s_linker_alignments.h"
+MEMORY
+{
+ FLASH (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE
+ RAM (rw) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE
+#if defined(S_RAM_CODE_START)
+ CODE_RAM (rwx) : ORIGIN = S_RAM_CODE_START, LENGTH = S_RAM_CODE_SIZE
+#endif
+#ifdef __ENABLE_SCRATCH__
+ SCRATCH_X(rwx) : ORIGIN = SCRATCH_X_START, LENGTH = SCRATCH_X_SIZE
+ SCRATCH_Y(rwx) : ORIGIN = SCRATCH_Y_START, LENGTH = SCRATCH_Y_SIZE
+#endif
+}
+
+#ifndef TFM_LINKER_VENEERS_START
+#define TFM_LINKER_VENEERS_START ALIGN(TFM_LINKER_VENEERS_ALIGNMENT)
+#endif
+
+#ifndef TFM_LINKER_VENEERS_END
+#define TFM_LINKER_VENEERS_END ALIGN(TFM_LINKER_VENEERS_ALIGNMENT)
+#endif
+
+#define VENEERS() \
+/* \
+ * Place the CMSE Veneers (containing the SG instruction) after the code, in \
+ * a separate at least 32 bytes aligned region so that the SAU can \
+ * programmed to just set this region as Non-Secure Callable. \
+ */ \
+.gnu.sgstubs TFM_LINKER_VENEERS_START : \
+{ \
+ *(.gnu.sgstubs*) \
+} > FLASH \
+/* GCC always places veneers at the end of .gnu.sgstubs section, so the only \
+ * way to align the end of .gnu.sgstubs section is to align start of the \
+ * next section */ \
+.sgstubs_end : TFM_LINKER_VENEERS_END \
+{ \
+} > FLASH
+
+__msp_stack_size__ = S_MSP_STACK_SIZE;
+
+ENTRY(_entry_point)
+
+SECTIONS
+{
+ /* Start address of the code. */
+ Image$$PT_RO_START$$Base = ADDR(.TFM_VECTORS);
+
+ .TFM_VECTORS : ALIGN(4)
+ {
+ __logical_binary_start = .;
+ __vectors_start__ = .;
+ KEEP(*(.vectors))
+ . = ALIGN(4);
+ __vectors_end__ = .;
+ } > FLASH
+
+ ASSERT(__vectors_start__ != __vectors_end__, ".vectors should not be empty")
+
+#if defined(S_CODE_VECTOR_TABLE_SIZE)
+ ASSERT(. <= ADDR(.TFM_VECTORS) + S_CODE_VECTOR_TABLE_SIZE, ".TFM_VECTORS section size overflow.")
+ . = ADDR(.TFM_VECTORS) + S_CODE_VECTOR_TABLE_SIZE;
+#endif
+
+ .PICO_RESET : ALIGN(4)
+ {
+ KEEP (*(.binary_info_header))
+ __binary_info_header_end = .;
+ KEEP (*(.embedded_block))
+ __embedded_block_end = .;
+ KEEP (*(.reset))
+ } > FLASH
+
+#if defined(CONFIG_TFM_USE_TRUSTZONE) && !defined(TFM_LINKER_VENEERS_LOCATION_END)
+ VENEERS()
+#endif
+
+ /**** Section for holding partition RO load data */
+ /*
+ * Sort the partition info by priority to guarantee the initing order.
+ * The first loaded partition will be inited at last in SFN model.
+ */
+ .TFM_SP_LOAD_LIST ALIGN(4) :
+ {
+ KEEP(*(.part_load_priority_00))
+ KEEP(*(.part_load_priority_01))
+ KEEP(*(.part_load_priority_02))
+ KEEP(*(.part_load_priority_03))
+ } > FLASH
+ Image$$TFM_SP_LOAD_LIST$$RO$$Base = ADDR(.TFM_SP_LOAD_LIST);
+ Image$$TFM_SP_LOAD_LIST$$RO$$Limit = ADDR(.TFM_SP_LOAD_LIST) + SIZEOF(.TFM_SP_LOAD_LIST);
+
+ /**** PSA RoT RO part (CODE + RODATA) start here */
+ . = ALIGN(TFM_LINKER_PSA_ROT_LINKER_CODE_ALIGNMENT);
+ Image$$TFM_PSA_CODE_START$$Base = .;
+
+ .TFM_PSA_ROT_LINKER ALIGN(TFM_LINKER_PSA_ROT_LINKER_CODE_ALIGNMENT) :
+ {
+ *tfm_psa_rot_partition*:(SORT_BY_ALIGNMENT(.text*))
+ *tfm_psa_rot_partition*:(SORT_BY_ALIGNMENT(.rodata*))
+ *(TFM_*_PSA-ROT_ATTR_FN)
+ . = ALIGN(TFM_LINKER_PSA_ROT_LINKER_CODE_ALIGNMENT);
+ } > FLASH
+
+ Image$$TFM_PSA_ROT_LINKER$$RO$$Base = ADDR(.TFM_PSA_ROT_LINKER);
+ Image$$TFM_PSA_ROT_LINKER$$RO$$Limit = ADDR(.TFM_PSA_ROT_LINKER) + SIZEOF(.TFM_PSA_ROT_LINKER);
+ Image$$TFM_PSA_ROT_LINKER$$Base = ADDR(.TFM_PSA_ROT_LINKER);
+ Image$$TFM_PSA_ROT_LINKER$$Limit = ADDR(.TFM_PSA_ROT_LINKER) + SIZEOF(.TFM_PSA_ROT_LINKER);
+
+ /**** PSA RoT RO part (CODE + RODATA) end here */
+ Image$$TFM_PSA_CODE_END$$Base = .;
+
+ /**** APPLICATION RoT RO part (CODE + RODATA) start here */
+ Image$$TFM_APP_CODE_START$$Base = .;
+
+ .TFM_APP_ROT_LINKER ALIGN(TFM_LINKER_APP_ROT_LINKER_CODE_ALIGNMENT) :
+ {
+ *tfm_app_rot_partition*:(SORT_BY_ALIGNMENT(.text*))
+ *tfm_app_rot_partition*:(SORT_BY_ALIGNMENT(.rodata*))
+ *(TFM_*_APP-ROT_ATTR_FN)
+ . = ALIGN(TFM_LINKER_APP_ROT_LINKER_CODE_ALIGNMENT);
+ } > FLASH
+
+ Image$$TFM_APP_ROT_LINKER$$RO$$Base = ADDR(.TFM_APP_ROT_LINKER);
+ Image$$TFM_APP_ROT_LINKER$$RO$$Limit = ADDR(.TFM_APP_ROT_LINKER) + SIZEOF(.TFM_APP_ROT_LINKER);
+ Image$$TFM_APP_ROT_LINKER$$Base = ADDR(.TFM_APP_ROT_LINKER);
+ Image$$TFM_APP_ROT_LINKER$$Limit = ADDR(.TFM_APP_ROT_LINKER) + SIZEOF(.TFM_APP_ROT_LINKER);
+
+ /**** APPLICATION RoT RO part (CODE + RODATA) end here */
+ Image$$TFM_APP_CODE_END$$Base = .;
+
+#if defined(S_RAM_CODE_START)
+ /* Flash drivers code that gets copied from Flash */
+ .ER_CODE_SRAM ALIGN(S_RAM_CODE_START, 4) :
+ {
+ *libflash_drivers*:(SORT_BY_ALIGNMENT(.text*))
+ *libflash_drivers*:(SORT_BY_ALIGNMENT(.rodata*))
+ KEEP(*(.ramfunc))
+ . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */
+ } > CODE_RAM AT > FLASH
+
+ ASSERT(S_RAM_CODE_START % 4 == 0, "S_RAM_CODE_START must be divisible by 4")
+
+ Image$$ER_CODE_SRAM$$RO$$Base = ADDR(.ER_CODE_SRAM);
+ Image$$ER_CODE_SRAM$$RO$$Limit = ADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM);
+ Image$$ER_CODE_SRAM$$Base = ADDR(.ER_CODE_SRAM);
+ Image$$ER_CODE_SRAM$$Limit = ADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM);
+#endif
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ /* Machine inspectable binary information */
+ . = ALIGN(4);
+ __binary_info_start = .;
+ .binary_info :
+ {
+ KEEP(*(.binary_info.keep.*))
+ *(.binary_info.*)
+ } > FLASH
+ __binary_info_end = .;
+
+ /* Data copy is done by extra_init */
+ __etext = 0;
+ __data_start__ = 0;
+ __data_end__ = 0;
+
+ .ER_TFM_CODE ALIGN(4) (READONLY) :
+ {
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__mutex_array_start = .);
+ KEEP(*(SORT(.mutex_array.*)))
+ KEEP(*(.mutex_array))
+ PROVIDE_HIDDEN (__mutex_array_end = .);
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(SORT(.preinit_array.*)))
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ /* .copy.table */
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+#ifdef RAM_VECTORS_SUPPORT
+ /* Copy interrupt vectors from flash to RAM */
+ LONG (__vectors_start__) /* From */
+ LONG (__ram_vectors_start__) /* To */
+ LONG ((__vectors_end__ - __vectors_start__) / 4) /* Size */
+#endif
+ LONG (LOADADDR(.TFM_DATA))
+ LONG (ADDR(.TFM_DATA))
+ LONG (SIZEOF(.TFM_DATA) / 4)
+
+ LONG (LOADADDR(.TFM_PSA_ROT_LINKER_DATA))
+ LONG (ADDR(.TFM_PSA_ROT_LINKER_DATA))
+ LONG (SIZEOF(.TFM_PSA_ROT_LINKER_DATA) / 4)
+
+ LONG (LOADADDR(.TFM_APP_ROT_LINKER_DATA))
+ LONG (ADDR(.TFM_APP_ROT_LINKER_DATA))
+ LONG (SIZEOF(.TFM_APP_ROT_LINKER_DATA) / 4)
+
+#if defined (S_RAM_CODE_START)
+ LONG (LOADADDR(.ER_CODE_SRAM))
+ LONG (ADDR(.ER_CODE_SRAM))
+ LONG (SIZEOF(.ER_CODE_SRAM) / 4)
+#endif
+ __copy_table_end__ = .;
+
+ /* .zero.table */
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ LONG (ADDR(.TFM_BSS))
+ LONG (SIZEOF(.TFM_BSS) / 4)
+ LONG (ADDR(.TFM_PSA_ROT_LINKER_BSS))
+ LONG (SIZEOF(.TFM_PSA_ROT_LINKER_BSS) / 4)
+
+ LONG (ADDR(.TFM_APP_ROT_LINKER_BSS))
+ LONG (SIZEOF(.TFM_APP_ROT_LINKER_BSS) / 4)
+#if defined(CONFIG_TFM_PARTITION_META)
+ LONG (ADDR(.TFM_SP_META_PTR))
+ LONG (SIZEOF(.TFM_SP_META_PTR) / 4)
+#endif
+ __zero_table_end__ = .;
+
+ *startup*(.text*)
+ /* Remove flash driver related files */
+ EXCLUDE_FILE (*libplatform_s*:*Flash_RPI*) *libplatform_s*:(SORT_BY_ALIGNMENT(.text*))
+ *libtfm_spm*:(SORT_BY_ALIGNMENT(.text*))
+
+ EXCLUDE_FILE (*libplatform_s*:*Flash_RPI*) *libplatform_s*:*(.rodata*)
+ *libtfm_spm*:*(.rodata*)
+ } > FLASH
+
+ .TFM_UNPRIV_CODE ALIGN(TFM_LINKER_UNPRIV_CODE_ALIGNMENT) :
+ {
+ /* Remove flash driver related files */
+ EXCLUDE_FILE (*libplatform_s*:*Flash_RPI*) *(SORT_BY_ALIGNMENT(.text*))
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(SORT_BY_ALIGNMENT(.rodata*))
+ . = ALIGN(4);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
+
+ KEEP(*(.eh_frame*))
+ . = ALIGN(TFM_LINKER_UNPRIV_CODE_ALIGNMENT);
+ } > FLASH
+ Image$$TFM_UNPRIV_CODE_START$$RO$$Base = ADDR(.TFM_UNPRIV_CODE);
+ Image$$TFM_UNPRIV_CODE_END$$RO$$Limit = ADDR(.TFM_UNPRIV_CODE) + SIZEOF(.TFM_UNPRIV_CODE);
+
+#if defined(CONFIG_TFM_USE_TRUSTZONE) && defined(TFM_LINKER_VENEERS_LOCATION_END)
+ VENEERS()
+#endif
+
+ /* Position tag */
+ . = ALIGN(TFM_LINKER_PT_RO_ALIGNMENT);
+ Image$$PT_RO_END$$Base = .;
+
+ /**** Base address of secure data area */
+ .tfm_secure_data_start :
+ {
+ /* Relocate current position to RAM */
+ . = ALIGN(4);
+ } > RAM
+
+ /*
+ * MPU on Armv6-M/v7-M core in multi-core topology may require more strict
+ * alignment that MPU region base address must align with the MPU region
+ * size.
+ * As a result, on Armv6-M/v7-M cores, to save memory resource and MPU
+ * regions, unprivileged data sections and privileged data sections are
+ * separated and gathered in unprivileged/privileged data area respectively.
+ * Keep BL2 shared data and MSP stack at the beginning of the secure data
+ * area on Armv8-M cores, while move the two areas to the beginning of
+ * privileged data region on Armv6-M/v7-M cores.
+ */
+#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) || \
+ defined(__ARM_ARCH_8_1M_MAIN__)
+#ifdef CODE_SHARING
+ /* The code sharing between bootloader and runtime requires to share the
+ * global variables.
+ */
+ .TFM_SHARED_SYMBOLS ALIGN(TFM_LINKER_SHARED_SYMBOLS_ALIGNMENT) :
+ {
+ . += SHARED_SYMBOL_AREA_SIZE;
+ } > RAM
+#endif
+
+ /* shared_data and msp_stack are overlapping on purpose when
+ * msp_stack is extended until the beginning of RAM, when shared_date
+ * was read out by partitions
+ */
+ .tfm_bl2_shared_data ALIGN(TFM_LINKER_BL2_SHARED_DATA_ALIGNMENT) :
+ {
+ . += BOOT_TFM_SHARED_DATA_SIZE;
+ } > RAM
+
+ .msp_stack ALIGN(TFM_LINKER_MSP_STACK_ALIGNMENT) :
+ {
+ . += __msp_stack_size__ - 0x8;
+ } > RAM
+ Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
+ Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
+
+ .msp_stack_seal_res :
+ {
+ . += 0x8;
+ } > RAM
+ __StackSeal = ADDR(.msp_stack_seal_res);
+
+#endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) || \
+ * defined(__ARM_ARCH_8_1M_MAIN__) */
+
+ .ram_vector_table (NOLOAD): ALIGN(256) {
+ *(.ram_vector_table)
+ } > RAM
+
+#if defined(ENABLE_HEAP)
+ __heap_size__ = S_HEAP_SIZE;
+ .heap (NOLOAD): ALIGN(8)
+ {
+ . = ALIGN(8);
+ __end__ = .;
+ end = __end__;
+ PROVIDE(end = .);
+ __HeapBase = .;
+ KEEP(*(.heap*))
+ . += __heap_size__;
+ __HeapLimit = .;
+ __heap_limit = .;
+ } > RAM
+#else
+ end = 0;
+#endif
+
+#if defined(CONFIG_TFM_PARTITION_META)
+ .TFM_SP_META_PTR ALIGN(TFM_LINKER_SP_META_PTR_ALIGNMENT) (NOLOAD):
+ {
+ *(.bss.SP_META_PTR_SPRTL_INST)
+ . = ALIGN(TFM_LINKER_SP_META_PTR_ALIGNMENT);
+ } > RAM
+ Image$$TFM_SP_META_PTR$$ZI$$Base = ADDR(.TFM_SP_META_PTR);
+ Image$$TFM_SP_META_PTR$$ZI$$Limit = ADDR(.TFM_SP_META_PTR) + SIZEOF(.TFM_SP_META_PTR);
+ /* This is needed for the uniform configuration of MPU region. */
+ Image$$TFM_SP_META_PTR_END$$ZI$$Limit = Image$$TFM_SP_META_PTR$$ZI$$Limit;
+#endif
+
+ /**** APPLICATION RoT DATA start here */
+ . = ALIGN(TFM_LINKER_APP_ROT_LINKER_DATA_ALIGNMENT);
+ Image$$TFM_APP_RW_STACK_START$$Base = .;
+
+ .TFM_APP_ROT_LINKER_DATA ALIGN(TFM_LINKER_APP_ROT_LINKER_DATA_ALIGNMENT) :
+ {
+ *tfm_app_rot_partition*:(SORT_BY_ALIGNMENT(.data*))
+ *(TFM_*_APP-ROT_ATTR_RW)
+ . = ALIGN(4);
+ } > RAM AT> FLASH
+ Image$$TFM_APP_ROT_LINKER_DATA$$RW$$Base = ADDR(.TFM_APP_ROT_LINKER_DATA);
+ Image$$TFM_APP_ROT_LINKER_DATA$$RW$$Limit = ADDR(.TFM_APP_ROT_LINKER_DATA) + SIZEOF(.TFM_APP_ROT_LINKER_DATA);
+
+ .TFM_APP_ROT_LINKER_BSS ALIGN(4) (NOLOAD) :
+ {
+ start_of_TFM_APP_ROT_LINKER = .;
+ *tfm_app_rot_partition*:(SORT_BY_ALIGNMENT(.bss*))
+ *tfm_app_rot_partition*:*(COMMON)
+ *(TFM_*_APP-ROT_ATTR_ZI)
+ . += (. - start_of_TFM_APP_ROT_LINKER) ? 0 : 4;
+ . = ALIGN(TFM_LINKER_APP_ROT_LINKER_DATA_ALIGNMENT);
+ } > RAM AT> RAM
+ Image$$TFM_APP_ROT_LINKER_DATA$$ZI$$Base = ADDR(.TFM_APP_ROT_LINKER_BSS);
+ Image$$TFM_APP_ROT_LINKER_DATA$$ZI$$Limit = ADDR(.TFM_APP_ROT_LINKER_BSS) + SIZEOF(.TFM_APP_ROT_LINKER_BSS);
+
+ /**** APPLICATION RoT DATA end here */
+ Image$$TFM_APP_RW_STACK_END$$Base = .;
+
+ /**** PSA RoT DATA start here */
+
+ Image$$TFM_PSA_RW_STACK_START$$Base = .;
+
+ .TFM_PSA_ROT_LINKER_DATA ALIGN(TFM_LINKER_PSA_ROT_LINKER_DATA_ALIGNMENT) :
+ {
+ *tfm_psa_rot_partition*:(SORT_BY_ALIGNMENT(.data*))
+ *(TFM_*_PSA-ROT_ATTR_RW)
+ . = ALIGN(4);
+ } > RAM AT> FLASH
+ Image$$TFM_PSA_ROT_LINKER_DATA$$RW$$Base = ADDR(.TFM_PSA_ROT_LINKER_DATA);
+ Image$$TFM_PSA_ROT_LINKER_DATA$$RW$$Limit = ADDR(.TFM_PSA_ROT_LINKER_DATA) + SIZEOF(.TFM_PSA_ROT_LINKER_DATA);
+
+ .TFM_PSA_ROT_LINKER_BSS ALIGN(4) (NOLOAD) :
+ {
+ start_of_TFM_PSA_ROT_LINKER = .;
+ *tfm_psa_rot_partition*:(SORT_BY_ALIGNMENT(.bss*))
+ *tfm_psa_rot_partition*:*(COMMON)
+ *(TFM_*_PSA-ROT_ATTR_ZI)
+ . += (. - start_of_TFM_PSA_ROT_LINKER) ? 0 : 4;
+ . = ALIGN(TFM_LINKER_PSA_ROT_LINKER_DATA_ALIGNMENT);
+ } > RAM AT> RAM
+ Image$$TFM_PSA_ROT_LINKER_DATA$$ZI$$Base = ADDR(.TFM_PSA_ROT_LINKER_BSS);
+ Image$$TFM_PSA_ROT_LINKER_DATA$$ZI$$Limit = ADDR(.TFM_PSA_ROT_LINKER_BSS) + SIZEOF(.TFM_PSA_ROT_LINKER_BSS);
+
+ /**** PSA RoT DATA end here */
+ Image$$TFM_PSA_RW_STACK_END$$Base = .;
+
+#ifdef RAM_VECTORS_SUPPORT
+ .ramVectors ALIGN(TFM_LINKER_RAM_VECTORS_ALIGNMENT) (NOLOAD) :
+ {
+ __ram_vectors_start__ = .;
+ KEEP(*(.ram_vectors))
+ __ram_vectors_end__ = .;
+ } > RAM
+ .TFM_DATA __ram_vectors_end__ :
+#else
+
+ .TFM_DATA ALIGN(4) :
+#endif
+ {
+ *(vtable)
+ *(.time_critical*)
+ *(*libplatform_s*:*Flash_RPI* .text*)
+ *(*libplatform_s*:*Flash_RPI* .rodata*)
+ *(SORT_BY_ALIGNMENT(.data*))
+ *(.sdata*)
+ . = ALIGN(4);
+ *(.after_data.*)
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+
+ } > RAM AT> FLASH
+ Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+
+ .uninitialized_data (NOLOAD): {
+ . = ALIGN(4);
+ *(.uninitialized_data*)
+ } > RAM AT> RAM
+
+ .TFM_BSS ALIGN(4) (NOLOAD) :
+ {
+ __bss_start__ = .;
+
+ /* The runtime partition placed order is same as load partition */
+ __partition_runtime_start__ = .;
+ KEEP(*(.bss.part_runtime_priority_00))
+ KEEP(*(.bss.part_runtime_priority_01))
+ KEEP(*(.bss.part_runtime_priority_02))
+ KEEP(*(.bss.part_runtime_priority_03))
+ __partition_runtime_end__ = .;
+ . = ALIGN(4);
+
+ /* The runtime service placed order is same as load partition */
+ __service_runtime_start__ = .;
+ KEEP(*(.bss.serv_runtime_priority_00))
+ KEEP(*(.bss.serv_runtime_priority_01))
+ KEEP(*(.bss.serv_runtime_priority_02))
+ KEEP(*(.bss.serv_runtime_priority_03))
+ __service_runtime_end__ = .;
+ *(SORT_BY_ALIGNMENT(.bss*))
+ *(COMMON)
+ *(.sbss*)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM AT> RAM
+ Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__;
+ Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__;
+ Image$$ER_SERV_RT_POOL$$ZI$$Base = __service_runtime_start__;
+ Image$$ER_SERV_RT_POOL$$ZI$$Limit = __service_runtime_end__;
+
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
+
+#if defined(CONFIG_TFM_USE_TRUSTZONE)
+ Image$$ER_VENEER$$Base = ADDR(.gnu.sgstubs);
+ Image$$VENEER_ALIGN$$Limit = ADDR(.sgstubs_end);
+
+#if defined(TFM_LINKER_VENEERS_SIZE)
+ ASSERT ((Image$$VENEER_ALIGN$$Limit - Image$$ER_VENEER$$Base) <= TFM_LINKER_VENEERS_SIZE, "Veneer region overflowed")
+#endif
+#endif
+
+ Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START;
+
+#ifdef BL2
+ Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START;
+#endif /* BL2 */
+
+ PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
+
+#ifdef __ENABLE_SCRATCH__
+ /* Start and end symbols must be word-aligned */
+ .scratch_x : {
+ __scratch_x_start__ = .;
+ *(.scratch_x.*)
+ . = ALIGN(4);
+ __scratch_x_end__ = .;
+ } > SCRATCH_X AT > FLASH
+ __scratch_x_source__ = LOADADDR(.scratch_x);
+ .scratch_y : {
+ __scratch_y_start__ = .;
+ *(.scratch_y.*)
+ . = ALIGN(4);
+ __scratch_y_end__ = .;
+ } > SCRATCH_Y AT > FLASH
+ __scratch_y_source__ = LOADADDR(.scratch_y);
+
+ .stack1_dummy (NOLOAD):
+ {
+ *(.stack1*)
+ } > SCRATCH_X
+ .stack_dummy (NOLOAD):
+ {
+ KEEP(*(.stack*))
+ } > SCRATCH_Y
+
+ PROVIDE(__StackBottom = Image$$ARM_LIB_STACK$$ZI$$Base);
+ PROVIDE(__StackTop = Image$$ARM_LIB_STACK$$ZI$$Limit);
+ __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
+ __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
+#endif
+
+ ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
+}
diff --git a/platform/ext/target/rpi/rp2350/mbedtls_extra_config.h b/platform/ext/target/rpi/rp2350/mbedtls_extra_config.h
new file mode 100644
index 0000000..0d29541
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/mbedtls_extra_config.h
@@ -0,0 +1,11 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#undef MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG 1
+
+#define PSA_WANT_ALG_GCM 1
+
diff --git a/platform/ext/target/rpi/rp2350/ns/CMakeLists.txt b/platform/ext/target/rpi/rp2350/ns/CMakeLists.txt
new file mode 100644
index 0000000..7de958b
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/ns/CMakeLists.txt
@@ -0,0 +1,177 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#
+#-------------------------------------------------------------------------------
+
+# initialize pico-sdk from GIT
+set(PICO_SDK_FETCH_FROM_GIT on)
+set(PICO_PLATFORM rp2350-arm-s)
+set(SKIP_BOOT_STAGE2 1)
+
+# initialize the Raspberry Pi Pico SDK
+include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_import.cmake)
+pico_sdk_init()
+
+get_target_property(pico_link_options pico_standard_link INTERFACE_LINK_OPTIONS)
+list(FILTER pico_link_options EXCLUDE REGEX "LINKER.*--script")
+list(APPEND pico_link_options "--entry=_entry_point")
+set_target_properties(pico_standard_link PROPERTIES INTERFACE_LINK_OPTIONS "${pico_link_options}")
+set_target_properties(pico_runtime PROPERTIES INTERFACE_LINK_OPTIONS "")
+
+
+cmake_policy(SET CMP0076 NEW)
+
+set(PLATFORM_DIR ${CMAKE_CURRENT_LIST_DIR})
+set(STATIC_ASSERT_OVERRIDE_HEADER "${PLATFORM_DIR}/static_assert_override.h")
+
+add_library(static_assert_override INTERFACE)
+add_library(device_definition INTERFACE)
+add_library(platform_ns STATIC)
+
+target_link_options(tfm_ns PRIVATE "LINKER:--no-warn-rwx-segments;LINKER:--entry=_entry_point")
+
+add_library(platform_ns_init INTERFACE)
+target_sources(platform_ns_init
+ INTERFACE
+ extra_init_ns.c
+)
+
+target_link_libraries(platform_ns_init
+ INTERFACE
+ cmsis_core_headers
+ pico_runtime_init
+ pico_runtime_headers
+ static_assert_override
+ pico_bootrom_headers
+ hardware_clocks
+)
+
+target_compile_definitions(platform_ns_init
+ INTERFACE
+ $<$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>:TFM_MULTI_CORE_TOPOLOGY>
+)
+
+# Note: This should be Private and in tfm_ns_scatter
+target_compile_definitions(platform_region_defs
+ INTERFACE
+ # u modifier in scatter file is not valid
+ NO_U_MODIFIER=1
+)
+#========================= Platform region defs ===============================#
+
+target_include_directories(platform_region_defs
+ INTERFACE
+ partition
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${PLATFORM_DIR}/include
+ ${PLATFORM_DIR}/device/config
+)
+
+target_link_libraries(platform_region_defs
+ INTERFACE
+ hardware_regs_headers
+ static_assert_override
+)
+
+target_compile_options(static_assert_override
+ INTERFACE
+ "$<$<C_COMPILER_ID:Armclang>:SHELL:-include ${STATIC_ASSERT_OVERRIDE_HEADER}>"
+ "$<$<C_COMPILER_ID:GNU>:SHELL:-include ${STATIC_ASSERT_OVERRIDE_HEADER}>"
+ "$<$<C_COMPILER_ID:IAR>:SHELL:--preinclude ${STATIC_ASSERT_OVERRIDE_HEADER}>"
+)
+
+#========================= Device definition lib ===============================#
+
+target_include_directories(device_definition
+ INTERFACE
+ .
+ device/include
+ native_drivers
+ partition
+ libraries
+ native_drivers
+ ${PLATFORM_DIR}/ext/target/arm/drivers/flash/common
+ ${PLATFORM_DIR}/ext/target/arm/drivers/usart/cmsdk
+ ${PLATFORM_DIR}/ext/target/arm/drivers/usart/common
+ ${PLATFORM_DIR}/ext/target/arm/drivers/mpc_sie
+ ${PLATFORM_DIR}/ext/target/arm/drivers/mpu/armv8m
+ ${PLATFORM_DIR}/ext/target/arm/drivers/counter/armv8m
+ ${PLATFORM_DIR}/ext/target/arm/drivers/timer/armv8m
+ ${ETHOS_DRIVER_PATH}/src
+ ${ETHOS_DRIVER_PATH}/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/device/config
+)
+
+#========================= Platform Non-Secure ================================#
+
+target_sources(platform_ns
+ PRIVATE
+ $<$<BOOL:${TFM_NS_MAILBOX_API}>:platform_ns_mailbox.c>
+ cmsis_drivers/Driver_USART_RPI.c
+ ${PLATFORM_DIR}/ext/target/arm/drivers/usart/cmsdk/uart_cmsdk_drv.c
+)
+
+target_include_directories(platform_ns
+ PUBLIC
+ cmsis_drivers
+ ${PLATFORM_DIR}/ext/cmsis/Include
+ ${PLATFORM_DIR}/ext/cmsis/Include/m-profile
+ ${PLATFORM_DIR}/include
+ ${PLATFORM_DIR}/ext/common
+)
+
+target_link_libraries(platform_ns
+ PUBLIC
+ cmsis_core_headers
+ platform_ns_init
+ PRIVATE
+ device_definition
+ pico_crt0
+ $<$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>:pico_multicore>
+ hardware_regs
+ hardware_flash
+ hardware_uart
+ cmsis_core
+)
+
+target_compile_definitions(platform_ns
+ PUBLIC
+ PICO_UART_DEFAULT_CRLF=1
+ CMSIS_device_header=<RP2350.h>
+ PICO_DEFAULT_TIMER=1
+ $<$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>:TFM_MULTI_CORE_TOPOLOGY>
+)
+
+if (TFM_NS_CUSTOM_API)
+ target_sources(tfm_api_ns PRIVATE
+ ${INTERFACE_SRC_DIR}/os_wrapper/tfm_ns_interface_rtos.c
+ )
+
+ add_library(tfm_api_ns_custom INTERFACE)
+
+ target_sources(tfm_api_ns_custom
+ INTERFACE
+ tfm_custom_psa_ns_api.c
+ )
+
+ target_link_libraries(tfm_api_ns_custom
+ INTERFACE
+ ${INTERFACE_SRC_DIR}/../lib/s_veneers.o
+ )
+
+ target_link_libraries(tfm_api_ns
+ PRIVATE
+ tfm_api_ns_custom
+ os_wrapper
+ )
+
+ # lib parth
+ set(APP_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../../lib)
+
+ target_sources(RTX_OS
+ INTERFACE
+ # Provide TZ context management stub to RTOS if protected by Trustzone
+ ${APP_LIB_DIR}/nsid_manager/tz_shim_layer.c
+ )
+endif()
diff --git a/platform/ext/target/rpi/rp2350/ns/extra_init_ns.c b/platform/ext/target/rpi/rp2350/ns/extra_init_ns.c
new file mode 100644
index 0000000..0941ece
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/ns/extra_init_ns.c
@@ -0,0 +1,84 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "hardware/clocks.h"
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+#include "hardware/structs/sio.h"
+#include "hardware/structs/scb.h"
+#include "tfm_multi_core_api.h"
+#endif
+
+#include "stdint.h"
+
+/* Do not use __cmsis_start */
+#define __PROGRAM_START
+#include "tfm_hal_device_header.h"
+
+void copy_zero_tables(void) {
+ typedef struct {
+ uint32_t const* src;
+ uint32_t* dest;
+ uint32_t wlen;
+ } __copy_table_t;
+
+ typedef struct {
+ uint32_t* dest;
+ uint32_t wlen;
+ } __zero_table_t;
+
+ extern const __copy_table_t __copy_table_start__;
+ extern const __copy_table_t __copy_table_end__;
+ extern const __zero_table_t __zero_table_start__;
+ extern const __zero_table_t __zero_table_end__;
+
+ for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) {
+ for(uint32_t i=0u; i<pTable->wlen; ++i) {
+ pTable->dest[i] = pTable->src[i];
+ }
+ }
+
+ for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
+ for(uint32_t i=0u; i<pTable->wlen; ++i) {
+ pTable->dest[i] = 0u;
+ }
+ }
+}
+
+void __weak hard_assertion_failure(void) {
+ panic("Hard assert");
+}
+
+extern void runtime_init_install_ram_vector_table(void);
+extern uint32_t ram_vector_table[PICO_RAM_VECTOR_TABLE_SIZE];
+
+void runtime_init(void) {
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ if(sio_hw->cpuid == 0) {
+ scb_hw->vtor = (uintptr_t) ram_vector_table;
+ return;
+ }
+#endif
+ copy_zero_tables();
+ runtime_init_install_ram_vector_table();
+
+ /* These are already configured by the Secure side, just fill the array */
+ clock_set_reported_hz(clk_ref, XOSC_KHZ * KHZ);
+ clock_set_reported_hz(clk_sys, SYS_CLK_KHZ * KHZ);
+ clock_set_reported_hz(clk_peri, SYS_CLK_KHZ * KHZ);
+ clock_set_reported_hz(clk_hstx, SYS_CLK_KHZ * KHZ);
+ clock_set_reported_hz(clk_usb, USB_CLK_KHZ * KHZ);
+ clock_set_reported_hz(clk_adc, USB_CLK_KHZ * KHZ);
+
+ SystemInit();
+}
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+int32_t tfm_ns_wait_for_s_cpu_ready(void)
+{
+ return tfm_platform_ns_wait_for_s_cpu_ready();
+}
+#endif
diff --git a/platform/ext/target/rpi/rp2350/ns/platform_ns_mailbox.c b/platform/ext/target/rpi/rp2350/ns/platform_ns_mailbox.c
new file mode 100644
index 0000000..469eacf
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/ns/platform_ns_mailbox.c
@@ -0,0 +1,154 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+/* FIXME: This shouldn't be required when TFM_PLAT_SPECIFIC_MULTI_CORE_COMM is
+ * enabled.
+ */
+
+#include "tfm_ns_mailbox.h"
+#include "platform_multicore.h"
+#include "region.h"
+
+#include "pico/multicore.h"
+#include "hardware/irq.h"
+#include "hardware/structs/scb.h"
+#include "hardware/structs/sio.h"
+
+#include "tfm_hal_device_header.h"
+#include "uart_stdout.h"
+#include "Driver_Common.h"
+
+int32_t tfm_ns_platform_init(void)
+{
+ if(sio_hw->cpuid == 0) {
+ __enable_irq();
+ } else {
+ /* Core1 */
+ __enable_irq();
+ stdio_init();
+ }
+
+ return ARM_DRIVER_OK;
+}
+
+/* Platform specific inter-processor communication interrupt handler. */
+void SIO_IRQ_FIFO_NS_IRQHandler(void)
+{
+ uint32_t msg;
+ if(multicore_fifo_rvalid())
+ {
+ msg = multicore_fifo_pop_blocking();
+ if (msg == NOTIFY_FROM_CORE0) {
+ /* Handle all the pending replies */
+ tfm_ns_mailbox_wake_reply_owner_isr();
+ }
+ }
+}
+
+int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue)
+{
+ uint32_t stage;
+
+ if(sio_hw->cpuid == 0) {
+ return MAILBOX_SUCCESS;
+ }
+
+ if (!queue) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ NVIC_SetVector(SIO_IRQ_FIFO_NS_IRQn, (uint32_t) SIO_IRQ_FIFO_NS_IRQHandler);
+
+ /*
+ * Wait until SPE mailbox library is ready to receive NSPE mailbox queue
+ * address.
+ */
+ while (1) {
+ stage = multicore_fifo_pop_blocking();
+ if (stage == NS_MAILBOX_INIT) {
+ break;
+ }
+ }
+
+ /* Send out the address */
+ struct mailbox_init_t ns_init;
+ ns_init.status = &queue->status;
+ ns_init.slot_count = NUM_MAILBOX_QUEUE_SLOT;
+ ns_init.slots = &queue->slots[0];
+ multicore_fifo_push_blocking((uint32_t) &ns_init);
+
+ /* Wait until SPE mailbox service is ready */
+ while (1) {
+ stage = multicore_fifo_pop_blocking();
+ if (stage == S_MAILBOX_READY) {
+ break;
+ }
+ }
+
+ NVIC_EnableIRQ(SIO_IRQ_FIFO_NS_IRQn);
+
+ return MAILBOX_SUCCESS;
+}
+
+int32_t tfm_ns_mailbox_hal_notify_peer(void)
+{
+ multicore_fifo_push_blocking(NOTIFY_FROM_CORE1);
+ return 0;
+}
+
+void tfm_ns_mailbox_hal_enter_critical(void)
+{
+ /* Reading a spinlock register attempts to claim it, returning nonzero
+ * if the claim was successful and 0 if unsuccessful */
+ while(!*MAILBOX_SPINLOCK);
+ return;
+}
+
+void tfm_ns_mailbox_hal_exit_critical(void)
+{
+ /* Writing to a spinlock register releases it */
+ *MAILBOX_SPINLOCK = 0x1u;
+ return;
+}
+
+void tfm_ns_mailbox_hal_enter_critical_isr(void)
+{
+ /* Reading a spinlock register attempts to claim it, returning nonzero
+ * if the claim was successful and 0 if unsuccessful */
+ while(!*MAILBOX_SPINLOCK);
+ return;
+}
+
+void tfm_ns_mailbox_hal_exit_critical_isr(void)
+{
+ /* Writing to a spinlock register releases it */
+ *MAILBOX_SPINLOCK = 0x1u;
+ return;
+}
+
+extern void runtime_init(void);
+extern int main(void);
+extern uint32_t __StackOneTop;
+extern uint32_t __Vectors_Start__;
+
+void __attribute__((section(".core1_ns_entry"), used, naked)) core1_ns_entry(void)
+{
+ scb_hw->vtor = (uintptr_t) &__Vectors_Start__;
+ __set_MSP((uint32_t)(&__StackOneTop));
+ __set_PSP((uint32_t)(&__StackOneTop));
+ runtime_init();
+ main();
+}
+
+#include "stdio.h"
+int32_t tfm_platform_ns_wait_for_s_cpu_ready(void)
+{
+ if(sio_hw->cpuid == 1) {
+ /* Core1 */
+ multicore_fifo_push_blocking(CORE1_NS_READY);
+ }
+ return 0;
+}
diff --git a/platform/ext/target/rpi/rp2350/ns/tfm_custom_psa_ns_api.c b/platform/ext/target/rpi/rp2350/ns/tfm_custom_psa_ns_api.c
new file mode 100644
index 0000000..3d45f5a
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/ns/tfm_custom_psa_ns_api.c
@@ -0,0 +1,234 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "psa/client.h"
+#include "tfm_ns_interface.h"
+#include "tfm_psa_call_pack.h"
+#include "tfm_mailbox.h"
+#include "tfm_ns_mailbox.h"
+
+#include "hardware/structs/sio.h"
+
+/*
+ * TODO
+ * Currently, force all the non-secure client to share the same ID.
+ *
+ * It requires a more clear mechanism to synchronize the non-secure client
+ * ID with SPE in dual core scenario.
+ * In current design, the value is transferred to SPE via mailbox message.
+ * A dedicated routine to receive the non-secure client information in
+ * TF-M core/SPM in dual core scenario should be added besides current
+ * implementation for single Armv8-M.
+ * The non-secure client identification is shared with SPE in
+ * single Armv8-M scenario via CMSIS TrustZone context management API,
+ * which may not work in dual core scenario.
+ */
+#define NON_SECURE_CLIENT_ID (-1)
+
+/*
+ * TODO
+ * Require a formal definition of errors related to mailbox in PSA client call.
+ */
+#define PSA_INTER_CORE_COMM_ERR (INT32_MIN + 0xFF)
+
+/**** TZ API functions ****/
+
+uint32_t tz_psa_framework_version(void)
+{
+ return tfm_ns_interface_dispatch(
+ (veneer_fn)tfm_psa_framework_version_veneer,
+ 0,
+ 0,
+ 0,
+ 0);
+}
+
+uint32_t tz_psa_version(uint32_t sid)
+{
+ return tfm_ns_interface_dispatch(
+ (veneer_fn)tfm_psa_version_veneer,
+ sid,
+ 0,
+ 0,
+ 0);
+}
+
+psa_status_t tz_psa_call(psa_handle_t handle, int32_t type,
+ const psa_invec *in_vec,
+ size_t in_len,
+ psa_outvec *out_vec,
+ size_t out_len)
+{
+ if ((type > PSA_CALL_TYPE_MAX) ||
+ (type < PSA_CALL_TYPE_MIN) ||
+ (in_len > PSA_MAX_IOVEC) ||
+ (out_len > PSA_MAX_IOVEC)) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
+ }
+
+ return tfm_ns_interface_dispatch(
+ (veneer_fn)tfm_psa_call_veneer,
+ (uint32_t)handle,
+ PARAM_PACK(type, in_len, out_len),
+ (uint32_t)in_vec,
+ (uint32_t)out_vec);
+}
+
+psa_handle_t tz_psa_connect(uint32_t sid, uint32_t version)
+{
+ return tfm_ns_interface_dispatch((veneer_fn)tfm_psa_connect_veneer, sid, version, 0, 0);
+}
+
+void tz_psa_close(psa_handle_t handle)
+{
+ (void)tfm_ns_interface_dispatch((veneer_fn)tfm_psa_close_veneer, (uint32_t)handle, 0, 0, 0);
+}
+
+/**** Mailbox API functions ****/
+
+uint32_t mb_psa_framework_version(void)
+{
+ struct psa_client_params_t params;
+ uint32_t version;
+ int32_t ret;
+
+ ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_FRAMEWORK_VERSION,
+ ¶ms, NON_SECURE_CLIENT_ID,
+ (int32_t *)&version);
+ if (ret != MAILBOX_SUCCESS) {
+ version = PSA_VERSION_NONE;
+ }
+
+ return version;
+}
+
+uint32_t mb_psa_version(uint32_t sid)
+{
+ struct psa_client_params_t params;
+ uint32_t version;
+ int32_t ret;
+
+ params.psa_version_params.sid = sid;
+
+ ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_VERSION, ¶ms,
+ NON_SECURE_CLIENT_ID,
+ (int32_t *)&version);
+ if (ret != MAILBOX_SUCCESS) {
+ version = PSA_VERSION_NONE;
+ }
+
+ return version;
+}
+
+psa_handle_t mb_psa_connect(uint32_t sid, uint32_t version)
+{
+ struct psa_client_params_t params;
+ psa_handle_t psa_handle;
+ int32_t ret;
+
+ params.psa_connect_params.sid = sid;
+ params.psa_connect_params.version = version;
+
+ ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_CONNECT, ¶ms,
+ NON_SECURE_CLIENT_ID,
+ (int32_t *)&psa_handle);
+ if (ret != MAILBOX_SUCCESS) {
+ psa_handle = PSA_NULL_HANDLE;
+ }
+
+ return psa_handle;
+}
+
+psa_status_t mb_psa_call(psa_handle_t handle, int32_t type,
+ const psa_invec *in_vec, size_t in_len,
+ psa_outvec *out_vec, size_t out_len)
+{
+ struct psa_client_params_t params;
+ int32_t ret;
+ psa_status_t status;
+
+ params.psa_call_params.handle = handle;
+ params.psa_call_params.type = type;
+ params.psa_call_params.in_vec = in_vec;
+ params.psa_call_params.in_len = in_len;
+ params.psa_call_params.out_vec = out_vec;
+ params.psa_call_params.out_len = out_len;
+
+ ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_CALL, ¶ms,
+ NON_SECURE_CLIENT_ID,
+ (int32_t *)&status);
+ if (ret != MAILBOX_SUCCESS) {
+ status = PSA_INTER_CORE_COMM_ERR;
+ }
+
+ return status;
+}
+
+void mb_psa_close(psa_handle_t handle)
+{
+ struct psa_client_params_t params;
+ int32_t reply;
+
+ params.psa_close_params.handle = handle;
+
+ (void)tfm_ns_mailbox_client_call(MAILBOX_PSA_CLOSE, ¶ms,
+ NON_SECURE_CLIENT_ID, &reply);
+}
+
+/**** API functions ****/
+
+uint32_t psa_framework_version(void)
+{
+ if(sio_hw->cpuid == 0) {
+ return tz_psa_framework_version();
+ } else {
+ return mb_psa_framework_version();
+ }
+}
+
+uint32_t psa_version(uint32_t sid)
+{
+ if(sio_hw->cpuid == 0) {
+ return tz_psa_version(sid);
+ } else {
+ return mb_psa_version(sid);
+ }
+}
+
+psa_status_t psa_call(psa_handle_t handle, int32_t type,
+ const psa_invec *in_vec,
+ size_t in_len,
+ psa_outvec *out_vec,
+ size_t out_len)
+{
+ if(sio_hw->cpuid == 0) {
+ return tz_psa_call(handle, type, in_vec, in_len, out_vec, out_len);
+ } else {
+ return mb_psa_call(handle, type, in_vec, in_len, out_vec, out_len);
+ }
+}
+
+psa_handle_t psa_connect(uint32_t sid, uint32_t version)
+{
+ if(sio_hw->cpuid == 0) {
+ return tz_psa_connect(sid, version);
+ } else {
+ return mb_psa_connect(sid, version);
+ }
+}
+
+void psa_close(psa_handle_t handle)
+{
+ if(sio_hw->cpuid == 0) {
+ return tz_psa_close(handle);
+ } else {
+ return mb_psa_close(handle);
+ }
+}
diff --git a/platform/ext/target/rpi/rp2350/nv_counters.c b/platform/ext/target/rpi/rp2350/nv_counters.c
new file mode 100644
index 0000000..fcab604
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/nv_counters.c
@@ -0,0 +1,168 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_plat_nv_counters.h"
+#include "tfm_plat_otp.h"
+
+#include <limits.h>
+#include <string.h>
+
+#define OTP_COUNTER_MAX_SIZE 64
+#define NV_COUNTER_SIZE 4
+#define OTP_COUNTER_MAGIC 0xAEC7
+
+enum tfm_plat_err_t tfm_plat_init_nv_counter(void)
+{
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+static enum tfm_plat_err_t read_otp_counter(enum tfm_otp_element_id_t id,
+ uint8_t *val)
+{
+ size_t counter_size;
+ enum tfm_plat_err_t err;
+ size_t idx;
+ uint16_t counter_value[OTP_COUNTER_MAX_SIZE / sizeof(uint16_t)] = {0};
+ uint32_t count;
+
+ err = tfm_plat_otp_get_size(id, &counter_size);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ counter_size = counter_size > OTP_COUNTER_MAX_SIZE ? OTP_COUNTER_MAX_SIZE
+ : counter_size;
+
+ err = tfm_plat_otp_read(id, counter_size, (uint8_t *)counter_value);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ count = 0;
+ for (idx = 0; idx < counter_size / sizeof(uint16_t); idx++) {
+ if (counter_value[idx] == OTP_COUNTER_MAGIC) {
+ count += 1;
+ } else if (counter_value[idx] == 0) {
+ break;
+ } else {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ memcpy(val, &count, NV_COUNTER_SIZE);
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t size, uint8_t *val)
+{
+ if (size != NV_COUNTER_SIZE) {
+ return TFM_PLAT_ERR_INVALID_INPUT;
+ }
+
+ /* Assumes Platform nv counters are contiguous*/
+ if (counter_id >= PLAT_NV_COUNTER_BL2_0 &&
+ counter_id < (PLAT_NV_COUNTER_BL2_0 + MCUBOOT_IMAGE_NUMBER)) {
+ return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_BL2_0 +
+ (counter_id - PLAT_NV_COUNTER_BL2_0),
+ val);
+ }
+
+ switch (counter_id) {
+ case (PLAT_NV_COUNTER_NS_0):
+ return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_0, val);
+ case (PLAT_NV_COUNTER_NS_1):
+ return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_1, val);
+ case (PLAT_NV_COUNTER_NS_2):
+ return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_2, val);
+ case (PLAT_NV_COUNTER_PS_0):
+ return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_0, val);
+ case (PLAT_NV_COUNTER_PS_1):
+ return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_1, val);
+ case (PLAT_NV_COUNTER_PS_2):
+ return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_2, val);
+
+ default:
+ return TFM_PLAT_ERR_UNSUPPORTED;
+ }
+}
+
+static enum tfm_plat_err_t set_otp_counter(enum tfm_otp_element_id_t id,
+ uint32_t val)
+{
+ size_t counter_size;
+ enum tfm_plat_err_t err;
+ size_t idx;
+ uint16_t counter_value[OTP_COUNTER_MAX_SIZE / sizeof(uint16_t)] = {0};
+
+ err = tfm_plat_otp_get_size(id, &counter_size);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ counter_size = counter_size > OTP_COUNTER_MAX_SIZE ? OTP_COUNTER_MAX_SIZE
+ : counter_size;
+
+ if (val > (counter_size / sizeof(uint16_t))) {
+ return TFM_PLAT_ERR_INVALID_INPUT;
+ }
+
+ for (idx = 0; idx < val; idx++) {
+ counter_value[idx] = OTP_COUNTER_MAGIC;
+ }
+
+ err = tfm_plat_otp_write(id, counter_size,
+ (uint8_t *)counter_value);
+
+ return err;
+}
+
+enum tfm_plat_err_t tfm_plat_set_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t value)
+{
+ /* Assumes Platform nv counters are contiguous*/
+ if (counter_id >= PLAT_NV_COUNTER_BL2_0 &&
+ counter_id < (PLAT_NV_COUNTER_BL2_0 + MCUBOOT_IMAGE_NUMBER)) {
+ return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_BL2_0 +
+ (counter_id - PLAT_NV_COUNTER_BL2_0),
+ value);
+ }
+
+ switch (counter_id) {
+ case (PLAT_NV_COUNTER_NS_0):
+ return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_0, value);
+ case (PLAT_NV_COUNTER_NS_1):
+ return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_1, value);
+ case (PLAT_NV_COUNTER_NS_2):
+ return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_2, value);
+ case (PLAT_NV_COUNTER_PS_0):
+ return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_0, value);
+ case (PLAT_NV_COUNTER_PS_1):
+ return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_1, value);
+ case (PLAT_NV_COUNTER_PS_2):
+ return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_2, value);
+
+ default:
+ return TFM_PLAT_ERR_UNSUPPORTED;
+ }
+}
+
+enum tfm_plat_err_t tfm_plat_increment_nv_counter(
+ enum tfm_nv_counter_t counter_id)
+{
+ uint32_t security_cnt;
+ enum tfm_plat_err_t err;
+
+ err = tfm_plat_read_nv_counter(counter_id,
+ sizeof(security_cnt),
+ (uint8_t *)&security_cnt);
+ if (err != TFM_PLAT_ERR_SUCCESS) {
+ return err;
+ }
+
+ return tfm_plat_set_nv_counter(counter_id, security_cnt + 1u);
+}
diff --git a/platform/ext/target/rpi/rp2350/partition/flash_layout.h b/platform/ext/target/rpi/rp2350/partition/flash_layout.h
new file mode 100644
index 0000000..6e982ea
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/partition/flash_layout.h
@@ -0,0 +1,203 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __FLASH_LAYOUT_H__
+#define __FLASH_LAYOUT_H__
+
+#include "hardware/regs/addressmap.h" /* Coming from SDK */
+
+
+#define FLASH_S_PARTITION_SIZE (0x3C000) /* 240 kB */
+#define FLASH_NS_PARTITION_SIZE (0x2F000) /* 188 kB */
+
+#define FLASH_MAX_PARTITION_SIZE FLASH_S_PARTITION_SIZE
+
+/* Sector size of the flash hardware; same as FLASH0_SECTOR_SIZE */
+#define FLASH_AREA_IMAGE_SECTOR_SIZE (0x1000) /* 4 kB */
+/* Same as FLASH0_SIZE */
+#define FLASH_TOTAL_SIZE (0x200000) /* 2MB */
+
+#if ((FLASH_S_PARTITION_SIZE % FLASH_AREA_IMAGE_SECTOR_SIZE) != 0)
+#error "Secure image size should be a multiple of flash sector size!"
+#endif
+
+#if ((FLASH_NS_PARTITION_SIZE % FLASH_AREA_IMAGE_SECTOR_SIZE) != 0)
+#error "Non-secure image size should be a multiple of flash sector size!"
+#endif
+
+/* Flash layout info for BL2 bootloader */
+#define FLASH_BASE_ADDRESS (XIP_BASE)
+
+/* Offset and size definitions of the flash partitions that are handled by the
+ * bootloader. The image swapping is done between IMAGE_PRIMARY and
+ * IMAGE_SECONDARY, SCRATCH is used as a temporary storage during image
+ * swapping.
+ */
+#define FLASH_AREA_BL2_OFFSET (0x0)
+#define FLASH_AREA_BL2_SIZE (0x11000) /* 68 kB */
+
+#if !defined(MCUBOOT_IMAGE_NUMBER) || (MCUBOOT_IMAGE_NUMBER == 1)
+/* Secure + Non-secure image primary slot */
+#define FLASH_AREA_0_ID (1)
+#define FLASH_AREA_0_OFFSET (FLASH_AREA_BL2_OFFSET + FLASH_AREA_BL2_SIZE)
+#define FLASH_AREA_0_SIZE (FLASH_S_PARTITION_SIZE + \
+ FLASH_NS_PARTITION_SIZE)
+/* Secure + Non-secure secondary slot */
+#define FLASH_AREA_2_ID (FLASH_AREA_0_ID + 1)
+#define FLASH_AREA_2_OFFSET (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE)
+#define FLASH_AREA_2_SIZE (FLASH_S_PARTITION_SIZE + \
+ FLASH_NS_PARTITION_SIZE)
+/* Scratch area */
+#define FLASH_AREA_SCRATCH_ID (FLASH_AREA_2_ID + 1)
+#define FLASH_AREA_SCRATCH_OFFSET (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE)
+#define FLASH_AREA_SCRATCH_SIZE (0x8000) /* 32 kB */
+/* The maximum number of status entries supported by the bootloader. */
+#define MCUBOOT_STATUS_MAX_ENTRIES ((FLASH_S_PARTITION_SIZE + \
+ FLASH_NS_PARTITION_SIZE) / \
+ FLASH_AREA_SCRATCH_SIZE)
+/* Maximum number of image sectors supported by the bootloader. */
+#define MCUBOOT_MAX_IMG_SECTORS ((FLASH_S_PARTITION_SIZE + \
+ FLASH_NS_PARTITION_SIZE) / \
+ FLASH_AREA_IMAGE_SECTOR_SIZE)
+#elif (MCUBOOT_IMAGE_NUMBER == 2)
+/* Secure image primary slot */
+#define FLASH_AREA_0_ID (1)
+#define FLASH_AREA_0_OFFSET (FLASH_AREA_BL2_OFFSET + FLASH_AREA_BL2_SIZE)
+#define FLASH_AREA_0_SIZE (FLASH_S_PARTITION_SIZE)
+/* Non-secure image primary slot */
+#define FLASH_AREA_1_ID (FLASH_AREA_0_ID + 1)
+#define FLASH_AREA_1_OFFSET (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE)
+#define FLASH_AREA_1_SIZE (FLASH_NS_PARTITION_SIZE)
+/* Secure image secondary slot */
+#define FLASH_AREA_2_ID (FLASH_AREA_1_ID + 1)
+#define FLASH_AREA_2_OFFSET (FLASH_AREA_1_OFFSET + FLASH_AREA_1_SIZE)
+#define FLASH_AREA_2_SIZE (FLASH_S_PARTITION_SIZE)
+/* Non-secure image secondary slot */
+#define FLASH_AREA_3_ID (FLASH_AREA_2_ID + 1)
+#define FLASH_AREA_3_OFFSET (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE)
+#define FLASH_AREA_3_SIZE (FLASH_NS_PARTITION_SIZE)
+/* Scratch area */
+#define FLASH_AREA_SCRATCH_ID (FLASH_AREA_3_ID + 1)
+#define FLASH_AREA_SCRATCH_OFFSET (FLASH_AREA_3_OFFSET + FLASH_AREA_3_SIZE)
+#define FLASH_AREA_SCRATCH_SIZE (0x8000) /* 32 kB */
+/* The maximum number of status entries supported by the bootloader. */
+#define MCUBOOT_STATUS_MAX_ENTRIES (FLASH_MAX_PARTITION_SIZE / \
+ FLASH_AREA_SCRATCH_SIZE)
+/* Maximum number of image sectors supported by the bootloader. */
+#define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \
+ FLASH_AREA_IMAGE_SECTOR_SIZE)
+#else /* MCUBOOT_IMAGE_NUMBER > 2 */
+#error "Only MCUBOOT_IMAGE_NUMBER 1 and 2 are supported!"
+#endif /* MCUBOOT_IMAGE_NUMBER */
+
+/* Protected Storage (PS) Service definitions */
+#define FLASH_PS_AREA_OFFSET (FLASH_AREA_SCRATCH_OFFSET + \
+ FLASH_AREA_SCRATCH_SIZE)
+#define FLASH_PS_AREA_SIZE (2 * FLASH_AREA_IMAGE_SECTOR_SIZE) /* 8 kB */
+
+/* Internal Trusted Storage (ITS) Service definitions */
+#define FLASH_ITS_AREA_OFFSET (FLASH_PS_AREA_OFFSET + \
+ FLASH_PS_AREA_SIZE)
+#define FLASH_ITS_AREA_SIZE (2 * FLASH_AREA_IMAGE_SECTOR_SIZE) /* 8 kB */
+
+/* OTP_definitions */
+#define FLASH_OTP_NV_COUNTERS_AREA_OFFSET (FLASH_ITS_AREA_OFFSET + \
+ FLASH_ITS_AREA_SIZE)
+#define FLASH_OTP_NV_COUNTERS_AREA_SIZE (2 * FLASH_AREA_IMAGE_SECTOR_SIZE) /* 8 kB */
+#define FLASH_OTP_NV_COUNTERS_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE
+
+#if (((FLASH_OTP_NV_COUNTERS_AREA_SIZE % FLASH_AREA_IMAGE_SECTOR_SIZE) != 0) || \
+ (FLASH_OTP_NV_COUNTERS_AREA_SIZE < (2 * FLASH_OTP_NV_COUNTERS_SECTOR_SIZE)) || \
+ (((FLASH_OTP_NV_COUNTERS_AREA_SIZE / FLASH_OTP_NV_COUNTERS_SECTOR_SIZE) % 2) != 0) \
+ )
+#error "NV_COUNTERS should be a multiple of block size and total number of blocks should be more greater than or equal to 2 and even."
+#endif
+
+#if ( FLASH_OTP_NV_COUNTERS_AREA_OFFSET + FLASH_OTP_NV_COUNTERS_AREA_SIZE > FLASH_TOTAL_SIZE)
+#error "Out of flash memory!"
+#endif
+
+/* Offset and size definition in flash area used by assemble.py */
+#define SECURE_IMAGE_OFFSET (0x0)
+#define SECURE_IMAGE_MAX_SIZE FLASH_S_PARTITION_SIZE
+
+#define NON_SECURE_IMAGE_OFFSET (SECURE_IMAGE_OFFSET + \
+ SECURE_IMAGE_MAX_SIZE)
+#define NON_SECURE_IMAGE_MAX_SIZE FLASH_NS_PARTITION_SIZE
+
+/* Flash device name used by BL2
+ * Name is defined in flash driver file: Driver_Flash_RPI.c
+ */
+#define FLASH_DEV_NAME RP2350_FLASH
+/* Smallest flash programmable unit in bytes */
+#define TFM_HAL_FLASH_PROGRAM_UNIT (0x100)
+
+/* Protected Storage (PS) Service definitions
+ * Note: Further documentation of these definitions can be found in the
+ * TF-M PS Integration Guide.
+ */
+#define TFM_HAL_PS_FLASH_DRIVER RP2350_FLASH
+
+/* In this target the CMSIS driver requires only the offset from the base
+ * address instead of the full memory address.
+ */
+/* Base address of dedicated flash area for PS */
+#define TFM_HAL_PS_FLASH_AREA_ADDR FLASH_PS_AREA_OFFSET
+/* Size of dedicated flash area for PS */
+#define TFM_HAL_PS_FLASH_AREA_SIZE FLASH_PS_AREA_SIZE
+#define PS_RAM_FS_SIZE TFM_HAL_PS_FLASH_AREA_SIZE
+/* Number of physical erase sectors per logical FS block */
+#define TFM_HAL_PS_SECTORS_PER_BLOCK (1)
+/* Smallest flash programmable unit in bytes */
+#define TFM_HAL_PS_PROGRAM_UNIT TFM_HAL_FLASH_PROGRAM_UNIT
+#define PS_FLASH_NAND_BUF_SIZE (FLASH_AREA_IMAGE_SECTOR_SIZE)
+
+#if (((TFM_HAL_PS_FLASH_AREA_SIZE % FLASH_AREA_IMAGE_SECTOR_SIZE) != 0) || \
+ ((TFM_HAL_PS_FLASH_AREA_SIZE / FLASH_AREA_IMAGE_SECTOR_SIZE) == 0) || \
+ ((TFM_HAL_PS_FLASH_AREA_SIZE / FLASH_AREA_IMAGE_SECTOR_SIZE) == 1) || \
+ ((TFM_HAL_PS_FLASH_AREA_SIZE / FLASH_AREA_IMAGE_SECTOR_SIZE) == 3) \
+ )
+#error "PS area size should be a multiple of block size and total number of blocks can not be 0, 1 or 3."
+#endif
+
+/* Internal Trusted Storage (ITS) Service definitions
+ * Note: Further documentation of these definitions can be found in the
+ * TF-M ITS Integration Guide. The ITS should be in the internal flash, but is
+ * allocated in the external flash just for development platforms that don't
+ * have internal flash available.
+ */
+#define TFM_HAL_ITS_FLASH_DRIVER RP2350_FLASH
+
+/* In this target the CMSIS driver requires only the offset from the base
+ * address instead of the full memory address.
+ */
+/* Base address of dedicated flash area for ITS */
+#define TFM_HAL_ITS_FLASH_AREA_ADDR FLASH_ITS_AREA_OFFSET
+/* Size of dedicated flash area for ITS */
+#define TFM_HAL_ITS_FLASH_AREA_SIZE FLASH_ITS_AREA_SIZE
+#define ITS_RAM_FS_SIZE TFM_HAL_ITS_FLASH_AREA_SIZE
+/* Number of physical erase sectors per logical FS block */
+#define TFM_HAL_ITS_SECTORS_PER_BLOCK (1)
+/* Smallest flash programmable unit in bytes */
+#define TFM_HAL_ITS_PROGRAM_UNIT TFM_HAL_FLASH_PROGRAM_UNIT
+#define ITS_FLASH_NAND_BUF_SIZE (2 * FLASH_AREA_IMAGE_SECTOR_SIZE)
+
+#if (((TFM_HAL_ITS_FLASH_AREA_SIZE % FLASH_AREA_IMAGE_SECTOR_SIZE) != 0) || \
+ ((TFM_HAL_ITS_FLASH_AREA_SIZE / FLASH_AREA_IMAGE_SECTOR_SIZE) == 0) || \
+ ((TFM_HAL_ITS_FLASH_AREA_SIZE / FLASH_AREA_IMAGE_SECTOR_SIZE) == 1) || \
+ ((TFM_HAL_ITS_FLASH_AREA_SIZE / FLASH_AREA_IMAGE_SECTOR_SIZE) == 3) \
+ )
+#error "ITS area size should be a multiple of block size and total number of blocks can not be 0, 1 or 3."
+#endif
+
+/* OTP / NV counter definitions */
+#define TFM_OTP_NV_COUNTERS_AREA_SIZE (FLASH_OTP_NV_COUNTERS_AREA_SIZE / 2)
+#define TFM_OTP_NV_COUNTERS_AREA_ADDR FLASH_OTP_NV_COUNTERS_AREA_OFFSET
+#define TFM_OTP_NV_COUNTERS_SECTOR_SIZE FLASH_OTP_NV_COUNTERS_SECTOR_SIZE
+#define TFM_OTP_NV_COUNTERS_BACKUP_AREA_ADDR (TFM_OTP_NV_COUNTERS_AREA_ADDR + \
+ TFM_OTP_NV_COUNTERS_AREA_SIZE)
+
+#endif /* __FLASH_LAYOUT_H__ */
diff --git a/platform/ext/target/rpi/rp2350/partition/region_defs.h b/platform/ext/target/rpi/rp2350/partition/region_defs.h
new file mode 100644
index 0000000..ec57475
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/partition/region_defs.h
@@ -0,0 +1,170 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __REGION_DEFS_H__
+#define __REGION_DEFS_H__
+
+#ifdef NO_U_MODIFIER
+#define _u(x) x
+#endif
+
+#include "flash_layout.h"
+#include "hardware/regs/addressmap.h" /* Coming from SDK */
+
+#define BL2_HEAP_SIZE (0x0001000)
+#define BL2_MSP_STACK_SIZE (0x0001800)
+
+#ifdef ENABLE_HEAP
+#define S_HEAP_SIZE (0x0000200)
+#endif
+
+#define S_MSP_STACK_SIZE (0x0000800)
+#define S_PSP_STACK_SIZE (0x0000800)
+
+#define NS_HEAP_SIZE (0x0001000)
+#define NS_STACK_SIZE (0x0001000)
+
+#ifdef BL2
+#ifndef LINK_TO_SECONDARY_PARTITION
+#define S_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_0_OFFSET)
+#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_2_OFFSET)
+#else
+#define S_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_2_OFFSET)
+#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_0_OFFSET)
+#endif /* !LINK_TO_SECONDARY_PARTITION */
+#else
+#define S_IMAGE_PRIMARY_PARTITION_OFFSET (0x0)
+#endif /* BL2 */
+
+#ifndef LINK_TO_SECONDARY_PARTITION
+#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_0_OFFSET \
+ + FLASH_S_PARTITION_SIZE)
+#else
+#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_2_OFFSET \
+ + FLASH_S_PARTITION_SIZE)
+#endif /* !LINK_TO_SECONDARY_PARTITION */
+
+/* IMAGE_CODE_SIZE is the space available for the software binary image.
+ * It is less than the FLASH_S_PARTITION_SIZE + FLASH_NS_PARTITION_SIZE
+ * because we reserve space for the image header and trailer introduced
+ * by the bootloader.
+ */
+#if (!defined(MCUBOOT_IMAGE_NUMBER) || (MCUBOOT_IMAGE_NUMBER == 1)) && \
+ (NS_IMAGE_PRIMARY_PARTITION_OFFSET > S_IMAGE_PRIMARY_PARTITION_OFFSET)
+/* If secure image and nonsecure image are concatenated, and nonsecure image
+ * locates at the higher memory range, then the secure image does not need
+ * the trailer area.
+ */
+#define IMAGE_S_CODE_SIZE \
+ (FLASH_S_PARTITION_SIZE - BL2_HEADER_SIZE)
+#else
+#define IMAGE_S_CODE_SIZE \
+ (FLASH_S_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)
+#endif
+
+#define IMAGE_NS_CODE_SIZE \
+ (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)
+
+/* Secure regions */
+#define S_IMAGE_PRIMARY_AREA_OFFSET \
+ (S_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE)
+/* Secure Code stored in Flash */
+#define S_CODE_START ((XIP_BASE) + (S_IMAGE_PRIMARY_AREA_OFFSET))
+#define S_CODE_SIZE (IMAGE_S_CODE_SIZE)
+#define S_CODE_LIMIT (S_CODE_START + S_CODE_SIZE - 1)
+
+#define S_DATA_OVERALL_SIZE (0x30000) /* 192 KB */
+
+/* Secure Data stored in SRAM0-3 */
+#define S_DATA_START (SRAM0_BASE)
+#define S_DATA_SIZE (S_DATA_OVERALL_SIZE)
+#define S_DATA_LIMIT (S_DATA_START + S_DATA_SIZE - 1)
+
+/* Size of vector table: 52 + 16 entry -> 0x110 bytes */
+/* Not defined, reason: TFM_VECTORS contain default handler implementations as
+ well, which increases the standard size, resulting a failed check in linker
+ script */
+//#define S_CODE_VECTOR_TABLE_SIZE (0x110)
+/* This is used instead of the above */
+#define NS_VECTOR_ALLOCATED_SIZE 0x124
+
+/* Non-secure regions */
+#define NS_IMAGE_PRIMARY_AREA_OFFSET \
+ (NS_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE)
+/* Non-Secure Code stored in Code SRAM memory */
+#define NS_CODE_START ((XIP_BASE) + (NS_IMAGE_PRIMARY_AREA_OFFSET))
+#define NS_CODE_SIZE (IMAGE_NS_CODE_SIZE)
+#define NS_CODE_LIMIT (NS_CODE_START + NS_CODE_SIZE - 1)
+
+/* Entry point of Core1 */
+#define NS_CODE_CORE1_START (NS_CODE_START + NS_VECTOR_ALLOCATED_SIZE)
+
+#define NS_DATA_OVERALL_SIZE (0x40000)
+
+/* Non-Secure Data stored in ISRAM0+ISRAM1 */
+#define NS_DATA_START (SRAM4_BASE)
+#define NS_DATA_SIZE (NS_DATA_OVERALL_SIZE)
+#define NS_DATA_LIMIT (NS_DATA_START + NS_DATA_SIZE - 1)
+
+/* NS partition information is used for SAU configuration */
+#define NS_PARTITION_START \
+ ((XIP_BASE) + (NS_IMAGE_PRIMARY_PARTITION_OFFSET))
+#define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE)
+
+/* Secondary partition for new images in case of firmware upgrade */
+#define SECONDARY_PARTITION_START \
+ ((XIP_BASE) + (S_IMAGE_SECONDARY_PARTITION_OFFSET))
+#define SECONDARY_PARTITION_SIZE (FLASH_S_PARTITION_SIZE + \
+ FLASH_NS_PARTITION_SIZE)
+
+#ifdef BL2
+/* Bootloader regions */
+#define BL2_CODE_START (XIP_BASE)
+#define BL2_CODE_SIZE (FLASH_AREA_BL2_SIZE)
+#define BL2_CODE_LIMIT (BL2_CODE_START + BL2_CODE_SIZE - 1)
+
+/* Bootloader uses same memory as for secure image */
+#define BL2_DATA_START (S_DATA_START)
+#define BL2_DATA_SIZE (S_DATA_SIZE)
+#define BL2_DATA_LIMIT (BL2_DATA_START + BL2_DATA_SIZE - 1)
+#endif /* BL2 */
+
+/* Shared data area between bootloader and runtime firmware.
+ * Shared data area is allocated at the beginning of the RAM, it is overlapping
+ * with TF-M Secure code's MSP stack
+ */
+#define BOOT_TFM_SHARED_DATA_BASE S_DATA_START
+#define BOOT_TFM_SHARED_DATA_SIZE (0x400)
+#define BOOT_TFM_SHARED_DATA_LIMIT (BOOT_TFM_SHARED_DATA_BASE + \
+ BOOT_TFM_SHARED_DATA_SIZE - 1)
+
+#define PROVISIONING_BUNDLE_CODE_START (NS_DATA_START)
+#define PROVISIONING_BUNDLE_CODE_SIZE (PROVISIONING_CODE_PADDED_SIZE)
+/* The max size of the values(keys, seeds) that are going to be provisioned
+ * into the OTP. */
+#define PROVISIONING_BUNDLE_VALUES_START (PROVISIONING_BUNDLE_CODE_START + PROVISIONING_BUNDLE_CODE_SIZE)
+#define PROVISIONING_BUNDLE_VALUES_SIZE (PROVISIONING_VALUES_PADDED_SIZE)
+#define PROVISIONING_BUNDLE_DATA_START (PROVISIONING_BUNDLE_VALUES_START + \
+ PROVISIONING_BUNDLE_VALUES_SIZE)
+#define PROVISIONING_BUNDLE_DATA_SIZE (PROVISIONING_DATA_PADDED_SIZE)
+
+#define PROVISIONING_BUNDLE_START (XIP_BASE + FLASH_OTP_NV_COUNTERS_AREA_OFFSET + FLASH_OTP_NV_COUNTERS_AREA_SIZE)
+#define PROVISIONING_BUNDLE_MAGIC (0x18)
+
+#if ((PROVISIONING_BUNDLE_START + PROVISIONING_BUNDLE_CODE_SIZE + PROVISIONING_BUNDLE_VALUES_SIZE + \
+ PROVISIONING_BUNDLE_DATA_SIZE + PROVISIONING_BUNDLE_MAGIC) > XIP_BASE + FLASH_TOTAL_SIZE)
+#error "Out of flash memory!"
+#endif
+
+/* Enable scratch regions for pico-rp2350 */
+#define __ENABLE_SCRATCH__
+
+#define SCRATCH_X_START (BL2_DATA_START + BL2_DATA_SIZE)
+#define SCRATCH_X_SIZE 0x1000
+#define SCRATCH_Y_START (SCRATCH_X_START + SCRATCH_X_SIZE)
+#define SCRATCH_Y_SIZE 0x1000
+
+#endif /* __REGION_DEFS_H__ */
diff --git a/platform/ext/target/rpi/rp2350/pico-sdk.patch b/platform/ext/target/rpi/rp2350/pico-sdk.patch
new file mode 100644
index 0000000..0ff2fbf
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/pico-sdk.patch
@@ -0,0 +1,39 @@
+diff --git a/src/common/pico_sync/sem.c b/src/common/pico_sync/sem.c
+index 9044817..8fc4458 100644
+--- a/src/common/pico_sync/sem.c
++++ b/src/common/pico_sync/sem.c
+@@ -15,7 +15,7 @@ void sem_init(semaphore_t *sem, int16_t initial_permits, int16_t max_permits) {
+ }
+
+ int __time_critical_func(sem_available)(semaphore_t *sem) {
+-#ifdef __GNUC__
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+ return *(volatile typeof(sem->permits) *) &sem->permits;
+ #else
+ static_assert(sizeof(sem->permits) == 2, "");
+diff --git a/src/rp2_common/pico_bootrom/CMakeLists.txt b/src/rp2_common/pico_bootrom/CMakeLists.txt
+index 0648098..93a52ea 100644
+--- a/src/rp2_common/pico_bootrom/CMakeLists.txt
++++ b/src/rp2_common/pico_bootrom/CMakeLists.txt
+@@ -8,5 +8,5 @@ target_sources(pico_bootrom INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/bootrom_lock.c
+ )
+
+-target_link_libraries(pico_bootrom_headers INTERFACE boot_picoboot_headers)
++target_link_libraries(pico_bootrom_headers INTERFACE boot_picoboot_headers boot_picobin_headers)
+ pico_mirrored_target_link_libraries(pico_bootrom INTERFACE pico_base hardware_boot_lock)
+diff --git a/src/rp2_common/pico_multicore/multicore.c b/src/rp2_common/pico_multicore/multicore.c
+index 58c2ee2..6ec689f 100644
+--- a/src/rp2_common/pico_multicore/multicore.c
++++ b/src/rp2_common/pico_multicore/multicore.c
+@@ -100,8 +100,8 @@ int core1_wrapper(int (*entry)(void), void *stack_base) {
+ void multicore_reset_core1(void) {
+ // Use atomic aliases just in case core 1 is also manipulating some PSM state
+ io_rw_32 *power_off = (io_rw_32 *) (PSM_BASE + PSM_FRCE_OFF_OFFSET);
+- io_rw_32 *power_off_set = hw_set_alias(power_off);
+- io_rw_32 *power_off_clr = hw_clear_alias(power_off);
++ io_rw_32 *power_off_set = hw_set_alias_untyped(power_off);
++ io_rw_32 *power_off_clr = hw_clear_alias_untyped(power_off);
+
+ // Hard-reset core 1.
+ // Reading back confirms the core 1 reset is in the correct state, but also
diff --git a/platform/ext/target/rpi/rp2350/pico_sdk_import.cmake b/platform/ext/target/rpi/rp2350/pico_sdk_import.cmake
new file mode 100644
index 0000000..9644ea2
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/pico_sdk_import.cmake
@@ -0,0 +1,88 @@
+# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
+
+# This can be dropped into an external project to help locate this SDK
+# It should be include()ed prior to project()
+
+if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
+ set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
+ message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
+endif ()
+
+if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
+ set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
+ message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
+endif ()
+
+if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
+ set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
+ message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
+endif ()
+
+if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
+ set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
+ message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
+endif ()
+
+if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
+ set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
+ message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
+endif()
+
+set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
+set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
+set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
+set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
+find_package(Git)
+set(PICO_SDK_PATCH_COMMAND ${GIT_EXECUTABLE} reset --hard --quiet && ${GIT_EXECUTABLE} apply "${CMAKE_CURRENT_LIST_DIR}/pico-sdk.patch")
+
+if (NOT PICO_SDK_PATH)
+ if (PICO_SDK_FETCH_FROM_GIT)
+ include(FetchContent)
+ set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
+ if (PICO_SDK_FETCH_FROM_GIT_PATH)
+ get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
+ endif ()
+ # GIT_SUBMODULES_RECURSE was added in 3.17
+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
+ FetchContent_Declare(
+ pico_sdk
+ GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
+ GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
+ GIT_SUBMODULES_RECURSE FALSE
+ PATCH_COMMAND ${PICO_SDK_PATCH_COMMAND}
+ )
+ else ()
+ FetchContent_Declare(
+ pico_sdk
+ GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
+ GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
+ PATCH_COMMAND ${PICO_SDK_PATCH_COMMAND}
+ )
+ endif ()
+
+ if (NOT pico_sdk)
+ message("Downloading Raspberry Pi Pico SDK")
+ FetchContent_Populate(pico_sdk)
+ set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
+ endif ()
+ set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
+ else ()
+ message(FATAL_ERROR
+ "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
+ )
+ endif ()
+endif ()
+
+get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
+if (NOT EXISTS ${PICO_SDK_PATH})
+ message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
+endif ()
+
+set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
+if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
+ message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
+endif ()
+
+set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
+
+include(${PICO_SDK_INIT_CMAKE_FILE})
diff --git a/platform/ext/target/rpi/rp2350/plat_test.c b/platform/ext/target/rpi/rp2350/plat_test.c
new file mode 100644
index 0000000..fef65b8
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/plat_test.c
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+
+#include "tfm_plat_test.h"
+#include "hardware/timer.h"
+#include "hardware/irq.h"
+
+#define TIMER0_IRQ0_NUM 0
+#define TIMER_MS 1000
+#define TIMER_DELAY_US (500 * TIMER_MS)
+
+extern void TFM_TIMER0_IRQ_Handler(void);
+
+#ifdef TFM_PARTITION_SLIH_TEST
+TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_SP_SLIH_TEST", "APP-ROT")
+#elif defined(TFM_PARTITION_FLIH_TEST)
+TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_SP_FLIH_TEST", "APP-ROT")
+#endif
+void tfm_plat_test_secure_timer_set_alarm_in_us(uint32_t delay_us)
+{
+ /* Load timer */
+ uint64_t target = timer0_hw->timerawl + delay_us;
+
+ /* Write the lower 32 bits of the target time to the alarm which will
+ arm it */
+ timer0_hw->alarm[TIMER0_IRQ0_NUM] = (uint32_t) target;
+}
+
+void tfm_plat_test_secure_timer_irq_handler(void)
+{
+ TFM_TIMER0_IRQ_Handler();
+ tfm_plat_test_secure_timer_set_alarm_in_us(TIMER_DELAY_US);
+}
+
+void tfm_plat_test_secure_timer_start(void)
+{
+ /* Enable Timer0_0 interrupt */
+ hw_set_bits(&timer0_hw->inte, 1u << TIMER0_IRQ0_NUM);
+ tfm_plat_test_secure_timer_set_alarm_in_us(TIMER_DELAY_US);
+}
+
+void tfm_plat_test_secure_timer_clear_intr(void)
+{
+ hw_clear_bits(&timer0_hw->intr, 1u << TIMER0_IRQ0_NUM);
+}
+
+void tfm_plat_test_secure_timer_stop(void)
+{
+ /* Disable Timer0_0 interrupt */
+ hw_clear_bits(&timer0_hw->inte, 1u << TIMER0_IRQ0_NUM);
+}
+
+void tfm_plat_test_non_secure_timer_start(void)
+{
+}
+
+void tfm_plat_test_non_secure_timer_stop(void)
+{
+}
diff --git a/platform/ext/target/rpi/rp2350/platform_builtin_key_loader_ids.h b/platform/ext/target/rpi/rp2350/platform_builtin_key_loader_ids.h
new file mode 100644
index 0000000..b76d67c
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/platform_builtin_key_loader_ids.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __PLATFORM_BUILTIN_KEY_LOADER_IDS_H__
+#define __PLATFORM_BUILTIN_KEY_LOADER_IDS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TFM_BUILTIN_MAX_KEY_LEN 96
+
+enum psa_drv_slot_number_t {
+ TFM_BUILTIN_KEY_SLOT_HUK = 0,
+ TFM_BUILTIN_KEY_SLOT_IAK,
+ TFM_BUILTIN_KEY_SLOT_MAX,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PLATFORM_BUILTIN_KEY_LOADER_IDS_H__ */
diff --git a/platform/ext/target/rpi/rp2350/platform_multicore.h b/platform/ext/target/rpi/rp2350/platform_multicore.h
new file mode 100644
index 0000000..3054886
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/platform_multicore.h
@@ -0,0 +1,48 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __PLATFORM_MULTICORE_H__
+#define __PLATFORM_MULTICORE_H__
+
+#include <stdint.h>
+
+#include "hardware/structs/sio.h"
+
+#define CORE1_S_READY 0x10
+#define CORE1_NS_READY 0x20
+#define CORE0_NS_READY 0x30
+
+#define NS_MAILBOX_INIT 0x100
+#define S_MAILBOX_READY 0x110
+
+#define NOTIFY_FROM_CORE0 0x200
+#define NOTIFY_FROM_CORE1 0x300
+
+#define HALT_DOORBELL_MASK (0x1UL << 0)
+#define FLASH_DOORBELL_MASK (0x1UL << 1)
+
+#define UART_SPINLOCK_NUM 0
+#define FLASH_SPINLOCK_NUM 1
+#define MAILBOX_SPINLOCK_NUM 2
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+#define UART_SPINLOCK (&sio_ns_hw->spinlock[UART_SPINLOCK_NUM])
+#define FLASH_SPINLOCK (&sio_hw->spinlock[FLASH_SPINLOCK_NUM])
+#define MAILBOX_SPINLOCK (&sio_ns_hw->spinlock[MAILBOX_SPINLOCK_NUM])
+#else
+#define UART_SPINLOCK (&sio_hw->spinlock[UART_SPINLOCK_NUM])
+#define MAILBOX_SPINLOCK (&sio_hw->spinlock[MAILBOX_SPINLOCK_NUM])
+#endif
+
+
+bool multicore_ns_fifo_rvalid(void);
+bool multicore_ns_fifo_wready(void);
+void multicore_ns_fifo_push_blocking_inline(uint32_t data);
+uint32_t multicore_ns_fifo_pop_blocking_inline(void);
+extern volatile uint32_t CORE1_RUNNING;
+
+
+#endif /* __PLATFORM_MULTICORE_H__ */
diff --git a/platform/ext/target/rpi/rp2350/platform_nv_counters_ids.h b/platform/ext/target/rpi/rp2350/platform_nv_counters_ids.h
new file mode 100644
index 0000000..1112e2e
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/platform_nv_counters_ids.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __PLATFORM_NV_COUNTERS_IDS_H__
+#define __PLATFORM_NV_COUNTERS_IDS_H__
+
+#include <stdint.h>
+
+enum tfm_nv_counter_t {
+ PLAT_NV_COUNTER_PS_0 = 0, /* Used by PS service */
+ PLAT_NV_COUNTER_PS_1, /* Used by PS service */
+ PLAT_NV_COUNTER_PS_2, /* Used by PS service */
+
+ /* BL2 NV counters must be contiguous */
+ PLAT_NV_COUNTER_BL2_0, /* Used by bootloader */
+ PLAT_NV_COUNTER_BL2_1, /* Used by bootloader */
+ PLAT_NV_COUNTER_BL2_2, /* Used by bootloader */
+ PLAT_NV_COUNTER_BL2_3, /* Used by bootloader */
+
+ /* NS counters must be contiguous */
+ PLAT_NV_COUNTER_NS_0, /* Used by NS */
+ PLAT_NV_COUNTER_NS_1, /* Used by NS */
+ PLAT_NV_COUNTER_NS_2, /* Used by NS */
+
+ PLAT_NV_COUNTER_MAX,
+ PLAT_NV_COUNTER_BOUNDARY = UINT32_MAX /* Fix tfm_nv_counter_t size
+ to 4 bytes */
+};
+
+#endif /* __PLATFORM_NV_COUNTERS_IDS_H__ */
diff --git a/platform/ext/target/rpi/rp2350/platform_otp_ids.h b/platform/ext/target/rpi/rp2350/platform_otp_ids.h
new file mode 100644
index 0000000..cad3f07
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/platform_otp_ids.h
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __PLATFORM_OTP_IDS_H__
+#define __PLATFORM_OTP_IDS_H__
+
+#include <stdint.h>
+
+enum tfm_otp_element_id_t {
+ PLAT_OTP_ID_HUK = 0,
+ PLAT_OTP_ID_GUK,
+ PLAT_OTP_ID_IAK,
+ PLAT_OTP_ID_IAK_LEN,
+ PLAT_OTP_ID_IAK_TYPE,
+ PLAT_OTP_ID_IAK_ID,
+
+ PLAT_OTP_ID_BOOT_SEED,
+ PLAT_OTP_ID_LCS,
+ PLAT_OTP_ID_IMPLEMENTATION_ID,
+ PLAT_OTP_ID_CERT_REF,
+ PLAT_OTP_ID_VERIFICATION_SERVICE_URL,
+ PLAT_OTP_ID_PROFILE_DEFINITION,
+
+ /* BL2 ROTPK must be contiguous */
+ PLAT_OTP_ID_BL2_ROTPK_0,
+ PLAT_OTP_ID_BL2_ROTPK_1,
+ PLAT_OTP_ID_BL2_ROTPK_2,
+ PLAT_OTP_ID_BL2_ROTPK_3,
+
+ /* BL2 NV counters must be contiguous */
+ PLAT_OTP_ID_NV_COUNTER_BL2_0,
+ PLAT_OTP_ID_NV_COUNTER_BL2_1,
+ PLAT_OTP_ID_NV_COUNTER_BL2_2,
+ PLAT_OTP_ID_NV_COUNTER_BL2_3,
+
+ PLAT_OTP_ID_NV_COUNTER_NS_0,
+ PLAT_OTP_ID_NV_COUNTER_NS_1,
+ PLAT_OTP_ID_NV_COUNTER_NS_2,
+
+ PLAT_OTP_ID_KEY_BL2_ENCRYPTION,
+ PLAT_OTP_ID_BL1_2_IMAGE,
+ PLAT_OTP_ID_BL1_2_IMAGE_HASH,
+ PLAT_OTP_ID_BL2_IMAGE_HASH,
+ PLAT_OTP_ID_BL1_ROTPK_0,
+
+ PLAT_OTP_ID_NV_COUNTER_BL1_0,
+
+ PLAT_OTP_ID_ENTROPY_SEED,
+
+ PLAT_OTP_ID_SECURE_DEBUG_PK,
+
+ PLAT_OTP_ID_NV_COUNTER_PS_0,
+ PLAT_OTP_ID_NV_COUNTER_PS_1,
+ PLAT_OTP_ID_NV_COUNTER_PS_2,
+
+ PLAT_OTP_ID_MAX = UINT32_MAX,
+};
+
+#endif /* __PLATFORM_OTP_IDS_H__ */
diff --git a/platform/ext/target/rpi/rp2350/rp2350_otp.c b/platform/ext/target/rpi/rp2350/rp2350_otp.c
new file mode 100644
index 0000000..c2f1499
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/rp2350_otp.c
@@ -0,0 +1,257 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_plat_otp.h"
+#include "pico/bootrom.h"
+#include "hardware/regs/otp_data.h"
+#include <string.h>
+
+#define OTP_BUFFER_MASK 0x0000FFFF
+#define OTP_IS_WRITE_MASK 0x00010000
+#define OTP_IS_ECC_MASK 0x00020000
+#define OTP_ROW_PER_PAGE 0x40
+
+struct rp2350_otp_element_t {
+ uint16_t row_offset; /* OTP row offset, used in otp_access() bootrom api */
+ uint8_t byte_len; /* Length of the element in bytes, should be aligned(2) or
+ aligned(4) depending usage mode */
+};
+
+/* RP2350 OTP is accessable through the bootrom api: otp_access. This OTP is
+ organized into pages and rows, it has 64 pages, each 64 rows in size, 4096
+ rows altogether. Each row has 24 bits (16 bit data, 8bit ECC). Because of its
+ structure accesses have to be aligned to 2 bytes. The default OTP elements
+ need to be placed here. This sturct serves as a map between rows and
+ tfm_otp_element_id_t ids.
+ The first 3 pages are occupied.
+*/
+static const struct rp2350_otp_element_t otp_map[] = {
+ [PLAT_OTP_ID_HUK] = {.row_offset = 0xC0 + 0x00 , .byte_len = 32 },
+ [PLAT_OTP_ID_GUK] = {.row_offset = 0xC0 + 0x10 , .byte_len = 32 },
+ [PLAT_OTP_ID_IAK] = {.row_offset = 0xC0 + 0x20 , .byte_len = 32 },
+ [PLAT_OTP_ID_IAK_LEN] = {.row_offset = 0xC0 + 0x30 , .byte_len = 4 },
+ [PLAT_OTP_ID_IAK_TYPE] = {.row_offset = 0xC0 + 0x32 , .byte_len = 4 },
+ [PLAT_OTP_ID_IAK_ID] = {.row_offset = 0xC0 + 0x34 , .byte_len = 32 },
+ [PLAT_OTP_ID_BOOT_SEED] = {.row_offset = 0xC0 + 0x44 , .byte_len = 32 },
+ [PLAT_OTP_ID_LCS] = {.row_offset = 0xC0 + 0x54 , .byte_len = 4 },
+ [PLAT_OTP_ID_IMPLEMENTATION_ID] = {.row_offset = 0xC0 + 0x56 , .byte_len = 32 },
+ [PLAT_OTP_ID_CERT_REF] = {.row_offset = 0xC0 + 0x66 , .byte_len = 32 },
+ [PLAT_OTP_ID_VERIFICATION_SERVICE_URL] = {.row_offset = 0xC0 + 0x76 , .byte_len = 32 },
+ [PLAT_OTP_ID_PROFILE_DEFINITION] = {.row_offset = 0xC0 + 0x86 , .byte_len = 32 },
+ [PLAT_OTP_ID_BL2_ROTPK_0] = {.row_offset = 0xC0 + 0x96 , .byte_len = 100},
+ [PLAT_OTP_ID_BL2_ROTPK_1] = {.row_offset = 0xC0 + 0xC8 , .byte_len = 100},
+ [PLAT_OTP_ID_BL2_ROTPK_2] = {.row_offset = 0xC0 + 0xFA , .byte_len = 100},
+ [PLAT_OTP_ID_BL2_ROTPK_3] = {.row_offset = 0xC0 + 0x12C, .byte_len = 100},
+ [PLAT_OTP_ID_NV_COUNTER_BL2_0] = {.row_offset = 0xC0 + 0x15E, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_BL2_1] = {.row_offset = 0xC0 + 0x17E, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_BL2_2] = {.row_offset = 0xC0 + 0x19E, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_BL2_3] = {.row_offset = 0xC0 + 0x1BE, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_NS_0] = {.row_offset = 0xC0 + 0x1DE, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_NS_1] = {.row_offset = 0xC0 + 0x1FE, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_NS_2] = {.row_offset = 0xC0 + 0x21E, .byte_len = 64 },
+ [PLAT_OTP_ID_KEY_BL2_ENCRYPTION] = {.row_offset = 0xC0 + 0x23E, .byte_len = 0 },
+ [PLAT_OTP_ID_BL1_2_IMAGE] = {.row_offset = 0xC0 + 0x23E, .byte_len = 0 },
+ [PLAT_OTP_ID_BL1_2_IMAGE_HASH] = {.row_offset = 0xC0 + 0x23E, .byte_len = 0 },
+ [PLAT_OTP_ID_BL2_IMAGE_HASH] = {.row_offset = 0xC0 + 0x23E, .byte_len = 0 },
+ [PLAT_OTP_ID_BL1_ROTPK_0] = {.row_offset = 0xC0 + 0x23E, .byte_len = 0 },
+ [PLAT_OTP_ID_NV_COUNTER_BL1_0] = {.row_offset = 0xC0 + 0x23E, .byte_len = 0 },
+ [PLAT_OTP_ID_ENTROPY_SEED] = {.row_offset = 0xC0 + 0x23E, .byte_len = 64 },
+ [PLAT_OTP_ID_SECURE_DEBUG_PK] = {.row_offset = 0xC0 + 0x25E, .byte_len = 32 },
+ [PLAT_OTP_ID_NV_COUNTER_PS_0] = {.row_offset = 0xC0 + 0x26E, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_PS_1] = {.row_offset = 0xC0 + 0x28E, .byte_len = 64 },
+ [PLAT_OTP_ID_NV_COUNTER_PS_2] = {.row_offset = 0xC0 + 0x2AE, .byte_len = 64 },
+};
+
+enum tfm_plat_err_t tfm_plat_otp_init(void)
+{
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_otp_read(enum tfm_otp_element_id_t id,
+ size_t out_len, uint8_t *out)
+{
+ otp_cmd_t row_and_flags;
+ otp_cmd_t odd_byte_row_and_flags;
+ int rc = 0;
+ size_t out_len_checked;
+ uint8_t odd_byte_buff[2] = {0};
+ uint8_t *odd_byte_p;
+
+
+ if ((out_len == 0) || (otp_map[id].byte_len == 0)) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ if (id >= PLAT_OTP_ID_MAX) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Output buffer can be bigger than the OTP element */
+ out_len_checked = (out_len < otp_map[id].byte_len) ? out_len : otp_map[id].byte_len;
+
+ /* Assemble command */
+ row_and_flags.flags = (OTP_BUFFER_MASK & otp_map[id].row_offset);
+ /* For LCS ECC is not used so it can be updated */
+ if (id != PLAT_OTP_ID_LCS) {
+ row_and_flags.flags |= OTP_IS_ECC_MASK;
+ }
+
+ /* Read OTP through API */
+ /* Bootrom API requires 2 byte alignment with ECC mode ON, handle odd byte separately */
+ if (out_len_checked % 2) {
+ /* Update len to be even */
+ out_len_checked -= 1;
+ /* Assemble the command for the odd byte, row number is incremented by (len in byte)/2 */
+ odd_byte_row_and_flags.flags = row_and_flags.flags + (out_len_checked / 2);
+ /* Set pointer to the last byte of the output (not the buffer) */
+ odd_byte_p = out + out_len_checked;
+
+ rc = rom_func_otp_access(&odd_byte_buff[0], 2, odd_byte_row_and_flags);
+ if (rc) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ memcpy(odd_byte_p, &odd_byte_buff[0], 1);
+ }
+ if (out_len_checked) {
+ rc = rom_func_otp_access(out, out_len_checked, row_and_flags);
+ if (rc) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+
+}
+
+enum tfm_plat_err_t tfm_plat_otp_write(enum tfm_otp_element_id_t id,
+ size_t in_len, const uint8_t *in)
+{
+ otp_cmd_t row_and_flags;
+ otp_cmd_t odd_byte_row_and_flags;
+ int rc = 0;
+ size_t in_len_checked;
+ uint8_t odd_byte_buff[2] = {0};
+ uint8_t *odd_byte_p;
+
+ if ((in_len == 0) || (otp_map[id].byte_len == 0)) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ if (id >= PLAT_OTP_ID_MAX) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ in_len_checked = (in_len < otp_map[id].byte_len) ? in_len : otp_map[id].byte_len;
+
+ /* Assemble command */
+ row_and_flags.flags = OTP_IS_WRITE_MASK |
+ (OTP_BUFFER_MASK & otp_map[id].row_offset);
+ /* For LCS ECC is not used so it can be updated */
+ if (id != PLAT_OTP_ID_LCS) {
+ row_and_flags.flags |= OTP_IS_ECC_MASK;
+ }
+
+ /* Write OTP through API */
+ /* Bootrom API requires 2 byte alignment with ECC mode ON, handle odd byte separately */
+ if (in_len_checked % 2) {
+ /* Update len to be even */
+ in_len_checked -= 1;
+ /* Assemble the command for the odd byte, row number is incremented by (len in byte)/2 */
+ odd_byte_row_and_flags.flags = row_and_flags.flags + (in_len_checked / 2);
+ /* Set pointer to the last byte of the input (not the buffer) */
+ odd_byte_p = in + in_len_checked;
+ memcpy(&odd_byte_buff[0], odd_byte_p, 1);
+
+ rc = rom_func_otp_access(&odd_byte_buff[0], 2, odd_byte_row_and_flags);
+ if (rc) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ if (in_len_checked) {
+ rc = rom_func_otp_access(in, in_len_checked, row_and_flags);
+ if (rc) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_otp_get_size(enum tfm_otp_element_id_t id,
+ size_t *size)
+{
+ if (id >= PLAT_OTP_ID_MAX) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ *size = otp_map[id].byte_len;
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_otp_secure_provisioning_start(void)
+{
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_otp_secure_provisioning_finish(void)
+{
+
+ uint32_t row_count = 0;
+ uint8_t first_page_to_lock;
+ uint8_t last_page_to_lock;
+ uint8_t num_pages_to_lock;
+ otp_cmd_t row_and_flags;
+ uint8_t msg_buff[4] = {0};
+ uint32_t lock_config;
+ int rc = 0;
+
+ /* Count the number of allocated OTP rows, assuming continious usage */
+ for (int i = 0; i <= PLAT_OTP_ID_SECURE_DEBUG_PK; i++) {
+ row_count += otp_map[i].byte_len;
+ }
+
+ /* Get the pages to be locked */
+ first_page_to_lock = otp_map[0].row_offset / OTP_ROW_PER_PAGE;
+
+ last_page_to_lock = (otp_map[PLAT_OTP_ID_SECURE_DEBUG_PK].row_offset +
+ (otp_map[PLAT_OTP_ID_SECURE_DEBUG_PK].byte_len / 2)) /
+ 0x40;
+ num_pages_to_lock = last_page_to_lock - first_page_to_lock + 1;
+
+ /* First and last 3 pages are already in use */
+ if ((first_page_to_lock < 3) || (last_page_to_lock > 60)) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Assmble message */
+ /* Lock information encoded to the first 8 bits of lock register 1 */
+ lock_config = (OTP_DATA_PAGE0_LOCK1_LOCK_NS_BITS &
+ (OTP_DATA_PAGE0_LOCK1_LOCK_NS_VALUE_INACCESSIBLE <<
+ OTP_DATA_PAGE0_LOCK1_LOCK_NS_LSB)) |
+ (OTP_DATA_PAGE0_LOCK1_LOCK_BL_BITS &
+ (OTP_DATA_PAGE0_LOCK1_LOCK_BL_VALUE_INACCESSIBLE <<
+ OTP_DATA_PAGE0_LOCK1_LOCK_BL_LSB));
+ /* Triple majority vote */
+ msg_buff[0] = lock_config;
+ msg_buff[1] = lock_config;
+ msg_buff[2] = lock_config;
+
+ /* Lock pages, NS and BL code should not be able to access them */
+ for (int i = 0; i < num_pages_to_lock; i++) {
+ /* Assemble command */
+ row_and_flags.flags = OTP_IS_WRITE_MASK |
+ (OTP_BUFFER_MASK & (OTP_DATA_PAGE0_LOCK1_ROW +
+ ((i + first_page_to_lock) * 2)));
+
+ /* Write lock register PAGExx_LOCK1 */
+ rc = rom_func_otp_access(&msg_buff[0], 4, row_and_flags);
+ if (rc) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
diff --git a/platform/ext/target/rpi/rp2350/rpi_trng.c b/platform/ext/target/rpi/rp2350/rpi_trng.c
new file mode 100644
index 0000000..dad35cd
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/rpi_trng.c
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "psa/crypto.h"
+#include "pico/rand.h"
+#include <string.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length)
+{
+ size_t i = 0;
+ size_t copy_size = 0;
+ size_t remaining_size = 0;
+
+ uint64_t tmp_trn;
+
+ (void) context;
+
+ while (i < output_size) {
+ remaining_size = output_size - i;
+ copy_size = (remaining_size > 8) ? 8 : remaining_size;
+
+ tmp_trn = get_rand_64();
+ memcpy(output + i, (uint8_t *)(&tmp_trn), copy_size);
+ i += copy_size;
+ }
+
+ *output_length = output_size;
+
+ return PSA_SUCCESS;
+}
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
diff --git a/platform/ext/target/rpi/rp2350/services/src/tfm_platform_system.c b/platform/ext/target/rpi/rp2350/services/src/tfm_platform_system.c
new file mode 100644
index 0000000..12c1835
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/services/src/tfm_platform_system.c
@@ -0,0 +1,28 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_platform_system.h"
+#include "tfm_hal_device_header.h"
+#include "tfm_hal_platform.h"
+
+void tfm_platform_hal_system_reset(void)
+{
+ __disable_irq();
+ tfm_hal_system_reset();
+}
+
+enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request,
+ psa_invec *in_vec,
+ psa_outvec *out_vec)
+{
+ (void)request;
+ (void)in_vec;
+ (void)out_vec;
+
+ /* Not needed for this platform */
+ return TFM_PLATFORM_ERR_NOT_SUPPORTED;
+}
+
diff --git a/platform/ext/target/rpi/rp2350/static_assert_override.h b/platform/ext/target/rpi/rp2350/static_assert_override.h
new file mode 100644
index 0000000..300cc43
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/static_assert_override.h
@@ -0,0 +1,8 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#define static_assert(cond, message)
+#define asm __asm
diff --git a/platform/ext/target/rpi/rp2350/target_cfg.c b/platform/ext/target/rpi/rp2350/target_cfg.c
new file mode 100644
index 0000000..a610493
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/target_cfg.c
@@ -0,0 +1,320 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_hal_device_header.h"
+#include "region_defs.h"
+#include "target_cfg.h"
+#include "tfm_plat_defs.h"
+#include "tfm_peripherals_def.h"
+#include "hardware/uart.h"
+#include "region.h"
+#include "hardware/regs/addressmap.h"
+#include "hardware/structs/accessctrl.h"
+#include "hardware/structs/dma.h"
+
+#define REG_RW(addr) (*(volatile uint32_t *)(addr))
+
+#define ACCESSCTRL_DBG (1U << 7)
+#define ACCESSCTRL_DMA (1U << 6)
+#define ACCESSCTRL_CORE1 (1U << 5)
+#define ACCESSCTRL_CORE0 (1U << 4)
+#define ACCESSCTRL_SP (1U << 3)
+#define ACCESSCTRL_SU (1U << 2)
+#define ACCESSCTRL_NSP (1U << 1)
+#define ACCESSCTRL_NSU (1U << 0)
+
+#define ACCESSCTRL_NS_PRIV (ACCESSCTRL_DBG | ACCESSCTRL_DMA | \
+ ACCESSCTRL_CORE1 | ACCESSCTRL_CORE0 |\
+ ACCESSCTRL_SP | ACCESSCTRL_SU | \
+ ACCESSCTRL_NSP)
+#define ACCESSCTRL_S_UNPRIV_C0 (ACCESSCTRL_DBG | ACCESSCTRL_CORE0 |\
+ ACCESSCTRL_SP | ACCESSCTRL_SU)
+/* Only grant access to Core0 when Multi-core topology is not in use */
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+#define ACCESSCTRL_S_UNPRIV_C0_C1 (ACCESSCTRL_DBG | ACCESSCTRL_CORE0 |\
+ ACCESSCTRL_CORE1 | ACCESSCTRL_SP |\
+ ACCESSCTRL_SU)
+#else
+#define ACCESSCTRL_S_UNPRIV_C0_C1 ACCESSCTRL_S_UNPRIV_C0
+#endif
+#define ACCESSCTRL_S_PRIV_C0 (ACCESSCTRL_DBG | ACCESSCTRL_CORE0 |\
+ ACCESSCTRL_SP)
+
+
+#ifdef CONFIG_TFM_USE_TRUSTZONE
+REGION_DECLARE(Image$$, ER_VENEER, $$Base);
+REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit);
+#endif /* CONFIG_TFM_USE_TRUSTZONE */
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE_START, $$RO$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE_END, $$RO$$Limit);
+REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base);
+#ifdef CONFIG_TFM_PARTITION_META
+REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_SP_META_PTR_END, $$ZI$$Limit);
+#endif /* CONFIG_TFM_PARTITION_META */
+
+#define FF_TEST_NVMEM_REGION_START 0x2005E000
+#define FF_TEST_NVMEM_REGION_END 0x2005E3FF
+#define FF_TEST_SERVER_PARTITION_MMIO_START 0x2005E400
+#define FF_TEST_SERVER_PARTITION_MMIO_END 0x2005E4FF
+#define FF_TEST_DRIVER_PARTITION_MMIO_START 0x2005E600
+#define FF_TEST_DRIVER_PARTITION_MMIO_END 0x2005E6FF
+
+extern const struct memory_region_limits memory_regions;
+
+struct platform_data_t tfm_peripheral_std_uart = {
+ .periph_start = UART0_BASE,
+ .periph_limit = UART0_BASE + 0x3FFF,
+ /* Based on platform_data_t definition TF-M expects PPC to control
+ security and privilege settings. There is no PPC on this platform.
+ Using periph_ppc_mask to store accessctrl register index. */
+ .periph_ppc_mask = AC_DO_NOT_CONFIGURE,
+};
+
+struct platform_data_t tfm_peripheral_timer0 = {
+ .periph_start = TIMER0_BASE,
+ .periph_limit = TIMER0_BASE + 0x3FFF,
+ /* Based on platform_data_t definition TF-M expects PPC to control
+ security and privilege settings. There is no PPC on this platform.
+ Using periph_ppc_mask to store accessctrl register index. */
+ .periph_ppc_mask = AC_TIMER0,
+};
+
+#ifdef PSA_API_TEST_IPC
+
+/* Below data structure are only used for PSA FF tests, and this pattern is
+ * definitely not to be followed for real life use cases, as it can break
+ * security.
+ */
+
+struct platform_data_t
+ tfm_peripheral_FF_TEST_UART_REGION = {
+ .periph_start = UART1_BASE,
+ .periph_limit = UART1_BASE + 0x3FFF,
+ .periph_ppc_mask = AC_UART1,
+};
+
+struct platform_data_t
+ tfm_peripheral_FF_TEST_WATCHDOG_REGION = {
+ .periph_start = WATCHDOG_BASE,
+ .periph_limit = WATCHDOG_BASE + 0x3FFF,
+ .periph_ppc_mask = AC_DO_NOT_CONFIGURE,
+};
+
+struct platform_data_t
+ tfm_peripheral_FF_TEST_NVMEM_REGION = {
+ .periph_start = FF_TEST_NVMEM_REGION_START,
+ .periph_limit = FF_TEST_NVMEM_REGION_END,
+ .periph_ppc_mask = AC_DO_NOT_CONFIGURE
+};
+
+struct platform_data_t
+ tfm_peripheral_FF_TEST_SERVER_PARTITION_MMIO = {
+ .periph_start = FF_TEST_SERVER_PARTITION_MMIO_START,
+ .periph_limit = FF_TEST_SERVER_PARTITION_MMIO_END,
+ .periph_ppc_mask = AC_DO_NOT_CONFIGURE
+};
+
+struct platform_data_t
+ tfm_peripheral_FF_TEST_DRIVER_PARTITION_MMIO = {
+ .periph_start = FF_TEST_DRIVER_PARTITION_MMIO_START,
+ .periph_limit = FF_TEST_DRIVER_PARTITION_MMIO_END,
+ .periph_ppc_mask = AC_DO_NOT_CONFIGURE
+};
+#endif
+
+/*------------------- SAU/IDAU configuration functions -----------------------*/
+void sau_and_idau_cfg(void)
+{
+ /* Ensure all memory accesses are completed */
+ __DMB();
+ #if 0 /* Bootrom set to be secure temporary */
+ /* Configures SAU regions to be non-secure */
+ /* Configure Bootrom */
+ SAU->RNR = 0;
+ SAU->RBAR = (ROM_BASE & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = ((ROM_BASE + 0x7E00 - 1) & SAU_RLAR_LADDR_Msk)
+ | SAU_RLAR_ENABLE_Msk;
+
+ /* Configure Bootrom SGs */
+ SAU->RNR = 1;
+ SAU->RBAR = ((ROM_BASE + 0x7E00) & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = ((ROM_BASE + 0x7FFF) & SAU_RLAR_LADDR_Msk)
+ | SAU_RLAR_ENABLE_Msk | SAU_RLAR_NSC_Msk;
+ #endif
+
+ /* Configures veneers region to be non-secure callable */
+ SAU->RNR = 2;
+ SAU->RBAR = (memory_regions.veneer_base & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = (memory_regions.veneer_limit & SAU_RLAR_LADDR_Msk)
+ | SAU_RLAR_ENABLE_Msk | SAU_RLAR_NSC_Msk;
+
+ /* Configure Non-Secure partition in flash */
+ SAU->RNR = 3;
+ SAU->RBAR = (memory_regions.non_secure_partition_base
+ & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = (memory_regions.non_secure_partition_limit
+ & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
+
+ /* Configure the rest of the address map up to PPB */
+ SAU->RNR = 4;
+ SAU->RBAR = (SRAM4_BASE & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = ((PPB_BASE - 1) & SAU_RLAR_LADDR_Msk)
+ | SAU_RLAR_ENABLE_Msk;
+
+ /* Turn off unused bootrom region */
+ SAU->RNR = 7;
+ SAU->RBAR = 0;
+ SAU->RLAR = 0;
+
+ /* Enables SAU */
+ TZ_SAU_Enable();
+ /* Add barriers to assure the SAU configuration is done before continue
+ * the execution.
+ */
+ __DSB();
+ __ISB();
+}
+
+enum tfm_plat_err_t bus_filter_cfg(void)
+{
+ enum tfm_plat_err_t err = TFM_PLAT_ERR_SUCCESS;
+ uint32_t c0_c1_unpriv_periph_offsets[] = {AC_SRAM0,
+ AC_SRAM1, AC_SRAM2, AC_SRAM3};
+ uint8_t nbr_of_c0_c1_unpriv_periphs;
+ uint32_t c0_unpriv_periph_offsets[] = {AC_SYSCFG, AC_CLOCKS_BANK_DEFAULT,
+ AC_RSM, AC_BUSCTRL, AC_OTP, AC_POWMAN, AC_TRNG, AC_XOSC,
+ AC_ROSC, AC_PLL_SYS, AC_PLL_USB, AC_TICKS, AC_XIP_CTRL,
+ AC_XIP_QMI};
+ uint8_t nbr_of_c0_unpriv_periphs;
+ uint32_t ns_priv_periph_offsets[] = {AC_ROM, AC_XIP_MAIN, AC_SRAM4,
+ AC_SRAM5, AC_SRAM6, AC_SRAM7, AC_SRAM8, AC_SRAM9, AC_DMA,
+ AC_USBCTRL, AC_PIO0, AC_PIO1, AC_PIO2, AC_CORESIGHT_TRACE,
+ AC_CORESIGHT_PERIPH, AC_SYSINFO, AC_RESETS, AC_IO_BANK0,
+ AC_IO_BANK1, AC_PADS_BANK0, AC_PADS_QSPI, AC_ADC0, AC_HSTX,
+ AC_I2C0, AC_I2C1, AC_PWM, AC_SPI0, AC_SPI1, AC_TIMER0,
+ AC_TIMER1, AC_UART0, AC_UART1, AC_TBMAN, AC_SHA256, AC_WATCHDOG,
+ AC_XIP_AUX};
+ uint8_t nbr_of_ns_periphs;
+ uint32_t temp_addr;
+
+ nbr_of_c0_c1_unpriv_periphs = sizeof(c0_c1_unpriv_periph_offsets) /
+ sizeof(c0_c1_unpriv_periph_offsets[0]);
+ nbr_of_c0_unpriv_periphs = sizeof(c0_unpriv_periph_offsets) /
+ sizeof(c0_unpriv_periph_offsets[0]);
+ nbr_of_ns_periphs = sizeof(ns_priv_periph_offsets) /
+ sizeof(ns_priv_periph_offsets[0]);
+
+ /* Probably worth doing a software reset of access ctrl before setup */
+ accessctrl_hw->cfgreset = ACCESSCTRL_PASSWORD_BITS | 0x1;
+
+ accessctrl_hw->gpio_nsmask[0] = 0xFFFFFFFC;
+ accessctrl_hw->gpio_nsmask[1] = 0xFF00FFFF;
+
+ /* Peripherals controlled by Secure Core0 and Core1 */
+ for (uint8_t i = 0; i < nbr_of_c0_c1_unpriv_periphs; i++){
+ temp_addr = ACCESSCTRL_BASE + c0_c1_unpriv_periph_offsets[i];
+ REG_RW(temp_addr) = ACCESSCTRL_S_UNPRIV_C0_C1 |
+ ACCESSCTRL_PASSWORD_BITS;
+ if (REG_RW(temp_addr) != ACCESSCTRL_S_UNPRIV_C0_C1) {
+ err = TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ /* Peripherals controlled by Secure Core0 */
+ for (uint8_t i = 0; i < nbr_of_c0_unpriv_periphs; i++){
+ temp_addr = ACCESSCTRL_BASE + c0_unpriv_periph_offsets[i];
+ REG_RW(temp_addr) = ACCESSCTRL_S_UNPRIV_C0 |
+ ACCESSCTRL_PASSWORD_BITS;
+ if (REG_RW(temp_addr) != ACCESSCTRL_S_UNPRIV_C0) {
+ err = TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ /* Peripherals accessable to all bus actors */
+ for (uint8_t i = 0; i < nbr_of_ns_periphs; i++){
+ temp_addr = ACCESSCTRL_BASE + ns_priv_periph_offsets[i];
+ REG_RW(temp_addr) = ACCESSCTRL_NS_PRIV |
+ ACCESSCTRL_PASSWORD_BITS;
+ if (REG_RW(temp_addr) != ACCESSCTRL_NS_PRIV) {
+ err = TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+ }
+
+ /* Lock setings for every actor except Core0, only hard reset can clear
+ this. Core0 must retain control for mmio control. */
+ accessctrl_hw->lock = ACCESSCTRL_PASSWORD_BITS | 0x6;
+
+ return err;
+}
+
+void access_ctrl_configure_to_secure_privileged(access_ctrl_reg_offset offset)
+{
+ if (offset != AC_DO_NOT_CONFIGURE){
+ REG_RW(ACCESSCTRL_BASE + offset) =
+ ACCESSCTRL_S_PRIV_C0 | ACCESSCTRL_PASSWORD_BITS;
+ }
+}
+
+void access_ctrl_configure_to_secure_unprivileged(access_ctrl_reg_offset offset)
+{
+ if (offset != AC_DO_NOT_CONFIGURE){
+ REG_RW(ACCESSCTRL_BASE + offset) =
+ ACCESSCTRL_S_UNPRIV_C0 | ACCESSCTRL_PASSWORD_BITS;
+ }
+}
+
+enum tfm_plat_err_t dma_security_config(void)
+{
+ /* Configure every DMA channel as Nonsecure Privileged since TF-M uses no DMA */
+ for (int i=0; i<16; i++){
+ REG_RW(DMA_BASE + DMA_SECCFG_CH0_OFFSET + (i * 4)) =
+ DMA_SECCFG_CH0_P_BITS;
+ }
+
+ /* Configure DMA MPU to mirror SAU settings */
+ /* Unmapped address regions default to SP */
+ dma_hw->mpu_ctrl = DMA_MPU_CTRL_NS_HIDE_ADDR_BITS | DMA_MPU_CTRL_S_BITS |
+ DMA_MPU_CTRL_P_BITS;
+
+ /* Configure MPU regions */
+ dma_hw->mpu_region[0].bar = (memory_regions.veneer_base &
+ DMA_MPU_BAR0_BITS);
+ dma_hw->mpu_region[0].lar = (memory_regions.veneer_limit &
+ DMA_MPU_LAR0_ADDR_BITS) |
+ DMA_MPU_LAR0_P_BITS | DMA_MPU_LAR0_EN_BITS;
+
+ dma_hw->mpu_region[1].bar = (memory_regions.non_secure_partition_base &
+ DMA_MPU_BAR0_BITS);
+ dma_hw->mpu_region[1].lar = (memory_regions.veneer_limit &
+ DMA_MPU_LAR0_ADDR_BITS) |
+ DMA_MPU_LAR0_P_BITS | DMA_MPU_LAR0_EN_BITS;
+
+ dma_hw->mpu_region[2].bar = (SRAM4_BASE & DMA_MPU_BAR0_BITS);
+ dma_hw->mpu_region[2].lar = ((PPB_BASE - 1) & DMA_MPU_LAR0_ADDR_BITS) |
+ DMA_MPU_LAR0_P_BITS | DMA_MPU_LAR0_EN_BITS;
+
+ dma_hw->mpu_region[3].bar = 0;
+ dma_hw->mpu_region[3].lar = 0;
+
+ dma_hw->mpu_region[4].bar = 0;
+ dma_hw->mpu_region[4].lar = 0;
+
+ dma_hw->mpu_region[5].bar = 0;
+ dma_hw->mpu_region[5].lar = 0;
+
+ dma_hw->mpu_region[6].bar = 0;
+ dma_hw->mpu_region[6].lar = 0;
+
+ dma_hw->mpu_region[7].bar = 0;
+ dma_hw->mpu_region[7].lar = 0;
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
diff --git a/platform/ext/target/rpi/rp2350/target_cfg.h b/platform/ext/target/rpi/rp2350/target_cfg.h
new file mode 100644
index 0000000..3719df6
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/target_cfg.h
@@ -0,0 +1,114 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __TARGET_CFG_H__
+#define __TARGET_CFG_H__
+
+#include <stdint.h>
+
+#define TFM_DRIVER_STDIO driver_usart0
+#define NS_DRIVER_STDIO driver_usart0
+
+/**
+ * \brief Defines the word offsets of Slave Peripheral Protection Controller
+ * Registers
+ */
+typedef enum
+{
+ PPC_SP_DO_NOT_CONFIGURE = -1,
+} ppc_bank_t;
+
+typedef enum
+{
+ AC_LOCK = 0x0,
+ AC_FORCE_CORE_NS = 0x4,
+ AC_CFGRESET = 0x8,
+ AC_GPIO_NSMASK0 = 0xC,
+ AC_GPIO_NSMASK1 = 0x10,
+ AC_ROM = 0x14,
+ AC_XIP_MAIN = 0x18,
+ AC_SRAM0 = 0x1C,
+ AC_SRAM1 = 0x20,
+ AC_SRAM2 = 0x24,
+ AC_SRAM3 = 0x28,
+ AC_SRAM4 = 0x2C,
+ AC_SRAM5 = 0x30,
+ AC_SRAM6 = 0x34,
+ AC_SRAM7 = 0x38,
+ AC_SRAM8 = 0x3C,
+ AC_SRAM9 = 0x40,
+ AC_DMA = 0x44,
+ AC_USBCTRL = 0x48,
+ AC_PIO0 = 0x4C,
+ AC_PIO1 = 0x50,
+ AC_PIO2 = 0x54,
+ AC_CORESIGHT_TRACE = 0x58,
+ AC_CORESIGHT_PERIPH = 0x5C,
+ AC_SYSINFO = 0x60,
+ AC_RESETS = 0x64,
+ AC_IO_BANK0 = 0x68,
+ AC_IO_BANK1 = 0x6C,
+ AC_PADS_BANK0 = 0x70,
+ AC_PADS_QSPI = 0x74,
+ AC_BUSCTRL = 0x78,
+ AC_ADC0 = 0x7C,
+ AC_HSTX = 0x80,
+ AC_I2C0 = 0x84,
+ AC_I2C1 = 0x88,
+ AC_PWM = 0x8C,
+ AC_SPI0 = 0x90,
+ AC_SPI1 = 0x94,
+ AC_TIMER0 = 0x98,
+ AC_TIMER1 = 0x9C,
+ AC_UART0 = 0xA0,
+ AC_UART1 = 0xA4,
+ AC_OTP = 0xA8,
+ AC_TBMAN = 0xAC,
+ AC_POWMAN = 0xB0,
+ AC_TRNG = 0xB4,
+ AC_SHA256 = 0xB8,
+ AC_SYSCFG = 0xBC,
+ AC_CLOCKS_BANK_DEFAULT = 0xC0,
+ AC_XOSC = 0xC4,
+ AC_ROSC = 0xC8,
+ AC_PLL_SYS = 0xCC,
+ AC_PLL_USB = 0xD0,
+ AC_TICKS = 0xD4,
+ AC_WATCHDOG = 0xD8,
+ AC_RSM = 0xDC,
+ AC_XIP_CTRL = 0xE0,
+ AC_XIP_QMI = 0xE4,
+ AC_XIP_AUX = 0xE8,
+ AC_DO_NOT_CONFIGURE = 0xFFFF,
+} access_ctrl_reg_offset;
+
+/**
+ * \brief Initialize SAU.
+ */
+void sau_and_idau_cfg(void);
+
+/**
+ * \brief Configure access control for bus endpoints.
+ */
+enum tfm_plat_err_t bus_filter_cfg(void);
+
+/**
+ * \brief Configure DMA channels' security
+ */
+enum tfm_plat_err_t dma_security_config(void);
+
+/**
+ * \brief Configure bus endpoint to be secure privileged accessible for core0
+ */
+void access_ctrl_configure_to_secure_privileged(access_ctrl_reg_offset offset);
+
+
+/**
+ * \brief Configure bus endpoint to be secure unprivileged accessible for core0
+ */
+void access_ctrl_configure_to_secure_unprivileged(access_ctrl_reg_offset offset);
+
+#endif /* __TARGET_CFG_H__ */
diff --git a/platform/ext/target/rpi/rp2350/tests/psa_arch_tests_config.cmake b/platform/ext/target/rpi/rp2350/tests/psa_arch_tests_config.cmake
new file mode 100644
index 0000000..6ae2b7b
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tests/psa_arch_tests_config.cmake
@@ -0,0 +1,9 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#
+#-------------------------------------------------------------------------------
+
+# Paramters for PSA API tests
+
+set(PSA_API_TEST_TARGET rp2350 CACHE STRING "PSA_API_TARGET name")
diff --git a/platform/ext/target/rpi/rp2350/tests/tfm_tests_config.cmake b/platform/ext/target/rpi/rp2350/tests/tfm_tests_config.cmake
new file mode 100644
index 0000000..3fff55d
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tests/tfm_tests_config.cmake
@@ -0,0 +1,10 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#
+#-------------------------------------------------------------------------------
+# Make FLIH IRQ test as the default IRQ test on RP2350
+set(TEST_NS_SLIH_IRQ OFF CACHE BOOL "Whether to build NS regression Second-Level Interrupt Handling tests")
+
+set(PLATFORM_SLIH_IRQ_TEST_SUPPORT ON)
+set(PLATFORM_FLIH_IRQ_TEST_SUPPORT ON)
diff --git a/platform/ext/target/rpi/rp2350/tfm_builtin_key_ids.h b/platform/ext/target/rpi/rp2350/tfm_builtin_key_ids.h
new file mode 100644
index 0000000..ec842ae
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tfm_builtin_key_ids.h
@@ -0,0 +1,31 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __TFM_BUILTIN_KEY_IDS_H__
+#define __TFM_BUILTIN_KEY_IDS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The persistent key identifiers for TF-M builtin keys.
+ *
+ * The value of TFM_BUILTIN_KEY_ID_MIN (and therefore of the whole range) is
+ * completely arbitrary except for being inside the PSA builtin keys range.
+ *
+ */
+enum tfm_key_id_builtin_t {
+ TFM_BUILTIN_KEY_ID_MIN = 0x7FFF815Bu,
+ TFM_BUILTIN_KEY_ID_HUK,
+ TFM_BUILTIN_KEY_ID_IAK,
+ TFM_BUILTIN_KEY_ID_MAX = 0x7FFF817Bu,
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TFM_BUILTIN_KEY_IDS_H__ */
diff --git a/platform/ext/target/rpi/rp2350/tfm_hal_isolation_rp2350.c b/platform/ext/target/rpi/rp2350/tfm_hal_isolation_rp2350.c
new file mode 100644
index 0000000..eda91fa
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tfm_hal_isolation_rp2350.c
@@ -0,0 +1,469 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include <arm_cmse.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include "array.h"
+#include "tfm_hal_device_header.h"
+#include "region.h"
+#include "armv8m_mpu.h"
+#include "target_cfg.h"
+#include "tfm_hal_defs.h"
+#include "tfm_hal_isolation.h"
+#include "tfm_peripherals_def.h"
+#include "load/spm_load_api.h"
+
+#define PROT_BOUNDARY_VAL \
+ ((1U << HANDLE_ATTR_PRIV_POS) & HANDLE_ATTR_PRIV_MASK)
+/* Boundary handle binding macros. */
+#define HANDLE_ATTR_PRIV_POS 1U
+#define HANDLE_ATTR_PRIV_MASK (0x1UL << HANDLE_ATTR_PRIV_POS)
+#define HANDLE_ATTR_NS_POS 0U
+#define HANDLE_ATTR_NS_MASK (0x1UL << HANDLE_ATTR_NS_POS)
+
+#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
+static uint32_t n_configured_regions = 0;
+
+#ifdef CONFIG_TFM_USE_TRUSTZONE
+REGION_DECLARE(Image$$, ER_VENEER, $$Base);
+REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit);
+#endif /* CONFIG_TFM_USE_TRUSTZONE */
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE_START, $$RO$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE_END, $$RO$$Limit);
+REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base);
+#ifdef CONFIG_TFM_PARTITION_META
+REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_SP_META_PTR_END, $$ZI$$Limit);
+#endif /* CONFIG_TFM_PARTITION_META */
+
+#define ARM_MPU_NON_TRANSIENT ( 1U )
+#define ARM_MPU_TRANSIENT ( 0U )
+#define ARM_MPU_WRITE_BACK ( 1U )
+#define ARM_MPU_WRITE_THROUGH ( 0U )
+#define ARM_MPU_READ_ALLOCATE ( 1U )
+#define ARM_MPU_NON_READ_ALLOCATE ( 0U )
+#define ARM_MPU_WRITE_ALLOCATE ( 1U )
+#define ARM_MPU_NON_WRITE_ALLOCATE ( 0U )
+#define ARM_MPU_READ_ONLY ( 1U )
+#define ARM_MPU_READ_WRITE ( 0U )
+#define ARM_MPU_UNPRIVILEGED ( 1U )
+#define ARM_MPU_PRIVILEGED ( 0U )
+#define ARM_MPU_EXECUTE_NEVER ( 1U )
+#define ARM_MPU_EXECUTE_OK ( 0U )
+#define ARM_MPU_PRIVILEGE_EXECUTE_NEVER ( 1U )
+#define ARM_MPU_PRIVILEGE_EXECUTE_OK ( 0U )
+#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
+
+enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(
+ uintptr_t *p_spm_boundary)
+{
+#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
+const ARM_MPU_Region_t mpu_region_attributes[] = {
+#ifdef CONFIG_TFM_USE_TRUSTZONE
+ /* TFM Veneer region (Bootrom SGs are not included)
+ * Region Number 0, Non-shareable, Read-Only, Non-Privileged, Executable,
+ * Privilege Executable - if PXN available, Attribute set: 0
+ */
+ {
+ ARM_MPU_RBAR((uint32_t)®ION_NAME(Image$$, ER_VENEER, $$Base),
+ ARM_MPU_SH_NON,
+ ARM_MPU_READ_ONLY,
+ ARM_MPU_UNPRIVILEGED,
+ ARM_MPU_EXECUTE_OK),
+ #ifdef TFM_PXN_ENABLE
+ ARM_MPU_RLAR_PXN((uint32_t)®ION_NAME(Image$$, VENEER_ALIGN, $$Limit) - 1,
+ ARM_MPU_PRIVILEGE_EXECUTE_OK,
+ 0)
+ #else
+ ARM_MPU_RLAR((uint32_t)®ION_NAME(Image$$, VENEER_ALIGN, $$Limit) - 1,
+ 0)
+ #endif
+ },
+#endif /* CONFIG_TFM_USE_TRUSTZONE */
+ /* TFM Core unprivileged code region
+ * Region Number 1, Non-shareable, Read-Only, Non-Privileged, Executable,
+ * Privilege Executable - if PXN available, Attribute set: 0
+ */
+ {
+ ARM_MPU_RBAR((uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE_START, $$RO$$Base),
+ ARM_MPU_SH_NON,
+ ARM_MPU_READ_ONLY,
+ ARM_MPU_UNPRIVILEGED,
+ ARM_MPU_EXECUTE_OK),
+ #ifdef TFM_PXN_ENABLE
+ ARM_MPU_RLAR_PXN((uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE_END, $$RO$$Limit) - 1,
+ ARM_MPU_PRIVILEGE_EXECUTE_OK,
+ 0)
+ #else
+ ARM_MPU_RLAR((uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE_END, $$RO$$Limit) - 1,
+ 0)
+ #endif
+ },
+ /* RO region
+ * Region Number 2, Non-shareable, Read-Only, Non-Privileged, Executable,
+ * PXN depends on isolation level, Attribute set: 0
+ */
+ {
+ ARM_MPU_RBAR((uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_START, $$Base),
+ ARM_MPU_SH_NON,
+ ARM_MPU_READ_ONLY,
+ ARM_MPU_UNPRIVILEGED,
+ ARM_MPU_EXECUTE_OK),
+ #ifdef TFM_PXN_ENABLE
+ ARM_MPU_RLAR_PXN((uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_END, $$Base) - 1,
+ #if TFM_ISOLATION_LEVEL == 1
+ ARM_MPU_PRIVILEGE_EXECUTE_OK,
+ #else
+ ARM_MPU_PRIVILEGE_EXECUTE_NEVER,
+ #endif
+ 0)
+ #else
+ ARM_MPU_RLAR((uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_END, $$Base) - 1,
+ 0)
+ #endif
+ },
+ /* RW, ZI and stack as one region
+ * Region Number 3, Non-shareable, Read-Write, Non-Privileged, Execute Never
+ * Attribute set: 1, Privilege Execute Never - if PXN available
+ */
+ {
+ ARM_MPU_RBAR((uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_START, $$Base),
+ ARM_MPU_SH_NON,
+ ARM_MPU_READ_WRITE,
+ ARM_MPU_UNPRIVILEGED,
+ ARM_MPU_EXECUTE_NEVER),
+ #ifdef TFM_PXN_ENABLE
+ ARM_MPU_RLAR_PXN((uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base) - 1,
+ ARM_MPU_PRIVILEGE_EXECUTE_NEVER,
+ 1)
+ #else
+ ARM_MPU_RLAR((uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base) - 1,
+ 1)
+ #endif
+ },
+#ifdef CONFIG_TFM_PARTITION_META
+ /* TFM partition metadata pointer region
+ * Region Number 4, Non-shareable, Read-Write, Non-Privileged, Execute Never
+ * Attribute set: 1, Privilege Execute Never - if PXN available
+ */
+ {
+ ARM_MPU_RBAR((uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Base),
+ ARM_MPU_SH_NON,
+ ARM_MPU_READ_WRITE,
+ ARM_MPU_UNPRIVILEGED,
+ ARM_MPU_EXECUTE_NEVER),
+ #ifdef TFM_PXN_ENABLE
+ ARM_MPU_RLAR_PXN((uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR_END, $$ZI$$Limit) - 1,
+ ARM_MPU_PRIVILEGE_EXECUTE_NEVER,
+ 1)
+ #else
+ ARM_MPU_RLAR((uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR_END, $$ZI$$Limit) - 1,
+ 1)
+ #endif
+ },
+#endif
+};
+ ARM_MPU_Region_t localcfg;
+#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
+
+ /* Set up isolation boundaries between SPE and NSPE */
+ sau_and_idau_cfg();
+ if (bus_filter_cfg() != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_HAL_ERROR_GENERIC;
+ }
+
+ if (dma_security_config() != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_HAL_ERROR_GENERIC;
+ }
+
+ /* Set up static isolation boundaries inside SPE */
+#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
+ int32_t i;
+
+ uint32_t mpu_region_num =
+ (MPU ->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
+
+ if (mpu_region_num < ARRAY_SIZE(mpu_region_attributes)) {
+ return TFM_HAL_ERROR_GENERIC;
+ }
+
+ /* Turn off MPU during configuration */
+ if ((MPU->CTRL & MPU_CTRL_ENABLE_Msk)) {
+ ARM_MPU_Disable();
+ }
+ /* Disable all regions */
+ for (i = 0; i < mpu_region_num; i++) {
+ ARM_MPU_ClrRegion(i);
+ }
+
+ /* Configure attribute registers
+ * Attr0 : Normal memory, Inner/Outer Cacheable, Write-Trough Read-Allocate
+ */
+ ARM_MPU_SetMemAttr(0,
+ ARM_MPU_ATTR(ARM_MPU_ATTR_MEMORY_(ARM_MPU_NON_TRANSIENT,
+ ARM_MPU_WRITE_THROUGH,
+ ARM_MPU_READ_ALLOCATE,
+ ARM_MPU_NON_WRITE_ALLOCATE),
+ ARM_MPU_ATTR_MEMORY_(ARM_MPU_NON_TRANSIENT,
+ ARM_MPU_WRITE_THROUGH,
+ ARM_MPU_READ_ALLOCATE,
+ ARM_MPU_NON_WRITE_ALLOCATE)));
+ /* Attr1 : Normal memory, Inner/Outer Cacheable, Write-Back R-W Allocate */
+ ARM_MPU_SetMemAttr(1,
+ ARM_MPU_ATTR(ARM_MPU_ATTR_MEMORY_(ARM_MPU_NON_TRANSIENT,
+ ARM_MPU_WRITE_BACK,
+ ARM_MPU_READ_ALLOCATE,
+ ARM_MPU_WRITE_ALLOCATE),
+ ARM_MPU_ATTR_MEMORY_(ARM_MPU_NON_TRANSIENT,
+ ARM_MPU_WRITE_BACK,
+ ARM_MPU_READ_ALLOCATE,
+ ARM_MPU_WRITE_ALLOCATE)));
+ /* Attr2 : Device memory, nGnRE */
+ ARM_MPU_SetMemAttr(2,
+ ARM_MPU_ATTR(ARM_MPU_ATTR_DEVICE,
+ ARM_MPU_ATTR_DEVICE_nGnRE));
+
+ /* Configure regions */
+ /* Note: CMSIS MPU API clears the lower 5 address bits without check */
+ for (i = 0; i < ARRAY_SIZE(mpu_region_attributes); i++) {
+ localcfg.RBAR = mpu_region_attributes[i].RBAR;
+ localcfg.RLAR = mpu_region_attributes[i].RLAR;
+ ARM_MPU_SetRegion(i, localcfg.RBAR, localcfg.RLAR);
+ }
+ n_configured_regions = i;
+
+ /* Enable MPU with the above configurations. Allow default memory map for
+ * privileged software and enable MPU during HardFault and NMI handlers.
+ */
+ ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
+#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
+
+ *p_spm_boundary = (uintptr_t)PROT_BOUNDARY_VAL;
+
+ return TFM_HAL_SUCCESS;
+}
+
+/*
+ * Implementation of tfm_hal_bind_boundary():
+ *
+ * The API encodes some attributes into a handle and returns it to SPM.
+ * The attributes include isolation boundaries, privilege, and MMIO information.
+ * When scheduler switches running partitions, SPM compares the handle between
+ * partitions to know if boundary update is necessary. If update is required,
+ * SPM passes the handle to platform to do platform settings and update
+ * isolation boundaries.
+ */
+enum tfm_hal_status_t tfm_hal_bind_boundary(
+ const struct partition_load_info_t *p_ldinf,
+ uintptr_t *p_boundary)
+{
+ uint32_t i, j;
+ bool privileged;
+ bool ns_agent_tz;
+ uint32_t partition_attrs = 0;
+ const struct asset_desc_t *p_asset;
+ struct platform_data_t *plat_data_ptr;
+ const uintptr_t* mmio_list;
+ size_t mmio_list_length;
+
+#if TFM_ISOLATION_LEVEL == 2
+ ARM_MPU_Region_t local_mpu_region;
+ uint32_t mpu_region_num;
+#endif
+ if (!p_ldinf || !p_boundary) {
+ return TFM_HAL_ERROR_GENERIC;
+ }
+
+#if TFM_ISOLATION_LEVEL == 1
+ privileged = true;
+#else
+ privileged = IS_PSA_ROT(p_ldinf);
+#endif
+
+ ns_agent_tz = IS_NS_AGENT_TZ(p_ldinf);
+ p_asset = LOAD_INFO_ASSET(p_ldinf);
+
+ get_partition_named_mmio_list(&mmio_list, &mmio_list_length);
+
+ /*
+ * Validate if the named MMIO of partition is allowed by the platform.
+ * Otherwise, skip validation.
+ *
+ * NOTE: Need to add validation of numbered MMIO if platform requires.
+ */
+ for (i = 0; i < p_ldinf->nassets; i++) {
+ if (!(p_asset[i].attr & ASSET_ATTR_NAMED_MMIO)) {
+ continue;
+ }
+ for (j = 0; j < mmio_list_length; j++) {
+ if (p_asset[i].dev.dev_ref == mmio_list[j]) {
+ break;
+ }
+ }
+
+ if (j == mmio_list_length) {
+ /* The MMIO asset is not in the allowed list of platform. */
+ return TFM_HAL_ERROR_GENERIC;
+ }
+ /* Assume sec and priv settings are required even under level 1 */
+ plat_data_ptr = REFERENCE_TO_PTR(p_asset[i].dev.dev_ref,
+ struct platform_data_t *);
+
+ if (plat_data_ptr->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) {
+ if (privileged) {
+ access_ctrl_configure_to_secure_privileged(
+ (access_ctrl_reg_offset)plat_data_ptr->periph_ppc_mask);
+ } else {
+ access_ctrl_configure_to_secure_unprivileged(
+ (access_ctrl_reg_offset)plat_data_ptr->periph_ppc_mask);
+ }
+ }
+#if TFM_ISOLATION_LEVEL == 2
+ /*
+ * Static boundaries are set. Set up MPU region for MMIO.
+ * Setup regions for unprivileged assets only.
+ */
+ if (!privileged) {
+ mpu_region_num =
+ (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
+
+ /* There is a limited number of available MPU regions in v8M */
+ if (mpu_region_num <= n_configured_regions) {
+ return TFM_HAL_ERROR_GENERIC;
+ }
+ if ((plat_data_ptr->periph_start & ~MPU_RBAR_BASE_Msk) != 0) {
+ return TFM_HAL_ERROR_GENERIC;
+ }
+ if ((plat_data_ptr->periph_limit & ~MPU_RLAR_LIMIT_Msk) != 0x1F) {
+ return TFM_HAL_ERROR_GENERIC;
+ }
+
+ /* Turn off MPU during configuration */
+ if (MPU->CTRL & MPU_CTRL_ENABLE_Msk) {
+ ARM_MPU_Disable();
+ }
+
+ /* Assemble region base and limit address register contents. */
+ local_mpu_region.RBAR = ARM_MPU_RBAR(plat_data_ptr->periph_start,
+ ARM_MPU_SH_NON,
+ ARM_MPU_READ_WRITE,
+ ARM_MPU_UNPRIVILEGED,
+ ARM_MPU_EXECUTE_NEVER);
+ /* Attr2 contains required attribute set for device regions */
+ #ifdef TFM_PXN_ENABLE
+ local_mpu_region.RLAR = ARM_MPU_RLAR_PXN(plat_data_ptr->periph_limit,
+ ARM_MPU_PRIVILEGE_EXECUTE_NEVER,
+ 2);
+ #else
+ local_mpu_region.RLAR = ARM_MPU_RLAR(plat_data_ptr->periph_limit,
+ 2);
+ #endif
+
+ /* Configure device mpu region */
+ ARM_MPU_SetRegion(n_configured_regions,
+ local_mpu_region.RBAR,
+ local_mpu_region.RLAR);
+
+ n_configured_regions++;
+
+ /* Enable MPU with the new region added */
+ ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
+ }
+#endif
+ }
+
+ partition_attrs = ((uint32_t)privileged << HANDLE_ATTR_PRIV_POS) &
+ HANDLE_ATTR_PRIV_MASK;
+ partition_attrs |= ((uint32_t)ns_agent_tz << HANDLE_ATTR_NS_POS) &
+ HANDLE_ATTR_NS_MASK;
+ *p_boundary = (uintptr_t)partition_attrs;
+
+ return TFM_HAL_SUCCESS;
+}
+
+enum tfm_hal_status_t tfm_hal_activate_boundary(
+ const struct partition_load_info_t *p_ldinf,
+ uintptr_t boundary)
+{
+ CONTROL_Type ctrl;
+ bool privileged = !!((uint32_t)boundary & HANDLE_ATTR_PRIV_MASK);
+
+ /* Privileged level is required to be set always */
+ ctrl.w = __get_CONTROL();
+ ctrl.b.nPRIV = privileged ? 0 : 1;
+ __set_CONTROL(ctrl.w);
+
+ return TFM_HAL_SUCCESS;
+}
+
+enum tfm_hal_status_t tfm_hal_memory_check(uintptr_t boundary, uintptr_t base,
+ size_t size, uint32_t access_type)
+{
+ int flags = 0;
+
+ /* If size is zero, this indicates an empty buffer and base is ignored */
+ if (size == 0) {
+ return TFM_HAL_SUCCESS;
+ }
+
+ if (!base) {
+ return TFM_HAL_ERROR_INVALID_INPUT;
+ }
+
+ if ((access_type & TFM_HAL_ACCESS_READWRITE) == TFM_HAL_ACCESS_READWRITE) {
+ flags |= CMSE_MPU_READWRITE;
+ } else if (access_type & TFM_HAL_ACCESS_READABLE) {
+ flags |= CMSE_MPU_READ;
+ } else {
+ return TFM_HAL_ERROR_INVALID_INPUT;
+ }
+
+ if (access_type & TFM_HAL_ACCESS_NS) {
+ flags |= CMSE_NONSECURE;
+ }
+
+ if (!((uint32_t)boundary & HANDLE_ATTR_PRIV_MASK)) {
+ flags |= CMSE_MPU_UNPRIV;
+ }
+
+ /* This check is only done for ns_agent_tz */
+ if ((uint32_t)boundary & HANDLE_ATTR_NS_MASK) {
+ CONTROL_Type ctrl;
+ ctrl.w = __TZ_get_CONTROL_NS();
+ if (ctrl.b.nPRIV == 1) {
+ flags |= CMSE_MPU_UNPRIV;
+ } else {
+ flags &= ~CMSE_MPU_UNPRIV;
+ }
+ flags |= CMSE_NONSECURE;
+ }
+
+ if (cmse_check_address_range((void *)base, size, flags) != NULL) {
+ return TFM_HAL_SUCCESS;
+ } else {
+ return TFM_HAL_ERROR_MEM_FAULT;
+ }
+}
+
+bool tfm_hal_boundary_need_switch(uintptr_t boundary_from,
+ uintptr_t boundary_to)
+{
+ if (boundary_from == boundary_to) {
+ return false;
+ }
+
+ if (((uint32_t)boundary_from & HANDLE_ATTR_PRIV_MASK) &&
+ ((uint32_t)boundary_to & HANDLE_ATTR_PRIV_MASK)) {
+ return false;
+ }
+ return true;
+}
diff --git a/platform/ext/target/rpi/rp2350/tfm_hal_mailbox.c b/platform/ext/target/rpi/rp2350/tfm_hal_mailbox.c
new file mode 100644
index 0000000..41b93eb
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tfm_hal_mailbox.c
@@ -0,0 +1,101 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_hal_mailbox.h"
+#include "tfm_multi_core.h"
+#include "tfm_hal_interrupt.h"
+#include "tfm_peripherals_def.h"
+#include "hardware/irq.h"
+#include "interrupt.h"
+
+#include "platform_multicore.h"
+
+#include "pico/multicore.h"
+
+static struct irq_t mbox_irq_info = {0};
+
+int32_t tfm_mailbox_hal_init(struct secure_mailbox_queue_t *s_queue)
+{
+ struct mailbox_init_t *ns_init = NULL;
+
+ multicore_ns_fifo_push_blocking_inline(NS_MAILBOX_INIT);
+
+ ns_init = (struct mailbox_init_t *) multicore_ns_fifo_pop_blocking_inline();
+
+ /*
+ * FIXME
+ * Necessary sanity check of the address of NPSE mailbox queue should
+ * be implemented there.
+ */
+ if (ns_init->slot_count > NUM_MAILBOX_QUEUE_SLOT) {
+ return MAILBOX_INIT_ERROR;
+ }
+
+ s_queue->ns_status = ns_init->status;
+ s_queue->ns_slot_count = ns_init->slot_count;
+ s_queue->ns_slots = ns_init->slots;
+
+ multicore_ns_fifo_push_blocking_inline(S_MAILBOX_READY);
+
+ return MAILBOX_SUCCESS;
+}
+
+int32_t tfm_mailbox_hal_notify_peer(void)
+{
+ multicore_ns_fifo_push_blocking_inline(NOTIFY_FROM_CORE0);
+ return MAILBOX_SUCCESS;
+}
+
+void tfm_mailbox_hal_enter_critical(void)
+{
+ /* Reading a spinlock register attempts to claim it, returning nonzero
+ * if the claim was successful and 0 if unsuccessful */
+ while(!*MAILBOX_SPINLOCK);
+ return;
+}
+
+void tfm_mailbox_hal_exit_critical(void)
+{
+ /* Writing to a spinlock register releases it */
+ *MAILBOX_SPINLOCK = 0x1u;
+ return;
+}
+
+/* Platform specific inter-processor communication interrupt handler. */
+void SIO_IRQ_FIFO_NS_IRQHandler(void)
+{
+ /*
+ * SPM will send a MAILBOX_SIGNAL to the corresponding partition
+ * indicating that a message has arrived and can be processed.
+ */
+ uint32_t msg;
+ if (multicore_ns_fifo_rvalid())
+ {
+ msg = multicore_ns_fifo_pop_blocking_inline();
+ if (msg == NOTIFY_FROM_CORE1) {
+ spm_handle_interrupt(mbox_irq_info.p_pt, mbox_irq_info.p_ildi);
+ }
+ }
+}
+
+enum tfm_hal_status_t mailbox_irq_init(void *p_pt,
+ const struct irq_load_info_t *p_ildi)
+{
+ mbox_irq_info.p_pt = p_pt;
+ mbox_irq_info.p_ildi = p_ildi;
+
+
+ NVIC_SetPriority(SIO_IRQ_FIFO_NS_IRQn, DEFAULT_IRQ_PRIORITY-1);
+ irq_set_exclusive_handler(SIO_IRQ_FIFO_NS, SIO_IRQ_FIFO_NS_IRQHandler);
+
+ if (tfm_multi_core_register_client_id_range(CLIENT_ID_OWNER_MAGIC,
+ p_ildi->client_id_base,
+ p_ildi->client_id_limit) != 0) {
+ return TFM_HAL_ERROR_INVALID_INPUT;
+ }
+
+ return TFM_HAL_SUCCESS;
+}
\ No newline at end of file
diff --git a/platform/ext/target/rpi/rp2350/tfm_hal_multi_core.c b/platform/ext/target/rpi/rp2350/tfm_hal_multi_core.c
new file mode 100644
index 0000000..ccf8c1c
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tfm_hal_multi_core.c
@@ -0,0 +1,147 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_hal_multi_core.h"
+#include "platform_multicore.h"
+#include "target_cfg.h"
+#include "region_defs.h"
+
+#include "interrupt.h"
+#include "pico/multicore.h"
+#include "hardware/structs/sio.h"
+
+/* Entrypoint function declaration */
+extern void ns_agent_tz_main(uint32_t c_entry);
+
+volatile uint32_t CORE1_RUNNING;
+
+bool multicore_ns_fifo_rvalid(void) {
+ return !!(sio_ns_hw->fifo_st & SIO_FIFO_ST_VLD_BITS);
+}
+
+bool multicore_ns_fifo_wready(void) {
+ return !!(sio_ns_hw->fifo_st & SIO_FIFO_ST_RDY_BITS);
+}
+
+void multicore_ns_fifo_push_blocking_inline(uint32_t data) {
+ /* We wait for the fifo to have some space */
+ while (!multicore_ns_fifo_wready())
+ tight_loop_contents();
+
+ sio_ns_hw->fifo_wr = data;
+
+ /* Fire off an event to the other core */
+ __sev();
+}
+
+uint32_t multicore_ns_fifo_pop_blocking_inline(void) {
+ /* If nothing there yet, we wait for an event first,
+ to try and avoid too much busy waiting */
+ while (!multicore_ns_fifo_rvalid())
+ __wfe();
+
+ return sio_ns_hw->fifo_rd;
+}
+
+static void wait_for_core1_ready(void)
+{
+ uint32_t stage;
+ while (1) {
+ stage = multicore_fifo_pop_blocking();
+ if (stage == CORE1_S_READY) {
+ break;
+ }
+ }
+}
+
+/* If Core0 wants to write Flash, Core1 must not use it.
+ * As Core1 partly runs from Flash, it must be stopped while Core0 is writing.
+ * The simplest solution is for Core0 to ring Core1's doorbell where we wait out
+ * the flash operation, using spinlock. */
+static void __not_in_flash_func(Core1Doorbell_Handler)() {
+ uint32_t status = 0;
+ /* Prevent IRQs to fire, as their handlers might be in Flash */
+ __ASM volatile ("mrs %0, primask \n cpsid i" : "=r" (status) :: "memory");
+ /* Check if this is the "flash-in-use" doorbell */
+ if (sio_hw->doorbell_in_set & FLASH_DOORBELL_MASK)
+ {
+ /* Clear doorbell */
+ sio_hw->doorbell_in_clr = FLASH_DOORBELL_MASK;
+ /* Wait for Flash to be available, then release it immediately */
+ while(!*FLASH_SPINLOCK);
+ *FLASH_SPINLOCK = 0x1;
+ /* Check if this is the "halt" doorbell */
+ } else if (sio_hw->doorbell_in_set & HALT_DOORBELL_MASK)
+ {
+ /* Clear doorbell */
+ sio_hw->doorbell_in_clr = HALT_DOORBELL_MASK;
+ while (1) {
+ __WFE();
+ }
+ }
+ /* Restore IRQ status */
+ __ASM volatile ("msr primask, %0" :: "r" (status) : "memory");
+}
+
+static void core1_entry(void)
+{
+ __TZ_set_STACKSEAL_S((uint32_t *)__get_MSP());
+ /* Set up isolation boundaries between SPE and NSPE */
+ sau_and_idau_cfg();
+
+ NVIC_SetVector(SIO_IRQ_BELL_IRQn, (uint32_t) Core1Doorbell_Handler);
+ /* Set it to highest priority */
+ NVIC_SetPriority(SIO_IRQ_BELL_IRQn, 0x0);
+ NVIC_EnableIRQ(SIO_IRQ_BELL_IRQn);
+ __enable_irq();
+
+ NVIC_SetTargetState(SIO_IRQ_FIFO_NS_IRQn);
+ multicore_fifo_push_blocking(CORE1_S_READY);
+
+ ns_agent_tz_main(NS_CODE_CORE1_START);
+}
+
+static void boot_s_core(void)
+{
+ CORE1_RUNNING = 0x1;
+ multicore_launch_core1(core1_entry);
+ wait_for_core1_ready();
+}
+
+void tfm_hal_boot_ns_cpu(uintptr_t start_addr)
+{
+ boot_s_core();
+ return;
+}
+
+void tfm_hal_wait_for_ns_cpu_ready(void)
+{
+ uint32_t stage;
+ while (1) {
+ stage = multicore_ns_fifo_pop_blocking_inline();
+ if (stage == CORE1_NS_READY) {
+ break;
+ }
+ }
+ return;
+}
+
+void tfm_hal_get_secure_access_attr(const void *p, size_t s,
+ struct mem_attr_info_t *p_attr)
+{
+ /* Check static memory layout to get memory attributes */
+ tfm_get_secure_mem_region_attr(p, s, p_attr);
+#if TFM_ISOLATION_LEVEL >= 2
+ p_attr->is_mpu_enabled = true;
+#endif
+}
+
+void tfm_hal_get_ns_access_attr(const void *p, size_t s,
+ struct mem_attr_info_t *p_attr)
+{
+ /* Check static memory layout to get memory attributes */
+ tfm_get_ns_mem_region_attr(p, s, p_attr);
+}
diff --git a/platform/ext/target/rpi/rp2350/tfm_hal_platform.c b/platform/ext/target/rpi/rp2350/tfm_hal_platform.c
new file mode 100644
index 0000000..01d9fc1
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tfm_hal_platform.c
@@ -0,0 +1,127 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_hal_device_header.h"
+#include "tfm_peripherals_def.h"
+#include "common_target_cfg.h"
+#include "tfm_hal_platform.h"
+#include "uart_stdout.h"
+#include "region.h"
+#include "region_defs.h"
+#include "pico/bootrom.h"
+
+#include "hardware/structs/psm.h"
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+#include "platform_multicore.h"
+#include "hardware/structs/sio.h"
+#endif
+
+#if defined(TFM_PARTITION_SLIH_TEST) || defined(TFM_PARTITION_FLIH_TEST)
+#include "hardware/irq.h"
+extern void tfm_plat_test_secure_timer_irq_handler(void);
+#endif
+
+/* The section names come from the scatter file */
+REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base);
+REGION_DECLARE(Image$$, ER_VENEER, $$Base);
+REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit);
+#ifdef BL2
+REGION_DECLARE(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base);
+#endif /* BL2 */
+
+const struct memory_region_limits memory_regions = {
+ .non_secure_code_start =
+ (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
+ BL2_HEADER_SIZE,
+
+ .non_secure_partition_base =
+ (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base),
+
+ .non_secure_partition_limit =
+ (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
+ NS_PARTITION_SIZE - 1,
+
+ .veneer_base =
+ (uint32_t)®ION_NAME(Image$$, ER_VENEER, $$Base),
+
+ .veneer_limit =
+ (uint32_t)®ION_NAME(Image$$, VENEER_ALIGN, $$Limit) - 1,
+
+#ifdef BL2
+ .secondary_partition_base =
+ (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base),
+
+ .secondary_partition_limit =
+ (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base) +
+ SECONDARY_PARTITION_SIZE - 1,
+#endif /* BL2 */
+};
+
+extern __NO_RETURN void MemManage_Handler(void);
+extern __NO_RETURN void BusFault_Handler(void);
+extern __NO_RETURN void UsageFault_Handler(void);
+extern __NO_RETURN void SecureFault_Handler(void);
+
+enum tfm_hal_status_t tfm_hal_platform_init(void)
+{
+ NVIC_SetVector(MemoryManagement_IRQn, (uint32_t) MemManage_Handler);
+ NVIC_SetVector(BusFault_IRQn, (uint32_t) BusFault_Handler);
+ NVIC_SetVector(UsageFault_IRQn, (uint32_t) UsageFault_Handler);
+ NVIC_SetVector(SecureFault_IRQn, (uint32_t) SecureFault_Handler);
+
+ stdio_init();
+
+#if defined(TFM_PARTITION_SLIH_TEST) || defined(TFM_PARTITION_FLIH_TEST)
+ irq_set_exclusive_handler(TFM_TIMER0_IRQ, tfm_plat_test_secure_timer_irq_handler);
+#endif
+
+#ifdef PSA_API_TEST_IPC
+ irq_set_exclusive_handler(FF_TEST_UART_IRQ, FF_TEST_UART_IRQ_Handler);
+#endif
+
+ /* Reset everything apart from ROSC and XOSC */
+ hw_set_bits(&psm_hw->wdsel, PSM_WDSEL_BITS & ~(PSM_WDSEL_ROSC_BITS | PSM_WDSEL_XOSC_BITS));
+
+ __enable_irq();
+ return TFM_HAL_SUCCESS;
+}
+
+uint32_t tfm_hal_get_ns_VTOR(void)
+{
+ return memory_regions.non_secure_code_start;
+}
+
+uint32_t tfm_hal_get_ns_MSP(void)
+{
+ return *((uint32_t *)memory_regions.non_secure_code_start);
+}
+
+uint32_t tfm_hal_get_ns_entry_point(void)
+{
+ return *((uint32_t *)(memory_regions.non_secure_code_start + 4));
+}
+
+void tfm_hal_system_reset(void)
+{
+ __disable_irq();
+
+ NVIC_SystemReset();
+}
+
+void tfm_hal_system_halt(void)
+{
+ __disable_irq();
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ /* Signal Core1 to wait for flash */
+ sio_hw->doorbell_out_set = HALT_DOORBELL_MASK;
+#endif
+
+ while (1) {
+ __WFE();
+ }
+
+}
diff --git a/platform/ext/target/rpi/rp2350/tfm_peripherals_def.c b/platform/ext/target/rpi/rp2350/tfm_peripherals_def.c
new file mode 100644
index 0000000..8a32c43
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tfm_peripherals_def.c
@@ -0,0 +1,27 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include "tfm_peripherals_def.h"
+#include "array.h"
+#include "tfm_hal_device_header.h"
+
+/* Allowed named MMIO of this platform */
+const uintptr_t partition_named_mmio_list[] = {
+ (uintptr_t)TFM_PERIPHERAL_TIMER0,
+ (uintptr_t)TFM_PERIPHERAL_STD_UART,
+#ifdef PSA_API_TEST_IPC
+ (uintptr_t)FF_TEST_UART_REGION,
+ (uintptr_t)FF_TEST_WATCHDOG_REGION,
+ (uintptr_t)FF_TEST_NVMEM_REGION,
+ (uintptr_t)FF_TEST_SERVER_PARTITION_MMIO,
+ (uintptr_t)FF_TEST_DRIVER_PARTITION_MMIO,
+#endif
+};
+
+void get_partition_named_mmio_list(const uintptr_t** list, size_t* length) {
+ *list = partition_named_mmio_list;
+ *length = ARRAY_SIZE(partition_named_mmio_list);
+}
diff --git a/platform/ext/target/rpi/rp2350/tfm_peripherals_def.h b/platform/ext/target/rpi/rp2350/tfm_peripherals_def.h
new file mode 100644
index 0000000..a758cdb
--- /dev/null
+++ b/platform/ext/target/rpi/rp2350/tfm_peripherals_def.h
@@ -0,0 +1,54 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#ifndef __TFM_PERIPHERALS_DEF_H__
+#define __TFM_PERIPHERALS_DEF_H__
+
+#include "hardware/irq.h"
+#include "common_target_cfg.h"
+#include "tfm_hal_device_header.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Quantized default IRQ priority, the value is:
+ * (Number of configurable priority) / 2: (1UL << __NVIC_PRIO_BITS) / 4
+ */
+
+#define DEFAULT_IRQ_PRIORITY (1UL << (__NVIC_PRIO_BITS - 2))
+
+#define TFM_TIMER0_IRQ (TIMER0_IRQ_0_IRQn)
+#define MAILBOX_IRQ SIO_IRQ_FIFO_NS_IRQn
+
+#define FF_TEST_UART_IRQ (UART0_IRQ)
+extern void FF_TEST_UART_IRQ_Handler(void);
+
+extern struct platform_data_t tfm_peripheral_std_uart;
+extern struct platform_data_t tfm_peripheral_timer0;
+
+#define TFM_PERIPHERAL_STD_UART (&tfm_peripheral_std_uart)
+#define TFM_PERIPHERAL_TIMER0 (&tfm_peripheral_timer0)
+
+#ifdef PSA_API_TEST_IPC
+extern struct platform_data_t tfm_peripheral_FF_TEST_UART_REGION;
+extern struct platform_data_t tfm_peripheral_FF_TEST_WATCHDOG_REGION;
+extern struct platform_data_t tfm_peripheral_FF_TEST_NVMEM_REGION;
+extern struct platform_data_t tfm_peripheral_FF_TEST_SERVER_PARTITION_MMIO;
+extern struct platform_data_t tfm_peripheral_FF_TEST_DRIVER_PARTITION_MMIO;
+#define FF_TEST_UART_REGION (&tfm_peripheral_FF_TEST_UART_REGION)
+#define FF_TEST_WATCHDOG_REGION (&tfm_peripheral_FF_TEST_WATCHDOG_REGION)
+#define FF_TEST_NVMEM_REGION (&tfm_peripheral_FF_TEST_NVMEM_REGION)
+#define FF_TEST_SERVER_PARTITION_MMIO (&tfm_peripheral_FF_TEST_SERVER_PARTITION_MMIO)
+#define FF_TEST_DRIVER_PARTITION_MMIO (&tfm_peripheral_FF_TEST_DRIVER_PARTITION_MMIO)
+#endif /* PSA_API_TEST_IPC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_PERIPHERALS_DEF_H__ */