blob: 02c93521b1dac086e44caeaa512dd5a8f942f639 [file] [log] [blame]
David Hu733d8f92019-09-23 15:32:40 +08001/*
Mingyang Sunbb4a42a2021-12-14 15:18:52 +08002 * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
David Hu733d8f92019-09-23 15:32:40 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
Mingyang Suneeca4652021-07-15 15:19:16 +08008#include <stdint.h>
Mingyang Sunb26b2802021-07-07 11:25:00 +08009#include "bitops.h"
Mingyang Sun4609ac72022-02-08 18:56:35 +080010#include "config_impl.h"
Ken Liu92ede9f2021-10-20 09:35:00 +080011#include "critical_section.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080012#include "psa/lifecycle.h"
David Hu733d8f92019-09-23 15:32:40 +080013#include "psa/service.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080014#include "interrupt.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080015#include "spm_ipc.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080016#include "tfm_arch.h"
David Hu733d8f92019-09-23 15:32:40 +080017#include "tfm_core_utils.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080018#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080019#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080020#include "load/interrupt_defs.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080021#include "ffm/psa_api.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080022#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080023#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080024#include "ffm/psa_api.h"
Ken Liubcae38b2021-01-20 15:47:44 +080025#include "ffm/spm_error_base.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080026#include "tfm_rpc.h"
27#include "tfm_spm_hal.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080028#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080029#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080030#include "tfm_psa_call_pack.h"
David Hu733d8f92019-09-23 15:32:40 +080031
Ken Liub3b2cb62021-05-22 00:39:28 +080032#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080033extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080034
Shawn Shan038348e2021-09-08 17:11:04 +080035#if PSA_FRAMEWORK_HAS_MM_IOVEC
36
37/*
38 * The MM-IOVEC status
39 * The max total number of invec and outvec is 8.
40 * Each invec/outvec takes 4 bit, 32 bits in total.
41 *
42 * The encoding format of the MM-IOVEC status:
43 *--------------------------------------------------------------
44 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
45 *--------------------------------------------------------------
46 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
47 *--------------------------------------------------------------
48 *
49 * Take invec[0] as an example:
50 *
51 * bit 0: whether invec[0] has been mapped.
52 * bit 1: whether invec[0] has been unmapped.
53 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
54 * psa_write().
55 * bit 3: reserved for invec[0].
56 */
57
58#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
59#define OUTVEC_IDX_BASE 4 /*
60 * Base index of outvec.
61 * There are four invecs in front of
62 * outvec.
63 */
64#define INVEC_IDX_BASE 0 /* Base index of invec. */
65
66#define IOVEC_MAPPED_BIT (1U << 0)
67#define IOVEC_UNMAPPED_BIT (1U << 1)
68#define IOVEC_ACCESSED_BIT (1U << 2)
69
Mingyang Suna09adda2022-02-16 18:11:33 +080070#define IOVEC_IS_MAPPED(handle, iovec_idx) \
71 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080072 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080073#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
74 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080075 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080076#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
77 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080078 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080079#define SET_IOVEC_MAPPED(handle, iovec_idx) \
80 (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080081 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080082#define SET_IOVEC_UNMAPPED(handle, iovec_idx) \
83 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080084 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080085#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
86 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080087 ((iovec_idx) * IOVEC_STATUS_BITS)))
88
89#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
90
Xinyu Zhangb287ef82021-11-03 18:38:50 +080091void spm_handle_programmer_errors(psa_status_t status)
92{
93 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
94 status == PSA_ERROR_CONNECTION_REFUSED ||
95 status == PSA_ERROR_CONNECTION_BUSY) {
96 if (!tfm_spm_is_ns_caller()) {
97 tfm_core_panic();
98 }
99 }
100}
101
Mingyang Suneeca4652021-07-15 15:19:16 +0800102uint32_t tfm_spm_get_lifecycle_state(void)
103{
104 /*
105 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
106 * implemented in the future.
107 */
108 return PSA_LIFECYCLE_UNKNOWN;
109}
110
111/* PSA Client API function body */
112
Mingyang Sund44522a2020-01-16 16:48:37 +0800113uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800114{
115 return PSA_FRAMEWORK_VERSION;
116}
117
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800118uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800119{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800120 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800121 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800122
123 /*
124 * It should return PSA_VERSION_NONE if the RoT Service is not
125 * implemented.
126 */
127 service = tfm_spm_get_service_by_sid(sid);
128 if (!service) {
129 return PSA_VERSION_NONE;
130 }
131
132 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800133 * It should return PSA_VERSION_NONE if the caller is not authorized
134 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800135 */
Ken Liubcae38b2021-01-20 15:47:44 +0800136 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800137 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800138 }
139
Ken Liuacd2a572021-05-12 16:19:04 +0800140 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800141}
142
Mingyang Suneeca4652021-07-15 15:19:16 +0800143psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
144 uint32_t ctrl_param,
145 const psa_invec *inptr,
146 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800147{
148 psa_invec invecs[PSA_MAX_IOVEC];
149 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800150 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800151 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800152 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800153 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800154 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800155 uint32_t privileged;
Mingyang Sun620c8562021-11-10 11:44:58 +0800156 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800157 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800158 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
159 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
160 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800161
162 /* The request type must be zero or positive. */
163 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800164 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800165 }
David Hu733d8f92019-09-23 15:32:40 +0800166
Shawn Shanb222d892021-01-04 17:41:48 +0800167 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800168 if ((in_num > PSA_MAX_IOVEC) ||
169 (out_num > PSA_MAX_IOVEC) ||
170 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800171 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800172 }
173
Kevin Peng385fda82021-08-18 10:41:19 +0800174 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800175
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800176 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800177 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800178 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800179
180 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800181 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800182 }
183
Mingyang Sun453ad402021-03-17 17:58:33 +0800184 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800185 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800186 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800187 }
188
Ken Liub3b2cb62021-05-22 00:39:28 +0800189 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800190
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800191 /*
192 * It is a PROGRAMMER ERROR if the caller is not authorized to access
193 * the RoT Service.
194 */
195 if (tfm_spm_check_authorization(sid, service, ns_caller)
196 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800197 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800198 }
199
Mingyang Sun453ad402021-03-17 17:58:33 +0800200 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
201
202 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800203 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800204 }
205
Mingyang Sun620c8562021-11-10 11:44:58 +0800206 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800207 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800208 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800209
210 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800211 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800212 }
213
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800214 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800215 handle = tfm_spm_to_user_handle(conn_handle);
216 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800217#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800218 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800219 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
220 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800221 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800222 }
223
224 /*
225 * It is a PROGRAMMER ERROR if the connection is currently
226 * handling a request.
227 */
228 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800229 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800230 }
231
232 /*
233 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
234 * has been terminated by the RoT Service.
235 */
236 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
237 return PSA_ERROR_PROGRAMMER_ERROR;
238 }
239
Ken Liu0bed7e02022-02-10 12:38:07 +0800240 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800241
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800242 if (!service) {
243 /* FixMe: Need to implement a mechanism to resolve this failure. */
244 return PSA_ERROR_PROGRAMMER_ERROR;
245 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800246#else
247 return PSA_ERROR_PROGRAMMER_ERROR;
248#endif
David Hu733d8f92019-09-23 15:32:40 +0800249 }
250
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800251 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800252
Kevin Pengedb8ee42021-03-09 16:50:11 +0800253 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800254 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800255 * if the memory reference for the wrap input vector is invalid or not
256 * readable.
257 */
258 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800259 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800260 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800261 }
Summer Qinba2346e2019-11-12 16:26:31 +0800262
David Hu733d8f92019-09-23 15:32:40 +0800263 /*
264 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800265 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800266 * the wrap output vector is invalid or not read-write.
267 */
268 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800269 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800270 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800271 }
272
Summer Qinf24dbb52020-07-23 14:53:54 +0800273 spm_memset(invecs, 0, sizeof(invecs));
274 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800275
276 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800277 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
278 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800279
280 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800281 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800282 * memory reference was invalid or not readable.
283 */
284 for (i = 0; i < in_num; i++) {
285 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800286 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800287 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800288 }
289 }
Summer Qinba2346e2019-11-12 16:26:31 +0800290
291 /*
292 * Clients must never overlap input parameters because of the risk of a
293 * double-fetch inconsistency.
294 * Overflow is checked in tfm_memory_check functions.
295 */
296 for (i = 0; i + 1 < in_num; i++) {
297 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100298 if (!((char *) invecs[j].base + invecs[j].len <=
299 (char *) invecs[i].base ||
300 (char *) invecs[j].base >=
301 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800302 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800303 }
304 }
305 }
306
David Hu733d8f92019-09-23 15:32:40 +0800307 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800308 * For client output vector, it is a PROGRAMMER ERROR if the provided
309 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800310 */
311 for (i = 0; i < out_num; i++) {
312 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800313 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800314 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800315 }
316 }
317
Ken Liu0bed7e02022-02-10 12:38:07 +0800318 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800319 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800320
Ken Liu0bed7e02022-02-10 12:38:07 +0800321 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800322}
323
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800324/* Following PSA APIs are only needed by connection-based services */
325#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
326
327psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
328{
329 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800330 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800331 int32_t client_id;
332 psa_handle_t handle;
333 bool ns_caller = tfm_spm_is_ns_caller();
334 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
335
336 /*
337 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
338 * platform.
339 */
340 service = tfm_spm_get_service_by_sid(sid);
341 if (!service) {
342 return PSA_ERROR_CONNECTION_REFUSED;
343 }
344
345 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
346 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
347 return PSA_ERROR_PROGRAMMER_ERROR;
348 }
349
350 /*
351 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
352 * RoT Service.
353 */
354 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
355 return PSA_ERROR_CONNECTION_REFUSED;
356 }
357
358 /*
359 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
360 * not supported on the platform.
361 */
362 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
363 return PSA_ERROR_CONNECTION_REFUSED;
364 }
365
366 client_id = tfm_spm_get_client_id(ns_caller);
367
368 /*
369 * Create connection handle here since it is possible to return the error
370 * code to client when creation fails.
371 */
372 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800373 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800374 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800375 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800376 return PSA_ERROR_CONNECTION_BUSY;
377 }
378
Mingyang Suna09adda2022-02-16 18:11:33 +0800379 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800380 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800381 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800382 client_id, NULL, 0, NULL, 0, NULL);
383
Mingyang Suna09adda2022-02-16 18:11:33 +0800384 return backend_instance.messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800385}
386
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800387psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800388{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800389 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800390 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800391 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800392 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800393
394 /* It will have no effect if called with the NULL handle */
395 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800396 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800397 }
398
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800399 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800400 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800401 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800402 }
403
Kevin Peng385fda82021-08-18 10:41:19 +0800404 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800405
David Hu733d8f92019-09-23 15:32:40 +0800406 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800407 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
408 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800409 */
Kevin Penge61e7052022-01-27 14:57:06 +0800410 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
411 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800412 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800413 }
Shawn Shanb222d892021-01-04 17:41:48 +0800414
Ken Liu0bed7e02022-02-10 12:38:07 +0800415 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800416 if (!service) {
417 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800418 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800419 }
420
Shawn Shanb222d892021-01-04 17:41:48 +0800421 /*
422 * It is a PROGRAMMER ERROR if the connection is currently handling a
423 * request.
424 */
Summer Qin630c76b2020-05-20 10:32:58 +0800425 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800426 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800427 }
428
David Hu733d8f92019-09-23 15:32:40 +0800429 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800430 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
431 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800432
Ken Liu0bed7e02022-02-10 12:38:07 +0800433 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800434}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800435
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800436#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
437
Mingyang Suneeca4652021-07-15 15:19:16 +0800438/* PSA Partition API function body */
439
Kevin Pengdef92de2021-11-10 16:14:48 +0800440#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
441 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800442psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
443 uint32_t timeout)
444{
445 struct partition_t *partition = NULL;
446
447 /*
448 * Timeout[30:0] are reserved for future use.
449 * SPM must ignore the value of RES.
450 */
451 timeout &= PSA_TIMEOUT_MASK;
452
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800453 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800454
455 /*
456 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
457 * signals.
458 */
459 if ((partition->signals_allowed & signal_mask) == 0) {
460 tfm_core_panic();
461 }
462
463 /*
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800464 * backend_instance.wait() blocks the caller thread if no signals are
465 * available. In this case, the return value of this function is temporary
466 * set into runtime context. After new signal(s) are available, the return
467 * value is updated with the available signal(s) and blocked thread gets
468 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800469 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800470 if (timeout == PSA_BLOCK) {
471 return backend_instance.wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800472 }
473
474 return partition->signals_asserted & signal_mask;
475}
Kevin Pengdef92de2021-11-10 16:14:48 +0800476#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800477
Kevin Pengdef92de2021-11-10 16:14:48 +0800478#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800479psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
480{
Mingyang Suna09adda2022-02-16 18:11:33 +0800481 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800482 struct partition_t *partition = NULL;
483 uint32_t privileged;
484
485 /*
486 * Only one message could be retrieved every time for psa_get(). It is a
487 * fatal error if the input signal has more than a signal bit set.
488 */
489 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
490 tfm_core_panic();
491 }
492
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800493 partition = GET_CURRENT_COMPONENT();
494
Kevin Penga40d29f2022-01-19 14:44:34 +0800495 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800496
497 /*
498 * Write the message to the service buffer. It is a fatal error if the
499 * input msg pointer is not a valid memory reference or not read-write.
500 */
501 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
502 privileged) != SPM_SUCCESS) {
503 tfm_core_panic();
504 }
505
506 /*
507 * It is a fatal error if the caller call psa_get() when no message has
508 * been set. The caller must call this function after an RoT Service signal
509 * is returned by psa_wait().
510 */
511 if (partition->signals_asserted == 0) {
512 tfm_core_panic();
513 }
514
515 /*
516 * It is a fatal error if the RoT Service signal is not currently asserted.
517 */
518 if ((partition->signals_asserted & signal) == 0) {
519 tfm_core_panic();
520 }
521
522 /*
523 * Get message by signal from partition. It is a fatal error if getting
524 * failed, which means the input signal is not correspond to an RoT service.
525 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800526 handle = spm_get_handle_by_signal(partition, signal);
527 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800528 return PSA_ERROR_DOES_NOT_EXIST;
529 }
530
Mingyang Suna09adda2022-02-16 18:11:33 +0800531 handle->status = TFM_HANDLE_STATUS_ACTIVE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800532
Mingyang Suna09adda2022-02-16 18:11:33 +0800533 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800534
535 return PSA_SUCCESS;
536}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800537#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800538
Mingyang Sunb26b2802021-07-07 11:25:00 +0800539size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
540 void *buffer, size_t num_bytes)
541{
542 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800543 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800544 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800545
546 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800547 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800548 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800549 tfm_core_panic();
550 }
551
Mingyang Suna09adda2022-02-16 18:11:33 +0800552 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
553 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800554
555 /*
556 * It is a fatal error if message handle does not refer to a request
557 * message
558 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800559 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800560 tfm_core_panic();
561 }
562
563 /*
564 * It is a fatal error if invec_idx is equal to or greater than
565 * PSA_MAX_IOVEC
566 */
567 if (invec_idx >= PSA_MAX_IOVEC) {
568 tfm_core_panic();
569 }
570
571 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800572 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800573 return 0;
574 }
575
Shawn Shan038348e2021-09-08 17:11:04 +0800576#if PSA_FRAMEWORK_HAS_MM_IOVEC
577 /*
578 * It is a fatal error if the input vector has already been mapped using
579 * psa_map_invec().
580 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800581 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800582 tfm_core_panic();
583 }
584
Mingyang Suna09adda2022-02-16 18:11:33 +0800585 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800586#endif
587
Mingyang Sunb26b2802021-07-07 11:25:00 +0800588 /*
589 * Copy the client data to the service buffer. It is a fatal error
590 * if the memory reference for buffer is invalid or not read-write.
591 */
592 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800593 TFM_MEMORY_ACCESS_RW, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800594 tfm_core_panic();
595 }
596
Mingyang Suna09adda2022-02-16 18:11:33 +0800597 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
598 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800599
Mingyang Suna09adda2022-02-16 18:11:33 +0800600 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800601
602 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800603 handle->invec[invec_idx].base =
604 (char *)handle->invec[invec_idx].base + bytes;
605 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800606
607 return bytes;
608}
609
610size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
611 size_t num_bytes)
612{
Mingyang Suna09adda2022-02-16 18:11:33 +0800613 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800614
615 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800616 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800617 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800618 tfm_core_panic();
619 }
620
621 /*
622 * It is a fatal error if message handle does not refer to a request
623 * message
624 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800625 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800626 tfm_core_panic();
627 }
628
629 /*
630 * It is a fatal error if invec_idx is equal to or greater than
631 * PSA_MAX_IOVEC
632 */
633 if (invec_idx >= PSA_MAX_IOVEC) {
634 tfm_core_panic();
635 }
636
637 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800638 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800639 return 0;
640 }
641
Shawn Shan038348e2021-09-08 17:11:04 +0800642#if PSA_FRAMEWORK_HAS_MM_IOVEC
643 /*
644 * It is a fatal error if the input vector has already been mapped using
645 * psa_map_invec().
646 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800647 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800648 tfm_core_panic();
649 }
650
Mingyang Suna09adda2022-02-16 18:11:33 +0800651 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800652#endif
653
Mingyang Sunb26b2802021-07-07 11:25:00 +0800654 /*
655 * If num_bytes is greater than the remaining size of the input vector then
656 * the remaining size of the input vector is used.
657 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800658 if (num_bytes > handle->msg.in_size[invec_idx]) {
659 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800660 }
661
662 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800663 handle->invec[invec_idx].base =
664 (char *)handle->invec[invec_idx].base + num_bytes;
665 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800666
667 return num_bytes;
668}
669
670void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
671 const void *buffer, size_t num_bytes)
672{
Mingyang Suna09adda2022-02-16 18:11:33 +0800673 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800674 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800675
676 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800677 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800678 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800679 tfm_core_panic();
680 }
681
Mingyang Suna09adda2022-02-16 18:11:33 +0800682 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
683 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800684
685 /*
686 * It is a fatal error if message handle does not refer to a request
687 * message
688 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800689 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800690 tfm_core_panic();
691 }
692
693 /*
694 * It is a fatal error if outvec_idx is equal to or greater than
695 * PSA_MAX_IOVEC
696 */
697 if (outvec_idx >= PSA_MAX_IOVEC) {
698 tfm_core_panic();
699 }
700
701 /*
702 * It is a fatal error if the call attempts to write data past the end of
703 * the client output vector
704 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800705 if (num_bytes > handle->msg.out_size[outvec_idx] -
706 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800707 tfm_core_panic();
708 }
709
Shawn Shan038348e2021-09-08 17:11:04 +0800710#if PSA_FRAMEWORK_HAS_MM_IOVEC
711 /*
712 * It is a fatal error if the output vector has already been mapped using
713 * psa_map_outvec().
714 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800715 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800716 tfm_core_panic();
717 }
718
Mingyang Suna09adda2022-02-16 18:11:33 +0800719 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800720#endif
721
Mingyang Sunb26b2802021-07-07 11:25:00 +0800722 /*
723 * Copy the service buffer to client outvecs. It is a fatal error
724 * if the memory reference for buffer is invalid or not readable.
725 */
726 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800727 TFM_MEMORY_ACCESS_RO, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800728 tfm_core_panic();
729 }
730
Mingyang Suna09adda2022-02-16 18:11:33 +0800731 spm_memcpy((char *)handle->outvec[outvec_idx].base +
732 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800733
734 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800735 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800736}
737
Ken Liuf8c7e532022-02-10 15:03:04 +0800738psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
739 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800740{
Ken Liu0bed7e02022-02-10 12:38:07 +0800741 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800742 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800743 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800744 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800745
746 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800747 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800748 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800749 tfm_core_panic();
750 }
751
752 /*
753 * RoT Service information is needed in this function, stored it in message
754 * body structure. Only two parameters are passed in this function: handle
755 * and status, so it is useful and simply to do like this.
756 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800757 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800758 if (!service) {
759 tfm_core_panic();
760 }
761
Mingyang Suna09adda2022-02-16 18:11:33 +0800762 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800763 case PSA_IPC_CONNECT:
764 /*
765 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
766 * input status is PSA_SUCCESS. Others return values are based on the
767 * input status.
768 */
769 if (status == PSA_SUCCESS) {
770 ret = msg_handle;
771 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
772 /* Refuse the client connection, indicating a permanent error. */
Kevin Penge61e7052022-01-27 14:57:06 +0800773 tfm_spm_free_conn_handle(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800774 ret = PSA_ERROR_CONNECTION_REFUSED;
775 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
776 /* Fail the client connection, indicating a transient error. */
777 ret = PSA_ERROR_CONNECTION_BUSY;
778 } else {
779 tfm_core_panic();
780 }
781 break;
782 case PSA_IPC_DISCONNECT:
783 /* Service handle is not used anymore */
Kevin Penge61e7052022-01-27 14:57:06 +0800784 tfm_spm_free_conn_handle(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800785
786 /*
787 * If the message type is PSA_IPC_DISCONNECT, then the status code is
788 * ignored
789 */
790 break;
791 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800792 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800793
794#if PSA_FRAMEWORK_HAS_MM_IOVEC
795
796 /*
797 * If the unmapped function is not called for an input/output vector
798 * that has been mapped, the framework will remove the mapping.
799 */
800 int i;
801
802 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800803 if (IOVEC_IS_MAPPED(handle, i) &&
804 (!IOVEC_IS_UNMAPPED(handle, i))) {
805 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800806 /*
807 * Any output vectors that are still mapped will report that
808 * zero bytes have been written.
809 */
810 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800811 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800812 }
813 }
814 }
815
816#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800817 /* Reply to a request message. Return values are based on status */
818 ret = status;
819 /*
820 * The total number of bytes written to a single parameter must be
821 * reported to the client by updating the len member of the
822 * psa_outvec structure for the parameter before returning from
823 * psa_call().
824 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800825 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800826 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Kevin Penge61e7052022-01-27 14:57:06 +0800827 tfm_spm_free_conn_handle(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800828 }
829 } else {
830 tfm_core_panic();
831 }
832 }
833
834 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
835 /*
836 * If the source of the programmer error is a Secure Partition, the SPM
837 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
838 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800839 if (TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
840 handle->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800841 } else {
842 tfm_core_panic();
843 }
844 } else {
Mingyang Suna09adda2022-02-16 18:11:33 +0800845 handle->status = TFM_HANDLE_STATUS_IDLE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800846 }
847
Mingyang Sun620c8562021-11-10 11:44:58 +0800848 /*
849 * TODO: It can be optimized further by moving critical section protection
850 * to mailbox. Also need to check implementation when secure context is
851 * involved.
852 */
853 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800854 ret = backend_instance.replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800855 CRITICAL_SECTION_LEAVE(cs_assert);
856
857 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800858}
859
Kevin Peng613b4172022-02-15 14:41:44 +0800860#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800861void tfm_spm_partition_psa_notify(int32_t partition_id)
862{
Ken Liu5d73c872021-08-19 19:23:17 +0800863 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
864
865 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800866}
867
868void tfm_spm_partition_psa_clear(void)
869{
Ken Liu92ede9f2021-10-20 09:35:00 +0800870 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800871 struct partition_t *partition = NULL;
872
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800873 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800874
875 /*
876 * It is a fatal error if the Secure Partition's doorbell signal is not
877 * currently asserted.
878 */
879 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
880 tfm_core_panic();
881 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800882
883 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800884 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800885 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800886}
Kevin Peng613b4172022-02-15 14:41:44 +0800887#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800888
Mingyang Sunb26b2802021-07-07 11:25:00 +0800889void tfm_spm_partition_psa_panic(void)
890{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100891#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
892 tfm_hal_system_halt();
893#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800894 /*
895 * PSA FF recommends that the SPM causes the system to restart when a secure
896 * partition panics.
897 */
898 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100899#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800900}
901
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800902/* psa_set_rhandle is only needed by connection-based services */
903#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
904
905void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
906{
Mingyang Suna09adda2022-02-16 18:11:33 +0800907 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800908
909 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800910 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800911 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800912 tfm_core_panic();
913 }
914
915 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800916 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800917 tfm_core_panic();
918 }
919
Mingyang Suna09adda2022-02-16 18:11:33 +0800920 handle->msg.rhandle = rhandle;
921 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800922}
923
924#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
925
926#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800927void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800928{
929 struct partition_t *partition;
930 struct irq_load_info_t *irq_info;
931
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800932 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800933
934 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
935 if (!irq_info) {
936 tfm_core_panic();
937 }
938
Kevin Pengd399a1f2021-09-08 15:33:14 +0800939 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800940}
941
Kevin Peng67a89fd2021-11-25 11:22:02 +0800942psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800943{
944 struct partition_t *partition;
945 struct irq_load_info_t *irq_info;
946
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800947 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800948
949 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
950 if (!irq_info) {
951 tfm_core_panic();
952 }
953
Kevin Pengd399a1f2021-09-08 15:33:14 +0800954 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800955
956 return 1;
957}
958
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800959/* This API is only used for FLIH. */
960#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800961void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
962{
Ken Liu92ede9f2021-10-20 09:35:00 +0800963 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800964 struct irq_load_info_t *irq_info;
965 struct partition_t *partition;
966
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800967 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800968
969 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
970 if (!irq_info) {
971 tfm_core_panic();
972 }
973
974 if (!irq_info->flih_func) {
975 /* This API is for FLIH IRQs only */
976 tfm_core_panic();
977 }
978
979 if ((partition->signals_asserted & irq_signal) == 0) {
980 /* The signal is not asserted */
981 tfm_core_panic();
982 }
983
Ken Liu92ede9f2021-10-20 09:35:00 +0800984 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800985 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800986 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800987}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800988#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800989
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800990/* This API is only used for SLIH. */
991#if CONFIG_TFM_SLIH_API == 1
992void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800993{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800994 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
995 struct irq_load_info_t *irq_info = NULL;
996 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800997
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800998 partition = GET_CURRENT_COMPONENT();
999
1000 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
1001 /* It is a fatal error if passed signal is not an interrupt signal. */
1002 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001003 tfm_core_panic();
1004 }
1005
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001006 if (irq_info->flih_func) {
1007 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001008 tfm_core_panic();
1009 }
1010
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001011 /* It is a fatal error if passed signal is not currently asserted */
1012 if ((partition->signals_asserted & irq_signal) == 0) {
1013 tfm_core_panic();
1014 }
1015
1016 CRITICAL_SECTION_ENTER(cs_assert);
1017 partition->signals_asserted &= ~irq_signal;
1018 CRITICAL_SECTION_LEAVE(cs_assert);
1019
1020 tfm_hal_irq_clear_pending(irq_info->source);
1021 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001022}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001023#endif
1024#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001025
Shawn Shan038348e2021-09-08 17:11:04 +08001026#if PSA_FRAMEWORK_HAS_MM_IOVEC
1027
1028const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1029 uint32_t invec_idx)
1030{
Mingyang Suna09adda2022-02-16 18:11:33 +08001031 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001032 uint32_t privileged;
1033 struct partition_t *partition = NULL;
1034
1035 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001036 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001037 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001038 tfm_core_panic();
1039 }
1040
Mingyang Suna09adda2022-02-16 18:11:33 +08001041 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001042 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001043
1044 /*
1045 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1046 * Service that received the message.
1047 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001048 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001049 tfm_core_panic();
1050 }
1051
1052 /*
1053 * It is a fatal error if message handle does not refer to a request
1054 * message.
1055 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001056 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001057 tfm_core_panic();
1058 }
1059
1060 /*
1061 * It is a fatal error if invec_idx is equal to or greater than
1062 * PSA_MAX_IOVEC.
1063 */
1064 if (invec_idx >= PSA_MAX_IOVEC) {
1065 tfm_core_panic();
1066 }
1067
1068 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001069 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001070 tfm_core_panic();
1071 }
1072
1073 /*
1074 * It is a fatal error if the input vector has already been mapped using
1075 * psa_map_invec().
1076 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001077 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001078 tfm_core_panic();
1079 }
1080
1081 /*
1082 * It is a fatal error if the input vector has already been accessed
1083 * using psa_read() or psa_skip().
1084 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001085 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001086 tfm_core_panic();
1087 }
1088
1089 /*
1090 * It is a fatal error if the memory reference for the wrap input vector is
1091 * invalid or not readable.
1092 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001093 if (tfm_memory_check(handle->invec[invec_idx].base,
1094 handle->invec[invec_idx].len,
1095 false, TFM_MEMORY_ACCESS_RO,
1096 privileged) != SPM_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001097 tfm_core_panic();
1098 }
1099
Mingyang Suna09adda2022-02-16 18:11:33 +08001100 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001101
Mingyang Suna09adda2022-02-16 18:11:33 +08001102 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001103}
1104
1105void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1106 uint32_t invec_idx)
1107{
Mingyang Suna09adda2022-02-16 18:11:33 +08001108 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001109
1110 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001111 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001112 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001113 tfm_core_panic();
1114 }
1115
1116 /*
1117 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1118 * Service that received the message.
1119 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001120 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001121 tfm_core_panic();
1122 }
1123
1124 /*
1125 * It is a fatal error if message handle does not refer to a request
1126 * message.
1127 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001128 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001129 tfm_core_panic();
1130 }
1131
1132 /*
1133 * It is a fatal error if invec_idx is equal to or greater than
1134 * PSA_MAX_IOVEC.
1135 */
1136 if (invec_idx >= PSA_MAX_IOVEC) {
1137 tfm_core_panic();
1138 }
1139
1140 /*
1141 * It is a fatal error if The input vector has not been mapped by a call to
1142 * psa_map_invec().
1143 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001144 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001145 tfm_core_panic();
1146 }
1147
1148 /*
1149 * It is a fatal error if the input vector has already been unmapped by a
1150 * call to psa_unmap_invec().
1151 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001152 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001153 tfm_core_panic();
1154 }
1155
Mingyang Suna09adda2022-02-16 18:11:33 +08001156 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001157}
1158
1159void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1160 uint32_t outvec_idx)
1161{
Mingyang Suna09adda2022-02-16 18:11:33 +08001162 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001163 uint32_t privileged;
1164 struct partition_t *partition = NULL;
1165
1166 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001167 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001168 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001169 tfm_core_panic();
1170 }
1171
Mingyang Suna09adda2022-02-16 18:11:33 +08001172 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001173 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001174
1175 /*
1176 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1177 * Service that received the message.
1178 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001179 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001180 tfm_core_panic();
1181 }
1182
1183 /*
1184 * It is a fatal error if message handle does not refer to a request
1185 * message.
1186 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001187 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001188 tfm_core_panic();
1189 }
1190
1191 /*
1192 * It is a fatal error if outvec_idx is equal to or greater than
1193 * PSA_MAX_IOVEC.
1194 */
1195 if (outvec_idx >= PSA_MAX_IOVEC) {
1196 tfm_core_panic();
1197 }
1198
1199 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001200 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001201 tfm_core_panic();
1202 }
1203
1204 /*
1205 * It is a fatal error if the output vector has already been mapped using
1206 * psa_map_outvec().
1207 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001208 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001209 tfm_core_panic();
1210 }
1211
1212 /*
1213 * It is a fatal error if the output vector has already been accessed
1214 * using psa_write().
1215 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001216 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001217 tfm_core_panic();
1218 }
1219
1220 /*
1221 * It is a fatal error if the output vector is invalid or not read-write.
1222 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001223 if (tfm_memory_check(handle->outvec[outvec_idx].base,
1224 handle->outvec[outvec_idx].len, false,
Shawn Shan038348e2021-09-08 17:11:04 +08001225 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
1226 tfm_core_panic();
1227 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001228 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001229
Mingyang Suna09adda2022-02-16 18:11:33 +08001230 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001231}
1232
1233void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1234 uint32_t outvec_idx, size_t len)
1235{
Mingyang Suna09adda2022-02-16 18:11:33 +08001236 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001237
1238 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001239 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001240 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001241 tfm_core_panic();
1242 }
1243
1244 /*
1245 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1246 * Service that received the message.
1247 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001248 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001249 tfm_core_panic();
1250 }
1251
1252 /*
1253 * It is a fatal error if message handle does not refer to a request
1254 * message.
1255 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001256 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001257 tfm_core_panic();
1258 }
1259
1260 /*
1261 * It is a fatal error if outvec_idx is equal to or greater than
1262 * PSA_MAX_IOVEC.
1263 */
1264 if (outvec_idx >= PSA_MAX_IOVEC) {
1265 tfm_core_panic();
1266 }
1267
1268 /*
1269 * It is a fatal error if len is greater than the output vector size.
1270 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001271 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001272 tfm_core_panic();
1273 }
1274
1275 /*
1276 * It is a fatal error if The output vector has not been mapped by a call to
1277 * psa_map_outvec().
1278 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001279 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001280 tfm_core_panic();
1281 }
1282
1283 /*
1284 * It is a fatal error if the output vector has already been unmapped by a
1285 * call to psa_unmap_outvec().
1286 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001287 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001288 tfm_core_panic();
1289 }
1290
Mingyang Suna09adda2022-02-16 18:11:33 +08001291 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001292
1293 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001294 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001295}
1296
1297#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */