blob: 60fd82d17f564cde1163e6d106d151ae4f268bc9 [file] [log] [blame]
Edison Ai764d41f2018-09-21 15:56:36 +08001/*
2 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
Mingyang Sunda01a972019-07-12 17:32:59 +08007
8/* All the APIs defined in this file are used for IPC model. */
9
Edison Ai764d41f2018-09-21 15:56:36 +080010#include <inttypes.h>
Summer Qin2bfd2a02018-09-26 17:10:41 +080011#include <limits.h>
Edison Ai764d41f2018-09-21 15:56:36 +080012#include <stdbool.h>
Edison Ai764d41f2018-09-21 15:56:36 +080013#include <stdlib.h>
Jamie Foxcc31d402019-01-28 17:13:52 +000014#include "psa/client.h"
15#include "psa/service.h"
Edison Ai764d41f2018-09-21 15:56:36 +080016#include "tfm_utils.h"
Mingyang Sunf3d29892019-07-10 17:50:23 +080017#include "tfm_spm_hal.h"
Edison Ai764d41f2018-09-21 15:56:36 +080018#include "spm_api.h"
19#include "spm_db.h"
David Hu326f3972019-08-06 14:16:51 +080020#include "tfm_core_mem_check.h"
Edison Ai764d41f2018-09-21 15:56:36 +080021#include "tfm_internal_defines.h"
22#include "tfm_wait.h"
23#include "tfm_message_queue.h"
24#include "tfm_list.h"
25#include "tfm_pools.h"
Edison Ai764d41f2018-09-21 15:56:36 +080026#include "tfm_thread.h"
Summer Qin2bfd2a02018-09-26 17:10:41 +080027#include "region_defs.h"
Edison Ai764d41f2018-09-21 15:56:36 +080028#include "tfm_nspm.h"
Edison Ai807fedb2019-03-07 11:22:03 +080029#include "tfm_memory_utils.h"
Edison Ai764d41f2018-09-21 15:56:36 +080030
Summer Qind99509f2019-08-02 17:36:58 +080031#include "secure_fw/services/tfm_service_list.inc"
32
33/* Extern service variable */
34extern struct tfm_spm_service_t service[];
35
Edison Ai764d41f2018-09-21 15:56:36 +080036/* Extern SPM variable */
37extern struct spm_partition_db_t g_spm_partition_db;
38
Mate Toth-Palc430b992019-05-09 21:01:14 +020039/* Extern secure lock variable */
40extern int32_t tfm_secure_lock;
Mingyang Sunf3d29892019-07-10 17:50:23 +080041
Edison Ai764d41f2018-09-21 15:56:36 +080042/* Pools */
43TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
44 TFM_CONN_HANDLE_MAX_NUM);
Edison Ai764d41f2018-09-21 15:56:36 +080045TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
46 TFM_MSG_QUEUE_MAX_MSG_NUM);
47
Edison Ai764d41f2018-09-21 15:56:36 +080048/********************** SPM functions for handler mode ***********************/
49
50/* Service handle management functions */
51psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
52{
53 struct tfm_conn_handle_t *node;
54
55 TFM_ASSERT(service);
56
57 /* Get buffer for handle list structure from handle pool */
58 node = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
59 if (!node) {
60 return PSA_NULL_HANDLE;
61 }
62
63 /* Global unique handle, use handle buffer address directly */
64 node->handle = (psa_handle_t)node;
65
66 /* Add handle node to list for next psa functions */
67 tfm_list_add_tail(&service->handle_list, &node->list);
68
69 return node->handle;
70}
71
72static struct tfm_conn_handle_t *
Mingyang Sun5e13aa72019-07-10 10:30:16 +080073 tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
74 psa_handle_t conn_handle)
Edison Ai764d41f2018-09-21 15:56:36 +080075{
76 struct tfm_conn_handle_t *handle_node;
77 struct tfm_list_node_t *node, *head;
78
79 TFM_ASSERT(service);
80
81 head = &service->handle_list;
82 TFM_LIST_FOR_EACH(node, head) {
83 handle_node = TFM_GET_CONTAINER_PTR(node, struct tfm_conn_handle_t,
84 list);
85 if (handle_node->handle == conn_handle) {
86 return handle_node;
87 }
88 }
89 return NULL;
90}
91
92int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
93 psa_handle_t conn_handle)
94{
95 struct tfm_conn_handle_t *node;
96
97 TFM_ASSERT(service);
98
99 /* There are many handles for each RoT Service */
100 node = tfm_spm_find_conn_handle_node(service, conn_handle);
101 if (!node) {
102 tfm_panic();
103 }
104
105 /* Remove node from handle list */
106 tfm_list_del_node(&node->list);
107
108 /* Back handle buffer to pool */
109 tfm_pool_free(node);
110 return IPC_SUCCESS;
111}
112
113int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
114 psa_handle_t conn_handle,
115 void *rhandle)
116{
117 struct tfm_conn_handle_t *node;
118
119 TFM_ASSERT(service);
120 /* Set reverse handle value only be allowed for a connected handle */
121 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
122
123 /* There are many handles for each RoT Service */
124 node = tfm_spm_find_conn_handle_node(service, conn_handle);
125 if (!node) {
126 tfm_panic();
127 }
128
129 node->rhandle = rhandle;
130 return IPC_SUCCESS;
131}
132
133void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
134 psa_handle_t conn_handle)
135{
136 struct tfm_conn_handle_t *node;
137
138 TFM_ASSERT(service);
139 /* Get reverse handle value only be allowed for a connected handle */
140 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
141
142 /* There are many handles for each RoT Service */
143 node = tfm_spm_find_conn_handle_node(service, conn_handle);
144 if (!node) {
145 tfm_panic();
146 }
147
148 return node->rhandle;
149}
150
151/* Partition management functions */
152struct tfm_spm_service_t *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800153 tfm_spm_get_service_by_signal(struct spm_partition_desc_t *partition,
154 psa_signal_t signal)
Edison Ai764d41f2018-09-21 15:56:36 +0800155{
156 struct tfm_list_node_t *node, *head;
157 struct tfm_spm_service_t *service;
158
159 TFM_ASSERT(partition);
160
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800161 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800162 tfm_panic();
163 }
164
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800165 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800166 TFM_LIST_FOR_EACH(node, head) {
167 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
Summer Qind99509f2019-08-02 17:36:58 +0800168 if (service->service_db.signal == signal) {
Edison Ai764d41f2018-09-21 15:56:36 +0800169 return service;
170 }
171 }
172 return NULL;
173}
174
175struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
176{
177 uint32_t i;
178 struct tfm_list_node_t *node, *head;
179 struct tfm_spm_service_t *service;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800180 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800181
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200182 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800183 partition = &g_spm_partition_db.partitions[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800184 /* Skip partition without IPC flag */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800185 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
Edison Ai764d41f2018-09-21 15:56:36 +0800186 continue;
187 }
188
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800189 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800190 continue;
191 }
192
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800193 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800194 TFM_LIST_FOR_EACH(node, head) {
195 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
196 list);
Summer Qind99509f2019-08-02 17:36:58 +0800197 if (service->service_db.sid == sid) {
Edison Ai764d41f2018-09-21 15:56:36 +0800198 return service;
199 }
200 }
201 }
202 return NULL;
203}
204
205struct tfm_spm_service_t *
206 tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
207{
208 uint32_t i;
209 struct tfm_conn_handle_t *handle;
210 struct tfm_list_node_t *service_node, *service_head;
211 struct tfm_list_node_t *handle_node, *handle_head;
212 struct tfm_spm_service_t *service;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800213 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800214
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200215 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800216 partition = &g_spm_partition_db.partitions[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800217 /* Skip partition without IPC flag */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800218 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
Edison Ai764d41f2018-09-21 15:56:36 +0800219 continue;
220 }
221
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800222 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800223 continue;
224 }
225
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800226 service_head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800227 TFM_LIST_FOR_EACH(service_node, service_head) {
228 service = TFM_GET_CONTAINER_PTR(service_node,
229 struct tfm_spm_service_t, list);
230 handle_head = &service->handle_list;
231 TFM_LIST_FOR_EACH(handle_node, handle_head) {
232 handle = TFM_GET_CONTAINER_PTR(handle_node,
233 struct tfm_conn_handle_t, list);
234 if (handle->handle == conn_handle) {
235 return service;
236 }
237 }
238 }
239 }
240 return NULL;
241}
242
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800243struct spm_partition_desc_t *tfm_spm_get_partition_by_id(int32_t partition_id)
Edison Ai764d41f2018-09-21 15:56:36 +0800244{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800245 uint32_t idx = get_partition_idx(partition_id);
Edison Ai764d41f2018-09-21 15:56:36 +0800246
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800247 if (idx != SPM_INVALID_PARTITION_IDX) {
248 return &(g_spm_partition_db.partitions[idx]);
Edison Ai764d41f2018-09-21 15:56:36 +0800249 }
250 return NULL;
251}
252
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800253struct spm_partition_desc_t *tfm_spm_get_running_partition(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800254{
255 uint32_t spid;
256
Mingyang Sunf3d29892019-07-10 17:50:23 +0800257 spid = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800258
259 return tfm_spm_get_partition_by_id(spid);
260}
261
262int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
263 uint32_t minor_version)
264{
265 TFM_ASSERT(service);
266
Summer Qind99509f2019-08-02 17:36:58 +0800267 switch (service->service_db.minor_policy) {
Edison Ai764d41f2018-09-21 15:56:36 +0800268 case TFM_VERSION_POLICY_RELAXED:
Summer Qind99509f2019-08-02 17:36:58 +0800269 if (minor_version > service->service_db.minor_version) {
Edison Ai764d41f2018-09-21 15:56:36 +0800270 return IPC_ERROR_VERSION;
271 }
272 break;
273 case TFM_VERSION_POLICY_STRICT:
Summer Qind99509f2019-08-02 17:36:58 +0800274 if (minor_version != service->service_db.minor_version) {
Edison Ai764d41f2018-09-21 15:56:36 +0800275 return IPC_ERROR_VERSION;
276 }
277 break;
278 default:
279 return IPC_ERROR_VERSION;
280 }
281 return IPC_SUCCESS;
282}
283
284/* Message functions */
285struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
286{
287 /*
288 * There may be one error handle passed by the caller in two conditions:
289 * 1. Not a valid message handle.
290 * 2. Handle between different Partitions. Partition A passes one handle
291 * belong to other Partitions and tries to access other's data.
292 * So, need do necessary checking to prevent those conditions.
293 */
294 struct tfm_msg_body_t *msg;
295 uint32_t partition_id;
296
297 msg = (struct tfm_msg_body_t *)msg_handle;
298 if (!msg) {
299 return NULL;
300 }
301
302 /*
303 * FixMe: For condition 1: using a magic number to define it's a message.
304 * It needs to be an enhancement to check the handle belong to service.
305 */
306 if (msg->magic != TFM_MSG_MAGIC) {
307 return NULL;
308 }
309
310 /* For condition 2: check if the partition ID is same */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800311 partition_id = tfm_spm_partition_get_running_partition_id();
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800312 if (partition_id != msg->service->partition->static_data.partition_id) {
Edison Ai764d41f2018-09-21 15:56:36 +0800313 return NULL;
314 }
315
316 return msg;
317}
318
319struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
320 psa_handle_t handle,
Summer Qin632b3e02019-07-29 15:34:38 +0800321 int32_t type, int32_t ns_caller,
Edison Ai764d41f2018-09-21 15:56:36 +0800322 psa_invec *invec, size_t in_len,
323 psa_outvec *outvec, size_t out_len,
324 psa_outvec *caller_outvec)
325{
326 struct tfm_msg_body_t *msg = NULL;
327 uint32_t i;
328
329 TFM_ASSERT(service);
330 TFM_ASSERT(!(invec == NULL && in_len != 0));
331 TFM_ASSERT(!(outvec == NULL && out_len != 0));
332 TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
333 TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
334 TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
335
336 /* Get message buffer from message pool */
337 msg = (struct tfm_msg_body_t *)tfm_pool_alloc(msg_db_pool);
338 if (!msg) {
339 return NULL;
340 }
341
342 /* Clear message buffer before using it */
343 tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
344
Ken Liu35f89392019-03-14 14:51:05 +0800345 tfm_event_init(&msg->ack_evnt);
Edison Ai764d41f2018-09-21 15:56:36 +0800346 msg->magic = TFM_MSG_MAGIC;
347 msg->service = service;
348 msg->handle = handle;
349 msg->caller_outvec = caller_outvec;
350 /* Get current partition id */
351 if (ns_caller) {
352 msg->msg.client_id = tfm_nspm_get_current_client_id();
353 } else {
Mingyang Sunf3d29892019-07-10 17:50:23 +0800354 msg->msg.client_id = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800355 }
356
357 /* Copy contents */
358 msg->msg.type = type;
359
360 for (i = 0; i < in_len; i++) {
361 msg->msg.in_size[i] = invec[i].len;
362 msg->invec[i].base = invec[i].base;
363 }
364
365 for (i = 0; i < out_len; i++) {
366 msg->msg.out_size[i] = outvec[i].len;
367 msg->outvec[i].base = outvec[i].base;
368 /* Out len is used to record the writed number, set 0 here again */
369 msg->outvec[i].len = 0;
370 }
371
372 /* Use message address as handle */
373 msg->msg.handle = (psa_handle_t)msg;
374
375 /* For connected handle, set rhandle to every message */
376 if (handle != PSA_NULL_HANDLE) {
377 msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
378 }
379
380 return msg;
381}
382
383void tfm_spm_free_msg(struct tfm_msg_body_t *msg)
384{
385 tfm_pool_free(msg);
386}
387
388int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
389 struct tfm_msg_body_t *msg)
390{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800391 struct spm_partition_runtime_data_t *p_runtime_data =
392 &service->partition->runtime_data;
393
Edison Ai764d41f2018-09-21 15:56:36 +0800394 TFM_ASSERT(service);
395 TFM_ASSERT(msg);
396
397 /* Enqueue message to service message queue */
398 if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
399 return IPC_ERROR_GENERIC;
400 }
401
402 /* Messages put. Update signals */
Summer Qind99509f2019-08-02 17:36:58 +0800403 p_runtime_data->signals |= service->service_db.signal;
Edison Ai764d41f2018-09-21 15:56:36 +0800404
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800405 tfm_event_wake(&p_runtime_data->signal_evnt, (p_runtime_data->signals &
406 p_runtime_data->signal_mask));
Edison Ai764d41f2018-09-21 15:56:36 +0800407
Ken Liu35f89392019-03-14 14:51:05 +0800408 tfm_event_wait(&msg->ack_evnt);
Edison Ai764d41f2018-09-21 15:56:36 +0800409
410 return IPC_SUCCESS;
411}
412
Edison Ai7aff9e82019-07-11 14:56:46 +0800413uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx)
414{
415 return g_spm_partition_db.partitions[partition_idx].
416 memory_data.stack_bottom;
417}
418
419uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx)
420{
421 return g_spm_partition_db.partitions[partition_idx].memory_data.stack_top;
422}
423
Mingyang Sunf3d29892019-07-10 17:50:23 +0800424uint32_t tfm_spm_partition_get_running_partition_id(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800425{
426 struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
427 struct spm_partition_desc_t *partition;
428
429 partition = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_desc_t,
430 sp_thrd);
431 return partition->static_data.partition_id;
432}
433
434static struct tfm_thrd_ctx *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800435 tfm_spm_partition_get_thread_info(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800436{
437 return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
438}
439
Edison Ai764d41f2018-09-21 15:56:36 +0800440static tfm_thrd_func_t
Mingyang Sunf3d29892019-07-10 17:50:23 +0800441 tfm_spm_partition_get_init_func(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800442{
443 return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
444 static_data.partition_init);
445}
446
Mingyang Sunf3d29892019-07-10 17:50:23 +0800447static uint32_t tfm_spm_partition_get_priority(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800448{
449 return g_spm_partition_db.partitions[partition_idx].static_data.
450 partition_priority;
451}
452
David Hucb05d972019-08-06 18:10:11 +0800453int32_t tfm_memory_check(const void *buffer, size_t len, int32_t ns_caller,
Summer Qineb537e52019-03-29 09:57:10 +0800454 enum tfm_memory_access_e access,
455 uint32_t privileged)
Summer Qin2bfd2a02018-09-26 17:10:41 +0800456{
Hugues de Valon99578562019-06-18 16:08:51 +0100457 enum tfm_status_e err;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800458
459 /* If len is zero, this indicates an empty buffer and base is ignored */
460 if (len == 0) {
461 return IPC_SUCCESS;
462 }
463
464 if (!buffer) {
465 return IPC_ERROR_BAD_PARAMETERS;
466 }
467
468 if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
469 return IPC_ERROR_MEMORY_CHECK;
470 }
471
Summer Qin424d4db2019-03-25 14:09:51 +0800472 if (access == TFM_MEMORY_ACCESS_RW) {
Summer Qineb537e52019-03-29 09:57:10 +0800473 err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
474 privileged);
Summer Qin2bfd2a02018-09-26 17:10:41 +0800475 } else {
Summer Qineb537e52019-03-29 09:57:10 +0800476 err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
477 privileged);
Summer Qin424d4db2019-03-25 14:09:51 +0800478 }
Summer Qin0fc3f592019-04-11 16:00:10 +0800479 if (err == TFM_SUCCESS) {
Summer Qin424d4db2019-03-25 14:09:51 +0800480 return IPC_SUCCESS;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800481 }
482
483 return IPC_ERROR_MEMORY_CHECK;
484}
485
Summer Qineb537e52019-03-29 09:57:10 +0800486uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx)
487{
488 if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) {
489 return TFM_PARTITION_PRIVILEGED_MODE;
490 } else {
491 return TFM_PARTITION_UNPRIVILEGED_MODE;
492 }
493}
494
Edison Ai764d41f2018-09-21 15:56:36 +0800495/********************** SPM functions for thread mode ************************/
496
497void tfm_spm_init(void)
498{
499 uint32_t i, num;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800500 struct spm_partition_desc_t *partition;
Summer Qind99509f2019-08-02 17:36:58 +0800501 /*struct tfm_spm_service_t *service;*/
Ken Liu483f5da2019-04-24 10:45:21 +0800502 struct tfm_thrd_ctx *pth, this_thrd;
Edison Ai764d41f2018-09-21 15:56:36 +0800503
504 tfm_pool_init(conn_handle_pool,
505 POOL_BUFFER_SIZE(conn_handle_pool),
506 sizeof(struct tfm_conn_handle_t),
507 TFM_CONN_HANDLE_MAX_NUM);
Edison Ai764d41f2018-09-21 15:56:36 +0800508 tfm_pool_init(msg_db_pool, POOL_BUFFER_SIZE(msg_db_pool),
509 sizeof(struct tfm_msg_body_t),
510 TFM_MSG_QUEUE_MAX_MSG_NUM);
511
512 /* Init partition first for it will be used when init service */
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200513 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800514 partition = &g_spm_partition_db.partitions[i];
515 tfm_spm_hal_configure_default_isolation(partition->platform_data);
516 partition->static_data.index = i;
Edison Ai764d41f2018-09-21 15:56:36 +0800517 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
518 continue;
519 }
Ken Liu35f89392019-03-14 14:51:05 +0800520
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800521 tfm_event_init(&partition->runtime_data.signal_evnt);
522 tfm_list_init(&partition->runtime_data.service_list);
Edison Ai764d41f2018-09-21 15:56:36 +0800523
Mingyang Sunf3d29892019-07-10 17:50:23 +0800524 pth = tfm_spm_partition_get_thread_info(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800525 if (!pth) {
526 tfm_panic();
527 }
528
529 tfm_thrd_init(pth,
Mingyang Sunf3d29892019-07-10 17:50:23 +0800530 tfm_spm_partition_get_init_func(i),
Edison Ai764d41f2018-09-21 15:56:36 +0800531 NULL,
Edison Ai788bae22019-02-18 17:38:59 +0800532 (uint8_t *)tfm_spm_partition_get_stack_top(i),
533 (uint8_t *)tfm_spm_partition_get_stack_bottom(i));
Edison Ai788bae22019-02-18 17:38:59 +0800534
Mingyang Sunf3d29892019-07-10 17:50:23 +0800535 pth->prior = tfm_spm_partition_get_priority(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800536
537 /* Kick off */
538 if (tfm_thrd_start(pth) != THRD_SUCCESS) {
539 tfm_panic();
540 }
541 }
542
543 /* Init Service */
Summer Qind99509f2019-08-02 17:36:58 +0800544 num = sizeof(service) / sizeof(struct tfm_spm_service_t);
Edison Ai764d41f2018-09-21 15:56:36 +0800545 for (i = 0; i < num; i++) {
546 partition =
Summer Qind99509f2019-08-02 17:36:58 +0800547 tfm_spm_get_partition_by_id(service[i].service_db.partition_id);
Edison Ai764d41f2018-09-21 15:56:36 +0800548 if (!partition) {
549 tfm_panic();
550 }
Summer Qind99509f2019-08-02 17:36:58 +0800551 service[i].partition = partition;
552 tfm_list_init(&service[i].handle_list);
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800553 tfm_list_add_tail(&partition->runtime_data.service_list,
Summer Qind99509f2019-08-02 17:36:58 +0800554 &service[i].list);
Edison Ai764d41f2018-09-21 15:56:36 +0800555 }
556
Ken Liu483f5da2019-04-24 10:45:21 +0800557 /*
558 * All threads initialized, start the scheduler.
559 *
560 * NOTE:
561 * Here is the booting privileged thread mode, and will never
562 * return to this place after scheduler is started. The start
563 * function has to save current runtime context to act as a
564 * 'current thread' to avoid repeating NULL 'current thread'
565 * checking while context switching. This saved context is worthy
566 * of being saved somewhere if there are potential usage purpose.
567 * Let's save this context in a local variable 'this_thrd' at
568 * current since there is no usage for it.
Mate Toth-Palc430b992019-05-09 21:01:14 +0200569 * Also set tfm_nspm_thread_entry as pfn for this thread to
570 * use in detecting NS/S thread scheduling changes.
Ken Liu483f5da2019-04-24 10:45:21 +0800571 */
Mate Toth-Palc430b992019-05-09 21:01:14 +0200572 this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry;
Ken Liu483f5da2019-04-24 10:45:21 +0800573 tfm_thrd_start_scheduler(&this_thrd);
Edison Ai764d41f2018-09-21 15:56:36 +0800574}
Ken Liu2d175172019-03-21 17:08:41 +0800575
576void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
577{
578#if TFM_LVL == 2
579 struct spm_partition_desc_t *p_next_partition;
580 uint32_t is_privileged;
581#endif
582 struct tfm_thrd_ctx *pth_next = tfm_thrd_next_thread();
583 struct tfm_thrd_ctx *pth_curr = tfm_thrd_curr_thread();
584
Mate Toth-Pal32b2ccd2019-04-26 10:00:16 +0200585 if (pth_next != NULL && pth_curr != pth_next) {
Ken Liu2d175172019-03-21 17:08:41 +0800586#if TFM_LVL == 2
587 p_next_partition = TFM_GET_CONTAINER_PTR(pth_next,
588 struct spm_partition_desc_t,
589 sp_thrd);
590
591 if (p_next_partition->static_data.partition_flags &
592 SPM_PART_FLAG_PSA_ROT) {
593 is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
594 } else {
595 is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
596 }
597
598 tfm_spm_partition_change_privilege(is_privileged);
599#endif
Mate Toth-Palc430b992019-05-09 21:01:14 +0200600 /* Increase the secure lock, if we enter secure from non-secure */
601 if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) {
602 ++tfm_secure_lock;
603 }
604 /* Decrease the secure lock, if we return from secure to non-secure */
605 if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) {
606 --tfm_secure_lock;
607 }
608
Ken Liu2d175172019-03-21 17:08:41 +0800609 tfm_thrd_context_switch(ctxb, pth_curr, pth_next);
610 }
611}