blob: 59b82a8a729b104dabedb3c5bed0e5f75b4bfd2c [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"
Xinyu Zhangcdbe3622022-10-31 14:34:25 +080014#include "config_spm.h"
Ken Liu92ede9f2021-10-20 09:35:00 +080015#include "critical_section.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080016#include "psa/lifecycle.h"
David Hu733d8f92019-09-23 15:32:40 +080017#include "psa/service.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080018#include "interrupt.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080019#include "spm_ipc.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080020#include "tfm_arch.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080021#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080022#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080023#include "load/interrupt_defs.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080024#include "ffm/psa_api.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080025#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080026#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080027#include "ffm/psa_api.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080028#include "tfm_rpc.h"
Kevin Pengb42ed862022-08-08 14:44:02 +080029#include "tfm_api.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080030#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080031#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080032#include "tfm_psa_call_pack.h"
Summer Qin56725eb2022-05-06 15:23:40 +080033#include "tfm_hal_isolation.h"
David Hu733d8f92019-09-23 15:32:40 +080034
Ken Liub3b2cb62021-05-22 00:39:28 +080035#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080036extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080037
Shawn Shan038348e2021-09-08 17:11:04 +080038#if PSA_FRAMEWORK_HAS_MM_IOVEC
39
40/*
41 * The MM-IOVEC status
42 * The max total number of invec and outvec is 8.
43 * Each invec/outvec takes 4 bit, 32 bits in total.
44 *
45 * The encoding format of the MM-IOVEC status:
46 *--------------------------------------------------------------
47 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
48 *--------------------------------------------------------------
49 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
50 *--------------------------------------------------------------
51 *
52 * Take invec[0] as an example:
53 *
54 * bit 0: whether invec[0] has been mapped.
55 * bit 1: whether invec[0] has been unmapped.
56 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
57 * psa_write().
58 * bit 3: reserved for invec[0].
59 */
60
61#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
62#define OUTVEC_IDX_BASE 4 /*
63 * Base index of outvec.
64 * There are four invecs in front of
65 * outvec.
66 */
67#define INVEC_IDX_BASE 0 /* Base index of invec. */
68
69#define IOVEC_MAPPED_BIT (1U << 0)
70#define IOVEC_UNMAPPED_BIT (1U << 1)
71#define IOVEC_ACCESSED_BIT (1U << 2)
72
Mingyang Suna09adda2022-02-16 18:11:33 +080073#define IOVEC_IS_MAPPED(handle, iovec_idx) \
74 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080075 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080076#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
77 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080078 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080079#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
80 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080081 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080082#define SET_IOVEC_MAPPED(handle, iovec_idx) \
83 (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080084 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080085#define SET_IOVEC_UNMAPPED(handle, iovec_idx) \
86 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080087 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080088#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
89 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080090 ((iovec_idx) * IOVEC_STATUS_BITS)))
91
92#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
93
Xinyu Zhangb287ef82021-11-03 18:38:50 +080094void spm_handle_programmer_errors(psa_status_t status)
95{
Summer Qind9d497b2022-04-14 14:39:26 +080096 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
97 status == PSA_ERROR_CONNECTION_REFUSED) {
98 if (!tfm_spm_is_ns_caller()) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +080099 tfm_core_panic();
Summer Qind9d497b2022-04-14 14:39:26 +0800100 }
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800101 }
102}
103
Mingyang Suneeca4652021-07-15 15:19:16 +0800104uint32_t tfm_spm_get_lifecycle_state(void)
105{
106 /*
107 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
108 * implemented in the future.
109 */
110 return PSA_LIFECYCLE_UNKNOWN;
111}
112
113/* PSA Client API function body */
114
Mingyang Sund44522a2020-01-16 16:48:37 +0800115uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800116{
117 return PSA_FRAMEWORK_VERSION;
118}
119
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800120uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800121{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800122 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800123 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800124
125 /*
126 * It should return PSA_VERSION_NONE if the RoT Service is not
127 * implemented.
128 */
129 service = tfm_spm_get_service_by_sid(sid);
130 if (!service) {
131 return PSA_VERSION_NONE;
132 }
133
134 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800135 * It should return PSA_VERSION_NONE if the caller is not authorized
136 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800137 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800138 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800139 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800140 }
141
Ken Liuacd2a572021-05-12 16:19:04 +0800142 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800143}
144
Mingyang Suneeca4652021-07-15 15:19:16 +0800145psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
146 uint32_t ctrl_param,
147 const psa_invec *inptr,
148 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800149{
150 psa_invec invecs[PSA_MAX_IOVEC];
151 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800152 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800153 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800154 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800155 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800156 uint32_t sid, version, index;
Mingyang Sun620c8562021-11-10 11:44:58 +0800157 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800158 bool ns_caller = tfm_spm_is_ns_caller();
Summer Qin56725eb2022-05-06 15:23:40 +0800159 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Mingyang Suneeca4652021-07-15 15:19:16 +0800160 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
161 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
162 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800163 fih_int fih_rc = FIH_FAILURE;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800164
165 /* The request type must be zero or positive. */
166 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800167 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800168 }
David Hu733d8f92019-09-23 15:32:40 +0800169
Shawn Shanb222d892021-01-04 17:41:48 +0800170 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
Summer Qin22c301a2022-04-27 17:36:00 +0800171 if ((in_num > SIZE_MAX - out_num) ||
David Hu733d8f92019-09-23 15:32:40 +0800172 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800173 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800174 }
175
Mingyang Suncf0b1a52022-03-28 17:29:03 +0800176 /* It is a PROGRAMMER ERROR if the handle is a null handle. */
177 if (handle == PSA_NULL_HANDLE) {
178 return PSA_ERROR_PROGRAMMER_ERROR;
179 }
180
Kevin Peng385fda82021-08-18 10:41:19 +0800181 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800182
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800183 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800184 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800185 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800186
187 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800188 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800189 }
190
Mingyang Sun453ad402021-03-17 17:58:33 +0800191 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800192 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800193 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800194 }
195
Ken Liub3b2cb62021-05-22 00:39:28 +0800196 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800197
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800198 /*
199 * It is a PROGRAMMER ERROR if the caller is not authorized to access
200 * the RoT Service.
201 */
202 if (tfm_spm_check_authorization(sid, service, ns_caller)
Ken Liuad3f3e62022-03-04 22:23:52 +0800203 != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800204 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800205 }
206
Mingyang Sun453ad402021-03-17 17:58:33 +0800207 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
208
Ken Liuad3f3e62022-03-04 22:23:52 +0800209 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800210 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800211 }
212
Mingyang Sun620c8562021-11-10 11:44:58 +0800213 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800214 conn_handle = tfm_spm_create_conn_handle();
Mingyang Sun620c8562021-11-10 11:44:58 +0800215 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800216
217 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800218 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800219 }
220
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800221 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800222 handle = tfm_spm_to_user_handle(conn_handle);
223 } else {
Sherry Zhanga4575f32022-02-23 15:45:51 +0800224#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800225 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
Kevin Penge61e7052022-01-27 14:57:06 +0800226 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
227 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800228 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800229 }
230
231 /*
232 * It is a PROGRAMMER ERROR if the connection is currently
233 * handling a request.
234 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800235 if (conn_handle->status != TFM_HANDLE_STATUS_IDLE) {
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800236 return PSA_ERROR_PROGRAMMER_ERROR;
237 }
238
Ken Liu0bed7e02022-02-10 12:38:07 +0800239 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800240
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800241 if (!service) {
242 /* FixMe: Need to implement a mechanism to resolve this failure. */
243 return PSA_ERROR_PROGRAMMER_ERROR;
244 }
Sherry Zhanga4575f32022-02-23 15:45:51 +0800245#else
246 return PSA_ERROR_PROGRAMMER_ERROR;
247#endif
David Hu733d8f92019-09-23 15:32:40 +0800248 }
249
Kevin Pengedb8ee42021-03-09 16:50:11 +0800250 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800251 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800252 * if the memory reference for the wrap input vector is invalid or not
253 * readable.
254 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800255 FIH_CALL(tfm_hal_memory_check, fih_rc,
256 curr_partition->boundary, (uintptr_t)inptr,
257 in_num * sizeof(psa_invec), TFM_HAL_ACCESS_READABLE);
258 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800259 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800260 }
Summer Qinba2346e2019-11-12 16:26:31 +0800261
David Hu733d8f92019-09-23 15:32:40 +0800262 /*
263 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800264 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800265 * the wrap output vector is invalid or not read-write.
266 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800267 FIH_CALL(tfm_hal_memory_check, fih_rc,
268 curr_partition->boundary, (uintptr_t)outptr,
269 out_num * sizeof(psa_outvec), TFM_HAL_ACCESS_READWRITE);
270 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800271 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800272 }
273
Summer Qinf24dbb52020-07-23 14:53:54 +0800274 spm_memset(invecs, 0, sizeof(invecs));
275 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800276
277 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800278 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
279 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800280
281 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800282 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800283 * memory reference was invalid or not readable.
284 */
285 for (i = 0; i < in_num; i++) {
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800286 FIH_CALL(tfm_hal_memory_check, fih_rc,
287 curr_partition->boundary, (uintptr_t)invecs[i].base,
288 invecs[i].len, TFM_HAL_ACCESS_READABLE);
289 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800290 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800291 }
292 }
Summer Qinba2346e2019-11-12 16:26:31 +0800293
294 /*
295 * Clients must never overlap input parameters because of the risk of a
296 * double-fetch inconsistency.
Summer Qin56725eb2022-05-06 15:23:40 +0800297 * Overflow is checked in tfm_hal_memory_check functions.
Summer Qinba2346e2019-11-12 16:26:31 +0800298 */
299 for (i = 0; i + 1 < in_num; i++) {
300 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100301 if (!((char *) invecs[j].base + invecs[j].len <=
302 (char *) invecs[i].base ||
303 (char *) invecs[j].base >=
304 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800305 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800306 }
307 }
308 }
309
David Hu733d8f92019-09-23 15:32:40 +0800310 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800311 * For client output vector, it is a PROGRAMMER ERROR if the provided
312 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800313 */
314 for (i = 0; i < out_num; i++) {
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800315 FIH_CALL(tfm_hal_memory_check, fih_rc,
316 curr_partition->boundary, (uintptr_t)outvecs[i].base,
317 outvecs[i].len, TFM_HAL_ACCESS_READWRITE);
318 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800319 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800320 }
321 }
322
Ken Liu0bed7e02022-02-10 12:38:07 +0800323 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800324 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800325
Ken Liu995a9742022-05-18 19:28:30 +0800326 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800327}
328
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800329/* Following PSA APIs are only needed by connection-based services */
330#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
331
332psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
333{
334 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800335 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800336 int32_t client_id;
337 psa_handle_t handle;
338 bool ns_caller = tfm_spm_is_ns_caller();
339 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
340
341 /*
342 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
343 * platform.
344 */
345 service = tfm_spm_get_service_by_sid(sid);
346 if (!service) {
347 return PSA_ERROR_CONNECTION_REFUSED;
348 }
349
350 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
351 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
352 return PSA_ERROR_PROGRAMMER_ERROR;
353 }
354
355 /*
356 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
357 * RoT Service.
358 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800359 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800360 return PSA_ERROR_CONNECTION_REFUSED;
361 }
362
363 /*
364 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
365 * not supported on the platform.
366 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800367 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800368 return PSA_ERROR_CONNECTION_REFUSED;
369 }
370
371 client_id = tfm_spm_get_client_id(ns_caller);
372
373 /*
374 * Create connection handle here since it is possible to return the error
375 * code to client when creation fails.
376 */
377 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800378 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800379 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800380 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800381 return PSA_ERROR_CONNECTION_BUSY;
382 }
383
Mingyang Suna09adda2022-02-16 18:11:33 +0800384 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800385 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800386 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800387 client_id, NULL, 0, NULL, 0, NULL);
388
Ken Liu995a9742022-05-18 19:28:30 +0800389 return backend_messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800390}
391
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800392psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800393{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800394 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800395 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800396 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800397 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800398
399 /* It will have no effect if called with the NULL handle */
400 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800401 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800402 }
403
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800404 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800405 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800406 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800407 }
408
Kevin Peng385fda82021-08-18 10:41:19 +0800409 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800410
David Hu733d8f92019-09-23 15:32:40 +0800411 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800412 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
413 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800414 */
Kevin Penge61e7052022-01-27 14:57:06 +0800415 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
416 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800417 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800418 }
Shawn Shanb222d892021-01-04 17:41:48 +0800419
Ken Liu0bed7e02022-02-10 12:38:07 +0800420 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800421 if (!service) {
422 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800423 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800424 }
425
Shawn Shanb222d892021-01-04 17:41:48 +0800426 /*
427 * It is a PROGRAMMER ERROR if the connection is currently handling a
428 * request.
429 */
Summer Qin630c76b2020-05-20 10:32:58 +0800430 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800431 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800432 }
433
David Hu733d8f92019-09-23 15:32:40 +0800434 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800435 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
436 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800437
Ken Liu995a9742022-05-18 19:28:30 +0800438 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800439}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800440
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800441#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
442
Mingyang Suneeca4652021-07-15 15:19:16 +0800443/* PSA Partition API function body */
444
Kevin Pengdef92de2021-11-10 16:14:48 +0800445#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
446 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800447psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
448 uint32_t timeout)
449{
450 struct partition_t *partition = NULL;
451
452 /*
453 * Timeout[30:0] are reserved for future use.
454 * SPM must ignore the value of RES.
455 */
456 timeout &= PSA_TIMEOUT_MASK;
457
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800458 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800459
460 /*
Ruchika Guptad1834172022-06-15 12:03:08 +0530461 * signals_allowed can be 0 for TF-M internal partitions for special usages.
462 * Regular Secure Partitions should have at least one signal.
463 * This is gauranteed by the manifest tool.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800464 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
465 * signals.
466 */
Ruchika Guptad1834172022-06-15 12:03:08 +0530467 if ((partition->signals_allowed) &&
468 (partition->signals_allowed & signal_mask) == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800469 tfm_core_panic();
470 }
471
472 /*
Ken Liu995a9742022-05-18 19:28:30 +0800473 * backend_wake_up() blocks the caller thread if no signals are
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800474 * available. In this case, the return value of this function is temporary
475 * set into runtime context. After new signal(s) are available, the return
476 * value is updated with the available signal(s) and blocked thread gets
477 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800478 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800479 if (timeout == PSA_BLOCK) {
Ken Liu995a9742022-05-18 19:28:30 +0800480 return backend_wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800481 }
482
483 return partition->signals_asserted & signal_mask;
484}
Kevin Pengdef92de2021-11-10 16:14:48 +0800485#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800486
Kevin Pengdef92de2021-11-10 16:14:48 +0800487#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800488psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
489{
Mingyang Suna09adda2022-02-16 18:11:33 +0800490 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800491 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800492 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800493
494 /*
495 * Only one message could be retrieved every time for psa_get(). It is a
496 * fatal error if the input signal has more than a signal bit set.
497 */
498 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
499 tfm_core_panic();
500 }
501
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800502 partition = GET_CURRENT_COMPONENT();
503
Mingyang Sunb26b2802021-07-07 11:25:00 +0800504 /*
505 * Write the message to the service buffer. It is a fatal error if the
506 * input msg pointer is not a valid memory reference or not read-write.
507 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800508 FIH_CALL(tfm_hal_memory_check, fih_rc,
509 partition->boundary, (uintptr_t)msg,
510 sizeof(psa_msg_t), TFM_HAL_ACCESS_READWRITE);
511 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800512 tfm_core_panic();
513 }
514
515 /*
516 * It is a fatal error if the caller call psa_get() when no message has
517 * been set. The caller must call this function after an RoT Service signal
518 * is returned by psa_wait().
519 */
520 if (partition->signals_asserted == 0) {
521 tfm_core_panic();
522 }
523
524 /*
525 * It is a fatal error if the RoT Service signal is not currently asserted.
526 */
527 if ((partition->signals_asserted & signal) == 0) {
528 tfm_core_panic();
529 }
530
531 /*
532 * Get message by signal from partition. It is a fatal error if getting
533 * failed, which means the input signal is not correspond to an RoT service.
534 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800535 handle = spm_get_handle_by_signal(partition, signal);
536 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800537 return PSA_ERROR_DOES_NOT_EXIST;
538 }
539
Mingyang Suna09adda2022-02-16 18:11:33 +0800540 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800541
542 return PSA_SUCCESS;
543}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800544#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800545
Mingyang Sunb26b2802021-07-07 11:25:00 +0800546size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
547 void *buffer, size_t num_bytes)
548{
549 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800550 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800551 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800552 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800553
554 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800555 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800556 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800557 tfm_core_panic();
558 }
559
Mingyang Sunb26b2802021-07-07 11:25:00 +0800560 /*
561 * It is a fatal error if message handle does not refer to a request
562 * message
563 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800564 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800565 tfm_core_panic();
566 }
567
568 /*
569 * It is a fatal error if invec_idx is equal to or greater than
570 * PSA_MAX_IOVEC
571 */
572 if (invec_idx >= PSA_MAX_IOVEC) {
573 tfm_core_panic();
574 }
575
Shawn Shan038348e2021-09-08 17:11:04 +0800576#if PSA_FRAMEWORK_HAS_MM_IOVEC
577 /*
578 * It is a fatal error if the input vector has already been mapped using
579 * psa_map_invec().
580 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800581 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800582 tfm_core_panic();
583 }
584
Mingyang Suna09adda2022-02-16 18:11:33 +0800585 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800586#endif
587
Kevin Peng016b0e42022-04-15 11:28:48 +0800588 /* There was no remaining data in this input vector */
589 if (handle->msg.in_size[invec_idx] == 0) {
590 return 0;
591 }
592
Mingyang Sunb26b2802021-07-07 11:25:00 +0800593 /*
594 * Copy the client data to the service buffer. It is a fatal error
595 * if the memory reference for buffer is invalid or not read-write.
596 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800597 FIH_CALL(tfm_hal_memory_check, fih_rc,
598 curr_partition->boundary, (uintptr_t)buffer,
599 num_bytes, TFM_HAL_ACCESS_READWRITE);
600 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800601 tfm_core_panic();
602 }
603
Mingyang Suna09adda2022-02-16 18:11:33 +0800604 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
605 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800606
Mingyang Suna09adda2022-02-16 18:11:33 +0800607 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800608
609 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800610 handle->invec[invec_idx].base =
611 (char *)handle->invec[invec_idx].base + bytes;
612 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800613
614 return bytes;
615}
616
617size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
618 size_t num_bytes)
619{
Mingyang Suna09adda2022-02-16 18:11:33 +0800620 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800621
622 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800623 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800624 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800625 tfm_core_panic();
626 }
627
628 /*
629 * It is a fatal error if message handle does not refer to a request
630 * message
631 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800632 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800633 tfm_core_panic();
634 }
635
636 /*
637 * It is a fatal error if invec_idx is equal to or greater than
638 * PSA_MAX_IOVEC
639 */
640 if (invec_idx >= PSA_MAX_IOVEC) {
641 tfm_core_panic();
642 }
643
Shawn Shan038348e2021-09-08 17:11:04 +0800644#if PSA_FRAMEWORK_HAS_MM_IOVEC
645 /*
646 * It is a fatal error if the input vector has already been mapped using
647 * psa_map_invec().
648 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800649 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800650 tfm_core_panic();
651 }
652
Mingyang Suna09adda2022-02-16 18:11:33 +0800653 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800654#endif
655
Kevin Peng016b0e42022-04-15 11:28:48 +0800656 /* There was no remaining data in this input vector */
657 if (handle->msg.in_size[invec_idx] == 0) {
658 return 0;
659 }
660
Mingyang Sunb26b2802021-07-07 11:25:00 +0800661 /*
662 * If num_bytes is greater than the remaining size of the input vector then
663 * the remaining size of the input vector is used.
664 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800665 if (num_bytes > handle->msg.in_size[invec_idx]) {
666 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800667 }
668
669 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800670 handle->invec[invec_idx].base =
671 (char *)handle->invec[invec_idx].base + num_bytes;
672 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800673
674 return num_bytes;
675}
676
677void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
678 const void *buffer, size_t num_bytes)
679{
Mingyang Suna09adda2022-02-16 18:11:33 +0800680 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800681 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800682 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800683
684 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800685 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800686 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800687 tfm_core_panic();
688 }
689
Mingyang Sunb26b2802021-07-07 11:25:00 +0800690 /*
691 * It is a fatal error if message handle does not refer to a request
692 * message
693 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800694 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800695 tfm_core_panic();
696 }
697
698 /*
699 * It is a fatal error if outvec_idx is equal to or greater than
700 * PSA_MAX_IOVEC
701 */
702 if (outvec_idx >= PSA_MAX_IOVEC) {
703 tfm_core_panic();
704 }
705
706 /*
707 * It is a fatal error if the call attempts to write data past the end of
708 * the client output vector
709 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800710 if (num_bytes > handle->msg.out_size[outvec_idx] -
711 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800712 tfm_core_panic();
713 }
714
Shawn Shan038348e2021-09-08 17:11:04 +0800715#if PSA_FRAMEWORK_HAS_MM_IOVEC
716 /*
717 * It is a fatal error if the output vector has already been mapped using
718 * psa_map_outvec().
719 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800720 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800721 tfm_core_panic();
722 }
723
Mingyang Suna09adda2022-02-16 18:11:33 +0800724 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800725#endif
726
Mingyang Sunb26b2802021-07-07 11:25:00 +0800727 /*
728 * Copy the service buffer to client outvecs. It is a fatal error
729 * if the memory reference for buffer is invalid or not readable.
730 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800731 FIH_CALL(tfm_hal_memory_check, fih_rc,
732 curr_partition->boundary, (uintptr_t)buffer,
733 num_bytes, TFM_HAL_ACCESS_READABLE);
734 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800735 tfm_core_panic();
736 }
737
Mingyang Suna09adda2022-02-16 18:11:33 +0800738 spm_memcpy((char *)handle->outvec[outvec_idx].base +
739 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800740
741 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800742 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800743}
744
Ken Liuf8c7e532022-02-10 15:03:04 +0800745psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
746 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800747{
Ken Liu0bed7e02022-02-10 12:38:07 +0800748 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800749 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800750 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800751 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800752
753 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800754 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800755 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800756 tfm_core_panic();
757 }
758
759 /*
760 * RoT Service information is needed in this function, stored it in message
761 * body structure. Only two parameters are passed in this function: handle
762 * and status, so it is useful and simply to do like this.
763 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800764 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800765 if (!service) {
766 tfm_core_panic();
767 }
768
Mingyang Suna09adda2022-02-16 18:11:33 +0800769 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800770 case PSA_IPC_CONNECT:
771 /*
772 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
773 * input status is PSA_SUCCESS. Others return values are based on the
774 * input status.
775 */
776 if (status == PSA_SUCCESS) {
777 ret = msg_handle;
778 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
779 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800780 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800781 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800782 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
783 /* Fail the client connection, indicating a transient error. */
784 ret = PSA_ERROR_CONNECTION_BUSY;
785 } else {
786 tfm_core_panic();
787 }
788 break;
789 case PSA_IPC_DISCONNECT:
790 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800791 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800792
793 /*
794 * If the message type is PSA_IPC_DISCONNECT, then the status code is
795 * ignored
796 */
797 break;
798 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800799 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800800
801#if PSA_FRAMEWORK_HAS_MM_IOVEC
802
803 /*
804 * If the unmapped function is not called for an input/output vector
805 * that has been mapped, the framework will remove the mapping.
806 */
807 int i;
808
809 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800810 if (IOVEC_IS_MAPPED(handle, i) &&
811 (!IOVEC_IS_UNMAPPED(handle, i))) {
812 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800813 /*
814 * Any output vectors that are still mapped will report that
815 * zero bytes have been written.
816 */
817 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800818 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800819 }
820 }
821 }
822
823#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800824 /* Reply to a request message. Return values are based on status */
825 ret = status;
826 /*
827 * The total number of bytes written to a single parameter must be
828 * reported to the client by updating the len member of the
829 * psa_outvec structure for the parameter before returning from
830 * psa_call().
831 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800832 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800833 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800834 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800835 }
836 } else {
837 tfm_core_panic();
838 }
839 }
840
841 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
842 /*
843 * If the source of the programmer error is a Secure Partition, the SPM
844 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
845 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800846 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800847 tfm_core_panic();
848 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800849 }
850
Mingyang Sun620c8562021-11-10 11:44:58 +0800851 /*
852 * TODO: It can be optimized further by moving critical section protection
853 * to mailbox. Also need to check implementation when secure context is
854 * involved.
855 */
856 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu995a9742022-05-18 19:28:30 +0800857 ret = backend_replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800858 CRITICAL_SECTION_LEAVE(cs_assert);
859
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800860 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
861 tfm_spm_free_conn_handle(handle);
862 } else {
863 handle->status = TFM_HANDLE_STATUS_IDLE;
864 }
865
Mingyang Sun620c8562021-11-10 11:44:58 +0800866 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800867}
868
Kevin Peng613b4172022-02-15 14:41:44 +0800869#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800870void tfm_spm_partition_psa_notify(int32_t partition_id)
871{
Ken Liu5d73c872021-08-19 19:23:17 +0800872 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
873
874 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800875}
876
877void tfm_spm_partition_psa_clear(void)
878{
Ken Liu92ede9f2021-10-20 09:35:00 +0800879 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800880 struct partition_t *partition = NULL;
881
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800882 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800883
884 /*
885 * It is a fatal error if the Secure Partition's doorbell signal is not
886 * currently asserted.
887 */
888 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
889 tfm_core_panic();
890 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800891
892 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800893 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800894 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800895}
Kevin Peng613b4172022-02-15 14:41:44 +0800896#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800897
Mingyang Sunb26b2802021-07-07 11:25:00 +0800898void tfm_spm_partition_psa_panic(void)
899{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100900#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
901 tfm_hal_system_halt();
902#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800903 /*
904 * PSA FF recommends that the SPM causes the system to restart when a secure
905 * partition panics.
906 */
907 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100908#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800909}
910
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800911/* psa_set_rhandle is only needed by connection-based services */
912#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
913
914void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
915{
Mingyang Suna09adda2022-02-16 18:11:33 +0800916 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800917
918 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800919 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800920 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800921 tfm_core_panic();
922 }
923
924 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800925 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800926 tfm_core_panic();
927 }
928
Mingyang Suna09adda2022-02-16 18:11:33 +0800929 handle->msg.rhandle = rhandle;
930 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800931}
932
933#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
934
935#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800936void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800937{
938 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700939 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800940
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800941 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800942
943 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
944 if (!irq_info) {
945 tfm_core_panic();
946 }
947
Kevin Pengd399a1f2021-09-08 15:33:14 +0800948 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800949}
950
Kevin Peng67a89fd2021-11-25 11:22:02 +0800951psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800952{
953 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700954 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800955
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800956 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800957
958 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
959 if (!irq_info) {
960 tfm_core_panic();
961 }
962
Kevin Pengd399a1f2021-09-08 15:33:14 +0800963 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800964
965 return 1;
966}
967
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800968/* This API is only used for FLIH. */
969#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800970void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
971{
Ken Liu92ede9f2021-10-20 09:35:00 +0800972 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700973 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800974 struct partition_t *partition;
975
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800976 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800977
978 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
979 if (!irq_info) {
980 tfm_core_panic();
981 }
982
983 if (!irq_info->flih_func) {
984 /* This API is for FLIH IRQs only */
985 tfm_core_panic();
986 }
987
988 if ((partition->signals_asserted & irq_signal) == 0) {
989 /* The signal is not asserted */
990 tfm_core_panic();
991 }
992
Ken Liu92ede9f2021-10-20 09:35:00 +0800993 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800994 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800995 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800996}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800997#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800998
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800999/* This API is only used for SLIH. */
1000#if CONFIG_TFM_SLIH_API == 1
1001void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001002{
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001003 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -07001004 const struct irq_load_info_t *irq_info = NULL;
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001005 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001006
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001007 partition = GET_CURRENT_COMPONENT();
1008
1009 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
1010 /* It is a fatal error if passed signal is not an interrupt signal. */
1011 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001012 tfm_core_panic();
1013 }
1014
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001015 if (irq_info->flih_func) {
1016 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001017 tfm_core_panic();
1018 }
1019
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001020 /* It is a fatal error if passed signal is not currently asserted */
1021 if ((partition->signals_asserted & irq_signal) == 0) {
1022 tfm_core_panic();
1023 }
1024
1025 CRITICAL_SECTION_ENTER(cs_assert);
1026 partition->signals_asserted &= ~irq_signal;
1027 CRITICAL_SECTION_LEAVE(cs_assert);
1028
1029 tfm_hal_irq_clear_pending(irq_info->source);
1030 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001031}
Mingyang Suned5fe7b2022-02-10 17:33:21 +08001032#endif
1033#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +08001034
Shawn Shan038348e2021-09-08 17:11:04 +08001035#if PSA_FRAMEWORK_HAS_MM_IOVEC
1036
1037const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1038 uint32_t invec_idx)
1039{
Mingyang Suna09adda2022-02-16 18:11:33 +08001040 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001041 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001042 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +08001043
1044 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001045 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001046 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001047 tfm_core_panic();
1048 }
1049
Mingyang Suna09adda2022-02-16 18:11:33 +08001050 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +08001051
1052 /*
1053 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1054 * Service that received the message.
1055 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001056 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001057 tfm_core_panic();
1058 }
1059
1060 /*
1061 * It is a fatal error if message handle does not refer to a request
1062 * message.
1063 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001064 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001065 tfm_core_panic();
1066 }
1067
1068 /*
1069 * It is a fatal error if invec_idx is equal to or greater than
1070 * PSA_MAX_IOVEC.
1071 */
1072 if (invec_idx >= PSA_MAX_IOVEC) {
1073 tfm_core_panic();
1074 }
1075
1076 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001077 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001078 tfm_core_panic();
1079 }
1080
1081 /*
1082 * It is a fatal error if the input vector has already been mapped using
1083 * psa_map_invec().
1084 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001085 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001086 tfm_core_panic();
1087 }
1088
1089 /*
1090 * It is a fatal error if the input vector has already been accessed
1091 * using psa_read() or psa_skip().
1092 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001093 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001094 tfm_core_panic();
1095 }
1096
1097 /*
1098 * It is a fatal error if the memory reference for the wrap input vector is
1099 * invalid or not readable.
1100 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001101 FIH_CALL(tfm_hal_memory_check, fih_rc,
1102 partition->boundary, (uintptr_t)handle->invec[invec_idx].base,
1103 handle->invec[invec_idx].len, TFM_HAL_ACCESS_READABLE);
1104 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001105 tfm_core_panic();
1106 }
1107
Mingyang Suna09adda2022-02-16 18:11:33 +08001108 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001109
Mingyang Suna09adda2022-02-16 18:11:33 +08001110 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001111}
1112
1113void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1114 uint32_t invec_idx)
1115{
Mingyang Suna09adda2022-02-16 18:11:33 +08001116 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001117
1118 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001119 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001120 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001121 tfm_core_panic();
1122 }
1123
1124 /*
1125 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1126 * Service that received the message.
1127 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001128 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001129 tfm_core_panic();
1130 }
1131
1132 /*
1133 * It is a fatal error if message handle does not refer to a request
1134 * message.
1135 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001136 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001137 tfm_core_panic();
1138 }
1139
1140 /*
1141 * It is a fatal error if invec_idx is equal to or greater than
1142 * PSA_MAX_IOVEC.
1143 */
1144 if (invec_idx >= PSA_MAX_IOVEC) {
1145 tfm_core_panic();
1146 }
1147
1148 /*
1149 * It is a fatal error if The input vector has not been mapped by a call to
1150 * psa_map_invec().
1151 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001152 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001153 tfm_core_panic();
1154 }
1155
1156 /*
1157 * It is a fatal error if the input vector has already been unmapped by a
1158 * call to psa_unmap_invec().
1159 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001160 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001161 tfm_core_panic();
1162 }
1163
Mingyang Suna09adda2022-02-16 18:11:33 +08001164 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001165}
1166
1167void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1168 uint32_t outvec_idx)
1169{
Mingyang Suna09adda2022-02-16 18:11:33 +08001170 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001171 uint32_t privileged;
1172 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001173 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +08001174
1175 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001176 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001177 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001178 tfm_core_panic();
1179 }
1180
Mingyang Suna09adda2022-02-16 18:11:33 +08001181 partition = handle->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001182 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001183
1184 /*
1185 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1186 * Service that received the message.
1187 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001188 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001189 tfm_core_panic();
1190 }
1191
1192 /*
1193 * It is a fatal error if message handle does not refer to a request
1194 * message.
1195 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001196 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001197 tfm_core_panic();
1198 }
1199
1200 /*
1201 * It is a fatal error if outvec_idx is equal to or greater than
1202 * PSA_MAX_IOVEC.
1203 */
1204 if (outvec_idx >= PSA_MAX_IOVEC) {
1205 tfm_core_panic();
1206 }
1207
1208 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001209 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001210 tfm_core_panic();
1211 }
1212
1213 /*
1214 * It is a fatal error if the output vector has already been mapped using
1215 * psa_map_outvec().
1216 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001217 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001218 tfm_core_panic();
1219 }
1220
1221 /*
1222 * It is a fatal error if the output vector has already been accessed
1223 * using psa_write().
1224 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001225 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001226 tfm_core_panic();
1227 }
1228
1229 /*
1230 * It is a fatal error if the output vector is invalid or not read-write.
1231 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001232 FIH_CALL(tfm_hal_memory_check, fih_rc,
1233 partition->boundary, (uintptr_t)handle->outvec[outvec_idx].base,
1234 handle->outvec[outvec_idx].len, TFM_HAL_ACCESS_READWRITE);
1235 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001236 tfm_core_panic();
1237 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001238 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001239
Mingyang Suna09adda2022-02-16 18:11:33 +08001240 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001241}
1242
1243void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1244 uint32_t outvec_idx, size_t len)
1245{
Mingyang Suna09adda2022-02-16 18:11:33 +08001246 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001247
1248 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001249 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001250 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001251 tfm_core_panic();
1252 }
1253
1254 /*
1255 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1256 * Service that received the message.
1257 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001258 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001259 tfm_core_panic();
1260 }
1261
1262 /*
1263 * It is a fatal error if message handle does not refer to a request
1264 * message.
1265 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001266 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001267 tfm_core_panic();
1268 }
1269
1270 /*
1271 * It is a fatal error if outvec_idx is equal to or greater than
1272 * PSA_MAX_IOVEC.
1273 */
1274 if (outvec_idx >= PSA_MAX_IOVEC) {
1275 tfm_core_panic();
1276 }
1277
1278 /*
1279 * It is a fatal error if len is greater than the output vector size.
1280 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001281 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001282 tfm_core_panic();
1283 }
1284
1285 /*
1286 * It is a fatal error if The output vector has not been mapped by a call to
1287 * psa_map_outvec().
1288 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001289 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001290 tfm_core_panic();
1291 }
1292
1293 /*
1294 * It is a fatal error if the output vector has already been unmapped by a
1295 * call to psa_unmap_outvec().
1296 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001297 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001298 tfm_core_panic();
1299 }
1300
Mingyang Suna09adda2022-02-16 18:11:33 +08001301 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001302
1303 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001304 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001305}
1306
1307#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */