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)&REGION_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