blob: c0c4aac9a57a686f0727c2fc11c8ca85c7911281 [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"
Kevin Pengb42ed862022-08-08 14:44:02 +080025#include "tfm_api.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"
Summer Qin56725eb2022-05-06 15:23:40 +080029#include "tfm_hal_isolation.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 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();
Summer Qin56725eb2022-05-06 15:23:40 +0800155 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
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);
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800159 fih_int fih_rc = FIH_FAILURE;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800160
161 /* The request type must be zero or positive. */
162 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800163 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800164 }
David Hu733d8f92019-09-23 15:32:40 +0800165
Shawn Shanb222d892021-01-04 17:41:48 +0800166 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
Summer Qin22c301a2022-04-27 17:36:00 +0800167 if ((in_num > SIZE_MAX - out_num) ||
David Hu733d8f92019-09-23 15:32:40 +0800168 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800169 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800170 }
171
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800172 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
173 if (handle == PSA_NULL_HANDLE) {
174 return PSA_ERROR_PROGRAMMER_ERROR;
175 }
176
Kevin Peng385fda82021-08-18 10:41:19 +0800177 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800178
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800179 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800180 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800181 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800182
183 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800184 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800185 }
186
Mingyang Sun453ad402021-03-17 17:58:33 +0800187 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800188 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800189 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800190 }
191
Ken Liub3b2cb62021-05-22 00:39:28 +0800192 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800193
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800194 /*
195 * It is a PROGRAMMER ERROR if the caller is not authorized to access
196 * the RoT Service.
197 */
198 if (tfm_spm_check_authorization(sid, service, ns_caller)
Ken Liuad3f3e62022-03-04 22:23:52 +0800199 != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800200 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800201 }
202
Mingyang Sun453ad402021-03-17 17:58:33 +0800203 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
204
Ken Liuad3f3e62022-03-04 22:23:52 +0800205 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800206 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800207 }
208
Mingyang Sun620c8562021-11-10 11:44:58 +0800209 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800210 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800211 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800212
213 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800214 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800215 }
216
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800217 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800218 handle = tfm_spm_to_user_handle(conn_handle);
219 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800220#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800221 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800222 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
223 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800224 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800225 }
226
227 /*
228 * It is a PROGRAMMER ERROR if the connection is currently
229 * handling a request.
230 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800231 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800232 return PSA_ERROR_PROGRAMMER_ERROR;
233 }
234
Ken Liu0bed7e02022-02-10 12:38:07 +0800235 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800236
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800237 if (!service) {
238 /* FixMe: Need to implement a mechanism to resolve this failure. */
239 return PSA_ERROR_PROGRAMMER_ERROR;
240 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800241#else
242 return PSA_ERROR_PROGRAMMER_ERROR;
243#endif
David Hu733d8f92019-09-23 15:32:40 +0800244 }
245
Kevin 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 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800251 FIH_CALL(tfm_hal_memory_check, fih_rc,
252 curr_partition->boundary, (uintptr_t)inptr,
253 in_num * sizeof(psa_invec), TFM_HAL_ACCESS_READABLE);
254 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800255 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800256 }
Summer Qinba2346e2019-11-12 16:26:31 +0800257
David Hu733d8f92019-09-23 15:32:40 +0800258 /*
259 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800260 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800261 * the wrap output vector is invalid or not read-write.
262 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800263 FIH_CALL(tfm_hal_memory_check, fih_rc,
264 curr_partition->boundary, (uintptr_t)outptr,
265 out_num * sizeof(psa_outvec), TFM_HAL_ACCESS_READWRITE);
266 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800267 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800268 }
269
Summer Qinf24dbb52020-07-23 14:53:54 +0800270 spm_memset(invecs, 0, sizeof(invecs));
271 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800272
273 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800274 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
275 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800276
277 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800278 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800279 * memory reference was invalid or not readable.
280 */
281 for (i = 0; i < in_num; i++) {
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800282 FIH_CALL(tfm_hal_memory_check, fih_rc,
283 curr_partition->boundary, (uintptr_t)invecs[i].base,
284 invecs[i].len, TFM_HAL_ACCESS_READABLE);
285 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800286 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800287 }
288 }
Summer Qinba2346e2019-11-12 16:26:31 +0800289
290 /*
291 * Clients must never overlap input parameters because of the risk of a
292 * double-fetch inconsistency.
Summer Qin56725eb2022-05-06 15:23:40 +0800293 * Overflow is checked in tfm_hal_memory_check functions.
Summer Qinba2346e2019-11-12 16:26:31 +0800294 */
295 for (i = 0; i + 1 < in_num; i++) {
296 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100297 if (!((char *) invecs[j].base + invecs[j].len <=
298 (char *) invecs[i].base ||
299 (char *) invecs[j].base >=
300 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800301 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800302 }
303 }
304 }
305
David Hu733d8f92019-09-23 15:32:40 +0800306 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800307 * For client output vector, it is a PROGRAMMER ERROR if the provided
308 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800309 */
310 for (i = 0; i < out_num; i++) {
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800311 FIH_CALL(tfm_hal_memory_check, fih_rc,
312 curr_partition->boundary, (uintptr_t)outvecs[i].base,
313 outvecs[i].len, TFM_HAL_ACCESS_READWRITE);
314 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800315 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800316 }
317 }
318
Ken Liu0bed7e02022-02-10 12:38:07 +0800319 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800320 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800321
Ken Liu995a9742022-05-18 19:28:30 +0800322 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800323}
324
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800325/* Following PSA APIs are only needed by connection-based services */
326#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
327
328psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
329{
330 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800331 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800332 int32_t client_id;
333 psa_handle_t handle;
334 bool ns_caller = tfm_spm_is_ns_caller();
335 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
336
337 /*
338 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
339 * platform.
340 */
341 service = tfm_spm_get_service_by_sid(sid);
342 if (!service) {
343 return PSA_ERROR_CONNECTION_REFUSED;
344 }
345
346 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
347 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
348 return PSA_ERROR_PROGRAMMER_ERROR;
349 }
350
351 /*
352 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
353 * RoT Service.
354 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800355 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800356 return PSA_ERROR_CONNECTION_REFUSED;
357 }
358
359 /*
360 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
361 * not supported on the platform.
362 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800363 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800364 return PSA_ERROR_CONNECTION_REFUSED;
365 }
366
367 client_id = tfm_spm_get_client_id(ns_caller);
368
369 /*
370 * Create connection handle here since it is possible to return the error
371 * code to client when creation fails.
372 */
373 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800374 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800375 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800376 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800377 return PSA_ERROR_CONNECTION_BUSY;
378 }
379
Mingyang Suna09adda2022-02-16 18:11:33 +0800380 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800381 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800382 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800383 client_id, NULL, 0, NULL, 0, NULL);
384
Ken Liu995a9742022-05-18 19:28:30 +0800385 return backend_messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800386}
387
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800388psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800389{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800390 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800391 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800392 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800393 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800394
395 /* It will have no effect if called with the NULL handle */
396 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800397 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800398 }
399
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800400 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800401 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800402 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800403 }
404
Kevin Peng385fda82021-08-18 10:41:19 +0800405 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800406
David Hu733d8f92019-09-23 15:32:40 +0800407 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800408 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
409 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800410 */
Kevin Penge61e7052022-01-27 14:57:06 +0800411 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
412 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800413 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800414 }
Shawn Shanb222d892021-01-04 17:41:48 +0800415
Ken Liu0bed7e02022-02-10 12:38:07 +0800416 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800417 if (!service) {
418 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800419 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800420 }
421
Shawn Shanb222d892021-01-04 17:41:48 +0800422 /*
423 * It is a PROGRAMMER ERROR if the connection is currently handling a
424 * request.
425 */
Summer Qin630c76b2020-05-20 10:32:58 +0800426 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800427 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800428 }
429
David Hu733d8f92019-09-23 15:32:40 +0800430 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800431 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
432 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800433
Ken Liu995a9742022-05-18 19:28:30 +0800434 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800435}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800436
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800437#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
438
Mingyang Suneeca4652021-07-15 15:19:16 +0800439/* PSA Partition API function body */
440
Kevin Pengdef92de2021-11-10 16:14:48 +0800441#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
442 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800443psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
444 uint32_t timeout)
445{
446 struct partition_t *partition = NULL;
447
448 /*
449 * Timeout[30:0] are reserved for future use.
450 * SPM must ignore the value of RES.
451 */
452 timeout &= PSA_TIMEOUT_MASK;
453
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800454 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800455
456 /*
Ruchika Guptad1834172022-06-15 12:03:08 +0530457 * signals_allowed can be 0 for TF-M internal partitions for special usages.
458 * Regular Secure Partitions should have at least one signal.
459 * This is gauranteed by the manifest tool.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800460 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
461 * signals.
462 */
Ruchika Guptad1834172022-06-15 12:03:08 +0530463 if ((partition->signals_allowed) &&
464 (partition->signals_allowed & signal_mask) == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800465 tfm_core_panic();
466 }
467
468 /*
Ken Liu995a9742022-05-18 19:28:30 +0800469 * backend_wake_up() blocks the caller thread if no signals are
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800470 * available. In this case, the return value of this function is temporary
471 * set into runtime context. After new signal(s) are available, the return
472 * value is updated with the available signal(s) and blocked thread gets
473 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800474 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800475 if (timeout == PSA_BLOCK) {
Ken Liu995a9742022-05-18 19:28:30 +0800476 return backend_wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800477 }
478
479 return partition->signals_asserted & signal_mask;
480}
Kevin Pengdef92de2021-11-10 16:14:48 +0800481#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800482
Kevin Pengdef92de2021-11-10 16:14:48 +0800483#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800484psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
485{
Mingyang Suna09adda2022-02-16 18:11:33 +0800486 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800487 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800488 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800489
490 /*
491 * Only one message could be retrieved every time for psa_get(). It is a
492 * fatal error if the input signal has more than a signal bit set.
493 */
494 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
495 tfm_core_panic();
496 }
497
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800498 partition = GET_CURRENT_COMPONENT();
499
Mingyang Sunb26b2802021-07-07 11:25:00 +0800500 /*
501 * Write the message to the service buffer. It is a fatal error if the
502 * input msg pointer is not a valid memory reference or not read-write.
503 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800504 FIH_CALL(tfm_hal_memory_check, fih_rc,
505 partition->boundary, (uintptr_t)msg,
506 sizeof(psa_msg_t), TFM_HAL_ACCESS_READWRITE);
507 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800508 tfm_core_panic();
509 }
510
511 /*
512 * It is a fatal error if the caller call psa_get() when no message has
513 * been set. The caller must call this function after an RoT Service signal
514 * is returned by psa_wait().
515 */
516 if (partition->signals_asserted == 0) {
517 tfm_core_panic();
518 }
519
520 /*
521 * It is a fatal error if the RoT Service signal is not currently asserted.
522 */
523 if ((partition->signals_asserted & signal) == 0) {
524 tfm_core_panic();
525 }
526
527 /*
528 * Get message by signal from partition. It is a fatal error if getting
529 * failed, which means the input signal is not correspond to an RoT service.
530 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800531 handle = spm_get_handle_by_signal(partition, signal);
532 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800533 return PSA_ERROR_DOES_NOT_EXIST;
534 }
535
Mingyang Suna09adda2022-02-16 18:11:33 +0800536 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800537
538 return PSA_SUCCESS;
539}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800540#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800541
Mingyang Sunb26b2802021-07-07 11:25:00 +0800542size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
543 void *buffer, size_t num_bytes)
544{
545 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800546 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800547 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800548 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800549
550 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800551 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800552 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800553 tfm_core_panic();
554 }
555
Mingyang Sunb26b2802021-07-07 11:25:00 +0800556 /*
557 * It is a fatal error if message handle does not refer to a request
558 * message
559 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800560 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800561 tfm_core_panic();
562 }
563
564 /*
565 * It is a fatal error if invec_idx is equal to or greater than
566 * PSA_MAX_IOVEC
567 */
568 if (invec_idx >= PSA_MAX_IOVEC) {
569 tfm_core_panic();
570 }
571
Shawn Shan038348e2021-09-08 17:11:04 +0800572#if PSA_FRAMEWORK_HAS_MM_IOVEC
573 /*
574 * It is a fatal error if the input vector has already been mapped using
575 * psa_map_invec().
576 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800577 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800578 tfm_core_panic();
579 }
580
Mingyang Suna09adda2022-02-16 18:11:33 +0800581 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800582#endif
583
Kevin Peng016b0e42022-04-15 11:28:48 +0800584 /* There was no remaining data in this input vector */
585 if (handle->msg.in_size[invec_idx] == 0) {
586 return 0;
587 }
588
Mingyang Sunb26b2802021-07-07 11:25:00 +0800589 /*
590 * Copy the client data to the service buffer. It is a fatal error
591 * if the memory reference for buffer is invalid or not read-write.
592 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800593 FIH_CALL(tfm_hal_memory_check, fih_rc,
594 curr_partition->boundary, (uintptr_t)buffer,
595 num_bytes, TFM_HAL_ACCESS_READWRITE);
596 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800597 tfm_core_panic();
598 }
599
Mingyang Suna09adda2022-02-16 18:11:33 +0800600 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
601 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800602
Mingyang Suna09adda2022-02-16 18:11:33 +0800603 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800604
605 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800606 handle->invec[invec_idx].base =
607 (char *)handle->invec[invec_idx].base + bytes;
608 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800609
610 return bytes;
611}
612
613size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
614 size_t num_bytes)
615{
Mingyang Suna09adda2022-02-16 18:11:33 +0800616 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800617
618 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800619 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800620 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800621 tfm_core_panic();
622 }
623
624 /*
625 * It is a fatal error if message handle does not refer to a request
626 * message
627 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800628 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800629 tfm_core_panic();
630 }
631
632 /*
633 * It is a fatal error if invec_idx is equal to or greater than
634 * PSA_MAX_IOVEC
635 */
636 if (invec_idx >= PSA_MAX_IOVEC) {
637 tfm_core_panic();
638 }
639
Shawn Shan038348e2021-09-08 17:11:04 +0800640#if PSA_FRAMEWORK_HAS_MM_IOVEC
641 /*
642 * It is a fatal error if the input vector has already been mapped using
643 * psa_map_invec().
644 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800645 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800646 tfm_core_panic();
647 }
648
Mingyang Suna09adda2022-02-16 18:11:33 +0800649 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800650#endif
651
Kevin Peng016b0e42022-04-15 11:28:48 +0800652 /* There was no remaining data in this input vector */
653 if (handle->msg.in_size[invec_idx] == 0) {
654 return 0;
655 }
656
Mingyang Sunb26b2802021-07-07 11:25:00 +0800657 /*
658 * If num_bytes is greater than the remaining size of the input vector then
659 * the remaining size of the input vector is used.
660 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800661 if (num_bytes > handle->msg.in_size[invec_idx]) {
662 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800663 }
664
665 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800666 handle->invec[invec_idx].base =
667 (char *)handle->invec[invec_idx].base + num_bytes;
668 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800669
670 return num_bytes;
671}
672
673void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
674 const void *buffer, size_t num_bytes)
675{
Mingyang Suna09adda2022-02-16 18:11:33 +0800676 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800677 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800678 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800679
680 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800681 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800682 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800683 tfm_core_panic();
684 }
685
Mingyang Sunb26b2802021-07-07 11:25:00 +0800686 /*
687 * It is a fatal error if message handle does not refer to a request
688 * message
689 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800690 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800691 tfm_core_panic();
692 }
693
694 /*
695 * It is a fatal error if outvec_idx is equal to or greater than
696 * PSA_MAX_IOVEC
697 */
698 if (outvec_idx >= PSA_MAX_IOVEC) {
699 tfm_core_panic();
700 }
701
702 /*
703 * It is a fatal error if the call attempts to write data past the end of
704 * the client output vector
705 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800706 if (num_bytes > handle->msg.out_size[outvec_idx] -
707 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800708 tfm_core_panic();
709 }
710
Shawn Shan038348e2021-09-08 17:11:04 +0800711#if PSA_FRAMEWORK_HAS_MM_IOVEC
712 /*
713 * It is a fatal error if the output vector has already been mapped using
714 * psa_map_outvec().
715 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800716 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800717 tfm_core_panic();
718 }
719
Mingyang Suna09adda2022-02-16 18:11:33 +0800720 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800721#endif
722
Mingyang Sunb26b2802021-07-07 11:25:00 +0800723 /*
724 * Copy the service buffer to client outvecs. It is a fatal error
725 * if the memory reference for buffer is invalid or not readable.
726 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800727 FIH_CALL(tfm_hal_memory_check, fih_rc,
728 curr_partition->boundary, (uintptr_t)buffer,
729 num_bytes, TFM_HAL_ACCESS_READABLE);
730 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800731 tfm_core_panic();
732 }
733
Mingyang Suna09adda2022-02-16 18:11:33 +0800734 spm_memcpy((char *)handle->outvec[outvec_idx].base +
735 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800736
737 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800738 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800739}
740
Ken Liuf8c7e532022-02-10 15:03:04 +0800741psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
742 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800743{
Ken Liu0bed7e02022-02-10 12:38:07 +0800744 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800745 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800746 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800747 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800748
749 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800750 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800751 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800752 tfm_core_panic();
753 }
754
755 /*
756 * RoT Service information is needed in this function, stored it in message
757 * body structure. Only two parameters are passed in this function: handle
758 * and status, so it is useful and simply to do like this.
759 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800760 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800761 if (!service) {
762 tfm_core_panic();
763 }
764
Mingyang Suna09adda2022-02-16 18:11:33 +0800765 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800766 case PSA_IPC_CONNECT:
767 /*
768 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
769 * input status is PSA_SUCCESS. Others return values are based on the
770 * input status.
771 */
772 if (status == PSA_SUCCESS) {
773 ret = msg_handle;
774 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
775 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800776 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800777 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800778 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
779 /* Fail the client connection, indicating a transient error. */
780 ret = PSA_ERROR_CONNECTION_BUSY;
781 } else {
782 tfm_core_panic();
783 }
784 break;
785 case PSA_IPC_DISCONNECT:
786 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800787 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800788
789 /*
790 * If the message type is PSA_IPC_DISCONNECT, then the status code is
791 * ignored
792 */
793 break;
794 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800795 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800796
797#if PSA_FRAMEWORK_HAS_MM_IOVEC
798
799 /*
800 * If the unmapped function is not called for an input/output vector
801 * that has been mapped, the framework will remove the mapping.
802 */
803 int i;
804
805 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800806 if (IOVEC_IS_MAPPED(handle, i) &&
807 (!IOVEC_IS_UNMAPPED(handle, i))) {
808 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800809 /*
810 * Any output vectors that are still mapped will report that
811 * zero bytes have been written.
812 */
813 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800814 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800815 }
816 }
817 }
818
819#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800820 /* Reply to a request message. Return values are based on status */
821 ret = status;
822 /*
823 * The total number of bytes written to a single parameter must be
824 * reported to the client by updating the len member of the
825 * psa_outvec structure for the parameter before returning from
826 * psa_call().
827 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800828 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800829 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800830 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800831 }
832 } else {
833 tfm_core_panic();
834 }
835 }
836
837 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
838 /*
839 * If the source of the programmer error is a Secure Partition, the SPM
840 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
841 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800842 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800843 tfm_core_panic();
844 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800845 }
846
Mingyang Sun620c8562021-11-10 11:44:58 +0800847 /*
848 * TODO: It can be optimized further by moving critical section protection
849 * to mailbox. Also need to check implementation when secure context is
850 * involved.
851 */
852 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu995a9742022-05-18 19:28:30 +0800853 ret = backend_replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800854 CRITICAL_SECTION_LEAVE(cs_assert);
855
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800856 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
857 tfm_spm_free_conn_handle(handle);
858 } else {
859 handle->status = TFM_HANDLE_STATUS_IDLE;
860 }
861
Mingyang Sun620c8562021-11-10 11:44:58 +0800862 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800863}
864
Kevin Peng613b4172022-02-15 14:41:44 +0800865#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800866void tfm_spm_partition_psa_notify(int32_t partition_id)
867{
Ken Liu5d73c872021-08-19 19:23:17 +0800868 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
869
870 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800871}
872
873void tfm_spm_partition_psa_clear(void)
874{
Ken Liu92ede9f2021-10-20 09:35:00 +0800875 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800876 struct partition_t *partition = NULL;
877
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800878 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800879
880 /*
881 * It is a fatal error if the Secure Partition's doorbell signal is not
882 * currently asserted.
883 */
884 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
885 tfm_core_panic();
886 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800887
888 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800889 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800890 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800891}
Kevin Peng613b4172022-02-15 14:41:44 +0800892#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800893
Mingyang Sunb26b2802021-07-07 11:25:00 +0800894void tfm_spm_partition_psa_panic(void)
895{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100896#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
897 tfm_hal_system_halt();
898#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800899 /*
900 * PSA FF recommends that the SPM causes the system to restart when a secure
901 * partition panics.
902 */
903 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100904#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800905}
906
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800907/* psa_set_rhandle is only needed by connection-based services */
908#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
909
910void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
911{
Mingyang Suna09adda2022-02-16 18:11:33 +0800912 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800913
914 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800915 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800916 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800917 tfm_core_panic();
918 }
919
920 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800921 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800922 tfm_core_panic();
923 }
924
Mingyang Suna09adda2022-02-16 18:11:33 +0800925 handle->msg.rhandle = rhandle;
926 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800927}
928
929#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
930
931#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800932void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800933{
934 struct partition_t *partition;
935 struct irq_load_info_t *irq_info;
936
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800937 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800938
939 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
940 if (!irq_info) {
941 tfm_core_panic();
942 }
943
Kevin Pengd399a1f2021-09-08 15:33:14 +0800944 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800945}
946
Kevin Peng67a89fd2021-11-25 11:22:02 +0800947psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800948{
949 struct partition_t *partition;
950 struct irq_load_info_t *irq_info;
951
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800952 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800953
954 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
955 if (!irq_info) {
956 tfm_core_panic();
957 }
958
Kevin Pengd399a1f2021-09-08 15:33:14 +0800959 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800960
961 return 1;
962}
963
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800964/* This API is only used for FLIH. */
965#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800966void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
967{
Ken Liu92ede9f2021-10-20 09:35:00 +0800968 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800969 struct irq_load_info_t *irq_info;
970 struct partition_t *partition;
971
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800972 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800973
974 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
975 if (!irq_info) {
976 tfm_core_panic();
977 }
978
979 if (!irq_info->flih_func) {
980 /* This API is for FLIH IRQs only */
981 tfm_core_panic();
982 }
983
984 if ((partition->signals_asserted & irq_signal) == 0) {
985 /* The signal is not asserted */
986 tfm_core_panic();
987 }
988
Ken Liu92ede9f2021-10-20 09:35:00 +0800989 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800990 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800991 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800992}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800993#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800994
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800995/* This API is only used for SLIH. */
996#if CONFIG_TFM_SLIH_API == 1
997void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800998{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800999 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
1000 struct irq_load_info_t *irq_info = NULL;
1001 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001002
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001003 partition = GET_CURRENT_COMPONENT();
1004
1005 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
1006 /* It is a fatal error if passed signal is not an interrupt signal. */
1007 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001008 tfm_core_panic();
1009 }
1010
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001011 if (irq_info->flih_func) {
1012 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001013 tfm_core_panic();
1014 }
1015
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001016 /* It is a fatal error if passed signal is not currently asserted */
1017 if ((partition->signals_asserted & irq_signal) == 0) {
1018 tfm_core_panic();
1019 }
1020
1021 CRITICAL_SECTION_ENTER(cs_assert);
1022 partition->signals_asserted &= ~irq_signal;
1023 CRITICAL_SECTION_LEAVE(cs_assert);
1024
1025 tfm_hal_irq_clear_pending(irq_info->source);
1026 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001027}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001028#endif
1029#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001030
Shawn Shan038348e2021-09-08 17:11:04 +08001031#if PSA_FRAMEWORK_HAS_MM_IOVEC
1032
1033const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1034 uint32_t invec_idx)
1035{
Mingyang Suna09adda2022-02-16 18:11:33 +08001036 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001037 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001038 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +08001039
1040 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001041 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001042 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001043 tfm_core_panic();
1044 }
1045
Mingyang Suna09adda2022-02-16 18:11:33 +08001046 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +08001047
1048 /*
1049 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1050 * Service that received the message.
1051 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001052 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001053 tfm_core_panic();
1054 }
1055
1056 /*
1057 * It is a fatal error if message handle does not refer to a request
1058 * message.
1059 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001060 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001061 tfm_core_panic();
1062 }
1063
1064 /*
1065 * It is a fatal error if invec_idx is equal to or greater than
1066 * PSA_MAX_IOVEC.
1067 */
1068 if (invec_idx >= PSA_MAX_IOVEC) {
1069 tfm_core_panic();
1070 }
1071
1072 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001073 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001074 tfm_core_panic();
1075 }
1076
1077 /*
1078 * It is a fatal error if the input vector has already been mapped using
1079 * psa_map_invec().
1080 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001081 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001082 tfm_core_panic();
1083 }
1084
1085 /*
1086 * It is a fatal error if the input vector has already been accessed
1087 * using psa_read() or psa_skip().
1088 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001089 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001090 tfm_core_panic();
1091 }
1092
1093 /*
1094 * It is a fatal error if the memory reference for the wrap input vector is
1095 * invalid or not readable.
1096 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001097 FIH_CALL(tfm_hal_memory_check, fih_rc,
1098 partition->boundary, (uintptr_t)handle->invec[invec_idx].base,
1099 handle->invec[invec_idx].len, TFM_HAL_ACCESS_READABLE);
1100 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001101 tfm_core_panic();
1102 }
1103
Mingyang Suna09adda2022-02-16 18:11:33 +08001104 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001105
Mingyang Suna09adda2022-02-16 18:11:33 +08001106 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001107}
1108
1109void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1110 uint32_t invec_idx)
1111{
Mingyang Suna09adda2022-02-16 18:11:33 +08001112 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001113
1114 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001115 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001116 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001117 tfm_core_panic();
1118 }
1119
1120 /*
1121 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1122 * Service that received the message.
1123 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001124 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001125 tfm_core_panic();
1126 }
1127
1128 /*
1129 * It is a fatal error if message handle does not refer to a request
1130 * message.
1131 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001132 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001133 tfm_core_panic();
1134 }
1135
1136 /*
1137 * It is a fatal error if invec_idx is equal to or greater than
1138 * PSA_MAX_IOVEC.
1139 */
1140 if (invec_idx >= PSA_MAX_IOVEC) {
1141 tfm_core_panic();
1142 }
1143
1144 /*
1145 * It is a fatal error if The input vector has not been mapped by a call to
1146 * psa_map_invec().
1147 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001148 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001149 tfm_core_panic();
1150 }
1151
1152 /*
1153 * It is a fatal error if the input vector has already been unmapped by a
1154 * call to psa_unmap_invec().
1155 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001156 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001157 tfm_core_panic();
1158 }
1159
Mingyang Suna09adda2022-02-16 18:11:33 +08001160 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001161}
1162
1163void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1164 uint32_t outvec_idx)
1165{
Mingyang Suna09adda2022-02-16 18:11:33 +08001166 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001167 uint32_t privileged;
1168 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001169 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +08001170
1171 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001172 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001173 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001174 tfm_core_panic();
1175 }
1176
Mingyang Suna09adda2022-02-16 18:11:33 +08001177 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001178 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001179
1180 /*
1181 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1182 * Service that received the message.
1183 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001184 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001185 tfm_core_panic();
1186 }
1187
1188 /*
1189 * It is a fatal error if message handle does not refer to a request
1190 * message.
1191 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001192 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001193 tfm_core_panic();
1194 }
1195
1196 /*
1197 * It is a fatal error if outvec_idx is equal to or greater than
1198 * PSA_MAX_IOVEC.
1199 */
1200 if (outvec_idx >= PSA_MAX_IOVEC) {
1201 tfm_core_panic();
1202 }
1203
1204 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001205 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001206 tfm_core_panic();
1207 }
1208
1209 /*
1210 * It is a fatal error if the output vector has already been mapped using
1211 * psa_map_outvec().
1212 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001213 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001214 tfm_core_panic();
1215 }
1216
1217 /*
1218 * It is a fatal error if the output vector has already been accessed
1219 * using psa_write().
1220 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001221 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001222 tfm_core_panic();
1223 }
1224
1225 /*
1226 * It is a fatal error if the output vector is invalid or not read-write.
1227 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001228 FIH_CALL(tfm_hal_memory_check, fih_rc,
1229 partition->boundary, (uintptr_t)handle->outvec[outvec_idx].base,
1230 handle->outvec[outvec_idx].len, TFM_HAL_ACCESS_READWRITE);
1231 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001232 tfm_core_panic();
1233 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001234 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001235
Mingyang Suna09adda2022-02-16 18:11:33 +08001236 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001237}
1238
1239void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1240 uint32_t outvec_idx, size_t len)
1241{
Mingyang Suna09adda2022-02-16 18:11:33 +08001242 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001243
1244 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001245 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001246 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001247 tfm_core_panic();
1248 }
1249
1250 /*
1251 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1252 * Service that received the message.
1253 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001254 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001255 tfm_core_panic();
1256 }
1257
1258 /*
1259 * It is a fatal error if message handle does not refer to a request
1260 * message.
1261 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001262 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001263 tfm_core_panic();
1264 }
1265
1266 /*
1267 * It is a fatal error if outvec_idx is equal to or greater than
1268 * PSA_MAX_IOVEC.
1269 */
1270 if (outvec_idx >= PSA_MAX_IOVEC) {
1271 tfm_core_panic();
1272 }
1273
1274 /*
1275 * It is a fatal error if len is greater than the output vector size.
1276 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001277 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001278 tfm_core_panic();
1279 }
1280
1281 /*
1282 * It is a fatal error if The output vector has not been mapped by a call to
1283 * psa_map_outvec().
1284 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001285 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001286 tfm_core_panic();
1287 }
1288
1289 /*
1290 * It is a fatal error if the output vector has already been unmapped by a
1291 * call to psa_unmap_outvec().
1292 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001293 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001294 tfm_core_panic();
1295 }
1296
Mingyang Suna09adda2022-02-16 18:11:33 +08001297 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001298
1299 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001300 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001301}
1302
1303#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */