diff --git a/interface/include/tfm_platform_api.h b/interface/include/tfm_platform_api.h index e925503943..f48a406bb8 100644 --- a/interface/include/tfm_platform_api.h +++ b/interface/include/tfm_platform_api.h @@ -27,6 +27,7 @@ extern "C" { #define TFM_PLATFORM_API_ID_NV_INCREMENT (1011) #define TFM_PLATFORM_API_ID_SYSTEM_RESET (1012) #define TFM_PLATFORM_API_ID_IOCTL (1013) +#define TFM_PLATFORM_API_ID_SYSTEM_OFF (1014) /*! * \enum tfm_platform_err_t @@ -53,6 +54,14 @@ typedef int32_t tfm_platform_ioctl_req_t; */ enum tfm_platform_err_t tfm_platform_system_reset(void); +/*! + * \brief System off function to move the system to the lowest power state + * + * \return On success the processor will go to system off, in case of error it returns + * values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_system_off(void); + /*! * \brief Performs a platform-specific service * diff --git a/interface/src/tfm_platform_api.c b/interface/src/tfm_platform_api.c index 4fc564b52e..ac6960a1b4 100644 --- a/interface/src/tfm_platform_api.c +++ b/interface/src/tfm_platform_api.c @@ -26,6 +26,21 @@ enum tfm_platform_err_t tfm_platform_system_reset(void) } +enum tfm_platform_err_t tfm_platform_system_off(void) +{ + psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; + + status = psa_call(TFM_PLATFORM_SERVICE_HANDLE, + TFM_PLATFORM_API_ID_SYSTEM_OFF, + NULL, 0, NULL, 0); + + if (status < PSA_SUCCESS) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } else { + return (enum tfm_platform_err_t)status; + } +} + enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, psa_invec *input, psa_outvec *output) diff --git a/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt b/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt index e8a884d638..7d97beeb06 100644 --- a/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt +++ b/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt @@ -158,6 +158,18 @@ if(TFM_SPM_LOG_RAW_ENABLED) ) endif() +if(TFM_NRF_SYSTEM_OFF_SERVICE) + target_sources(platform_s + PRIVATE + ${HAL_NORDIC_PATH}/nrfx/helpers/nrfx_ram_ctrl.c + ) + + target_compile_definitions(platform_s + PUBLIC + TFM_NRF_SYSTEM_OFF_SERVICE + ) +endif() + target_compile_options(platform_s PUBLIC ${COMPILER_CMSE_FLAG} diff --git a/platform/include/tfm_platform_system.h b/platform/include/tfm_platform_system.h index 40bd13026c..a2fd5217af 100644 --- a/platform/include/tfm_platform_system.h +++ b/platform/include/tfm_platform_system.h @@ -28,6 +28,14 @@ extern "C" { TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_SP_PLATFORM", "PSA-ROT") void tfm_platform_hal_system_reset(void); +/** + * \brief Set system power state to off. + * + * \details Requests the system to enter a low-power state. + */ +TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_SP_PLATFORM", "PSA-ROT") +enum tfm_platform_err_t tfm_platform_hal_system_off(void); + /*! * \brief Performs a platform-specific service * diff --git a/secure_fw/partitions/platform/platform_sp.c b/secure_fw/partitions/platform/platform_sp.c index d0172b36fa..7872e05616 100644 --- a/secure_fw/partitions/platform/platform_sp.c +++ b/secure_fw/partitions/platform/platform_sp.c @@ -39,6 +39,24 @@ enum tfm_platform_err_t platform_sp_system_reset(void) return TFM_PLATFORM_ERR_SUCCESS; } +#if TFM_NRF_SYSTEM_OFF_SERVICE +enum tfm_platform_err_t platform_sp_system_off(void) +{ + /* FIXME: The system off functionality is only supported in isolation + * level 1. + */ + + return tfm_platform_hal_system_off(); +} + +static psa_status_t platform_sp_system_off_psa_api(const psa_msg_t *msg) +{ + (void)msg; /* unused parameter */ + + return platform_sp_system_off(); +} +#endif /* TFM_NRF_SYSTEM_OFF_SERVICE */ + static psa_status_t platform_sp_system_reset_psa_api(const psa_msg_t *msg) { (void)msg; /* unused parameter */ @@ -225,6 +243,10 @@ psa_status_t tfm_platform_service_sfn(const psa_msg_t *msg) #endif /* PLATFORM_NV_COUNTER_MODULE_DISABLED */ case TFM_PLATFORM_API_ID_SYSTEM_RESET: return platform_sp_system_reset_psa_api(msg); +#if TFM_NRF_SYSTEM_OFF_SERVICE + case TFM_PLATFORM_API_ID_SYSTEM_OFF: + return platform_sp_system_off_psa_api(msg); +#endif /* TFM_NRF_SYSTEM_OFF_SERVICE */ case TFM_PLATFORM_API_ID_IOCTL: return platform_sp_ioctl_psa_api(msg); default: