blob: a303784fffb579711515005cda3f2be90fe3fb5e [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"
Mingyang Sunb26b2802021-07-07 11:25:00 +080025#include "tfm_rpc.h"
26#include "tfm_spm_hal.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080027#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080028#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080029#include "tfm_psa_call_pack.h"
David Hu733d8f92019-09-23 15:32:40 +080030
Ken Liub3b2cb62021-05-22 00:39:28 +080031#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080032extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080033
Shawn Shan038348e2021-09-08 17:11:04 +080034#if PSA_FRAMEWORK_HAS_MM_IOVEC
35
36/*
37 * The MM-IOVEC status
38 * The max total number of invec and outvec is 8.
39 * Each invec/outvec takes 4 bit, 32 bits in total.
40 *
41 * The encoding format of the MM-IOVEC status:
42 *--------------------------------------------------------------
43 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
44 *--------------------------------------------------------------
45 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
46 *--------------------------------------------------------------
47 *
48 * Take invec[0] as an example:
49 *
50 * bit 0: whether invec[0] has been mapped.
51 * bit 1: whether invec[0] has been unmapped.
52 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
53 * psa_write().
54 * bit 3: reserved for invec[0].
55 */
56
57#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
58#define OUTVEC_IDX_BASE 4 /*
59 * Base index of outvec.
60 * There are four invecs in front of
61 * outvec.
62 */
63#define INVEC_IDX_BASE 0 /* Base index of invec. */
64
65#define IOVEC_MAPPED_BIT (1U << 0)
66#define IOVEC_UNMAPPED_BIT (1U << 1)
67#define IOVEC_ACCESSED_BIT (1U << 2)
68
Mingyang Suna09adda2022-02-16 18:11:33 +080069#define IOVEC_IS_MAPPED(handle, iovec_idx) \
70 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080071 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080072#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
73 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080074 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080075#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
76 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080077 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080078#define SET_IOVEC_MAPPED(handle, iovec_idx) \
79 (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080080 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080081#define SET_IOVEC_UNMAPPED(handle, iovec_idx) \
82 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080083 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080084#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
85 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080086 ((iovec_idx) * IOVEC_STATUS_BITS)))
87
88#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
89
Xinyu Zhangb287ef82021-11-03 18:38:50 +080090void spm_handle_programmer_errors(psa_status_t status)
91{
Summer Qind9d497b2022-04-14 14:39:26 +080092 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
93 status == PSA_ERROR_CONNECTION_REFUSED) {
94 if (!tfm_spm_is_ns_caller()) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +080095 tfm_core_panic();
Summer Qind9d497b2022-04-14 14:39:26 +080096 }
Xinyu Zhangb287ef82021-11-03 18:38:50 +080097 }
98}
99
Mingyang Suneeca4652021-07-15 15:19:16 +0800100uint32_t tfm_spm_get_lifecycle_state(void)
101{
102 /*
103 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
104 * implemented in the future.
105 */
106 return PSA_LIFECYCLE_UNKNOWN;
107}
108
109/* PSA Client API function body */
110
Mingyang Sund44522a2020-01-16 16:48:37 +0800111uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800112{
113 return PSA_FRAMEWORK_VERSION;
114}
115
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800116uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800117{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800118 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800119 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800120
121 /*
122 * It should return PSA_VERSION_NONE if the RoT Service is not
123 * implemented.
124 */
125 service = tfm_spm_get_service_by_sid(sid);
126 if (!service) {
127 return PSA_VERSION_NONE;
128 }
129
130 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800131 * It should return PSA_VERSION_NONE if the caller is not authorized
132 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800133 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800134 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800135 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800136 }
137
Ken Liuacd2a572021-05-12 16:19:04 +0800138 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800139}
140
Mingyang Suneeca4652021-07-15 15:19:16 +0800141psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
142 uint32_t ctrl_param,
143 const psa_invec *inptr,
144 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800145{
146 psa_invec invecs[PSA_MAX_IOVEC];
147 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800148 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800149 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800150 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800151 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800152 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800153 uint32_t privileged;
Mingyang Sun620c8562021-11-10 11:44:58 +0800154 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800155 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800156 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
157 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
158 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800159
160 /* The request type must be zero or positive. */
161 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800162 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800163 }
David Hu733d8f92019-09-23 15:32:40 +0800164
Shawn Shanb222d892021-01-04 17:41:48 +0800165 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800166 if ((in_num > PSA_MAX_IOVEC) ||
167 (out_num > PSA_MAX_IOVEC) ||
168 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800169 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800170 }
171
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800172 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
173 if (handle == PSA_NULL_HANDLE) {
174 return PSA_ERROR_PROGRAMMER_ERROR;
175 }
176
Kevin Peng385fda82021-08-18 10:41:19 +0800177 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800178
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800179 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800180 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800181 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800182
183 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800184 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800185 }
186
Mingyang Sun453ad402021-03-17 17:58:33 +0800187 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800188 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800189 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800190 }
191
Ken Liub3b2cb62021-05-22 00:39:28 +0800192 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800193
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800194 /*
195 * It is a PROGRAMMER ERROR if the caller is not authorized to access
196 * the RoT Service.
197 */
198 if (tfm_spm_check_authorization(sid, service, ns_caller)
Ken Liuad3f3e62022-03-04 22:23:52 +0800199 != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800200 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800201 }
202
Mingyang Sun453ad402021-03-17 17:58:33 +0800203 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
204
Ken Liuad3f3e62022-03-04 22:23:52 +0800205 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800206 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800207 }
208
Mingyang Sun620c8562021-11-10 11:44:58 +0800209 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800210 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800211 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800212
213 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800214 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800215 }
216
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800217 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800218 handle = tfm_spm_to_user_handle(conn_handle);
219 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800220#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800221 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800222 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
223 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800224 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800225 }
226
227 /*
228 * It is a PROGRAMMER ERROR if the connection is currently
229 * handling a request.
230 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800231 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800232 return PSA_ERROR_PROGRAMMER_ERROR;
233 }
234
Ken Liu0bed7e02022-02-10 12:38:07 +0800235 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800236
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800237 if (!service) {
238 /* FixMe: Need to implement a mechanism to resolve this failure. */
239 return PSA_ERROR_PROGRAMMER_ERROR;
240 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800241#else
242 return PSA_ERROR_PROGRAMMER_ERROR;
243#endif
David Hu733d8f92019-09-23 15:32:40 +0800244 }
245
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800246 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800247
Kevin Pengedb8ee42021-03-09 16:50:11 +0800248 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800249 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800250 * if the memory reference for the wrap input vector is invalid or not
251 * readable.
252 */
253 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800254 TFM_MEMORY_ACCESS_RO, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800255 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800256 }
Summer Qinba2346e2019-11-12 16:26:31 +0800257
David Hu733d8f92019-09-23 15:32:40 +0800258 /*
259 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800260 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800261 * the wrap output vector is invalid or not read-write.
262 */
263 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800264 TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800265 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800266 }
267
Summer Qinf24dbb52020-07-23 14:53:54 +0800268 spm_memset(invecs, 0, sizeof(invecs));
269 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800270
271 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800272 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
273 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800274
275 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800276 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800277 * memory reference was invalid or not readable.
278 */
279 for (i = 0; i < in_num; i++) {
280 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800281 TFM_MEMORY_ACCESS_RO, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800282 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800283 }
284 }
Summer Qinba2346e2019-11-12 16:26:31 +0800285
286 /*
287 * Clients must never overlap input parameters because of the risk of a
288 * double-fetch inconsistency.
289 * Overflow is checked in tfm_memory_check functions.
290 */
291 for (i = 0; i + 1 < in_num; i++) {
292 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100293 if (!((char *) invecs[j].base + invecs[j].len <=
294 (char *) invecs[i].base ||
295 (char *) invecs[j].base >=
296 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800297 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800298 }
299 }
300 }
301
David Hu733d8f92019-09-23 15:32:40 +0800302 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800303 * For client output vector, it is a PROGRAMMER ERROR if the provided
304 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800305 */
306 for (i = 0; i < out_num; i++) {
307 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liuad3f3e62022-03-04 22:23:52 +0800308 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800309 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800310 }
311 }
312
Ken Liu0bed7e02022-02-10 12:38:07 +0800313 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800314 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800315
Ken Liu0bed7e02022-02-10 12:38:07 +0800316 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800317}
318
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800319/* Following PSA APIs are only needed by connection-based services */
320#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
321
322psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
323{
324 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800325 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800326 int32_t client_id;
327 psa_handle_t handle;
328 bool ns_caller = tfm_spm_is_ns_caller();
329 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
330
331 /*
332 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
333 * platform.
334 */
335 service = tfm_spm_get_service_by_sid(sid);
336 if (!service) {
337 return PSA_ERROR_CONNECTION_REFUSED;
338 }
339
340 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
341 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
342 return PSA_ERROR_PROGRAMMER_ERROR;
343 }
344
345 /*
346 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
347 * RoT Service.
348 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800349 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800350 return PSA_ERROR_CONNECTION_REFUSED;
351 }
352
353 /*
354 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
355 * not supported on the platform.
356 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800357 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800358 return PSA_ERROR_CONNECTION_REFUSED;
359 }
360
361 client_id = tfm_spm_get_client_id(ns_caller);
362
363 /*
364 * Create connection handle here since it is possible to return the error
365 * code to client when creation fails.
366 */
367 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800368 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800369 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800370 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800371 return PSA_ERROR_CONNECTION_BUSY;
372 }
373
Mingyang Suna09adda2022-02-16 18:11:33 +0800374 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800375 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800376 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800377 client_id, NULL, 0, NULL, 0, NULL);
378
Mingyang Suna09adda2022-02-16 18:11:33 +0800379 return backend_instance.messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800380}
381
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800382psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800383{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800384 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800385 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800386 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800387 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800388
389 /* It will have no effect if called with the NULL handle */
390 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800391 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800392 }
393
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800394 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800395 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800396 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800397 }
398
Kevin Peng385fda82021-08-18 10:41:19 +0800399 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800400
David Hu733d8f92019-09-23 15:32:40 +0800401 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800402 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
403 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800404 */
Kevin Penge61e7052022-01-27 14:57:06 +0800405 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
406 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800407 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800408 }
Shawn Shanb222d892021-01-04 17:41:48 +0800409
Ken Liu0bed7e02022-02-10 12:38:07 +0800410 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800411 if (!service) {
412 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800413 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800414 }
415
Shawn Shanb222d892021-01-04 17:41:48 +0800416 /*
417 * It is a PROGRAMMER ERROR if the connection is currently handling a
418 * request.
419 */
Summer Qin630c76b2020-05-20 10:32:58 +0800420 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800421 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800422 }
423
David Hu733d8f92019-09-23 15:32:40 +0800424 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800425 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
426 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800427
Ken Liu0bed7e02022-02-10 12:38:07 +0800428 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800429}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800430
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800431#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
432
Mingyang Suneeca4652021-07-15 15:19:16 +0800433/* PSA Partition API function body */
434
Kevin Pengdef92de2021-11-10 16:14:48 +0800435#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
436 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800437psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
438 uint32_t timeout)
439{
440 struct partition_t *partition = NULL;
441
442 /*
443 * Timeout[30:0] are reserved for future use.
444 * SPM must ignore the value of RES.
445 */
446 timeout &= PSA_TIMEOUT_MASK;
447
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800448 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800449
450 /*
451 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
452 * signals.
453 */
454 if ((partition->signals_allowed & signal_mask) == 0) {
455 tfm_core_panic();
456 }
457
458 /*
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800459 * backend_instance.wait() blocks the caller thread if no signals are
460 * available. In this case, the return value of this function is temporary
461 * set into runtime context. After new signal(s) are available, the return
462 * value is updated with the available signal(s) and blocked thread gets
463 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800464 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800465 if (timeout == PSA_BLOCK) {
466 return backend_instance.wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800467 }
468
469 return partition->signals_asserted & signal_mask;
470}
Kevin Pengdef92de2021-11-10 16:14:48 +0800471#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800472
Kevin Pengdef92de2021-11-10 16:14:48 +0800473#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800474psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
475{
Mingyang Suna09adda2022-02-16 18:11:33 +0800476 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800477 struct partition_t *partition = NULL;
478 uint32_t privileged;
479
480 /*
481 * Only one message could be retrieved every time for psa_get(). It is a
482 * fatal error if the input signal has more than a signal bit set.
483 */
484 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
485 tfm_core_panic();
486 }
487
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800488 partition = GET_CURRENT_COMPONENT();
489
Kevin Penga40d29f2022-01-19 14:44:34 +0800490 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800491
492 /*
493 * Write the message to the service buffer. It is a fatal error if the
494 * input msg pointer is not a valid memory reference or not read-write.
495 */
496 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
Ken Liuad3f3e62022-03-04 22:23:52 +0800497 privileged) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800498 tfm_core_panic();
499 }
500
501 /*
502 * It is a fatal error if the caller call psa_get() when no message has
503 * been set. The caller must call this function after an RoT Service signal
504 * is returned by psa_wait().
505 */
506 if (partition->signals_asserted == 0) {
507 tfm_core_panic();
508 }
509
510 /*
511 * It is a fatal error if the RoT Service signal is not currently asserted.
512 */
513 if ((partition->signals_asserted & signal) == 0) {
514 tfm_core_panic();
515 }
516
517 /*
518 * Get message by signal from partition. It is a fatal error if getting
519 * failed, which means the input signal is not correspond to an RoT service.
520 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800521 handle = spm_get_handle_by_signal(partition, signal);
522 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800523 return PSA_ERROR_DOES_NOT_EXIST;
524 }
525
Mingyang Suna09adda2022-02-16 18:11:33 +0800526 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800527
528 return PSA_SUCCESS;
529}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800530#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800531
Mingyang Sunb26b2802021-07-07 11:25:00 +0800532size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
533 void *buffer, size_t num_bytes)
534{
535 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800536 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800537 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800538
539 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800540 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800541 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800542 tfm_core_panic();
543 }
544
Mingyang Suna09adda2022-02-16 18:11:33 +0800545 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
546 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800547
548 /*
549 * It is a fatal error if message handle does not refer to a request
550 * message
551 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800552 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800553 tfm_core_panic();
554 }
555
556 /*
557 * It is a fatal error if invec_idx is equal to or greater than
558 * PSA_MAX_IOVEC
559 */
560 if (invec_idx >= PSA_MAX_IOVEC) {
561 tfm_core_panic();
562 }
563
564 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800565 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800566 return 0;
567 }
568
Shawn Shan038348e2021-09-08 17:11:04 +0800569#if PSA_FRAMEWORK_HAS_MM_IOVEC
570 /*
571 * It is a fatal error if the input vector has already been mapped using
572 * psa_map_invec().
573 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800574 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800575 tfm_core_panic();
576 }
577
Mingyang Suna09adda2022-02-16 18:11:33 +0800578 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800579#endif
580
Mingyang Sunb26b2802021-07-07 11:25:00 +0800581 /*
582 * Copy the client data to the service buffer. It is a fatal error
583 * if the memory reference for buffer is invalid or not read-write.
584 */
585 if (tfm_memory_check(buffer, num_bytes, false,
Ken Liuad3f3e62022-03-04 22:23:52 +0800586 TFM_MEMORY_ACCESS_RW, priv_mode) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800587 tfm_core_panic();
588 }
589
Mingyang Suna09adda2022-02-16 18:11:33 +0800590 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
591 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800592
Mingyang Suna09adda2022-02-16 18:11:33 +0800593 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800594
595 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800596 handle->invec[invec_idx].base =
597 (char *)handle->invec[invec_idx].base + bytes;
598 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800599
600 return bytes;
601}
602
603size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
604 size_t num_bytes)
605{
Mingyang Suna09adda2022-02-16 18:11:33 +0800606 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800607
608 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800609 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800610 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800611 tfm_core_panic();
612 }
613
614 /*
615 * It is a fatal error if message handle does not refer to a request
616 * message
617 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800618 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800619 tfm_core_panic();
620 }
621
622 /*
623 * It is a fatal error if invec_idx is equal to or greater than
624 * PSA_MAX_IOVEC
625 */
626 if (invec_idx >= PSA_MAX_IOVEC) {
627 tfm_core_panic();
628 }
629
630 /* There was no remaining data in this input vector */
Mingyang Suna09adda2022-02-16 18:11:33 +0800631 if (handle->msg.in_size[invec_idx] == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800632 return 0;
633 }
634
Shawn Shan038348e2021-09-08 17:11:04 +0800635#if PSA_FRAMEWORK_HAS_MM_IOVEC
636 /*
637 * It is a fatal error if the input vector has already been mapped using
638 * psa_map_invec().
639 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800640 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800641 tfm_core_panic();
642 }
643
Mingyang Suna09adda2022-02-16 18:11:33 +0800644 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800645#endif
646
Mingyang Sunb26b2802021-07-07 11:25:00 +0800647 /*
648 * If num_bytes is greater than the remaining size of the input vector then
649 * the remaining size of the input vector is used.
650 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800651 if (num_bytes > handle->msg.in_size[invec_idx]) {
652 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800653 }
654
655 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800656 handle->invec[invec_idx].base =
657 (char *)handle->invec[invec_idx].base + num_bytes;
658 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800659
660 return num_bytes;
661}
662
663void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
664 const void *buffer, size_t num_bytes)
665{
Mingyang Suna09adda2022-02-16 18:11:33 +0800666 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800667 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800668
669 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800670 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800671 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800672 tfm_core_panic();
673 }
674
Mingyang Suna09adda2022-02-16 18:11:33 +0800675 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
676 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800677
678 /*
679 * It is a fatal error if message handle does not refer to a request
680 * message
681 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800682 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800683 tfm_core_panic();
684 }
685
686 /*
687 * It is a fatal error if outvec_idx is equal to or greater than
688 * PSA_MAX_IOVEC
689 */
690 if (outvec_idx >= PSA_MAX_IOVEC) {
691 tfm_core_panic();
692 }
693
694 /*
695 * It is a fatal error if the call attempts to write data past the end of
696 * the client output vector
697 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800698 if (num_bytes > handle->msg.out_size[outvec_idx] -
699 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800700 tfm_core_panic();
701 }
702
Shawn Shan038348e2021-09-08 17:11:04 +0800703#if PSA_FRAMEWORK_HAS_MM_IOVEC
704 /*
705 * It is a fatal error if the output vector has already been mapped using
706 * psa_map_outvec().
707 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800708 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800709 tfm_core_panic();
710 }
711
Mingyang Suna09adda2022-02-16 18:11:33 +0800712 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800713#endif
714
Mingyang Sunb26b2802021-07-07 11:25:00 +0800715 /*
716 * Copy the service buffer to client outvecs. It is a fatal error
717 * if the memory reference for buffer is invalid or not readable.
718 */
719 if (tfm_memory_check(buffer, num_bytes, false,
Ken Liuad3f3e62022-03-04 22:23:52 +0800720 TFM_MEMORY_ACCESS_RO, priv_mode) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800721 tfm_core_panic();
722 }
723
Mingyang Suna09adda2022-02-16 18:11:33 +0800724 spm_memcpy((char *)handle->outvec[outvec_idx].base +
725 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800726
727 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800728 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800729}
730
Ken Liuf8c7e532022-02-10 15:03:04 +0800731psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
732 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800733{
Ken Liu0bed7e02022-02-10 12:38:07 +0800734 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800735 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800736 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800737 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800738
739 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800740 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800741 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800742 tfm_core_panic();
743 }
744
745 /*
746 * RoT Service information is needed in this function, stored it in message
747 * body structure. Only two parameters are passed in this function: handle
748 * and status, so it is useful and simply to do like this.
749 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800750 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800751 if (!service) {
752 tfm_core_panic();
753 }
754
Mingyang Suna09adda2022-02-16 18:11:33 +0800755 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800756 case PSA_IPC_CONNECT:
757 /*
758 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
759 * input status is PSA_SUCCESS. Others return values are based on the
760 * input status.
761 */
762 if (status == PSA_SUCCESS) {
763 ret = msg_handle;
764 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
765 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800766 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800767 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800768 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
769 /* Fail the client connection, indicating a transient error. */
770 ret = PSA_ERROR_CONNECTION_BUSY;
771 } else {
772 tfm_core_panic();
773 }
774 break;
775 case PSA_IPC_DISCONNECT:
776 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800777 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800778
779 /*
780 * If the message type is PSA_IPC_DISCONNECT, then the status code is
781 * ignored
782 */
783 break;
784 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800785 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800786
787#if PSA_FRAMEWORK_HAS_MM_IOVEC
788
789 /*
790 * If the unmapped function is not called for an input/output vector
791 * that has been mapped, the framework will remove the mapping.
792 */
793 int i;
794
795 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800796 if (IOVEC_IS_MAPPED(handle, i) &&
797 (!IOVEC_IS_UNMAPPED(handle, i))) {
798 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800799 /*
800 * Any output vectors that are still mapped will report that
801 * zero bytes have been written.
802 */
803 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800804 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800805 }
806 }
807 }
808
809#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800810 /* Reply to a request message. Return values are based on status */
811 ret = status;
812 /*
813 * The total number of bytes written to a single parameter must be
814 * reported to the client by updating the len member of the
815 * psa_outvec structure for the parameter before returning from
816 * psa_call().
817 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800818 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800819 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800820 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800821 }
822 } else {
823 tfm_core_panic();
824 }
825 }
826
827 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
828 /*
829 * If the source of the programmer error is a Secure Partition, the SPM
830 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
831 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800832 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800833 tfm_core_panic();
834 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800835 }
836
Mingyang Sun620c8562021-11-10 11:44:58 +0800837 /*
838 * TODO: It can be optimized further by moving critical section protection
839 * to mailbox. Also need to check implementation when secure context is
840 * involved.
841 */
842 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800843 ret = backend_instance.replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800844 CRITICAL_SECTION_LEAVE(cs_assert);
845
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800846 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
847 tfm_spm_free_conn_handle(handle);
848 } else {
849 handle->status = TFM_HANDLE_STATUS_IDLE;
850 }
851
Mingyang Sun620c8562021-11-10 11:44:58 +0800852 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800853}
854
Kevin Peng613b4172022-02-15 14:41:44 +0800855#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800856void tfm_spm_partition_psa_notify(int32_t partition_id)
857{
Ken Liu5d73c872021-08-19 19:23:17 +0800858 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
859
860 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800861}
862
863void tfm_spm_partition_psa_clear(void)
864{
Ken Liu92ede9f2021-10-20 09:35:00 +0800865 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800866 struct partition_t *partition = NULL;
867
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800868 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800869
870 /*
871 * It is a fatal error if the Secure Partition's doorbell signal is not
872 * currently asserted.
873 */
874 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
875 tfm_core_panic();
876 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800877
878 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800879 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800880 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800881}
Kevin Peng613b4172022-02-15 14:41:44 +0800882#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800883
Mingyang Sunb26b2802021-07-07 11:25:00 +0800884void tfm_spm_partition_psa_panic(void)
885{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100886#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
887 tfm_hal_system_halt();
888#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800889 /*
890 * PSA FF recommends that the SPM causes the system to restart when a secure
891 * partition panics.
892 */
893 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100894#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800895}
896
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800897/* psa_set_rhandle is only needed by connection-based services */
898#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
899
900void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
901{
Mingyang Suna09adda2022-02-16 18:11:33 +0800902 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800903
904 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800905 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800906 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800907 tfm_core_panic();
908 }
909
910 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800911 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800912 tfm_core_panic();
913 }
914
Mingyang Suna09adda2022-02-16 18:11:33 +0800915 handle->msg.rhandle = rhandle;
916 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800917}
918
919#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
920
921#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800922void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800923{
924 struct partition_t *partition;
925 struct irq_load_info_t *irq_info;
926
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800927 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800928
929 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
930 if (!irq_info) {
931 tfm_core_panic();
932 }
933
Kevin Pengd399a1f2021-09-08 15:33:14 +0800934 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800935}
936
Kevin Peng67a89fd2021-11-25 11:22:02 +0800937psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800938{
939 struct partition_t *partition;
940 struct irq_load_info_t *irq_info;
941
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800942 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800943
944 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
945 if (!irq_info) {
946 tfm_core_panic();
947 }
948
Kevin Pengd399a1f2021-09-08 15:33:14 +0800949 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800950
951 return 1;
952}
953
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800954/* This API is only used for FLIH. */
955#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800956void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
957{
Ken Liu92ede9f2021-10-20 09:35:00 +0800958 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800959 struct irq_load_info_t *irq_info;
960 struct partition_t *partition;
961
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800962 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800963
964 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
965 if (!irq_info) {
966 tfm_core_panic();
967 }
968
969 if (!irq_info->flih_func) {
970 /* This API is for FLIH IRQs only */
971 tfm_core_panic();
972 }
973
974 if ((partition->signals_asserted & irq_signal) == 0) {
975 /* The signal is not asserted */
976 tfm_core_panic();
977 }
978
Ken Liu92ede9f2021-10-20 09:35:00 +0800979 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800980 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800981 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800982}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800983#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800984
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800985/* This API is only used for SLIH. */
986#if CONFIG_TFM_SLIH_API == 1
987void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800988{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800989 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
990 struct irq_load_info_t *irq_info = NULL;
991 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800992
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800993 partition = GET_CURRENT_COMPONENT();
994
995 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
996 /* It is a fatal error if passed signal is not an interrupt signal. */
997 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800998 tfm_core_panic();
999 }
1000
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001001 if (irq_info->flih_func) {
1002 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001003 tfm_core_panic();
1004 }
1005
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001006 /* It is a fatal error if passed signal is not currently asserted */
1007 if ((partition->signals_asserted & irq_signal) == 0) {
1008 tfm_core_panic();
1009 }
1010
1011 CRITICAL_SECTION_ENTER(cs_assert);
1012 partition->signals_asserted &= ~irq_signal;
1013 CRITICAL_SECTION_LEAVE(cs_assert);
1014
1015 tfm_hal_irq_clear_pending(irq_info->source);
1016 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001017}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001018#endif
1019#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001020
Shawn Shan038348e2021-09-08 17:11:04 +08001021#if PSA_FRAMEWORK_HAS_MM_IOVEC
1022
1023const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1024 uint32_t invec_idx)
1025{
Mingyang Suna09adda2022-02-16 18:11:33 +08001026 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001027 uint32_t privileged;
1028 struct partition_t *partition = NULL;
1029
1030 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001031 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001032 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001033 tfm_core_panic();
1034 }
1035
Mingyang Suna09adda2022-02-16 18:11:33 +08001036 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001037 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001038
1039 /*
1040 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1041 * Service that received the message.
1042 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001043 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001044 tfm_core_panic();
1045 }
1046
1047 /*
1048 * It is a fatal error if message handle does not refer to a request
1049 * message.
1050 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001051 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001052 tfm_core_panic();
1053 }
1054
1055 /*
1056 * It is a fatal error if invec_idx is equal to or greater than
1057 * PSA_MAX_IOVEC.
1058 */
1059 if (invec_idx >= PSA_MAX_IOVEC) {
1060 tfm_core_panic();
1061 }
1062
1063 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001064 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001065 tfm_core_panic();
1066 }
1067
1068 /*
1069 * It is a fatal error if the input vector has already been mapped using
1070 * psa_map_invec().
1071 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001072 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001073 tfm_core_panic();
1074 }
1075
1076 /*
1077 * It is a fatal error if the input vector has already been accessed
1078 * using psa_read() or psa_skip().
1079 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001080 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001081 tfm_core_panic();
1082 }
1083
1084 /*
1085 * It is a fatal error if the memory reference for the wrap input vector is
1086 * invalid or not readable.
1087 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001088 if (tfm_memory_check(handle->invec[invec_idx].base,
1089 handle->invec[invec_idx].len,
1090 false, TFM_MEMORY_ACCESS_RO,
Ken Liuad3f3e62022-03-04 22:23:52 +08001091 privileged) != PSA_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001092 tfm_core_panic();
1093 }
1094
Mingyang Suna09adda2022-02-16 18:11:33 +08001095 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001096
Mingyang Suna09adda2022-02-16 18:11:33 +08001097 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001098}
1099
1100void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1101 uint32_t invec_idx)
1102{
Mingyang Suna09adda2022-02-16 18:11:33 +08001103 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001104
1105 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001106 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001107 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001108 tfm_core_panic();
1109 }
1110
1111 /*
1112 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1113 * Service that received the message.
1114 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001115 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001116 tfm_core_panic();
1117 }
1118
1119 /*
1120 * It is a fatal error if message handle does not refer to a request
1121 * message.
1122 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001123 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001124 tfm_core_panic();
1125 }
1126
1127 /*
1128 * It is a fatal error if invec_idx is equal to or greater than
1129 * PSA_MAX_IOVEC.
1130 */
1131 if (invec_idx >= PSA_MAX_IOVEC) {
1132 tfm_core_panic();
1133 }
1134
1135 /*
1136 * It is a fatal error if The input vector has not been mapped by a call to
1137 * psa_map_invec().
1138 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001139 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001140 tfm_core_panic();
1141 }
1142
1143 /*
1144 * It is a fatal error if the input vector has already been unmapped by a
1145 * call to psa_unmap_invec().
1146 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001147 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001148 tfm_core_panic();
1149 }
1150
Mingyang Suna09adda2022-02-16 18:11:33 +08001151 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001152}
1153
1154void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1155 uint32_t outvec_idx)
1156{
Mingyang Suna09adda2022-02-16 18:11:33 +08001157 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001158 uint32_t privileged;
1159 struct partition_t *partition = NULL;
1160
1161 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001162 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001163 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001164 tfm_core_panic();
1165 }
1166
Mingyang Suna09adda2022-02-16 18:11:33 +08001167 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001168 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001169
1170 /*
1171 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1172 * Service that received the message.
1173 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001174 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001175 tfm_core_panic();
1176 }
1177
1178 /*
1179 * It is a fatal error if message handle does not refer to a request
1180 * message.
1181 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001182 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001183 tfm_core_panic();
1184 }
1185
1186 /*
1187 * It is a fatal error if outvec_idx is equal to or greater than
1188 * PSA_MAX_IOVEC.
1189 */
1190 if (outvec_idx >= PSA_MAX_IOVEC) {
1191 tfm_core_panic();
1192 }
1193
1194 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001195 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001196 tfm_core_panic();
1197 }
1198
1199 /*
1200 * It is a fatal error if the output vector has already been mapped using
1201 * psa_map_outvec().
1202 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001203 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001204 tfm_core_panic();
1205 }
1206
1207 /*
1208 * It is a fatal error if the output vector has already been accessed
1209 * using psa_write().
1210 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001211 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001212 tfm_core_panic();
1213 }
1214
1215 /*
1216 * It is a fatal error if the output vector is invalid or not read-write.
1217 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001218 if (tfm_memory_check(handle->outvec[outvec_idx].base,
1219 handle->outvec[outvec_idx].len, false,
Ken Liuad3f3e62022-03-04 22:23:52 +08001220 TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001221 tfm_core_panic();
1222 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001223 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001224
Mingyang Suna09adda2022-02-16 18:11:33 +08001225 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001226}
1227
1228void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1229 uint32_t outvec_idx, size_t len)
1230{
Mingyang Suna09adda2022-02-16 18:11:33 +08001231 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001232
1233 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001234 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001235 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001236 tfm_core_panic();
1237 }
1238
1239 /*
1240 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1241 * Service that received the message.
1242 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001243 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001244 tfm_core_panic();
1245 }
1246
1247 /*
1248 * It is a fatal error if message handle does not refer to a request
1249 * message.
1250 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001251 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001252 tfm_core_panic();
1253 }
1254
1255 /*
1256 * It is a fatal error if outvec_idx is equal to or greater than
1257 * PSA_MAX_IOVEC.
1258 */
1259 if (outvec_idx >= PSA_MAX_IOVEC) {
1260 tfm_core_panic();
1261 }
1262
1263 /*
1264 * It is a fatal error if len is greater than the output vector size.
1265 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001266 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001267 tfm_core_panic();
1268 }
1269
1270 /*
1271 * It is a fatal error if The output vector has not been mapped by a call to
1272 * psa_map_outvec().
1273 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001274 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001275 tfm_core_panic();
1276 }
1277
1278 /*
1279 * It is a fatal error if the output vector has already been unmapped by a
1280 * call to psa_unmap_outvec().
1281 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001282 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001283 tfm_core_panic();
1284 }
1285
Mingyang Suna09adda2022-02-16 18:11:33 +08001286 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001287
1288 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001289 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001290}
1291
1292#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */