blob: b930713e034237d36a79721ecceddfc61fc2f741 [file] [log] [blame]
David Hu733d8f92019-09-23 15:32:40 +08001/*
Xinyu Zhang669744c2023-02-06 15:24:26 +08002 * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
BohdanHunko628109f2023-01-31 17:23:35 +02003 * Copyright (c) 2022-2023 Cypress Semiconductor Corporation (an Infineon
Chris Brand10a2acb2022-10-18 17:12:27 -07004 * 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"
Sherry Zhangc7147022023-02-03 11:21:10 +080019#include "spm.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"
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
Shawn Shan038348e2021-09-08 17:11:04 +080034#if PSA_FRAMEWORK_HAS_MM_IOVEC
35
36/*
37 * The MM-IOVEC status
38 * The max total number of invec and outvec is 8.
39 * Each invec/outvec takes 4 bit, 32 bits in total.
40 *
41 * The encoding format of the MM-IOVEC status:
42 *--------------------------------------------------------------
43 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
44 *--------------------------------------------------------------
45 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
46 *--------------------------------------------------------------
47 *
48 * Take invec[0] as an example:
49 *
50 * bit 0: whether invec[0] has been mapped.
51 * bit 1: whether invec[0] has been unmapped.
52 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
53 * psa_write().
54 * bit 3: reserved for invec[0].
55 */
56
57#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
58#define OUTVEC_IDX_BASE 4 /*
59 * Base index of outvec.
60 * There are four invecs in front of
61 * outvec.
62 */
63#define INVEC_IDX_BASE 0 /* Base index of invec. */
64
65#define IOVEC_MAPPED_BIT (1U << 0)
66#define IOVEC_UNMAPPED_BIT (1U << 1)
67#define IOVEC_ACCESSED_BIT (1U << 2)
68
Mingyang Suna09adda2022-02-16 18:11:33 +080069#define IOVEC_IS_MAPPED(handle, iovec_idx) \
70 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080071 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080072#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
73 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080074 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080075#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
76 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080077 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080078#define SET_IOVEC_MAPPED(handle, iovec_idx) \
79 (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080080 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080081#define SET_IOVEC_UNMAPPED(handle, iovec_idx) \
82 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080083 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080084#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
85 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080086 ((iovec_idx) * IOVEC_STATUS_BITS)))
87
88#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
89
Xinyu Zhangb287ef82021-11-03 18:38:50 +080090void spm_handle_programmer_errors(psa_status_t status)
91{
Summer Qind9d497b2022-04-14 14:39:26 +080092 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
93 status == PSA_ERROR_CONNECTION_REFUSED) {
94 if (!tfm_spm_is_ns_caller()) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +080095 tfm_core_panic();
Summer Qind9d497b2022-04-14 14:39:26 +080096 }
Xinyu Zhangb287ef82021-11-03 18:38:50 +080097 }
98}
99
Mingyang Suneeca4652021-07-15 15:19:16 +0800100uint32_t tfm_spm_get_lifecycle_state(void)
101{
102 /*
103 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
104 * implemented in the future.
105 */
106 return PSA_LIFECYCLE_UNKNOWN;
107}
108
109/* PSA Client API function body */
110
Mingyang Sund44522a2020-01-16 16:48:37 +0800111uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800112{
113 return PSA_FRAMEWORK_VERSION;
114}
115
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800116uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800117{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800118 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800119 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800120
121 /*
122 * It should return PSA_VERSION_NONE if the RoT Service is not
123 * implemented.
124 */
125 service = tfm_spm_get_service_by_sid(sid);
126 if (!service) {
127 return PSA_VERSION_NONE;
128 }
129
130 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800131 * It should return PSA_VERSION_NONE if the caller is not authorized
132 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800133 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800134 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800135 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800136 }
137
Ken Liuacd2a572021-05-12 16:19:04 +0800138 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800139}
140
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800141/* Following PSA APIs are only needed by connection-based services */
142#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
143
144psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
145{
146 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800147 struct conn_handle_t *conn_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800148 int32_t client_id;
149 psa_handle_t handle;
150 bool ns_caller = tfm_spm_is_ns_caller();
151 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
152
153 /*
154 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
155 * platform.
156 */
157 service = tfm_spm_get_service_by_sid(sid);
158 if (!service) {
159 return PSA_ERROR_CONNECTION_REFUSED;
160 }
161
162 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
163 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
164 return PSA_ERROR_PROGRAMMER_ERROR;
165 }
166
167 /*
168 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
169 * RoT Service.
170 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800171 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800172 return PSA_ERROR_CONNECTION_REFUSED;
173 }
174
175 /*
176 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
177 * not supported on the platform.
178 */
Ken Liuad3f3e62022-03-04 22:23:52 +0800179 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800180 return PSA_ERROR_CONNECTION_REFUSED;
181 }
182
183 client_id = tfm_spm_get_client_id(ns_caller);
184
185 /*
186 * Create connection handle here since it is possible to return the error
187 * code to client when creation fails.
188 */
189 CRITICAL_SECTION_ENTER(cs_assert);
Kevin Penge61e7052022-01-27 14:57:06 +0800190 conn_handle = tfm_spm_create_conn_handle();
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800191 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suna09adda2022-02-16 18:11:33 +0800192 if (!conn_handle) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800193 return PSA_ERROR_CONNECTION_BUSY;
194 }
195
Mingyang Suna09adda2022-02-16 18:11:33 +0800196 handle = tfm_spm_to_user_handle(conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800197 /* No input or output needed for connect message */
Mingyang Suna09adda2022-02-16 18:11:33 +0800198 spm_fill_message(conn_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800199 client_id, NULL, 0, NULL, 0, NULL);
200
Ken Liu995a9742022-05-18 19:28:30 +0800201 return backend_messaging(service, conn_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800202}
203
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800204psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800205{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800206 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800207 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800208 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800209 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800210
211 /* It will have no effect if called with the NULL handle */
212 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800213 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800214 }
215
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800216 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800217 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800218 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800219 }
220
Kevin Peng385fda82021-08-18 10:41:19 +0800221 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800222
David Hu733d8f92019-09-23 15:32:40 +0800223 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800224 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
225 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800226 */
Kevin Penge61e7052022-01-27 14:57:06 +0800227 conn_handle = spm_get_handle_by_client_handle(handle, client_id);
228 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800229 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800230 }
Shawn Shanb222d892021-01-04 17:41:48 +0800231
Ken Liu0bed7e02022-02-10 12:38:07 +0800232 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800233 if (!service) {
234 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800235 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800236 }
237
Shawn Shanb222d892021-01-04 17:41:48 +0800238 /*
239 * It is a PROGRAMMER ERROR if the connection is currently handling a
240 * request.
241 */
Summer Qin630c76b2020-05-20 10:32:58 +0800242 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800243 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800244 }
245
David Hu733d8f92019-09-23 15:32:40 +0800246 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800247 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
248 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800249
Ken Liu995a9742022-05-18 19:28:30 +0800250 return backend_messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800251}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800252
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800253#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
254
Mingyang Suneeca4652021-07-15 15:19:16 +0800255/* PSA Partition API function body */
256
Kevin Pengdef92de2021-11-10 16:14:48 +0800257#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
258 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800259psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
260 uint32_t timeout)
261{
262 struct partition_t *partition = NULL;
263
264 /*
265 * Timeout[30:0] are reserved for future use.
266 * SPM must ignore the value of RES.
267 */
268 timeout &= PSA_TIMEOUT_MASK;
269
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800270 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800271
272 /*
Ruchika Guptad1834172022-06-15 12:03:08 +0530273 * signals_allowed can be 0 for TF-M internal partitions for special usages.
274 * Regular Secure Partitions should have at least one signal.
275 * This is gauranteed by the manifest tool.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800276 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
277 * signals.
278 */
Ruchika Guptad1834172022-06-15 12:03:08 +0530279 if ((partition->signals_allowed) &&
280 (partition->signals_allowed & signal_mask) == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800281 tfm_core_panic();
282 }
283
284 /*
Ken Liu995a9742022-05-18 19:28:30 +0800285 * backend_wake_up() blocks the caller thread if no signals are
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800286 * available. In this case, the return value of this function is temporary
287 * set into runtime context. After new signal(s) are available, the return
288 * value is updated with the available signal(s) and blocked thread gets
289 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800290 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800291 if (timeout == PSA_BLOCK) {
Ken Liu995a9742022-05-18 19:28:30 +0800292 return backend_wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800293 }
294
295 return partition->signals_asserted & signal_mask;
296}
Kevin Pengdef92de2021-11-10 16:14:48 +0800297#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800298
Kevin Pengdef92de2021-11-10 16:14:48 +0800299#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800300psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
301{
Mingyang Suna09adda2022-02-16 18:11:33 +0800302 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800303 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800304 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800305
306 /*
307 * Only one message could be retrieved every time for psa_get(). It is a
308 * fatal error if the input signal has more than a signal bit set.
309 */
310 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
311 tfm_core_panic();
312 }
313
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800314 partition = GET_CURRENT_COMPONENT();
315
Mingyang Sunb26b2802021-07-07 11:25:00 +0800316 /*
317 * Write the message to the service buffer. It is a fatal error if the
318 * input msg pointer is not a valid memory reference or not read-write.
319 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800320 FIH_CALL(tfm_hal_memory_check, fih_rc,
321 partition->boundary, (uintptr_t)msg,
322 sizeof(psa_msg_t), TFM_HAL_ACCESS_READWRITE);
323 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800324 tfm_core_panic();
325 }
326
327 /*
328 * It is a fatal error if the caller call psa_get() when no message has
329 * been set. The caller must call this function after an RoT Service signal
330 * is returned by psa_wait().
331 */
332 if (partition->signals_asserted == 0) {
333 tfm_core_panic();
334 }
335
336 /*
337 * It is a fatal error if the RoT Service signal is not currently asserted.
338 */
339 if ((partition->signals_asserted & signal) == 0) {
340 tfm_core_panic();
341 }
342
343 /*
344 * Get message by signal from partition. It is a fatal error if getting
345 * failed, which means the input signal is not correspond to an RoT service.
346 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800347 handle = spm_get_handle_by_signal(partition, signal);
348 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800349 return PSA_ERROR_DOES_NOT_EXIST;
350 }
351
Mingyang Suna09adda2022-02-16 18:11:33 +0800352 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800353
354 return PSA_SUCCESS;
355}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800356#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800357
Mingyang Sunb26b2802021-07-07 11:25:00 +0800358size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
359 void *buffer, size_t num_bytes)
360{
361 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800362 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800363 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800364 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800365
366 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800367 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800368 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800369 tfm_core_panic();
370 }
371
Mingyang Sunb26b2802021-07-07 11:25:00 +0800372 /*
373 * It is a fatal error if message handle does not refer to a request
374 * message
375 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800376 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800377 tfm_core_panic();
378 }
379
380 /*
381 * It is a fatal error if invec_idx is equal to or greater than
382 * PSA_MAX_IOVEC
383 */
384 if (invec_idx >= PSA_MAX_IOVEC) {
385 tfm_core_panic();
386 }
387
Shawn Shan038348e2021-09-08 17:11:04 +0800388#if PSA_FRAMEWORK_HAS_MM_IOVEC
389 /*
390 * It is a fatal error if the input vector has already been mapped using
391 * psa_map_invec().
392 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800393 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800394 tfm_core_panic();
395 }
396
Mingyang Suna09adda2022-02-16 18:11:33 +0800397 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800398#endif
399
Kevin Peng016b0e42022-04-15 11:28:48 +0800400 /* There was no remaining data in this input vector */
401 if (handle->msg.in_size[invec_idx] == 0) {
402 return 0;
403 }
404
Mingyang Sunb26b2802021-07-07 11:25:00 +0800405 /*
406 * Copy the client data to the service buffer. It is a fatal error
407 * if the memory reference for buffer is invalid or not read-write.
408 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800409 FIH_CALL(tfm_hal_memory_check, fih_rc,
410 curr_partition->boundary, (uintptr_t)buffer,
411 num_bytes, TFM_HAL_ACCESS_READWRITE);
412 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800413 tfm_core_panic();
414 }
415
Mingyang Suna09adda2022-02-16 18:11:33 +0800416 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
417 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800418
Mingyang Suna09adda2022-02-16 18:11:33 +0800419 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800420
421 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800422 handle->invec[invec_idx].base =
423 (char *)handle->invec[invec_idx].base + bytes;
424 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800425
426 return bytes;
427}
428
429size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
430 size_t num_bytes)
431{
Mingyang Suna09adda2022-02-16 18:11:33 +0800432 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800433
434 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800435 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800436 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800437 tfm_core_panic();
438 }
439
440 /*
441 * It is a fatal error if message handle does not refer to a request
442 * message
443 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800444 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800445 tfm_core_panic();
446 }
447
448 /*
449 * It is a fatal error if invec_idx is equal to or greater than
450 * PSA_MAX_IOVEC
451 */
452 if (invec_idx >= PSA_MAX_IOVEC) {
453 tfm_core_panic();
454 }
455
Shawn Shan038348e2021-09-08 17:11:04 +0800456#if PSA_FRAMEWORK_HAS_MM_IOVEC
457 /*
458 * It is a fatal error if the input vector has already been mapped using
459 * psa_map_invec().
460 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800461 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800462 tfm_core_panic();
463 }
464
Mingyang Suna09adda2022-02-16 18:11:33 +0800465 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800466#endif
467
Kevin Peng016b0e42022-04-15 11:28:48 +0800468 /* There was no remaining data in this input vector */
469 if (handle->msg.in_size[invec_idx] == 0) {
470 return 0;
471 }
472
Mingyang Sunb26b2802021-07-07 11:25:00 +0800473 /*
474 * If num_bytes is greater than the remaining size of the input vector then
475 * the remaining size of the input vector is used.
476 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800477 if (num_bytes > handle->msg.in_size[invec_idx]) {
478 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800479 }
480
481 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800482 handle->invec[invec_idx].base =
483 (char *)handle->invec[invec_idx].base + num_bytes;
484 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800485
486 return num_bytes;
487}
488
489void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
490 const void *buffer, size_t num_bytes)
491{
Mingyang Suna09adda2022-02-16 18:11:33 +0800492 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800493 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800494 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800495
496 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800497 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800498 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800499 tfm_core_panic();
500 }
501
Mingyang Sunb26b2802021-07-07 11:25:00 +0800502 /*
503 * It is a fatal error if message handle does not refer to a request
504 * message
505 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800506 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800507 tfm_core_panic();
508 }
509
510 /*
511 * It is a fatal error if outvec_idx is equal to or greater than
512 * PSA_MAX_IOVEC
513 */
514 if (outvec_idx >= PSA_MAX_IOVEC) {
515 tfm_core_panic();
516 }
517
518 /*
519 * It is a fatal error if the call attempts to write data past the end of
520 * the client output vector
521 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800522 if (num_bytes > handle->msg.out_size[outvec_idx] -
523 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800524 tfm_core_panic();
525 }
526
Shawn Shan038348e2021-09-08 17:11:04 +0800527#if PSA_FRAMEWORK_HAS_MM_IOVEC
528 /*
529 * It is a fatal error if the output vector has already been mapped using
530 * psa_map_outvec().
531 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800532 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800533 tfm_core_panic();
534 }
535
Mingyang Suna09adda2022-02-16 18:11:33 +0800536 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800537#endif
538
Mingyang Sunb26b2802021-07-07 11:25:00 +0800539 /*
540 * Copy the service buffer to client outvecs. It is a fatal error
541 * if the memory reference for buffer is invalid or not readable.
542 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800543 FIH_CALL(tfm_hal_memory_check, fih_rc,
544 curr_partition->boundary, (uintptr_t)buffer,
545 num_bytes, TFM_HAL_ACCESS_READABLE);
546 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800547 tfm_core_panic();
548 }
549
Mingyang Suna09adda2022-02-16 18:11:33 +0800550 spm_memcpy((char *)handle->outvec[outvec_idx].base +
551 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800552
553 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800554 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800555}
556
Ken Liuf8c7e532022-02-10 15:03:04 +0800557psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
558 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800559{
Ken Liu0bed7e02022-02-10 12:38:07 +0800560 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800561 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800562 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800563 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800564
565 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800566 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800567 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800568 tfm_core_panic();
569 }
570
571 /*
572 * RoT Service information is needed in this function, stored it in message
573 * body structure. Only two parameters are passed in this function: handle
574 * and status, so it is useful and simply to do like this.
575 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800576 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800577 if (!service) {
578 tfm_core_panic();
579 }
580
Mingyang Suna09adda2022-02-16 18:11:33 +0800581 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800582 case PSA_IPC_CONNECT:
583 /*
584 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
585 * input status is PSA_SUCCESS. Others return values are based on the
586 * input status.
587 */
588 if (status == PSA_SUCCESS) {
589 ret = msg_handle;
590 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
591 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800592 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800593 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800594 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
595 /* Fail the client connection, indicating a transient error. */
596 ret = PSA_ERROR_CONNECTION_BUSY;
597 } else {
598 tfm_core_panic();
599 }
600 break;
601 case PSA_IPC_DISCONNECT:
602 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800603 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800604
605 /*
606 * If the message type is PSA_IPC_DISCONNECT, then the status code is
607 * ignored
608 */
609 break;
610 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800611 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800612
613#if PSA_FRAMEWORK_HAS_MM_IOVEC
614
615 /*
616 * If the unmapped function is not called for an input/output vector
617 * that has been mapped, the framework will remove the mapping.
618 */
619 int i;
620
621 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800622 if (IOVEC_IS_MAPPED(handle, i) &&
623 (!IOVEC_IS_UNMAPPED(handle, i))) {
624 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800625 /*
626 * Any output vectors that are still mapped will report that
627 * zero bytes have been written.
628 */
629 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800630 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800631 }
632 }
633 }
634
635#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800636 /* Reply to a request message. Return values are based on status */
637 ret = status;
638 /*
639 * The total number of bytes written to a single parameter must be
640 * reported to the client by updating the len member of the
641 * psa_outvec structure for the parameter before returning from
642 * psa_call().
643 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800644 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800645 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800646 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800647 }
648 } else {
649 tfm_core_panic();
650 }
651 }
652
653 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
654 /*
655 * If the source of the programmer error is a Secure Partition, the SPM
656 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
657 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800658 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800659 tfm_core_panic();
660 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800661 }
662
Mingyang Sun620c8562021-11-10 11:44:58 +0800663 /*
664 * TODO: It can be optimized further by moving critical section protection
665 * to mailbox. Also need to check implementation when secure context is
666 * involved.
667 */
668 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu995a9742022-05-18 19:28:30 +0800669 ret = backend_replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800670 CRITICAL_SECTION_LEAVE(cs_assert);
671
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800672 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
673 tfm_spm_free_conn_handle(handle);
674 } else {
675 handle->status = TFM_HANDLE_STATUS_IDLE;
676 }
677
Mingyang Sun620c8562021-11-10 11:44:58 +0800678 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800679}
680
Kevin Peng613b4172022-02-15 14:41:44 +0800681#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800682void tfm_spm_partition_psa_notify(int32_t partition_id)
683{
Ken Liu5d73c872021-08-19 19:23:17 +0800684 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
685
686 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800687}
688
689void tfm_spm_partition_psa_clear(void)
690{
Ken Liu92ede9f2021-10-20 09:35:00 +0800691 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800692 struct partition_t *partition = NULL;
693
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800694 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800695
696 /*
697 * It is a fatal error if the Secure Partition's doorbell signal is not
698 * currently asserted.
699 */
700 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
701 tfm_core_panic();
702 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800703
704 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800705 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800706 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800707}
Kevin Peng613b4172022-02-15 14:41:44 +0800708#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800709
Mingyang Sunb26b2802021-07-07 11:25:00 +0800710void tfm_spm_partition_psa_panic(void)
711{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100712#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
713 tfm_hal_system_halt();
714#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800715 /*
716 * PSA FF recommends that the SPM causes the system to restart when a secure
717 * partition panics.
718 */
719 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100720#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800721}
722
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800723/* psa_set_rhandle is only needed by connection-based services */
724#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
725
726void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
727{
Mingyang Suna09adda2022-02-16 18:11:33 +0800728 struct conn_handle_t *handle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800729
730 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800731 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800732 if (!handle) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800733 tfm_core_panic();
734 }
735
736 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800737 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800738 tfm_core_panic();
739 }
740
Mingyang Suna09adda2022-02-16 18:11:33 +0800741 handle->msg.rhandle = rhandle;
742 handle->rhandle = rhandle;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800743}
744
745#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
746
747#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800748void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800749{
750 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700751 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800752
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800753 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800754
755 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
756 if (!irq_info) {
757 tfm_core_panic();
758 }
759
Kevin Pengd399a1f2021-09-08 15:33:14 +0800760 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800761}
762
Kevin Peng67a89fd2021-11-25 11:22:02 +0800763psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800764{
765 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700766 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800767
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800768 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800769
770 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
771 if (!irq_info) {
772 tfm_core_panic();
773 }
774
Kevin Pengd399a1f2021-09-08 15:33:14 +0800775 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800776
777 return 1;
778}
779
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800780/* This API is only used for FLIH. */
781#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800782void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
783{
Ken Liu92ede9f2021-10-20 09:35:00 +0800784 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700785 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800786 struct partition_t *partition;
787
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800788 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800789
790 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
791 if (!irq_info) {
792 tfm_core_panic();
793 }
794
795 if (!irq_info->flih_func) {
796 /* This API is for FLIH IRQs only */
797 tfm_core_panic();
798 }
799
800 if ((partition->signals_asserted & irq_signal) == 0) {
801 /* The signal is not asserted */
802 tfm_core_panic();
803 }
804
Ken Liu92ede9f2021-10-20 09:35:00 +0800805 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800806 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800807 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800808}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800809#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800810
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800811/* This API is only used for SLIH. */
812#if CONFIG_TFM_SLIH_API == 1
813void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800814{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800815 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700816 const struct irq_load_info_t *irq_info = NULL;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800817 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800818
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800819 partition = GET_CURRENT_COMPONENT();
820
821 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
822 /* It is a fatal error if passed signal is not an interrupt signal. */
823 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800824 tfm_core_panic();
825 }
826
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800827 if (irq_info->flih_func) {
828 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800829 tfm_core_panic();
830 }
831
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800832 /* It is a fatal error if passed signal is not currently asserted */
833 if ((partition->signals_asserted & irq_signal) == 0) {
834 tfm_core_panic();
835 }
836
837 CRITICAL_SECTION_ENTER(cs_assert);
838 partition->signals_asserted &= ~irq_signal;
839 CRITICAL_SECTION_LEAVE(cs_assert);
840
841 tfm_hal_irq_clear_pending(irq_info->source);
842 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800843}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800844#endif
845#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800846
Shawn Shan038348e2021-09-08 17:11:04 +0800847#if PSA_FRAMEWORK_HAS_MM_IOVEC
848
849const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
850 uint32_t invec_idx)
851{
Mingyang Suna09adda2022-02-16 18:11:33 +0800852 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800853 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800854 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +0800855
856 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800857 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800858 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800859 tfm_core_panic();
860 }
861
Mingyang Suna09adda2022-02-16 18:11:33 +0800862 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +0800863
864 /*
865 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
866 * Service that received the message.
867 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800868 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800869 tfm_core_panic();
870 }
871
872 /*
873 * It is a fatal error if message handle does not refer to a request
874 * message.
875 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800876 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800877 tfm_core_panic();
878 }
879
880 /*
881 * It is a fatal error if invec_idx is equal to or greater than
882 * PSA_MAX_IOVEC.
883 */
884 if (invec_idx >= PSA_MAX_IOVEC) {
885 tfm_core_panic();
886 }
887
888 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800889 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +0800890 tfm_core_panic();
891 }
892
893 /*
894 * It is a fatal error if the input vector has already been mapped using
895 * psa_map_invec().
896 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800897 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800898 tfm_core_panic();
899 }
900
901 /*
902 * It is a fatal error if the input vector has already been accessed
903 * using psa_read() or psa_skip().
904 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800905 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800906 tfm_core_panic();
907 }
908
909 /*
910 * It is a fatal error if the memory reference for the wrap input vector is
911 * invalid or not readable.
912 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800913 FIH_CALL(tfm_hal_memory_check, fih_rc,
914 partition->boundary, (uintptr_t)handle->invec[invec_idx].base,
915 handle->invec[invec_idx].len, TFM_HAL_ACCESS_READABLE);
916 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800917 tfm_core_panic();
918 }
919
Mingyang Suna09adda2022-02-16 18:11:33 +0800920 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800921
Mingyang Suna09adda2022-02-16 18:11:33 +0800922 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +0800923}
924
925void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
926 uint32_t invec_idx)
927{
Mingyang Suna09adda2022-02-16 18:11:33 +0800928 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800929
930 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800931 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800932 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800933 tfm_core_panic();
934 }
935
936 /*
937 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
938 * Service that received the message.
939 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800940 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800941 tfm_core_panic();
942 }
943
944 /*
945 * It is a fatal error if message handle does not refer to a request
946 * message.
947 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800948 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800949 tfm_core_panic();
950 }
951
952 /*
953 * It is a fatal error if invec_idx is equal to or greater than
954 * PSA_MAX_IOVEC.
955 */
956 if (invec_idx >= PSA_MAX_IOVEC) {
957 tfm_core_panic();
958 }
959
960 /*
961 * It is a fatal error if The input vector has not been mapped by a call to
962 * psa_map_invec().
963 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800964 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800965 tfm_core_panic();
966 }
967
968 /*
969 * It is a fatal error if the input vector has already been unmapped by a
970 * call to psa_unmap_invec().
971 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800972 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800973 tfm_core_panic();
974 }
975
Mingyang Suna09adda2022-02-16 18:11:33 +0800976 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800977}
978
979void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
980 uint32_t outvec_idx)
981{
Mingyang Suna09adda2022-02-16 18:11:33 +0800982 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800983 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800984 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +0800985
986 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800987 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800988 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800989 tfm_core_panic();
990 }
991
Mingyang Suna09adda2022-02-16 18:11:33 +0800992 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +0800993
994 /*
995 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
996 * Service that received the message.
997 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800998 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800999 tfm_core_panic();
1000 }
1001
1002 /*
1003 * It is a fatal error if message handle does not refer to a request
1004 * message.
1005 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001006 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001007 tfm_core_panic();
1008 }
1009
1010 /*
1011 * It is a fatal error if outvec_idx is equal to or greater than
1012 * PSA_MAX_IOVEC.
1013 */
1014 if (outvec_idx >= PSA_MAX_IOVEC) {
1015 tfm_core_panic();
1016 }
1017
1018 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +08001019 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001020 tfm_core_panic();
1021 }
1022
1023 /*
1024 * It is a fatal error if the output vector has already been mapped using
1025 * psa_map_outvec().
1026 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001027 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001028 tfm_core_panic();
1029 }
1030
1031 /*
1032 * It is a fatal error if the output vector has already been accessed
1033 * using psa_write().
1034 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001035 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001036 tfm_core_panic();
1037 }
1038
1039 /*
1040 * It is a fatal error if the output vector is invalid or not read-write.
1041 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +08001042 FIH_CALL(tfm_hal_memory_check, fih_rc,
1043 partition->boundary, (uintptr_t)handle->outvec[outvec_idx].base,
1044 handle->outvec[outvec_idx].len, TFM_HAL_ACCESS_READWRITE);
1045 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001046 tfm_core_panic();
1047 }
Mingyang Suna09adda2022-02-16 18:11:33 +08001048 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001049
Mingyang Suna09adda2022-02-16 18:11:33 +08001050 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001051}
1052
1053void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1054 uint32_t outvec_idx, size_t len)
1055{
Mingyang Suna09adda2022-02-16 18:11:33 +08001056 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +08001057
1058 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +08001059 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +08001060 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +08001061 tfm_core_panic();
1062 }
1063
1064 /*
1065 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1066 * Service that received the message.
1067 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001068 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001069 tfm_core_panic();
1070 }
1071
1072 /*
1073 * It is a fatal error if message handle does not refer to a request
1074 * message.
1075 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001076 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001077 tfm_core_panic();
1078 }
1079
1080 /*
1081 * It is a fatal error if outvec_idx is equal to or greater than
1082 * PSA_MAX_IOVEC.
1083 */
1084 if (outvec_idx >= PSA_MAX_IOVEC) {
1085 tfm_core_panic();
1086 }
1087
1088 /*
1089 * It is a fatal error if len is greater than the output vector size.
1090 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001091 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001092 tfm_core_panic();
1093 }
1094
1095 /*
1096 * It is a fatal error if The output vector has not been mapped by a call to
1097 * psa_map_outvec().
1098 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001099 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001100 tfm_core_panic();
1101 }
1102
1103 /*
1104 * It is a fatal error if the output vector has already been unmapped by a
1105 * call to psa_unmap_outvec().
1106 */
Mingyang Suna09adda2022-02-16 18:11:33 +08001107 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001108 tfm_core_panic();
1109 }
1110
Mingyang Suna09adda2022-02-16 18:11:33 +08001111 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001112
1113 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +08001114 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001115}
1116
1117#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */