Core: separate IPC and veneer fn-based code
Improve separation of IPC and veneer function-based code in the
source tree for memory optimization and better readability of source:
- Do not compile unused SVC handler functions if using IPC messaging
- Avoid activation of MPU regions not needed in selected build
configuration
- Flag error if a service veneer function is called when running IPC
messaging
- Do not include memory bounds for partitions in SPM database if
level 1 isolation and veneer functions are used to save memory
Signed-off-by: Miklos Balint <miklos.balint@arm.com>
Change-Id: Iaef91e69061b639a71ec8cb638b6393762d10761
diff --git a/platform/ext/common/armclang/tfm_common_s.sct b/platform/ext/common/armclang/tfm_common_s.sct
index bef75d5..be87a0b 100644
--- a/platform/ext/common/armclang/tfm_common_s.sct
+++ b/platform/ext/common/armclang/tfm_common_s.sct
@@ -157,15 +157,10 @@
.ANY (+RW +ZI)
}
-#if TFM_LVL == 1
-#ifdef TFM_PSA_API
- TFM_SECURE_STACK +0 ALIGN 128 EMPTY 0x0200 {
- }
-#else
+#if (TFM_LVL == 1) && !defined(TFM_PSA_API)
TFM_SECURE_STACK +0 ALIGN 128 EMPTY 0x2000 {
}
-#endif /* TFM_PSA_API */
-#endif /* TFM_LVL == 1 */
+#endif /* (TFM_LVL == 1) && !defined(TFM_PSA_API) */
TFM_UNPRIV_DATA +0 ALIGN 32 {
tfm_spm_services.o (+RW +ZI)
@@ -177,10 +172,7 @@
device_definition.o (+RW +ZI)
}
-#ifdef TFM_PSA_API
- TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x0 {
- }
-#else
+#if !defined(TFM_PSA_API)
TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 {
}
#endif /* TFM_PSA_API */
@@ -197,36 +189,52 @@
*tfm_storage* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_STORAGE_STACK +0 ALIGN 128 EMPTY 0x1800 {
}
+#endif
TFM_SP_AUDIT_LOG_DATA +0 ALIGN 32 {
*tfm_audit* (+RW +ZI)
}
+#if defined (TFM_PSA_API)
+ TFM_SP_AUDIT_LOG_STACK +0 ALIGN 128 EMPTY 0 {
+ }
+#elif TFM_LVL != 1
TFM_SP_AUDIT_LOG_STACK +0 ALIGN 128 EMPTY 0x0200 {
}
+#endif
TFM_SP_CRYPTO_DATA +0 ALIGN 32 {
*tfm_crypto* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_CRYPTO_STACK +0 ALIGN 128 EMPTY 0x2000 {
}
+#endif
TFM_SP_PLATFORM_DATA +0 ALIGN 32 {
*tfm_platform* (+RW +ZI)
}
+#if defined (TFM_PSA_API)
+ TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0 {
+ }
+#elif TFM_LVL != 1
TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 {
}
+#endif
TFM_SP_INITIAL_ATTESTATION_DATA +0 ALIGN 32 {
*tfm_attest* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_INITIAL_ATTESTATION_STACK +0 ALIGN 128 EMPTY 0x0A00 {
}
+#endif
#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
TFM_SP_SECURE_TEST_PARTITION_DATA +0 ALIGN 32 {
@@ -240,8 +248,10 @@
*attestation_s_interface_testsuite.* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_SECURE_TEST_PARTITION_STACK +0 ALIGN 128 EMPTY 0x0C00 {
}
+#endif
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
#ifdef TFM_PSA_API
@@ -249,8 +259,10 @@
*ipc_service_test.* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_IPC_SERVICE_TEST_STACK +0 ALIGN 128 EMPTY 0x0200 {
}
+#endif
#endif /* TFM_PSA_API */
/*
@@ -273,8 +285,10 @@
*tfm_ss_core_test.* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_CORE_TEST_STACK +0 ALIGN 128 EMPTY 0x0300 {
}
+#endif
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PARTITION_TEST_CORE
@@ -282,8 +296,10 @@
*tfm_ss_core_test_2.* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_CORE_TEST_2_STACK +0 ALIGN 128 EMPTY 0x0200 {
}
+#endif
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PSA_API
@@ -291,8 +307,10 @@
*ipc_client_test.* (+RW +ZI)
}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
TFM_SP_IPC_CLIENT_TEST_STACK +0 ALIGN 128 EMPTY 0x0200 {
}
+#endif
#endif /* TFM_PSA_API */
/*
diff --git a/platform/ext/common/armclang/tfm_common_s.sct.template b/platform/ext/common/armclang/tfm_common_s.sct.template
index 5ff6546..5b86230 100644
--- a/platform/ext/common/armclang/tfm_common_s.sct.template
+++ b/platform/ext/common/armclang/tfm_common_s.sct.template
@@ -138,15 +138,10 @@
.ANY (+RW +ZI)
}
-#if TFM_LVL == 1
-#ifdef TFM_PSA_API
- TFM_SECURE_STACK +0 ALIGN 128 EMPTY 0x0200 {
- }
-#else
+#if (TFM_LVL == 1) && !defined(TFM_PSA_API)
TFM_SECURE_STACK +0 ALIGN 128 EMPTY 0x2000 {
}
-#endif /* TFM_PSA_API */
-#endif /* TFM_LVL == 1 */
+#endif /* (TFM_LVL == 1) && !defined(TFM_PSA_API) */
TFM_UNPRIV_DATA +0 ALIGN 32 {
tfm_spm_services.o (+RW +ZI)
@@ -158,10 +153,7 @@
device_definition.o (+RW +ZI)
}
-#ifdef TFM_PSA_API
- TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x0 {
- }
-#else
+#if !defined(TFM_PSA_API)
TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 {
}
#endif /* TFM_PSA_API */
@@ -192,8 +184,20 @@
{% endif %}
}
+ {% if manifest.manifest.tfm_partition_ipc %}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
{{manifest.manifest.name}}_STACK +0 ALIGN 128 EMPTY {{manifest.manifest.stack_size}} {
}
+#endif
+ {% else %}
+#if defined (TFM_PSA_API)
+ {{manifest.manifest.name}}_STACK +0 ALIGN 128 EMPTY 0 {
+ }
+#elif TFM_LVL != 1
+ {{manifest.manifest.name}}_STACK +0 ALIGN 128 EMPTY {{manifest.manifest.stack_size}} {
+ }
+#endif
+ {% endif %}
{% if manifest.attr.conditional %}
#endif /* {{manifest.attr.conditional}} */
{% endif %}
@@ -233,8 +237,20 @@
{% endif %}
}
+ {% if manifest.manifest.tfm_partition_ipc %}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
{{manifest.manifest.name}}_STACK +0 ALIGN 128 EMPTY {{manifest.manifest.stack_size}} {
}
+#endif
+ {% else %}
+#if defined (TFM_PSA_API)
+ {{manifest.manifest.name}}_STACK +0 ALIGN 128 EMPTY 0 {
+ }
+#elif TFM_LVL != 1
+ {{manifest.manifest.name}}_STACK +0 ALIGN 128 EMPTY {{manifest.manifest.stack_size}} {
+ }
+#endif
+ {% endif %}
{% if manifest.attr.conditional %}
#endif /* {{manifest.attr.conditional}} */
{% endif %}
diff --git a/platform/ext/common/gcc/tfm_common_s.ld b/platform/ext/common/gcc/tfm_common_s.ld
index 7a57ff1..fa31129 100644
--- a/platform/ext/common/gcc/tfm_common_s.ld
+++ b/platform/ext/common/gcc/tfm_common_s.ld
@@ -117,6 +117,7 @@
__zero_table_start__ = .;
LONG (ADDR(.TFM_BSS))
LONG (SIZEOF(.TFM_BSS))
+#if !defined(TFM_PSA_API)
#if TFM_LVL == 1
LONG (ADDR(.TFM_SECURE_STACK))
LONG (SIZEOF(.TFM_SECURE_STACK))
@@ -124,58 +125,81 @@
LONG (ADDR(.TFM_UNPRIV_BSS))
LONG (SIZEOF(.TFM_UNPRIV_BSS))
#endif /* TFM_LVL == 1 */
+#endif /* !defined(TFM_PSA_API) */
LONG (ADDR(.TFM_SP_STORAGE_BSS))
LONG (SIZEOF(.TFM_SP_STORAGE_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_STORAGE_STACK))
LONG (SIZEOF(.TFM_SP_STORAGE_STACK))
+#endif
LONG (ADDR(.TFM_SP_AUDIT_LOG_BSS))
LONG (SIZEOF(.TFM_SP_AUDIT_LOG_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_AUDIT_LOG_STACK))
LONG (SIZEOF(.TFM_SP_AUDIT_LOG_STACK))
+#endif
LONG (ADDR(.TFM_SP_CRYPTO_BSS))
LONG (SIZEOF(.TFM_SP_CRYPTO_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_CRYPTO_STACK))
LONG (SIZEOF(.TFM_SP_CRYPTO_STACK))
+#endif
LONG (ADDR(.TFM_SP_PLATFORM_BSS))
LONG (SIZEOF(.TFM_SP_PLATFORM_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_PLATFORM_STACK))
LONG (SIZEOF(.TFM_SP_PLATFORM_STACK))
+#endif
LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS))
LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK))
LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK))
+#endif
#ifdef TFM_PARTITION_TEST_CORE
LONG (ADDR(.TFM_SP_CORE_TEST_BSS))
LONG (SIZEOF(.TFM_SP_CORE_TEST_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_CORE_TEST_STACK))
LONG (SIZEOF(.TFM_SP_CORE_TEST_STACK))
+#endif
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PARTITION_TEST_CORE
LONG (ADDR(.TFM_SP_CORE_TEST_2_BSS))
LONG (SIZEOF(.TFM_SP_CORE_TEST_2_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_CORE_TEST_2_STACK))
LONG (SIZEOF(.TFM_SP_CORE_TEST_2_STACK))
+#endif
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_BSS))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK))
+#endif
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
#ifdef TFM_PSA_API
LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS))
LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK))
LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK))
+#endif
#endif /* TFM_PSA_API */
#ifdef TFM_PSA_API
LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS))
LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK))
LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK))
+#endif
#endif /* TFM_PSA_API */
+#if !defined(TFM_PSA_API)
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
+#endif /* !defined(TFM_PSA_API) */
__zero_table_end__ = .;
} > FLASH
@@ -429,16 +453,14 @@
#if TFM_LVL == 1
+#if !defined(TFM_PSA_API)
.TFM_SECURE_STACK : ALIGN(128)
{
-#ifdef TFM_PSA_API
- . += 0x0200;
-#else
. += 0x2000;
-#endif /* TFM_PSA_API */
} > RAM
Image$$TFM_SECURE_STACK$$ZI$$Base = ADDR(.TFM_SECURE_STACK);
Image$$TFM_SECURE_STACK$$ZI$$Limit = ADDR(.TFM_SECURE_STACK) + SIZEOF(.TFM_SECURE_STACK);
+#endif /* !defined(TFM_PSA_API) */
.heap : ALIGN(8)
{
@@ -486,16 +508,14 @@
Image$$TFM_UNPRIV_DATA$$ZI$$Limit = ADDR(.TFM_UNPRIV_BSS) + SIZEOF(.TFM_UNPRIV_BSS);
#endif /* TFM_LVL == 1 */
+#if !defined(TFM_PSA_API)
.TFM_UNPRIV_SCRATCH : ALIGN(32)
{
-#ifdef TFM_PSA_API
- . += 0x0;
-#else
. += 0x400;
-#endif /* TFM_PSA_API */
} > RAM
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH);
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH);
+#endif /* !defined(TFM_PSA_API) */
/**** PSA RoT DATA start here */
Image$$TFM_PSA_RW_STACK_START$$Base = .;
@@ -517,12 +537,15 @@
Image$$TFM_SP_STORAGE_DATA$$ZI$$Base = ADDR(.TFM_SP_STORAGE_BSS);
Image$$TFM_SP_STORAGE_DATA$$ZI$$Limit = ADDR(.TFM_SP_STORAGE_BSS) + SIZEOF(.TFM_SP_STORAGE_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_STORAGE_STACK : ALIGN(128)
{
. += 0x1800;
} > RAM
Image$$TFM_SP_STORAGE_STACK$$ZI$$Base = ADDR(.TFM_SP_STORAGE_STACK);
Image$$TFM_SP_STORAGE_STACK$$ZI$$Limit = ADDR(.TFM_SP_STORAGE_STACK) + SIZEOF(.TFM_SP_STORAGE_STACK);
+#endif
+
.TFM_SP_AUDIT_LOG_DATA : ALIGN(32)
{
@@ -541,12 +564,17 @@
Image$$TFM_SP_AUDIT_LOG_DATA$$ZI$$Base = ADDR(.TFM_SP_AUDIT_LOG_BSS);
Image$$TFM_SP_AUDIT_LOG_DATA$$ZI$$Limit = ADDR(.TFM_SP_AUDIT_LOG_BSS) + SIZEOF(.TFM_SP_AUDIT_LOG_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_AUDIT_LOG_STACK : ALIGN(128)
{
+#if !defined(TFM_PSA_API)
. += 0x0200;
+#endif
} > RAM
Image$$TFM_SP_AUDIT_LOG_STACK$$ZI$$Base = ADDR(.TFM_SP_AUDIT_LOG_STACK);
Image$$TFM_SP_AUDIT_LOG_STACK$$ZI$$Limit = ADDR(.TFM_SP_AUDIT_LOG_STACK) + SIZEOF(.TFM_SP_AUDIT_LOG_STACK);
+#endif
+
.TFM_SP_CRYPTO_DATA : ALIGN(32)
{
@@ -565,12 +593,15 @@
Image$$TFM_SP_CRYPTO_DATA$$ZI$$Base = ADDR(.TFM_SP_CRYPTO_BSS);
Image$$TFM_SP_CRYPTO_DATA$$ZI$$Limit = ADDR(.TFM_SP_CRYPTO_BSS) + SIZEOF(.TFM_SP_CRYPTO_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_CRYPTO_STACK : ALIGN(128)
{
. += 0x2000;
} > RAM
Image$$TFM_SP_CRYPTO_STACK$$ZI$$Base = ADDR(.TFM_SP_CRYPTO_STACK);
Image$$TFM_SP_CRYPTO_STACK$$ZI$$Limit = ADDR(.TFM_SP_CRYPTO_STACK) + SIZEOF(.TFM_SP_CRYPTO_STACK);
+#endif
+
.TFM_SP_PLATFORM_DATA : ALIGN(32)
{
@@ -589,12 +620,17 @@
Image$$TFM_SP_PLATFORM_DATA$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_BSS);
Image$$TFM_SP_PLATFORM_DATA$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_BSS) + SIZEOF(.TFM_SP_PLATFORM_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_PLATFORM_STACK : ALIGN(128)
{
+#if !defined(TFM_PSA_API)
. += 0x0400;
+#endif
} > RAM
Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK);
Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK);
+#endif
+
.TFM_SP_INITIAL_ATTESTATION_DATA : ALIGN(32)
{
@@ -613,12 +649,15 @@
Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS);
Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_INITIAL_ATTESTATION_STACK : ALIGN(128)
{
. += 0x0A00;
} > RAM
Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK);
Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK);
+#endif
+
#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
.TFM_SP_SECURE_TEST_PARTITION_DATA : ALIGN(32)
@@ -659,12 +698,15 @@
Image$$TFM_SP_SECURE_TEST_PARTITION_DATA$$ZI$$Base = ADDR(.TFM_SP_SECURE_TEST_PARTITION_BSS);
Image$$TFM_SP_SECURE_TEST_PARTITION_DATA$$ZI$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION_BSS) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_SECURE_TEST_PARTITION_STACK : ALIGN(128)
{
. += 0x0C00;
} > RAM
Image$$TFM_SP_SECURE_TEST_PARTITION_STACK$$ZI$$Base = ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK);
Image$$TFM_SP_SECURE_TEST_PARTITION_STACK$$ZI$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK);
+#endif
+
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
#ifdef TFM_PSA_API
@@ -685,12 +727,15 @@
Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS);
Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_IPC_SERVICE_TEST_STACK : ALIGN(128)
{
. += 0x0200;
} > RAM
Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK);
Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK);
+#endif
+
#endif /* TFM_PSA_API */
/**** PSA RoT DATA end here */
@@ -717,12 +762,15 @@
Image$$TFM_SP_CORE_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_CORE_TEST_BSS);
Image$$TFM_SP_CORE_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_CORE_TEST_BSS) + SIZEOF(.TFM_SP_CORE_TEST_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_CORE_TEST_STACK : ALIGN(128)
{
. += 0x0300;
} > RAM
Image$$TFM_SP_CORE_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_CORE_TEST_STACK);
Image$$TFM_SP_CORE_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_CORE_TEST_STACK) + SIZEOF(.TFM_SP_CORE_TEST_STACK);
+#endif
+
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PARTITION_TEST_CORE
@@ -743,12 +791,15 @@
Image$$TFM_SP_CORE_TEST_2_DATA$$ZI$$Base = ADDR(.TFM_SP_CORE_TEST_2_BSS);
Image$$TFM_SP_CORE_TEST_2_DATA$$ZI$$Limit = ADDR(.TFM_SP_CORE_TEST_2_BSS) + SIZEOF(.TFM_SP_CORE_TEST_2_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_CORE_TEST_2_STACK : ALIGN(128)
{
. += 0x0200;
} > RAM
Image$$TFM_SP_CORE_TEST_2_STACK$$ZI$$Base = ADDR(.TFM_SP_CORE_TEST_2_STACK);
Image$$TFM_SP_CORE_TEST_2_STACK$$ZI$$Limit = ADDR(.TFM_SP_CORE_TEST_2_STACK) + SIZEOF(.TFM_SP_CORE_TEST_2_STACK);
+#endif
+
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PSA_API
@@ -769,12 +820,15 @@
Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS);
Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS);
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.TFM_SP_IPC_CLIENT_TEST_STACK : ALIGN(128)
{
. += 0x0200;
} > RAM
Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK);
Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK);
+#endif
+
#endif /* TFM_PSA_API */
/**** APPLICATION RoT DATA end here */
diff --git a/platform/ext/common/gcc/tfm_common_s.ld.template b/platform/ext/common/gcc/tfm_common_s.ld.template
index b985d83..4f0395d 100644
--- a/platform/ext/common/gcc/tfm_common_s.ld.template
+++ b/platform/ext/common/gcc/tfm_common_s.ld.template
@@ -88,6 +88,7 @@
__zero_table_start__ = .;
LONG (ADDR(.TFM_BSS))
LONG (SIZEOF(.TFM_BSS))
+#if !defined(TFM_PSA_API)
#if TFM_LVL == 1
LONG (ADDR(.TFM_SECURE_STACK))
LONG (SIZEOF(.TFM_SECURE_STACK))
@@ -95,20 +96,25 @@
LONG (ADDR(.TFM_UNPRIV_BSS))
LONG (SIZEOF(.TFM_UNPRIV_BSS))
#endif /* TFM_LVL == 1 */
+#endif /* !defined(TFM_PSA_API) */
{% for manifest in manifests %}
{% if manifest.attr.conditional %}
#ifdef {{manifest.attr.conditional}}
{% endif %}
LONG (ADDR(.{{manifest.manifest.name}}_BSS))
LONG (SIZEOF(.{{manifest.manifest.name}}_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
LONG (ADDR(.{{manifest.manifest.name}}_STACK))
LONG (SIZEOF(.{{manifest.manifest.name}}_STACK))
- {% if manifest.attr.conditional %}
+#endif
+ {% if manifest.attr.conditional %}
#endif /* {{manifest.attr.conditional}} */
{% endif %}
{% endfor %}
+#if !defined(TFM_PSA_API)
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
+#endif /* !defined(TFM_PSA_API) */
__zero_table_end__ = .;
} > FLASH
@@ -282,16 +288,14 @@
#if TFM_LVL == 1
+#if !defined(TFM_PSA_API)
.TFM_SECURE_STACK : ALIGN(128)
{
-#ifdef TFM_PSA_API
- . += 0x0200;
-#else
. += 0x2000;
-#endif /* TFM_PSA_API */
} > RAM
Image$$TFM_SECURE_STACK$$ZI$$Base = ADDR(.TFM_SECURE_STACK);
Image$$TFM_SECURE_STACK$$ZI$$Limit = ADDR(.TFM_SECURE_STACK) + SIZEOF(.TFM_SECURE_STACK);
+#endif /* !defined(TFM_PSA_API) */
.heap : ALIGN(8)
{
@@ -339,16 +343,14 @@
Image$$TFM_UNPRIV_DATA$$ZI$$Limit = ADDR(.TFM_UNPRIV_BSS) + SIZEOF(.TFM_UNPRIV_BSS);
#endif /* TFM_LVL == 1 */
+#if !defined(TFM_PSA_API)
.TFM_UNPRIV_SCRATCH : ALIGN(32)
{
-#ifdef TFM_PSA_API
- . += 0x0;
-#else
. += 0x400;
-#endif /* TFM_PSA_API */
} > RAM
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH);
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH);
+#endif /* !defined(TFM_PSA_API) */
/**** PSA RoT DATA start here */
Image$$TFM_PSA_RW_STACK_START$$Base = .;
@@ -394,12 +396,29 @@
Image$${{manifest.manifest.name}}_DATA$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_BSS);
Image$${{manifest.manifest.name}}_DATA$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_BSS) + SIZEOF(.{{manifest.manifest.name}}_BSS);
+ {% if manifest.manifest.tfm_partition_ipc %}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.{{manifest.manifest.name}}_STACK : ALIGN(128)
{
. += {{manifest.manifest.stack_size}};
} > RAM
Image$${{manifest.manifest.name}}_STACK$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_STACK);
Image$${{manifest.manifest.name}}_STACK$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_STACK) + SIZEOF(.{{manifest.manifest.name}}_STACK);
+#endif
+ {% else %}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
+ .{{manifest.manifest.name}}_STACK : ALIGN(128)
+ {
+ {# Note: Don't allocate stack for partition when using TFM_PSA_API if tfm_partition_ipc is false #}
+#if !defined(TFM_PSA_API)
+ . += {{manifest.manifest.stack_size}};
+#endif
+ } > RAM
+ Image$${{manifest.manifest.name}}_STACK$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_STACK);
+ Image$${{manifest.manifest.name}}_STACK$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_STACK) + SIZEOF(.{{manifest.manifest.name}}_STACK);
+#endif
+ {% endif %}
+
{% if manifest.attr.conditional %}
#endif /* {{manifest.attr.conditional}} */
{% endif %}
@@ -453,12 +472,29 @@
Image$${{manifest.manifest.name}}_DATA$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_BSS);
Image$${{manifest.manifest.name}}_DATA$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_BSS) + SIZEOF(.{{manifest.manifest.name}}_BSS);
+ {% if manifest.manifest.tfm_partition_ipc %}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
.{{manifest.manifest.name}}_STACK : ALIGN(128)
{
. += {{manifest.manifest.stack_size}};
} > RAM
Image$${{manifest.manifest.name}}_STACK$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_STACK);
Image$${{manifest.manifest.name}}_STACK$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_STACK) + SIZEOF(.{{manifest.manifest.name}}_STACK);
+#endif
+ {% else %}
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
+ .{{manifest.manifest.name}}_STACK : ALIGN(128)
+ {
+ {# Note: Don't allocate stack for partition when using TFM_PSA_API if tfm_partition_ipc is false #}
+#if !defined(TFM_PSA_API)
+ . += {{manifest.manifest.stack_size}};
+#endif
+ } > RAM
+ Image$${{manifest.manifest.name}}_STACK$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_STACK);
+ Image$${{manifest.manifest.name}}_STACK$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_STACK) + SIZEOF(.{{manifest.manifest.name}}_STACK);
+#endif
+ {% endif %}
+
{% if manifest.attr.conditional %}
#endif /* {{manifest.attr.conditional}} */
{% endif %}
diff --git a/platform/ext/target/mps2/an519/spm_hal.c b/platform/ext/target/mps2/an519/spm_hal.c
index 2ebac2e..a8c4ec5 100644
--- a/platform/ext/target/mps2/an519/spm_hal.c
+++ b/platform/ext/target/mps2/an519/spm_hal.c
@@ -63,8 +63,10 @@
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$RW$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$ZI$$Limit);
+#ifndef TFM_PSA_API
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif
#if TFM_LVL == 2
REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
@@ -275,6 +277,7 @@
return SPM_ERR_OK;
}
+#if !defined(TFM_PSA_API)
/**
* Set share region to which the partition needs access
*/
@@ -328,7 +331,7 @@
return res;
}
-
+#endif /* !defined(TFM_PSA_API) */
#endif /* TFM_LVL != 1 */
void tfm_spm_hal_setup_isolation_hw(void)
diff --git a/platform/ext/target/mps2/an521/spm_hal.c b/platform/ext/target/mps2/an521/spm_hal.c
index ecb244b..6a8d7be 100644
--- a/platform/ext/target/mps2/an521/spm_hal.c
+++ b/platform/ext/target/mps2/an521/spm_hal.c
@@ -63,8 +63,10 @@
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$RW$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$ZI$$Limit);
+#ifndef TFM_PSA_API
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif
#if TFM_LVL == 2
REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
@@ -275,6 +277,7 @@
return SPM_ERR_OK;
}
+#if !defined(TFM_PSA_API)
/**
* Set share region to which the partition needs access
*/
@@ -328,7 +331,7 @@
return res;
}
-
+#endif /* !defined(TFM_PSA_API) */
#endif /* TFM_LVL != 1 */
void tfm_spm_hal_setup_isolation_hw(void)
diff --git a/platform/ext/target/musca_a/spm_hal.c b/platform/ext/target/musca_a/spm_hal.c
index 85c4d76..11f618d 100644
--- a/platform/ext/target/musca_a/spm_hal.c
+++ b/platform/ext/target/musca_a/spm_hal.c
@@ -63,8 +63,10 @@
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$RW$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$ZI$$Limit);
+#ifndef TFM_PSA_API
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif
#if TFM_LVL == 2
REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
@@ -275,6 +277,7 @@
return SPM_ERR_OK;
}
+#if !defined(TFM_PSA_API)
/**
* Set share region to which the partition needs access
*/
@@ -328,7 +331,7 @@
return res;
}
-
+#endif /* !defined(TFM_PSA_API) */
#endif /* TFM_LVL != 1 */
void tfm_spm_hal_setup_isolation_hw(void)
diff --git a/platform/ext/target/musca_a/target_cfg.c b/platform/ext/target/musca_a/target_cfg.c
index bd12d31..f02518a 100644
--- a/platform/ext/target/musca_a/target_cfg.c
+++ b/platform/ext/target/musca_a/target_cfg.c
@@ -231,10 +231,6 @@
SAU->RLAR = (PERIPHERALS_BASE_NS_END & SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk;
- /* FIXME: Secondary image partition info comes from BL2. Configure SAU
- * based on those limits.
- */
-
/* Allows SAU to define the code region as a NSC */
struct spctrl_def* spctrl = CMSDK_SPCTRL;
spctrl->nsccfg |= NSCCFG_CODENSC;
diff --git a/platform/ext/target/musca_b1/spm_hal.c b/platform/ext/target/musca_b1/spm_hal.c
index 2d8f678..858c4d1 100644
--- a/platform/ext/target/musca_b1/spm_hal.c
+++ b/platform/ext/target/musca_b1/spm_hal.c
@@ -63,8 +63,10 @@
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$RW$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$ZI$$Limit);
+#ifndef TFM_PSA_API
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif
#if TFM_LVL == 2
REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
@@ -275,6 +277,7 @@
return SPM_ERR_OK;
}
+#if !defined(TFM_PSA_API)
/**
* Set share region to which the partition needs access
*/
@@ -328,7 +331,7 @@
return res;
}
-
+#endif /* !defined(TFM_PSA_API) */
#endif /* TFM_LVL != 1 */
void tfm_spm_hal_setup_isolation_hw(void)
diff --git a/platform/include/tfm_spm_hal.h b/platform/include/tfm_spm_hal.h
index f1a82a0..3ce0b29 100644
--- a/platform/include/tfm_spm_hal.h
+++ b/platform/include/tfm_spm_hal.h
@@ -28,6 +28,7 @@
*/
struct tfm_spm_partition_platform_data_t;
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
/**
* \brief Holds SPM db fields that define the memory regions used by a
* partition.
@@ -57,6 +58,7 @@
uint32_t stack_bottom; /*!< The bottom of the stack for the partition. */
uint32_t stack_top; /*!< The top of the stack for the partition. */
};
+#endif
/**
* \brief This function initialises the HW used for isolation, and sets the
@@ -145,7 +147,7 @@
uint32_t tfm_spm_hal_get_ns_entry_point(void);
-#if TFM_LVL != 1
+#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
/**
* \brief Configure the sandbox for a partition.
*
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index d3a3214..75a0a5e 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -165,12 +165,10 @@
#partition is present.
#FIXME Remove the explicit load and the above comment once the secure client
#test partition uses the generated veneers.
- if(${COMPILER} STREQUAL "ARMCLANG")
+ if((${COMPILER} STREQUAL "ARMCLANG") AND (NOT TFM_PSA_API))
target_link_libraries(${EXE_NAME} tfm_attest tfm_secure_tests tfm_attest tfm_crypto tfm_storage tfm_audit tfm_platform $<TARGET_LINKER_FILE:tfm_secure_tests>\(*veneers.o\) tfm_attest)
- elseif(${COMPILER} STREQUAL "GNUARM")
- target_link_libraries(${EXE_NAME} tfm_attest tfm_secure_tests tfm_attest tfm_crypto tfm_storage tfm_audit tfm_platform tfm_attest)
else()
- message(FATAL_ERROR "unknown compiler" )
+ target_link_libraries(${EXE_NAME} tfm_attest tfm_secure_tests tfm_attest tfm_crypto tfm_storage tfm_audit tfm_platform tfm_attest)
endif()
else()
target_link_libraries(${EXE_NAME} tfm_attest tfm_crypto tfm_storage tfm_audit tfm_platform tfm_secure_tests tfm_attest)
diff --git a/secure_fw/core/CMakeLists.inc b/secure_fw/core/CMakeLists.inc
index 0b290d5..c9bfbb7 100644
--- a/secure_fw/core/CMakeLists.inc
+++ b/secure_fw/core/CMakeLists.inc
@@ -34,6 +34,7 @@
"${SS_CORE_DIR}/tfm_core.c"
"${SS_CORE_DIR}/tfm_handler.c"
"${SS_CORE_DIR}/tfm_secure_api.c"
+ "${SS_CORE_DIR}/tfm_func_api.c"
"${SS_CORE_DIR}/tfm_spm_services.c"
"${SS_CORE_DIR}/tfm_nspm.c"
"${SS_CORE_DIR}/tfm_boot_data.c"
diff --git a/secure_fw/core/tfm_core.c b/secure_fw/core/tfm_core.c
index 1c53071..fc060f3 100644
--- a/secure_fw/core/tfm_core.c
+++ b/secure_fw/core/tfm_core.c
@@ -48,6 +48,7 @@
#error Only TFM_LVL 1, 2 and 3 are supported!
#endif
+#ifndef TFM_PSA_API
/* Macros to pick linker symbols and allow to form the partition data base */
#define REGION(a, b, c) a##b##c
#define REGION_NAME(a, b, c) REGION(a, b, c)
@@ -55,6 +56,7 @@
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif
void configure_ns_code(void)
{
@@ -108,11 +110,20 @@
/* Enable secure peripherals interrupts */
nvic_interrupt_enable();
+#ifdef TFM_PSA_API
+ /* FixMe: In case of IPC messaging, scratch area must not be referenced
+ * These variables should be removed when all obsolete references are
+ * removed from the codebase
+ */
+ tfm_scratch_area = NULL;
+ tfm_scratch_area_size = 0;
+#else
tfm_scratch_area =
(uint8_t *)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
tfm_scratch_area_size =
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit) -
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
+#endif
return 0;
}
diff --git a/secure_fw/core/tfm_func_api.c b/secure_fw/core/tfm_func_api.c
new file mode 100644
index 0000000..aeaf5f2
--- /dev/null
+++ b/secure_fw/core/tfm_func_api.c
@@ -0,0 +1,1036 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <arm_cmse.h>
+#include "tfm_secure_api.h"
+#include "tfm_nspm.h"
+#include "secure_utilities.h"
+#include "uart_stdout.h"
+#include "secure_fw/spm/spm_api.h"
+#include "region_defs.h"
+#include "tfm_api.h"
+
+#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
+
+#ifndef TFM_LVL
+#error TFM_LVL is not defined!
+#endif
+
+/* Macros to pick linker symbols and allow references to sections */
+#define REGION(a, b, c) a##b##c
+#define REGION_NAME(a, b, c) REGION(a, b, c)
+#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
+
+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+
+#if TFM_LVL == 1
+REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
+#endif
+
+/* This is the "Big Lock" on the secure side, to guarantee single entry
+ * to SPE
+ */
+extern int32_t tfm_secure_lock;
+static int32_t tfm_secure_api_initializing = 1;
+
+static int32_t is_iovec_api_call(void)
+{
+ uint32_t current_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *curr_part_data =
+ tfm_spm_partition_get_runtime_data(current_partition_idx);
+ return curr_part_data->iovec_api;
+}
+
+static uint32_t *prepare_partition_ctx(
+ const struct tfm_exc_stack_t *svc_ctx,
+ const struct tfm_sfn_req_s *desc_ptr,
+ uint32_t *dst)
+{
+ /* XPSR = as was when called, but make sure it's thread mode */
+ *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U;
+ /* ReturnAddress = resume veneer in new context */
+ *(--dst) = svc_ctx->RetAddr;
+ /* LR = sfn address */
+ *(--dst) = (uint32_t)desc_ptr->sfn;
+ /* R12 = don't care */
+ *(--dst) = 0;
+
+ /* R0-R3 = sfn arguments */
+ int32_t i = 4;
+
+ while (i > 0) {
+ i--;
+ *(--dst) = (uint32_t)desc_ptr->args[i];
+ }
+ return dst;
+}
+
+static uint32_t *prepare_partition_iovec_ctx(
+ const struct tfm_exc_stack_t *svc_ctx,
+ const struct tfm_sfn_req_s *desc_ptr,
+ const struct iovec_args_t *iovec_args,
+ uint32_t *dst)
+{
+ /* XPSR = as was when called, but make sure it's thread mode */
+ *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U;
+ /* ReturnAddress = resume veneer in new context */
+ *(--dst) = svc_ctx->RetAddr;
+ /* LR = sfn address */
+ *(--dst) = (uint32_t)desc_ptr->sfn;
+ /* R12 = don't care */
+ *(--dst) = 0U;
+
+ /* R0-R3 = sfn arguments */
+ *(--dst) = iovec_args->out_len;
+ *(--dst) = (uint32_t)iovec_args->out_vec;
+ *(--dst) = iovec_args->in_len;
+ *(--dst) = (uint32_t)iovec_args->in_vec;
+
+ return dst;
+}
+
+static void restore_caller_ctx(
+ const struct tfm_exc_stack_t *svc_ctx,
+ struct tfm_exc_stack_t *target_ctx)
+{
+ /* ReturnAddress = resume veneer after second SVC */
+ target_ctx->RetAddr = svc_ctx->RetAddr;
+
+ /* R0 = function return value */
+ target_ctx->R0 = svc_ctx->R0;
+
+ return;
+}
+
+/** \brief Check whether the iovec parameters are valid, and the memory ranges
+ * are in the posession of the calling partition
+ *
+ * \param[in] desc_ptr The secure function request descriptor
+ *
+ * \return Return /ref TFM_SUCCESS if the iovec parameters are valid, error code
+ * otherwise as in /ref tfm_status_e
+ */
+static int32_t tfm_core_check_sfn_parameters(
+ const struct tfm_sfn_req_s *desc_ptr)
+{
+ struct psa_invec *in_vec = (psa_invec *)desc_ptr->args[0];
+ size_t in_len;
+ struct psa_outvec *out_vec = (psa_outvec *)desc_ptr->args[2];
+ size_t out_len;
+
+ uint32_t i;
+
+ if ((desc_ptr->args[1] < 0) || (desc_ptr->args[3] < 0)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ in_len = (size_t)(desc_ptr->args[1]);
+ out_len = (size_t)(desc_ptr->args[3]);
+
+ /* The number of vectors are within range. Extra checks to avoid overflow */
+ if ((in_len > PSA_MAX_IOVEC) || (out_len > PSA_MAX_IOVEC) ||
+ (in_len + out_len > PSA_MAX_IOVEC)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check whether the caller partition has at write access to the iovec
+ * structures themselves. Use the TT instruction for this.
+ */
+ if (in_len > 0) {
+ if ((in_vec == NULL) ||
+ (tfm_core_has_write_access_to_region(in_vec,
+ sizeof(psa_invec)*in_len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ if (in_vec != NULL) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+ if (out_len > 0) {
+ if ((out_vec == NULL) ||
+ (tfm_core_has_write_access_to_region(out_vec,
+ sizeof(psa_outvec)*out_len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ if (out_vec != NULL) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ /* Check whether the caller partition has access to the data inside the
+ * iovecs
+ */
+ for (i = 0; i < in_len; ++i) {
+ if (in_vec[i].len > 0) {
+ if ((in_vec[i].base == NULL) ||
+ (tfm_core_has_read_access_to_region(in_vec[i].base,
+ in_vec[i].len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+ }
+ for (i = 0; i < out_len; ++i) {
+ if (out_vec[i].len > 0) {
+ if ((out_vec[i].base == NULL) ||
+ (tfm_core_has_write_access_to_region(out_vec[i].base,
+ out_vec[i].len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ return TFM_SUCCESS;
+}
+
+static void tfm_copy_iovec_parameters(struct iovec_args_t *target,
+ const struct iovec_args_t *source)
+{
+ size_t i;
+
+ target->in_len = source->in_len;
+ for (i = 0; i < source->in_len; ++i) {
+ target->in_vec[i].base = source->in_vec[i].base;
+ target->in_vec[i].len = source->in_vec[i].len;
+ }
+ target->out_len = source->out_len;
+ for (i = 0; i < source->out_len; ++i) {
+ target->out_vec[i].base = source->out_vec[i].base;
+ target->out_vec[i].len = source->out_vec[i].len;
+ }
+}
+
+static void tfm_clear_iovec_parameters(struct iovec_args_t *args)
+{
+ int i;
+
+ args->in_len = 0;
+ for (i = 0; i < PSA_MAX_IOVEC; ++i) {
+ args->in_vec[i].base = NULL;
+ args->in_vec[i].len = 0;
+ }
+ args->out_len = 0;
+ for (i = 0; i < PSA_MAX_IOVEC; ++i) {
+ args->out_vec[i].base = NULL;
+ args->out_vec[i].len = 0;
+ }
+}
+
+static int32_t tfm_start_partition(const struct tfm_sfn_req_s *desc_ptr,
+ uint32_t excReturn)
+{
+ uint32_t caller_partition_idx = desc_ptr->caller_part_idx;
+ const struct spm_partition_runtime_data_t *curr_part_data;
+ uint32_t caller_flags;
+ register uint32_t partition_idx;
+ uint32_t psp;
+ uint32_t partition_psp, partition_psplim;
+ uint32_t partition_state;
+ uint32_t partition_flags;
+ struct tfm_exc_stack_t *svc_ctx;
+ uint32_t caller_partition_id;
+ int32_t client_id;
+ struct iovec_args_t *iovec_args;
+
+ psp = __get_PSP();
+ svc_ctx = (struct tfm_exc_stack_t *)psp;
+ caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
+
+ /* Check partition state consistency */
+ if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0)
+ != (!desc_ptr->ns_caller)) {
+ /* Partition state inconsistency detected */
+ return TFM_SECURE_LOCK_FAILED;
+ }
+
+ if ((caller_flags & SPM_PART_FLAG_APP_ROT) == 0) {
+ /* Disable NS exception handling while secure service is running.
+ * FixMe:
+ * This restriction is applied to limit the number of possible attack
+ * vectors.
+ * To be removed when pre-emption and context management issues have
+ * been analysed and resolved.
+ */
+ TFM_NS_EXC_DISABLE();
+ }
+
+ partition_idx = get_partition_idx(desc_ptr->sp_id);
+
+ curr_part_data = tfm_spm_partition_get_runtime_data(partition_idx);
+ partition_state = curr_part_data->partition_state;
+ partition_flags = tfm_spm_partition_get_flags(partition_idx);
+ caller_partition_id = tfm_spm_partition_get_partition_id(
+ caller_partition_idx);
+
+ if (tfm_secure_api_initializing) {
+#if TFM_LVL != 1
+ /* Make thread mode unprivileged while untrusted partition init is
+ * executed
+ */
+ if ((partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
+ tfm_spm_partition_change_privilege(
+ TFM_PARTITION_UNPRIVILEGED_MODE);
+ }
+#endif
+ } else if (partition_state == SPM_PARTITION_STATE_RUNNING ||
+ partition_state == SPM_PARTITION_STATE_SUSPENDED ||
+ partition_state == SPM_PARTITION_STATE_BLOCKED) {
+ /* Recursion is not permitted! */
+ return TFM_ERROR_PARTITION_NON_REENTRANT;
+ } else if (partition_state != SPM_PARTITION_STATE_IDLE) {
+ /* The partition to be called is not in a proper state */
+ return TFM_SECURE_LOCK_FAILED;
+ }
+
+#if TFM_LVL == 1
+ /* Prepare switch to shared secure partition stack */
+ /* In case the call is coming from the non-secure world, we save the iovecs
+ * on the stop of the stack. So the memory area, that can actually be used
+ * as stack by the partitions starts at a lower address
+ */
+ partition_psp =
+ (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
+ sizeof(struct iovec_args_t);
+ partition_psplim =
+ (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
+#else
+ partition_psp = curr_part_data->stack_ptr;
+ partition_psplim = tfm_spm_partition_get_stack_bottom(partition_idx);
+#endif
+ /* Store the context for the partition call */
+ tfm_spm_partition_set_caller_partition_idx(partition_idx,
+ caller_partition_idx);
+ tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn);
+
+ if ((caller_flags & SPM_PART_FLAG_APP_ROT)) {
+ tfm_spm_partition_set_caller_client_id(partition_idx,
+ caller_partition_id);
+ } else {
+ client_id = tfm_nspm_get_current_client_id();
+ if (client_id >= 0) {
+ return TFM_SECURE_LOCK_FAILED;
+ }
+ tfm_spm_partition_set_caller_client_id(partition_idx, client_id);
+ }
+
+#if (TFM_LVL != 1) && (TFM_LVL != 2)
+ /* Dynamic partitioning is only done is TFM level 3 */
+ tfm_spm_partition_sandbox_deconfig(caller_partition_idx);
+
+ /* Configure partition execution environment */
+ if (tfm_spm_partition_sandbox_config(partition_idx) != SPM_ERR_OK) {
+ ERROR_MSG("Failed to configure sandbox for partition!");
+ tfm_secure_api_error_handler();
+ }
+#endif
+
+ /* Default share to scratch area in case of partition to partition calls
+ * this way partitions always get default access to input buffers
+ */
+ /* FixMe: return value/error handling TBD */
+ tfm_spm_partition_set_share(partition_idx, desc_ptr->ns_caller ?
+ TFM_BUFFER_SHARE_NS_CODE : TFM_BUFFER_SHARE_SCRATCH);
+
+#if TFM_LVL == 1
+ /* In level one, only switch context and return from exception if in
+ * handler mode
+ */
+ if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) {
+ if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
+ /* Save the iovecs on the common stack. The vectors had been sanity
+ * checked already, and since then the interrupts have been kept
+ * disabled. So we can be sure that the vectors haven't been
+ * tampered with since the check.
+ */
+ iovec_args = (struct iovec_args_t *)
+ ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
+ sizeof(struct iovec_args_t));
+ if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) !=
+ SPM_ERR_OK) {
+ return TFM_ERROR_GENERIC;
+ }
+ tfm_copy_iovec_parameters(iovec_args,
+ &(curr_part_data->iovec_args));
+
+ /* Prepare the partition context, update stack ptr */
+ psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
+ iovec_args,
+ (uint32_t *)partition_psp);
+ } else {
+ /* Prepare the partition context, update stack ptr */
+ psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
+ (uint32_t *)partition_psp);
+ }
+ __set_PSP(psp);
+ __set_PSPLIM(partition_psplim);
+ }
+#else
+ if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
+ /* Save the iovecs on the stack of the partition. The vectors had been
+ * sanity checked already, and since then the interrupts have been kept
+ * disabled. So we can be sure that the vectors haven't been tampered
+ * with since the check.
+ */
+ iovec_args =
+ (struct iovec_args_t *)(tfm_spm_partition_get_stack_top(partition_idx) -
+ sizeof(struct iovec_args_t));
+ if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) !=
+ SPM_ERR_OK) {
+ return TFM_ERROR_GENERIC;
+ }
+ tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->iovec_args));
+
+ /* Prepare the partition context, update stack ptr */
+ psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
+ iovec_args,
+ (uint32_t *)partition_psp);
+ } else {
+ /* Prepare the partition context, update stack ptr */
+ psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
+ (uint32_t *)partition_psp);
+ }
+ __set_PSP(psp);
+ __set_PSPLIM(partition_psplim);
+#endif
+
+ tfm_spm_partition_set_state(caller_partition_idx,
+ SPM_PARTITION_STATE_BLOCKED);
+ tfm_spm_partition_set_state(partition_idx, SPM_PARTITION_STATE_RUNNING);
+ tfm_secure_lock++;
+
+ return TFM_SUCCESS;
+}
+
+static int32_t tfm_return_from_partition(uint32_t *excReturn)
+{
+ uint32_t current_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *curr_part_data, *ret_part_data;
+ uint32_t current_partition_flags;
+ uint32_t return_partition_idx;
+ uint32_t return_partition_flags;
+ uint32_t psp = __get_PSP();
+ size_t i;
+ struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
+ struct iovec_args_t *iovec_args;
+
+ if (current_partition_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_SECURE_UNLOCK_FAILED;
+ }
+
+ curr_part_data = tfm_spm_partition_get_runtime_data(current_partition_idx);
+ return_partition_idx = curr_part_data->caller_partition_idx;
+
+ if (return_partition_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_SECURE_UNLOCK_FAILED;
+ }
+
+ ret_part_data = tfm_spm_partition_get_runtime_data(return_partition_idx);
+
+ return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx);
+ current_partition_flags = tfm_spm_partition_get_flags(
+ current_partition_idx);
+
+ tfm_secure_lock--;
+
+ if ((return_partition_flags & SPM_PART_FLAG_APP_ROT) == 0) {
+ /* Re-enable NS exceptions when secure service returns to NS client.
+ * FixMe:
+ * To be removed when pre-emption and context management issues have
+ * been analysed and resolved.
+ */
+ TFM_NS_EXC_ENABLE();
+ }
+
+#if (TFM_LVL != 1) && (TFM_LVL != 2)
+ /* Deconfigure completed partition environment */
+ tfm_spm_partition_sandbox_deconfig(current_partition_idx);
+ if (tfm_secure_api_initializing) {
+ /* Restore privilege for thread mode during TF-M init. This is only
+ * have to be done if the partition is not trusted.
+ */
+ if ((current_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
+ tfm_spm_partition_change_privilege(TFM_PARTITION_PRIVILEGED_MODE);
+ }
+ } else {
+ /* Configure the caller partition environment in case this was a
+ * partition to partition call and returning to untrusted partition
+ */
+ if (tfm_spm_partition_sandbox_config(return_partition_idx)
+ != SPM_ERR_OK) {
+ ERROR_MSG("Failed to configure sandbox for partition!");
+ tfm_secure_api_error_handler();
+ }
+ if (return_partition_flags & SPM_PART_FLAG_APP_ROT) {
+ /* Restore share status */
+ tfm_spm_partition_set_share(
+ return_partition_idx,
+ tfm_spm_partition_get_runtime_data(
+ return_partition_idx)->share);
+ }
+ }
+#endif
+
+#if TFM_LVL == 1
+ if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) ||
+ (tfm_secure_api_initializing)) {
+ /* In TFM level 1 context restore is only done when
+ * returning to NS or after initialization
+ */
+ /* Restore caller context */
+ restore_caller_ctx(svc_ctx,
+ (struct tfm_exc_stack_t *)ret_part_data->stack_ptr);
+ *excReturn = ret_part_data->lr;
+ __set_PSP(ret_part_data->stack_ptr);
+ extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
+ uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
+ __set_PSPLIM(psp_stack_bottom);
+
+ /* FIXME: The condition should be removed once all the secure service
+ * calls are done via the iovec veneers
+ */
+ if (curr_part_data->iovec_api) {
+ iovec_args = (struct iovec_args_t *)
+ ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit) -
+ sizeof(struct iovec_args_t));
+
+ for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) {
+ curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len;
+ }
+ tfm_clear_iovec_parameters(iovec_args);
+ }
+ }
+#else
+ /* Restore caller context */
+ restore_caller_ctx(svc_ctx,
+ (struct tfm_exc_stack_t *)ret_part_data->stack_ptr);
+ *excReturn = ret_part_data->lr;
+ __set_PSP(ret_part_data->stack_ptr);
+ __set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx));
+ /* Clear the context entry before returning */
+ tfm_spm_partition_set_stack(
+ current_partition_idx, psp + sizeof(struct tfm_exc_stack_t));
+
+ /* FIXME: The condition should be removed once all the secure service
+ * calls are done via the iovec veneers */
+ if (curr_part_data->iovec_api) {
+ iovec_args = (struct iovec_args_t *)
+ (tfm_spm_partition_get_stack_top(current_partition_idx) -
+ sizeof(struct iovec_args_t));
+
+ for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) {
+ curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len;
+ }
+ tfm_clear_iovec_parameters(iovec_args);
+ }
+#endif
+
+ tfm_spm_partition_cleanup_context(current_partition_idx);
+
+ tfm_spm_partition_set_state(current_partition_idx,
+ SPM_PARTITION_STATE_IDLE);
+ tfm_spm_partition_set_state(return_partition_idx,
+ SPM_PARTITION_STATE_RUNNING);
+
+ return TFM_SUCCESS;
+}
+
+static int32_t tfm_check_sfn_req_integrity(const struct tfm_sfn_req_s *desc_ptr)
+{
+ if ((desc_ptr == NULL) ||
+ (desc_ptr->sp_id == 0) ||
+ (desc_ptr->sfn == NULL)) {
+ /* invalid parameter */
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ return TFM_SUCCESS;
+}
+
+static int32_t tfm_core_check_sfn_req_rules(
+ const struct tfm_sfn_req_s *desc_ptr)
+{
+ /* Check partition idx validity */
+ if (desc_ptr->caller_part_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_ERROR_NO_ACTIVE_PARTITION;
+ }
+
+ if ((desc_ptr->ns_caller) && (tfm_secure_lock != 0)) {
+ /* Secure domain is already locked!
+ * This should only happen if caller is secure partition!
+ * FixMe: This scenario is a potential security breach
+ * Take appropriate action!
+ */
+ return TFM_ERROR_SECURE_DOMAIN_LOCKED;
+ }
+
+ if (tfm_secure_api_initializing) {
+ int32_t id =
+ tfm_spm_partition_get_partition_id(desc_ptr->caller_part_idx);
+
+ if ((id != TFM_SP_CORE_ID) || (tfm_secure_lock != 0)) {
+ /* Invalid request during system initialization */
+ ERROR_MSG("Invalid service request during initialization!");
+ return TFM_ERROR_NOT_INITIALIZED;
+ }
+ }
+
+ return TFM_SUCCESS;
+}
+
+void tfm_secure_api_init_done(void)
+{
+ tfm_secure_api_initializing = 0;
+#if TFM_LVL != 1
+ if (tfm_spm_partition_sandbox_config(TFM_SP_NON_SECURE_ID) != SPM_ERR_OK) {
+ ERROR_MSG("Failed to configure sandbox for partition!");
+ tfm_secure_api_error_handler();
+ }
+#endif
+}
+
+int32_t tfm_core_sfn_request_handler(
+ struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn)
+{
+ int32_t res;
+
+ res = tfm_check_sfn_req_integrity(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ ERROR_MSG("Invalid service request!");
+ tfm_secure_api_error_handler();
+ }
+
+ __disable_irq();
+
+ desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx();
+
+ if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
+ res = tfm_core_check_sfn_parameters(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ /* The sanity check of iovecs failed. */
+ __enable_irq();
+ tfm_secure_api_error_handler();
+ }
+ }
+
+ res = tfm_core_check_sfn_req_rules(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ /* FixMe: error compartmentalization TBD */
+ tfm_spm_partition_set_state(
+ desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED);
+ __enable_irq();
+ ERROR_MSG("Unauthorized service request!");
+ tfm_secure_api_error_handler();
+ }
+
+ res = tfm_start_partition(desc_ptr, excReturn);
+ if (res != TFM_SUCCESS) {
+ /* FixMe: consider possible fault scenarios */
+ __enable_irq();
+ ERROR_MSG("Failed to process service request!");
+ tfm_secure_api_error_handler();
+ }
+
+ __enable_irq();
+
+ return res;
+}
+
+#if TFM_LVL == 1
+int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr)
+{
+ int32_t res;
+ int32_t *args;
+ int32_t retVal;
+
+ if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
+ res = tfm_core_check_sfn_parameters(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ /* The sanity check of iovecs failed. */
+ return res;
+ }
+ }
+
+ /* No excReturn value is needed as no exception handling is used */
+ res = tfm_core_sfn_request_handler(desc_ptr, 0);
+
+ if (res != TFM_SUCCESS) {
+ tfm_secure_api_error_handler();
+ }
+
+ /* Secure partition to secure partition call in TFM level 1 */
+ args = desc_ptr->args;
+ retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]);
+
+ /* return handler should restore original exc_return value... */
+ res = tfm_return_from_partition(NULL);
+ if (res == TFM_SUCCESS) {
+ /* If unlock successful, pass SS return value to caller */
+ res = retVal;
+ } else {
+ /* Unlock errors indicate ctx database corruption or unknown
+ * anomalies. Halt execution
+ */
+ ERROR_MSG("Secure API error during unlock!");
+ tfm_secure_api_error_handler();
+ }
+ return res;
+}
+#endif
+
+void tfm_core_validate_secure_caller_handler(uint32_t *svc_args)
+{
+
+ int32_t res = TFM_ERROR_GENERIC;
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *curr_part_data =
+ tfm_spm_partition_get_runtime_data(running_partition_idx);
+ uint32_t running_partition_flags =
+ tfm_spm_partition_get_flags(running_partition_idx);
+ uint32_t caller_partition_flags =
+ tfm_spm_partition_get_flags(curr_part_data->caller_partition_idx);
+
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
+ /* This handler shouldn't be called from outside partition context.
+ * Partitions are only allowed to run while S domain is locked.
+ */
+ svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* Store return value in r0 */
+ if (caller_partition_flags & SPM_PART_FLAG_APP_ROT) {
+ res = TFM_SUCCESS;
+ }
+ svc_args[0] = res;
+}
+
+int32_t tfm_core_check_buffer_access(uint32_t partition_idx,
+ void *start_addr,
+ size_t len,
+ uint32_t alignment)
+{
+ uintptr_t start_addr_value = (uintptr_t)start_addr;
+ uintptr_t end_addr_value = (uintptr_t)start_addr + len;
+ uintptr_t alignment_mask;
+
+ alignment_mask = (((uintptr_t)1) << alignment) - 1;
+
+ /* Check that the pointer is aligned properly */
+ if (start_addr_value & alignment_mask) {
+ /* not aligned, return error */
+ return 0;
+ }
+
+ /* Protect against overflow (and zero len) */
+ if (end_addr_value <= start_addr_value) {
+ return 0;
+ }
+
+#if TFM_LVL == 1
+ /* For privileged partition execution, all secure data memory and stack
+ * is accessible
+ */
+ if (start_addr_value >= S_DATA_START &&
+ end_addr_value <= (S_DATA_START + S_DATA_SIZE)) {
+ return 1;
+ }
+#else
+ /* For non-privileged execution the partition's data and stack is
+ * accessible
+ */
+ if (start_addr_value >=
+ tfm_spm_partition_get_stack_bottom(partition_idx) &&
+ end_addr_value <=
+ tfm_spm_partition_get_stack_top(partition_idx)) {
+ return 1;
+ }
+ if (start_addr_value >=
+ tfm_spm_partition_get_rw_start(partition_idx) &&
+ end_addr_value <=
+ tfm_spm_partition_get_rw_limit(partition_idx)) {
+ return 1;
+ }
+ if (start_addr_value >=
+ tfm_spm_partition_get_zi_start(partition_idx) &&
+ end_addr_value <=
+ tfm_spm_partition_get_zi_limit(partition_idx)) {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+void tfm_core_get_caller_client_id_handler(uint32_t *svc_args)
+{
+ uintptr_t result_ptr_value = svc_args[0];
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const uint32_t running_partition_flags =
+ tfm_spm_partition_get_flags(running_partition_idx);
+ const struct spm_partition_runtime_data_t *curr_part_data =
+ tfm_spm_partition_get_runtime_data(running_partition_idx);
+ int res = 0;
+
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
+ /* This handler shouldn't be called from outside partition context.
+ * Partitions are only allowed to run while S domain is locked.
+ */
+ svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* Make sure that the output pointer points to a memory area that is owned
+ * by the partition
+ */
+ res = tfm_core_check_buffer_access(running_partition_idx,
+ (void *)result_ptr_value,
+ sizeof(curr_part_data->caller_client_id),
+ 2);
+ if (!res) {
+ /* Not in accessible range, return error */
+ svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ *((int32_t *)result_ptr_value) = curr_part_data->caller_client_id;
+
+ /* Store return value in r0 */
+ svc_args[0] = TFM_SUCCESS;
+}
+
+void tfm_core_memory_permission_check_handler(uint32_t *svc_args)
+{
+ uint32_t ptr = svc_args[0];
+ uint32_t size = svc_args[1];
+ int32_t access = svc_args[2];
+
+ uint32_t max_buf_size, ptr_start, range_limit, range_check = false;
+ int32_t res;
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *curr_part_data =
+ tfm_spm_partition_get_runtime_data(running_partition_idx);
+ uint32_t running_partition_flags =
+ tfm_spm_partition_get_flags(running_partition_idx);
+ int32_t flags = 0;
+ void *rangeptr;
+
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) || (size == 0)) {
+ /* This handler should only be called from a secure partition. */
+ svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ if (curr_part_data->share != TFM_BUFFER_SHARE_PRIV) {
+ flags |= CMSE_MPU_UNPRIV;
+ }
+
+ if (access == TFM_MEMORY_ACCESS_RW) {
+ flags |= CMSE_MPU_READWRITE;
+ } else {
+ flags |= CMSE_MPU_READ;
+ }
+
+ /* Check if partition access to address would fail */
+ rangeptr = cmse_check_address_range((void *)ptr, size, flags);
+
+ /* Get regions associated with address */
+ cmse_address_info_t addr_info = cmse_TT((void *)ptr);
+
+ if (rangeptr == NULL) {
+ svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ if (addr_info.flags.secure) {
+#if TFM_LVL == 1
+ /* For privileged partition execution, all secure data memory is
+ * accessible
+ */
+ max_buf_size = S_DATA_SIZE;
+ ptr_start = S_DATA_START;
+ range_limit = S_DATA_LIMIT;
+#else
+ /* Only scratch is permitted in secure memory */
+ max_buf_size = (uint32_t)tfm_scratch_area_size;
+ ptr_start = (uint32_t)tfm_scratch_area;
+ range_limit = (uint32_t)tfm_scratch_area + tfm_scratch_area_size - 1;
+#endif
+ range_check = true;
+ } else {
+ if (!addr_info.flags.sau_region_valid) {
+ /* If address is NS, TF-M expects SAU to be configured
+ */
+ svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+ switch (addr_info.flags.sau_region) {
+ case TFM_NS_REGION_CODE:
+ if (access == TFM_MEMORY_ACCESS_RW) {
+ res = TFM_ERROR_INVALID_PARAMETER;
+ } else {
+ /* Currently TF-M does not support checks for NS Memory
+ * accesses by partitions
+ */
+ res = TFM_SUCCESS;
+ }
+ break;
+ case TFM_NS_REGION_DATA:
+ /* Currently TF-M does not support checks for NS Memory
+ * accesses by partitions
+ */
+ res = TFM_SUCCESS;
+ break;
+ default:
+ /* Only NS data and code regions can be accessed as buffers */
+ res = TFM_ERROR_INVALID_PARAMETER;
+ break;
+ }
+ }
+
+ if (range_check == true) {
+ if ((size <= max_buf_size) && (ptr >= ptr_start)
+ && (ptr <= range_limit + 1 - size)) {
+ res = TFM_SUCCESS;
+ } else {
+ res = TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ /* Store return value in r0 */
+ svc_args[0] = res;
+}
+
+/* This SVC handler is called if veneer is running in thread mode */
+uint32_t tfm_core_partition_request_svc_handler(
+ const struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn)
+{
+ struct tfm_sfn_req_s *desc_ptr;
+
+ if (!(excReturn & EXC_RETURN_STACK_PROCESS)) {
+ /* Service request SVC called with MSP active.
+ * Either invalid configuration for Thread mode or SVC called
+ * from Handler mode, which is not supported.
+ * FixMe: error severity TBD
+ */
+ ERROR_MSG("Service request SVC called with MSP active!");
+ tfm_secure_api_error_handler();
+ }
+
+ desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0;
+
+ if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) {
+ tfm_secure_api_error_handler();
+ }
+
+ return EXC_RETURN_SECURE_FUNCTION;
+}
+
+/* This SVC handler is called when sfn returns */
+uint32_t tfm_core_partition_return_handler(uint32_t lr)
+{
+ int32_t res;
+
+ if (!(lr & EXC_RETURN_STACK_PROCESS)) {
+ /* Partition return SVC called with MSP active.
+ * This should not happen!
+ */
+ ERROR_MSG("Partition return SVC called with MSP active!");
+ tfm_secure_api_error_handler();
+ }
+
+ /* Store return value from secure partition */
+ int32_t retVal = *(int32_t *)__get_PSP();
+
+ if (!is_iovec_api_call()) {
+ if ((retVal > TFM_SUCCESS) &&
+ (retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) {
+ /* Secure function returned a reserved value */
+#ifdef TFM_CORE_DEBUG
+ LOG_MSG("Invalid return value from secure partition!");
+#endif
+ /* FixMe: error can be traced to specific secure partition
+ * and Core is not compromised. Error handling flow can be
+ * refined
+ */
+ tfm_secure_api_error_handler();
+ }
+ }
+
+ res = tfm_return_from_partition(&lr);
+ if (res != TFM_SUCCESS) {
+ /* Unlock errors indicate ctx database corruption or unknown anomalies
+ * Halt execution
+ */
+ ERROR_MSG("Secure API error during unlock!");
+ tfm_secure_api_error_handler();
+ }
+
+ return lr;
+}
+
+void tfm_core_set_buffer_area_handler(uint32_t *args)
+{
+ /* r0 is stored in args[0] in exception stack frame
+ * Store input parameter before writing return value to that address
+ */
+ enum tfm_buffer_share_region_e share;
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *curr_part_data =
+ tfm_spm_partition_get_runtime_data(running_partition_idx);
+ uint32_t caller_partition_idx = curr_part_data->caller_partition_idx;
+ uint32_t running_partition_flags =
+ tfm_spm_partition_get_flags(running_partition_idx);
+ uint32_t caller_partition_flags =
+ tfm_spm_partition_get_flags(caller_partition_idx);
+
+ /* tfm_core_set_buffer_area() returns int32_t */
+ int32_t *res_ptr = (int32_t *)&args[0];
+
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
+ /* This handler should only be called from a secure partition. */
+ *res_ptr = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ switch (args[0]) {
+ case TFM_BUFFER_SHARE_DEFAULT:
+ share = (!(caller_partition_flags & SPM_PART_FLAG_APP_ROT)) ?
+ (TFM_BUFFER_SHARE_NS_CODE) : (TFM_BUFFER_SHARE_SCRATCH);
+ break;
+ case TFM_BUFFER_SHARE_SCRATCH:
+ case TFM_BUFFER_SHARE_NS_CODE:
+ share = args[0];
+ break;
+ default:
+ *res_ptr = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ if (tfm_spm_partition_set_share(running_partition_idx, share) ==
+ SPM_ERR_OK) {
+ *res_ptr = TFM_SUCCESS;
+ } else {
+ *res_ptr = TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ return;
+}
+
diff --git a/secure_fw/core/tfm_handler.c b/secure_fw/core/tfm_handler.c
index d600ddc..10a91a56 100644
--- a/secure_fw/core/tfm_handler.c
+++ b/secure_fw/core/tfm_handler.c
@@ -156,6 +156,30 @@
return lr;
}
switch (svc_number) {
+#ifdef TFM_PSA_API
+ case TFM_SVC_IPC_REQUEST:
+ tfm_psa_ipc_request_handler(svc_args);
+ break;
+ case TFM_SVC_SCHEDULE:
+ case TFM_SVC_EXIT_THRD:
+ case TFM_SVC_PSA_FRAMEWORK_VERSION:
+ case TFM_SVC_PSA_VERSION:
+ case TFM_SVC_PSA_CONNECT:
+ case TFM_SVC_PSA_CALL:
+ case TFM_SVC_PSA_CLOSE:
+ case TFM_SVC_PSA_WAIT:
+ case TFM_SVC_PSA_GET:
+ case TFM_SVC_PSA_SET_RHANDLE:
+ case TFM_SVC_PSA_READ:
+ case TFM_SVC_PSA_SKIP:
+ case TFM_SVC_PSA_WRITE:
+ case TFM_SVC_PSA_REPLY:
+ case TFM_SVC_PSA_NOTIFY:
+ case TFM_SVC_PSA_CLEAR:
+ case TFM_SVC_PSA_EOI:
+ svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, lr);
+ break;
+#else
case TFM_SVC_SFN_REQUEST:
lr = tfm_core_partition_request_svc_handler(svc_args, lr);
break;
@@ -177,10 +201,6 @@
case TFM_SVC_SET_SHARE_AREA:
tfm_core_set_buffer_area_handler(svc_args);
break;
-#ifdef TFM_PSA_API
- case TFM_SVC_IPC_REQUEST:
- tfm_psa_ipc_request_handler(svc_args);
- break;
#endif
case TFM_SVC_PRINT:
printf("\e[1;34m[Sec Thread] %s\e[0m\r\n", (char *)svc_args[0]);
@@ -188,27 +208,6 @@
case TFM_SVC_GET_BOOT_DATA:
tfm_core_get_boot_data_handler(svc_args);
break;
-#ifdef TFM_PSA_API
- case TFM_SVC_SCHEDULE:
- case TFM_SVC_EXIT_THRD:
- case TFM_SVC_PSA_FRAMEWORK_VERSION:
- case TFM_SVC_PSA_VERSION:
- case TFM_SVC_PSA_CONNECT:
- case TFM_SVC_PSA_CALL:
- case TFM_SVC_PSA_CLOSE:
- case TFM_SVC_PSA_WAIT:
- case TFM_SVC_PSA_GET:
- case TFM_SVC_PSA_SET_RHANDLE:
- case TFM_SVC_PSA_READ:
- case TFM_SVC_PSA_SKIP:
- case TFM_SVC_PSA_WRITE:
- case TFM_SVC_PSA_REPLY:
- case TFM_SVC_PSA_NOTIFY:
- case TFM_SVC_PSA_CLEAR:
- case TFM_SVC_PSA_EOI:
- svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, lr);
- break;
-#endif
default:
LOG_MSG("Unknown SVC number requested!");
break;
diff --git a/secure_fw/core/tfm_secure_api.c b/secure_fw/core/tfm_secure_api.c
index cf65c44..ca0e51c 100644
--- a/secure_fw/core/tfm_secure_api.c
+++ b/secure_fw/core/tfm_secure_api.c
@@ -28,89 +28,15 @@
#define REGION_NAME(a, b, c) REGION(a, b, c)
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
+#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
-
-#if TFM_LVL == 1
-REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
-REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
-#endif
+#endif /* !defined(TFM_PSA_API) */
/* This is the "Big Lock" on the secure side, to guarantee single entry
* to SPE
*/
int32_t tfm_secure_lock;
-static int32_t tfm_secure_api_initializing = 1;
-
-static int32_t is_iovec_api_call(void)
-{
- uint32_t current_partition_idx =
- tfm_spm_partition_get_running_partition_idx();
- const struct spm_partition_runtime_data_t *curr_part_data =
- tfm_spm_partition_get_runtime_data(current_partition_idx);
- return curr_part_data->iovec_api;
-}
-
-static uint32_t *prepare_partition_ctx(
- const struct tfm_exc_stack_t *svc_ctx,
- const struct tfm_sfn_req_s *desc_ptr,
- uint32_t *dst)
-{
- /* XPSR = as was when called, but make sure it's thread mode */
- *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U;
- /* ReturnAddress = resume veneer in new context */
- *(--dst) = svc_ctx->RetAddr;
- /* LR = sfn address */
- *(--dst) = (uint32_t)desc_ptr->sfn;
- /* R12 = don't care */
- *(--dst) = 0;
-
- /* R0-R3 = sfn arguments */
- int32_t i = 4;
-
- while (i > 0) {
- i--;
- *(--dst) = (uint32_t)desc_ptr->args[i];
- }
- return dst;
-}
-
-static uint32_t *prepare_partition_iovec_ctx(
- const struct tfm_exc_stack_t *svc_ctx,
- const struct tfm_sfn_req_s *desc_ptr,
- const struct iovec_args_t *iovec_args,
- uint32_t *dst)
-{
- /* XPSR = as was when called, but make sure it's thread mode */
- *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U;
- /* ReturnAddress = resume veneer in new context */
- *(--dst) = svc_ctx->RetAddr;
- /* LR = sfn address */
- *(--dst) = (uint32_t)desc_ptr->sfn;
- /* R12 = don't care */
- *(--dst) = 0U;
-
- /* R0-R3 = sfn arguments */
- *(--dst) = iovec_args->out_len;
- *(--dst) = (uint32_t)iovec_args->out_vec;
- *(--dst) = iovec_args->in_len;
- *(--dst) = (uint32_t)iovec_args->in_vec;
-
- return dst;
-}
-
-static void restore_caller_ctx(
- const struct tfm_exc_stack_t *svc_ctx,
- struct tfm_exc_stack_t *target_ctx)
-{
- /* ReturnAddress = resume veneer after second SVC */
- target_ctx->RetAddr = svc_ctx->RetAddr;
-
- /* R0 = function return value */
- target_ctx->R0 = svc_ctx->R0;
-
- return;
-}
/**
* \brief Check whether a memory range is inside a memory region.
@@ -167,10 +93,12 @@
{
int32_t range_access_allowed_by_mpu;
+#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
uint32_t scratch_base =
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
uint32_t scratch_limit =
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif /* !defined(TFM_PSA_API) */
/* Use the TT instruction to check access to the partition's regions*/
range_access_allowed_by_mpu =
@@ -180,6 +108,7 @@
return TFM_SUCCESS;
}
+#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
/* If the check for the current MPU settings fails, check for the share
* region, only if the partition is secure
*/
@@ -189,6 +118,7 @@
return TFM_SUCCESS;
}
}
+#endif /* !defined(TFM_PSA_API) */
/* If all else fails, check whether the region is in the non-secure
* memory
@@ -237,442 +167,6 @@
return has_access_to_region(p, s, flags);
}
-/** \brief Check whether the iovec parameters are valid, and the memory ranges
- * are in the posession of the calling partition
- *
- * \param[in] desc_ptr The secure function request descriptor
- *
- * \return Return /ref TFM_SUCCESS if the iovec parameters are valid, error code
- * otherwise as in /ref tfm_status_e
- */
-static int32_t tfm_core_check_sfn_parameters(
- const struct tfm_sfn_req_s *desc_ptr)
-{
- struct psa_invec *in_vec = (psa_invec *)desc_ptr->args[0];
- size_t in_len;
- struct psa_outvec *out_vec = (psa_outvec *)desc_ptr->args[2];
- size_t out_len;
-
- uint32_t i;
-
- if ((desc_ptr->args[1] < 0) || (desc_ptr->args[3] < 0)) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
-
- in_len = (size_t)(desc_ptr->args[1]);
- out_len = (size_t)(desc_ptr->args[3]);
-
- /* The number of vectors are within range. Extra checks to avoid overflow */
- if ((in_len > PSA_MAX_IOVEC) || (out_len > PSA_MAX_IOVEC) ||
- (in_len + out_len > PSA_MAX_IOVEC)) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
-
- /* Check whether the caller partition has at write access to the iovec
- * structures themselves. Use the TT instruction for this.
- */
- if (in_len > 0) {
- if ((in_vec == NULL) ||
- (tfm_core_has_write_access_to_region(in_vec,
- sizeof(psa_invec)*in_len, desc_ptr->ns_caller,
- TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
- } else {
- if (in_vec != NULL) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
- }
- if (out_len > 0) {
- if ((out_vec == NULL) ||
- (tfm_core_has_write_access_to_region(out_vec,
- sizeof(psa_outvec)*out_len, desc_ptr->ns_caller,
- TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
- } else {
- if (out_vec != NULL) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
- }
-
- /* Check whether the caller partition has access to the data inside the
- * iovecs
- */
- for (i = 0; i < in_len; ++i) {
- if (in_vec[i].len > 0) {
- if ((in_vec[i].base == NULL) ||
- (tfm_core_has_read_access_to_region(in_vec[i].base,
- in_vec[i].len, desc_ptr->ns_caller,
- TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
- }
- }
- for (i = 0; i < out_len; ++i) {
- if (out_vec[i].len > 0) {
- if ((out_vec[i].base == NULL) ||
- (tfm_core_has_write_access_to_region(out_vec[i].base,
- out_vec[i].len, desc_ptr->ns_caller,
- TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
- return TFM_ERROR_INVALID_PARAMETER;
- }
- }
- }
-
- return TFM_SUCCESS;
-}
-
-static void tfm_copy_iovec_parameters(struct iovec_args_t *target,
- const struct iovec_args_t *source)
-{
- size_t i;
-
- target->in_len = source->in_len;
- for (i = 0; i < source->in_len; ++i) {
- target->in_vec[i].base = source->in_vec[i].base;
- target->in_vec[i].len = source->in_vec[i].len;
- }
- target->out_len = source->out_len;
- for (i = 0; i < source->out_len; ++i) {
- target->out_vec[i].base = source->out_vec[i].base;
- target->out_vec[i].len = source->out_vec[i].len;
- }
-}
-
-static void tfm_clear_iovec_parameters(struct iovec_args_t *args)
-{
- int i;
-
- args->in_len = 0;
- for (i = 0; i < PSA_MAX_IOVEC; ++i) {
- args->in_vec[i].base = NULL;
- args->in_vec[i].len = 0;
- }
- args->out_len = 0;
- for (i = 0; i < PSA_MAX_IOVEC; ++i) {
- args->out_vec[i].base = NULL;
- args->out_vec[i].len = 0;
- }
-}
-
-static int32_t tfm_start_partition(const struct tfm_sfn_req_s *desc_ptr,
- uint32_t excReturn)
-{
- uint32_t caller_partition_idx = desc_ptr->caller_part_idx;
- const struct spm_partition_runtime_data_t *curr_part_data;
- uint32_t caller_flags;
- register uint32_t partition_idx;
- uint32_t psp = __get_PSP();
- uint32_t partition_psp, partition_psplim;
- uint32_t partition_state;
- uint32_t partition_flags;
- struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
- uint32_t caller_partition_id;
- int32_t client_id;
- struct iovec_args_t *iovec_args;
-
- caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
-
- /* Check partition state consistency */
- if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0)
- != (!desc_ptr->ns_caller)) {
- /* Partition state inconsistency detected */
- return TFM_SECURE_LOCK_FAILED;
- }
-
- if((caller_flags & SPM_PART_FLAG_APP_ROT) == 0) {
- /* Disable NS exception handling while secure service is running.
- * FixMe:
- * This restriction is applied to limit the number of possible attack
- * vectors.
- * To be removed when pre-emption and context management issues have
- * been analysed and resolved.
- */
- TFM_NS_EXC_DISABLE();
- }
-
- partition_idx = get_partition_idx(desc_ptr->sp_id);
-
- curr_part_data = tfm_spm_partition_get_runtime_data(partition_idx);
- partition_state = curr_part_data->partition_state;
- partition_flags = tfm_spm_partition_get_flags(partition_idx);
- caller_partition_id = tfm_spm_partition_get_partition_id(
- caller_partition_idx);
-
- if (tfm_secure_api_initializing) {
-#if TFM_LVL != 1
- /* Make thread mode unprivileged while untrusted partition init is
- * executed
- */
- if ((partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
- tfm_spm_partition_change_privilege(
- TFM_PARTITION_UNPRIVILEGED_MODE);
- }
-#endif
- } else if (partition_state == SPM_PARTITION_STATE_RUNNING ||
- partition_state == SPM_PARTITION_STATE_SUSPENDED ||
- partition_state == SPM_PARTITION_STATE_BLOCKED) {
- /* Recursion is not permitted! */
- return TFM_ERROR_PARTITION_NON_REENTRANT;
- } else if (partition_state != SPM_PARTITION_STATE_IDLE) {
- /* The partition to be called is not in a proper state */
- return TFM_SECURE_LOCK_FAILED;
- }
-
-#if TFM_LVL == 1
- /* Prepare switch to shared secure partition stack */
- /* In case the call is coming from the non-secure world, we save the iovecs
- * on the stop of the stack. So the memory area, that can actually be used
- * as stack by the partitions starts at a lower address
- */
- partition_psp =
- (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
- sizeof(struct iovec_args_t);
- partition_psplim =
- (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
-#else
- partition_psp = curr_part_data->stack_ptr;
- partition_psplim = tfm_spm_partition_get_stack_bottom(partition_idx);
-#endif
- /* Store the context for the partition call */
- tfm_spm_partition_set_caller_partition_idx(partition_idx,
- caller_partition_idx);
- tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn);
-
- if ((caller_flags & SPM_PART_FLAG_APP_ROT)) {
- tfm_spm_partition_set_caller_client_id(partition_idx,
- caller_partition_id);
- } else {
- client_id = tfm_nspm_get_current_client_id();
- if (client_id >= 0)
- {
- return TFM_SECURE_LOCK_FAILED;
- }
- tfm_spm_partition_set_caller_client_id(partition_idx, client_id);
- }
-
-#if (TFM_LVL != 1) && (TFM_LVL != 2)
- /* Dynamic partitioning is only done is TFM level 3 */
- tfm_spm_partition_sandbox_deconfig(caller_partition_idx);
-
- /* Configure partition execution environment */
- if (tfm_spm_partition_sandbox_config(partition_idx) != SPM_ERR_OK) {
- ERROR_MSG("Failed to configure sandbox for partition!");
- tfm_secure_api_error_handler();
- }
-#endif
-
- /* Default share to scratch area in case of partition to partition calls
- * this way partitions always get default access to input buffers
- */
- /* FixMe: return value/error handling TBD */
- tfm_spm_partition_set_share(partition_idx, desc_ptr->ns_caller ?
- TFM_BUFFER_SHARE_NS_CODE : TFM_BUFFER_SHARE_SCRATCH);
-
-#if TFM_LVL == 1
- /* In level one, only switch context and return from exception if in
- * handler mode
- */
- if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) {
- if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
- /* Save the iovecs on the common stack. The vectors had been sanity
- * checked already, and since then the interrupts have been kept
- * disabled. So we can be sure that the vectors haven't been
- * tampered with since the check.
- */
- iovec_args = (struct iovec_args_t *)
- ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
- sizeof(struct iovec_args_t));
- if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) !=
- SPM_ERR_OK) {
- return TFM_ERROR_GENERIC;
- }
- tfm_copy_iovec_parameters(iovec_args,
- &(curr_part_data->iovec_args));
-
- /* Prepare the partition context, update stack ptr */
- psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
- iovec_args,
- (uint32_t *)partition_psp);
- } else {
- /* Prepare the partition context, update stack ptr */
- psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
- (uint32_t *)partition_psp);
- }
- __set_PSP(psp);
- __set_PSPLIM(partition_psplim);
- }
-#else
- if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
- /* Save the iovecs on the stack of the partition. The vectors had been
- * sanity checked already, and since then the interrupts have been kept
- * disabled. So we can be sure that the vectors haven't been tampered
- * with since the check.
- */
- iovec_args =
- (struct iovec_args_t *)(tfm_spm_partition_get_stack_top(partition_idx) -
- sizeof(struct iovec_args_t));
- if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) !=
- SPM_ERR_OK) {
- return TFM_ERROR_GENERIC;
- }
- tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->iovec_args));
-
- /* Prepare the partition context, update stack ptr */
- psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
- iovec_args,
- (uint32_t *)partition_psp);
- } else {
- /* Prepare the partition context, update stack ptr */
- psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
- (uint32_t *)partition_psp);
- }
- __set_PSP(psp);
- __set_PSPLIM(partition_psplim);
-#endif
-
- tfm_spm_partition_set_state(caller_partition_idx,
- SPM_PARTITION_STATE_BLOCKED);
- tfm_spm_partition_set_state(partition_idx, SPM_PARTITION_STATE_RUNNING);
- tfm_secure_lock++;
-
- return TFM_SUCCESS;
-}
-
-static int32_t tfm_return_from_partition(uint32_t *excReturn)
-{
- uint32_t current_partition_idx =
- tfm_spm_partition_get_running_partition_idx();
- const struct spm_partition_runtime_data_t *curr_part_data, *ret_part_data;
- uint32_t current_partition_flags;
- uint32_t return_partition_idx;
- uint32_t return_partition_flags;
- uint32_t psp = __get_PSP();
- size_t i;
- struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
- struct iovec_args_t *iovec_args;
-
- if (current_partition_idx == SPM_INVALID_PARTITION_IDX) {
- return TFM_SECURE_UNLOCK_FAILED;
- }
-
- curr_part_data = tfm_spm_partition_get_runtime_data(current_partition_idx);
- return_partition_idx = curr_part_data->caller_partition_idx;
-
- if (return_partition_idx == SPM_INVALID_PARTITION_IDX) {
- return TFM_SECURE_UNLOCK_FAILED;
- }
-
- ret_part_data = tfm_spm_partition_get_runtime_data(return_partition_idx);
-
- return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx);
- current_partition_flags = tfm_spm_partition_get_flags(
- current_partition_idx);
-
- tfm_secure_lock--;
-
- if((return_partition_flags & SPM_PART_FLAG_APP_ROT) == 0) {
- /* Re-enable NS exceptions when secure service returns to NS client.
- * FixMe:
- * To be removed when pre-emption and context management issues have
- * been analysed and resolved.
- */
- TFM_NS_EXC_ENABLE();
- }
-
-#if (TFM_LVL != 1) && (TFM_LVL != 2)
- /* Deconfigure completed partition environment */
- tfm_spm_partition_sandbox_deconfig(current_partition_idx);
- if (tfm_secure_api_initializing) {
- /* Restore privilege for thread mode during TF-M init. This is only
- * have to be done if the partition is not trusted.
- */
- if ((current_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
- tfm_spm_partition_change_privilege(TFM_PARTITION_PRIVILEGED_MODE);
- }
- } else {
- /* Configure the caller partition environment in case this was a
- * partition to partition call and returning to untrusted partition
- */
- if (tfm_spm_partition_sandbox_config(return_partition_idx)
- != SPM_ERR_OK) {
- ERROR_MSG("Failed to configure sandbox for partition!");
- tfm_secure_api_error_handler();
- }
- if (return_partition_flags & SPM_PART_FLAG_APP_ROT) {
- /* Restore share status */
- tfm_spm_partition_set_share(
- return_partition_idx,
- tfm_spm_partition_get_runtime_data(
- return_partition_idx)->share);
- }
- }
-#endif
-
-#if TFM_LVL == 1
- if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) ||
- (tfm_secure_api_initializing)) {
- /* In TFM level 1 context restore is only done when
- * returning to NS or after initialization
- */
- /* Restore caller context */
- restore_caller_ctx(svc_ctx,
- (struct tfm_exc_stack_t *)ret_part_data->stack_ptr);
- *excReturn = ret_part_data->lr;
- __set_PSP(ret_part_data->stack_ptr);
- extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
- uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
- __set_PSPLIM(psp_stack_bottom);
-
- /* FIXME: The condition should be removed once all the secure service
- * calls are done via the iovec veneers */
- if (curr_part_data->iovec_api) {
- iovec_args = (struct iovec_args_t *)
- ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
- sizeof(struct iovec_args_t));
-
- for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) {
- curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len;
- }
- tfm_clear_iovec_parameters(iovec_args);
- }
- }
-#else
- /* Restore caller context */
- restore_caller_ctx(svc_ctx,
- (struct tfm_exc_stack_t *)ret_part_data->stack_ptr);
- *excReturn = ret_part_data->lr;
- __set_PSP(ret_part_data->stack_ptr);
- __set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx));
- /* Clear the context entry before returning */
- tfm_spm_partition_set_stack(
- current_partition_idx, psp + sizeof(struct tfm_exc_stack_t));
-
- /* FIXME: The condition should be removed once all the secure service
- * calls are done via the iovec veneers */
- if (curr_part_data->iovec_api) {
- iovec_args = (struct iovec_args_t *)
- (tfm_spm_partition_get_stack_top(current_partition_idx) -
- sizeof(struct iovec_args_t));
-
- for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) {
- curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len;
- }
- tfm_clear_iovec_parameters(iovec_args);
- }
-#endif
-
- tfm_spm_partition_cleanup_context(current_partition_idx);
-
- tfm_spm_partition_set_state(current_partition_idx,
- SPM_PARTITION_STATE_IDLE);
- tfm_spm_partition_set_state(return_partition_idx,
- SPM_PARTITION_STATE_RUNNING);
-
- return TFM_SUCCESS;
-}
-
void tfm_secure_api_error_handler(void)
{
ERROR_MSG("Security violation when calling secure API");
@@ -681,487 +175,3 @@
}
}
-static int32_t tfm_check_sfn_req_integrity(const struct tfm_sfn_req_s *desc_ptr)
-{
- if ((desc_ptr == NULL) ||
- (desc_ptr->sp_id == 0) ||
- (desc_ptr->sfn == NULL)) {
- /* invalid parameter */
- return TFM_ERROR_INVALID_PARAMETER;
- }
- return TFM_SUCCESS;
-}
-
-static int32_t tfm_core_check_sfn_req_rules(
- const struct tfm_sfn_req_s *desc_ptr)
-{
- /* Check partition idx validity */
- if (desc_ptr->caller_part_idx == SPM_INVALID_PARTITION_IDX) {
- return TFM_ERROR_NO_ACTIVE_PARTITION;
- }
-
- if ((desc_ptr->ns_caller) && (tfm_secure_lock != 0)) {
- /* Secure domain is already locked!
- * This should only happen if caller is secure partition!
- * FixMe: This scenario is a potential security breach
- * Take appropriate action!
- */
- return TFM_ERROR_SECURE_DOMAIN_LOCKED;
- }
-
- if (tfm_secure_api_initializing) {
- int32_t id =
- tfm_spm_partition_get_partition_id(desc_ptr->caller_part_idx);
-
- if ((id != TFM_SP_CORE_ID) || (tfm_secure_lock != 0)) {
- /* Invalid request during system initialization */
- ERROR_MSG("Invalid service request during initialization!");
- return TFM_ERROR_NOT_INITIALIZED;
- }
- }
-
- return TFM_SUCCESS;
-}
-
-void tfm_secure_api_init_done(void)
-{
- tfm_secure_api_initializing = 0;
-#if TFM_LVL != 1
- if (tfm_spm_partition_sandbox_config(TFM_SP_NON_SECURE_ID) != SPM_ERR_OK) {
- ERROR_MSG("Failed to configure sandbox for partition!");
- tfm_secure_api_error_handler();
- }
-#endif
-}
-
-int32_t tfm_core_sfn_request_handler(
- struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn)
-{
- int32_t res;
-
- res = tfm_check_sfn_req_integrity(desc_ptr);
- if (res != TFM_SUCCESS) {
- ERROR_MSG("Invalid service request!");
- tfm_secure_api_error_handler();
- }
-
- __disable_irq();
-
- desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx();
-
- if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
- res = tfm_core_check_sfn_parameters(desc_ptr);
- if (res != TFM_SUCCESS) {
- /* The sanity check of iovecs failed. */
- __enable_irq();
- tfm_secure_api_error_handler();
- }
- }
-
- res = tfm_core_check_sfn_req_rules(desc_ptr);
- if (res != TFM_SUCCESS) {
- /* FixMe: error compartmentalization TBD */
- tfm_spm_partition_set_state(
- desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED);
- __enable_irq();
- ERROR_MSG("Unauthorized service request!");
- tfm_secure_api_error_handler();
- }
-
- res = tfm_start_partition(desc_ptr, excReturn);
- if (res != TFM_SUCCESS) {
- /* FixMe: consider possible fault scenarios */
- __enable_irq();
- ERROR_MSG("Failed to process service request!");
- tfm_secure_api_error_handler();
- }
-
- __enable_irq();
-
- return res;
-}
-
-#if TFM_LVL == 1
-int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr)
-{
- int32_t res;
- int32_t *args;
- int32_t retVal;
-
- if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
- res = tfm_core_check_sfn_parameters(desc_ptr);
- if (res != TFM_SUCCESS) {
- /* The sanity check of iovecs failed. */
- return res;
- }
- }
-
- /* No excReturn value is needed as no exception handling is used */
- res = tfm_core_sfn_request_handler(desc_ptr, 0);
-
- if (res != TFM_SUCCESS) {
- tfm_secure_api_error_handler();
- }
-
- /* Secure partition to secure partition call in TFM level 1 */
- args = desc_ptr->args;
- retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]);
-
- /* return handler should restore original exc_return value... */
- res = tfm_return_from_partition(NULL);
- if (res == TFM_SUCCESS) {
- /* If unlock successful, pass SS return value to caller */
- res = retVal;
- } else {
- /* Unlock errors indicate ctx database corruption or unknown
- * anomalies. Halt execution
- */
- ERROR_MSG("Secure API error during unlock!");
- tfm_secure_api_error_handler();
- }
- return res;
-}
-#endif
-
-void tfm_core_validate_secure_caller_handler(uint32_t *svc_args)
-{
-
- int32_t res = TFM_ERROR_GENERIC;
- uint32_t running_partition_idx =
- tfm_spm_partition_get_running_partition_idx();
- const struct spm_partition_runtime_data_t *curr_part_data =
- tfm_spm_partition_get_runtime_data(running_partition_idx);
- uint32_t running_partition_flags =
- tfm_spm_partition_get_flags(running_partition_idx);
- uint32_t caller_partition_flags =
- tfm_spm_partition_get_flags(curr_part_data->caller_partition_idx);
-
- if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
- /* This handler shouldn't be called from outside partition context.
- * Partitions are only allowed to run while S domain is locked.
- */
- svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
-
- /* Store return value in r0 */
- if (caller_partition_flags & SPM_PART_FLAG_APP_ROT) {
- res = TFM_SUCCESS;
- }
- svc_args[0] = res;
-}
-
-int32_t tfm_core_check_buffer_access(uint32_t partition_idx,
- void *start_addr,
- size_t len,
- uint32_t alignment)
-{
- uintptr_t start_addr_value = (uintptr_t)start_addr;
- uintptr_t end_addr_value = (uintptr_t)start_addr + len;
- uintptr_t alignment_mask;
-
- alignment_mask = (((uintptr_t)1) << alignment) - 1;
-
- /* Check that the pointer is aligned properly */
- if (start_addr_value & alignment_mask) {
- /* not aligned, return error */
- return 0;
- }
-
- /* Protect against overflow (and zero len) */
- if (end_addr_value <= start_addr_value)
- {
- return 0;
- }
-
-#if TFM_LVL == 1
- /* For privileged partition execution, all secure data memory and stack
- * is accessible
- */
- if (start_addr_value >= S_DATA_START &&
- end_addr_value <= (S_DATA_START + S_DATA_SIZE)) {
- return 1;
- }
-#else
- /* For non-privileged execution the partition's data and stack is
- * accessible
- */
- if (start_addr_value >=
- tfm_spm_partition_get_stack_bottom(partition_idx) &&
- end_addr_value <=
- tfm_spm_partition_get_stack_top(partition_idx)) {
- return 1;
- }
- if (start_addr_value >=
- tfm_spm_partition_get_rw_start(partition_idx) &&
- end_addr_value <=
- tfm_spm_partition_get_rw_limit(partition_idx)) {
- return 1;
- }
- if (start_addr_value >=
- tfm_spm_partition_get_zi_start(partition_idx) &&
- end_addr_value <=
- tfm_spm_partition_get_zi_limit(partition_idx)) {
- return 1;
- }
-#endif
- return 0;
-}
-
-void tfm_core_get_caller_client_id_handler(uint32_t *svc_args)
-{
- uintptr_t result_ptr_value = svc_args[0];
- uint32_t running_partition_idx =
- tfm_spm_partition_get_running_partition_idx();
- const uint32_t running_partition_flags =
- tfm_spm_partition_get_flags(running_partition_idx);
- const struct spm_partition_runtime_data_t *curr_part_data =
- tfm_spm_partition_get_runtime_data(running_partition_idx);
- int res = 0;
-
- if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
- /* This handler shouldn't be called from outside partition context.
- * Partitions are only allowed to run while S domain is locked.
- */
- svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
-
- /* Make sure that the output pointer points to a memory area that is owned
- * by the partition
- */
- res = tfm_core_check_buffer_access(running_partition_idx,
- (void *)result_ptr_value,
- sizeof(curr_part_data->caller_client_id),
- 2);
- if (!res) {
- /* Not in accessible range, return error */
- svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
-
- *((int32_t *)result_ptr_value) = curr_part_data->caller_client_id;
-
- /* Store return value in r0 */
- svc_args[0] = TFM_SUCCESS;
-}
-
-void tfm_core_memory_permission_check_handler(uint32_t *svc_args)
-{
- uint32_t ptr = svc_args[0];
- uint32_t size = svc_args[1];
- int32_t access = svc_args[2];
-
- uint32_t max_buf_size, ptr_start, range_limit, range_check = false;
- int32_t res;
- uint32_t running_partition_idx =
- tfm_spm_partition_get_running_partition_idx();
- const struct spm_partition_runtime_data_t *curr_part_data =
- tfm_spm_partition_get_runtime_data(running_partition_idx);
- uint32_t running_partition_flags =
- tfm_spm_partition_get_flags(running_partition_idx);
- int32_t flags = 0;
- void *rangeptr;
-
- if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) || (size == 0)) {
- /* This handler should only be called from a secure partition. */
- svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
-
- if (curr_part_data->share != TFM_BUFFER_SHARE_PRIV) {
- flags |= CMSE_MPU_UNPRIV;
- }
-
- if (access == TFM_MEMORY_ACCESS_RW) {
- flags |= CMSE_MPU_READWRITE;
- } else {
- flags |= CMSE_MPU_READ;
- }
-
- /* Check if partition access to address would fail */
- rangeptr = cmse_check_address_range((void *)ptr, size, flags);
-
- /* Get regions associated with address */
- cmse_address_info_t addr_info = cmse_TT((void *)ptr);
-
- if (rangeptr == NULL) {
- svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
-
- if (addr_info.flags.secure) {
-#if TFM_LVL == 1
- /* For privileged partition execution, all secure data memory is
- * accessible
- */
- max_buf_size = S_DATA_SIZE;
- ptr_start = S_DATA_START;
- range_limit = S_DATA_LIMIT;
-#else
- /* Only scratch is permitted in secure memory */
- max_buf_size = (uint32_t)tfm_scratch_area_size;
- ptr_start = (uint32_t)tfm_scratch_area;
- range_limit = (uint32_t)tfm_scratch_area + tfm_scratch_area_size - 1;
-#endif
- range_check = true;
- } else {
- if (!addr_info.flags.sau_region_valid) {
- /* If address is NS, TF-M expects SAU to be configured
- */
- svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
- switch (addr_info.flags.sau_region) {
- case TFM_NS_REGION_CODE:
- if (access == TFM_MEMORY_ACCESS_RW) {
- res = TFM_ERROR_INVALID_PARAMETER;
- } else {
- /* Currently TF-M does not support checks for NS Memory
- * accesses by partitions
- */
- res = TFM_SUCCESS;
- }
- break;
- case TFM_NS_REGION_DATA:
- /* Currently TF-M does not support checks for NS Memory
- * accesses by partitions
- */
- res = TFM_SUCCESS;
- break;
- default:
- /* Only NS data and code regions can be accessed as buffers */
- res = TFM_ERROR_INVALID_PARAMETER;
- break;
- }
- }
-
- if (range_check == true) {
- if ((size <= max_buf_size) && (ptr >= ptr_start)
- && (ptr <= range_limit + 1 - size)) {
- res = TFM_SUCCESS;
- } else {
- res = TFM_ERROR_INVALID_PARAMETER;
- }
- }
-
- /* Store return value in r0 */
- svc_args[0] = res;
-}
-
-/* This SVC handler is called if veneer is running in thread mode */
-uint32_t tfm_core_partition_request_svc_handler(
- const struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn)
-{
- struct tfm_sfn_req_s *desc_ptr;
-
- if (!(excReturn & EXC_RETURN_STACK_PROCESS)) {
- /* Service request SVC called with MSP active.
- * Either invalid configuration for Thread mode or SVC called
- * from Handler mode, which is not supported.
- * FixMe: error severity TBD
- */
- ERROR_MSG("Service request SVC called with MSP active!");
- tfm_secure_api_error_handler();
- }
-
- desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0;
-
- if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) {
- tfm_secure_api_error_handler();
- }
-
- return EXC_RETURN_SECURE_FUNCTION;
-}
-
-/* This SVC handler is called when sfn returns */
-uint32_t tfm_core_partition_return_handler(uint32_t lr)
-{
- int32_t res;
-
- if (!(lr & EXC_RETURN_STACK_PROCESS)) {
- /* Partition return SVC called with MSP active.
- * This should not happen!
- */
- ERROR_MSG("Partition return SVC called with MSP active!");
- tfm_secure_api_error_handler();
- }
-
- /* Store return value from secure partition */
- int32_t retVal = *(int32_t *)__get_PSP();
-
- if (!is_iovec_api_call()) {
- if ((retVal > TFM_SUCCESS) &&
- (retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) {
- /* Secure function returned a reserved value */
-#ifdef TFM_CORE_DEBUG
- LOG_MSG("Invalid return value from secure partition!");
-#endif
- /* FixMe: error can be traced to specific secure partition
- * and Core is not compromised. Error handling flow can be
- * refined
- */
- tfm_secure_api_error_handler();
- }
- }
-
- res = tfm_return_from_partition(&lr);
- if (res != TFM_SUCCESS) {
- /* Unlock errors indicate ctx database corruption or unknown anomalies
- * Halt execution
- */
- ERROR_MSG("Secure API error during unlock!");
- tfm_secure_api_error_handler();
- }
-
- return lr;
-}
-
-void tfm_core_set_buffer_area_handler(uint32_t *args)
-{
- /* r0 is stored in args[0] in exception stack frame
- * Store input parameter before writing return value to that address
- */
- enum tfm_buffer_share_region_e share;
- uint32_t running_partition_idx =
- tfm_spm_partition_get_running_partition_idx();
- const struct spm_partition_runtime_data_t *curr_part_data =
- tfm_spm_partition_get_runtime_data(running_partition_idx);
- uint32_t caller_partition_idx = curr_part_data->caller_partition_idx;
- uint32_t running_partition_flags =
- tfm_spm_partition_get_flags(running_partition_idx);
- uint32_t caller_partition_flags =
- tfm_spm_partition_get_flags(caller_partition_idx);
-
- /* tfm_core_set_buffer_area() returns int32_t */
- int32_t *res_ptr = (int32_t *)&args[0];
-
- if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
- /* This handler should only be called from a secure partition. */
- *res_ptr = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
-
- switch (args[0]) {
- case TFM_BUFFER_SHARE_DEFAULT:
- share = (!(caller_partition_flags & SPM_PART_FLAG_APP_ROT)) ?
- (TFM_BUFFER_SHARE_NS_CODE) : (TFM_BUFFER_SHARE_SCRATCH);
- break;
- case TFM_BUFFER_SHARE_SCRATCH:
- case TFM_BUFFER_SHARE_NS_CODE:
- share = args[0];
- break;
- default:
- *res_ptr = TFM_ERROR_INVALID_PARAMETER;
- return;
- }
-
- if (tfm_spm_partition_set_share(running_partition_idx, share) ==
- SPM_ERR_OK) {
- *res_ptr = TFM_SUCCESS;
- } else {
- *res_ptr = TFM_ERROR_INVALID_PARAMETER;
- }
-
- return;
-}
diff --git a/secure_fw/core/tfm_secure_api.h b/secure_fw/core/tfm_secure_api.h
index 23bcd40..50b56fc 100644
--- a/secure_fw/core/tfm_secure_api.h
+++ b/secure_fw/core/tfm_secure_api.h
@@ -130,6 +130,25 @@
uint32_t ns_caller,
uint32_t privileged);
+#ifdef TFM_PSA_API
+/* The following macros are only valid if secure services can be called
+ * using veneer functions. This is not the case if IPC messaging is enabled
+ */
+#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
+ do { \
+ ERROR_MSG("Invalid TF-M configuration detected"); \
+ tfm_secure_api_error_handler(); \
+ /* This point never reached */ \
+ return (int32_t)TFM_ERROR_GENERIC; \
+ } while (0)
+#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
+ do { \
+ ERROR_MSG("Invalid TF-M configuration detected"); \
+ tfm_secure_api_error_handler(); \
+ /* This point never reached */ \
+ return (int32_t)TFM_ERROR_GENERIC; \
+ } while (0)
+#else
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
return tfm_core_partition_request(id, fn, TFM_SFN_API_IOVEC, \
(int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
@@ -190,5 +209,6 @@
}
}
+#endif
#endif /* __TFM_SECURE_API_H__ */
diff --git a/secure_fw/spm/spm_api.c b/secure_fw/spm/spm_api.c
index 5f10465..4d56a91 100644
--- a/secure_fw/spm/spm_api.c
+++ b/secure_fw/spm/spm_api.c
@@ -98,10 +98,12 @@
*/
/* For the non secure Execution environment */
+#if (TFM_LVL != 1) || defined(TFM_PSA_API)
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[];
uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
uint32_t psp_stack_top = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Limit;
+#endif
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) {
return SPM_ERR_INVALID_CONFIG;
}
@@ -117,12 +119,14 @@
part_ptr->static_data.partition_flags = 0;
#endif
+#if (TFM_LVL != 1) || defined(TFM_PSA_API)
part_ptr->memory_data.stack_bottom = psp_stack_bottom;
part_ptr->memory_data.stack_top = psp_stack_top;
/* Since RW, ZI and stack are configured as one MPU region, configure
* RW start address to psp_stack_bottom to get RW access to stack
*/
part_ptr->memory_data.rw_start = psp_stack_bottom;
+#endif
part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT;
tfm_nspm_configure_clients();
@@ -189,7 +193,10 @@
}
}
+#ifndef TFM_PSA_API
+ /* Not applicable if IPC messaging is used */
tfm_secure_api_init_done();
+#endif
if (fail_cnt == 0) {
return SPM_ERR_OK;
@@ -198,6 +205,7 @@
}
}
+#if (TFM_LVL != 1) || defined(TFM_PSA_API)
uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx)
{
return g_spm_partition_db.partitions[partition_idx].
@@ -208,8 +216,9 @@
{
return g_spm_partition_db.partitions[partition_idx].memory_data.stack_top;
}
+#endif
-#if TFM_LVL != 1
+#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx)
{
struct spm_partition_desc_t *part;
@@ -319,6 +328,7 @@
caller_client_id = caller_client_id;
}
+#ifndef TFM_PSA_API
enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
uint32_t share)
{
@@ -334,6 +344,7 @@
}
return ret;
}
+#endif
enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
const int32_t *args)
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
index c0122d6..106b29f 100644
--- a/secure_fw/spm/spm_api.h
+++ b/secure_fw/spm/spm_api.h
@@ -87,6 +87,7 @@
*/
uint32_t get_partition_idx(uint32_t partition_id);
+#if (TFM_LVL != 1) || defined(TFM_PSA_API)
/**
* \brief Get bottom of stack region for a partition
*
@@ -108,8 +109,9 @@
* \note This function doesn't check if partition_idx is valid.
*/
uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx);
+#endif
-#if TFM_LVL != 1
+#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
/**
* \brief Configure isolated sandbox for a partition
*
diff --git a/secure_fw/spm/spm_db.h b/secure_fw/spm/spm_db.h
index b8827b4..6e6e25c 100644
--- a/secure_fw/spm/spm_db.h
+++ b/secure_fw/spm/spm_db.h
@@ -57,7 +57,9 @@
struct spm_partition_static_data_t static_data;
struct spm_partition_runtime_data_t runtime_data;
struct tfm_spm_partition_platform_data_t *platform_data;
+#if (TFM_LVL != 1) || defined(TFM_PSA_API)
struct tfm_spm_partition_memory_data_t memory_data;
+#endif
#ifdef TFM_PSA_API
struct tfm_thrd_ctx sp_thrd;
#endif
@@ -66,8 +68,12 @@
/* Macros to pick linker symbols and allow to form the partition data base */
#define REGION(a, b, c) a##b##c
#define REGION_NAME(a, b, c) REGION(a, b, c)
+#if (TFM_LVL == 1) && !defined(TFM_PSA_API)
+#define REGION_DECLARE(a, b, c)
+#else
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
#define PART_REGION_ADDR(partition, region) \
(uint32_t)®ION_NAME(Image$$, partition, region)
+#endif
#endif /* __SPM_DB_H__ */
diff --git a/secure_fw/spm/spm_db_setup.h b/secure_fw/spm/spm_db_setup.h
index 1e91271..db06154 100644
--- a/secure_fw/spm/spm_db_setup.h
+++ b/secure_fw/spm/spm_db_setup.h
@@ -38,6 +38,9 @@
data.partition_priority = TFM_PRIORITY(priority); \
} while (0)
+#if (TFM_LVL == 1) && !defined(TFM_PSA_API)
+#define PARTITION_INIT_MEMORY_DATA(data, partition)
+#else
#define PARTITION_INIT_MEMORY_DATA(data, partition) \
do { \
data.code_start = PART_REGION_ADDR(partition, $$Base); \
@@ -51,7 +54,7 @@
data.stack_bottom = PART_REGION_ADDR(partition, _STACK$$ZI$$Base); \
data.stack_top = PART_REGION_ADDR(partition, _STACK$$ZI$$Limit); \
} while (0)
-
+#endif
#if TFM_LVL == 1
#define PARTITION_INIT_RUNTIME_DATA(data, partition) \