blob: d0ce0ade97ba18808d9ef095db2f6f1690bbca13 [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
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800174 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
175 if (handle == PSA_NULL_HANDLE) {
176 return PSA_ERROR_PROGRAMMER_ERROR;
177 }
178
Kevin Peng385fda82021-08-18 10:41:19 +0800179 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800180
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800181 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800182 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800183 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800184
185 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800186 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800187 }
188
Mingyang Sun453ad402021-03-17 17:58:33 +0800189 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800190 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800191 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800192 }
193
Ken Liub3b2cb62021-05-22 00:39:28 +0800194 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800195
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800196 /*
197 * It is a PROGRAMMER ERROR if the caller is not authorized to access
198 * the RoT Service.
199 */
200 if (tfm_spm_check_authorization(sid, service, ns_caller)
201 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800202 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800203 }
204
Mingyang Sun453ad402021-03-17 17:58:33 +0800205 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
206
207 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800208 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800209 }
210
Mingyang Sun620c8562021-11-10 11:44:58 +0800211 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800212 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800213 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800214
215 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800216 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800217 }
218
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800219 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800220 handle = tfm_spm_to_user_handle(conn_handle);
221 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800222#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800223 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800224 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
225 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800226 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800227 }
228
229 /*
230 * It is a PROGRAMMER ERROR if the connection is currently
231 * handling a request.
232 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800233 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800234 return PSA_ERROR_PROGRAMMER_ERROR;
235 }
236
Ken Liu0bed7e02022-02-10 12:38:07 +0800237 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800238
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800239 if (!service) {
240 /* FixMe: Need to implement a mechanism to resolve this failure. */
241 return PSA_ERROR_PROGRAMMER_ERROR;
242 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800243#else
244 return PSA_ERROR_PROGRAMMER_ERROR;
245#endif
David Hu733d8f92019-09-23 15:32:40 +0800246 }
247
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800248 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800249
Kevin Pengedb8ee42021-03-09 16:50:11 +0800250 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800251 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800252 * if the memory reference for the wrap input vector is invalid or not
253 * readable.
254 */
255 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800256 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800257 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800258 }
Summer Qinba2346e2019-11-12 16:26:31 +0800259
David Hu733d8f92019-09-23 15:32:40 +0800260 /*
261 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800262 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800263 * the wrap output vector is invalid or not read-write.
264 */
265 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800266 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800267 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800268 }
269
Summer Qinf24dbb52020-07-23 14:53:54 +0800270 spm_memset(invecs, 0, sizeof(invecs));
271 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800272
273 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800274 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
275 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800276
277 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800278 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800279 * memory reference was invalid or not readable.
280 */
281 for (i = 0; i < in_num; i++) {
282 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800283 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800284 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800285 }
286 }
Summer Qinba2346e2019-11-12 16:26:31 +0800287
288 /*
289 * Clients must never overlap input parameters because of the risk of a
290 * double-fetch inconsistency.
291 * Overflow is checked in tfm_memory_check functions.
292 */
293 for (i = 0; i + 1 < in_num; i++) {
294 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100295 if (!((char *) invecs[j].base + invecs[j].len <=
296 (char *) invecs[i].base ||
297 (char *) invecs[j].base >=
298 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800299 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800300 }
301 }
302 }
303
David Hu733d8f92019-09-23 15:32:40 +0800304 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800305 * For client output vector, it is a PROGRAMMER ERROR if the provided
306 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800307 */
308 for (i = 0; i < out_num; i++) {
309 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800310 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800311 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800312 }
313 }
314
Ken Liu0bed7e02022-02-10 12:38:07 +0800315 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800316 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800317
Ken Liu0bed7e02022-02-10 12:38:07 +0800318 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800319}
320
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800321/* Following PSA APIs are only needed by connection-based services */
322#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
323
324psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
325{
326 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800327 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800328 int32_t client_id;
329 psa_handle_t handle;
330 bool ns_caller = tfm_spm_is_ns_caller();
331 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
332
333 /*
334 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
335 * platform.
336 */
337 service = tfm_spm_get_service_by_sid(sid);
338 if (!service) {
339 return PSA_ERROR_CONNECTION_REFUSED;
340 }
341
342 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
343 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
344 return PSA_ERROR_PROGRAMMER_ERROR;
345 }
346
347 /*
348 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
349 * RoT Service.
350 */
351 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
352 return PSA_ERROR_CONNECTION_REFUSED;
353 }
354
355 /*
356 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
357 * not supported on the platform.
358 */
359 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
360 return PSA_ERROR_CONNECTION_REFUSED;
361 }
362
363 client_id = tfm_spm_get_client_id(ns_caller);
364
365 /*
366 * Create connection handle here since it is possible to return the error
367 * code to client when creation fails.
368 */
369 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800370 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800371 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800372 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800373 return PSA_ERROR_CONNECTION_BUSY;
374 }
375
Mingyang Suna09adda2022-02-16 18:11:33 +0800376 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800377 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800378 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800379 client_id, NULL, 0, NULL, 0, NULL);
380
Mingyang Suna09adda2022-02-16 18:11:33 +0800381 return backend_instance.messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800382}
383
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800384psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800385{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800386 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800387 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800388 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800389 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800390
391 /* It will have no effect if called with the NULL handle */
392 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800393 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800394 }
395
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800396 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800397 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800398 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800399 }
400
Kevin Peng385fda82021-08-18 10:41:19 +0800401 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800402
David Hu733d8f92019-09-23 15:32:40 +0800403 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800404 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
405 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800406 */
Kevin Penge61e7052022-01-27 14:57:06 +0800407 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
408 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800409 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800410 }
Shawn Shanb222d892021-01-04 17:41:48 +0800411
Ken Liu0bed7e02022-02-10 12:38:07 +0800412 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800413 if (!service) {
414 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800415 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800416 }
417
Shawn Shanb222d892021-01-04 17:41:48 +0800418 /*
419 * It is a PROGRAMMER ERROR if the connection is currently handling a
420 * request.
421 */
Summer Qin630c76b2020-05-20 10:32:58 +0800422 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800423 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800424 }
425
David Hu733d8f92019-09-23 15:32:40 +0800426 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800427 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
428 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800429
Ken Liu0bed7e02022-02-10 12:38:07 +0800430 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800431}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800432
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800433#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
434
Mingyang Suneeca4652021-07-15 15:19:16 +0800435/* PSA Partition API function body */
436
Kevin Pengdef92de2021-11-10 16:14:48 +0800437#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
438 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800439psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
440 uint32_t timeout)
441{
442 struct partition_t *partition = NULL;
443
444 /*
445 * Timeout[30:0] are reserved for future use.
446 * SPM must ignore the value of RES.
447 */
448 timeout &= PSA_TIMEOUT_MASK;
449
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800450 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800451
452 /*
453 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
454 * signals.
455 */
456 if ((partition->signals_allowed & signal_mask) == 0) {
457 tfm_core_panic();
458 }
459
460 /*
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800461 * backend_instance.wait() blocks the caller thread if no signals are
462 * available. In this case, the return value of this function is temporary
463 * set into runtime context. After new signal(s) are available, the return
464 * value is updated with the available signal(s) and blocked thread gets
465 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800466 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800467 if (timeout == PSA_BLOCK) {
468 return backend_instance.wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800469 }
470
471 return partition->signals_asserted & signal_mask;
472}
Kevin Pengdef92de2021-11-10 16:14:48 +0800473#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800474
Kevin Pengdef92de2021-11-10 16:14:48 +0800475#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800476psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
477{
Mingyang Suna09adda2022-02-16 18:11:33 +0800478 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800479 struct partition_t *partition = NULL;
480 uint32_t privileged;
481
482 /*
483 * Only one message could be retrieved every time for psa_get(). It is a
484 * fatal error if the input signal has more than a signal bit set.
485 */
486 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
487 tfm_core_panic();
488 }
489
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800490 partition = GET_CURRENT_COMPONENT();
491
Kevin Penga40d29f2022-01-19 14:44:34 +0800492 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800493
494 /*
495 * Write the message to the service buffer. It is a fatal error if the
496 * input msg pointer is not a valid memory reference or not read-write.
497 */
498 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
499 privileged) != SPM_SUCCESS) {
500 tfm_core_panic();
501 }
502
503 /*
504 * It is a fatal error if the caller call psa_get() when no message has
505 * been set. The caller must call this function after an RoT Service signal
506 * is returned by psa_wait().
507 */
508 if (partition->signals_asserted == 0) {
509 tfm_core_panic();
510 }
511
512 /*
513 * It is a fatal error if the RoT Service signal is not currently asserted.
514 */
515 if ((partition->signals_asserted & signal) == 0) {
516 tfm_core_panic();
517 }
518
519 /*
520 * Get message by signal from partition. It is a fatal error if getting
521 * failed, which means the input signal is not correspond to an RoT service.
522 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800523 handle = spm_get_handle_by_signal(partition, signal);
524 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800525 return PSA_ERROR_DOES_NOT_EXIST;
526 }
527
Mingyang Suna09adda2022-02-16 18:11:33 +0800528 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800529
530 return PSA_SUCCESS;
531}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800532#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800533
Mingyang Sunb26b2802021-07-07 11:25:00 +0800534size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
535 void *buffer, size_t num_bytes)
536{
537 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800538 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800539 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800540
541 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800542 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800543 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800544 tfm_core_panic();
545 }
546
Mingyang Suna09adda2022-02-16 18:11:33 +0800547 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
548 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800549
550 /*
551 * It is a fatal error if message handle does not refer to a request
552 * message
553 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800554 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800555 tfm_core_panic();
556 }
557
558 /*
559 * It is a fatal error if invec_idx is equal to or greater than
560 * PSA_MAX_IOVEC
561 */
562 if (invec_idx >= PSA_MAX_IOVEC) {
563 tfm_core_panic();
564 }
565
566 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800567 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800568 return 0;
569 }
570
Shawn Shan038348e2021-09-08 17:11:04 +0800571#if PSA_FRAMEWORK_HAS_MM_IOVEC
572 /*
573 * It is a fatal error if the input vector has already been mapped using
574 * psa_map_invec().
575 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800576 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800577 tfm_core_panic();
578 }
579
Mingyang Suna09adda2022-02-16 18:11:33 +0800580 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800581#endif
582
Mingyang Sunb26b2802021-07-07 11:25:00 +0800583 /*
584 * Copy the client data to the service buffer. It is a fatal error
585 * if the memory reference for buffer is invalid or not read-write.
586 */
587 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800588 TFM_MEMORY_ACCESS_RW, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800589 tfm_core_panic();
590 }
591
Mingyang Suna09adda2022-02-16 18:11:33 +0800592 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
593 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800594
Mingyang Suna09adda2022-02-16 18:11:33 +0800595 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800596
597 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800598 handle->invec[invec_idx].base =
599 (char *)handle->invec[invec_idx].base + bytes;
600 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800601
602 return bytes;
603}
604
605size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
606 size_t num_bytes)
607{
Mingyang Suna09adda2022-02-16 18:11:33 +0800608 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800609
610 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800611 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800612 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800613 tfm_core_panic();
614 }
615
616 /*
617 * It is a fatal error if message handle does not refer to a request
618 * message
619 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800620 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800621 tfm_core_panic();
622 }
623
624 /*
625 * It is a fatal error if invec_idx is equal to or greater than
626 * PSA_MAX_IOVEC
627 */
628 if (invec_idx >= PSA_MAX_IOVEC) {
629 tfm_core_panic();
630 }
631
632 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800633 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800634 return 0;
635 }
636
Shawn Shan038348e2021-09-08 17:11:04 +0800637#if PSA_FRAMEWORK_HAS_MM_IOVEC
638 /*
639 * It is a fatal error if the input vector has already been mapped using
640 * psa_map_invec().
641 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800642 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800643 tfm_core_panic();
644 }
645
Mingyang Suna09adda2022-02-16 18:11:33 +0800646 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800647#endif
648
Mingyang Sunb26b2802021-07-07 11:25:00 +0800649 /*
650 * If num_bytes is greater than the remaining size of the input vector then
651 * the remaining size of the input vector is used.
652 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800653 if (num_bytes > handle->msg.in_size[invec_idx]) {
654 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800655 }
656
657 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800658 handle->invec[invec_idx].base =
659 (char *)handle->invec[invec_idx].base + num_bytes;
660 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800661
662 return num_bytes;
663}
664
665void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
666 const void *buffer, size_t num_bytes)
667{
Mingyang Suna09adda2022-02-16 18:11:33 +0800668 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800669 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800670
671 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800672 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800673 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800674 tfm_core_panic();
675 }
676
Mingyang Suna09adda2022-02-16 18:11:33 +0800677 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
678 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800679
680 /*
681 * It is a fatal error if message handle does not refer to a request
682 * message
683 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800684 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800685 tfm_core_panic();
686 }
687
688 /*
689 * It is a fatal error if outvec_idx is equal to or greater than
690 * PSA_MAX_IOVEC
691 */
692 if (outvec_idx >= PSA_MAX_IOVEC) {
693 tfm_core_panic();
694 }
695
696 /*
697 * It is a fatal error if the call attempts to write data past the end of
698 * the client output vector
699 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800700 if (num_bytes > handle->msg.out_size[outvec_idx] -
701 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800702 tfm_core_panic();
703 }
704
Shawn Shan038348e2021-09-08 17:11:04 +0800705#if PSA_FRAMEWORK_HAS_MM_IOVEC
706 /*
707 * It is a fatal error if the output vector has already been mapped using
708 * psa_map_outvec().
709 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800710 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800711 tfm_core_panic();
712 }
713
Mingyang Suna09adda2022-02-16 18:11:33 +0800714 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800715#endif
716
Mingyang Sunb26b2802021-07-07 11:25:00 +0800717 /*
718 * Copy the service buffer to client outvecs. It is a fatal error
719 * if the memory reference for buffer is invalid or not readable.
720 */
721 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800722 TFM_MEMORY_ACCESS_RO, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800723 tfm_core_panic();
724 }
725
Mingyang Suna09adda2022-02-16 18:11:33 +0800726 spm_memcpy((char *)handle->outvec[outvec_idx].base +
727 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800728
729 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800730 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800731}
732
Ken Liuf8c7e532022-02-10 15:03:04 +0800733psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
734 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800735{
Ken Liu0bed7e02022-02-10 12:38:07 +0800736 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800737 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800738 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800739 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800740
741 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800742 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800743 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800744 tfm_core_panic();
745 }
746
747 /*
748 * RoT Service information is needed in this function, stored it in message
749 * body structure. Only two parameters are passed in this function: handle
750 * and status, so it is useful and simply to do like this.
751 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800752 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800753 if (!service) {
754 tfm_core_panic();
755 }
756
Mingyang Suna09adda2022-02-16 18:11:33 +0800757 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800758 case PSA_IPC_CONNECT:
759 /*
760 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
761 * input status is PSA_SUCCESS. Others return values are based on the
762 * input status.
763 */
764 if (status == PSA_SUCCESS) {
765 ret = msg_handle;
766 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
767 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800768 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800769 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800770 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
771 /* Fail the client connection, indicating a transient error. */
772 ret = PSA_ERROR_CONNECTION_BUSY;
773 } else {
774 tfm_core_panic();
775 }
776 break;
777 case PSA_IPC_DISCONNECT:
778 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800779 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800780
781 /*
782 * If the message type is PSA_IPC_DISCONNECT, then the status code is
783 * ignored
784 */
785 break;
786 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800787 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800788
789#if PSA_FRAMEWORK_HAS_MM_IOVEC
790
791 /*
792 * If the unmapped function is not called for an input/output vector
793 * that has been mapped, the framework will remove the mapping.
794 */
795 int i;
796
797 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800798 if (IOVEC_IS_MAPPED(handle, i) &&
799 (!IOVEC_IS_UNMAPPED(handle, i))) {
800 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800801 /*
802 * Any output vectors that are still mapped will report that
803 * zero bytes have been written.
804 */
805 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800806 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800807 }
808 }
809 }
810
811#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800812 /* Reply to a request message. Return values are based on status */
813 ret = status;
814 /*
815 * The total number of bytes written to a single parameter must be
816 * reported to the client by updating the len member of the
817 * psa_outvec structure for the parameter before returning from
818 * psa_call().
819 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800820 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800821 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800822 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800823 }
824 } else {
825 tfm_core_panic();
826 }
827 }
828
829 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
830 /*
831 * If the source of the programmer error is a Secure Partition, the SPM
832 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
833 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800834 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800835 tfm_core_panic();
836 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800837 }
838
Mingyang Sun620c8562021-11-10 11:44:58 +0800839 /*
840 * TODO: It can be optimized further by moving critical section protection
841 * to mailbox. Also need to check implementation when secure context is
842 * involved.
843 */
844 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800845 ret = backend_instance.replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800846 CRITICAL_SECTION_LEAVE(cs_assert);
847
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800848 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
849 tfm_spm_free_conn_handle(handle);
850 } else {
851 handle->status = TFM_HANDLE_STATUS_IDLE;
852 }
853
Mingyang Sun620c8562021-11-10 11:44:58 +0800854 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800855}
856
Kevin Peng613b4172022-02-15 14:41:44 +0800857#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800858void tfm_spm_partition_psa_notify(int32_t partition_id)
859{
Ken Liu5d73c872021-08-19 19:23:17 +0800860 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
861
862 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800863}
864
865void tfm_spm_partition_psa_clear(void)
866{
Ken Liu92ede9f2021-10-20 09:35:00 +0800867 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800868 struct partition_t *partition = NULL;
869
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800870 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800871
872 /*
873 * It is a fatal error if the Secure Partition's doorbell signal is not
874 * currently asserted.
875 */
876 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
877 tfm_core_panic();
878 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800879
880 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800881 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800882 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800883}
Kevin Peng613b4172022-02-15 14:41:44 +0800884#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800885
Mingyang Sunb26b2802021-07-07 11:25:00 +0800886void tfm_spm_partition_psa_panic(void)
887{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100888#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
889 tfm_hal_system_halt();
890#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800891 /*
892 * PSA FF recommends that the SPM causes the system to restart when a secure
893 * partition panics.
894 */
895 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100896#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800897}
898
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800899/* psa_set_rhandle is only needed by connection-based services */
900#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
901
902void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
903{
Mingyang Suna09adda2022-02-16 18:11:33 +0800904 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800905
906 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800907 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800908 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800909 tfm_core_panic();
910 }
911
912 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800913 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800914 tfm_core_panic();
915 }
916
Mingyang Suna09adda2022-02-16 18:11:33 +0800917 handle->msg.rhandle = rhandle;
918 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800919}
920
921#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
922
923#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800924void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800925{
926 struct partition_t *partition;
927 struct irq_load_info_t *irq_info;
928
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800929 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800930
931 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
932 if (!irq_info) {
933 tfm_core_panic();
934 }
935
Kevin Pengd399a1f2021-09-08 15:33:14 +0800936 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800937}
938
Kevin Peng67a89fd2021-11-25 11:22:02 +0800939psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800940{
941 struct partition_t *partition;
942 struct irq_load_info_t *irq_info;
943
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800944 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800945
946 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
947 if (!irq_info) {
948 tfm_core_panic();
949 }
950
Kevin Pengd399a1f2021-09-08 15:33:14 +0800951 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800952
953 return 1;
954}
955
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800956/* This API is only used for FLIH. */
957#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800958void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
959{
Ken Liu92ede9f2021-10-20 09:35:00 +0800960 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800961 struct irq_load_info_t *irq_info;
962 struct partition_t *partition;
963
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800964 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800965
966 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
967 if (!irq_info) {
968 tfm_core_panic();
969 }
970
971 if (!irq_info->flih_func) {
972 /* This API is for FLIH IRQs only */
973 tfm_core_panic();
974 }
975
976 if ((partition->signals_asserted & irq_signal) == 0) {
977 /* The signal is not asserted */
978 tfm_core_panic();
979 }
980
Ken Liu92ede9f2021-10-20 09:35:00 +0800981 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800982 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800983 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800984}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800985#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800986
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800987/* This API is only used for SLIH. */
988#if CONFIG_TFM_SLIH_API == 1
989void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800990{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800991 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
992 struct irq_load_info_t *irq_info = NULL;
993 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800994
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800995 partition = GET_CURRENT_COMPONENT();
996
997 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
998 /* It is a fatal error if passed signal is not an interrupt signal. */
999 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001000 tfm_core_panic();
1001 }
1002
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001003 if (irq_info->flih_func) {
1004 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001005 tfm_core_panic();
1006 }
1007
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001008 /* It is a fatal error if passed signal is not currently asserted */
1009 if ((partition->signals_asserted & irq_signal) == 0) {
1010 tfm_core_panic();
1011 }
1012
1013 CRITICAL_SECTION_ENTER(cs_assert);
1014 partition->signals_asserted &= ~irq_signal;
1015 CRITICAL_SECTION_LEAVE(cs_assert);
1016
1017 tfm_hal_irq_clear_pending(irq_info->source);
1018 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001019}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001020#endif
1021#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001022
Shawn Shan038348e2021-09-08 17:11:04 +08001023#if PSA_FRAMEWORK_HAS_MM_IOVEC
1024
1025const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1026 uint32_t invec_idx)
1027{
Mingyang Suna09adda2022-02-16 18:11:33 +08001028 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001029 uint32_t privileged;
1030 struct partition_t *partition = NULL;
1031
1032 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001033 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001034 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001035 tfm_core_panic();
1036 }
1037
Mingyang Suna09adda2022-02-16 18:11:33 +08001038 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001039 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001040
1041 /*
1042 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1043 * Service that received the message.
1044 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001045 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001046 tfm_core_panic();
1047 }
1048
1049 /*
1050 * It is a fatal error if message handle does not refer to a request
1051 * message.
1052 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001053 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001054 tfm_core_panic();
1055 }
1056
1057 /*
1058 * It is a fatal error if invec_idx is equal to or greater than
1059 * PSA_MAX_IOVEC.
1060 */
1061 if (invec_idx >= PSA_MAX_IOVEC) {
1062 tfm_core_panic();
1063 }
1064
1065 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001066 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001067 tfm_core_panic();
1068 }
1069
1070 /*
1071 * It is a fatal error if the input vector has already been mapped using
1072 * psa_map_invec().
1073 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001074 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001075 tfm_core_panic();
1076 }
1077
1078 /*
1079 * It is a fatal error if the input vector has already been accessed
1080 * using psa_read() or psa_skip().
1081 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001082 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001083 tfm_core_panic();
1084 }
1085
1086 /*
1087 * It is a fatal error if the memory reference for the wrap input vector is
1088 * invalid or not readable.
1089 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001090 if (tfm_memory_check(handle->invec[invec_idx].base,
1091 handle->invec[invec_idx].len,
1092 false, TFM_MEMORY_ACCESS_RO,
1093 privileged) != SPM_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001094 tfm_core_panic();
1095 }
1096
Mingyang Suna09adda2022-02-16 18:11:33 +08001097 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001098
Mingyang Suna09adda2022-02-16 18:11:33 +08001099 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001100}
1101
1102void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1103 uint32_t invec_idx)
1104{
Mingyang Suna09adda2022-02-16 18:11:33 +08001105 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001106
1107 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001108 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001109 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001110 tfm_core_panic();
1111 }
1112
1113 /*
1114 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1115 * Service that received the message.
1116 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001117 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001118 tfm_core_panic();
1119 }
1120
1121 /*
1122 * It is a fatal error if message handle does not refer to a request
1123 * message.
1124 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001125 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001126 tfm_core_panic();
1127 }
1128
1129 /*
1130 * It is a fatal error if invec_idx is equal to or greater than
1131 * PSA_MAX_IOVEC.
1132 */
1133 if (invec_idx >= PSA_MAX_IOVEC) {
1134 tfm_core_panic();
1135 }
1136
1137 /*
1138 * It is a fatal error if The input vector has not been mapped by a call to
1139 * psa_map_invec().
1140 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001141 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001142 tfm_core_panic();
1143 }
1144
1145 /*
1146 * It is a fatal error if the input vector has already been unmapped by a
1147 * call to psa_unmap_invec().
1148 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001149 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001150 tfm_core_panic();
1151 }
1152
Mingyang Suna09adda2022-02-16 18:11:33 +08001153 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001154}
1155
1156void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1157 uint32_t outvec_idx)
1158{
Mingyang Suna09adda2022-02-16 18:11:33 +08001159 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001160 uint32_t privileged;
1161 struct partition_t *partition = NULL;
1162
1163 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001164 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001165 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001166 tfm_core_panic();
1167 }
1168
Mingyang Suna09adda2022-02-16 18:11:33 +08001169 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001170 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001171
1172 /*
1173 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1174 * Service that received the message.
1175 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001176 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001177 tfm_core_panic();
1178 }
1179
1180 /*
1181 * It is a fatal error if message handle does not refer to a request
1182 * message.
1183 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001184 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001185 tfm_core_panic();
1186 }
1187
1188 /*
1189 * It is a fatal error if outvec_idx is equal to or greater than
1190 * PSA_MAX_IOVEC.
1191 */
1192 if (outvec_idx >= PSA_MAX_IOVEC) {
1193 tfm_core_panic();
1194 }
1195
1196 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001197 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001198 tfm_core_panic();
1199 }
1200
1201 /*
1202 * It is a fatal error if the output vector has already been mapped using
1203 * psa_map_outvec().
1204 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001205 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001206 tfm_core_panic();
1207 }
1208
1209 /*
1210 * It is a fatal error if the output vector has already been accessed
1211 * using psa_write().
1212 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001213 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001214 tfm_core_panic();
1215 }
1216
1217 /*
1218 * It is a fatal error if the output vector is invalid or not read-write.
1219 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001220 if (tfm_memory_check(handle->outvec[outvec_idx].base,
1221 handle->outvec[outvec_idx].len, false,
Shawn Shan038348e2021-09-08 17:11:04 +08001222 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
1223 tfm_core_panic();
1224 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001225 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001226
Mingyang Suna09adda2022-02-16 18:11:33 +08001227 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001228}
1229
1230void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1231 uint32_t outvec_idx, size_t len)
1232{
Mingyang Suna09adda2022-02-16 18:11:33 +08001233 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001234
1235 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001236 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001237 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001238 tfm_core_panic();
1239 }
1240
1241 /*
1242 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1243 * Service that received the message.
1244 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001245 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001246 tfm_core_panic();
1247 }
1248
1249 /*
1250 * It is a fatal error if message handle does not refer to a request
1251 * message.
1252 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001253 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001254 tfm_core_panic();
1255 }
1256
1257 /*
1258 * It is a fatal error if outvec_idx is equal to or greater than
1259 * PSA_MAX_IOVEC.
1260 */
1261 if (outvec_idx >= PSA_MAX_IOVEC) {
1262 tfm_core_panic();
1263 }
1264
1265 /*
1266 * It is a fatal error if len is greater than the output vector size.
1267 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001268 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001269 tfm_core_panic();
1270 }
1271
1272 /*
1273 * It is a fatal error if The output vector has not been mapped by a call to
1274 * psa_map_outvec().
1275 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001276 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001277 tfm_core_panic();
1278 }
1279
1280 /*
1281 * It is a fatal error if the output vector has already been unmapped by a
1282 * call to psa_unmap_outvec().
1283 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001284 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001285 tfm_core_panic();
1286 }
1287
Mingyang Suna09adda2022-02-16 18:11:33 +08001288 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001289
1290 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001291 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001292}
1293
1294#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */