blob: 58a0fd37c8acdad739efd03fc4f1c6dc55f54f6c [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"
Mingyang Sun94b1b412019-09-20 15:11:14 +080030#include "tfm_core_utils.h"
David Hufb38d562019-09-23 15:58:34 +080031#include "tfm_rpc.h"
Shawn Shan9b0e0c72019-10-22 13:43:07 +080032#include "tfm_irq_list.h"
Edison Ai764d41f2018-09-21 15:56:36 +080033
Summer Qind99509f2019-08-02 17:36:58 +080034#include "secure_fw/services/tfm_service_list.inc"
35
36/* Extern service variable */
37extern struct tfm_spm_service_t service[];
Summer Qine578c5b2019-08-16 16:42:16 +080038extern const struct tfm_spm_service_db_t service_db[];
Summer Qind99509f2019-08-02 17:36:58 +080039
Edison Ai764d41f2018-09-21 15:56:36 +080040/* Extern SPM variable */
41extern struct spm_partition_db_t g_spm_partition_db;
42
Mate Toth-Palc430b992019-05-09 21:01:14 +020043/* Extern secure lock variable */
44extern int32_t tfm_secure_lock;
Mingyang Sunf3d29892019-07-10 17:50:23 +080045
Edison Ai764d41f2018-09-21 15:56:36 +080046/* Pools */
47TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
48 TFM_CONN_HANDLE_MAX_NUM);
Edison Ai764d41f2018-09-21 15:56:36 +080049
Edison Ai764d41f2018-09-21 15:56:36 +080050/********************** SPM functions for handler mode ***********************/
51
52/* Service handle management functions */
53psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
54{
Edison Ai9cc26242019-08-06 11:28:04 +080055 struct tfm_conn_handle_t *p_handle;
Edison Ai764d41f2018-09-21 15:56:36 +080056
57 TFM_ASSERT(service);
58
59 /* Get buffer for handle list structure from handle pool */
Edison Ai9cc26242019-08-06 11:28:04 +080060 p_handle = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
61 if (!p_handle) {
Edison Ai764d41f2018-09-21 15:56:36 +080062 return PSA_NULL_HANDLE;
63 }
64
Edison Ai9cc26242019-08-06 11:28:04 +080065 p_handle->service = service;
Shawn Shancc39fcb2019-11-13 15:38:16 +080066 p_handle->status = TFM_HANDLE_STATUS_IDLE;
Edison Ai764d41f2018-09-21 15:56:36 +080067
68 /* Add handle node to list for next psa functions */
Edison Ai9cc26242019-08-06 11:28:04 +080069 tfm_list_add_tail(&service->handle_list, &p_handle->list);
Edison Ai764d41f2018-09-21 15:56:36 +080070
Edison Ai9cc26242019-08-06 11:28:04 +080071 return (psa_handle_t)p_handle;
Edison Ai764d41f2018-09-21 15:56:36 +080072}
73
74static struct tfm_conn_handle_t *
Mingyang Sun5e13aa72019-07-10 10:30:16 +080075 tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
76 psa_handle_t conn_handle)
Edison Ai764d41f2018-09-21 15:56:36 +080077{
Edison Ai764d41f2018-09-21 15:56:36 +080078 TFM_ASSERT(service);
79
Edison Ai9cc26242019-08-06 11:28:04 +080080 return (struct tfm_conn_handle_t *)conn_handle;
Edison Ai764d41f2018-09-21 15:56:36 +080081}
82
83int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
84 psa_handle_t conn_handle)
85{
Edison Ai9cc26242019-08-06 11:28:04 +080086 struct tfm_conn_handle_t *p_handle;
Edison Ai764d41f2018-09-21 15:56:36 +080087
88 TFM_ASSERT(service);
89
90 /* There are many handles for each RoT Service */
Edison Ai9cc26242019-08-06 11:28:04 +080091 p_handle = tfm_spm_find_conn_handle_node(service, conn_handle);
92 if (!p_handle) {
Edison Ai764d41f2018-09-21 15:56:36 +080093 tfm_panic();
94 }
95
Mate Toth-Pala4b5d242019-09-23 09:14:47 +020096 /* Clear magic as the handler is not used anymore */
97 p_handle->internal_msg.magic = 0;
98
Edison Ai764d41f2018-09-21 15:56:36 +080099 /* Remove node from handle list */
Edison Ai9cc26242019-08-06 11:28:04 +0800100 tfm_list_del_node(&p_handle->list);
Edison Ai764d41f2018-09-21 15:56:36 +0800101
102 /* Back handle buffer to pool */
Edison Ai9cc26242019-08-06 11:28:04 +0800103 tfm_pool_free(p_handle);
Edison Ai764d41f2018-09-21 15:56:36 +0800104 return IPC_SUCCESS;
105}
106
107int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
108 psa_handle_t conn_handle,
109 void *rhandle)
110{
Edison Ai9cc26242019-08-06 11:28:04 +0800111 struct tfm_conn_handle_t *p_handle;
Edison Ai764d41f2018-09-21 15:56:36 +0800112
113 TFM_ASSERT(service);
114 /* Set reverse handle value only be allowed for a connected handle */
115 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
116
117 /* There are many handles for each RoT Service */
Edison Ai9cc26242019-08-06 11:28:04 +0800118 p_handle = tfm_spm_find_conn_handle_node(service, conn_handle);
119 if (!p_handle) {
Edison Ai764d41f2018-09-21 15:56:36 +0800120 tfm_panic();
121 }
122
Edison Ai9cc26242019-08-06 11:28:04 +0800123 p_handle->rhandle = rhandle;
Edison Ai764d41f2018-09-21 15:56:36 +0800124 return IPC_SUCCESS;
125}
126
127void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
128 psa_handle_t conn_handle)
129{
Edison Ai9cc26242019-08-06 11:28:04 +0800130 struct tfm_conn_handle_t *p_handle;
Edison Ai764d41f2018-09-21 15:56:36 +0800131
132 TFM_ASSERT(service);
133 /* Get reverse handle value only be allowed for a connected handle */
134 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
135
136 /* There are many handles for each RoT Service */
Edison Ai9cc26242019-08-06 11:28:04 +0800137 p_handle = tfm_spm_find_conn_handle_node(service, conn_handle);
138 if (!p_handle) {
Edison Ai764d41f2018-09-21 15:56:36 +0800139 tfm_panic();
140 }
141
Edison Ai9cc26242019-08-06 11:28:04 +0800142 return p_handle->rhandle;
Edison Ai764d41f2018-09-21 15:56:36 +0800143}
144
145/* Partition management functions */
146struct tfm_spm_service_t *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800147 tfm_spm_get_service_by_signal(struct spm_partition_desc_t *partition,
148 psa_signal_t signal)
Edison Ai764d41f2018-09-21 15:56:36 +0800149{
150 struct tfm_list_node_t *node, *head;
151 struct tfm_spm_service_t *service;
152
153 TFM_ASSERT(partition);
154
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800155 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800156 tfm_panic();
157 }
158
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800159 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800160 TFM_LIST_FOR_EACH(node, head) {
161 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
Summer Qine578c5b2019-08-16 16:42:16 +0800162 if (service->service_db->signal == signal) {
Edison Ai764d41f2018-09-21 15:56:36 +0800163 return service;
164 }
165 }
166 return NULL;
167}
168
169struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
170{
171 uint32_t i;
172 struct tfm_list_node_t *node, *head;
173 struct tfm_spm_service_t *service;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800174 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800175
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200176 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800177 partition = &g_spm_partition_db.partitions[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800178 /* Skip partition without IPC flag */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800179 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
Edison Ai764d41f2018-09-21 15:56:36 +0800180 continue;
181 }
182
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800183 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800184 continue;
185 }
186
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800187 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800188 TFM_LIST_FOR_EACH(node, head) {
189 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
190 list);
Summer Qine578c5b2019-08-16 16:42:16 +0800191 if (service->service_db->sid == sid) {
Edison Ai764d41f2018-09-21 15:56:36 +0800192 return service;
193 }
194 }
195 }
196 return NULL;
197}
198
199struct tfm_spm_service_t *
200 tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
201{
Edison Ai9cc26242019-08-06 11:28:04 +0800202 return ((struct tfm_conn_handle_t *)conn_handle)->service;
Edison Ai764d41f2018-09-21 15:56:36 +0800203}
204
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800205struct spm_partition_desc_t *tfm_spm_get_partition_by_id(int32_t partition_id)
Edison Ai764d41f2018-09-21 15:56:36 +0800206{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800207 uint32_t idx = get_partition_idx(partition_id);
Edison Ai764d41f2018-09-21 15:56:36 +0800208
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800209 if (idx != SPM_INVALID_PARTITION_IDX) {
210 return &(g_spm_partition_db.partitions[idx]);
Edison Ai764d41f2018-09-21 15:56:36 +0800211 }
212 return NULL;
213}
214
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800215struct spm_partition_desc_t *tfm_spm_get_running_partition(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800216{
217 uint32_t spid;
218
Mingyang Sunf3d29892019-07-10 17:50:23 +0800219 spid = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800220
221 return tfm_spm_get_partition_by_id(spid);
222}
223
224int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530225 uint32_t version)
Edison Ai764d41f2018-09-21 15:56:36 +0800226{
227 TFM_ASSERT(service);
228
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530229 switch (service->service_db->version_policy) {
Edison Ai764d41f2018-09-21 15:56:36 +0800230 case TFM_VERSION_POLICY_RELAXED:
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530231 if (version > service->service_db->version) {
Edison Ai764d41f2018-09-21 15:56:36 +0800232 return IPC_ERROR_VERSION;
233 }
234 break;
235 case TFM_VERSION_POLICY_STRICT:
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530236 if (version != service->service_db->version) {
Edison Ai764d41f2018-09-21 15:56:36 +0800237 return IPC_ERROR_VERSION;
238 }
239 break;
240 default:
241 return IPC_ERROR_VERSION;
242 }
243 return IPC_SUCCESS;
244}
245
246/* Message functions */
247struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
248{
249 /*
Mate Toth-Pala4b5d242019-09-23 09:14:47 +0200250 * The message handler passed by the caller is considered invalid in the
251 * following cases:
252 * 1. Not a valid message handle. (The address of a message is not the
253 * address of a possible handle from the pool
254 * 2. Handle not belongs to the caller partition (The handle is either
255 * unused, or owned by anither partition)
256 * Check the conditions above
Edison Ai764d41f2018-09-21 15:56:36 +0800257 */
Mate Toth-Pala4b5d242019-09-23 09:14:47 +0200258 struct tfm_conn_handle_t *connection_handle_address;
Edison Ai764d41f2018-09-21 15:56:36 +0800259 struct tfm_msg_body_t *msg;
260 uint32_t partition_id;
261
262 msg = (struct tfm_msg_body_t *)msg_handle;
Mate Toth-Pala4b5d242019-09-23 09:14:47 +0200263
264 connection_handle_address =
265 TFM_GET_CONTAINER_PTR(msg, struct tfm_conn_handle_t, internal_msg);
266
267 if (is_valid_chunk_data_in_pool(
268 conn_handle_pool, (uint8_t *)connection_handle_address) != 1) {
Edison Ai764d41f2018-09-21 15:56:36 +0800269 return NULL;
270 }
271
272 /*
Mate Toth-Pala4b5d242019-09-23 09:14:47 +0200273 * Check that the magic number is correct. This proves that the message
274 * structure contains an active message.
Edison Ai764d41f2018-09-21 15:56:36 +0800275 */
276 if (msg->magic != TFM_MSG_MAGIC) {
277 return NULL;
278 }
279
Mate Toth-Pala4b5d242019-09-23 09:14:47 +0200280 /* Check that the running partition owns the message */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800281 partition_id = tfm_spm_partition_get_running_partition_id();
Summer Qin423dbef2019-08-22 15:59:35 +0800282 if (partition_id != msg->service->partition->static_data->partition_id) {
Edison Ai764d41f2018-09-21 15:56:36 +0800283 return NULL;
284 }
285
Mate Toth-Pala4b5d242019-09-23 09:14:47 +0200286 /*
287 * FixMe: For condition 1 it should be checked whether the message belongs
288 * to the service. Skipping this check isn't a security risk as even if the
289 * message belongs to another service, the handle belongs to the calling
290 * partition.
291 */
292
Edison Ai764d41f2018-09-21 15:56:36 +0800293 return msg;
294}
295
Edison Ai97115822019-08-01 14:22:19 +0800296struct tfm_msg_body_t *
297 tfm_spm_get_msg_buffer_from_conn_handle(psa_handle_t conn_handle)
Edison Ai764d41f2018-09-21 15:56:36 +0800298{
Edison Ai97115822019-08-01 14:22:19 +0800299 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
300
301 return &(((struct tfm_conn_handle_t *)conn_handle)->internal_msg);
302}
303
304void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
305 struct tfm_spm_service_t *service,
306 psa_handle_t handle,
307 int32_t type, int32_t ns_caller,
308 psa_invec *invec, size_t in_len,
309 psa_outvec *outvec, size_t out_len,
310 psa_outvec *caller_outvec)
311{
Edison Ai764d41f2018-09-21 15:56:36 +0800312 uint32_t i;
313
Edison Ai97115822019-08-01 14:22:19 +0800314 TFM_ASSERT(msg);
Edison Ai764d41f2018-09-21 15:56:36 +0800315 TFM_ASSERT(service);
316 TFM_ASSERT(!(invec == NULL && in_len != 0));
317 TFM_ASSERT(!(outvec == NULL && out_len != 0));
318 TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
319 TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
320 TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
321
Edison Ai764d41f2018-09-21 15:56:36 +0800322 /* Clear message buffer before using it */
Mingyang Sun94b1b412019-09-20 15:11:14 +0800323 tfm_core_util_memset(msg, 0, sizeof(struct tfm_msg_body_t));
Edison Ai764d41f2018-09-21 15:56:36 +0800324
Ken Liu35f89392019-03-14 14:51:05 +0800325 tfm_event_init(&msg->ack_evnt);
Edison Ai764d41f2018-09-21 15:56:36 +0800326 msg->magic = TFM_MSG_MAGIC;
327 msg->service = service;
328 msg->handle = handle;
329 msg->caller_outvec = caller_outvec;
330 /* Get current partition id */
331 if (ns_caller) {
332 msg->msg.client_id = tfm_nspm_get_current_client_id();
333 } else {
Mingyang Sunf3d29892019-07-10 17:50:23 +0800334 msg->msg.client_id = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800335 }
336
337 /* Copy contents */
338 msg->msg.type = type;
339
340 for (i = 0; i < in_len; i++) {
341 msg->msg.in_size[i] = invec[i].len;
342 msg->invec[i].base = invec[i].base;
343 }
344
345 for (i = 0; i < out_len; i++) {
346 msg->msg.out_size[i] = outvec[i].len;
347 msg->outvec[i].base = outvec[i].base;
348 /* Out len is used to record the writed number, set 0 here again */
349 msg->outvec[i].len = 0;
350 }
351
352 /* Use message address as handle */
353 msg->msg.handle = (psa_handle_t)msg;
354
355 /* For connected handle, set rhandle to every message */
356 if (handle != PSA_NULL_HANDLE) {
357 msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
358 }
Edison Ai764d41f2018-09-21 15:56:36 +0800359}
360
361int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
362 struct tfm_msg_body_t *msg)
363{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800364 struct spm_partition_runtime_data_t *p_runtime_data =
365 &service->partition->runtime_data;
366
Edison Ai764d41f2018-09-21 15:56:36 +0800367 TFM_ASSERT(service);
368 TFM_ASSERT(msg);
369
370 /* Enqueue message to service message queue */
371 if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
372 return IPC_ERROR_GENERIC;
373 }
374
375 /* Messages put. Update signals */
Summer Qine578c5b2019-08-16 16:42:16 +0800376 p_runtime_data->signals |= service->service_db->signal;
Edison Ai764d41f2018-09-21 15:56:36 +0800377
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800378 tfm_event_wake(&p_runtime_data->signal_evnt, (p_runtime_data->signals &
379 p_runtime_data->signal_mask));
Edison Ai764d41f2018-09-21 15:56:36 +0800380
David Hufb38d562019-09-23 15:58:34 +0800381 /*
382 * If it is a NS request via RPC, it is unnecessary to block current
383 * thread.
384 */
385 if (!is_tfm_rpc_msg(msg)) {
386 tfm_event_wait(&msg->ack_evnt);
387 }
Edison Ai764d41f2018-09-21 15:56:36 +0800388
389 return IPC_SUCCESS;
390}
391
Edison Ai7aff9e82019-07-11 14:56:46 +0800392uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx)
393{
394 return g_spm_partition_db.partitions[partition_idx].
Summer Qin423dbef2019-08-22 15:59:35 +0800395 memory_data->stack_bottom;
Edison Ai7aff9e82019-07-11 14:56:46 +0800396}
397
398uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx)
399{
Summer Qin423dbef2019-08-22 15:59:35 +0800400 return g_spm_partition_db.partitions[partition_idx].memory_data->stack_top;
Edison Ai7aff9e82019-07-11 14:56:46 +0800401}
402
Mingyang Sunf3d29892019-07-10 17:50:23 +0800403uint32_t tfm_spm_partition_get_running_partition_id(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800404{
405 struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
406 struct spm_partition_desc_t *partition;
Summer Qinb5da9cc2019-08-26 15:19:45 +0800407 struct spm_partition_runtime_data_t *r_data;
Edison Ai764d41f2018-09-21 15:56:36 +0800408
Summer Qinb5da9cc2019-08-26 15:19:45 +0800409 r_data = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_runtime_data_t,
410 sp_thrd);
411 partition = TFM_GET_CONTAINER_PTR(r_data, struct spm_partition_desc_t,
412 runtime_data);
Summer Qin423dbef2019-08-22 15:59:35 +0800413 return partition->static_data->partition_id;
Edison Ai764d41f2018-09-21 15:56:36 +0800414}
415
416static struct tfm_thrd_ctx *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800417 tfm_spm_partition_get_thread_info(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800418{
Summer Qinb5da9cc2019-08-26 15:19:45 +0800419 return &g_spm_partition_db.partitions[partition_idx].runtime_data.sp_thrd;
Edison Ai764d41f2018-09-21 15:56:36 +0800420}
421
Edison Ai764d41f2018-09-21 15:56:36 +0800422static tfm_thrd_func_t
Mingyang Sunf3d29892019-07-10 17:50:23 +0800423 tfm_spm_partition_get_init_func(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800424{
425 return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
Summer Qin423dbef2019-08-22 15:59:35 +0800426 static_data->partition_init);
Edison Ai764d41f2018-09-21 15:56:36 +0800427}
428
Mingyang Sunf3d29892019-07-10 17:50:23 +0800429static uint32_t tfm_spm_partition_get_priority(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800430{
Summer Qin423dbef2019-08-22 15:59:35 +0800431 return g_spm_partition_db.partitions[partition_idx].static_data->
Edison Ai764d41f2018-09-21 15:56:36 +0800432 partition_priority;
433}
434
David Hucb05d972019-08-06 18:10:11 +0800435int32_t tfm_memory_check(const void *buffer, size_t len, int32_t ns_caller,
Summer Qineb537e52019-03-29 09:57:10 +0800436 enum tfm_memory_access_e access,
437 uint32_t privileged)
Summer Qin2bfd2a02018-09-26 17:10:41 +0800438{
Hugues de Valon99578562019-06-18 16:08:51 +0100439 enum tfm_status_e err;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800440
441 /* If len is zero, this indicates an empty buffer and base is ignored */
442 if (len == 0) {
443 return IPC_SUCCESS;
444 }
445
446 if (!buffer) {
447 return IPC_ERROR_BAD_PARAMETERS;
448 }
449
450 if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
451 return IPC_ERROR_MEMORY_CHECK;
452 }
453
Summer Qin424d4db2019-03-25 14:09:51 +0800454 if (access == TFM_MEMORY_ACCESS_RW) {
Summer Qineb537e52019-03-29 09:57:10 +0800455 err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
456 privileged);
Summer Qin2bfd2a02018-09-26 17:10:41 +0800457 } else {
Summer Qineb537e52019-03-29 09:57:10 +0800458 err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
459 privileged);
Summer Qin424d4db2019-03-25 14:09:51 +0800460 }
Summer Qin0fc3f592019-04-11 16:00:10 +0800461 if (err == TFM_SUCCESS) {
Summer Qin424d4db2019-03-25 14:09:51 +0800462 return IPC_SUCCESS;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800463 }
464
465 return IPC_ERROR_MEMORY_CHECK;
466}
467
Summer Qin75f0d752019-08-27 14:38:20 +0800468uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags)
Summer Qineb537e52019-03-29 09:57:10 +0800469{
Summer Qin75f0d752019-08-27 14:38:20 +0800470 if (partition_flags & SPM_PART_FLAG_PSA_ROT) {
Summer Qineb537e52019-03-29 09:57:10 +0800471 return TFM_PARTITION_PRIVILEGED_MODE;
472 } else {
473 return TFM_PARTITION_UNPRIVILEGED_MODE;
474 }
475}
476
Edison Ai764d41f2018-09-21 15:56:36 +0800477/********************** SPM functions for thread mode ************************/
478
479void tfm_spm_init(void)
480{
Shawn Shan9b0e0c72019-10-22 13:43:07 +0800481 uint32_t i, j, num;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800482 struct spm_partition_desc_t *partition;
Ken Liu483f5da2019-04-24 10:45:21 +0800483 struct tfm_thrd_ctx *pth, this_thrd;
Edison Ai764d41f2018-09-21 15:56:36 +0800484
485 tfm_pool_init(conn_handle_pool,
486 POOL_BUFFER_SIZE(conn_handle_pool),
487 sizeof(struct tfm_conn_handle_t),
488 TFM_CONN_HANDLE_MAX_NUM);
Edison Ai764d41f2018-09-21 15:56:36 +0800489
490 /* Init partition first for it will be used when init service */
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200491 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800492 partition = &g_spm_partition_db.partitions[i];
Edison Aif0501702019-10-11 14:36:42 +0800493
494 /* Check if the PSA framework version matches. */
495 if (partition->static_data->psa_framework_version !=
496 PSA_FRAMEWORK_VERSION) {
497 ERROR_MSG("Warning: PSA Framework Verison is not matched!");
498 continue;
499 }
500
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800501 tfm_spm_hal_configure_default_isolation(partition->platform_data);
Edison Ai764d41f2018-09-21 15:56:36 +0800502 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
503 continue;
504 }
Ken Liu35f89392019-03-14 14:51:05 +0800505
Shawn Shan9b0e0c72019-10-22 13:43:07 +0800506 /* TODO: This can be optimized by generating the assigned signal
507 * in code generation time.
508 */
509 for (j = 0; j < tfm_core_irq_signals_count; ++j) {
510 if (tfm_core_irq_signals[j].partition_id ==
511 partition->static_data->partition_id) {
512 partition->runtime_data.assigned_signals |=
513 tfm_core_irq_signals[j].signal_value;
514 }
515 }
516
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800517 tfm_event_init(&partition->runtime_data.signal_evnt);
518 tfm_list_init(&partition->runtime_data.service_list);
Edison Ai764d41f2018-09-21 15:56:36 +0800519
Mingyang Sunf3d29892019-07-10 17:50:23 +0800520 pth = tfm_spm_partition_get_thread_info(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800521 if (!pth) {
522 tfm_panic();
523 }
524
525 tfm_thrd_init(pth,
Mingyang Sunf3d29892019-07-10 17:50:23 +0800526 tfm_spm_partition_get_init_func(i),
Edison Ai764d41f2018-09-21 15:56:36 +0800527 NULL,
Ken Liu5a2b9052019-08-15 19:03:29 +0800528 (uintptr_t)tfm_spm_partition_get_stack_top(i),
529 (uintptr_t)tfm_spm_partition_get_stack_bottom(i));
Edison Ai788bae22019-02-18 17:38:59 +0800530
Mingyang Sunf3d29892019-07-10 17:50:23 +0800531 pth->prior = tfm_spm_partition_get_priority(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800532
533 /* Kick off */
534 if (tfm_thrd_start(pth) != THRD_SUCCESS) {
535 tfm_panic();
536 }
537 }
538
539 /* Init Service */
Summer Qind99509f2019-08-02 17:36:58 +0800540 num = sizeof(service) / sizeof(struct tfm_spm_service_t);
Edison Ai764d41f2018-09-21 15:56:36 +0800541 for (i = 0; i < num; i++) {
Summer Qine578c5b2019-08-16 16:42:16 +0800542 service[i].service_db = &service_db[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800543 partition =
Summer Qine578c5b2019-08-16 16:42:16 +0800544 tfm_spm_get_partition_by_id(service[i].service_db->partition_id);
Edison Ai764d41f2018-09-21 15:56:36 +0800545 if (!partition) {
546 tfm_panic();
547 }
Summer Qind99509f2019-08-02 17:36:58 +0800548 service[i].partition = partition;
Shawn Shan9b0e0c72019-10-22 13:43:07 +0800549 partition->runtime_data.assigned_signals |= service->service_db->signal;
550
Summer Qind99509f2019-08-02 17:36:58 +0800551 tfm_list_init(&service[i].handle_list);
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800552 tfm_list_add_tail(&partition->runtime_data.service_list,
Summer Qind99509f2019-08-02 17:36:58 +0800553 &service[i].list);
Edison Ai764d41f2018-09-21 15:56:36 +0800554 }
555
Ken Liu483f5da2019-04-24 10:45:21 +0800556 /*
557 * All threads initialized, start the scheduler.
558 *
559 * NOTE:
560 * Here is the booting privileged thread mode, and will never
561 * return to this place after scheduler is started. The start
562 * function has to save current runtime context to act as a
563 * 'current thread' to avoid repeating NULL 'current thread'
564 * checking while context switching. This saved context is worthy
565 * of being saved somewhere if there are potential usage purpose.
566 * Let's save this context in a local variable 'this_thrd' at
567 * current since there is no usage for it.
Mate Toth-Palc430b992019-05-09 21:01:14 +0200568 * Also set tfm_nspm_thread_entry as pfn for this thread to
569 * use in detecting NS/S thread scheduling changes.
Ken Liu483f5da2019-04-24 10:45:21 +0800570 */
Mate Toth-Palc430b992019-05-09 21:01:14 +0200571 this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry;
Ken Liu483f5da2019-04-24 10:45:21 +0800572 tfm_thrd_start_scheduler(&this_thrd);
Edison Ai764d41f2018-09-21 15:56:36 +0800573}
Ken Liu2d175172019-03-21 17:08:41 +0800574
575void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
576{
577#if TFM_LVL == 2
578 struct spm_partition_desc_t *p_next_partition;
Summer Qinb5da9cc2019-08-26 15:19:45 +0800579 struct spm_partition_runtime_data_t *r_data;
Ken Liu2d175172019-03-21 17:08:41 +0800580 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
Summer Qinb5da9cc2019-08-26 15:19:45 +0800587 r_data = TFM_GET_CONTAINER_PTR(pth_next,
588 struct spm_partition_runtime_data_t,
589 sp_thrd);
590 p_next_partition = TFM_GET_CONTAINER_PTR(r_data,
Ken Liu2d175172019-03-21 17:08:41 +0800591 struct spm_partition_desc_t,
Summer Qinb5da9cc2019-08-26 15:19:45 +0800592 runtime_data);
Ken Liu2d175172019-03-21 17:08:41 +0800593
Summer Qin423dbef2019-08-22 15:59:35 +0800594 if (p_next_partition->static_data->partition_flags &
Ken Liu2d175172019-03-21 17:08:41 +0800595 SPM_PART_FLAG_PSA_ROT) {
596 is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
597 } else {
598 is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
599 }
600
601 tfm_spm_partition_change_privilege(is_privileged);
602#endif
Mate Toth-Palc430b992019-05-09 21:01:14 +0200603 /* Increase the secure lock, if we enter secure from non-secure */
604 if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) {
605 ++tfm_secure_lock;
606 }
607 /* Decrease the secure lock, if we return from secure to non-secure */
608 if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) {
609 --tfm_secure_lock;
610 }
611
Ken Liu2d175172019-03-21 17:08:41 +0800612 tfm_thrd_context_switch(ctxb, pth_curr, pth_next);
613 }
David Hufb38d562019-09-23 15:58:34 +0800614
615 /*
616 * Handle pending mailbox message from NS in multi-core topology.
617 * Empty operation on single Armv8-M platform.
618 */
619 tfm_rpc_client_call_handler();
Ken Liu2d175172019-03-21 17:08:41 +0800620}