1 /*
2 * Copyright (c) 2017-2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <string.h>
9 #include "config_spm.h"
10 #include "memory_symbols.h"
11 #include "spm.h"
12 #include "svc_num.h"
13 #include "tfm_api.h"
14 #include "tfm_arch.h"
15 #include "tfm_core_trustzone.h"
16 #include "tfm_svcalls.h"
17 #include "utilities.h"
18 #include "load/spm_load_api.h"
19 #include "ffm/interrupt.h"
20 #include "ffm/tfm_boot_data.h"
21 #include "ffm/psa_api.h"
22 #include "tfm_hal_isolation.h"
23 #include "tfm_hal_spm_logdev.h"
24 #include "load/partition_defs.h"
25 #include "psa/client.h"
26 #include "tfm_hal_platform.h"
27
28 #ifdef PLATFORM_SVC_HANDLERS
29 extern int32_t platform_svc_handlers(uint8_t svc_num,
30 uint32_t *ctx, uint32_t lr);
31 #endif
32
33 #if CONFIG_TFM_PSA_API_SUPERVISOR_CALL == 1
SVC_Handler_IPC(uint8_t svc_num,uint32_t * ctx,uint32_t lr)34 static int32_t SVC_Handler_IPC(uint8_t svc_num, uint32_t *ctx,
35 uint32_t lr)
36 {
37 psa_status_t status = PSA_SUCCESS;
38
39 switch (svc_num) {
40 case TFM_SVC_PSA_FRAMEWORK_VERSION:
41 return tfm_spm_client_psa_framework_version();
42 case TFM_SVC_PSA_VERSION:
43 return tfm_spm_client_psa_version(ctx[0]);
44 case TFM_SVC_PSA_CALL:
45 status = tfm_spm_client_psa_call((psa_handle_t)ctx[0], ctx[1],
46 (const psa_invec *)ctx[2],
47 (psa_outvec *)ctx[3]);
48 break;
49 case TFM_SVC_PSA_READ:
50 return tfm_spm_partition_psa_read((psa_handle_t)ctx[0], ctx[1],
51 (void *)ctx[2], (size_t)ctx[3]);
52 case TFM_SVC_PSA_SKIP:
53 return tfm_spm_partition_psa_skip((psa_handle_t)ctx[0], ctx[1],
54 (size_t)ctx[2]);
55 case TFM_SVC_PSA_WRITE:
56 tfm_spm_partition_psa_write((psa_handle_t)ctx[0], ctx[1],
57 (void *)ctx[2], (size_t)ctx[3]);
58 break;
59 #if CONFIG_TFM_DOORBELL_API == 1
60 case TFM_SVC_PSA_NOTIFY:
61 tfm_spm_partition_psa_notify((int32_t)ctx[0]);
62 break;
63 case TFM_SVC_PSA_CLEAR:
64 tfm_spm_partition_psa_clear();
65 break;
66 #endif /* CONFIG_TFM_DOORBELL_API == 1 */
67 case TFM_SVC_PSA_PANIC:
68 tfm_spm_partition_psa_panic();
69 break;
70 case TFM_SVC_PSA_LIFECYCLE:
71 return tfm_spm_get_lifecycle_state();
72 /* Following svc handlers are only needed by connection-based services */
73 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
74 case TFM_SVC_PSA_CONNECT:
75 status = tfm_spm_client_psa_connect(ctx[0], ctx[1]);
76 break;
77 case TFM_SVC_PSA_CLOSE:
78 status = tfm_spm_client_psa_close((psa_handle_t)ctx[0]);
79 break;
80 case TFM_SVC_PSA_SET_RHANDLE:
81 tfm_spm_partition_psa_set_rhandle((psa_handle_t)ctx[0], (void *)ctx[1]);
82 break;
83 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
84 /* These APIs are only used in IPC backend. */
85 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
86 case TFM_SVC_PSA_GET:
87 return tfm_spm_partition_psa_get((psa_signal_t)ctx[0],
88 (psa_msg_t *)ctx[1]);
89 case TFM_SVC_PSA_REPLY:
90 tfm_spm_partition_psa_reply((psa_handle_t)ctx[0], (psa_status_t)ctx[1]);
91 break;
92 case TFM_SVC_PSA_WAIT:
93 return tfm_spm_partition_psa_wait((psa_signal_t)ctx[0], ctx[1]);
94 #endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
95
96 #if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
97 case TFM_SVC_PSA_IRQ_ENABLE:
98 tfm_spm_partition_psa_irq_enable((psa_signal_t)ctx[0]);
99 break;
100 case TFM_SVC_PSA_IRQ_DISABLE:
101 return tfm_spm_partition_psa_irq_disable((psa_signal_t)ctx[0]);
102 /* This API is only used for FLIH. */
103 #if CONFIG_TFM_FLIH_API == 1
104 case TFM_SVC_PSA_RESET_SIGNAL:
105 tfm_spm_partition_psa_reset_signal((psa_signal_t)ctx[0]);
106 break;
107 #endif
108 /* This API is only used for SLIH. */
109 #if CONFIG_TFM_SLIH_API == 1
110 case TFM_SVC_PSA_EOI:
111 tfm_spm_partition_psa_eoi((psa_signal_t)ctx[0]);
112 break;
113 #endif
114 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
115 default:
116 #ifdef PLATFORM_SVC_HANDLERS
117 return (platform_svc_handlers(svc_num, ctx, lr));
118 #else
119 SPMLOG_ERRMSG("Unknown SVC number requested!\r\n");
120 return PSA_ERROR_GENERIC_ERROR;
121 #endif
122 }
123 spm_handle_programmer_errors(status);
124 return status;
125 }
126 #endif
127
tfm_core_svc_handler(uint32_t * msp,uint32_t exc_return,uint32_t * psp)128 uint32_t tfm_core_svc_handler(uint32_t *msp, uint32_t exc_return,
129 uint32_t *psp)
130 {
131 uint8_t svc_number = TFM_SVC_PSA_FRAMEWORK_VERSION;
132 uint32_t *svc_args = msp;
133
134 if ((exc_return & EXC_RETURN_MODE) && (exc_return & EXC_RETURN_SPSEL)) {
135 /* Use PSP when both EXC_RETURN.MODE and EXC_RETURN.SPSEL are set */
136 svc_args = psp;
137 }
138
139 if (is_return_secure_stack(exc_return)) {
140 if (is_default_stacking_rules_apply(exc_return) == false) {
141 /* In this case offset the svc_args and only use
142 * the caller-saved registers
143 */
144 svc_args = &svc_args[10];
145 }
146
147 /* SV called directly from secure context. Check instruction for
148 * svc_number
149 */
150 svc_number = ((uint8_t *)svc_args[6])[-2];
151 } else {
152 /* Secure SV executing with NS return.
153 * NS cannot directly trigger S SVC so this should not happen. This is
154 * an unrecoverable error.
155 */
156 tfm_core_panic();
157 }
158
159 if (!(exc_return & EXC_RETURN_MODE)
160 != (svc_number > TFM_SVC_THREAD_NUMBER_END)) {
161 tfm_core_panic();
162 }
163
164 switch (svc_number) {
165 case TFM_SVC_SPM_INIT:
166 exc_return = tfm_spm_init();
167 tfm_arch_check_msp_sealing();
168 /* The following call does not return */
169 tfm_arch_free_msp_and_exc_ret(SPM_BOOT_STACK_BOTTOM, exc_return);
170 break;
171 case TFM_SVC_GET_BOOT_DATA:
172 tfm_core_get_boot_data_handler(svc_args);
173 break;
174 #if (TFM_LVL != 1) && (CONFIG_TFM_FLIH_API == 1)
175 case TFM_SVC_PREPARE_DEPRIV_FLIH:
176 exc_return = tfm_flih_prepare_depriv_flih(
177 (struct partition_t *)svc_args[0],
178 (uintptr_t)svc_args[1]);
179 break;
180 case TFM_SVC_FLIH_FUNC_RETURN:
181 exc_return = tfm_flih_return_to_isr(svc_args[0],
182 (struct context_flih_ret_t *)msp);
183 break;
184 #endif
185 #if TFM_SP_LOG_RAW_ENABLED
186 case TFM_SVC_OUTPUT_UNPRIV_STRING:
187 svc_args[0] = tfm_hal_output_spm_log((const char *)svc_args[0],
188 svc_args[1]);
189 break;
190 #endif
191 default:
192 #if CONFIG_TFM_PSA_API_SUPERVISOR_CALL == 1
193 if (((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Limit)
194 - (uint32_t)msp) > 0) {
195 /* The Main Stack has contents, not calling from Partition thread */
196 tfm_core_panic();
197 }
198 svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, exc_return);
199 if (THRD_EXPECTING_SCHEDULE()) {
200 tfm_arch_trigger_pendsv();
201 }
202 #else
203 #ifdef PLATFORM_SVC_HANDLERS
204 svc_args[0] = (platform_svc_handlers(svc_number, svc_args, exc_return));
205 #else
206 SPMLOG_ERRMSG("Unknown SVC number requested!\r\n");
207 svc_args[0] = PSA_ERROR_GENERIC_ERROR;
208 #endif
209 spm_handle_programmer_errors(svc_args[0]);
210 #endif
211 break;
212 }
213
214 return exc_return;
215 }
216
tfm_core_handler_mode(void)217 __attribute__ ((naked)) void tfm_core_handler_mode(void)
218 {
219 __ASM volatile("SVC %0 \n"
220 "BX LR \n"
221 : : "I" (TFM_SVC_SPM_INIT));
222 }
223