blob: be92c76834c7ecbcd7ad0266ab32a6ada2c1f75e [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{
Summer Qind9d497b2022-04-14 14:39:26 +080093 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
94 status == PSA_ERROR_CONNECTION_REFUSED) {
95 if (!tfm_spm_is_ns_caller()) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +080096 tfm_core_panic();
Summer Qind9d497b2022-04-14 14:39:26 +080097 }
Xinyu Zhangb287ef82021-11-03 18:38:50 +080098 }
99}
100
Mingyang Suneeca4652021-07-15 15:19:16 +0800101uint32_t tfm_spm_get_lifecycle_state(void)
102{
103 /*
104 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
105 * implemented in the future.
106 */
107 return PSA_LIFECYCLE_UNKNOWN;
108}
109
110/* PSA Client API function body */
111
Mingyang Sund44522a2020-01-16 16:48:37 +0800112uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800113{
114 return PSA_FRAMEWORK_VERSION;
115}
116
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800117uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800118{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800119 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800120 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800121
122 /*
123 * It should return PSA_VERSION_NONE if the RoT Service is not
124 * implemented.
125 */
126 service = tfm_spm_get_service_by_sid(sid);
127 if (!service) {
128 return PSA_VERSION_NONE;
129 }
130
131 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800132 * It should return PSA_VERSION_NONE if the caller is not authorized
133 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800134 */
Ken Liubcae38b2021-01-20 15:47:44 +0800135 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800136 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800137 }
138
Ken Liuacd2a572021-05-12 16:19:04 +0800139 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800140}
141
Mingyang Suneeca4652021-07-15 15:19:16 +0800142psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
143 uint32_t ctrl_param,
144 const psa_invec *inptr,
145 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800146{
147 psa_invec invecs[PSA_MAX_IOVEC];
148 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800149 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800150 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800151 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800152 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800153 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800154 uint32_t privileged;
Mingyang Sun620c8562021-11-10 11:44:58 +0800155 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800156 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800157 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
158 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
159 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800160
161 /* The request type must be zero or positive. */
162 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800163 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800164 }
David Hu733d8f92019-09-23 15:32:40 +0800165
Shawn Shanb222d892021-01-04 17:41:48 +0800166 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800167 if ((in_num > PSA_MAX_IOVEC) ||
168 (out_num > PSA_MAX_IOVEC) ||
169 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800170 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800171 }
172
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800173 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
174 if (handle == PSA_NULL_HANDLE) {
175 return PSA_ERROR_PROGRAMMER_ERROR;
176 }
177
Kevin Peng385fda82021-08-18 10:41:19 +0800178 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800179
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800180 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800181 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800182 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800183
184 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800185 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800186 }
187
Mingyang Sun453ad402021-03-17 17:58:33 +0800188 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800189 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800190 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800191 }
192
Ken Liub3b2cb62021-05-22 00:39:28 +0800193 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800194
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800195 /*
196 * It is a PROGRAMMER ERROR if the caller is not authorized to access
197 * the RoT Service.
198 */
199 if (tfm_spm_check_authorization(sid, service, ns_caller)
200 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800201 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800202 }
203
Mingyang Sun453ad402021-03-17 17:58:33 +0800204 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
205
206 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800207 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800208 }
209
Mingyang Sun620c8562021-11-10 11:44:58 +0800210 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800211 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800212 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800213
214 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800215 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800216 }
217
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800218 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800219 handle = tfm_spm_to_user_handle(conn_handle);
220 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800221#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800222 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800223 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
224 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800225 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800226 }
227
228 /*
229 * It is a PROGRAMMER ERROR if the connection is currently
230 * handling a request.
231 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800232 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800233 return PSA_ERROR_PROGRAMMER_ERROR;
234 }
235
Ken Liu0bed7e02022-02-10 12:38:07 +0800236 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800237
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800238 if (!service) {
239 /* FixMe: Need to implement a mechanism to resolve this failure. */
240 return PSA_ERROR_PROGRAMMER_ERROR;
241 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800242#else
243 return PSA_ERROR_PROGRAMMER_ERROR;
244#endif
David Hu733d8f92019-09-23 15:32:40 +0800245 }
246
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800247 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800248
Kevin Pengedb8ee42021-03-09 16:50:11 +0800249 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800250 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800251 * if the memory reference for the wrap input vector is invalid or not
252 * readable.
253 */
254 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800255 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800256 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800257 }
Summer Qinba2346e2019-11-12 16:26:31 +0800258
David Hu733d8f92019-09-23 15:32:40 +0800259 /*
260 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800261 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800262 * the wrap output vector is invalid or not read-write.
263 */
264 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800265 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800266 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800267 }
268
Summer Qinf24dbb52020-07-23 14:53:54 +0800269 spm_memset(invecs, 0, sizeof(invecs));
270 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800271
272 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800273 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
274 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800275
276 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800277 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800278 * memory reference was invalid or not readable.
279 */
280 for (i = 0; i < in_num; i++) {
281 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800282 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800283 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800284 }
285 }
Summer Qinba2346e2019-11-12 16:26:31 +0800286
287 /*
288 * Clients must never overlap input parameters because of the risk of a
289 * double-fetch inconsistency.
290 * Overflow is checked in tfm_memory_check functions.
291 */
292 for (i = 0; i + 1 < in_num; i++) {
293 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100294 if (!((char *) invecs[j].base + invecs[j].len <=
295 (char *) invecs[i].base ||
296 (char *) invecs[j].base >=
297 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800298 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800299 }
300 }
301 }
302
David Hu733d8f92019-09-23 15:32:40 +0800303 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800304 * For client output vector, it is a PROGRAMMER ERROR if the provided
305 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800306 */
307 for (i = 0; i < out_num; i++) {
308 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800309 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800310 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800311 }
312 }
313
Ken Liu0bed7e02022-02-10 12:38:07 +0800314 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800315 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800316
Ken Liu0bed7e02022-02-10 12:38:07 +0800317 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800318}
319
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800320/* Following PSA APIs are only needed by connection-based services */
321#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
322
323psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
324{
325 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800326 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800327 int32_t client_id;
328 psa_handle_t handle;
329 bool ns_caller = tfm_spm_is_ns_caller();
330 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
331
332 /*
333 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
334 * platform.
335 */
336 service = tfm_spm_get_service_by_sid(sid);
337 if (!service) {
338 return PSA_ERROR_CONNECTION_REFUSED;
339 }
340
341 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
342 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
343 return PSA_ERROR_PROGRAMMER_ERROR;
344 }
345
346 /*
347 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
348 * RoT Service.
349 */
350 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
351 return PSA_ERROR_CONNECTION_REFUSED;
352 }
353
354 /*
355 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
356 * not supported on the platform.
357 */
358 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
359 return PSA_ERROR_CONNECTION_REFUSED;
360 }
361
362 client_id = tfm_spm_get_client_id(ns_caller);
363
364 /*
365 * Create connection handle here since it is possible to return the error
366 * code to client when creation fails.
367 */
368 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800369 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800370 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800371 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800372 return PSA_ERROR_CONNECTION_BUSY;
373 }
374
Mingyang Suna09adda2022-02-16 18:11:33 +0800375 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800376 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800377 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800378 client_id, NULL, 0, NULL, 0, NULL);
379
Mingyang Suna09adda2022-02-16 18:11:33 +0800380 return backend_instance.messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800381}
382
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800383psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800384{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800385 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800386 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800387 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800388 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800389
390 /* It will have no effect if called with the NULL handle */
391 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800392 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800393 }
394
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800395 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800396 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800397 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800398 }
399
Kevin Peng385fda82021-08-18 10:41:19 +0800400 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800401
David Hu733d8f92019-09-23 15:32:40 +0800402 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800403 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
404 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800405 */
Kevin Penge61e7052022-01-27 14:57:06 +0800406 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
407 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800408 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800409 }
Shawn Shanb222d892021-01-04 17:41:48 +0800410
Ken Liu0bed7e02022-02-10 12:38:07 +0800411 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800412 if (!service) {
413 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800414 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800415 }
416
Shawn Shanb222d892021-01-04 17:41:48 +0800417 /*
418 * It is a PROGRAMMER ERROR if the connection is currently handling a
419 * request.
420 */
Summer Qin630c76b2020-05-20 10:32:58 +0800421 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800422 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800423 }
424
David Hu733d8f92019-09-23 15:32:40 +0800425 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800426 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
427 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800428
Ken Liu0bed7e02022-02-10 12:38:07 +0800429 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800430}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800431
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800432#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
433
Mingyang Suneeca4652021-07-15 15:19:16 +0800434/* PSA Partition API function body */
435
Kevin Pengdef92de2021-11-10 16:14:48 +0800436#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
437 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800438psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
439 uint32_t timeout)
440{
441 struct partition_t *partition = NULL;
442
443 /*
444 * Timeout[30:0] are reserved for future use.
445 * SPM must ignore the value of RES.
446 */
447 timeout &= PSA_TIMEOUT_MASK;
448
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800449 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800450
451 /*
452 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
453 * signals.
454 */
455 if ((partition->signals_allowed & signal_mask) == 0) {
456 tfm_core_panic();
457 }
458
459 /*
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800460 * backend_instance.wait() blocks the caller thread if no signals are
461 * available. In this case, the return value of this function is temporary
462 * set into runtime context. After new signal(s) are available, the return
463 * value is updated with the available signal(s) and blocked thread gets
464 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800465 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800466 if (timeout == PSA_BLOCK) {
467 return backend_instance.wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800468 }
469
470 return partition->signals_asserted & signal_mask;
471}
Kevin Pengdef92de2021-11-10 16:14:48 +0800472#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800473
Kevin Pengdef92de2021-11-10 16:14:48 +0800474#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800475psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
476{
Mingyang Suna09adda2022-02-16 18:11:33 +0800477 struct conn_handle_t *handle = 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 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800522 handle = spm_get_handle_by_signal(partition, signal);
523 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800524 return PSA_ERROR_DOES_NOT_EXIST;
525 }
526
Mingyang Suna09adda2022-02-16 18:11:33 +0800527 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800528
529 return PSA_SUCCESS;
530}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800531#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800532
Mingyang Sunb26b2802021-07-07 11:25:00 +0800533size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
534 void *buffer, size_t num_bytes)
535{
536 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800537 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800538 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800539
540 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800541 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800542 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800543 tfm_core_panic();
544 }
545
Mingyang Suna09adda2022-02-16 18:11:33 +0800546 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
547 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800548
549 /*
550 * It is a fatal error if message handle does not refer to a request
551 * message
552 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800553 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800554 tfm_core_panic();
555 }
556
557 /*
558 * It is a fatal error if invec_idx is equal to or greater than
559 * PSA_MAX_IOVEC
560 */
561 if (invec_idx >= PSA_MAX_IOVEC) {
562 tfm_core_panic();
563 }
564
565 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800566 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800567 return 0;
568 }
569
Shawn Shan038348e2021-09-08 17:11:04 +0800570#if PSA_FRAMEWORK_HAS_MM_IOVEC
571 /*
572 * It is a fatal error if the input vector has already been mapped using
573 * psa_map_invec().
574 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800575 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800576 tfm_core_panic();
577 }
578
Mingyang Suna09adda2022-02-16 18:11:33 +0800579 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800580#endif
581
Mingyang Sunb26b2802021-07-07 11:25:00 +0800582 /*
583 * Copy the client data to the service buffer. It is a fatal error
584 * if the memory reference for buffer is invalid or not read-write.
585 */
586 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800587 TFM_MEMORY_ACCESS_RW, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800588 tfm_core_panic();
589 }
590
Mingyang Suna09adda2022-02-16 18:11:33 +0800591 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
592 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800593
Mingyang Suna09adda2022-02-16 18:11:33 +0800594 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800595
596 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800597 handle->invec[invec_idx].base =
598 (char *)handle->invec[invec_idx].base + bytes;
599 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800600
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{
Mingyang Suna09adda2022-02-16 18:11:33 +0800607 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800608
609 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800610 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800611 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800612 tfm_core_panic();
613 }
614
615 /*
616 * It is a fatal error if message handle does not refer to a request
617 * message
618 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800619 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800620 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 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800632 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800633 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 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800641 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800642 tfm_core_panic();
643 }
644
Mingyang Suna09adda2022-02-16 18:11:33 +0800645 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800646#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 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800652 if (num_bytes > handle->msg.in_size[invec_idx]) {
653 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800654 }
655
656 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800657 handle->invec[invec_idx].base =
658 (char *)handle->invec[invec_idx].base + num_bytes;
659 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800660
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{
Mingyang Suna09adda2022-02-16 18:11:33 +0800667 struct conn_handle_t *handle = 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 */
Kevin Penge61e7052022-01-27 14:57:06 +0800671 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800672 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800673 tfm_core_panic();
674 }
675
Mingyang Suna09adda2022-02-16 18:11:33 +0800676 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
677 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800678
679 /*
680 * It is a fatal error if message handle does not refer to a request
681 * message
682 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800683 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800684 tfm_core_panic();
685 }
686
687 /*
688 * It is a fatal error if outvec_idx is equal to or greater than
689 * PSA_MAX_IOVEC
690 */
691 if (outvec_idx >= PSA_MAX_IOVEC) {
692 tfm_core_panic();
693 }
694
695 /*
696 * It is a fatal error if the call attempts to write data past the end of
697 * the client output vector
698 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800699 if (num_bytes > handle->msg.out_size[outvec_idx] -
700 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800701 tfm_core_panic();
702 }
703
Shawn Shan038348e2021-09-08 17:11:04 +0800704#if PSA_FRAMEWORK_HAS_MM_IOVEC
705 /*
706 * It is a fatal error if the output vector has already been mapped using
707 * psa_map_outvec().
708 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800709 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800710 tfm_core_panic();
711 }
712
Mingyang Suna09adda2022-02-16 18:11:33 +0800713 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800714#endif
715
Mingyang Sunb26b2802021-07-07 11:25:00 +0800716 /*
717 * Copy the service buffer to client outvecs. It is a fatal error
718 * if the memory reference for buffer is invalid or not readable.
719 */
720 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800721 TFM_MEMORY_ACCESS_RO, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800722 tfm_core_panic();
723 }
724
Mingyang Suna09adda2022-02-16 18:11:33 +0800725 spm_memcpy((char *)handle->outvec[outvec_idx].base +
726 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800727
728 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800729 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800730}
731
Ken Liuf8c7e532022-02-10 15:03:04 +0800732psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
733 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800734{
Ken Liu0bed7e02022-02-10 12:38:07 +0800735 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800736 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800737 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800738 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800739
740 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800741 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800742 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800743 tfm_core_panic();
744 }
745
746 /*
747 * RoT Service information is needed in this function, stored it in message
748 * body structure. Only two parameters are passed in this function: handle
749 * and status, so it is useful and simply to do like this.
750 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800751 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800752 if (!service) {
753 tfm_core_panic();
754 }
755
Mingyang Suna09adda2022-02-16 18:11:33 +0800756 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800757 case PSA_IPC_CONNECT:
758 /*
759 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
760 * input status is PSA_SUCCESS. Others return values are based on the
761 * input status.
762 */
763 if (status == PSA_SUCCESS) {
764 ret = msg_handle;
765 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
766 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800767 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800768 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800769 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
770 /* Fail the client connection, indicating a transient error. */
771 ret = PSA_ERROR_CONNECTION_BUSY;
772 } else {
773 tfm_core_panic();
774 }
775 break;
776 case PSA_IPC_DISCONNECT:
777 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800778 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800779
780 /*
781 * If the message type is PSA_IPC_DISCONNECT, then the status code is
782 * ignored
783 */
784 break;
785 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800786 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800787
788#if PSA_FRAMEWORK_HAS_MM_IOVEC
789
790 /*
791 * If the unmapped function is not called for an input/output vector
792 * that has been mapped, the framework will remove the mapping.
793 */
794 int i;
795
796 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800797 if (IOVEC_IS_MAPPED(handle, i) &&
798 (!IOVEC_IS_UNMAPPED(handle, i))) {
799 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800800 /*
801 * Any output vectors that are still mapped will report that
802 * zero bytes have been written.
803 */
804 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800805 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800806 }
807 }
808 }
809
810#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800811 /* Reply to a request message. Return values are based on status */
812 ret = status;
813 /*
814 * The total number of bytes written to a single parameter must be
815 * reported to the client by updating the len member of the
816 * psa_outvec structure for the parameter before returning from
817 * psa_call().
818 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800819 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800820 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800821 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800822 }
823 } else {
824 tfm_core_panic();
825 }
826 }
827
828 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
829 /*
830 * If the source of the programmer error is a Secure Partition, the SPM
831 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
832 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800833 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800834 tfm_core_panic();
835 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800836 }
837
Mingyang Sun620c8562021-11-10 11:44:58 +0800838 /*
839 * TODO: It can be optimized further by moving critical section protection
840 * to mailbox. Also need to check implementation when secure context is
841 * involved.
842 */
843 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800844 ret = backend_instance.replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800845 CRITICAL_SECTION_LEAVE(cs_assert);
846
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800847 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
848 tfm_spm_free_conn_handle(handle);
849 } else {
850 handle->status = TFM_HANDLE_STATUS_IDLE;
851 }
852
Mingyang Sun620c8562021-11-10 11:44:58 +0800853 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800854}
855
Kevin Peng613b4172022-02-15 14:41:44 +0800856#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800857void tfm_spm_partition_psa_notify(int32_t partition_id)
858{
Ken Liu5d73c872021-08-19 19:23:17 +0800859 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
860
861 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800862}
863
864void tfm_spm_partition_psa_clear(void)
865{
Ken Liu92ede9f2021-10-20 09:35:00 +0800866 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800867 struct partition_t *partition = NULL;
868
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800869 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800870
871 /*
872 * It is a fatal error if the Secure Partition's doorbell signal is not
873 * currently asserted.
874 */
875 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
876 tfm_core_panic();
877 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800878
879 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800880 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800881 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800882}
Kevin Peng613b4172022-02-15 14:41:44 +0800883#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800884
Mingyang Sunb26b2802021-07-07 11:25:00 +0800885void tfm_spm_partition_psa_panic(void)
886{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100887#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
888 tfm_hal_system_halt();
889#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800890 /*
891 * PSA FF recommends that the SPM causes the system to restart when a secure
892 * partition panics.
893 */
894 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100895#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800896}
897
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800898/* psa_set_rhandle is only needed by connection-based services */
899#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
900
901void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
902{
Mingyang Suna09adda2022-02-16 18:11:33 +0800903 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800904
905 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800906 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800907 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800908 tfm_core_panic();
909 }
910
911 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800912 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800913 tfm_core_panic();
914 }
915
Mingyang Suna09adda2022-02-16 18:11:33 +0800916 handle->msg.rhandle = rhandle;
917 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800918}
919
920#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
921
922#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800923void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800924{
925 struct partition_t *partition;
926 struct irq_load_info_t *irq_info;
927
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800928 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800929
930 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
931 if (!irq_info) {
932 tfm_core_panic();
933 }
934
Kevin Pengd399a1f2021-09-08 15:33:14 +0800935 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800936}
937
Kevin Peng67a89fd2021-11-25 11:22:02 +0800938psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800939{
940 struct partition_t *partition;
941 struct irq_load_info_t *irq_info;
942
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800943 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800944
945 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
946 if (!irq_info) {
947 tfm_core_panic();
948 }
949
Kevin Pengd399a1f2021-09-08 15:33:14 +0800950 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800951
952 return 1;
953}
954
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800955/* This API is only used for FLIH. */
956#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800957void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
958{
Ken Liu92ede9f2021-10-20 09:35:00 +0800959 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800960 struct irq_load_info_t *irq_info;
961 struct partition_t *partition;
962
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800963 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800964
965 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
966 if (!irq_info) {
967 tfm_core_panic();
968 }
969
970 if (!irq_info->flih_func) {
971 /* This API is for FLIH IRQs only */
972 tfm_core_panic();
973 }
974
975 if ((partition->signals_asserted & irq_signal) == 0) {
976 /* The signal is not asserted */
977 tfm_core_panic();
978 }
979
Ken Liu92ede9f2021-10-20 09:35:00 +0800980 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800981 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800982 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800983}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800984#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800985
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800986/* This API is only used for SLIH. */
987#if CONFIG_TFM_SLIH_API == 1
988void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800989{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800990 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
991 struct irq_load_info_t *irq_info = NULL;
992 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800993
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800994 partition = GET_CURRENT_COMPONENT();
995
996 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
997 /* It is a fatal error if passed signal is not an interrupt signal. */
998 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800999 tfm_core_panic();
1000 }
1001
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001002 if (irq_info->flih_func) {
1003 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001004 tfm_core_panic();
1005 }
1006
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001007 /* It is a fatal error if passed signal is not currently asserted */
1008 if ((partition->signals_asserted & irq_signal) == 0) {
1009 tfm_core_panic();
1010 }
1011
1012 CRITICAL_SECTION_ENTER(cs_assert);
1013 partition->signals_asserted &= ~irq_signal;
1014 CRITICAL_SECTION_LEAVE(cs_assert);
1015
1016 tfm_hal_irq_clear_pending(irq_info->source);
1017 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001018}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001019#endif
1020#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001021
Shawn Shan038348e2021-09-08 17:11:04 +08001022#if PSA_FRAMEWORK_HAS_MM_IOVEC
1023
1024const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1025 uint32_t invec_idx)
1026{
Mingyang Suna09adda2022-02-16 18:11:33 +08001027 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001028 uint32_t privileged;
1029 struct partition_t *partition = NULL;
1030
1031 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001032 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001033 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001034 tfm_core_panic();
1035 }
1036
Mingyang Suna09adda2022-02-16 18:11:33 +08001037 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001038 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001039
1040 /*
1041 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1042 * Service that received the message.
1043 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001044 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001045 tfm_core_panic();
1046 }
1047
1048 /*
1049 * It is a fatal error if message handle does not refer to a request
1050 * message.
1051 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001052 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001053 tfm_core_panic();
1054 }
1055
1056 /*
1057 * It is a fatal error if invec_idx is equal to or greater than
1058 * PSA_MAX_IOVEC.
1059 */
1060 if (invec_idx >= PSA_MAX_IOVEC) {
1061 tfm_core_panic();
1062 }
1063
1064 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001065 if (handle->msg.in_size[invec_idx] == 0) {
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 mapped using
1071 * psa_map_invec().
1072 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001073 if (IOVEC_IS_MAPPED(handle, (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 input vector has already been accessed
1079 * using psa_read() or psa_skip().
1080 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001081 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001082 tfm_core_panic();
1083 }
1084
1085 /*
1086 * It is a fatal error if the memory reference for the wrap input vector is
1087 * invalid or not readable.
1088 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001089 if (tfm_memory_check(handle->invec[invec_idx].base,
1090 handle->invec[invec_idx].len,
1091 false, TFM_MEMORY_ACCESS_RO,
1092 privileged) != SPM_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001093 tfm_core_panic();
1094 }
1095
Mingyang Suna09adda2022-02-16 18:11:33 +08001096 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001097
Mingyang Suna09adda2022-02-16 18:11:33 +08001098 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001099}
1100
1101void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1102 uint32_t invec_idx)
1103{
Mingyang Suna09adda2022-02-16 18:11:33 +08001104 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001105
1106 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001107 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001108 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001109 tfm_core_panic();
1110 }
1111
1112 /*
1113 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1114 * Service that received the message.
1115 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001116 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001117 tfm_core_panic();
1118 }
1119
1120 /*
1121 * It is a fatal error if message handle does not refer to a request
1122 * message.
1123 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001124 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001125 tfm_core_panic();
1126 }
1127
1128 /*
1129 * It is a fatal error if invec_idx is equal to or greater than
1130 * PSA_MAX_IOVEC.
1131 */
1132 if (invec_idx >= PSA_MAX_IOVEC) {
1133 tfm_core_panic();
1134 }
1135
1136 /*
1137 * It is a fatal error if The input vector has not been mapped by a call to
1138 * psa_map_invec().
1139 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001140 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001141 tfm_core_panic();
1142 }
1143
1144 /*
1145 * It is a fatal error if the input vector has already been unmapped by a
1146 * call to psa_unmap_invec().
1147 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001148 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001149 tfm_core_panic();
1150 }
1151
Mingyang Suna09adda2022-02-16 18:11:33 +08001152 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001153}
1154
1155void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1156 uint32_t outvec_idx)
1157{
Mingyang Suna09adda2022-02-16 18:11:33 +08001158 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001159 uint32_t privileged;
1160 struct partition_t *partition = NULL;
1161
1162 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001163 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001164 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001165 tfm_core_panic();
1166 }
1167
Mingyang Suna09adda2022-02-16 18:11:33 +08001168 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001169 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001170
1171 /*
1172 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1173 * Service that received the message.
1174 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001175 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001176 tfm_core_panic();
1177 }
1178
1179 /*
1180 * It is a fatal error if message handle does not refer to a request
1181 * message.
1182 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001183 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001184 tfm_core_panic();
1185 }
1186
1187 /*
1188 * It is a fatal error if outvec_idx is equal to or greater than
1189 * PSA_MAX_IOVEC.
1190 */
1191 if (outvec_idx >= PSA_MAX_IOVEC) {
1192 tfm_core_panic();
1193 }
1194
1195 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001196 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001197 tfm_core_panic();
1198 }
1199
1200 /*
1201 * It is a fatal error if the output vector has already been mapped using
1202 * psa_map_outvec().
1203 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001204 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001205 tfm_core_panic();
1206 }
1207
1208 /*
1209 * It is a fatal error if the output vector has already been accessed
1210 * using psa_write().
1211 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001212 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001213 tfm_core_panic();
1214 }
1215
1216 /*
1217 * It is a fatal error if the output vector is invalid or not read-write.
1218 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001219 if (tfm_memory_check(handle->outvec[outvec_idx].base,
1220 handle->outvec[outvec_idx].len, false,
Shawn Shan038348e2021-09-08 17:11:04 +08001221 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
1222 tfm_core_panic();
1223 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001224 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001225
Mingyang Suna09adda2022-02-16 18:11:33 +08001226 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001227}
1228
1229void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1230 uint32_t outvec_idx, size_t len)
1231{
Mingyang Suna09adda2022-02-16 18:11:33 +08001232 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001233
1234 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001235 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001236 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001237 tfm_core_panic();
1238 }
1239
1240 /*
1241 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1242 * Service that received the message.
1243 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001244 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001245 tfm_core_panic();
1246 }
1247
1248 /*
1249 * It is a fatal error if message handle does not refer to a request
1250 * message.
1251 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001252 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001253 tfm_core_panic();
1254 }
1255
1256 /*
1257 * It is a fatal error if outvec_idx is equal to or greater than
1258 * PSA_MAX_IOVEC.
1259 */
1260 if (outvec_idx >= PSA_MAX_IOVEC) {
1261 tfm_core_panic();
1262 }
1263
1264 /*
1265 * It is a fatal error if len is greater than the output vector size.
1266 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001267 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001268 tfm_core_panic();
1269 }
1270
1271 /*
1272 * It is a fatal error if The output vector has not been mapped by a call to
1273 * psa_map_outvec().
1274 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001275 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001276 tfm_core_panic();
1277 }
1278
1279 /*
1280 * It is a fatal error if the output vector has already been unmapped by a
1281 * call to psa_unmap_outvec().
1282 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001283 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001284 tfm_core_panic();
1285 }
1286
Mingyang Suna09adda2022-02-16 18:11:33 +08001287 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001288
1289 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001290 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001291}
1292
1293#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */