blob: 3b4fb8cf4e76dcf613399dfb7717babb3653bebc [file] [log] [blame]
Mingyang Sunda01a972019-07-12 17:32:59 +08001/*
2 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8/* All the APIs defined in this file are used for library model. */
9
10#include <inttypes.h>
11#include <limits.h>
12#include <stdbool.h>
13#include <stdlib.h>
14#include "tfm_utils.h"
15#include "tfm_spm_hal.h"
16#include "spm_api.h"
17#include "spm_db.h"
18#include "region_defs.h"
19#include "tfm_nspm.h"
20#include "tfm_memory_utils.h"
21#include "tfm_internal.h"
22
23extern struct spm_partition_db_t g_spm_partition_db;
24
25typedef enum {
26 TFM_INIT_FAILURE,
27} sp_error_type_t;
28
29/*
30 * This function is called when a secure partition causes an error.
31 * In case of an error in the error handling, a non-zero value have to be
32 * returned.
33 */
34static void tfm_spm_partition_err_handler(
35 const struct spm_partition_desc_t *partition,
36 sp_error_type_t err_type,
37 int32_t err_code)
38{
39#ifdef TFM_CORE_DEBUG
40 if (err_type == TFM_INIT_FAILURE) {
41 printf("Partition init failed for partition id 0x%08X\r\n",
42 partition->static_data.partition_id);
43 } else {
44 printf(
45 "Unknown partition error %d (code: %d) for partition id 0x%08X\r\n",
46 err_type, err_code, partition->static_data.partition_id);
47 }
48#else
49 (void)err_type;
50 (void)err_code;
51#endif
52 tfm_spm_partition_set_state(partition->static_data.partition_id,
53 SPM_PARTITION_STATE_CLOSED);
54}
55
56enum spm_err_t tfm_spm_partition_init(void)
57{
58 struct spm_partition_desc_t *part;
59 struct tfm_sfn_req_s desc;
60 int32_t args[4] = {0};
61 int32_t fail_cnt = 0;
62 uint32_t idx;
63
64 /* Call the init function for each partition */
65 for (idx = 0; idx < g_spm_partition_db.partition_count; ++idx) {
66 part = &g_spm_partition_db.partitions[idx];
67 tfm_spm_hal_configure_default_isolation(part->platform_data);
68 if (part->static_data.partition_init == NULL) {
69 tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
70 tfm_spm_partition_set_caller_partition_idx(idx,
71 SPM_INVALID_PARTITION_IDX);
72 } else {
73 int32_t res;
74
75 desc.args = args;
76 desc.ns_caller = 0U;
77 desc.iovec_api = TFM_SFN_API_IOVEC;
78 desc.sfn = (sfn_t)part->static_data.partition_init;
79 desc.sp_id = part->static_data.partition_id;
80 res = tfm_core_sfn_request(&desc);
81 if (res == TFM_SUCCESS) {
82 tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
83 } else {
84 tfm_spm_partition_err_handler(part, TFM_INIT_FAILURE, res);
85 fail_cnt++;
86 }
87 }
88 }
89
90 tfm_secure_api_init_done();
91
92 if (fail_cnt == 0) {
93 return SPM_ERR_OK;
94 } else {
95 return SPM_ERR_PARTITION_NOT_AVAILABLE;
96 }
97}
98
99void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx)
100{
101 struct spm_partition_runtime_data_t *runtime_data =
102 &g_spm_partition_db.partitions[partition_idx].runtime_data;
103 struct interrupted_ctx_stack_frame_t *stack_frame =
104 (struct interrupted_ctx_stack_frame_t *)
105 runtime_data->ctx_stack_ptr;
106
107 stack_frame->partition_state = runtime_data->partition_state;
108#if TFM_LVL != 1
109 stack_frame->stack_ptr = runtime_data->stack_ptr;
110#endif
111 runtime_data->ctx_stack_ptr +=
112 sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t);
113}
114
115void tfm_spm_partition_pop_interrupted_ctx(uint32_t partition_idx)
116{
117 struct spm_partition_runtime_data_t *runtime_data =
118 &g_spm_partition_db.partitions[partition_idx].runtime_data;
119 struct interrupted_ctx_stack_frame_t *stack_frame;
120
121 runtime_data->ctx_stack_ptr -=
122 sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t);
123 stack_frame = (struct interrupted_ctx_stack_frame_t *)
124 runtime_data->ctx_stack_ptr;
125 tfm_spm_partition_set_state(partition_idx, stack_frame->partition_state);
126 stack_frame->partition_state = 0;
127#if TFM_LVL != 1
128 tfm_spm_partition_set_stack(partition_idx, stack_frame->stack_ptr);
129 stack_frame->stack_ptr = 0;
130#endif
131}
132
133void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx)
134{
135 struct spm_partition_runtime_data_t *runtime_data =
136 &g_spm_partition_db.partitions[partition_idx].runtime_data;
137 struct handler_ctx_stack_frame_t *stack_frame =
138 (struct handler_ctx_stack_frame_t *)
139 runtime_data->ctx_stack_ptr;
140
141 stack_frame->partition_state = runtime_data->partition_state;
142 stack_frame->caller_partition_idx = runtime_data->caller_partition_idx;
143
144 runtime_data->ctx_stack_ptr +=
145 sizeof(struct handler_ctx_stack_frame_t) / sizeof(uint32_t);
146}
147
148void tfm_spm_partition_pop_handler_ctx(uint32_t partition_idx)
149{
150 struct spm_partition_runtime_data_t *runtime_data =
151 &g_spm_partition_db.partitions[partition_idx].runtime_data;
152 struct handler_ctx_stack_frame_t *stack_frame;
153
154 runtime_data->ctx_stack_ptr -=
155 sizeof(struct handler_ctx_stack_frame_t) / sizeof(uint32_t);
156
157 stack_frame = (struct handler_ctx_stack_frame_t *)
158 runtime_data->ctx_stack_ptr;
159
160 tfm_spm_partition_set_state(partition_idx, stack_frame->partition_state);
161 stack_frame->partition_state = 0;
162 tfm_spm_partition_set_caller_partition_idx(
163 partition_idx, stack_frame->caller_partition_idx);
164 stack_frame->caller_partition_idx = 0;
165}
166
167#if (TFM_LVL != 1)
168enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx)
169{
170 struct spm_partition_desc_t *part;
171 if (!g_spm_partition_db.is_init) {
172 return SPM_ERR_PARTITION_DB_NOT_INIT;
173 }
174
175 part = &g_spm_partition_db.partitions[partition_idx];
176
177 return tfm_spm_hal_partition_sandbox_config(&(part->memory_data),
178 part->platform_data);
179
180}
181
182enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx)
183{
184 /* This function takes a partition id and disables the
185 * SPM partition for that partition
186 */
187
188 struct spm_partition_desc_t *part;
189
190 part = &g_spm_partition_db.partitions[partition_idx];
191
192 return tfm_spm_hal_partition_sandbox_deconfig(&(part->memory_data),
193 part->platform_data);
194}
195
196uint32_t tfm_spm_partition_get_zi_start(uint32_t partition_idx)
197{
198 return g_spm_partition_db.partitions[partition_idx].
199 memory_data.zi_start;
200}
201
202uint32_t tfm_spm_partition_get_zi_limit(uint32_t partition_idx)
203{
204 return g_spm_partition_db.partitions[partition_idx].
205 memory_data.zi_limit;
206}
207
208uint32_t tfm_spm_partition_get_rw_start(uint32_t partition_idx)
209{
210 return g_spm_partition_db.partitions[partition_idx].
211 memory_data.rw_start;
212}
213
214uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx)
215{
216 return g_spm_partition_db.partitions[partition_idx].
217 memory_data.rw_limit;
218}
219
220void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr)
221{
222 g_spm_partition_db.partitions[partition_idx].
223 runtime_data.stack_ptr = stack_ptr;
224}
225#endif
226
227void tfm_spm_partition_store_context(uint32_t partition_idx,
228 uint32_t stack_ptr, uint32_t lr)
229{
230 g_spm_partition_db.partitions[partition_idx].
231 runtime_data.stack_ptr = stack_ptr;
232 g_spm_partition_db.partitions[partition_idx].
233 runtime_data.lr = lr;
234}
235
236const struct spm_partition_runtime_data_t *
237 tfm_spm_partition_get_runtime_data(uint32_t partition_idx)
238{
239 return &(g_spm_partition_db.partitions[partition_idx].runtime_data);
240}
241
242void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state)
243{
244 g_spm_partition_db.partitions[partition_idx].runtime_data.partition_state =
245 state;
246 if (state == SPM_PARTITION_STATE_RUNNING ||
247 state == SPM_PARTITION_STATE_HANDLING_IRQ) {
248 g_spm_partition_db.running_partition_idx = partition_idx;
249 }
250}
251
252void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
253 uint32_t caller_partition_idx)
254{
255 g_spm_partition_db.partitions[partition_idx].runtime_data.
256 caller_partition_idx = caller_partition_idx;
257}
258
259void tfm_spm_partition_set_signal_mask(uint32_t partition_idx,
260 uint32_t signal_mask)
261{
262 g_spm_partition_db.partitions[partition_idx].runtime_data.
263 signal_mask = signal_mask;
264}
265
266void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
267 int32_t caller_client_id)
268{
269 g_spm_partition_db.partitions[partition_idx].runtime_data.
270 caller_client_id = caller_client_id;
271}
272
273enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
274 uint32_t share)
275{
276 enum spm_err_t ret = SPM_ERR_OK;
277
278#if TFM_LVL != 1
279 /* Only need to set configuration on levels higher than 1 */
280 ret = tfm_spm_hal_set_share_region(share);
281#endif
282
283 if (ret == SPM_ERR_OK) {
284 g_spm_partition_db.partitions[partition_idx].runtime_data.share = share;
285 }
286 return ret;
287}
288
289enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
290 const int32_t *args)
291{
292 struct spm_partition_runtime_data_t *runtime_data =
293 &g_spm_partition_db.partitions[partition_idx].runtime_data;
294 size_t i;
295
296 if ((args[1] < 0) || (args[3] < 0)) {
297 return SPM_ERR_INVALID_PARAMETER;
298 }
299
300 runtime_data->iovec_args.in_len = (size_t)args[1];
301 for (i = 0U; i < runtime_data->iovec_args.in_len; ++i) {
302 runtime_data->iovec_args.in_vec[i].base =
303 ((psa_invec *)args[0])[i].base;
304 runtime_data->iovec_args.in_vec[i].len = ((psa_invec *)args[0])[i].len;
305 }
306 runtime_data->iovec_args.out_len = (size_t)args[3];
307 for (i = 0U; i < runtime_data->iovec_args.out_len; ++i) {
308 runtime_data->iovec_args.out_vec[i].base =
309 ((psa_outvec *)args[2])[i].base;
310 runtime_data->iovec_args.out_vec[i].len =
311 ((psa_outvec *)args[2])[i].len;
312 }
313 runtime_data->orig_outvec = (psa_outvec *)args[2];
314 runtime_data->iovec_api = 1;
315
316 return SPM_ERR_OK;
317}
318
319uint32_t tfm_spm_partition_get_running_partition_idx(void)
320{
321 return g_spm_partition_db.running_partition_idx;
322}
323
324void tfm_spm_partition_cleanup_context(uint32_t partition_idx)
325{
326 struct spm_partition_desc_t *partition =
327 &(g_spm_partition_db.partitions[partition_idx]);
328 int32_t i;
329
330 partition->runtime_data.caller_partition_idx = SPM_INVALID_PARTITION_IDX;
331 partition->runtime_data.share = 0;
332 partition->runtime_data.iovec_args.in_len = 0;
333 for (i = 0; i < PSA_MAX_IOVEC; ++i) {
334 partition->runtime_data.iovec_args.in_vec[i].base = 0;
335 partition->runtime_data.iovec_args.in_vec[i].len = 0;
336 }
337 partition->runtime_data.iovec_args.out_len = 0;
338 for (i = 0; i < PSA_MAX_IOVEC; ++i) {
339 partition->runtime_data.iovec_args.out_vec[i].base = 0;
340 partition->runtime_data.iovec_args.out_vec[i].len = 0;
341 }
342 partition->runtime_data.orig_outvec = 0;
343 partition->runtime_data.iovec_api = 0;
344}