blob: d787dd24011e08acc97a57a4eb3c7fd136190c05 [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
Mingyang Suna09adda2022-02-16 18:11:33 +080070#define IOVEC_IS_MAPPED(handle, iovec_idx) \
71 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080072 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080073#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
74 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080075 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080076#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
77 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080078 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080079#define SET_IOVEC_MAPPED(handle, iovec_idx) \
80 (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080081 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080082#define SET_IOVEC_UNMAPPED(handle, iovec_idx) \
83 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080084 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080085#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
86 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080087 ((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 {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800217#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800218 conn_handle = tfm_spm_to_handle_instance(handle);
219
220 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
221 if (tfm_spm_validate_conn_handle(conn_handle, client_id)
222 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800223 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800224 }
225
226 /*
227 * It is a PROGRAMMER ERROR if the connection is currently
228 * handling a request.
229 */
230 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800231 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800232 }
233
234 /*
235 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
236 * has been terminated by the RoT Service.
237 */
238 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
239 return PSA_ERROR_PROGRAMMER_ERROR;
240 }
241
Ken Liu0bed7e02022-02-10 12:38:07 +0800242 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800243
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800244 if (!service) {
245 /* FixMe: Need to implement a mechanism to resolve this failure. */
246 return PSA_ERROR_PROGRAMMER_ERROR;
247 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800248#else
249 return PSA_ERROR_PROGRAMMER_ERROR;
250#endif
David Hu733d8f92019-09-23 15:32:40 +0800251 }
252
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800253 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800254
Kevin Pengedb8ee42021-03-09 16:50:11 +0800255 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800256 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800257 * if the memory reference for the wrap input vector is invalid or not
258 * readable.
259 */
260 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800261 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800262 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800263 }
Summer Qinba2346e2019-11-12 16:26:31 +0800264
David Hu733d8f92019-09-23 15:32:40 +0800265 /*
266 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800267 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800268 * the wrap output vector is invalid or not read-write.
269 */
270 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800271 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800272 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800273 }
274
Summer Qinf24dbb52020-07-23 14:53:54 +0800275 spm_memset(invecs, 0, sizeof(invecs));
276 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800277
278 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800279 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
280 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800281
282 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800283 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800284 * memory reference was invalid or not readable.
285 */
286 for (i = 0; i < in_num; i++) {
287 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800288 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800289 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800290 }
291 }
Summer Qinba2346e2019-11-12 16:26:31 +0800292
293 /*
294 * Clients must never overlap input parameters because of the risk of a
295 * double-fetch inconsistency.
296 * Overflow is checked in tfm_memory_check functions.
297 */
298 for (i = 0; i + 1 < in_num; i++) {
299 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100300 if (!((char *) invecs[j].base + invecs[j].len <=
301 (char *) invecs[i].base ||
302 (char *) invecs[j].base >=
303 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800304 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800305 }
306 }
307 }
308
David Hu733d8f92019-09-23 15:32:40 +0800309 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800310 * For client output vector, it is a PROGRAMMER ERROR if the provided
311 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800312 */
313 for (i = 0; i < out_num; i++) {
314 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800315 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800316 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800317 }
318 }
319
Ken Liu0bed7e02022-02-10 12:38:07 +0800320 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800321 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800322
Ken Liu0bed7e02022-02-10 12:38:07 +0800323 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800324}
325
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800326/* Following PSA APIs are only needed by connection-based services */
327#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
328
329psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
330{
331 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800332 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800333 int32_t client_id;
334 psa_handle_t handle;
335 bool ns_caller = tfm_spm_is_ns_caller();
336 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
337
338 /*
339 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
340 * platform.
341 */
342 service = tfm_spm_get_service_by_sid(sid);
343 if (!service) {
344 return PSA_ERROR_CONNECTION_REFUSED;
345 }
346
347 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
348 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
349 return PSA_ERROR_PROGRAMMER_ERROR;
350 }
351
352 /*
353 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
354 * RoT Service.
355 */
356 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
357 return PSA_ERROR_CONNECTION_REFUSED;
358 }
359
360 /*
361 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
362 * not supported on the platform.
363 */
364 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
365 return PSA_ERROR_CONNECTION_REFUSED;
366 }
367
368 client_id = tfm_spm_get_client_id(ns_caller);
369
370 /*
371 * Create connection handle here since it is possible to return the error
372 * code to client when creation fails.
373 */
374 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800375 conn_handle = tfm_spm_create_conn_handle(service, client_id);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800376 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800377 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800378 return PSA_ERROR_CONNECTION_BUSY;
379 }
380
Mingyang Suna09adda2022-02-16 18:11:33 +0800381 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800382 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800383 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800384 client_id, NULL, 0, NULL, 0, NULL);
385
Mingyang Suna09adda2022-02-16 18:11:33 +0800386 return backend_instance.messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800387}
388
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800389psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800390{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800391 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800392 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800393 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800394 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800395
396 /* It will have no effect if called with the NULL handle */
397 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800398 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800399 }
400
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800401 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800402 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800403 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800404 }
405
Kevin Peng385fda82021-08-18 10:41:19 +0800406 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800407
Summer Qin373feb12020-03-27 15:35:33 +0800408 conn_handle = tfm_spm_to_handle_instance(handle);
David Hu733d8f92019-09-23 15:32:40 +0800409 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800410 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
411 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800412 */
Ken Liubcae38b2021-01-20 15:47:44 +0800413 if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800414 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800415 }
Shawn Shanb222d892021-01-04 17:41:48 +0800416
Ken Liu0bed7e02022-02-10 12:38:07 +0800417 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800418 if (!service) {
419 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800420 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800421 }
422
Shawn Shanb222d892021-01-04 17:41:48 +0800423 /*
424 * It is a PROGRAMMER ERROR if the connection is currently handling a
425 * request.
426 */
Summer Qin630c76b2020-05-20 10:32:58 +0800427 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800428 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800429 }
430
David Hu733d8f92019-09-23 15:32:40 +0800431 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800432 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
433 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800434
Ken Liu0bed7e02022-02-10 12:38:07 +0800435 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800436}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800437
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800438#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
439
Mingyang Suneeca4652021-07-15 15:19:16 +0800440/* PSA Partition API function body */
441
Kevin Pengdef92de2021-11-10 16:14:48 +0800442#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
443 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800444psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
445 uint32_t timeout)
446{
447 struct partition_t *partition = NULL;
448
449 /*
450 * Timeout[30:0] are reserved for future use.
451 * SPM must ignore the value of RES.
452 */
453 timeout &= PSA_TIMEOUT_MASK;
454
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800455 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800456
457 /*
458 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
459 * signals.
460 */
461 if ((partition->signals_allowed & signal_mask) == 0) {
462 tfm_core_panic();
463 }
464
465 /*
Ken Liu5d73c872021-08-19 19:23:17 +0800466 * thrd_wait_on() blocks the caller thread if no signals are available.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800467 * In this case, the return value of this function is temporary set into
468 * runtime context. After new signal(s) are available, the return value
469 * is updated with the available signal(s) and blocked thread gets to run.
470 */
471 if (timeout == PSA_BLOCK &&
472 (partition->signals_asserted & signal_mask) == 0) {
473 partition->signals_waiting = signal_mask;
Kevin Pengdef92de2021-11-10 16:14:48 +0800474 backend_instance.wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800475 }
476
477 return partition->signals_asserted & signal_mask;
478}
Kevin Pengdef92de2021-11-10 16:14:48 +0800479#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800480
Kevin Pengdef92de2021-11-10 16:14:48 +0800481#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800482psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
483{
Mingyang Suna09adda2022-02-16 18:11:33 +0800484 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800485 struct partition_t *partition = NULL;
486 uint32_t privileged;
487
488 /*
489 * Only one message could be retrieved every time for psa_get(). It is a
490 * fatal error if the input signal has more than a signal bit set.
491 */
492 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
493 tfm_core_panic();
494 }
495
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800496 partition = GET_CURRENT_COMPONENT();
497
Kevin Penga40d29f2022-01-19 14:44:34 +0800498 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800499
500 /*
501 * Write the message to the service buffer. It is a fatal error if the
502 * input msg pointer is not a valid memory reference or not read-write.
503 */
504 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
505 privileged) != SPM_SUCCESS) {
506 tfm_core_panic();
507 }
508
509 /*
510 * It is a fatal error if the caller call psa_get() when no message has
511 * been set. The caller must call this function after an RoT Service signal
512 * is returned by psa_wait().
513 */
514 if (partition->signals_asserted == 0) {
515 tfm_core_panic();
516 }
517
518 /*
519 * It is a fatal error if the RoT Service signal is not currently asserted.
520 */
521 if ((partition->signals_asserted & signal) == 0) {
522 tfm_core_panic();
523 }
524
525 /*
526 * Get message by signal from partition. It is a fatal error if getting
527 * failed, which means the input signal is not correspond to an RoT service.
528 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800529 handle = spm_get_handle_by_signal(partition, signal);
530 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800531 return PSA_ERROR_DOES_NOT_EXIST;
532 }
533
Mingyang Suna09adda2022-02-16 18:11:33 +0800534 handle->status = TFM_HANDLE_STATUS_ACTIVE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800535
Mingyang Suna09adda2022-02-16 18:11:33 +0800536 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800537
538 return PSA_SUCCESS;
539}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800540#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800541
Mingyang Sunb26b2802021-07-07 11:25:00 +0800542size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
543 void *buffer, size_t num_bytes)
544{
545 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800546 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800547 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800548
549 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +0800550 handle = spm_get_handle_by_user_handle(msg_handle);
551 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800552 tfm_core_panic();
553 }
554
Mingyang Suna09adda2022-02-16 18:11:33 +0800555 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
556 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800557
558 /*
559 * It is a fatal error if message handle does not refer to a request
560 * message
561 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800562 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800563 tfm_core_panic();
564 }
565
566 /*
567 * It is a fatal error if invec_idx is equal to or greater than
568 * PSA_MAX_IOVEC
569 */
570 if (invec_idx >= PSA_MAX_IOVEC) {
571 tfm_core_panic();
572 }
573
574 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800575 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800576 return 0;
577 }
578
Shawn Shan038348e2021-09-08 17:11:04 +0800579#if PSA_FRAMEWORK_HAS_MM_IOVEC
580 /*
581 * It is a fatal error if the input vector has already been mapped using
582 * psa_map_invec().
583 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800584 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800585 tfm_core_panic();
586 }
587
Mingyang Suna09adda2022-02-16 18:11:33 +0800588 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800589#endif
590
Mingyang Sunb26b2802021-07-07 11:25:00 +0800591 /*
592 * Copy the client data to the service buffer. It is a fatal error
593 * if the memory reference for buffer is invalid or not read-write.
594 */
595 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800596 TFM_MEMORY_ACCESS_RW, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800597 tfm_core_panic();
598 }
599
Mingyang Suna09adda2022-02-16 18:11:33 +0800600 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
601 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800602
Mingyang Suna09adda2022-02-16 18:11:33 +0800603 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800604
605 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800606 handle->invec[invec_idx].base =
607 (char *)handle->invec[invec_idx].base + bytes;
608 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800609
610 return bytes;
611}
612
613size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
614 size_t num_bytes)
615{
Mingyang Suna09adda2022-02-16 18:11:33 +0800616 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800617
618 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +0800619 handle = spm_get_handle_by_user_handle(msg_handle);
620 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800621 tfm_core_panic();
622 }
623
624 /*
625 * It is a fatal error if message handle does not refer to a request
626 * message
627 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800628 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800629 tfm_core_panic();
630 }
631
632 /*
633 * It is a fatal error if invec_idx is equal to or greater than
634 * PSA_MAX_IOVEC
635 */
636 if (invec_idx >= PSA_MAX_IOVEC) {
637 tfm_core_panic();
638 }
639
640 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800641 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800642 return 0;
643 }
644
Shawn Shan038348e2021-09-08 17:11:04 +0800645#if PSA_FRAMEWORK_HAS_MM_IOVEC
646 /*
647 * It is a fatal error if the input vector has already been mapped using
648 * psa_map_invec().
649 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800650 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800651 tfm_core_panic();
652 }
653
Mingyang Suna09adda2022-02-16 18:11:33 +0800654 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800655#endif
656
Mingyang Sunb26b2802021-07-07 11:25:00 +0800657 /*
658 * If num_bytes is greater than the remaining size of the input vector then
659 * the remaining size of the input vector is used.
660 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800661 if (num_bytes > handle->msg.in_size[invec_idx]) {
662 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800663 }
664
665 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800666 handle->invec[invec_idx].base =
667 (char *)handle->invec[invec_idx].base + num_bytes;
668 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800669
670 return num_bytes;
671}
672
673void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
674 const void *buffer, size_t num_bytes)
675{
Mingyang Suna09adda2022-02-16 18:11:33 +0800676 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800677 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800678
679 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +0800680 handle = spm_get_handle_by_user_handle(msg_handle);
681 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800682 tfm_core_panic();
683 }
684
Mingyang Suna09adda2022-02-16 18:11:33 +0800685 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
686 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800687
688 /*
689 * It is a fatal error if message handle does not refer to a request
690 * message
691 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800692 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800693 tfm_core_panic();
694 }
695
696 /*
697 * It is a fatal error if outvec_idx is equal to or greater than
698 * PSA_MAX_IOVEC
699 */
700 if (outvec_idx >= PSA_MAX_IOVEC) {
701 tfm_core_panic();
702 }
703
704 /*
705 * It is a fatal error if the call attempts to write data past the end of
706 * the client output vector
707 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800708 if (num_bytes > handle->msg.out_size[outvec_idx] -
709 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800710 tfm_core_panic();
711 }
712
Shawn Shan038348e2021-09-08 17:11:04 +0800713#if PSA_FRAMEWORK_HAS_MM_IOVEC
714 /*
715 * It is a fatal error if the output vector has already been mapped using
716 * psa_map_outvec().
717 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800718 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800719 tfm_core_panic();
720 }
721
Mingyang Suna09adda2022-02-16 18:11:33 +0800722 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800723#endif
724
Mingyang Sunb26b2802021-07-07 11:25:00 +0800725 /*
726 * Copy the service buffer to client outvecs. It is a fatal error
727 * if the memory reference for buffer is invalid or not readable.
728 */
729 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800730 TFM_MEMORY_ACCESS_RO, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800731 tfm_core_panic();
732 }
733
Mingyang Suna09adda2022-02-16 18:11:33 +0800734 spm_memcpy((char *)handle->outvec[outvec_idx].base +
735 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800736
737 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800738 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800739}
740
Ken Liuf8c7e532022-02-10 15:03:04 +0800741psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
742 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800743{
Ken Liu0bed7e02022-02-10 12:38:07 +0800744 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800745 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800746 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800747 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800748
749 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +0800750 handle = spm_get_handle_by_user_handle(msg_handle);
751 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800752 tfm_core_panic();
753 }
754
755 /*
756 * RoT Service information is needed in this function, stored it in message
757 * body structure. Only two parameters are passed in this function: handle
758 * and status, so it is useful and simply to do like this.
759 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800760 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800761 if (!service) {
762 tfm_core_panic();
763 }
764
Mingyang Suna09adda2022-02-16 18:11:33 +0800765 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800766 case PSA_IPC_CONNECT:
767 /*
768 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
769 * input status is PSA_SUCCESS. Others return values are based on the
770 * input status.
771 */
772 if (status == PSA_SUCCESS) {
773 ret = msg_handle;
774 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
775 /* Refuse the client connection, indicating a permanent error. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800776 tfm_spm_free_conn_handle(service, handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800777 ret = PSA_ERROR_CONNECTION_REFUSED;
778 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
779 /* Fail the client connection, indicating a transient error. */
780 ret = PSA_ERROR_CONNECTION_BUSY;
781 } else {
782 tfm_core_panic();
783 }
784 break;
785 case PSA_IPC_DISCONNECT:
786 /* Service handle is not used anymore */
Mingyang Suna09adda2022-02-16 18:11:33 +0800787 tfm_spm_free_conn_handle(service, handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800788
789 /*
790 * If the message type is PSA_IPC_DISCONNECT, then the status code is
791 * ignored
792 */
793 break;
794 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800795 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800796
797#if PSA_FRAMEWORK_HAS_MM_IOVEC
798
799 /*
800 * If the unmapped function is not called for an input/output vector
801 * that has been mapped, the framework will remove the mapping.
802 */
803 int i;
804
805 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800806 if (IOVEC_IS_MAPPED(handle, i) &&
807 (!IOVEC_IS_UNMAPPED(handle, i))) {
808 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800809 /*
810 * Any output vectors that are still mapped will report that
811 * zero bytes have been written.
812 */
813 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800814 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800815 }
816 }
817 }
818
819#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800820 /* Reply to a request message. Return values are based on status */
821 ret = status;
822 /*
823 * The total number of bytes written to a single parameter must be
824 * reported to the client by updating the len member of the
825 * psa_outvec structure for the parameter before returning from
826 * psa_call().
827 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800828 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800829 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800830 tfm_spm_free_conn_handle(service, handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800831 }
832 } else {
833 tfm_core_panic();
834 }
835 }
836
837 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
838 /*
839 * If the source of the programmer error is a Secure Partition, the SPM
840 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
841 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800842 if (TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
843 handle->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800844 } else {
845 tfm_core_panic();
846 }
847 } else {
Mingyang Suna09adda2022-02-16 18:11:33 +0800848 handle->status = TFM_HANDLE_STATUS_IDLE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800849 }
850
Mingyang Sun620c8562021-11-10 11:44:58 +0800851 /*
852 * TODO: It can be optimized further by moving critical section protection
853 * to mailbox. Also need to check implementation when secure context is
854 * involved.
855 */
856 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800857 ret = backend_instance.replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800858 CRITICAL_SECTION_LEAVE(cs_assert);
859
860 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800861}
862
Kevin Peng613b4172022-02-15 14:41:44 +0800863#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800864void tfm_spm_partition_psa_notify(int32_t partition_id)
865{
Ken Liu5d73c872021-08-19 19:23:17 +0800866 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
867
868 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800869}
870
871void tfm_spm_partition_psa_clear(void)
872{
Ken Liu92ede9f2021-10-20 09:35:00 +0800873 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800874 struct partition_t *partition = NULL;
875
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800876 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800877
878 /*
879 * It is a fatal error if the Secure Partition's doorbell signal is not
880 * currently asserted.
881 */
882 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
883 tfm_core_panic();
884 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800885
886 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800887 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800888 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800889}
Kevin Peng613b4172022-02-15 14:41:44 +0800890#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800891
Mingyang Sunb26b2802021-07-07 11:25:00 +0800892void tfm_spm_partition_psa_panic(void)
893{
894 /*
895 * PSA FF recommends that the SPM causes the system to restart when a secure
896 * partition panics.
897 */
898 tfm_hal_system_reset();
899}
900
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800901/* psa_set_rhandle is only needed by connection-based services */
902#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
903
904void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
905{
Mingyang Suna09adda2022-02-16 18:11:33 +0800906 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800907
908 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +0800909 handle = spm_get_handle_by_user_handle(msg_handle);
910 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800911 tfm_core_panic();
912 }
913
914 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800915 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800916 tfm_core_panic();
917 }
918
Mingyang Suna09adda2022-02-16 18:11:33 +0800919 handle->msg.rhandle = rhandle;
920 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800921}
922
923#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
924
925#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800926void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800927{
928 struct partition_t *partition;
929 struct irq_load_info_t *irq_info;
930
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800931 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800932
933 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
934 if (!irq_info) {
935 tfm_core_panic();
936 }
937
Kevin Pengd399a1f2021-09-08 15:33:14 +0800938 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800939}
940
Kevin Peng67a89fd2021-11-25 11:22:02 +0800941psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800942{
943 struct partition_t *partition;
944 struct irq_load_info_t *irq_info;
945
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800946 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800947
948 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
949 if (!irq_info) {
950 tfm_core_panic();
951 }
952
Kevin Pengd399a1f2021-09-08 15:33:14 +0800953 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800954
955 return 1;
956}
957
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800958/* This API is only used for FLIH. */
959#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800960void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
961{
Ken Liu92ede9f2021-10-20 09:35:00 +0800962 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800963 struct irq_load_info_t *irq_info;
964 struct partition_t *partition;
965
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800966 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800967
968 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
969 if (!irq_info) {
970 tfm_core_panic();
971 }
972
973 if (!irq_info->flih_func) {
974 /* This API is for FLIH IRQs only */
975 tfm_core_panic();
976 }
977
978 if ((partition->signals_asserted & irq_signal) == 0) {
979 /* The signal is not asserted */
980 tfm_core_panic();
981 }
982
Ken Liu92ede9f2021-10-20 09:35:00 +0800983 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800984 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800985 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800986}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800987#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800988
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800989/* This API is only used for SLIH. */
990#if CONFIG_TFM_SLIH_API == 1
991void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800992{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800993 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
994 struct irq_load_info_t *irq_info = NULL;
995 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800996
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800997 partition = GET_CURRENT_COMPONENT();
998
999 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
1000 /* It is a fatal error if passed signal is not an interrupt signal. */
1001 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001002 tfm_core_panic();
1003 }
1004
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001005 if (irq_info->flih_func) {
1006 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001007 tfm_core_panic();
1008 }
1009
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001010 /* It is a fatal error if passed signal is not currently asserted */
1011 if ((partition->signals_asserted & irq_signal) == 0) {
1012 tfm_core_panic();
1013 }
1014
1015 CRITICAL_SECTION_ENTER(cs_assert);
1016 partition->signals_asserted &= ~irq_signal;
1017 CRITICAL_SECTION_LEAVE(cs_assert);
1018
1019 tfm_hal_irq_clear_pending(irq_info->source);
1020 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001021}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001022#endif
1023#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001024
Shawn Shan038348e2021-09-08 17:11:04 +08001025#if PSA_FRAMEWORK_HAS_MM_IOVEC
1026
1027const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1028 uint32_t invec_idx)
1029{
Mingyang Suna09adda2022-02-16 18:11:33 +08001030 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001031 uint32_t privileged;
1032 struct partition_t *partition = NULL;
1033
1034 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +08001035 handle = spm_get_handle_by_user_handle(msg_handle);
1036 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001037 tfm_core_panic();
1038 }
1039
Mingyang Suna09adda2022-02-16 18:11:33 +08001040 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001041 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001042
1043 /*
1044 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1045 * Service that received the message.
1046 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001047 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001048 tfm_core_panic();
1049 }
1050
1051 /*
1052 * It is a fatal error if message handle does not refer to a request
1053 * message.
1054 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001055 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001056 tfm_core_panic();
1057 }
1058
1059 /*
1060 * It is a fatal error if invec_idx is equal to or greater than
1061 * PSA_MAX_IOVEC.
1062 */
1063 if (invec_idx >= PSA_MAX_IOVEC) {
1064 tfm_core_panic();
1065 }
1066
1067 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001068 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001069 tfm_core_panic();
1070 }
1071
1072 /*
1073 * It is a fatal error if the input vector has already been mapped using
1074 * psa_map_invec().
1075 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001076 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001077 tfm_core_panic();
1078 }
1079
1080 /*
1081 * It is a fatal error if the input vector has already been accessed
1082 * using psa_read() or psa_skip().
1083 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001084 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001085 tfm_core_panic();
1086 }
1087
1088 /*
1089 * It is a fatal error if the memory reference for the wrap input vector is
1090 * invalid or not readable.
1091 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001092 if (tfm_memory_check(handle->invec[invec_idx].base,
1093 handle->invec[invec_idx].len,
1094 false, TFM_MEMORY_ACCESS_RO,
1095 privileged) != SPM_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001096 tfm_core_panic();
1097 }
1098
Mingyang Suna09adda2022-02-16 18:11:33 +08001099 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001100
Mingyang Suna09adda2022-02-16 18:11:33 +08001101 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001102}
1103
1104void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1105 uint32_t invec_idx)
1106{
Mingyang Suna09adda2022-02-16 18:11:33 +08001107 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001108
1109 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +08001110 handle = spm_get_handle_by_user_handle(msg_handle);
1111 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001112 tfm_core_panic();
1113 }
1114
1115 /*
1116 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1117 * Service that received the message.
1118 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001119 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001120 tfm_core_panic();
1121 }
1122
1123 /*
1124 * It is a fatal error if message handle does not refer to a request
1125 * message.
1126 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001127 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001128 tfm_core_panic();
1129 }
1130
1131 /*
1132 * It is a fatal error if invec_idx is equal to or greater than
1133 * PSA_MAX_IOVEC.
1134 */
1135 if (invec_idx >= PSA_MAX_IOVEC) {
1136 tfm_core_panic();
1137 }
1138
1139 /*
1140 * It is a fatal error if The input vector has not been mapped by a call to
1141 * psa_map_invec().
1142 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001143 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001144 tfm_core_panic();
1145 }
1146
1147 /*
1148 * It is a fatal error if the input vector has already been unmapped by a
1149 * call to psa_unmap_invec().
1150 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001151 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001152 tfm_core_panic();
1153 }
1154
Mingyang Suna09adda2022-02-16 18:11:33 +08001155 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001156}
1157
1158void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1159 uint32_t outvec_idx)
1160{
Mingyang Suna09adda2022-02-16 18:11:33 +08001161 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001162 uint32_t privileged;
1163 struct partition_t *partition = NULL;
1164
1165 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +08001166 handle = spm_get_handle_by_user_handle(msg_handle);
1167 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001168 tfm_core_panic();
1169 }
1170
Mingyang Suna09adda2022-02-16 18:11:33 +08001171 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001172 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001173
1174 /*
1175 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1176 * Service that received the message.
1177 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001178 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001179 tfm_core_panic();
1180 }
1181
1182 /*
1183 * It is a fatal error if message handle does not refer to a request
1184 * message.
1185 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001186 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001187 tfm_core_panic();
1188 }
1189
1190 /*
1191 * It is a fatal error if outvec_idx is equal to or greater than
1192 * PSA_MAX_IOVEC.
1193 */
1194 if (outvec_idx >= PSA_MAX_IOVEC) {
1195 tfm_core_panic();
1196 }
1197
1198 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001199 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001200 tfm_core_panic();
1201 }
1202
1203 /*
1204 * It is a fatal error if the output vector has already been mapped using
1205 * psa_map_outvec().
1206 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001207 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001208 tfm_core_panic();
1209 }
1210
1211 /*
1212 * It is a fatal error if the output vector has already been accessed
1213 * using psa_write().
1214 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001215 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001216 tfm_core_panic();
1217 }
1218
1219 /*
1220 * It is a fatal error if the output vector is invalid or not read-write.
1221 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001222 if (tfm_memory_check(handle->outvec[outvec_idx].base,
1223 handle->outvec[outvec_idx].len, false,
Shawn Shan038348e2021-09-08 17:11:04 +08001224 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
1225 tfm_core_panic();
1226 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001227 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001228
Mingyang Suna09adda2022-02-16 18:11:33 +08001229 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001230}
1231
1232void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1233 uint32_t outvec_idx, size_t len)
1234{
Mingyang Suna09adda2022-02-16 18:11:33 +08001235 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001236
1237 /* It is a fatal error if message handle is invalid */
Mingyang Suna09adda2022-02-16 18:11:33 +08001238 handle = spm_get_handle_by_user_handle(msg_handle);
1239 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001240 tfm_core_panic();
1241 }
1242
1243 /*
1244 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1245 * Service that received the message.
1246 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001247 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001248 tfm_core_panic();
1249 }
1250
1251 /*
1252 * It is a fatal error if message handle does not refer to a request
1253 * message.
1254 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001255 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001256 tfm_core_panic();
1257 }
1258
1259 /*
1260 * It is a fatal error if outvec_idx is equal to or greater than
1261 * PSA_MAX_IOVEC.
1262 */
1263 if (outvec_idx >= PSA_MAX_IOVEC) {
1264 tfm_core_panic();
1265 }
1266
1267 /*
1268 * It is a fatal error if len is greater than the output vector size.
1269 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001270 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001271 tfm_core_panic();
1272 }
1273
1274 /*
1275 * It is a fatal error if The output vector has not been mapped by a call to
1276 * psa_map_outvec().
1277 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001278 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001279 tfm_core_panic();
1280 }
1281
1282 /*
1283 * It is a fatal error if the output vector has already been unmapped by a
1284 * call to psa_unmap_outvec().
1285 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001286 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001287 tfm_core_panic();
1288 }
1289
Mingyang Suna09adda2022-02-16 18:11:33 +08001290 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001291
1292 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001293 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001294}
1295
1296#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */