blob: 52990811e78a77c4ce0ec420536de306e970ad61 [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. */
Summer Qin22c301a2022-04-27 17:36:00 +0800166 if ((in_num > SIZE_MAX - out_num) ||
David Hu733d8f92019-09-23 15:32:40 +0800167 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800168 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800169 }
170
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800171 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
172 if (handle == PSA_NULL_HANDLE) {
173 return PSA_ERROR_PROGRAMMER_ERROR;
174 }
175
Kevin Peng385fda82021-08-18 10:41:19 +0800176 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800177
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800178 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800179 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800180 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800181
182 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800183 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800184 }
185
Mingyang Sun453ad402021-03-17 17:58:33 +0800186 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800187 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800188 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800189 }
190
Ken Liub3b2cb62021-05-22 00:39:28 +0800191 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800192
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800193 /*
194 * It is a PROGRAMMER ERROR if the caller is not authorized to access
195 * the RoT Service.
196 */
197 if (tfm_spm_check_authorization(sid, service, ns_caller)
Ken Liuad3f3e62022-03-04 22:23:52 +0800198 != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800199 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800200 }
201
Mingyang Sun453ad402021-03-17 17:58:33 +0800202 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
203
Ken Liuad3f3e62022-03-04 22:23:52 +0800204 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800205 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800206 }
207
Mingyang Sun620c8562021-11-10 11:44:58 +0800208 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800209 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800210 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800211
212 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800213 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800214 }
215
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800216 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800217 handle = tfm_spm_to_user_handle(conn_handle);
218 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800219#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800220 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800221 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
222 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800223 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800224 }
225
226 /*
227 * It is a PROGRAMMER ERROR if the connection is currently
228 * handling a request.
229 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800230 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800231 return PSA_ERROR_PROGRAMMER_ERROR;
232 }
233
Ken Liu0bed7e02022-02-10 12:38:07 +0800234 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800235
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800236 if (!service) {
237 /* FixMe: Need to implement a mechanism to resolve this failure. */
238 return PSA_ERROR_PROGRAMMER_ERROR;
239 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800240#else
241 return PSA_ERROR_PROGRAMMER_ERROR;
242#endif
David Hu733d8f92019-09-23 15:32:40 +0800243 }
244
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800245 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800246
Kevin Pengedb8ee42021-03-09 16:50:11 +0800247 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800248 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800249 * if the memory reference for the wrap input vector is invalid or not
250 * readable.
251 */
252 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800253 TFM_MEMORY_ACCESS_RO, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800254 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800255 }
Summer Qinba2346e2019-11-12 16:26:31 +0800256
David Hu733d8f92019-09-23 15:32:40 +0800257 /*
258 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800259 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800260 * the wrap output vector is invalid or not read-write.
261 */
262 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800263 TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800264 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800265 }
266
Summer Qinf24dbb52020-07-23 14:53:54 +0800267 spm_memset(invecs, 0, sizeof(invecs));
268 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800269
270 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800271 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
272 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800273
274 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800275 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800276 * memory reference was invalid or not readable.
277 */
278 for (i = 0; i < in_num; i++) {
279 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800280 TFM_MEMORY_ACCESS_RO, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800281 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800282 }
283 }
Summer Qinba2346e2019-11-12 16:26:31 +0800284
285 /*
286 * Clients must never overlap input parameters because of the risk of a
287 * double-fetch inconsistency.
288 * Overflow is checked in tfm_memory_check functions.
289 */
290 for (i = 0; i + 1 < in_num; i++) {
291 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100292 if (!((char *) invecs[j].base + invecs[j].len <=
293 (char *) invecs[i].base ||
294 (char *) invecs[j].base >=
295 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800296 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800297 }
298 }
299 }
300
David Hu733d8f92019-09-23 15:32:40 +0800301 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800302 * For client output vector, it is a PROGRAMMER ERROR if the provided
303 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800304 */
305 for (i = 0; i < out_num; i++) {
306 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liuad3f3e62022-03-04 22:23:52 +0800307 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800308 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800309 }
310 }
311
Ken Liu0bed7e02022-02-10 12:38:07 +0800312 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800313 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800314
Ken Liu0bed7e02022-02-10 12:38:07 +0800315 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800316}
317
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800318/* Following PSA APIs are only needed by connection-based services */
319#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
320
321psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
322{
323 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800324 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800325 int32_t client_id;
326 psa_handle_t handle;
327 bool ns_caller = tfm_spm_is_ns_caller();
328 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
329
330 /*
331 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
332 * platform.
333 */
334 service = tfm_spm_get_service_by_sid(sid);
335 if (!service) {
336 return PSA_ERROR_CONNECTION_REFUSED;
337 }
338
339 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
340 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
341 return PSA_ERROR_PROGRAMMER_ERROR;
342 }
343
344 /*
345 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
346 * RoT Service.
347 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800348 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800349 return PSA_ERROR_CONNECTION_REFUSED;
350 }
351
352 /*
353 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
354 * not supported on the platform.
355 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800356 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800357 return PSA_ERROR_CONNECTION_REFUSED;
358 }
359
360 client_id = tfm_spm_get_client_id(ns_caller);
361
362 /*
363 * Create connection handle here since it is possible to return the error
364 * code to client when creation fails.
365 */
366 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800367 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800368 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800369 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800370 return PSA_ERROR_CONNECTION_BUSY;
371 }
372
Mingyang Suna09adda2022-02-16 18:11:33 +0800373 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800374 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800375 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800376 client_id, NULL, 0, NULL, 0, NULL);
377
Mingyang Suna09adda2022-02-16 18:11:33 +0800378 return backend_instance.messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800379}
380
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800381psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800382{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800383 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800384 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800385 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800386 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800387
388 /* It will have no effect if called with the NULL handle */
389 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800390 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800391 }
392
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800393 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800394 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800395 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800396 }
397
Kevin Peng385fda82021-08-18 10:41:19 +0800398 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800399
David Hu733d8f92019-09-23 15:32:40 +0800400 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800401 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
402 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800403 */
Kevin Penge61e7052022-01-27 14:57:06 +0800404 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
405 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800406 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800407 }
Shawn Shanb222d892021-01-04 17:41:48 +0800408
Ken Liu0bed7e02022-02-10 12:38:07 +0800409 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800410 if (!service) {
411 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800412 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800413 }
414
Shawn Shanb222d892021-01-04 17:41:48 +0800415 /*
416 * It is a PROGRAMMER ERROR if the connection is currently handling a
417 * request.
418 */
Summer Qin630c76b2020-05-20 10:32:58 +0800419 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800420 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800421 }
422
David Hu733d8f92019-09-23 15:32:40 +0800423 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800424 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
425 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800426
Ken Liu0bed7e02022-02-10 12:38:07 +0800427 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800428}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800429
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800430#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
431
Mingyang Suneeca4652021-07-15 15:19:16 +0800432/* PSA Partition API function body */
433
Kevin Pengdef92de2021-11-10 16:14:48 +0800434#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
435 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800436psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
437 uint32_t timeout)
438{
439 struct partition_t *partition = NULL;
440
441 /*
442 * Timeout[30:0] are reserved for future use.
443 * SPM must ignore the value of RES.
444 */
445 timeout &= PSA_TIMEOUT_MASK;
446
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800447 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800448
449 /*
450 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
451 * signals.
452 */
453 if ((partition->signals_allowed & signal_mask) == 0) {
454 tfm_core_panic();
455 }
456
457 /*
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800458 * backend_instance.wait() blocks the caller thread if no signals are
459 * available. In this case, the return value of this function is temporary
460 * set into runtime context. After new signal(s) are available, the return
461 * value is updated with the available signal(s) and blocked thread gets
462 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800463 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800464 if (timeout == PSA_BLOCK) {
465 return backend_instance.wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800466 }
467
468 return partition->signals_asserted & signal_mask;
469}
Kevin Pengdef92de2021-11-10 16:14:48 +0800470#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800471
Kevin Pengdef92de2021-11-10 16:14:48 +0800472#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800473psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
474{
Mingyang Suna09adda2022-02-16 18:11:33 +0800475 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800476 struct partition_t *partition = NULL;
477 uint32_t privileged;
478
479 /*
480 * Only one message could be retrieved every time for psa_get(). It is a
481 * fatal error if the input signal has more than a signal bit set.
482 */
483 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
484 tfm_core_panic();
485 }
486
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800487 partition = GET_CURRENT_COMPONENT();
488
Kevin Penga40d29f2022-01-19 14:44:34 +0800489 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800490
491 /*
492 * Write the message to the service buffer. It is a fatal error if the
493 * input msg pointer is not a valid memory reference or not read-write.
494 */
495 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
Ken Liuad3f3e62022-03-04 22:23:52 +0800496 privileged) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800497 tfm_core_panic();
498 }
499
500 /*
501 * It is a fatal error if the caller call psa_get() when no message has
502 * been set. The caller must call this function after an RoT Service signal
503 * is returned by psa_wait().
504 */
505 if (partition->signals_asserted == 0) {
506 tfm_core_panic();
507 }
508
509 /*
510 * It is a fatal error if the RoT Service signal is not currently asserted.
511 */
512 if ((partition->signals_asserted & signal) == 0) {
513 tfm_core_panic();
514 }
515
516 /*
517 * Get message by signal from partition. It is a fatal error if getting
518 * failed, which means the input signal is not correspond to an RoT service.
519 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800520 handle = spm_get_handle_by_signal(partition, signal);
521 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800522 return PSA_ERROR_DOES_NOT_EXIST;
523 }
524
Mingyang Suna09adda2022-02-16 18:11:33 +0800525 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800526
527 return PSA_SUCCESS;
528}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800529#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800530
Mingyang Sunb26b2802021-07-07 11:25:00 +0800531size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
532 void *buffer, size_t num_bytes)
533{
534 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800535 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800536 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800537
538 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800539 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800540 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800541 tfm_core_panic();
542 }
543
Mingyang Suna09adda2022-02-16 18:11:33 +0800544 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
545 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800546
547 /*
548 * It is a fatal error if message handle does not refer to a request
549 * message
550 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800551 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800552 tfm_core_panic();
553 }
554
555 /*
556 * It is a fatal error if invec_idx is equal to or greater than
557 * PSA_MAX_IOVEC
558 */
559 if (invec_idx >= PSA_MAX_IOVEC) {
560 tfm_core_panic();
561 }
562
Shawn Shan038348e2021-09-08 17:11:04 +0800563#if PSA_FRAMEWORK_HAS_MM_IOVEC
564 /*
565 * It is a fatal error if the input vector has already been mapped using
566 * psa_map_invec().
567 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800568 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800569 tfm_core_panic();
570 }
571
Mingyang Suna09adda2022-02-16 18:11:33 +0800572 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800573#endif
574
Kevin Peng016b0e42022-04-15 11:28:48 +0800575 /* There was no remaining data in this input vector */
576 if (handle->msg.in_size[invec_idx] == 0) {
577 return 0;
578 }
579
Mingyang Sunb26b2802021-07-07 11:25:00 +0800580 /*
581 * Copy the client data to the service buffer. It is a fatal error
582 * if the memory reference for buffer is invalid or not read-write.
583 */
584 if (tfm_memory_check(buffer, num_bytes, false,
Ken Liuad3f3e62022-03-04 22:23:52 +0800585 TFM_MEMORY_ACCESS_RW, priv_mode) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800586 tfm_core_panic();
587 }
588
Mingyang Suna09adda2022-02-16 18:11:33 +0800589 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
590 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800591
Mingyang Suna09adda2022-02-16 18:11:33 +0800592 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800593
594 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800595 handle->invec[invec_idx].base =
596 (char *)handle->invec[invec_idx].base + bytes;
597 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800598
599 return bytes;
600}
601
602size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
603 size_t num_bytes)
604{
Mingyang Suna09adda2022-02-16 18:11:33 +0800605 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800606
607 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800608 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800609 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800610 tfm_core_panic();
611 }
612
613 /*
614 * It is a fatal error if message handle does not refer to a request
615 * message
616 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800617 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800618 tfm_core_panic();
619 }
620
621 /*
622 * It is a fatal error if invec_idx is equal to or greater than
623 * PSA_MAX_IOVEC
624 */
625 if (invec_idx >= PSA_MAX_IOVEC) {
626 tfm_core_panic();
627 }
628
Shawn Shan038348e2021-09-08 17:11:04 +0800629#if PSA_FRAMEWORK_HAS_MM_IOVEC
630 /*
631 * It is a fatal error if the input vector has already been mapped using
632 * psa_map_invec().
633 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800634 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800635 tfm_core_panic();
636 }
637
Mingyang Suna09adda2022-02-16 18:11:33 +0800638 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800639#endif
640
Kevin Peng016b0e42022-04-15 11:28:48 +0800641 /* There was no remaining data in this input vector */
642 if (handle->msg.in_size[invec_idx] == 0) {
643 return 0;
644 }
645
Mingyang Sunb26b2802021-07-07 11:25:00 +0800646 /*
647 * If num_bytes is greater than the remaining size of the input vector then
648 * the remaining size of the input vector is used.
649 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800650 if (num_bytes > handle->msg.in_size[invec_idx]) {
651 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800652 }
653
654 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800655 handle->invec[invec_idx].base =
656 (char *)handle->invec[invec_idx].base + num_bytes;
657 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800658
659 return num_bytes;
660}
661
662void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
663 const void *buffer, size_t num_bytes)
664{
Mingyang Suna09adda2022-02-16 18:11:33 +0800665 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800666 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800667
668 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800669 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800670 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800671 tfm_core_panic();
672 }
673
Mingyang Suna09adda2022-02-16 18:11:33 +0800674 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
675 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800676
677 /*
678 * It is a fatal error if message handle does not refer to a request
679 * message
680 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800681 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800682 tfm_core_panic();
683 }
684
685 /*
686 * It is a fatal error if outvec_idx is equal to or greater than
687 * PSA_MAX_IOVEC
688 */
689 if (outvec_idx >= PSA_MAX_IOVEC) {
690 tfm_core_panic();
691 }
692
693 /*
694 * It is a fatal error if the call attempts to write data past the end of
695 * the client output vector
696 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800697 if (num_bytes > handle->msg.out_size[outvec_idx] -
698 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800699 tfm_core_panic();
700 }
701
Shawn Shan038348e2021-09-08 17:11:04 +0800702#if PSA_FRAMEWORK_HAS_MM_IOVEC
703 /*
704 * It is a fatal error if the output vector has already been mapped using
705 * psa_map_outvec().
706 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800707 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800708 tfm_core_panic();
709 }
710
Mingyang Suna09adda2022-02-16 18:11:33 +0800711 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800712#endif
713
Mingyang Sunb26b2802021-07-07 11:25:00 +0800714 /*
715 * Copy the service buffer to client outvecs. It is a fatal error
716 * if the memory reference for buffer is invalid or not readable.
717 */
718 if (tfm_memory_check(buffer, num_bytes, false,
Ken Liuad3f3e62022-03-04 22:23:52 +0800719 TFM_MEMORY_ACCESS_RO, priv_mode) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800720 tfm_core_panic();
721 }
722
Mingyang Suna09adda2022-02-16 18:11:33 +0800723 spm_memcpy((char *)handle->outvec[outvec_idx].base +
724 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800725
726 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800727 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800728}
729
Ken Liuf8c7e532022-02-10 15:03:04 +0800730psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
731 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800732{
Ken Liu0bed7e02022-02-10 12:38:07 +0800733 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800734 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800735 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800736 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800737
738 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800739 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800740 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800741 tfm_core_panic();
742 }
743
744 /*
745 * RoT Service information is needed in this function, stored it in message
746 * body structure. Only two parameters are passed in this function: handle
747 * and status, so it is useful and simply to do like this.
748 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800749 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800750 if (!service) {
751 tfm_core_panic();
752 }
753
Mingyang Suna09adda2022-02-16 18:11:33 +0800754 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800755 case PSA_IPC_CONNECT:
756 /*
757 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
758 * input status is PSA_SUCCESS. Others return values are based on the
759 * input status.
760 */
761 if (status == PSA_SUCCESS) {
762 ret = msg_handle;
763 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
764 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800765 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800766 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800767 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
768 /* Fail the client connection, indicating a transient error. */
769 ret = PSA_ERROR_CONNECTION_BUSY;
770 } else {
771 tfm_core_panic();
772 }
773 break;
774 case PSA_IPC_DISCONNECT:
775 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800776 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800777
778 /*
779 * If the message type is PSA_IPC_DISCONNECT, then the status code is
780 * ignored
781 */
782 break;
783 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800784 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800785
786#if PSA_FRAMEWORK_HAS_MM_IOVEC
787
788 /*
789 * If the unmapped function is not called for an input/output vector
790 * that has been mapped, the framework will remove the mapping.
791 */
792 int i;
793
794 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800795 if (IOVEC_IS_MAPPED(handle, i) &&
796 (!IOVEC_IS_UNMAPPED(handle, i))) {
797 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800798 /*
799 * Any output vectors that are still mapped will report that
800 * zero bytes have been written.
801 */
802 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800803 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800804 }
805 }
806 }
807
808#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800809 /* Reply to a request message. Return values are based on status */
810 ret = status;
811 /*
812 * The total number of bytes written to a single parameter must be
813 * reported to the client by updating the len member of the
814 * psa_outvec structure for the parameter before returning from
815 * psa_call().
816 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800817 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800818 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800819 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800820 }
821 } else {
822 tfm_core_panic();
823 }
824 }
825
826 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
827 /*
828 * If the source of the programmer error is a Secure Partition, the SPM
829 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
830 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800831 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800832 tfm_core_panic();
833 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800834 }
835
Mingyang Sun620c8562021-11-10 11:44:58 +0800836 /*
837 * TODO: It can be optimized further by moving critical section protection
838 * to mailbox. Also need to check implementation when secure context is
839 * involved.
840 */
841 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800842 ret = backend_instance.replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800843 CRITICAL_SECTION_LEAVE(cs_assert);
844
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800845 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
846 tfm_spm_free_conn_handle(handle);
847 } else {
848 handle->status = TFM_HANDLE_STATUS_IDLE;
849 }
850
Mingyang Sun620c8562021-11-10 11:44:58 +0800851 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800852}
853
Kevin Peng613b4172022-02-15 14:41:44 +0800854#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800855void tfm_spm_partition_psa_notify(int32_t partition_id)
856{
Ken Liu5d73c872021-08-19 19:23:17 +0800857 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
858
859 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800860}
861
862void tfm_spm_partition_psa_clear(void)
863{
Ken Liu92ede9f2021-10-20 09:35:00 +0800864 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800865 struct partition_t *partition = NULL;
866
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800867 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800868
869 /*
870 * It is a fatal error if the Secure Partition's doorbell signal is not
871 * currently asserted.
872 */
873 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
874 tfm_core_panic();
875 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800876
877 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800878 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800879 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800880}
Kevin Peng613b4172022-02-15 14:41:44 +0800881#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800882
Mingyang Sunb26b2802021-07-07 11:25:00 +0800883void tfm_spm_partition_psa_panic(void)
884{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100885#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
886 tfm_hal_system_halt();
887#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800888 /*
889 * PSA FF recommends that the SPM causes the system to restart when a secure
890 * partition panics.
891 */
892 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100893#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800894}
895
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800896/* psa_set_rhandle is only needed by connection-based services */
897#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
898
899void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
900{
Mingyang Suna09adda2022-02-16 18:11:33 +0800901 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800902
903 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800904 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800905 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800906 tfm_core_panic();
907 }
908
909 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800910 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800911 tfm_core_panic();
912 }
913
Mingyang Suna09adda2022-02-16 18:11:33 +0800914 handle->msg.rhandle = rhandle;
915 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800916}
917
918#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
919
920#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800921void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800922{
923 struct partition_t *partition;
924 struct irq_load_info_t *irq_info;
925
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800926 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800927
928 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
929 if (!irq_info) {
930 tfm_core_panic();
931 }
932
Kevin Pengd399a1f2021-09-08 15:33:14 +0800933 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800934}
935
Kevin Peng67a89fd2021-11-25 11:22:02 +0800936psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800937{
938 struct partition_t *partition;
939 struct irq_load_info_t *irq_info;
940
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800941 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800942
943 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
944 if (!irq_info) {
945 tfm_core_panic();
946 }
947
Kevin Pengd399a1f2021-09-08 15:33:14 +0800948 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800949
950 return 1;
951}
952
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800953/* This API is only used for FLIH. */
954#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800955void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
956{
Ken Liu92ede9f2021-10-20 09:35:00 +0800957 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800958 struct irq_load_info_t *irq_info;
959 struct partition_t *partition;
960
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800961 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800962
963 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
964 if (!irq_info) {
965 tfm_core_panic();
966 }
967
968 if (!irq_info->flih_func) {
969 /* This API is for FLIH IRQs only */
970 tfm_core_panic();
971 }
972
973 if ((partition->signals_asserted & irq_signal) == 0) {
974 /* The signal is not asserted */
975 tfm_core_panic();
976 }
977
Ken Liu92ede9f2021-10-20 09:35:00 +0800978 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800979 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800980 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800981}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800982#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800983
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800984/* This API is only used for SLIH. */
985#if CONFIG_TFM_SLIH_API == 1
986void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800987{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800988 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
989 struct irq_load_info_t *irq_info = NULL;
990 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800991
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800992 partition = GET_CURRENT_COMPONENT();
993
994 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
995 /* It is a fatal error if passed signal is not an interrupt signal. */
996 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800997 tfm_core_panic();
998 }
999
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001000 if (irq_info->flih_func) {
1001 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001002 tfm_core_panic();
1003 }
1004
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001005 /* It is a fatal error if passed signal is not currently asserted */
1006 if ((partition->signals_asserted & irq_signal) == 0) {
1007 tfm_core_panic();
1008 }
1009
1010 CRITICAL_SECTION_ENTER(cs_assert);
1011 partition->signals_asserted &= ~irq_signal;
1012 CRITICAL_SECTION_LEAVE(cs_assert);
1013
1014 tfm_hal_irq_clear_pending(irq_info->source);
1015 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001016}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001017#endif
1018#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001019
Shawn Shan038348e2021-09-08 17:11:04 +08001020#if PSA_FRAMEWORK_HAS_MM_IOVEC
1021
1022const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1023 uint32_t invec_idx)
1024{
Mingyang Suna09adda2022-02-16 18:11:33 +08001025 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001026 uint32_t privileged;
1027 struct partition_t *partition = NULL;
1028
1029 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001030 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001031 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001032 tfm_core_panic();
1033 }
1034
Mingyang Suna09adda2022-02-16 18:11:33 +08001035 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001036 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001037
1038 /*
1039 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1040 * Service that received the message.
1041 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001042 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001043 tfm_core_panic();
1044 }
1045
1046 /*
1047 * It is a fatal error if message handle does not refer to a request
1048 * message.
1049 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001050 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001051 tfm_core_panic();
1052 }
1053
1054 /*
1055 * It is a fatal error if invec_idx is equal to or greater than
1056 * PSA_MAX_IOVEC.
1057 */
1058 if (invec_idx >= PSA_MAX_IOVEC) {
1059 tfm_core_panic();
1060 }
1061
1062 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001063 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001064 tfm_core_panic();
1065 }
1066
1067 /*
1068 * It is a fatal error if the input vector has already been mapped using
1069 * psa_map_invec().
1070 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001071 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001072 tfm_core_panic();
1073 }
1074
1075 /*
1076 * It is a fatal error if the input vector has already been accessed
1077 * using psa_read() or psa_skip().
1078 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001079 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001080 tfm_core_panic();
1081 }
1082
1083 /*
1084 * It is a fatal error if the memory reference for the wrap input vector is
1085 * invalid or not readable.
1086 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001087 if (tfm_memory_check(handle->invec[invec_idx].base,
1088 handle->invec[invec_idx].len,
1089 false, TFM_MEMORY_ACCESS_RO,
Ken Liuad3f3e62022-03-04 22:23:52 +08001090 privileged) != PSA_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001091 tfm_core_panic();
1092 }
1093
Mingyang Suna09adda2022-02-16 18:11:33 +08001094 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001095
Mingyang Suna09adda2022-02-16 18:11:33 +08001096 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001097}
1098
1099void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1100 uint32_t invec_idx)
1101{
Mingyang Suna09adda2022-02-16 18:11:33 +08001102 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001103
1104 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001105 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001106 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001107 tfm_core_panic();
1108 }
1109
1110 /*
1111 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1112 * Service that received the message.
1113 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001114 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001115 tfm_core_panic();
1116 }
1117
1118 /*
1119 * It is a fatal error if message handle does not refer to a request
1120 * message.
1121 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001122 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001123 tfm_core_panic();
1124 }
1125
1126 /*
1127 * It is a fatal error if invec_idx is equal to or greater than
1128 * PSA_MAX_IOVEC.
1129 */
1130 if (invec_idx >= PSA_MAX_IOVEC) {
1131 tfm_core_panic();
1132 }
1133
1134 /*
1135 * It is a fatal error if The input vector has not been mapped by a call to
1136 * psa_map_invec().
1137 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001138 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001139 tfm_core_panic();
1140 }
1141
1142 /*
1143 * It is a fatal error if the input vector has already been unmapped by a
1144 * call to psa_unmap_invec().
1145 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001146 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001147 tfm_core_panic();
1148 }
1149
Mingyang Suna09adda2022-02-16 18:11:33 +08001150 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001151}
1152
1153void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1154 uint32_t outvec_idx)
1155{
Mingyang Suna09adda2022-02-16 18:11:33 +08001156 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001157 uint32_t privileged;
1158 struct partition_t *partition = NULL;
1159
1160 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001161 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001162 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001163 tfm_core_panic();
1164 }
1165
Mingyang Suna09adda2022-02-16 18:11:33 +08001166 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001167 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001168
1169 /*
1170 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1171 * Service that received the message.
1172 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001173 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001174 tfm_core_panic();
1175 }
1176
1177 /*
1178 * It is a fatal error if message handle does not refer to a request
1179 * message.
1180 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001181 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001182 tfm_core_panic();
1183 }
1184
1185 /*
1186 * It is a fatal error if outvec_idx is equal to or greater than
1187 * PSA_MAX_IOVEC.
1188 */
1189 if (outvec_idx >= PSA_MAX_IOVEC) {
1190 tfm_core_panic();
1191 }
1192
1193 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001194 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001195 tfm_core_panic();
1196 }
1197
1198 /*
1199 * It is a fatal error if the output vector has already been mapped using
1200 * psa_map_outvec().
1201 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001202 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001203 tfm_core_panic();
1204 }
1205
1206 /*
1207 * It is a fatal error if the output vector has already been accessed
1208 * using psa_write().
1209 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001210 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001211 tfm_core_panic();
1212 }
1213
1214 /*
1215 * It is a fatal error if the output vector is invalid or not read-write.
1216 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001217 if (tfm_memory_check(handle->outvec[outvec_idx].base,
1218 handle->outvec[outvec_idx].len, false,
Ken Liuad3f3e62022-03-04 22:23:52 +08001219 TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001220 tfm_core_panic();
1221 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001222 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001223
Mingyang Suna09adda2022-02-16 18:11:33 +08001224 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001225}
1226
1227void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1228 uint32_t outvec_idx, size_t len)
1229{
Mingyang Suna09adda2022-02-16 18:11:33 +08001230 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001231
1232 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001233 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001234 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001235 tfm_core_panic();
1236 }
1237
1238 /*
1239 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1240 * Service that received the message.
1241 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001242 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001243 tfm_core_panic();
1244 }
1245
1246 /*
1247 * It is a fatal error if message handle does not refer to a request
1248 * message.
1249 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001250 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001251 tfm_core_panic();
1252 }
1253
1254 /*
1255 * It is a fatal error if outvec_idx is equal to or greater than
1256 * PSA_MAX_IOVEC.
1257 */
1258 if (outvec_idx >= PSA_MAX_IOVEC) {
1259 tfm_core_panic();
1260 }
1261
1262 /*
1263 * It is a fatal error if len is greater than the output vector size.
1264 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001265 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001266 tfm_core_panic();
1267 }
1268
1269 /*
1270 * It is a fatal error if The output vector has not been mapped by a call to
1271 * psa_map_outvec().
1272 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001273 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001274 tfm_core_panic();
1275 }
1276
1277 /*
1278 * It is a fatal error if the output vector has already been unmapped by a
1279 * call to psa_unmap_outvec().
1280 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001281 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001282 tfm_core_panic();
1283 }
1284
Mingyang Suna09adda2022-02-16 18:11:33 +08001285 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001286
1287 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001288 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001289}
1290
1291#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */