blob: 55cc169a76b99201b0c10d2fcc8d653d5a91f317 [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"
Mingyang Sunb26b2802021-07-07 11:25:00 +080017#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080018#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080019#include "load/interrupt_defs.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080020#include "ffm/psa_api.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080021#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080022#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080023#include "ffm/psa_api.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080024#include "tfm_rpc.h"
25#include "tfm_spm_hal.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080026#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080027#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080028#include "tfm_psa_call_pack.h"
David Hu733d8f92019-09-23 15:32:40 +080029
Ken Liub3b2cb62021-05-22 00:39:28 +080030#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080031extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080032
Shawn Shan038348e2021-09-08 17:11:04 +080033#if PSA_FRAMEWORK_HAS_MM_IOVEC
34
35/*
36 * The MM-IOVEC status
37 * The max total number of invec and outvec is 8.
38 * Each invec/outvec takes 4 bit, 32 bits in total.
39 *
40 * The encoding format of the MM-IOVEC status:
41 *--------------------------------------------------------------
42 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
43 *--------------------------------------------------------------
44 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
45 *--------------------------------------------------------------
46 *
47 * Take invec[0] as an example:
48 *
49 * bit 0: whether invec[0] has been mapped.
50 * bit 1: whether invec[0] has been unmapped.
51 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
52 * psa_write().
53 * bit 3: reserved for invec[0].
54 */
55
56#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
57#define OUTVEC_IDX_BASE 4 /*
58 * Base index of outvec.
59 * There are four invecs in front of
60 * outvec.
61 */
62#define INVEC_IDX_BASE 0 /* Base index of invec. */
63
64#define IOVEC_MAPPED_BIT (1U << 0)
65#define IOVEC_UNMAPPED_BIT (1U << 1)
66#define IOVEC_ACCESSED_BIT (1U << 2)
67
Mingyang Suna09adda2022-02-16 18:11:33 +080068#define IOVEC_IS_MAPPED(handle, iovec_idx) \
69 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080070 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080071#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
72 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080073 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080074#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
75 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080076 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080077#define SET_IOVEC_MAPPED(handle, iovec_idx) \
78 (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080079 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080080#define SET_IOVEC_UNMAPPED(handle, iovec_idx) \
81 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080082 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080083#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
84 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080085 ((iovec_idx) * IOVEC_STATUS_BITS)))
86
87#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
88
Xinyu Zhangb287ef82021-11-03 18:38:50 +080089void spm_handle_programmer_errors(psa_status_t status)
90{
Summer Qind9d497b2022-04-14 14:39:26 +080091 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
92 status == PSA_ERROR_CONNECTION_REFUSED) {
93 if (!tfm_spm_is_ns_caller()) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +080094 tfm_core_panic();
Summer Qind9d497b2022-04-14 14:39:26 +080095 }
Xinyu Zhangb287ef82021-11-03 18:38:50 +080096 }
97}
98
Mingyang Suneeca4652021-07-15 15:19:16 +080099uint32_t tfm_spm_get_lifecycle_state(void)
100{
101 /*
102 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
103 * implemented in the future.
104 */
105 return PSA_LIFECYCLE_UNKNOWN;
106}
107
108/* PSA Client API function body */
109
Mingyang Sund44522a2020-01-16 16:48:37 +0800110uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800111{
112 return PSA_FRAMEWORK_VERSION;
113}
114
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800115uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800116{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800117 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800118 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800119
120 /*
121 * It should return PSA_VERSION_NONE if the RoT Service is not
122 * implemented.
123 */
124 service = tfm_spm_get_service_by_sid(sid);
125 if (!service) {
126 return PSA_VERSION_NONE;
127 }
128
129 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800130 * It should return PSA_VERSION_NONE if the caller is not authorized
131 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800132 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800133 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800134 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800135 }
136
Ken Liuacd2a572021-05-12 16:19:04 +0800137 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800138}
139
Mingyang Suneeca4652021-07-15 15:19:16 +0800140psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
141 uint32_t ctrl_param,
142 const psa_invec *inptr,
143 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800144{
145 psa_invec invecs[PSA_MAX_IOVEC];
146 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800147 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800148 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800149 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800150 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800151 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800152 uint32_t privileged;
Mingyang Sun620c8562021-11-10 11:44:58 +0800153 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800154 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800155 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
156 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
157 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800158
159 /* The request type must be zero or positive. */
160 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800161 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800162 }
David Hu733d8f92019-09-23 15:32:40 +0800163
Shawn Shanb222d892021-01-04 17:41:48 +0800164 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
Summer Qin22c301a2022-04-27 17:36:00 +0800165 if ((in_num > SIZE_MAX - out_num) ||
David Hu733d8f92019-09-23 15:32:40 +0800166 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800167 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800168 }
169
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800170 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
171 if (handle == PSA_NULL_HANDLE) {
172 return PSA_ERROR_PROGRAMMER_ERROR;
173 }
174
Kevin Peng385fda82021-08-18 10:41:19 +0800175 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800176
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800177 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800178 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800179 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800180
181 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800182 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800183 }
184
Mingyang Sun453ad402021-03-17 17:58:33 +0800185 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800186 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800187 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800188 }
189
Ken Liub3b2cb62021-05-22 00:39:28 +0800190 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800191
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800192 /*
193 * It is a PROGRAMMER ERROR if the caller is not authorized to access
194 * the RoT Service.
195 */
196 if (tfm_spm_check_authorization(sid, service, ns_caller)
Ken Liuad3f3e62022-03-04 22:23:52 +0800197 != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800198 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800199 }
200
Mingyang Sun453ad402021-03-17 17:58:33 +0800201 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
202
Ken Liuad3f3e62022-03-04 22:23:52 +0800203 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800204 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800205 }
206
Mingyang Sun620c8562021-11-10 11:44:58 +0800207 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800208 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800209 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800210
211 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800212 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800213 }
214
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800215 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800216 handle = tfm_spm_to_user_handle(conn_handle);
217 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800218#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800219 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800220 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
221 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800222 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800223 }
224
225 /*
226 * It is a PROGRAMMER ERROR if the connection is currently
227 * handling a request.
228 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800229 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800230 return PSA_ERROR_PROGRAMMER_ERROR;
231 }
232
Ken Liu0bed7e02022-02-10 12:38:07 +0800233 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800234
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800235 if (!service) {
236 /* FixMe: Need to implement a mechanism to resolve this failure. */
237 return PSA_ERROR_PROGRAMMER_ERROR;
238 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800239#else
240 return PSA_ERROR_PROGRAMMER_ERROR;
241#endif
David Hu733d8f92019-09-23 15:32:40 +0800242 }
243
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800244 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800245
Kevin Pengedb8ee42021-03-09 16:50:11 +0800246 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800247 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800248 * if the memory reference for the wrap input vector is invalid or not
249 * readable.
250 */
251 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800252 TFM_MEMORY_ACCESS_RO, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800253 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800254 }
Summer Qinba2346e2019-11-12 16:26:31 +0800255
David Hu733d8f92019-09-23 15:32:40 +0800256 /*
257 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800258 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800259 * the wrap output vector is invalid or not read-write.
260 */
261 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800262 TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800263 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800264 }
265
Summer Qinf24dbb52020-07-23 14:53:54 +0800266 spm_memset(invecs, 0, sizeof(invecs));
267 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800268
269 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800270 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
271 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800272
273 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800274 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800275 * memory reference was invalid or not readable.
276 */
277 for (i = 0; i < in_num; i++) {
278 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liuad3f3e62022-03-04 22:23:52 +0800279 TFM_MEMORY_ACCESS_RO, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800280 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800281 }
282 }
Summer Qinba2346e2019-11-12 16:26:31 +0800283
284 /*
285 * Clients must never overlap input parameters because of the risk of a
286 * double-fetch inconsistency.
287 * Overflow is checked in tfm_memory_check functions.
288 */
289 for (i = 0; i + 1 < in_num; i++) {
290 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100291 if (!((char *) invecs[j].base + invecs[j].len <=
292 (char *) invecs[i].base ||
293 (char *) invecs[j].base >=
294 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800295 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800296 }
297 }
298 }
299
David Hu733d8f92019-09-23 15:32:40 +0800300 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800301 * For client output vector, it is a PROGRAMMER ERROR if the provided
302 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800303 */
304 for (i = 0; i < out_num; i++) {
305 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liuad3f3e62022-03-04 22:23:52 +0800306 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800307 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800308 }
309 }
310
Ken Liu0bed7e02022-02-10 12:38:07 +0800311 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800312 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800313
Ken Liu995a9742022-05-18 19:28:30 +0800314 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800315}
316
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800317/* Following PSA APIs are only needed by connection-based services */
318#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
319
320psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
321{
322 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800323 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800324 int32_t client_id;
325 psa_handle_t handle;
326 bool ns_caller = tfm_spm_is_ns_caller();
327 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
328
329 /*
330 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
331 * platform.
332 */
333 service = tfm_spm_get_service_by_sid(sid);
334 if (!service) {
335 return PSA_ERROR_CONNECTION_REFUSED;
336 }
337
338 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
339 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
340 return PSA_ERROR_PROGRAMMER_ERROR;
341 }
342
343 /*
344 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
345 * RoT Service.
346 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800347 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800348 return PSA_ERROR_CONNECTION_REFUSED;
349 }
350
351 /*
352 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
353 * not supported on the platform.
354 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800355 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800356 return PSA_ERROR_CONNECTION_REFUSED;
357 }
358
359 client_id = tfm_spm_get_client_id(ns_caller);
360
361 /*
362 * Create connection handle here since it is possible to return the error
363 * code to client when creation fails.
364 */
365 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800366 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800367 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800368 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800369 return PSA_ERROR_CONNECTION_BUSY;
370 }
371
Mingyang Suna09adda2022-02-16 18:11:33 +0800372 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800373 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800374 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800375 client_id, NULL, 0, NULL, 0, NULL);
376
Ken Liu995a9742022-05-18 19:28:30 +0800377 return backend_messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800378}
379
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800380psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800381{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800382 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800383 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800384 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800385 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800386
387 /* It will have no effect if called with the NULL handle */
388 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800389 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800390 }
391
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800392 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800393 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800394 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800395 }
396
Kevin Peng385fda82021-08-18 10:41:19 +0800397 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800398
David Hu733d8f92019-09-23 15:32:40 +0800399 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800400 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
401 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800402 */
Kevin Penge61e7052022-01-27 14:57:06 +0800403 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
404 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800405 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800406 }
Shawn Shanb222d892021-01-04 17:41:48 +0800407
Ken Liu0bed7e02022-02-10 12:38:07 +0800408 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800409 if (!service) {
410 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800411 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800412 }
413
Shawn Shanb222d892021-01-04 17:41:48 +0800414 /*
415 * It is a PROGRAMMER ERROR if the connection is currently handling a
416 * request.
417 */
Summer Qin630c76b2020-05-20 10:32:58 +0800418 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800419 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800420 }
421
David Hu733d8f92019-09-23 15:32:40 +0800422 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800423 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
424 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800425
Ken Liu995a9742022-05-18 19:28:30 +0800426 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800427}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800428
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800429#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
430
Mingyang Suneeca4652021-07-15 15:19:16 +0800431/* PSA Partition API function body */
432
Kevin Pengdef92de2021-11-10 16:14:48 +0800433#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
434 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800435psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
436 uint32_t timeout)
437{
438 struct partition_t *partition = NULL;
439
440 /*
441 * Timeout[30:0] are reserved for future use.
442 * SPM must ignore the value of RES.
443 */
444 timeout &= PSA_TIMEOUT_MASK;
445
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800446 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800447
448 /*
449 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
450 * signals.
451 */
452 if ((partition->signals_allowed & signal_mask) == 0) {
453 tfm_core_panic();
454 }
455
456 /*
Ken Liu995a9742022-05-18 19:28:30 +0800457 * backend_wake_up() blocks the caller thread if no signals are
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800458 * available. In this case, the return value of this function is temporary
459 * set into runtime context. After new signal(s) are available, the return
460 * value is updated with the available signal(s) and blocked thread gets
461 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800462 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800463 if (timeout == PSA_BLOCK) {
Ken Liu995a9742022-05-18 19:28:30 +0800464 return backend_wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800465 }
466
467 return partition->signals_asserted & signal_mask;
468}
Kevin Pengdef92de2021-11-10 16:14:48 +0800469#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800470
Kevin Pengdef92de2021-11-10 16:14:48 +0800471#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800472psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
473{
Mingyang Suna09adda2022-02-16 18:11:33 +0800474 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800475 struct partition_t *partition = NULL;
476 uint32_t privileged;
477
478 /*
479 * Only one message could be retrieved every time for psa_get(). It is a
480 * fatal error if the input signal has more than a signal bit set.
481 */
482 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
483 tfm_core_panic();
484 }
485
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800486 partition = GET_CURRENT_COMPONENT();
487
Kevin Penga40d29f2022-01-19 14:44:34 +0800488 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800489
490 /*
491 * Write the message to the service buffer. It is a fatal error if the
492 * input msg pointer is not a valid memory reference or not read-write.
493 */
494 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
Ken Liuad3f3e62022-03-04 22:23:52 +0800495 privileged) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800496 tfm_core_panic();
497 }
498
499 /*
500 * It is a fatal error if the caller call psa_get() when no message has
501 * been set. The caller must call this function after an RoT Service signal
502 * is returned by psa_wait().
503 */
504 if (partition->signals_asserted == 0) {
505 tfm_core_panic();
506 }
507
508 /*
509 * It is a fatal error if the RoT Service signal is not currently asserted.
510 */
511 if ((partition->signals_asserted & signal) == 0) {
512 tfm_core_panic();
513 }
514
515 /*
516 * Get message by signal from partition. It is a fatal error if getting
517 * failed, which means the input signal is not correspond to an RoT service.
518 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800519 handle = spm_get_handle_by_signal(partition, signal);
520 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800521 return PSA_ERROR_DOES_NOT_EXIST;
522 }
523
Mingyang Suna09adda2022-02-16 18:11:33 +0800524 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800525
526 return PSA_SUCCESS;
527}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800528#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800529
Mingyang Sunb26b2802021-07-07 11:25:00 +0800530size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
531 void *buffer, size_t num_bytes)
532{
533 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800534 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800535 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800536
537 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800538 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800539 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800540 tfm_core_panic();
541 }
542
Mingyang Suna09adda2022-02-16 18:11:33 +0800543 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
544 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800545
546 /*
547 * It is a fatal error if message handle does not refer to a request
548 * message
549 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800550 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800551 tfm_core_panic();
552 }
553
554 /*
555 * It is a fatal error if invec_idx is equal to or greater than
556 * PSA_MAX_IOVEC
557 */
558 if (invec_idx >= PSA_MAX_IOVEC) {
559 tfm_core_panic();
560 }
561
Shawn Shan038348e2021-09-08 17:11:04 +0800562#if PSA_FRAMEWORK_HAS_MM_IOVEC
563 /*
564 * It is a fatal error if the input vector has already been mapped using
565 * psa_map_invec().
566 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800567 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800568 tfm_core_panic();
569 }
570
Mingyang Suna09adda2022-02-16 18:11:33 +0800571 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800572#endif
573
Kevin Peng016b0e42022-04-15 11:28:48 +0800574 /* There was no remaining data in this input vector */
575 if (handle->msg.in_size[invec_idx] == 0) {
576 return 0;
577 }
578
Mingyang Sunb26b2802021-07-07 11:25:00 +0800579 /*
580 * Copy the client data to the service buffer. It is a fatal error
581 * if the memory reference for buffer is invalid or not read-write.
582 */
583 if (tfm_memory_check(buffer, num_bytes, false,
Ken Liuad3f3e62022-03-04 22:23:52 +0800584 TFM_MEMORY_ACCESS_RW, priv_mode) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800585 tfm_core_panic();
586 }
587
Mingyang Suna09adda2022-02-16 18:11:33 +0800588 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
589 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800590
Mingyang Suna09adda2022-02-16 18:11:33 +0800591 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800592
593 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800594 handle->invec[invec_idx].base =
595 (char *)handle->invec[invec_idx].base + bytes;
596 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800597
598 return bytes;
599}
600
601size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
602 size_t num_bytes)
603{
Mingyang Suna09adda2022-02-16 18:11:33 +0800604 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800605
606 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800607 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800608 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800609 tfm_core_panic();
610 }
611
612 /*
613 * It is a fatal error if message handle does not refer to a request
614 * message
615 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800616 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800617 tfm_core_panic();
618 }
619
620 /*
621 * It is a fatal error if invec_idx is equal to or greater than
622 * PSA_MAX_IOVEC
623 */
624 if (invec_idx >= PSA_MAX_IOVEC) {
625 tfm_core_panic();
626 }
627
Shawn Shan038348e2021-09-08 17:11:04 +0800628#if PSA_FRAMEWORK_HAS_MM_IOVEC
629 /*
630 * It is a fatal error if the input vector has already been mapped using
631 * psa_map_invec().
632 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800633 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800634 tfm_core_panic();
635 }
636
Mingyang Suna09adda2022-02-16 18:11:33 +0800637 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800638#endif
639
Kevin Peng016b0e42022-04-15 11:28:48 +0800640 /* There was no remaining data in this input vector */
641 if (handle->msg.in_size[invec_idx] == 0) {
642 return 0;
643 }
644
Mingyang Sunb26b2802021-07-07 11:25:00 +0800645 /*
646 * If num_bytes is greater than the remaining size of the input vector then
647 * the remaining size of the input vector is used.
648 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800649 if (num_bytes > handle->msg.in_size[invec_idx]) {
650 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800651 }
652
653 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800654 handle->invec[invec_idx].base =
655 (char *)handle->invec[invec_idx].base + num_bytes;
656 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800657
658 return num_bytes;
659}
660
661void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
662 const void *buffer, size_t num_bytes)
663{
Mingyang Suna09adda2022-02-16 18:11:33 +0800664 struct conn_handle_t *handle = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800665 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800666
667 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800668 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800669 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800670 tfm_core_panic();
671 }
672
Mingyang Suna09adda2022-02-16 18:11:33 +0800673 priv_mode = GET_PARTITION_PRIVILEGED_MODE(
674 handle->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800675
676 /*
677 * It is a fatal error if message handle does not refer to a request
678 * message
679 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800680 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800681 tfm_core_panic();
682 }
683
684 /*
685 * It is a fatal error if outvec_idx is equal to or greater than
686 * PSA_MAX_IOVEC
687 */
688 if (outvec_idx >= PSA_MAX_IOVEC) {
689 tfm_core_panic();
690 }
691
692 /*
693 * It is a fatal error if the call attempts to write data past the end of
694 * the client output vector
695 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800696 if (num_bytes > handle->msg.out_size[outvec_idx] -
697 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800698 tfm_core_panic();
699 }
700
Shawn Shan038348e2021-09-08 17:11:04 +0800701#if PSA_FRAMEWORK_HAS_MM_IOVEC
702 /*
703 * It is a fatal error if the output vector has already been mapped using
704 * psa_map_outvec().
705 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800706 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800707 tfm_core_panic();
708 }
709
Mingyang Suna09adda2022-02-16 18:11:33 +0800710 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800711#endif
712
Mingyang Sunb26b2802021-07-07 11:25:00 +0800713 /*
714 * Copy the service buffer to client outvecs. It is a fatal error
715 * if the memory reference for buffer is invalid or not readable.
716 */
717 if (tfm_memory_check(buffer, num_bytes, false,
Ken Liuad3f3e62022-03-04 22:23:52 +0800718 TFM_MEMORY_ACCESS_RO, priv_mode) != PSA_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800719 tfm_core_panic();
720 }
721
Mingyang Suna09adda2022-02-16 18:11:33 +0800722 spm_memcpy((char *)handle->outvec[outvec_idx].base +
723 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800724
725 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800726 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800727}
728
Ken Liuf8c7e532022-02-10 15:03:04 +0800729psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
730 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800731{
Ken Liu0bed7e02022-02-10 12:38:07 +0800732 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800733 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800734 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800735 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800736
737 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800738 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800739 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800740 tfm_core_panic();
741 }
742
743 /*
744 * RoT Service information is needed in this function, stored it in message
745 * body structure. Only two parameters are passed in this function: handle
746 * and status, so it is useful and simply to do like this.
747 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800748 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800749 if (!service) {
750 tfm_core_panic();
751 }
752
Mingyang Suna09adda2022-02-16 18:11:33 +0800753 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800754 case PSA_IPC_CONNECT:
755 /*
756 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
757 * input status is PSA_SUCCESS. Others return values are based on the
758 * input status.
759 */
760 if (status == PSA_SUCCESS) {
761 ret = msg_handle;
762 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
763 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800764 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800765 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800766 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
767 /* Fail the client connection, indicating a transient error. */
768 ret = PSA_ERROR_CONNECTION_BUSY;
769 } else {
770 tfm_core_panic();
771 }
772 break;
773 case PSA_IPC_DISCONNECT:
774 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800775 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800776
777 /*
778 * If the message type is PSA_IPC_DISCONNECT, then the status code is
779 * ignored
780 */
781 break;
782 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800783 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800784
785#if PSA_FRAMEWORK_HAS_MM_IOVEC
786
787 /*
788 * If the unmapped function is not called for an input/output vector
789 * that has been mapped, the framework will remove the mapping.
790 */
791 int i;
792
793 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800794 if (IOVEC_IS_MAPPED(handle, i) &&
795 (!IOVEC_IS_UNMAPPED(handle, i))) {
796 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800797 /*
798 * Any output vectors that are still mapped will report that
799 * zero bytes have been written.
800 */
801 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800802 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800803 }
804 }
805 }
806
807#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800808 /* Reply to a request message. Return values are based on status */
809 ret = status;
810 /*
811 * The total number of bytes written to a single parameter must be
812 * reported to the client by updating the len member of the
813 * psa_outvec structure for the parameter before returning from
814 * psa_call().
815 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800816 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800817 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800818 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800819 }
820 } else {
821 tfm_core_panic();
822 }
823 }
824
825 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
826 /*
827 * If the source of the programmer error is a Secure Partition, the SPM
828 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
829 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800830 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800831 tfm_core_panic();
832 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800833 }
834
Mingyang Sun620c8562021-11-10 11:44:58 +0800835 /*
836 * TODO: It can be optimized further by moving critical section protection
837 * to mailbox. Also need to check implementation when secure context is
838 * involved.
839 */
840 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu995a9742022-05-18 19:28:30 +0800841 ret = backend_replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800842 CRITICAL_SECTION_LEAVE(cs_assert);
843
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800844 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
845 tfm_spm_free_conn_handle(handle);
846 } else {
847 handle->status = TFM_HANDLE_STATUS_IDLE;
848 }
849
Mingyang Sun620c8562021-11-10 11:44:58 +0800850 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800851}
852
Kevin Peng613b4172022-02-15 14:41:44 +0800853#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800854void tfm_spm_partition_psa_notify(int32_t partition_id)
855{
Ken Liu5d73c872021-08-19 19:23:17 +0800856 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
857
858 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800859}
860
861void tfm_spm_partition_psa_clear(void)
862{
Ken Liu92ede9f2021-10-20 09:35:00 +0800863 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800864 struct partition_t *partition = NULL;
865
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800866 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800867
868 /*
869 * It is a fatal error if the Secure Partition's doorbell signal is not
870 * currently asserted.
871 */
872 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
873 tfm_core_panic();
874 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800875
876 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800877 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800878 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800879}
Kevin Peng613b4172022-02-15 14:41:44 +0800880#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800881
Mingyang Sunb26b2802021-07-07 11:25:00 +0800882void tfm_spm_partition_psa_panic(void)
883{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100884#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
885 tfm_hal_system_halt();
886#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800887 /*
888 * PSA FF recommends that the SPM causes the system to restart when a secure
889 * partition panics.
890 */
891 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100892#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800893}
894
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800895/* psa_set_rhandle is only needed by connection-based services */
896#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
897
898void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
899{
Mingyang Suna09adda2022-02-16 18:11:33 +0800900 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800901
902 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800903 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800904 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800905 tfm_core_panic();
906 }
907
908 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800909 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800910 tfm_core_panic();
911 }
912
Mingyang Suna09adda2022-02-16 18:11:33 +0800913 handle->msg.rhandle = rhandle;
914 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800915}
916
917#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
918
919#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800920void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800921{
922 struct partition_t *partition;
923 struct irq_load_info_t *irq_info;
924
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800925 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800926
927 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
928 if (!irq_info) {
929 tfm_core_panic();
930 }
931
Kevin Pengd399a1f2021-09-08 15:33:14 +0800932 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800933}
934
Kevin Peng67a89fd2021-11-25 11:22:02 +0800935psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800936{
937 struct partition_t *partition;
938 struct irq_load_info_t *irq_info;
939
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800940 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800941
942 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
943 if (!irq_info) {
944 tfm_core_panic();
945 }
946
Kevin Pengd399a1f2021-09-08 15:33:14 +0800947 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800948
949 return 1;
950}
951
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800952/* This API is only used for FLIH. */
953#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800954void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
955{
Ken Liu92ede9f2021-10-20 09:35:00 +0800956 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800957 struct irq_load_info_t *irq_info;
958 struct partition_t *partition;
959
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800960 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800961
962 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
963 if (!irq_info) {
964 tfm_core_panic();
965 }
966
967 if (!irq_info->flih_func) {
968 /* This API is for FLIH IRQs only */
969 tfm_core_panic();
970 }
971
972 if ((partition->signals_asserted & irq_signal) == 0) {
973 /* The signal is not asserted */
974 tfm_core_panic();
975 }
976
Ken Liu92ede9f2021-10-20 09:35:00 +0800977 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800978 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800979 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800980}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800981#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800982
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800983/* This API is only used for SLIH. */
984#if CONFIG_TFM_SLIH_API == 1
985void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800986{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800987 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
988 struct irq_load_info_t *irq_info = NULL;
989 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800990
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800991 partition = GET_CURRENT_COMPONENT();
992
993 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
994 /* It is a fatal error if passed signal is not an interrupt signal. */
995 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800996 tfm_core_panic();
997 }
998
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800999 if (irq_info->flih_func) {
1000 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001001 tfm_core_panic();
1002 }
1003
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001004 /* It is a fatal error if passed signal is not currently asserted */
1005 if ((partition->signals_asserted & irq_signal) == 0) {
1006 tfm_core_panic();
1007 }
1008
1009 CRITICAL_SECTION_ENTER(cs_assert);
1010 partition->signals_asserted &= ~irq_signal;
1011 CRITICAL_SECTION_LEAVE(cs_assert);
1012
1013 tfm_hal_irq_clear_pending(irq_info->source);
1014 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001015}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001016#endif
1017#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001018
Shawn Shan038348e2021-09-08 17:11:04 +08001019#if PSA_FRAMEWORK_HAS_MM_IOVEC
1020
1021const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1022 uint32_t invec_idx)
1023{
Mingyang Suna09adda2022-02-16 18:11:33 +08001024 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001025 uint32_t privileged;
1026 struct partition_t *partition = NULL;
1027
1028 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001029 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001030 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001031 tfm_core_panic();
1032 }
1033
Mingyang Suna09adda2022-02-16 18:11:33 +08001034 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001035 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001036
1037 /*
1038 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1039 * Service that received the message.
1040 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001041 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001042 tfm_core_panic();
1043 }
1044
1045 /*
1046 * It is a fatal error if message handle does not refer to a request
1047 * message.
1048 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001049 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001050 tfm_core_panic();
1051 }
1052
1053 /*
1054 * It is a fatal error if invec_idx is equal to or greater than
1055 * PSA_MAX_IOVEC.
1056 */
1057 if (invec_idx >= PSA_MAX_IOVEC) {
1058 tfm_core_panic();
1059 }
1060
1061 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001062 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001063 tfm_core_panic();
1064 }
1065
1066 /*
1067 * It is a fatal error if the input vector has already been mapped using
1068 * psa_map_invec().
1069 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001070 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001071 tfm_core_panic();
1072 }
1073
1074 /*
1075 * It is a fatal error if the input vector has already been accessed
1076 * using psa_read() or psa_skip().
1077 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001078 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001079 tfm_core_panic();
1080 }
1081
1082 /*
1083 * It is a fatal error if the memory reference for the wrap input vector is
1084 * invalid or not readable.
1085 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001086 if (tfm_memory_check(handle->invec[invec_idx].base,
1087 handle->invec[invec_idx].len,
1088 false, TFM_MEMORY_ACCESS_RO,
Ken Liuad3f3e62022-03-04 22:23:52 +08001089 privileged) != PSA_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001090 tfm_core_panic();
1091 }
1092
Mingyang Suna09adda2022-02-16 18:11:33 +08001093 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001094
Mingyang Suna09adda2022-02-16 18:11:33 +08001095 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001096}
1097
1098void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1099 uint32_t invec_idx)
1100{
Mingyang Suna09adda2022-02-16 18:11:33 +08001101 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001102
1103 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001104 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001105 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001106 tfm_core_panic();
1107 }
1108
1109 /*
1110 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1111 * Service that received the message.
1112 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001113 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001114 tfm_core_panic();
1115 }
1116
1117 /*
1118 * It is a fatal error if message handle does not refer to a request
1119 * message.
1120 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001121 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001122 tfm_core_panic();
1123 }
1124
1125 /*
1126 * It is a fatal error if invec_idx is equal to or greater than
1127 * PSA_MAX_IOVEC.
1128 */
1129 if (invec_idx >= PSA_MAX_IOVEC) {
1130 tfm_core_panic();
1131 }
1132
1133 /*
1134 * It is a fatal error if The input vector has not been mapped by a call to
1135 * psa_map_invec().
1136 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001137 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001138 tfm_core_panic();
1139 }
1140
1141 /*
1142 * It is a fatal error if the input vector has already been unmapped by a
1143 * call to psa_unmap_invec().
1144 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001145 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001146 tfm_core_panic();
1147 }
1148
Mingyang Suna09adda2022-02-16 18:11:33 +08001149 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001150}
1151
1152void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1153 uint32_t outvec_idx)
1154{
Mingyang Suna09adda2022-02-16 18:11:33 +08001155 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001156 uint32_t privileged;
1157 struct partition_t *partition = NULL;
1158
1159 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001160 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001161 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001162 tfm_core_panic();
1163 }
1164
Mingyang Suna09adda2022-02-16 18:11:33 +08001165 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001166 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001167
1168 /*
1169 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1170 * Service that received the message.
1171 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001172 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001173 tfm_core_panic();
1174 }
1175
1176 /*
1177 * It is a fatal error if message handle does not refer to a request
1178 * message.
1179 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001180 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001181 tfm_core_panic();
1182 }
1183
1184 /*
1185 * It is a fatal error if outvec_idx is equal to or greater than
1186 * PSA_MAX_IOVEC.
1187 */
1188 if (outvec_idx >= PSA_MAX_IOVEC) {
1189 tfm_core_panic();
1190 }
1191
1192 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001193 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001194 tfm_core_panic();
1195 }
1196
1197 /*
1198 * It is a fatal error if the output vector has already been mapped using
1199 * psa_map_outvec().
1200 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001201 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001202 tfm_core_panic();
1203 }
1204
1205 /*
1206 * It is a fatal error if the output vector has already been accessed
1207 * using psa_write().
1208 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001209 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001210 tfm_core_panic();
1211 }
1212
1213 /*
1214 * It is a fatal error if the output vector is invalid or not read-write.
1215 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001216 if (tfm_memory_check(handle->outvec[outvec_idx].base,
1217 handle->outvec[outvec_idx].len, false,
Ken Liuad3f3e62022-03-04 22:23:52 +08001218 TFM_MEMORY_ACCESS_RW, privileged) != PSA_SUCCESS) {
Shawn Shan038348e2021-09-08 17:11:04 +08001219 tfm_core_panic();
1220 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001221 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001222
Mingyang Suna09adda2022-02-16 18:11:33 +08001223 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001224}
1225
1226void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1227 uint32_t outvec_idx, size_t len)
1228{
Mingyang Suna09adda2022-02-16 18:11:33 +08001229 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001230
1231 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001232 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001233 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001234 tfm_core_panic();
1235 }
1236
1237 /*
1238 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1239 * Service that received the message.
1240 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001241 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001242 tfm_core_panic();
1243 }
1244
1245 /*
1246 * It is a fatal error if message handle does not refer to a request
1247 * message.
1248 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001249 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001250 tfm_core_panic();
1251 }
1252
1253 /*
1254 * It is a fatal error if outvec_idx is equal to or greater than
1255 * PSA_MAX_IOVEC.
1256 */
1257 if (outvec_idx >= PSA_MAX_IOVEC) {
1258 tfm_core_panic();
1259 }
1260
1261 /*
1262 * It is a fatal error if len is greater than the output vector size.
1263 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001264 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001265 tfm_core_panic();
1266 }
1267
1268 /*
1269 * It is a fatal error if The output vector has not been mapped by a call to
1270 * psa_map_outvec().
1271 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001272 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001273 tfm_core_panic();
1274 }
1275
1276 /*
1277 * It is a fatal error if the output vector has already been unmapped by a
1278 * call to psa_unmap_outvec().
1279 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001280 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001281 tfm_core_panic();
1282 }
1283
Mingyang Suna09adda2022-02-16 18:11:33 +08001284 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001285
1286 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001287 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001288}
1289
1290#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */