mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /*
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * SPDX-License-Identifier: BSD-3-Clause
kenjiArai 0:5b88d5760320 5 *
kenjiArai 0:5b88d5760320 6 */
kenjiArai 0:5b88d5760320 7 #include <inttypes.h>
kenjiArai 0:5b88d5760320 8 #include <limits.h>
kenjiArai 0:5b88d5760320 9 #include <stdbool.h>
kenjiArai 0:5b88d5760320 10 #include <stdio.h>
kenjiArai 0:5b88d5760320 11 #include <stdlib.h>
kenjiArai 0:5b88d5760320 12 #include "psa_client.h"
kenjiArai 0:5b88d5760320 13 #include "psa_service.h"
kenjiArai 0:5b88d5760320 14 #include "tfm_utils.h"
kenjiArai 0:5b88d5760320 15 #include "platform/include/tfm_spm_hal.h"
kenjiArai 0:5b88d5760320 16 #include "spm_api.h"
kenjiArai 0:5b88d5760320 17 #include "spm_db.h"
kenjiArai 0:5b88d5760320 18 #include "spm_db_setup.h"
kenjiArai 0:5b88d5760320 19 #include "tfm_internal_defines.h"
kenjiArai 0:5b88d5760320 20 #include "tfm_wait.h"
kenjiArai 0:5b88d5760320 21 #include "tfm_message_queue.h"
kenjiArai 0:5b88d5760320 22 #include "tfm_list.h"
kenjiArai 0:5b88d5760320 23 #include "tfm_pools.h"
kenjiArai 0:5b88d5760320 24 #include "tfm_spm.h"
kenjiArai 0:5b88d5760320 25 #include "tfm_spm_signal_defs.h"
kenjiArai 0:5b88d5760320 26 #include "tfm_thread.h"
kenjiArai 0:5b88d5760320 27 #include "region_defs.h"
kenjiArai 0:5b88d5760320 28 #include "tfm_nspm.h"
kenjiArai 0:5b88d5760320 29 #include "tfm_memory_utils.h"
kenjiArai 0:5b88d5760320 30
kenjiArai 0:5b88d5760320 31 /*
kenjiArai 0:5b88d5760320 32 * IPC partitions.
kenjiArai 0:5b88d5760320 33 * FixMe: Need to get align with spm_partition_db_t.
kenjiArai 0:5b88d5760320 34 */
kenjiArai 0:5b88d5760320 35 static struct tfm_spm_ipc_partition_t
kenjiArai 0:5b88d5760320 36 g_spm_ipc_partition[SPM_MAX_PARTITIONS] = {};
kenjiArai 0:5b88d5760320 37
kenjiArai 0:5b88d5760320 38 /* Extern SPM variable */
kenjiArai 0:5b88d5760320 39 extern struct spm_partition_db_t g_spm_partition_db;
kenjiArai 0:5b88d5760320 40
kenjiArai 0:5b88d5760320 41 /* Extern secure lock variable */
kenjiArai 0:5b88d5760320 42 extern int32_t tfm_secure_lock;
kenjiArai 0:5b88d5760320 43 /* Pools */
kenjiArai 0:5b88d5760320 44 TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
kenjiArai 0:5b88d5760320 45 TFM_CONN_HANDLE_MAX_NUM);
kenjiArai 0:5b88d5760320 46 TFM_POOL_DECLARE(spm_service_pool, sizeof(struct tfm_spm_service_t),
kenjiArai 0:5b88d5760320 47 TFM_SPM_MAX_ROT_SERV_NUM);
kenjiArai 0:5b88d5760320 48 TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
kenjiArai 0:5b88d5760320 49 TFM_MSG_QUEUE_MAX_MSG_NUM);
kenjiArai 0:5b88d5760320 50
kenjiArai 0:5b88d5760320 51 static struct tfm_spm_service_db_t g_spm_service_db[] = {
kenjiArai 0:5b88d5760320 52 #include "tfm_service_list.inc"
kenjiArai 0:5b88d5760320 53 };
kenjiArai 0:5b88d5760320 54
kenjiArai 0:5b88d5760320 55 /********************** SPM functions for handler mode ***********************/
kenjiArai 0:5b88d5760320 56
kenjiArai 0:5b88d5760320 57 /* Service handle management functions */
kenjiArai 0:5b88d5760320 58 psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
kenjiArai 0:5b88d5760320 59 {
kenjiArai 0:5b88d5760320 60 struct tfm_conn_handle_t *node;
kenjiArai 0:5b88d5760320 61
kenjiArai 0:5b88d5760320 62 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 63
kenjiArai 0:5b88d5760320 64 /* Get buffer for handle list structure from handle pool */
kenjiArai 0:5b88d5760320 65 node = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
kenjiArai 0:5b88d5760320 66 if (!node) {
kenjiArai 0:5b88d5760320 67 return PSA_NULL_HANDLE;
kenjiArai 0:5b88d5760320 68 }
kenjiArai 0:5b88d5760320 69
kenjiArai 0:5b88d5760320 70 /* Global unique handle, use handle buffer address directly */
kenjiArai 0:5b88d5760320 71 node->handle = (psa_handle_t)node;
kenjiArai 0:5b88d5760320 72
kenjiArai 0:5b88d5760320 73 /* Add handle node to list for next psa functions */
kenjiArai 0:5b88d5760320 74 tfm_list_add_tail(&service->handle_list, &node->list);
kenjiArai 0:5b88d5760320 75
kenjiArai 0:5b88d5760320 76 return node->handle;
kenjiArai 0:5b88d5760320 77 }
kenjiArai 0:5b88d5760320 78
kenjiArai 0:5b88d5760320 79 static struct tfm_conn_handle_t *
kenjiArai 0:5b88d5760320 80 tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
kenjiArai 0:5b88d5760320 81 psa_handle_t conn_handle)
kenjiArai 0:5b88d5760320 82 {
kenjiArai 0:5b88d5760320 83 struct tfm_conn_handle_t *handle_node;
kenjiArai 0:5b88d5760320 84 struct tfm_list_node_t *node, *head;
kenjiArai 0:5b88d5760320 85
kenjiArai 0:5b88d5760320 86 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 87
kenjiArai 0:5b88d5760320 88 head = &service->handle_list;
kenjiArai 0:5b88d5760320 89 TFM_LIST_FOR_EACH(node, head) {
kenjiArai 0:5b88d5760320 90 handle_node = TFM_GET_CONTAINER_PTR(node, struct tfm_conn_handle_t,
kenjiArai 0:5b88d5760320 91 list);
kenjiArai 0:5b88d5760320 92 if (handle_node->handle == conn_handle) {
kenjiArai 0:5b88d5760320 93 return handle_node;
kenjiArai 0:5b88d5760320 94 }
kenjiArai 0:5b88d5760320 95 }
kenjiArai 0:5b88d5760320 96 return NULL;
kenjiArai 0:5b88d5760320 97 }
kenjiArai 0:5b88d5760320 98
kenjiArai 0:5b88d5760320 99 int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
kenjiArai 0:5b88d5760320 100 psa_handle_t conn_handle)
kenjiArai 0:5b88d5760320 101 {
kenjiArai 0:5b88d5760320 102 struct tfm_conn_handle_t *node;
kenjiArai 0:5b88d5760320 103
kenjiArai 0:5b88d5760320 104 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 105
kenjiArai 0:5b88d5760320 106 /* There are many handles for each RoT Service */
kenjiArai 0:5b88d5760320 107 node = tfm_spm_find_conn_handle_node(service, conn_handle);
kenjiArai 0:5b88d5760320 108 if (!node) {
kenjiArai 0:5b88d5760320 109 tfm_panic();
kenjiArai 0:5b88d5760320 110 }
kenjiArai 0:5b88d5760320 111
kenjiArai 0:5b88d5760320 112 /* Remove node from handle list */
kenjiArai 0:5b88d5760320 113 tfm_list_del_node(&node->list);
kenjiArai 0:5b88d5760320 114
kenjiArai 0:5b88d5760320 115 node->rhandle = NULL;
kenjiArai 0:5b88d5760320 116
kenjiArai 0:5b88d5760320 117 /* Back handle buffer to pool */
kenjiArai 0:5b88d5760320 118 tfm_pool_free(node);
kenjiArai 0:5b88d5760320 119 return IPC_SUCCESS;
kenjiArai 0:5b88d5760320 120 }
kenjiArai 0:5b88d5760320 121
kenjiArai 0:5b88d5760320 122 int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
kenjiArai 0:5b88d5760320 123 psa_handle_t conn_handle,
kenjiArai 0:5b88d5760320 124 void *rhandle)
kenjiArai 0:5b88d5760320 125 {
kenjiArai 0:5b88d5760320 126 struct tfm_conn_handle_t *node;
kenjiArai 0:5b88d5760320 127
kenjiArai 0:5b88d5760320 128 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 129 /* Set reverse handle value only be allowed for a connected handle */
kenjiArai 0:5b88d5760320 130 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
kenjiArai 0:5b88d5760320 131
kenjiArai 0:5b88d5760320 132 /* There are many handles for each RoT Service */
kenjiArai 0:5b88d5760320 133 node = tfm_spm_find_conn_handle_node(service, conn_handle);
kenjiArai 0:5b88d5760320 134 if (!node) {
kenjiArai 0:5b88d5760320 135 tfm_panic();
kenjiArai 0:5b88d5760320 136 }
kenjiArai 0:5b88d5760320 137
kenjiArai 0:5b88d5760320 138 node->rhandle = rhandle;
kenjiArai 0:5b88d5760320 139 return IPC_SUCCESS;
kenjiArai 0:5b88d5760320 140 }
kenjiArai 0:5b88d5760320 141
kenjiArai 0:5b88d5760320 142 void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
kenjiArai 0:5b88d5760320 143 psa_handle_t conn_handle)
kenjiArai 0:5b88d5760320 144 {
kenjiArai 0:5b88d5760320 145 struct tfm_conn_handle_t *node;
kenjiArai 0:5b88d5760320 146
kenjiArai 0:5b88d5760320 147 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 148 /* Get reverse handle value only be allowed for a connected handle */
kenjiArai 0:5b88d5760320 149 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
kenjiArai 0:5b88d5760320 150
kenjiArai 0:5b88d5760320 151 /* There are many handles for each RoT Service */
kenjiArai 0:5b88d5760320 152 node = tfm_spm_find_conn_handle_node(service, conn_handle);
kenjiArai 0:5b88d5760320 153 if (!node) {
kenjiArai 0:5b88d5760320 154 tfm_panic();
kenjiArai 0:5b88d5760320 155 }
kenjiArai 0:5b88d5760320 156
kenjiArai 0:5b88d5760320 157 return node->rhandle;
kenjiArai 0:5b88d5760320 158 }
kenjiArai 0:5b88d5760320 159
kenjiArai 0:5b88d5760320 160 /* Partition management functions */
kenjiArai 0:5b88d5760320 161 struct tfm_spm_service_t *
kenjiArai 0:5b88d5760320 162 tfm_spm_get_service_by_signal(struct tfm_spm_ipc_partition_t *partition,
kenjiArai 0:5b88d5760320 163 psa_signal_t signal)
kenjiArai 0:5b88d5760320 164 {
kenjiArai 0:5b88d5760320 165 struct tfm_list_node_t *node, *head;
kenjiArai 0:5b88d5760320 166 struct tfm_spm_service_t *service;
kenjiArai 0:5b88d5760320 167
kenjiArai 0:5b88d5760320 168 TFM_ASSERT(partition);
kenjiArai 0:5b88d5760320 169
kenjiArai 0:5b88d5760320 170 if (tfm_list_is_empty(&partition->service_list)) {
kenjiArai 0:5b88d5760320 171 tfm_panic();
kenjiArai 0:5b88d5760320 172 }
kenjiArai 0:5b88d5760320 173
kenjiArai 0:5b88d5760320 174 head = &partition->service_list;
kenjiArai 0:5b88d5760320 175 TFM_LIST_FOR_EACH(node, head) {
kenjiArai 0:5b88d5760320 176 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
kenjiArai 0:5b88d5760320 177 if (service->service_db->signal == signal) {
kenjiArai 0:5b88d5760320 178 return service;
kenjiArai 0:5b88d5760320 179 }
kenjiArai 0:5b88d5760320 180 }
kenjiArai 0:5b88d5760320 181 return NULL;
kenjiArai 0:5b88d5760320 182 }
kenjiArai 0:5b88d5760320 183
kenjiArai 0:5b88d5760320 184 struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
kenjiArai 0:5b88d5760320 185 {
kenjiArai 0:5b88d5760320 186 uint32_t i;
kenjiArai 0:5b88d5760320 187 struct tfm_list_node_t *node, *head;
kenjiArai 0:5b88d5760320 188 struct tfm_spm_service_t *service;
kenjiArai 0:5b88d5760320 189
kenjiArai 0:5b88d5760320 190 for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
kenjiArai 0:5b88d5760320 191 /* Skip partition without IPC flag */
kenjiArai 0:5b88d5760320 192 if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
kenjiArai 0:5b88d5760320 193 SPM_PART_FLAG_IPC) == 0) {
kenjiArai 0:5b88d5760320 194 continue;
kenjiArai 0:5b88d5760320 195 }
kenjiArai 0:5b88d5760320 196
kenjiArai 0:5b88d5760320 197 if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
kenjiArai 0:5b88d5760320 198 continue;
kenjiArai 0:5b88d5760320 199 }
kenjiArai 0:5b88d5760320 200
kenjiArai 0:5b88d5760320 201 head = &g_spm_ipc_partition[i].service_list;
kenjiArai 0:5b88d5760320 202 TFM_LIST_FOR_EACH(node, head) {
kenjiArai 0:5b88d5760320 203 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
kenjiArai 0:5b88d5760320 204 list);
kenjiArai 0:5b88d5760320 205 if (service->service_db->sid == sid) {
kenjiArai 0:5b88d5760320 206 return service;
kenjiArai 0:5b88d5760320 207 }
kenjiArai 0:5b88d5760320 208 }
kenjiArai 0:5b88d5760320 209 }
kenjiArai 0:5b88d5760320 210 return NULL;
kenjiArai 0:5b88d5760320 211 }
kenjiArai 0:5b88d5760320 212
kenjiArai 0:5b88d5760320 213 struct tfm_spm_service_t *
kenjiArai 0:5b88d5760320 214 tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
kenjiArai 0:5b88d5760320 215 {
kenjiArai 0:5b88d5760320 216 uint32_t i;
kenjiArai 0:5b88d5760320 217 struct tfm_conn_handle_t *handle;
kenjiArai 0:5b88d5760320 218 struct tfm_list_node_t *service_node, *service_head;
kenjiArai 0:5b88d5760320 219 struct tfm_list_node_t *handle_node, *handle_head;
kenjiArai 0:5b88d5760320 220 struct tfm_spm_service_t *service;
kenjiArai 0:5b88d5760320 221
kenjiArai 0:5b88d5760320 222 for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
kenjiArai 0:5b88d5760320 223 /* Skip partition without IPC flag */
kenjiArai 0:5b88d5760320 224 if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
kenjiArai 0:5b88d5760320 225 SPM_PART_FLAG_IPC) == 0) {
kenjiArai 0:5b88d5760320 226 continue;
kenjiArai 0:5b88d5760320 227 }
kenjiArai 0:5b88d5760320 228
kenjiArai 0:5b88d5760320 229 if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
kenjiArai 0:5b88d5760320 230 continue;
kenjiArai 0:5b88d5760320 231 }
kenjiArai 0:5b88d5760320 232
kenjiArai 0:5b88d5760320 233 service_head = &g_spm_ipc_partition[i].service_list;
kenjiArai 0:5b88d5760320 234 TFM_LIST_FOR_EACH(service_node, service_head) {
kenjiArai 0:5b88d5760320 235 service = TFM_GET_CONTAINER_PTR(service_node,
kenjiArai 0:5b88d5760320 236 struct tfm_spm_service_t, list);
kenjiArai 0:5b88d5760320 237 handle_head = &service->handle_list;
kenjiArai 0:5b88d5760320 238 TFM_LIST_FOR_EACH(handle_node, handle_head) {
kenjiArai 0:5b88d5760320 239 handle = TFM_GET_CONTAINER_PTR(handle_node,
kenjiArai 0:5b88d5760320 240 struct tfm_conn_handle_t, list);
kenjiArai 0:5b88d5760320 241 if (handle->handle == conn_handle) {
kenjiArai 0:5b88d5760320 242 return service;
kenjiArai 0:5b88d5760320 243 }
kenjiArai 0:5b88d5760320 244 }
kenjiArai 0:5b88d5760320 245 }
kenjiArai 0:5b88d5760320 246 }
kenjiArai 0:5b88d5760320 247 return NULL;
kenjiArai 0:5b88d5760320 248 }
kenjiArai 0:5b88d5760320 249
kenjiArai 0:5b88d5760320 250 struct tfm_spm_ipc_partition_t *
kenjiArai 0:5b88d5760320 251 tfm_spm_get_partition_by_id(int32_t partition_id)
kenjiArai 0:5b88d5760320 252 {
kenjiArai 0:5b88d5760320 253 uint32_t i;
kenjiArai 0:5b88d5760320 254
kenjiArai 0:5b88d5760320 255 for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
kenjiArai 0:5b88d5760320 256 if (g_spm_ipc_partition[i].id == partition_id) {
kenjiArai 0:5b88d5760320 257 return &g_spm_ipc_partition[i];
kenjiArai 0:5b88d5760320 258 }
kenjiArai 0:5b88d5760320 259 }
kenjiArai 0:5b88d5760320 260 return NULL;
kenjiArai 0:5b88d5760320 261 }
kenjiArai 0:5b88d5760320 262
kenjiArai 0:5b88d5760320 263 struct tfm_spm_ipc_partition_t *tfm_spm_get_running_partition(void)
kenjiArai 0:5b88d5760320 264 {
kenjiArai 0:5b88d5760320 265 uint32_t spid;
kenjiArai 0:5b88d5760320 266
kenjiArai 0:5b88d5760320 267 spid = tfm_spm_partition_get_running_partition_id_ext();
kenjiArai 0:5b88d5760320 268
kenjiArai 0:5b88d5760320 269 return tfm_spm_get_partition_by_id(spid);
kenjiArai 0:5b88d5760320 270 }
kenjiArai 0:5b88d5760320 271
kenjiArai 0:5b88d5760320 272 int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
kenjiArai 0:5b88d5760320 273 uint32_t minor_version)
kenjiArai 0:5b88d5760320 274 {
kenjiArai 0:5b88d5760320 275 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 276
kenjiArai 0:5b88d5760320 277 switch (service->service_db->minor_policy) {
kenjiArai 0:5b88d5760320 278 case TFM_VERSION_POLICY_RELAXED:
kenjiArai 0:5b88d5760320 279 if (minor_version > service->service_db->minor_version) {
kenjiArai 0:5b88d5760320 280 return IPC_ERROR_VERSION;
kenjiArai 0:5b88d5760320 281 }
kenjiArai 0:5b88d5760320 282 break;
kenjiArai 0:5b88d5760320 283 case TFM_VERSION_POLICY_STRICT:
kenjiArai 0:5b88d5760320 284 if (minor_version != service->service_db->minor_version) {
kenjiArai 0:5b88d5760320 285 return IPC_ERROR_VERSION;
kenjiArai 0:5b88d5760320 286 }
kenjiArai 0:5b88d5760320 287 break;
kenjiArai 0:5b88d5760320 288 default:
kenjiArai 0:5b88d5760320 289 return IPC_ERROR_VERSION;
kenjiArai 0:5b88d5760320 290 }
kenjiArai 0:5b88d5760320 291 return IPC_SUCCESS;
kenjiArai 0:5b88d5760320 292 }
kenjiArai 0:5b88d5760320 293
kenjiArai 0:5b88d5760320 294 /* Message functions */
kenjiArai 0:5b88d5760320 295 struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
kenjiArai 0:5b88d5760320 296 {
kenjiArai 0:5b88d5760320 297 /*
kenjiArai 0:5b88d5760320 298 * There may be one error handle passed by the caller in two conditions:
kenjiArai 0:5b88d5760320 299 * 1. Not a valid message handle.
kenjiArai 0:5b88d5760320 300 * 2. Handle between different Partitions. Partition A passes one handle
kenjiArai 0:5b88d5760320 301 * belong to other Partitions and tries to access other's data.
kenjiArai 0:5b88d5760320 302 * So, need do necessary checking to prevent those conditions.
kenjiArai 0:5b88d5760320 303 */
kenjiArai 0:5b88d5760320 304 struct tfm_msg_body_t *msg;
kenjiArai 0:5b88d5760320 305 uint32_t partition_id;
kenjiArai 0:5b88d5760320 306
kenjiArai 0:5b88d5760320 307 msg = (struct tfm_msg_body_t *)msg_handle;
kenjiArai 0:5b88d5760320 308 if (!msg) {
kenjiArai 0:5b88d5760320 309 return NULL;
kenjiArai 0:5b88d5760320 310 }
kenjiArai 0:5b88d5760320 311
kenjiArai 0:5b88d5760320 312 /*
kenjiArai 0:5b88d5760320 313 * FixMe: For condition 1: using a magic number to define it's a message.
kenjiArai 0:5b88d5760320 314 * It needs to be an enhancement to check the handle belong to service.
kenjiArai 0:5b88d5760320 315 */
kenjiArai 0:5b88d5760320 316 if (msg->magic != TFM_MSG_MAGIC) {
kenjiArai 0:5b88d5760320 317 return NULL;
kenjiArai 0:5b88d5760320 318 }
kenjiArai 0:5b88d5760320 319
kenjiArai 0:5b88d5760320 320 /* For condition 2: check if the partition ID is same */
kenjiArai 0:5b88d5760320 321 partition_id = tfm_spm_partition_get_running_partition_id_ext();
kenjiArai 0:5b88d5760320 322 if (partition_id != msg->service->partition->id) {
kenjiArai 0:5b88d5760320 323 return NULL;
kenjiArai 0:5b88d5760320 324 }
kenjiArai 0:5b88d5760320 325
kenjiArai 0:5b88d5760320 326 return msg;
kenjiArai 0:5b88d5760320 327 }
kenjiArai 0:5b88d5760320 328
kenjiArai 0:5b88d5760320 329 struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
kenjiArai 0:5b88d5760320 330 psa_handle_t handle,
kenjiArai 0:5b88d5760320 331 uint32_t type, int32_t ns_caller,
kenjiArai 0:5b88d5760320 332 psa_invec *invec, size_t in_len,
kenjiArai 0:5b88d5760320 333 psa_outvec *outvec, size_t out_len,
kenjiArai 0:5b88d5760320 334 psa_outvec *caller_outvec)
kenjiArai 0:5b88d5760320 335 {
kenjiArai 0:5b88d5760320 336 struct tfm_msg_body_t *msg = NULL;
kenjiArai 0:5b88d5760320 337 uint32_t i;
kenjiArai 0:5b88d5760320 338
kenjiArai 0:5b88d5760320 339 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 340 TFM_ASSERT(!(invec == NULL && in_len != 0));
kenjiArai 0:5b88d5760320 341 TFM_ASSERT(!(outvec == NULL && out_len != 0));
kenjiArai 0:5b88d5760320 342 TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
kenjiArai 0:5b88d5760320 343 TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
kenjiArai 0:5b88d5760320 344 TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
kenjiArai 0:5b88d5760320 345
kenjiArai 0:5b88d5760320 346 /* Get message buffer from message pool */
kenjiArai 0:5b88d5760320 347 msg = (struct tfm_msg_body_t *)tfm_pool_alloc(msg_db_pool);
kenjiArai 0:5b88d5760320 348 if (!msg) {
kenjiArai 0:5b88d5760320 349 return NULL;
kenjiArai 0:5b88d5760320 350 }
kenjiArai 0:5b88d5760320 351
kenjiArai 0:5b88d5760320 352 /* Clear message buffer before using it */
kenjiArai 0:5b88d5760320 353 tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
kenjiArai 0:5b88d5760320 354
kenjiArai 0:5b88d5760320 355 tfm_event_init(&msg->ack_evnt);
kenjiArai 0:5b88d5760320 356 msg->magic = TFM_MSG_MAGIC;
kenjiArai 0:5b88d5760320 357 msg->service = service;
kenjiArai 0:5b88d5760320 358 msg->handle = handle;
kenjiArai 0:5b88d5760320 359 msg->caller_outvec = caller_outvec;
kenjiArai 0:5b88d5760320 360 /* Get current partition id */
kenjiArai 0:5b88d5760320 361 if (ns_caller) {
kenjiArai 0:5b88d5760320 362 msg->msg.client_id = tfm_nspm_get_current_client_id();
kenjiArai 0:5b88d5760320 363 } else {
kenjiArai 0:5b88d5760320 364 msg->msg.client_id = tfm_spm_partition_get_running_partition_id_ext();
kenjiArai 0:5b88d5760320 365 }
kenjiArai 0:5b88d5760320 366
kenjiArai 0:5b88d5760320 367 /* Copy contents */
kenjiArai 0:5b88d5760320 368 msg->msg.type = type;
kenjiArai 0:5b88d5760320 369
kenjiArai 0:5b88d5760320 370 for (i = 0; i < in_len; i++) {
kenjiArai 0:5b88d5760320 371 msg->msg.in_size[i] = invec[i].len;
kenjiArai 0:5b88d5760320 372 msg->invec[i].base = invec[i].base;
kenjiArai 0:5b88d5760320 373 }
kenjiArai 0:5b88d5760320 374
kenjiArai 0:5b88d5760320 375 for (i = 0; i < out_len; i++) {
kenjiArai 0:5b88d5760320 376 msg->msg.out_size[i] = outvec[i].len;
kenjiArai 0:5b88d5760320 377 msg->outvec[i].base = outvec[i].base;
kenjiArai 0:5b88d5760320 378 /* Out len is used to record the writed number, set 0 here again */
kenjiArai 0:5b88d5760320 379 msg->outvec[i].len = 0;
kenjiArai 0:5b88d5760320 380 }
kenjiArai 0:5b88d5760320 381
kenjiArai 0:5b88d5760320 382 /* Use message address as handle */
kenjiArai 0:5b88d5760320 383 msg->msg.handle = (psa_handle_t)msg;
kenjiArai 0:5b88d5760320 384
kenjiArai 0:5b88d5760320 385 /* For connected handle, set rhandle to every message */
kenjiArai 0:5b88d5760320 386 if (handle != PSA_NULL_HANDLE) {
kenjiArai 0:5b88d5760320 387 msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
kenjiArai 0:5b88d5760320 388 }
kenjiArai 0:5b88d5760320 389
kenjiArai 0:5b88d5760320 390 return msg;
kenjiArai 0:5b88d5760320 391 }
kenjiArai 0:5b88d5760320 392
kenjiArai 0:5b88d5760320 393 void tfm_spm_free_msg(struct tfm_msg_body_t *msg)
kenjiArai 0:5b88d5760320 394 {
kenjiArai 0:5b88d5760320 395 tfm_pool_free(msg);
kenjiArai 0:5b88d5760320 396 }
kenjiArai 0:5b88d5760320 397
kenjiArai 0:5b88d5760320 398 int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
kenjiArai 0:5b88d5760320 399 struct tfm_msg_body_t *msg)
kenjiArai 0:5b88d5760320 400 {
kenjiArai 0:5b88d5760320 401 TFM_ASSERT(service);
kenjiArai 0:5b88d5760320 402 TFM_ASSERT(msg);
kenjiArai 0:5b88d5760320 403
kenjiArai 0:5b88d5760320 404 /* Enqueue message to service message queue */
kenjiArai 0:5b88d5760320 405 if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
kenjiArai 0:5b88d5760320 406 return IPC_ERROR_GENERIC;
kenjiArai 0:5b88d5760320 407 }
kenjiArai 0:5b88d5760320 408
kenjiArai 0:5b88d5760320 409 /* Messages put. Update signals */
kenjiArai 0:5b88d5760320 410 service->partition->signals |= service->service_db->signal;
kenjiArai 0:5b88d5760320 411
kenjiArai 0:5b88d5760320 412 tfm_event_wake(&service->partition->signal_evnt,
kenjiArai 0:5b88d5760320 413 (service->partition->signals &
kenjiArai 0:5b88d5760320 414 service->partition->signal_mask));
kenjiArai 0:5b88d5760320 415
kenjiArai 0:5b88d5760320 416 tfm_event_wait(&msg->ack_evnt);
kenjiArai 0:5b88d5760320 417
kenjiArai 0:5b88d5760320 418 return IPC_SUCCESS;
kenjiArai 0:5b88d5760320 419 }
kenjiArai 0:5b88d5760320 420
kenjiArai 0:5b88d5760320 421 /* SPM extend functions */
kenjiArai 0:5b88d5760320 422 uint32_t tfm_spm_partition_get_running_partition_id_ext(void)
kenjiArai 0:5b88d5760320 423 {
kenjiArai 0:5b88d5760320 424 struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
kenjiArai 0:5b88d5760320 425 struct spm_partition_desc_t *partition;
kenjiArai 0:5b88d5760320 426
kenjiArai 0:5b88d5760320 427 partition = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_desc_t,
kenjiArai 0:5b88d5760320 428 sp_thrd);
kenjiArai 0:5b88d5760320 429 return partition->static_data.partition_id;
kenjiArai 0:5b88d5760320 430 }
kenjiArai 0:5b88d5760320 431
kenjiArai 0:5b88d5760320 432 static struct tfm_thrd_ctx *
kenjiArai 0:5b88d5760320 433 tfm_spm_partition_get_thread_info_ext(uint32_t partition_idx)
kenjiArai 0:5b88d5760320 434 {
kenjiArai 0:5b88d5760320 435 return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
kenjiArai 0:5b88d5760320 436 }
kenjiArai 0:5b88d5760320 437
kenjiArai 0:5b88d5760320 438 static tfm_thrd_func_t
kenjiArai 0:5b88d5760320 439 tfm_spm_partition_get_init_func_ext(uint32_t partition_idx)
kenjiArai 0:5b88d5760320 440 {
kenjiArai 0:5b88d5760320 441 return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
kenjiArai 0:5b88d5760320 442 static_data.partition_init);
kenjiArai 0:5b88d5760320 443 }
kenjiArai 0:5b88d5760320 444
kenjiArai 0:5b88d5760320 445 static uint32_t tfm_spm_partition_get_priority_ext(uint32_t partition_idx)
kenjiArai 0:5b88d5760320 446 {
kenjiArai 0:5b88d5760320 447 return g_spm_partition_db.partitions[partition_idx].static_data.
kenjiArai 0:5b88d5760320 448 partition_priority;
kenjiArai 0:5b88d5760320 449 }
kenjiArai 0:5b88d5760320 450
kenjiArai 0:5b88d5760320 451 int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
kenjiArai 0:5b88d5760320 452 enum tfm_memory_access_e access,
kenjiArai 0:5b88d5760320 453 uint32_t privileged)
kenjiArai 0:5b88d5760320 454 {
kenjiArai 0:5b88d5760320 455 int32_t err;
kenjiArai 0:5b88d5760320 456
kenjiArai 0:5b88d5760320 457 /* If len is zero, this indicates an empty buffer and base is ignored */
kenjiArai 0:5b88d5760320 458 if (len == 0) {
kenjiArai 0:5b88d5760320 459 return IPC_SUCCESS;
kenjiArai 0:5b88d5760320 460 }
kenjiArai 0:5b88d5760320 461
kenjiArai 0:5b88d5760320 462 if (!buffer) {
kenjiArai 0:5b88d5760320 463 return IPC_ERROR_BAD_PARAMETERS;
kenjiArai 0:5b88d5760320 464 }
kenjiArai 0:5b88d5760320 465
kenjiArai 0:5b88d5760320 466 if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
kenjiArai 0:5b88d5760320 467 return IPC_ERROR_MEMORY_CHECK;
kenjiArai 0:5b88d5760320 468 }
kenjiArai 0:5b88d5760320 469
kenjiArai 0:5b88d5760320 470 if (access == TFM_MEMORY_ACCESS_RW) {
kenjiArai 0:5b88d5760320 471 err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
kenjiArai 0:5b88d5760320 472 privileged);
kenjiArai 0:5b88d5760320 473 } else {
kenjiArai 0:5b88d5760320 474 err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
kenjiArai 0:5b88d5760320 475 privileged);
kenjiArai 0:5b88d5760320 476 }
kenjiArai 0:5b88d5760320 477 if (err == TFM_SUCCESS) {
kenjiArai 0:5b88d5760320 478 return IPC_SUCCESS;
kenjiArai 0:5b88d5760320 479 }
kenjiArai 0:5b88d5760320 480
kenjiArai 0:5b88d5760320 481 return IPC_ERROR_MEMORY_CHECK;
kenjiArai 0:5b88d5760320 482 }
kenjiArai 0:5b88d5760320 483
kenjiArai 0:5b88d5760320 484 uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx)
kenjiArai 0:5b88d5760320 485 {
kenjiArai 0:5b88d5760320 486 if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) {
kenjiArai 0:5b88d5760320 487 return TFM_PARTITION_PRIVILEGED_MODE;
kenjiArai 0:5b88d5760320 488 } else {
kenjiArai 0:5b88d5760320 489 return TFM_PARTITION_UNPRIVILEGED_MODE;
kenjiArai 0:5b88d5760320 490 }
kenjiArai 0:5b88d5760320 491 }
kenjiArai 0:5b88d5760320 492
kenjiArai 0:5b88d5760320 493 /********************** SPM functions for thread mode ************************/
kenjiArai 0:5b88d5760320 494
kenjiArai 0:5b88d5760320 495 void tfm_spm_init(void)
kenjiArai 0:5b88d5760320 496 {
kenjiArai 0:5b88d5760320 497 uint32_t i, num;
kenjiArai 0:5b88d5760320 498 struct tfm_spm_ipc_partition_t *partition;
kenjiArai 0:5b88d5760320 499 struct tfm_spm_service_t *service;
kenjiArai 0:5b88d5760320 500 struct tfm_thrd_ctx *pth, this_thrd;
kenjiArai 0:5b88d5760320 501 struct spm_partition_desc_t *part;
kenjiArai 0:5b88d5760320 502
kenjiArai 0:5b88d5760320 503 tfm_pool_init(conn_handle_pool,
kenjiArai 0:5b88d5760320 504 POOL_BUFFER_SIZE(conn_handle_pool),
kenjiArai 0:5b88d5760320 505 sizeof(struct tfm_conn_handle_t),
kenjiArai 0:5b88d5760320 506 TFM_CONN_HANDLE_MAX_NUM);
kenjiArai 0:5b88d5760320 507 tfm_pool_init(spm_service_pool, POOL_BUFFER_SIZE(spm_service_pool),
kenjiArai 0:5b88d5760320 508 sizeof(struct tfm_spm_service_t),
kenjiArai 0:5b88d5760320 509 TFM_SPM_MAX_ROT_SERV_NUM);
kenjiArai 0:5b88d5760320 510 tfm_pool_init(msg_db_pool, POOL_BUFFER_SIZE(msg_db_pool),
kenjiArai 0:5b88d5760320 511 sizeof(struct tfm_msg_body_t),
kenjiArai 0:5b88d5760320 512 TFM_MSG_QUEUE_MAX_MSG_NUM);
kenjiArai 0:5b88d5760320 513
kenjiArai 0:5b88d5760320 514 /* Init partition first for it will be used when init service */
kenjiArai 0:5b88d5760320 515 for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
kenjiArai 0:5b88d5760320 516 part = &g_spm_partition_db.partitions[i];
kenjiArai 0:5b88d5760320 517 tfm_spm_hal_configure_default_isolation(part->platform_data);
kenjiArai 0:5b88d5760320 518 g_spm_ipc_partition[i].index = i;
kenjiArai 0:5b88d5760320 519 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
kenjiArai 0:5b88d5760320 520 continue;
kenjiArai 0:5b88d5760320 521 }
kenjiArai 0:5b88d5760320 522 g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i);
kenjiArai 0:5b88d5760320 523
kenjiArai 0:5b88d5760320 524 tfm_event_init(&g_spm_ipc_partition[i].signal_evnt);
kenjiArai 0:5b88d5760320 525 tfm_list_init(&g_spm_ipc_partition[i].service_list);
kenjiArai 0:5b88d5760320 526
kenjiArai 0:5b88d5760320 527 pth = tfm_spm_partition_get_thread_info_ext(i);
kenjiArai 0:5b88d5760320 528 if (!pth) {
kenjiArai 0:5b88d5760320 529 tfm_panic();
kenjiArai 0:5b88d5760320 530 }
kenjiArai 0:5b88d5760320 531
kenjiArai 0:5b88d5760320 532 tfm_thrd_init(pth,
kenjiArai 0:5b88d5760320 533 tfm_spm_partition_get_init_func_ext(i),
kenjiArai 0:5b88d5760320 534 NULL,
kenjiArai 0:5b88d5760320 535 (uint8_t *)tfm_spm_partition_get_stack_top(i),
kenjiArai 0:5b88d5760320 536 (uint8_t *)tfm_spm_partition_get_stack_bottom(i));
kenjiArai 0:5b88d5760320 537
kenjiArai 0:5b88d5760320 538 pth->prior = tfm_spm_partition_get_priority_ext(i);
kenjiArai 0:5b88d5760320 539
kenjiArai 0:5b88d5760320 540 /* Kick off */
kenjiArai 0:5b88d5760320 541 if (tfm_thrd_start(pth) != THRD_SUCCESS) {
kenjiArai 0:5b88d5760320 542 tfm_panic();
kenjiArai 0:5b88d5760320 543 }
kenjiArai 0:5b88d5760320 544 }
kenjiArai 0:5b88d5760320 545
kenjiArai 0:5b88d5760320 546 /* Init Service */
kenjiArai 0:5b88d5760320 547 num = sizeof(g_spm_service_db) / sizeof(struct tfm_spm_service_db_t);
kenjiArai 0:5b88d5760320 548 for (i = 0; i < num; i++) {
kenjiArai 0:5b88d5760320 549 partition =
kenjiArai 0:5b88d5760320 550 tfm_spm_get_partition_by_id(g_spm_service_db[i].partition_id);
kenjiArai 0:5b88d5760320 551 if (!partition) {
kenjiArai 0:5b88d5760320 552 tfm_panic();
kenjiArai 0:5b88d5760320 553 }
kenjiArai 0:5b88d5760320 554 service = (struct tfm_spm_service_t *)tfm_pool_alloc(spm_service_pool);
kenjiArai 0:5b88d5760320 555 if (!service) {
kenjiArai 0:5b88d5760320 556 tfm_panic();
kenjiArai 0:5b88d5760320 557 }
kenjiArai 0:5b88d5760320 558 service->service_db = &g_spm_service_db[i];
kenjiArai 0:5b88d5760320 559 service->partition = partition;
kenjiArai 0:5b88d5760320 560 tfm_list_init(&service->handle_list);
kenjiArai 0:5b88d5760320 561 tfm_list_add_tail(&partition->service_list, &service->list);
kenjiArai 0:5b88d5760320 562 }
kenjiArai 0:5b88d5760320 563
kenjiArai 0:5b88d5760320 564 /*
kenjiArai 0:5b88d5760320 565 * All threads initialized, start the scheduler.
kenjiArai 0:5b88d5760320 566 *
kenjiArai 0:5b88d5760320 567 * NOTE:
kenjiArai 0:5b88d5760320 568 * Here is the booting privileged thread mode, and will never
kenjiArai 0:5b88d5760320 569 * return to this place after scheduler is started. The start
kenjiArai 0:5b88d5760320 570 * function has to save current runtime context to act as a
kenjiArai 0:5b88d5760320 571 * 'current thread' to avoid repeating NULL 'current thread'
kenjiArai 0:5b88d5760320 572 * checking while context switching. This saved context is worthy
kenjiArai 0:5b88d5760320 573 * of being saved somewhere if there are potential usage purpose.
kenjiArai 0:5b88d5760320 574 * Let's save this context in a local variable 'this_thrd' at
kenjiArai 0:5b88d5760320 575 * current since there is no usage for it.
kenjiArai 0:5b88d5760320 576 * Also set tfm_nspm_thread_entry as pfn for this thread to
kenjiArai 0:5b88d5760320 577 * use in detecting NS/S thread scheduling changes.
kenjiArai 0:5b88d5760320 578 */
kenjiArai 0:5b88d5760320 579 this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry;
kenjiArai 0:5b88d5760320 580 tfm_thrd_start_scheduler(&this_thrd);
kenjiArai 0:5b88d5760320 581 }
kenjiArai 0:5b88d5760320 582
kenjiArai 0:5b88d5760320 583 void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
kenjiArai 0:5b88d5760320 584 {
kenjiArai 0:5b88d5760320 585 #if TFM_LVL == 2
kenjiArai 0:5b88d5760320 586 struct spm_partition_desc_t *p_next_partition;
kenjiArai 0:5b88d5760320 587 uint32_t is_privileged;
kenjiArai 0:5b88d5760320 588 #endif
kenjiArai 0:5b88d5760320 589 struct tfm_thrd_ctx *pth_next = tfm_thrd_next_thread();
kenjiArai 0:5b88d5760320 590 struct tfm_thrd_ctx *pth_curr = tfm_thrd_curr_thread();
kenjiArai 0:5b88d5760320 591
kenjiArai 0:5b88d5760320 592 if (pth_curr != pth_next) {
kenjiArai 0:5b88d5760320 593 #if TFM_LVL == 2
kenjiArai 0:5b88d5760320 594 p_next_partition = TFM_GET_CONTAINER_PTR(pth_next,
kenjiArai 0:5b88d5760320 595 struct spm_partition_desc_t,
kenjiArai 0:5b88d5760320 596 sp_thrd);
kenjiArai 0:5b88d5760320 597
kenjiArai 0:5b88d5760320 598 if (p_next_partition->static_data.partition_flags &
kenjiArai 0:5b88d5760320 599 SPM_PART_FLAG_PSA_ROT) {
kenjiArai 0:5b88d5760320 600 is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
kenjiArai 0:5b88d5760320 601 } else {
kenjiArai 0:5b88d5760320 602 is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
kenjiArai 0:5b88d5760320 603 }
kenjiArai 0:5b88d5760320 604
kenjiArai 0:5b88d5760320 605 tfm_spm_partition_change_privilege(is_privileged);
kenjiArai 0:5b88d5760320 606 #endif
kenjiArai 0:5b88d5760320 607 /* Increase the secure lock, if we enter secure from non-secure */
kenjiArai 0:5b88d5760320 608 if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) {
kenjiArai 0:5b88d5760320 609 ++tfm_secure_lock;
kenjiArai 0:5b88d5760320 610 }
kenjiArai 0:5b88d5760320 611 /* Decrease the secure lock, if we return from secure to non-secure */
kenjiArai 0:5b88d5760320 612 if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) {
kenjiArai 0:5b88d5760320 613 --tfm_secure_lock;
kenjiArai 0:5b88d5760320 614 }
kenjiArai 0:5b88d5760320 615
kenjiArai 0:5b88d5760320 616 tfm_thrd_context_switch(ctxb, pth_curr, pth_next);
kenjiArai 0:5b88d5760320 617 }
kenjiArai 0:5b88d5760320 618 }