blob: 62715db6db13936629ecbeffd3248e58ad048054 [file] [log] [blame]
David Hu733d8f92019-09-23 15:32:40 +08001/*
Mingyang Sunbb4a42a2021-12-14 15:18:52 +08002 * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
David Hu733d8f92019-09-23 15:32:40 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
Mingyang Suneeca4652021-07-15 15:19:16 +08008#include <stdint.h>
Mingyang Sunb26b2802021-07-07 11:25:00 +08009#include "bitops.h"
Mingyang Sun4609ac72022-02-08 18:56:35 +080010#include "config_impl.h"
Ken Liu92ede9f2021-10-20 09:35:00 +080011#include "critical_section.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080012#include "psa/lifecycle.h"
David Hu733d8f92019-09-23 15:32:40 +080013#include "psa/service.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080014#include "interrupt.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080015#include "spm_ipc.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080016#include "tfm_arch.h"
David Hu733d8f92019-09-23 15:32:40 +080017#include "tfm_core_utils.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080018#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080019#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080020#include "load/interrupt_defs.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080021#include "ffm/psa_api.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080022#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080023#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080024#include "ffm/psa_api.h"
Ken Liubcae38b2021-01-20 15:47:44 +080025#include "ffm/spm_error_base.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080026#include "tfm_rpc.h"
27#include "tfm_spm_hal.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080028#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080029#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080030#include "tfm_psa_call_pack.h"
David Hu733d8f92019-09-23 15:32:40 +080031
Ken Liub3b2cb62021-05-22 00:39:28 +080032#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080033extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080034
Shawn Shan038348e2021-09-08 17:11:04 +080035#if PSA_FRAMEWORK_HAS_MM_IOVEC
36
37/*
38 * The MM-IOVEC status
39 * The max total number of invec and outvec is 8.
40 * Each invec/outvec takes 4 bit, 32 bits in total.
41 *
42 * The encoding format of the MM-IOVEC status:
43 *--------------------------------------------------------------
44 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
45 *--------------------------------------------------------------
46 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
47 *--------------------------------------------------------------
48 *
49 * Take invec[0] as an example:
50 *
51 * bit 0: whether invec[0] has been mapped.
52 * bit 1: whether invec[0] has been unmapped.
53 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
54 * psa_write().
55 * bit 3: reserved for invec[0].
56 */
57
58#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
59#define OUTVEC_IDX_BASE 4 /*
60 * Base index of outvec.
61 * There are four invecs in front of
62 * outvec.
63 */
64#define INVEC_IDX_BASE 0 /* Base index of invec. */
65
66#define IOVEC_MAPPED_BIT (1U << 0)
67#define IOVEC_UNMAPPED_BIT (1U << 1)
68#define IOVEC_ACCESSED_BIT (1U << 2)
69
70#define IOVEC_IS_MAPPED(msg, iovec_idx) \
71 ((((msg)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
72 IOVEC_MAPPED_BIT)
73#define IOVEC_IS_UNMAPPED(msg, iovec_idx) \
74 ((((msg)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
75 IOVEC_UNMAPPED_BIT)
76#define IOVEC_IS_ACCESSED(msg, iovec_idx) \
77 ((((msg)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
78 IOVEC_ACCESSED_BIT)
79#define SET_IOVEC_MAPPED(msg, iovec_idx) \
80 (((msg)->iovec_status) |= (IOVEC_MAPPED_BIT << \
81 ((iovec_idx) * IOVEC_STATUS_BITS)))
82#define SET_IOVEC_UNMAPPED(msg, iovec_idx) \
83 (((msg)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
84 ((iovec_idx) * IOVEC_STATUS_BITS)))
85#define SET_IOVEC_ACCESSED(msg, iovec_idx) \
86 (((msg)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
87 ((iovec_idx) * IOVEC_STATUS_BITS)))
88
89#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
90
Xinyu Zhangb287ef82021-11-03 18:38:50 +080091void spm_handle_programmer_errors(psa_status_t status)
92{
93 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
94 status == PSA_ERROR_CONNECTION_REFUSED ||
95 status == PSA_ERROR_CONNECTION_BUSY) {
96 if (!tfm_spm_is_ns_caller()) {
97 tfm_core_panic();
98 }
99 }
100}
101
Mingyang Suneeca4652021-07-15 15:19:16 +0800102uint32_t tfm_spm_get_lifecycle_state(void)
103{
104 /*
105 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
106 * implemented in the future.
107 */
108 return PSA_LIFECYCLE_UNKNOWN;
109}
110
111/* PSA Client API function body */
112
Mingyang Sund44522a2020-01-16 16:48:37 +0800113uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800114{
115 return PSA_FRAMEWORK_VERSION;
116}
117
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800118uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800119{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800120 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800121 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800122
123 /*
124 * It should return PSA_VERSION_NONE if the RoT Service is not
125 * implemented.
126 */
127 service = tfm_spm_get_service_by_sid(sid);
128 if (!service) {
129 return PSA_VERSION_NONE;
130 }
131
132 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800133 * It should return PSA_VERSION_NONE if the caller is not authorized
134 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800135 */
Ken Liubcae38b2021-01-20 15:47:44 +0800136 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800137 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800138 }
139
Ken Liuacd2a572021-05-12 16:19:04 +0800140 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800141}
142
Mingyang Suneeca4652021-07-15 15:19:16 +0800143psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
144 uint32_t ctrl_param,
145 const psa_invec *inptr,
146 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800147{
148 psa_invec invecs[PSA_MAX_IOVEC];
149 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800150 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800151 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800152 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800153 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800154 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800155 uint32_t privileged;
Mingyang Sun620c8562021-11-10 11:44:58 +0800156 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800157 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800158 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
159 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
160 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800161
162 /* The request type must be zero or positive. */
163 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800164 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800165 }
David Hu733d8f92019-09-23 15:32:40 +0800166
Shawn Shanb222d892021-01-04 17:41:48 +0800167 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800168 if ((in_num > PSA_MAX_IOVEC) ||
169 (out_num > PSA_MAX_IOVEC) ||
170 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800171 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800172 }
173
Kevin Peng385fda82021-08-18 10:41:19 +0800174 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800175
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800176 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800177 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800178 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800179
180 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800181 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800182 }
183
Mingyang Sun453ad402021-03-17 17:58:33 +0800184 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800185 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800186 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800187 }
188
Ken Liub3b2cb62021-05-22 00:39:28 +0800189 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800190
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800191 /*
192 * It is a PROGRAMMER ERROR if the caller is not authorized to access
193 * the RoT Service.
194 */
195 if (tfm_spm_check_authorization(sid, service, ns_caller)
196 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800197 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800198 }
199
Mingyang Sun453ad402021-03-17 17:58:33 +0800200 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
201
202 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800203 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800204 }
205
Mingyang Sun620c8562021-11-10 11:44:58 +0800206 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800207 conn_handle = tfm_spm_create_conn_handle(service, client_id);
Mingyang Sun620c8562021-11-10 11:44:58 +0800208 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800209
210 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800211 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800212 }
213
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800214 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800215 handle = tfm_spm_to_user_handle(conn_handle);
216 } else {
217 conn_handle = tfm_spm_to_handle_instance(handle);
218
219 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
220 if (tfm_spm_validate_conn_handle(conn_handle, client_id)
221 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800222 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800223 }
224
225 /*
226 * It is a PROGRAMMER ERROR if the connection is currently
227 * handling a request.
228 */
229 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800230 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800231 }
232
233 /*
234 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
235 * has been terminated by the RoT Service.
236 */
237 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
238 return PSA_ERROR_PROGRAMMER_ERROR;
239 }
240
Ken Liu0bed7e02022-02-10 12:38:07 +0800241 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800242
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800243 if (!service) {
244 /* FixMe: Need to implement a mechanism to resolve this failure. */
245 return PSA_ERROR_PROGRAMMER_ERROR;
246 }
David Hu733d8f92019-09-23 15:32:40 +0800247 }
248
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800249 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800250
Kevin Pengedb8ee42021-03-09 16:50:11 +0800251 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800252 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800253 * if the memory reference for the wrap input vector is invalid or not
254 * readable.
255 */
256 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800257 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800258 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800259 }
Summer Qinba2346e2019-11-12 16:26:31 +0800260
David Hu733d8f92019-09-23 15:32:40 +0800261 /*
262 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800263 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800264 * the wrap output vector is invalid or not read-write.
265 */
266 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800267 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800268 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800269 }
270
Summer Qinf24dbb52020-07-23 14:53:54 +0800271 spm_memset(invecs, 0, sizeof(invecs));
272 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800273
274 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800275 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
276 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800277
278 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800279 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800280 * memory reference was invalid or not readable.
281 */
282 for (i = 0; i < in_num; i++) {
283 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800284 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800285 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800286 }
287 }
Summer Qinba2346e2019-11-12 16:26:31 +0800288
289 /*
290 * Clients must never overlap input parameters because of the risk of a
291 * double-fetch inconsistency.
292 * Overflow is checked in tfm_memory_check functions.
293 */
294 for (i = 0; i + 1 < in_num; i++) {
295 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100296 if (!((char *) invecs[j].base + invecs[j].len <=
297 (char *) invecs[i].base ||
298 (char *) invecs[j].base >=
299 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800300 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800301 }
302 }
303 }
304
David Hu733d8f92019-09-23 15:32:40 +0800305 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800306 * For client output vector, it is a PROGRAMMER ERROR if the provided
307 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800308 */
309 for (i = 0; i < out_num; i++) {
310 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800311 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800312 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800313 }
314 }
315
Ken Liu0bed7e02022-02-10 12:38:07 +0800316 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800317 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800318
Ken Liu0bed7e02022-02-10 12:38:07 +0800319 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800320}
321
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800322/* Following PSA APIs are only needed by connection-based services */
323#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
324
325psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
326{
327 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800328 struct conn_handle_t *connect_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800329 int32_t client_id;
330 psa_handle_t handle;
331 bool ns_caller = tfm_spm_is_ns_caller();
332 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
333
334 /*
335 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
336 * platform.
337 */
338 service = tfm_spm_get_service_by_sid(sid);
339 if (!service) {
340 return PSA_ERROR_CONNECTION_REFUSED;
341 }
342
343 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
344 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
345 return PSA_ERROR_PROGRAMMER_ERROR;
346 }
347
348 /*
349 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
350 * RoT Service.
351 */
352 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
353 return PSA_ERROR_CONNECTION_REFUSED;
354 }
355
356 /*
357 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
358 * not supported on the platform.
359 */
360 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
361 return PSA_ERROR_CONNECTION_REFUSED;
362 }
363
364 client_id = tfm_spm_get_client_id(ns_caller);
365
366 /*
367 * Create connection handle here since it is possible to return the error
368 * code to client when creation fails.
369 */
370 CRITICAL_SECTION_ENTER(cs_assert);
371 connect_handle = tfm_spm_create_conn_handle(service, client_id);
372 CRITICAL_SECTION_LEAVE(cs_assert);
373 if (!connect_handle) {
374 return PSA_ERROR_CONNECTION_BUSY;
375 }
376
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800377 handle = tfm_spm_to_user_handle(connect_handle);
378 /* No input or output needed for connect message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800379 spm_fill_message(connect_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800380 client_id, NULL, 0, NULL, 0, NULL);
381
Ken Liu0bed7e02022-02-10 12:38:07 +0800382 return backend_instance.messaging(service, connect_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800383}
384
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800385psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800386{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800387 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800388 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800389 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800390 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800391
392 /* It will have no effect if called with the NULL handle */
393 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800394 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800395 }
396
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800397 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800398 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800399 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800400 }
401
Kevin Peng385fda82021-08-18 10:41:19 +0800402 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800403
Summer Qin373feb12020-03-27 15:35:33 +0800404 conn_handle = tfm_spm_to_handle_instance(handle);
David Hu733d8f92019-09-23 15:32:40 +0800405 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800406 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
407 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800408 */
Ken Liubcae38b2021-01-20 15:47:44 +0800409 if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800410 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800411 }
Shawn Shanb222d892021-01-04 17:41:48 +0800412
Ken Liu0bed7e02022-02-10 12:38:07 +0800413 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800414 if (!service) {
415 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800416 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800417 }
418
Shawn Shanb222d892021-01-04 17:41:48 +0800419 /*
420 * It is a PROGRAMMER ERROR if the connection is currently handling a
421 * request.
422 */
Summer Qin630c76b2020-05-20 10:32:58 +0800423 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800424 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800425 }
426
David Hu733d8f92019-09-23 15:32:40 +0800427 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800428 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
429 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800430
Ken Liu0bed7e02022-02-10 12:38:07 +0800431 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800432}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800433
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800434#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
435
Mingyang Suneeca4652021-07-15 15:19:16 +0800436/* PSA Partition API function body */
437
Kevin Peng613b4172022-02-15 14:41:44 +0800438#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800439psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
440 uint32_t timeout)
441{
442 struct partition_t *partition = NULL;
443
444 /*
445 * Timeout[30:0] are reserved for future use.
446 * SPM must ignore the value of RES.
447 */
448 timeout &= PSA_TIMEOUT_MASK;
449
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800450 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800451
452 /*
453 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
454 * signals.
455 */
456 if ((partition->signals_allowed & signal_mask) == 0) {
457 tfm_core_panic();
458 }
459
460 /*
Ken Liu5d73c872021-08-19 19:23:17 +0800461 * thrd_wait_on() blocks the caller thread if no signals are available.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800462 * In this case, the return value of this function is temporary set into
463 * runtime context. After new signal(s) are available, the return value
464 * is updated with the available signal(s) and blocked thread gets to run.
465 */
466 if (timeout == PSA_BLOCK &&
467 (partition->signals_asserted & signal_mask) == 0) {
468 partition->signals_waiting = signal_mask;
Ken Liuf39d8eb2021-10-07 12:55:33 +0800469 thrd_wait_on(&partition->waitobj, CURRENT_THREAD);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800470 }
471
472 return partition->signals_asserted & signal_mask;
473}
474
475psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
476{
Ken Liu0bed7e02022-02-10 12:38:07 +0800477 struct conn_handle_t *tmp_msg = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800478 struct partition_t *partition = NULL;
479 uint32_t privileged;
480
481 /*
482 * Only one message could be retrieved every time for psa_get(). It is a
483 * fatal error if the input signal has more than a signal bit set.
484 */
485 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
486 tfm_core_panic();
487 }
488
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800489 partition = GET_CURRENT_COMPONENT();
490
Kevin Penga40d29f2022-01-19 14:44:34 +0800491 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800492
493 /*
494 * Write the message to the service buffer. It is a fatal error if the
495 * input msg pointer is not a valid memory reference or not read-write.
496 */
497 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
498 privileged) != SPM_SUCCESS) {
499 tfm_core_panic();
500 }
501
502 /*
503 * It is a fatal error if the caller call psa_get() when no message has
504 * been set. The caller must call this function after an RoT Service signal
505 * is returned by psa_wait().
506 */
507 if (partition->signals_asserted == 0) {
508 tfm_core_panic();
509 }
510
511 /*
512 * It is a fatal error if the RoT Service signal is not currently asserted.
513 */
514 if ((partition->signals_asserted & signal) == 0) {
515 tfm_core_panic();
516 }
517
518 /*
519 * Get message by signal from partition. It is a fatal error if getting
520 * failed, which means the input signal is not correspond to an RoT service.
521 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800522 tmp_msg = spm_get_handle_by_signal(partition, signal);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800523 if (!tmp_msg) {
524 return PSA_ERROR_DOES_NOT_EXIST;
525 }
526
Ken Liu0bed7e02022-02-10 12:38:07 +0800527 tmp_msg->status = TFM_HANDLE_STATUS_ACTIVE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800528
529 spm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t));
530
531 return PSA_SUCCESS;
532}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800533#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800534
Mingyang Sunb26b2802021-07-07 11:25:00 +0800535size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
536 void *buffer, size_t num_bytes)
537{
538 size_t bytes;
Ken Liu0bed7e02022-02-10 12:38:07 +0800539 struct conn_handle_t *msg = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800540 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800541
542 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800543 msg = spm_get_handle_by_user_handle(msg_handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800544 if (!msg) {
545 tfm_core_panic();
546 }
547
Kevin Penga40d29f2022-01-19 14:44:34 +0800548 priv_mode = GET_PARTITION_PRIVILEGED_MODE(msg->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800549
550 /*
551 * It is a fatal error if message handle does not refer to a request
552 * message
553 */
554 if (msg->msg.type < PSA_IPC_CALL) {
555 tfm_core_panic();
556 }
557
558 /*
559 * It is a fatal error if invec_idx is equal to or greater than
560 * PSA_MAX_IOVEC
561 */
562 if (invec_idx >= PSA_MAX_IOVEC) {
563 tfm_core_panic();
564 }
565
566 /* There was no remaining data in this input vector */
567 if (msg->msg.in_size[invec_idx] == 0) {
568 return 0;
569 }
570
Shawn Shan038348e2021-09-08 17:11:04 +0800571#if PSA_FRAMEWORK_HAS_MM_IOVEC
572 /*
573 * It is a fatal error if the input vector has already been mapped using
574 * psa_map_invec().
575 */
576 if (IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
577 tfm_core_panic();
578 }
579
580 SET_IOVEC_ACCESSED(msg, (invec_idx + INVEC_IDX_BASE));
581#endif
582
Mingyang Sunb26b2802021-07-07 11:25:00 +0800583 /*
584 * Copy the client data to the service buffer. It is a fatal error
585 * if the memory reference for buffer is invalid or not read-write.
586 */
587 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800588 TFM_MEMORY_ACCESS_RW, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800589 tfm_core_panic();
590 }
591
592 bytes = num_bytes > msg->msg.in_size[invec_idx] ?
593 msg->msg.in_size[invec_idx] : num_bytes;
594
595 spm_memcpy(buffer, msg->invec[invec_idx].base, bytes);
596
597 /* There maybe some remaining data */
598 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base + bytes;
599 msg->msg.in_size[invec_idx] -= bytes;
600
601 return bytes;
602}
603
604size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
605 size_t num_bytes)
606{
Ken Liu0bed7e02022-02-10 12:38:07 +0800607 struct conn_handle_t *msg = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800608
609 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800610 msg = spm_get_handle_by_user_handle(msg_handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800611 if (!msg) {
612 tfm_core_panic();
613 }
614
615 /*
616 * It is a fatal error if message handle does not refer to a request
617 * message
618 */
619 if (msg->msg.type < PSA_IPC_CALL) {
620 tfm_core_panic();
621 }
622
623 /*
624 * It is a fatal error if invec_idx is equal to or greater than
625 * PSA_MAX_IOVEC
626 */
627 if (invec_idx >= PSA_MAX_IOVEC) {
628 tfm_core_panic();
629 }
630
631 /* There was no remaining data in this input vector */
632 if (msg->msg.in_size[invec_idx] == 0) {
633 return 0;
634 }
635
Shawn Shan038348e2021-09-08 17:11:04 +0800636#if PSA_FRAMEWORK_HAS_MM_IOVEC
637 /*
638 * It is a fatal error if the input vector has already been mapped using
639 * psa_map_invec().
640 */
641 if (IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
642 tfm_core_panic();
643 }
644
645 SET_IOVEC_ACCESSED(msg, (invec_idx + INVEC_IDX_BASE));
646#endif
647
Mingyang Sunb26b2802021-07-07 11:25:00 +0800648 /*
649 * If num_bytes is greater than the remaining size of the input vector then
650 * the remaining size of the input vector is used.
651 */
652 if (num_bytes > msg->msg.in_size[invec_idx]) {
653 num_bytes = msg->msg.in_size[invec_idx];
654 }
655
656 /* There maybe some remaining data */
657 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base +
658 num_bytes;
659 msg->msg.in_size[invec_idx] -= num_bytes;
660
661 return num_bytes;
662}
663
664void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
665 const void *buffer, size_t num_bytes)
666{
Ken Liu0bed7e02022-02-10 12:38:07 +0800667 struct conn_handle_t *msg = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800668 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800669
670 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800671 msg = spm_get_handle_by_user_handle(msg_handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800672 if (!msg) {
673 tfm_core_panic();
674 }
675
Kevin Penga40d29f2022-01-19 14:44:34 +0800676 priv_mode = GET_PARTITION_PRIVILEGED_MODE(msg->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800677
678 /*
679 * It is a fatal error if message handle does not refer to a request
680 * message
681 */
682 if (msg->msg.type < PSA_IPC_CALL) {
683 tfm_core_panic();
684 }
685
686 /*
687 * It is a fatal error if outvec_idx is equal to or greater than
688 * PSA_MAX_IOVEC
689 */
690 if (outvec_idx >= PSA_MAX_IOVEC) {
691 tfm_core_panic();
692 }
693
694 /*
695 * It is a fatal error if the call attempts to write data past the end of
696 * the client output vector
697 */
698 if (num_bytes > msg->msg.out_size[outvec_idx] -
699 msg->outvec[outvec_idx].len) {
700 tfm_core_panic();
701 }
702
Shawn Shan038348e2021-09-08 17:11:04 +0800703#if PSA_FRAMEWORK_HAS_MM_IOVEC
704 /*
705 * It is a fatal error if the output vector has already been mapped using
706 * psa_map_outvec().
707 */
708 if (IOVEC_IS_MAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE))) {
709 tfm_core_panic();
710 }
711
712 SET_IOVEC_ACCESSED(msg, (outvec_idx + OUTVEC_IDX_BASE));
713#endif
714
Mingyang Sunb26b2802021-07-07 11:25:00 +0800715 /*
716 * Copy the service buffer to client outvecs. It is a fatal error
717 * if the memory reference for buffer is invalid or not readable.
718 */
719 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800720 TFM_MEMORY_ACCESS_RO, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800721 tfm_core_panic();
722 }
723
724 spm_memcpy((char *)msg->outvec[outvec_idx].base +
725 msg->outvec[outvec_idx].len, buffer, num_bytes);
726
727 /* Update the write number */
728 msg->outvec[outvec_idx].len += num_bytes;
729}
730
Ken Liuf8c7e532022-02-10 15:03:04 +0800731psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
732 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800733{
Ken Liu0bed7e02022-02-10 12:38:07 +0800734 struct service_t *service;
735 struct conn_handle_t *hdl;
Ken Liuf8c7e532022-02-10 15:03:04 +0800736 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800737 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800738
739 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800740 hdl = spm_get_handle_by_user_handle(msg_handle);
741 if (!hdl) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800742 tfm_core_panic();
743 }
744
745 /*
746 * RoT Service information is needed in this function, stored it in message
747 * body structure. Only two parameters are passed in this function: handle
748 * and status, so it is useful and simply to do like this.
749 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800750 service = hdl->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800751 if (!service) {
752 tfm_core_panic();
753 }
754
Ken Liu0bed7e02022-02-10 12:38:07 +0800755 switch (hdl->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800756 case PSA_IPC_CONNECT:
757 /*
758 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
759 * input status is PSA_SUCCESS. Others return values are based on the
760 * input status.
761 */
762 if (status == PSA_SUCCESS) {
763 ret = msg_handle;
764 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
765 /* Refuse the client connection, indicating a permanent error. */
Ken Liu0bed7e02022-02-10 12:38:07 +0800766 tfm_spm_free_conn_handle(service, hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800767 ret = PSA_ERROR_CONNECTION_REFUSED;
768 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
769 /* Fail the client connection, indicating a transient error. */
770 ret = PSA_ERROR_CONNECTION_BUSY;
771 } else {
772 tfm_core_panic();
773 }
774 break;
775 case PSA_IPC_DISCONNECT:
776 /* Service handle is not used anymore */
Ken Liu0bed7e02022-02-10 12:38:07 +0800777 tfm_spm_free_conn_handle(service, hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800778
779 /*
780 * If the message type is PSA_IPC_DISCONNECT, then the status code is
781 * ignored
782 */
783 break;
784 default:
Ken Liu0bed7e02022-02-10 12:38:07 +0800785 if (hdl->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800786
787#if PSA_FRAMEWORK_HAS_MM_IOVEC
788
789 /*
790 * If the unmapped function is not called for an input/output vector
791 * that has been mapped, the framework will remove the mapping.
792 */
793 int i;
794
795 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Ken Liu0bed7e02022-02-10 12:38:07 +0800796 if (IOVEC_IS_MAPPED(hdl, i) && (!IOVEC_IS_UNMAPPED(hdl, i))) {
797 SET_IOVEC_UNMAPPED(hdl, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800798 /*
799 * Any output vectors that are still mapped will report that
800 * zero bytes have been written.
801 */
802 if (i >= OUTVEC_IDX_BASE) {
Ken Liu0bed7e02022-02-10 12:38:07 +0800803 hdl->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800804 }
805 }
806 }
807
808#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800809 /* Reply to a request message. Return values are based on status */
810 ret = status;
811 /*
812 * The total number of bytes written to a single parameter must be
813 * reported to the client by updating the len member of the
814 * psa_outvec structure for the parameter before returning from
815 * psa_call().
816 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800817 update_caller_outvec_len(hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800818 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Ken Liu0bed7e02022-02-10 12:38:07 +0800819 tfm_spm_free_conn_handle(service, hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800820 }
821 } else {
822 tfm_core_panic();
823 }
824 }
825
826 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
827 /*
828 * If the source of the programmer error is a Secure Partition, the SPM
829 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
830 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800831 if (TFM_CLIENT_ID_IS_NS(hdl->msg.client_id)) {
832 hdl->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800833 } else {
834 tfm_core_panic();
835 }
836 } else {
Ken Liu0bed7e02022-02-10 12:38:07 +0800837 hdl->status = TFM_HANDLE_STATUS_IDLE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800838 }
839
Mingyang Sun620c8562021-11-10 11:44:58 +0800840 /*
841 * TODO: It can be optimized further by moving critical section protection
842 * to mailbox. Also need to check implementation when secure context is
843 * involved.
844 */
845 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu0bed7e02022-02-10 12:38:07 +0800846 ret = backend_instance.replying(hdl, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800847 CRITICAL_SECTION_LEAVE(cs_assert);
848
849 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800850}
851
Kevin Peng613b4172022-02-15 14:41:44 +0800852#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800853void tfm_spm_partition_psa_notify(int32_t partition_id)
854{
Ken Liu5d73c872021-08-19 19:23:17 +0800855 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
856
857 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800858}
859
860void tfm_spm_partition_psa_clear(void)
861{
Ken Liu92ede9f2021-10-20 09:35:00 +0800862 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800863 struct partition_t *partition = NULL;
864
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800865 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800866
867 /*
868 * It is a fatal error if the Secure Partition's doorbell signal is not
869 * currently asserted.
870 */
871 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
872 tfm_core_panic();
873 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800874
875 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800876 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800877 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800878}
Kevin Peng613b4172022-02-15 14:41:44 +0800879#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800880
Mingyang Sunb26b2802021-07-07 11:25:00 +0800881void tfm_spm_partition_psa_panic(void)
882{
883 /*
884 * PSA FF recommends that the SPM causes the system to restart when a secure
885 * partition panics.
886 */
887 tfm_hal_system_reset();
888}
889
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800890/* psa_set_rhandle is only needed by connection-based services */
891#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
892
893void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
894{
895 struct conn_handle_t *hdl;
896
897 /* It is a fatal error if message handle is invalid */
898 hdl = spm_get_handle_by_user_handle(msg_handle);
899 if (!hdl) {
900 tfm_core_panic();
901 }
902
903 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
904 if (SERVICE_IS_STATELESS(hdl->service->p_ldinf->flags)) {
905 tfm_core_panic();
906 }
907
908 hdl->msg.rhandle = rhandle;
909 hdl->rhandle = rhandle;
910}
911
912#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
913
914#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800915void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800916{
917 struct partition_t *partition;
918 struct irq_load_info_t *irq_info;
919
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800920 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800921
922 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
923 if (!irq_info) {
924 tfm_core_panic();
925 }
926
Kevin Pengd399a1f2021-09-08 15:33:14 +0800927 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800928}
929
Kevin Peng67a89fd2021-11-25 11:22:02 +0800930psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800931{
932 struct partition_t *partition;
933 struct irq_load_info_t *irq_info;
934
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800935 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800936
937 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
938 if (!irq_info) {
939 tfm_core_panic();
940 }
941
Kevin Pengd399a1f2021-09-08 15:33:14 +0800942 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800943
944 return 1;
945}
946
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800947/* This API is only used for FLIH. */
948#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800949void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
950{
Ken Liu92ede9f2021-10-20 09:35:00 +0800951 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800952 struct irq_load_info_t *irq_info;
953 struct partition_t *partition;
954
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800955 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800956
957 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
958 if (!irq_info) {
959 tfm_core_panic();
960 }
961
962 if (!irq_info->flih_func) {
963 /* This API is for FLIH IRQs only */
964 tfm_core_panic();
965 }
966
967 if ((partition->signals_asserted & irq_signal) == 0) {
968 /* The signal is not asserted */
969 tfm_core_panic();
970 }
971
Ken Liu92ede9f2021-10-20 09:35:00 +0800972 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800973 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800974 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800975}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800976#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800977
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800978/* This API is only used for SLIH. */
979#if CONFIG_TFM_SLIH_API == 1
980void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800981{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800982 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
983 struct irq_load_info_t *irq_info = NULL;
984 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800985
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800986 partition = GET_CURRENT_COMPONENT();
987
988 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
989 /* It is a fatal error if passed signal is not an interrupt signal. */
990 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800991 tfm_core_panic();
992 }
993
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800994 if (irq_info->flih_func) {
995 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800996 tfm_core_panic();
997 }
998
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800999 /* It is a fatal error if passed signal is not currently asserted */
1000 if ((partition->signals_asserted & irq_signal) == 0) {
1001 tfm_core_panic();
1002 }
1003
1004 CRITICAL_SECTION_ENTER(cs_assert);
1005 partition->signals_asserted &= ~irq_signal;
1006 CRITICAL_SECTION_LEAVE(cs_assert);
1007
1008 tfm_hal_irq_clear_pending(irq_info->source);
1009 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001010}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001011#endif
1012#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001013
Shawn Shan038348e2021-09-08 17:11:04 +08001014#if PSA_FRAMEWORK_HAS_MM_IOVEC
1015
1016const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1017 uint32_t invec_idx)
1018{
Ken Liu0bed7e02022-02-10 12:38:07 +08001019 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001020 uint32_t privileged;
1021 struct partition_t *partition = NULL;
1022
1023 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001024 hdl = spm_get_handle_by_user_handle(msg_handle);
1025 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001026 tfm_core_panic();
1027 }
1028
Ken Liu0bed7e02022-02-10 12:38:07 +08001029 partition = hdl->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001030 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001031
1032 /*
1033 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1034 * Service that received the message.
1035 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001036 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001037 tfm_core_panic();
1038 }
1039
1040 /*
1041 * It is a fatal error if message handle does not refer to a request
1042 * message.
1043 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001044 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001045 tfm_core_panic();
1046 }
1047
1048 /*
1049 * It is a fatal error if invec_idx is equal to or greater than
1050 * PSA_MAX_IOVEC.
1051 */
1052 if (invec_idx >= PSA_MAX_IOVEC) {
1053 tfm_core_panic();
1054 }
1055
1056 /* It is a fatal error if the input vector has length zero. */
Ken Liu0bed7e02022-02-10 12:38:07 +08001057 if (hdl->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001058 tfm_core_panic();
1059 }
1060
1061 /*
1062 * It is a fatal error if the input vector has already been mapped using
1063 * psa_map_invec().
1064 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001065 if (IOVEC_IS_MAPPED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001066 tfm_core_panic();
1067 }
1068
1069 /*
1070 * It is a fatal error if the input vector has already been accessed
1071 * using psa_read() or psa_skip().
1072 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001073 if (IOVEC_IS_ACCESSED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001074 tfm_core_panic();
1075 }
1076
1077 /*
1078 * It is a fatal error if the memory reference for the wrap input vector is
1079 * invalid or not readable.
1080 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001081 if (tfm_memory_check(hdl->invec[invec_idx].base, hdl->invec[invec_idx].len,
Shawn Shan038348e2021-09-08 17:11:04 +08001082 false, TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
1083 tfm_core_panic();
1084 }
1085
Ken Liu0bed7e02022-02-10 12:38:07 +08001086 SET_IOVEC_MAPPED(hdl, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001087
Ken Liu0bed7e02022-02-10 12:38:07 +08001088 return hdl->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001089}
1090
1091void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1092 uint32_t invec_idx)
1093{
Ken Liu0bed7e02022-02-10 12:38:07 +08001094 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001095
1096 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001097 hdl = spm_get_handle_by_user_handle(msg_handle);
1098 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001099 tfm_core_panic();
1100 }
1101
1102 /*
1103 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1104 * Service that received the message.
1105 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001106 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001107 tfm_core_panic();
1108 }
1109
1110 /*
1111 * It is a fatal error if message handle does not refer to a request
1112 * message.
1113 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001114 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001115 tfm_core_panic();
1116 }
1117
1118 /*
1119 * It is a fatal error if invec_idx is equal to or greater than
1120 * PSA_MAX_IOVEC.
1121 */
1122 if (invec_idx >= PSA_MAX_IOVEC) {
1123 tfm_core_panic();
1124 }
1125
1126 /*
1127 * It is a fatal error if The input vector has not been mapped by a call to
1128 * psa_map_invec().
1129 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001130 if (!IOVEC_IS_MAPPED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001131 tfm_core_panic();
1132 }
1133
1134 /*
1135 * It is a fatal error if the input vector has already been unmapped by a
1136 * call to psa_unmap_invec().
1137 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001138 if (IOVEC_IS_UNMAPPED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001139 tfm_core_panic();
1140 }
1141
Ken Liu0bed7e02022-02-10 12:38:07 +08001142 SET_IOVEC_UNMAPPED(hdl, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001143}
1144
1145void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1146 uint32_t outvec_idx)
1147{
Ken Liu0bed7e02022-02-10 12:38:07 +08001148 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001149 uint32_t privileged;
1150 struct partition_t *partition = NULL;
1151
1152 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001153 hdl = spm_get_handle_by_user_handle(msg_handle);
1154 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001155 tfm_core_panic();
1156 }
1157
Ken Liu0bed7e02022-02-10 12:38:07 +08001158 partition = hdl->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001159 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001160
1161 /*
1162 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1163 * Service that received the message.
1164 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001165 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001166 tfm_core_panic();
1167 }
1168
1169 /*
1170 * It is a fatal error if message handle does not refer to a request
1171 * message.
1172 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001173 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001174 tfm_core_panic();
1175 }
1176
1177 /*
1178 * It is a fatal error if outvec_idx is equal to or greater than
1179 * PSA_MAX_IOVEC.
1180 */
1181 if (outvec_idx >= PSA_MAX_IOVEC) {
1182 tfm_core_panic();
1183 }
1184
1185 /* It is a fatal error if the output vector has length zero. */
Ken Liu0bed7e02022-02-10 12:38:07 +08001186 if (hdl->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001187 tfm_core_panic();
1188 }
1189
1190 /*
1191 * It is a fatal error if the output vector has already been mapped using
1192 * psa_map_outvec().
1193 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001194 if (IOVEC_IS_MAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001195 tfm_core_panic();
1196 }
1197
1198 /*
1199 * It is a fatal error if the output vector has already been accessed
1200 * using psa_write().
1201 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001202 if (IOVEC_IS_ACCESSED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001203 tfm_core_panic();
1204 }
1205
1206 /*
1207 * It is a fatal error if the output vector is invalid or not read-write.
1208 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001209 if (tfm_memory_check(hdl->outvec[outvec_idx].base,
1210 hdl->outvec[outvec_idx].len, false,
Shawn Shan038348e2021-09-08 17:11:04 +08001211 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
1212 tfm_core_panic();
1213 }
Ken Liu0bed7e02022-02-10 12:38:07 +08001214 SET_IOVEC_MAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001215
Ken Liu0bed7e02022-02-10 12:38:07 +08001216 return hdl->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001217}
1218
1219void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1220 uint32_t outvec_idx, size_t len)
1221{
Ken Liu0bed7e02022-02-10 12:38:07 +08001222 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001223
1224 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001225 hdl = spm_get_handle_by_user_handle(msg_handle);
1226 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001227 tfm_core_panic();
1228 }
1229
1230 /*
1231 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1232 * Service that received the message.
1233 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001234 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001235 tfm_core_panic();
1236 }
1237
1238 /*
1239 * It is a fatal error if message handle does not refer to a request
1240 * message.
1241 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001242 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001243 tfm_core_panic();
1244 }
1245
1246 /*
1247 * It is a fatal error if outvec_idx is equal to or greater than
1248 * PSA_MAX_IOVEC.
1249 */
1250 if (outvec_idx >= PSA_MAX_IOVEC) {
1251 tfm_core_panic();
1252 }
1253
1254 /*
1255 * It is a fatal error if len is greater than the output vector size.
1256 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001257 if (len > hdl->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001258 tfm_core_panic();
1259 }
1260
1261 /*
1262 * It is a fatal error if The output vector has not been mapped by a call to
1263 * psa_map_outvec().
1264 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001265 if (!IOVEC_IS_MAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001266 tfm_core_panic();
1267 }
1268
1269 /*
1270 * It is a fatal error if the output vector has already been unmapped by a
1271 * call to psa_unmap_outvec().
1272 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001273 if (IOVEC_IS_UNMAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001274 tfm_core_panic();
1275 }
1276
Ken Liu0bed7e02022-02-10 12:38:07 +08001277 SET_IOVEC_UNMAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001278
1279 /* Update the write number */
Ken Liu0bed7e02022-02-10 12:38:07 +08001280 hdl->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001281}
1282
1283#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */