blob: 6b60e53e665b592dacd2451f85a3db33b1a8fd5b [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.
Chris Brand10a2acb2022-10-18 17:12:27 -07003 * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon
4 * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5 * reserved.
David Hu733d8f92019-09-23 15:32:40 +08006 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
Mingyang Suneeca4652021-07-15 15:19:16 +080011#include <stdint.h>
Mingyang Sunb26b2802021-07-07 11:25:00 +080012#include "bitops.h"
Mingyang Sun4609ac72022-02-08 18:56:35 +080013#include "config_impl.h"
Ken Liu92ede9f2021-10-20 09:35:00 +080014#include "critical_section.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080015#include "psa/lifecycle.h"
David Hu733d8f92019-09-23 15:32:40 +080016#include "psa/service.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080017#include "interrupt.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080018#include "spm_ipc.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080019#include "tfm_arch.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080020#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080021#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080022#include "load/interrupt_defs.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080023#include "ffm/psa_api.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080024#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080025#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080026#include "ffm/psa_api.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080027#include "tfm_rpc.h"
Kevin Pengb42ed862022-08-08 14:44:02 +080028#include "tfm_api.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080029#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080030#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080031#include "tfm_psa_call_pack.h"
Summer Qin56725eb2022-05-06 15:23:40 +080032#include "tfm_hal_isolation.h"
David Hu733d8f92019-09-23 15:32:40 +080033
Ken Liub3b2cb62021-05-22 00:39:28 +080034#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080035extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080036
Shawn Shan038348e2021-09-08 17:11:04 +080037#if PSA_FRAMEWORK_HAS_MM_IOVEC
38
39/*
40 * The MM-IOVEC status
41 * The max total number of invec and outvec is 8.
42 * Each invec/outvec takes 4 bit, 32 bits in total.
43 *
44 * The encoding format of the MM-IOVEC status:
45 *--------------------------------------------------------------
46 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
47 *--------------------------------------------------------------
48 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
49 *--------------------------------------------------------------
50 *
51 * Take invec[0] as an example:
52 *
53 * bit 0: whether invec[0] has been mapped.
54 * bit 1: whether invec[0] has been unmapped.
55 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
56 * psa_write().
57 * bit 3: reserved for invec[0].
58 */
59
60#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
61#define OUTVEC_IDX_BASE 4 /*
62 * Base index of outvec.
63 * There are four invecs in front of
64 * outvec.
65 */
66#define INVEC_IDX_BASE 0 /* Base index of invec. */
67
68#define IOVEC_MAPPED_BIT (1U << 0)
69#define IOVEC_UNMAPPED_BIT (1U << 1)
70#define IOVEC_ACCESSED_BIT (1U << 2)
71
Mingyang Suna09adda2022-02-16 18:11:33 +080072#define IOVEC_IS_MAPPED(handle, iovec_idx) \
73 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080074 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080075#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
76 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080077 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080078#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
79 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080080 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080081#define SET_IOVEC_MAPPED(handle, iovec_idx) \
82 (((handle)->iovec_status) |= (IOVEC_MAPPED_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_UNMAPPED(handle, iovec_idx) \
85 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080086 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080087#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
88 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080089 ((iovec_idx) * IOVEC_STATUS_BITS)))
90
91#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
92
Xinyu Zhangb287ef82021-11-03 18:38:50 +080093void spm_handle_programmer_errors(psa_status_t status)
94{
Summer Qind9d497b2022-04-14 14:39:26 +080095 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
96 status == PSA_ERROR_CONNECTION_REFUSED) {
97 if (!tfm_spm_is_ns_caller()) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +080098 tfm_core_panic();
Summer Qind9d497b2022-04-14 14:39:26 +080099 }
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800100 }
101}
102
Mingyang Suneeca4652021-07-15 15:19:16 +0800103uint32_t tfm_spm_get_lifecycle_state(void)
104{
105 /*
106 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
107 * implemented in the future.
108 */
109 return PSA_LIFECYCLE_UNKNOWN;
110}
111
112/* PSA Client API function body */
113
Mingyang Sund44522a2020-01-16 16:48:37 +0800114uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800115{
116 return PSA_FRAMEWORK_VERSION;
117}
118
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800119uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800120{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800121 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800122 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800123
124 /*
125 * It should return PSA_VERSION_NONE if the RoT Service is not
126 * implemented.
127 */
128 service = tfm_spm_get_service_by_sid(sid);
129 if (!service) {
130 return PSA_VERSION_NONE;
131 }
132
133 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800134 * It should return PSA_VERSION_NONE if the caller is not authorized
135 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800136 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800137 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800138 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800139 }
140
Ken Liuacd2a572021-05-12 16:19:04 +0800141 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800142}
143
Mingyang Suneeca4652021-07-15 15:19:16 +0800144psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
145 uint32_t ctrl_param,
146 const psa_invec *inptr,
147 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800148{
149 psa_invec invecs[PSA_MAX_IOVEC];
150 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800151 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800152 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800153 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800154 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800155 uint32_t sid, version, index;
Mingyang Sun620c8562021-11-10 11:44:58 +0800156 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800157 bool ns_caller = tfm_spm_is_ns_caller();
Summer Qin56725eb2022-05-06 15:23:40 +0800158 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Mingyang Suneeca4652021-07-15 15:19:16 +0800159 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
160 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
161 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800162 fih_int fih_rc = FIH_FAILURE;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800163
164 /* The request type must be zero or positive. */
165 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800166 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800167 }
David Hu733d8f92019-09-23 15:32:40 +0800168
Shawn Shanb222d892021-01-04 17:41:48 +0800169 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
Summer Qin22c301a2022-04-27 17:36:00 +0800170 if ((in_num > SIZE_MAX - out_num) ||
David Hu733d8f92019-09-23 15:32:40 +0800171 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800172 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800173 }
174
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800175 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
176 if (handle == PSA_NULL_HANDLE) {
177 return PSA_ERROR_PROGRAMMER_ERROR;
178 }
179
Kevin Peng385fda82021-08-18 10:41:19 +0800180 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800181
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800182 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800183 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800184 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800185
186 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800187 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800188 }
189
Mingyang Sun453ad402021-03-17 17:58:33 +0800190 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800191 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800192 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800193 }
194
Ken Liub3b2cb62021-05-22 00:39:28 +0800195 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800196
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800197 /*
198 * It is a PROGRAMMER ERROR if the caller is not authorized to access
199 * the RoT Service.
200 */
201 if (tfm_spm_check_authorization(sid, service, ns_caller)
Ken Liuad3f3e62022-03-04 22:23:52 +0800202 != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800203 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800204 }
205
Mingyang Sun453ad402021-03-17 17:58:33 +0800206 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
207
Ken Liuad3f3e62022-03-04 22:23:52 +0800208 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800209 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800210 }
211
Mingyang Sun620c8562021-11-10 11:44:58 +0800212 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800213 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800214 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800215
216 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800217 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800218 }
219
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800220 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800221 handle = tfm_spm_to_user_handle(conn_handle);
222 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800223#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800224 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800225 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
226 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800227 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800228 }
229
230 /*
231 * It is a PROGRAMMER ERROR if the connection is currently
232 * handling a request.
233 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800234 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800235 return PSA_ERROR_PROGRAMMER_ERROR;
236 }
237
Ken Liu0bed7e02022-02-10 12:38:07 +0800238 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800239
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800240 if (!service) {
241 /* FixMe: Need to implement a mechanism to resolve this failure. */
242 return PSA_ERROR_PROGRAMMER_ERROR;
243 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800244#else
245 return PSA_ERROR_PROGRAMMER_ERROR;
246#endif
David Hu733d8f92019-09-23 15:32:40 +0800247 }
248
Kevin Pengedb8ee42021-03-09 16:50:11 +0800249 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800250 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800251 * if the memory reference for the wrap input vector is invalid or not
252 * readable.
253 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800254 FIH_CALL(tfm_hal_memory_check, fih_rc,
255 curr_partition->boundary, (uintptr_t)inptr,
256 in_num * sizeof(psa_invec), TFM_HAL_ACCESS_READABLE);
257 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800258 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800259 }
Summer Qinba2346e2019-11-12 16:26:31 +0800260
David Hu733d8f92019-09-23 15:32:40 +0800261 /*
262 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800263 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800264 * the wrap output vector is invalid or not read-write.
265 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800266 FIH_CALL(tfm_hal_memory_check, fih_rc,
267 curr_partition->boundary, (uintptr_t)outptr,
268 out_num * sizeof(psa_outvec), TFM_HAL_ACCESS_READWRITE);
269 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800270 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800271 }
272
Summer Qinf24dbb52020-07-23 14:53:54 +0800273 spm_memset(invecs, 0, sizeof(invecs));
274 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800275
276 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800277 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
278 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800279
280 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800281 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800282 * memory reference was invalid or not readable.
283 */
284 for (i = 0; i < in_num; i++) {
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800285 FIH_CALL(tfm_hal_memory_check, fih_rc,
286 curr_partition->boundary, (uintptr_t)invecs[i].base,
287 invecs[i].len, TFM_HAL_ACCESS_READABLE);
288 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800289 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800290 }
291 }
Summer Qinba2346e2019-11-12 16:26:31 +0800292
293 /*
294 * Clients must never overlap input parameters because of the risk of a
295 * double-fetch inconsistency.
Summer Qin56725eb2022-05-06 15:23:40 +0800296 * Overflow is checked in tfm_hal_memory_check functions.
Summer Qinba2346e2019-11-12 16:26:31 +0800297 */
298 for (i = 0; i + 1 < in_num; i++) {
299 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100300 if (!((char *) invecs[j].base + invecs[j].len <=
301 (char *) invecs[i].base ||
302 (char *) invecs[j].base >=
303 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800304 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800305 }
306 }
307 }
308
David Hu733d8f92019-09-23 15:32:40 +0800309 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800310 * For client output vector, it is a PROGRAMMER ERROR if the provided
311 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800312 */
313 for (i = 0; i < out_num; i++) {
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800314 FIH_CALL(tfm_hal_memory_check, fih_rc,
315 curr_partition->boundary, (uintptr_t)outvecs[i].base,
316 outvecs[i].len, TFM_HAL_ACCESS_READWRITE);
317 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800318 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800319 }
320 }
321
Ken Liu0bed7e02022-02-10 12:38:07 +0800322 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800323 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800324
Ken Liu995a9742022-05-18 19:28:30 +0800325 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800326}
327
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800328/* Following PSA APIs are only needed by connection-based services */
329#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
330
331psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
332{
333 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800334 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800335 int32_t client_id;
336 psa_handle_t handle;
337 bool ns_caller = tfm_spm_is_ns_caller();
338 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
339
340 /*
341 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
342 * platform.
343 */
344 service = tfm_spm_get_service_by_sid(sid);
345 if (!service) {
346 return PSA_ERROR_CONNECTION_REFUSED;
347 }
348
349 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
350 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
351 return PSA_ERROR_PROGRAMMER_ERROR;
352 }
353
354 /*
355 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
356 * RoT Service.
357 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800358 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800359 return PSA_ERROR_CONNECTION_REFUSED;
360 }
361
362 /*
363 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
364 * not supported on the platform.
365 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800366 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800367 return PSA_ERROR_CONNECTION_REFUSED;
368 }
369
370 client_id = tfm_spm_get_client_id(ns_caller);
371
372 /*
373 * Create connection handle here since it is possible to return the error
374 * code to client when creation fails.
375 */
376 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800377 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800378 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800379 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800380 return PSA_ERROR_CONNECTION_BUSY;
381 }
382
Mingyang Suna09adda2022-02-16 18:11:33 +0800383 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800384 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800385 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800386 client_id, NULL, 0, NULL, 0, NULL);
387
Ken Liu995a9742022-05-18 19:28:30 +0800388 return backend_messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800389}
390
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800391psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800392{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800393 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800394 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800395 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800396 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800397
398 /* It will have no effect if called with the NULL handle */
399 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800400 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800401 }
402
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800403 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800404 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800405 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800406 }
407
Kevin Peng385fda82021-08-18 10:41:19 +0800408 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800409
David Hu733d8f92019-09-23 15:32:40 +0800410 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800411 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
412 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800413 */
Kevin Penge61e7052022-01-27 14:57:06 +0800414 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
415 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800416 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800417 }
Shawn Shanb222d892021-01-04 17:41:48 +0800418
Ken Liu0bed7e02022-02-10 12:38:07 +0800419 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800420 if (!service) {
421 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800422 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800423 }
424
Shawn Shanb222d892021-01-04 17:41:48 +0800425 /*
426 * It is a PROGRAMMER ERROR if the connection is currently handling a
427 * request.
428 */
Summer Qin630c76b2020-05-20 10:32:58 +0800429 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800430 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800431 }
432
David Hu733d8f92019-09-23 15:32:40 +0800433 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800434 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
435 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800436
Ken Liu995a9742022-05-18 19:28:30 +0800437 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800438}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800439
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800440#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
441
Mingyang Suneeca4652021-07-15 15:19:16 +0800442/* PSA Partition API function body */
443
Kevin Pengdef92de2021-11-10 16:14:48 +0800444#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
445 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800446psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
447 uint32_t timeout)
448{
449 struct partition_t *partition = NULL;
450
451 /*
452 * Timeout[30:0] are reserved for future use.
453 * SPM must ignore the value of RES.
454 */
455 timeout &= PSA_TIMEOUT_MASK;
456
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800457 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800458
459 /*
Ruchika Guptad1834172022-06-15 12:03:08 +0530460 * signals_allowed can be 0 for TF-M internal partitions for special usages.
461 * Regular Secure Partitions should have at least one signal.
462 * This is gauranteed by the manifest tool.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800463 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
464 * signals.
465 */
Ruchika Guptad1834172022-06-15 12:03:08 +0530466 if ((partition->signals_allowed) &&
467 (partition->signals_allowed & signal_mask) == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800468 tfm_core_panic();
469 }
470
471 /*
Ken Liu995a9742022-05-18 19:28:30 +0800472 * backend_wake_up() blocks the caller thread if no signals are
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800473 * available. In this case, the return value of this function is temporary
474 * set into runtime context. After new signal(s) are available, the return
475 * value is updated with the available signal(s) and blocked thread gets
476 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800477 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800478 if (timeout == PSA_BLOCK) {
Ken Liu995a9742022-05-18 19:28:30 +0800479 return backend_wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800480 }
481
482 return partition->signals_asserted & signal_mask;
483}
Kevin Pengdef92de2021-11-10 16:14:48 +0800484#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800485
Kevin Pengdef92de2021-11-10 16:14:48 +0800486#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800487psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
488{
Mingyang Suna09adda2022-02-16 18:11:33 +0800489 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800490 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800491 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800492
493 /*
494 * Only one message could be retrieved every time for psa_get(). It is a
495 * fatal error if the input signal has more than a signal bit set.
496 */
497 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
498 tfm_core_panic();
499 }
500
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800501 partition = GET_CURRENT_COMPONENT();
502
Mingyang Sunb26b2802021-07-07 11:25:00 +0800503 /*
504 * Write the message to the service buffer. It is a fatal error if the
505 * input msg pointer is not a valid memory reference or not read-write.
506 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800507 FIH_CALL(tfm_hal_memory_check, fih_rc,
508 partition->boundary, (uintptr_t)msg,
509 sizeof(psa_msg_t), TFM_HAL_ACCESS_READWRITE);
510 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800511 tfm_core_panic();
512 }
513
514 /*
515 * It is a fatal error if the caller call psa_get() when no message has
516 * been set. The caller must call this function after an RoT Service signal
517 * is returned by psa_wait().
518 */
519 if (partition->signals_asserted == 0) {
520 tfm_core_panic();
521 }
522
523 /*
524 * It is a fatal error if the RoT Service signal is not currently asserted.
525 */
526 if ((partition->signals_asserted & signal) == 0) {
527 tfm_core_panic();
528 }
529
530 /*
531 * Get message by signal from partition. It is a fatal error if getting
532 * failed, which means the input signal is not correspond to an RoT service.
533 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800534 handle = spm_get_handle_by_signal(partition, signal);
535 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800536 return PSA_ERROR_DOES_NOT_EXIST;
537 }
538
Mingyang Suna09adda2022-02-16 18:11:33 +0800539 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800540
541 return PSA_SUCCESS;
542}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800543#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800544
Mingyang Sunb26b2802021-07-07 11:25:00 +0800545size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
546 void *buffer, size_t num_bytes)
547{
548 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800549 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800550 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800551 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800552
553 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800554 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800555 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800556 tfm_core_panic();
557 }
558
Mingyang Sunb26b2802021-07-07 11:25:00 +0800559 /*
560 * It is a fatal error if message handle does not refer to a request
561 * message
562 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800563 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800564 tfm_core_panic();
565 }
566
567 /*
568 * It is a fatal error if invec_idx is equal to or greater than
569 * PSA_MAX_IOVEC
570 */
571 if (invec_idx >= PSA_MAX_IOVEC) {
572 tfm_core_panic();
573 }
574
Shawn Shan038348e2021-09-08 17:11:04 +0800575#if PSA_FRAMEWORK_HAS_MM_IOVEC
576 /*
577 * It is a fatal error if the input vector has already been mapped using
578 * psa_map_invec().
579 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800580 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800581 tfm_core_panic();
582 }
583
Mingyang Suna09adda2022-02-16 18:11:33 +0800584 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800585#endif
586
Kevin Peng016b0e42022-04-15 11:28:48 +0800587 /* There was no remaining data in this input vector */
588 if (handle->msg.in_size[invec_idx] == 0) {
589 return 0;
590 }
591
Mingyang Sunb26b2802021-07-07 11:25:00 +0800592 /*
593 * Copy the client data to the service buffer. It is a fatal error
594 * if the memory reference for buffer is invalid or not read-write.
595 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800596 FIH_CALL(tfm_hal_memory_check, fih_rc,
597 curr_partition->boundary, (uintptr_t)buffer,
598 num_bytes, TFM_HAL_ACCESS_READWRITE);
599 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800600 tfm_core_panic();
601 }
602
Mingyang Suna09adda2022-02-16 18:11:33 +0800603 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
604 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800605
Mingyang Suna09adda2022-02-16 18:11:33 +0800606 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800607
608 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800609 handle->invec[invec_idx].base =
610 (char *)handle->invec[invec_idx].base + bytes;
611 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800612
613 return bytes;
614}
615
616size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
617 size_t num_bytes)
618{
Mingyang Suna09adda2022-02-16 18:11:33 +0800619 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800620
621 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800622 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800623 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800624 tfm_core_panic();
625 }
626
627 /*
628 * It is a fatal error if message handle does not refer to a request
629 * message
630 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800631 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800632 tfm_core_panic();
633 }
634
635 /*
636 * It is a fatal error if invec_idx is equal to or greater than
637 * PSA_MAX_IOVEC
638 */
639 if (invec_idx >= PSA_MAX_IOVEC) {
640 tfm_core_panic();
641 }
642
Shawn Shan038348e2021-09-08 17:11:04 +0800643#if PSA_FRAMEWORK_HAS_MM_IOVEC
644 /*
645 * It is a fatal error if the input vector has already been mapped using
646 * psa_map_invec().
647 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800648 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800649 tfm_core_panic();
650 }
651
Mingyang Suna09adda2022-02-16 18:11:33 +0800652 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800653#endif
654
Kevin Peng016b0e42022-04-15 11:28:48 +0800655 /* There was no remaining data in this input vector */
656 if (handle->msg.in_size[invec_idx] == 0) {
657 return 0;
658 }
659
Mingyang Sunb26b2802021-07-07 11:25:00 +0800660 /*
661 * If num_bytes is greater than the remaining size of the input vector then
662 * the remaining size of the input vector is used.
663 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800664 if (num_bytes > handle->msg.in_size[invec_idx]) {
665 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800666 }
667
668 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800669 handle->invec[invec_idx].base =
670 (char *)handle->invec[invec_idx].base + num_bytes;
671 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800672
673 return num_bytes;
674}
675
676void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
677 const void *buffer, size_t num_bytes)
678{
Mingyang Suna09adda2022-02-16 18:11:33 +0800679 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800680 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800681 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800682
683 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800684 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800685 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800686 tfm_core_panic();
687 }
688
Mingyang Sunb26b2802021-07-07 11:25:00 +0800689 /*
690 * It is a fatal error if message handle does not refer to a request
691 * message
692 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800693 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800694 tfm_core_panic();
695 }
696
697 /*
698 * It is a fatal error if outvec_idx is equal to or greater than
699 * PSA_MAX_IOVEC
700 */
701 if (outvec_idx >= PSA_MAX_IOVEC) {
702 tfm_core_panic();
703 }
704
705 /*
706 * It is a fatal error if the call attempts to write data past the end of
707 * the client output vector
708 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800709 if (num_bytes > handle->msg.out_size[outvec_idx] -
710 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800711 tfm_core_panic();
712 }
713
Shawn Shan038348e2021-09-08 17:11:04 +0800714#if PSA_FRAMEWORK_HAS_MM_IOVEC
715 /*
716 * It is a fatal error if the output vector has already been mapped using
717 * psa_map_outvec().
718 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800719 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800720 tfm_core_panic();
721 }
722
Mingyang Suna09adda2022-02-16 18:11:33 +0800723 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800724#endif
725
Mingyang Sunb26b2802021-07-07 11:25:00 +0800726 /*
727 * Copy the service buffer to client outvecs. It is a fatal error
728 * if the memory reference for buffer is invalid or not readable.
729 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800730 FIH_CALL(tfm_hal_memory_check, fih_rc,
731 curr_partition->boundary, (uintptr_t)buffer,
732 num_bytes, TFM_HAL_ACCESS_READABLE);
733 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800734 tfm_core_panic();
735 }
736
Mingyang Suna09adda2022-02-16 18:11:33 +0800737 spm_memcpy((char *)handle->outvec[outvec_idx].base +
738 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800739
740 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800741 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800742}
743
Ken Liuf8c7e532022-02-10 15:03:04 +0800744psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
745 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800746{
Ken Liu0bed7e02022-02-10 12:38:07 +0800747 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800748 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800749 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800750 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800751
752 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800753 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800754 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800755 tfm_core_panic();
756 }
757
758 /*
759 * RoT Service information is needed in this function, stored it in message
760 * body structure. Only two parameters are passed in this function: handle
761 * and status, so it is useful and simply to do like this.
762 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800763 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800764 if (!service) {
765 tfm_core_panic();
766 }
767
Mingyang Suna09adda2022-02-16 18:11:33 +0800768 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800769 case PSA_IPC_CONNECT:
770 /*
771 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
772 * input status is PSA_SUCCESS. Others return values are based on the
773 * input status.
774 */
775 if (status == PSA_SUCCESS) {
776 ret = msg_handle;
777 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
778 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800779 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800780 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800781 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
782 /* Fail the client connection, indicating a transient error. */
783 ret = PSA_ERROR_CONNECTION_BUSY;
784 } else {
785 tfm_core_panic();
786 }
787 break;
788 case PSA_IPC_DISCONNECT:
789 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800790 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800791
792 /*
793 * If the message type is PSA_IPC_DISCONNECT, then the status code is
794 * ignored
795 */
796 break;
797 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800798 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800799
800#if PSA_FRAMEWORK_HAS_MM_IOVEC
801
802 /*
803 * If the unmapped function is not called for an input/output vector
804 * that has been mapped, the framework will remove the mapping.
805 */
806 int i;
807
808 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800809 if (IOVEC_IS_MAPPED(handle, i) &&
810 (!IOVEC_IS_UNMAPPED(handle, i))) {
811 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800812 /*
813 * Any output vectors that are still mapped will report that
814 * zero bytes have been written.
815 */
816 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800817 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800818 }
819 }
820 }
821
822#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800823 /* Reply to a request message. Return values are based on status */
824 ret = status;
825 /*
826 * The total number of bytes written to a single parameter must be
827 * reported to the client by updating the len member of the
828 * psa_outvec structure for the parameter before returning from
829 * psa_call().
830 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800831 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800832 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800833 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800834 }
835 } else {
836 tfm_core_panic();
837 }
838 }
839
840 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
841 /*
842 * If the source of the programmer error is a Secure Partition, the SPM
843 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
844 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800845 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800846 tfm_core_panic();
847 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800848 }
849
Mingyang Sun620c8562021-11-10 11:44:58 +0800850 /*
851 * TODO: It can be optimized further by moving critical section protection
852 * to mailbox. Also need to check implementation when secure context is
853 * involved.
854 */
855 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu995a9742022-05-18 19:28:30 +0800856 ret = backend_replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800857 CRITICAL_SECTION_LEAVE(cs_assert);
858
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800859 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
860 tfm_spm_free_conn_handle(handle);
861 } else {
862 handle->status = TFM_HANDLE_STATUS_IDLE;
863 }
864
Mingyang Sun620c8562021-11-10 11:44:58 +0800865 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800866}
867
Kevin Peng613b4172022-02-15 14:41:44 +0800868#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800869void tfm_spm_partition_psa_notify(int32_t partition_id)
870{
Ken Liu5d73c872021-08-19 19:23:17 +0800871 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
872
873 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800874}
875
876void tfm_spm_partition_psa_clear(void)
877{
Ken Liu92ede9f2021-10-20 09:35:00 +0800878 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800879 struct partition_t *partition = NULL;
880
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800881 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800882
883 /*
884 * It is a fatal error if the Secure Partition's doorbell signal is not
885 * currently asserted.
886 */
887 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
888 tfm_core_panic();
889 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800890
891 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800892 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800893 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800894}
Kevin Peng613b4172022-02-15 14:41:44 +0800895#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800896
Mingyang Sunb26b2802021-07-07 11:25:00 +0800897void tfm_spm_partition_psa_panic(void)
898{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100899#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
900 tfm_hal_system_halt();
901#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800902 /*
903 * PSA FF recommends that the SPM causes the system to restart when a secure
904 * partition panics.
905 */
906 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100907#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800908}
909
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800910/* psa_set_rhandle is only needed by connection-based services */
911#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
912
913void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
914{
Mingyang Suna09adda2022-02-16 18:11:33 +0800915 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800916
917 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800918 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800919 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800920 tfm_core_panic();
921 }
922
923 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800924 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800925 tfm_core_panic();
926 }
927
Mingyang Suna09adda2022-02-16 18:11:33 +0800928 handle->msg.rhandle = rhandle;
929 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800930}
931
932#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
933
934#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800935void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800936{
937 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700938 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800939
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_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800948}
949
Kevin Peng67a89fd2021-11-25 11:22:02 +0800950psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800951{
952 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700953 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800954
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800955 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800956
957 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
958 if (!irq_info) {
959 tfm_core_panic();
960 }
961
Kevin Pengd399a1f2021-09-08 15:33:14 +0800962 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800963
964 return 1;
965}
966
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800967/* This API is only used for FLIH. */
968#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800969void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
970{
Ken Liu92ede9f2021-10-20 09:35:00 +0800971 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700972 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800973 struct partition_t *partition;
974
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800975 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800976
977 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
978 if (!irq_info) {
979 tfm_core_panic();
980 }
981
982 if (!irq_info->flih_func) {
983 /* This API is for FLIH IRQs only */
984 tfm_core_panic();
985 }
986
987 if ((partition->signals_asserted & irq_signal) == 0) {
988 /* The signal is not asserted */
989 tfm_core_panic();
990 }
991
Ken Liu92ede9f2021-10-20 09:35:00 +0800992 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800993 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800994 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800995}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800996#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800997
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800998/* This API is only used for SLIH. */
999#if CONFIG_TFM_SLIH_API == 1
1000void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001001{
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001002 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -07001003 const struct irq_load_info_t *irq_info = NULL;
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001004 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001005
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001006 partition = GET_CURRENT_COMPONENT();
1007
1008 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
1009 /* It is a fatal error if passed signal is not an interrupt signal. */
1010 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001011 tfm_core_panic();
1012 }
1013
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001014 if (irq_info->flih_func) {
1015 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001016 tfm_core_panic();
1017 }
1018
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001019 /* It is a fatal error if passed signal is not currently asserted */
1020 if ((partition->signals_asserted & irq_signal) == 0) {
1021 tfm_core_panic();
1022 }
1023
1024 CRITICAL_SECTION_ENTER(cs_assert);
1025 partition->signals_asserted &= ~irq_signal;
1026 CRITICAL_SECTION_LEAVE(cs_assert);
1027
1028 tfm_hal_irq_clear_pending(irq_info->source);
1029 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001030}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001031#endif
1032#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001033
Shawn Shan038348e2021-09-08 17:11:04 +08001034#if PSA_FRAMEWORK_HAS_MM_IOVEC
1035
1036const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1037 uint32_t invec_idx)
1038{
Mingyang Suna09adda2022-02-16 18:11:33 +08001039 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001040 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001041 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +08001042
1043 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001044 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001045 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001046 tfm_core_panic();
1047 }
1048
Mingyang Suna09adda2022-02-16 18:11:33 +08001049 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +08001050
1051 /*
1052 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1053 * Service that received the message.
1054 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001055 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001056 tfm_core_panic();
1057 }
1058
1059 /*
1060 * It is a fatal error if message handle does not refer to a request
1061 * message.
1062 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001063 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001064 tfm_core_panic();
1065 }
1066
1067 /*
1068 * It is a fatal error if invec_idx is equal to or greater than
1069 * PSA_MAX_IOVEC.
1070 */
1071 if (invec_idx >= PSA_MAX_IOVEC) {
1072 tfm_core_panic();
1073 }
1074
1075 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001076 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001077 tfm_core_panic();
1078 }
1079
1080 /*
1081 * It is a fatal error if the input vector has already been mapped using
1082 * psa_map_invec().
1083 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001084 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001085 tfm_core_panic();
1086 }
1087
1088 /*
1089 * It is a fatal error if the input vector has already been accessed
1090 * using psa_read() or psa_skip().
1091 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001092 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001093 tfm_core_panic();
1094 }
1095
1096 /*
1097 * It is a fatal error if the memory reference for the wrap input vector is
1098 * invalid or not readable.
1099 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001100 FIH_CALL(tfm_hal_memory_check, fih_rc,
1101 partition->boundary, (uintptr_t)handle->invec[invec_idx].base,
1102 handle->invec[invec_idx].len, TFM_HAL_ACCESS_READABLE);
1103 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001104 tfm_core_panic();
1105 }
1106
Mingyang Suna09adda2022-02-16 18:11:33 +08001107 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001108
Mingyang Suna09adda2022-02-16 18:11:33 +08001109 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001110}
1111
1112void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1113 uint32_t invec_idx)
1114{
Mingyang Suna09adda2022-02-16 18:11:33 +08001115 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001116
1117 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001118 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001119 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001120 tfm_core_panic();
1121 }
1122
1123 /*
1124 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1125 * Service that received the message.
1126 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001127 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001128 tfm_core_panic();
1129 }
1130
1131 /*
1132 * It is a fatal error if message handle does not refer to a request
1133 * message.
1134 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001135 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001136 tfm_core_panic();
1137 }
1138
1139 /*
1140 * It is a fatal error if invec_idx is equal to or greater than
1141 * PSA_MAX_IOVEC.
1142 */
1143 if (invec_idx >= PSA_MAX_IOVEC) {
1144 tfm_core_panic();
1145 }
1146
1147 /*
1148 * It is a fatal error if The input vector has not been mapped by a call to
1149 * psa_map_invec().
1150 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001151 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001152 tfm_core_panic();
1153 }
1154
1155 /*
1156 * It is a fatal error if the input vector has already been unmapped by a
1157 * call to psa_unmap_invec().
1158 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001159 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001160 tfm_core_panic();
1161 }
1162
Mingyang Suna09adda2022-02-16 18:11:33 +08001163 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001164}
1165
1166void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1167 uint32_t outvec_idx)
1168{
Mingyang Suna09adda2022-02-16 18:11:33 +08001169 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001170 uint32_t privileged;
1171 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001172 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +08001173
1174 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001175 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001176 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001177 tfm_core_panic();
1178 }
1179
Mingyang Suna09adda2022-02-16 18:11:33 +08001180 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001181 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001182
1183 /*
1184 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1185 * Service that received the message.
1186 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001187 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001188 tfm_core_panic();
1189 }
1190
1191 /*
1192 * It is a fatal error if message handle does not refer to a request
1193 * message.
1194 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001195 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001196 tfm_core_panic();
1197 }
1198
1199 /*
1200 * It is a fatal error if outvec_idx is equal to or greater than
1201 * PSA_MAX_IOVEC.
1202 */
1203 if (outvec_idx >= PSA_MAX_IOVEC) {
1204 tfm_core_panic();
1205 }
1206
1207 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001208 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001209 tfm_core_panic();
1210 }
1211
1212 /*
1213 * It is a fatal error if the output vector has already been mapped using
1214 * psa_map_outvec().
1215 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001216 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001217 tfm_core_panic();
1218 }
1219
1220 /*
1221 * It is a fatal error if the output vector has already been accessed
1222 * using psa_write().
1223 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001224 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001225 tfm_core_panic();
1226 }
1227
1228 /*
1229 * It is a fatal error if the output vector is invalid or not read-write.
1230 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001231 FIH_CALL(tfm_hal_memory_check, fih_rc,
1232 partition->boundary, (uintptr_t)handle->outvec[outvec_idx].base,
1233 handle->outvec[outvec_idx].len, TFM_HAL_ACCESS_READWRITE);
1234 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001235 tfm_core_panic();
1236 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001237 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001238
Mingyang Suna09adda2022-02-16 18:11:33 +08001239 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001240}
1241
1242void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1243 uint32_t outvec_idx, size_t len)
1244{
Mingyang Suna09adda2022-02-16 18:11:33 +08001245 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001246
1247 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001248 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001249 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001250 tfm_core_panic();
1251 }
1252
1253 /*
1254 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1255 * Service that received the message.
1256 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001257 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001258 tfm_core_panic();
1259 }
1260
1261 /*
1262 * It is a fatal error if message handle does not refer to a request
1263 * message.
1264 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001265 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001266 tfm_core_panic();
1267 }
1268
1269 /*
1270 * It is a fatal error if outvec_idx is equal to or greater than
1271 * PSA_MAX_IOVEC.
1272 */
1273 if (outvec_idx >= PSA_MAX_IOVEC) {
1274 tfm_core_panic();
1275 }
1276
1277 /*
1278 * It is a fatal error if len is greater than the output vector size.
1279 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001280 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001281 tfm_core_panic();
1282 }
1283
1284 /*
1285 * It is a fatal error if The output vector has not been mapped by a call to
1286 * psa_map_outvec().
1287 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001288 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001289 tfm_core_panic();
1290 }
1291
1292 /*
1293 * It is a fatal error if the output vector has already been unmapped by a
1294 * call to psa_unmap_outvec().
1295 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001296 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001297 tfm_core_panic();
1298 }
1299
Mingyang Suna09adda2022-02-16 18:11:33 +08001300 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001301
1302 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001303 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001304}
1305
1306#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */