blob: 80af53fa01312a4dde59b93bacee4d1226c4581f [file] [log] [blame]
David Hu733d8f92019-09-23 15:32:40 +08001/*
Mingyang Sunbb4a42a2021-12-14 15:18:52 +08002 * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
David Hu733d8f92019-09-23 15:32:40 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
Mingyang Suneeca4652021-07-15 15:19:16 +08008#include <stdint.h>
Mingyang Sunb26b2802021-07-07 11:25:00 +08009#include "bitops.h"
Ken Liu92ede9f2021-10-20 09:35:00 +080010#include "critical_section.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080011#include "psa/lifecycle.h"
David Hu733d8f92019-09-23 15:32:40 +080012#include "psa/service.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080013#include "interrupt.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080014#include "spm_ipc.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080015#include "tfm_arch.h"
David Hu733d8f92019-09-23 15:32:40 +080016#include "tfm_core_utils.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080017#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080018#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080019#include "load/interrupt_defs.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080020#include "ffm/psa_api.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080021#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080022#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080023#include "ffm/psa_api.h"
Ken Liubcae38b2021-01-20 15:47:44 +080024#include "ffm/spm_error_base.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080025#include "tfm_rpc.h"
26#include "tfm_spm_hal.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080027#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080028#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080029#include "tfm_psa_call_pack.h"
David Hu733d8f92019-09-23 15:32:40 +080030
Ken Liub3b2cb62021-05-22 00:39:28 +080031#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080032extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080033
Shawn Shan038348e2021-09-08 17:11:04 +080034#if PSA_FRAMEWORK_HAS_MM_IOVEC
35
36/*
37 * The MM-IOVEC status
38 * The max total number of invec and outvec is 8.
39 * Each invec/outvec takes 4 bit, 32 bits in total.
40 *
41 * The encoding format of the MM-IOVEC status:
42 *--------------------------------------------------------------
43 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
44 *--------------------------------------------------------------
45 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
46 *--------------------------------------------------------------
47 *
48 * Take invec[0] as an example:
49 *
50 * bit 0: whether invec[0] has been mapped.
51 * bit 1: whether invec[0] has been unmapped.
52 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
53 * psa_write().
54 * bit 3: reserved for invec[0].
55 */
56
57#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
58#define OUTVEC_IDX_BASE 4 /*
59 * Base index of outvec.
60 * There are four invecs in front of
61 * outvec.
62 */
63#define INVEC_IDX_BASE 0 /* Base index of invec. */
64
65#define IOVEC_MAPPED_BIT (1U << 0)
66#define IOVEC_UNMAPPED_BIT (1U << 1)
67#define IOVEC_ACCESSED_BIT (1U << 2)
68
69#define IOVEC_IS_MAPPED(msg, iovec_idx) \
70 ((((msg)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
71 IOVEC_MAPPED_BIT)
72#define IOVEC_IS_UNMAPPED(msg, iovec_idx) \
73 ((((msg)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
74 IOVEC_UNMAPPED_BIT)
75#define IOVEC_IS_ACCESSED(msg, iovec_idx) \
76 ((((msg)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
77 IOVEC_ACCESSED_BIT)
78#define SET_IOVEC_MAPPED(msg, iovec_idx) \
79 (((msg)->iovec_status) |= (IOVEC_MAPPED_BIT << \
80 ((iovec_idx) * IOVEC_STATUS_BITS)))
81#define SET_IOVEC_UNMAPPED(msg, iovec_idx) \
82 (((msg)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
83 ((iovec_idx) * IOVEC_STATUS_BITS)))
84#define SET_IOVEC_ACCESSED(msg, iovec_idx) \
85 (((msg)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
86 ((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{
92 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
93 status == PSA_ERROR_CONNECTION_REFUSED ||
94 status == PSA_ERROR_CONNECTION_BUSY) {
95 if (!tfm_spm_is_ns_caller()) {
96 tfm_core_panic();
97 }
98 }
99}
100
Mingyang Suneeca4652021-07-15 15:19:16 +0800101uint32_t tfm_spm_get_lifecycle_state(void)
102{
103 /*
104 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
105 * implemented in the future.
106 */
107 return PSA_LIFECYCLE_UNKNOWN;
108}
109
110/* PSA Client API function body */
111
Mingyang Sund44522a2020-01-16 16:48:37 +0800112uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +0800113{
114 return PSA_FRAMEWORK_VERSION;
115}
116
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800117uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +0800118{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800119 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800120 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800121
122 /*
123 * It should return PSA_VERSION_NONE if the RoT Service is not
124 * implemented.
125 */
126 service = tfm_spm_get_service_by_sid(sid);
127 if (!service) {
128 return PSA_VERSION_NONE;
129 }
130
131 /*
Shawn Shan2365c902019-12-19 18:35:36 +0800132 * It should return PSA_VERSION_NONE if the caller is not authorized
133 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +0800134 */
Ken Liubcae38b2021-01-20 15:47:44 +0800135 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +0800136 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +0800137 }
138
Ken Liuacd2a572021-05-12 16:19:04 +0800139 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +0800140}
141
Mingyang Suneeca4652021-07-15 15:19:16 +0800142psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
143 uint32_t ctrl_param,
144 const psa_invec *inptr,
145 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800146{
147 psa_invec invecs[PSA_MAX_IOVEC];
148 psa_outvec outvecs[PSA_MAX_IOVEC];
Ken Liu0bed7e02022-02-10 12:38:07 +0800149 struct conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800150 struct service_t *service;
Summer Qinba2346e2019-11-12 16:26:31 +0800151 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800152 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800153 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800154 uint32_t privileged;
Mingyang Sun620c8562021-11-10 11:44:58 +0800155 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800156 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800157 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
158 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
159 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800160
161 /* The request type must be zero or positive. */
162 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800163 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800164 }
David Hu733d8f92019-09-23 15:32:40 +0800165
Shawn Shanb222d892021-01-04 17:41:48 +0800166 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800167 if ((in_num > PSA_MAX_IOVEC) ||
168 (out_num > PSA_MAX_IOVEC) ||
169 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800170 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800171 }
172
Kevin Peng385fda82021-08-18 10:41:19 +0800173 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800174
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800175 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800176 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800177 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800178
179 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800180 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800181 }
182
Mingyang Sun453ad402021-03-17 17:58:33 +0800183 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800184 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800185 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800186 }
187
Ken Liub3b2cb62021-05-22 00:39:28 +0800188 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800189
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800190 /*
191 * It is a PROGRAMMER ERROR if the caller is not authorized to access
192 * the RoT Service.
193 */
194 if (tfm_spm_check_authorization(sid, service, ns_caller)
195 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800196 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800197 }
198
Mingyang Sun453ad402021-03-17 17:58:33 +0800199 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
200
201 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800202 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800203 }
204
Mingyang Sun620c8562021-11-10 11:44:58 +0800205 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800206 conn_handle = tfm_spm_create_conn_handle(service, client_id);
Mingyang Sun620c8562021-11-10 11:44:58 +0800207 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800208
209 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800210 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800211 }
212
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800213 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800214 handle = tfm_spm_to_user_handle(conn_handle);
215 } else {
216 conn_handle = tfm_spm_to_handle_instance(handle);
217
218 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
219 if (tfm_spm_validate_conn_handle(conn_handle, client_id)
220 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800221 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800222 }
223
224 /*
225 * It is a PROGRAMMER ERROR if the connection is currently
226 * handling a request.
227 */
228 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800229 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800230 }
231
232 /*
233 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
234 * has been terminated by the RoT Service.
235 */
236 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
237 return PSA_ERROR_PROGRAMMER_ERROR;
238 }
239
Ken Liu0bed7e02022-02-10 12:38:07 +0800240 service = conn_handle->service;
Shawn Shanb222d892021-01-04 17:41:48 +0800241
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800242 if (!service) {
243 /* FixMe: Need to implement a mechanism to resolve this failure. */
244 return PSA_ERROR_PROGRAMMER_ERROR;
245 }
David Hu733d8f92019-09-23 15:32:40 +0800246 }
247
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800248 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800249
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 */
255 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800256 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800257 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800258 }
Summer Qinba2346e2019-11-12 16:26:31 +0800259
David Hu733d8f92019-09-23 15:32:40 +0800260 /*
261 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800262 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800263 * the wrap output vector is invalid or not read-write.
264 */
265 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800266 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800267 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800268 }
269
Summer Qinf24dbb52020-07-23 14:53:54 +0800270 spm_memset(invecs, 0, sizeof(invecs));
271 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800272
273 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800274 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
275 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800276
277 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800278 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800279 * memory reference was invalid or not readable.
280 */
281 for (i = 0; i < in_num; i++) {
282 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800283 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800284 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800285 }
286 }
Summer Qinba2346e2019-11-12 16:26:31 +0800287
288 /*
289 * Clients must never overlap input parameters because of the risk of a
290 * double-fetch inconsistency.
291 * Overflow is checked in tfm_memory_check functions.
292 */
293 for (i = 0; i + 1 < in_num; i++) {
294 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100295 if (!((char *) invecs[j].base + invecs[j].len <=
296 (char *) invecs[i].base ||
297 (char *) invecs[j].base >=
298 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800299 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800300 }
301 }
302 }
303
David Hu733d8f92019-09-23 15:32:40 +0800304 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800305 * For client output vector, it is a PROGRAMMER ERROR if the provided
306 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800307 */
308 for (i = 0; i < out_num; i++) {
309 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800310 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800311 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800312 }
313 }
314
Ken Liu0bed7e02022-02-10 12:38:07 +0800315 spm_fill_message(conn_handle, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800316 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800317
Ken Liu0bed7e02022-02-10 12:38:07 +0800318 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800319}
320
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800321/* Following PSA APIs are only needed by connection-based services */
322#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
323
324psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
325{
326 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800327 struct conn_handle_t *connect_handle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800328 int32_t client_id;
329 psa_handle_t handle;
330 bool ns_caller = tfm_spm_is_ns_caller();
331 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
332
333 /*
334 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
335 * platform.
336 */
337 service = tfm_spm_get_service_by_sid(sid);
338 if (!service) {
339 return PSA_ERROR_CONNECTION_REFUSED;
340 }
341
342 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
343 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
344 return PSA_ERROR_PROGRAMMER_ERROR;
345 }
346
347 /*
348 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
349 * RoT Service.
350 */
351 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
352 return PSA_ERROR_CONNECTION_REFUSED;
353 }
354
355 /*
356 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
357 * not supported on the platform.
358 */
359 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
360 return PSA_ERROR_CONNECTION_REFUSED;
361 }
362
363 client_id = tfm_spm_get_client_id(ns_caller);
364
365 /*
366 * Create connection handle here since it is possible to return the error
367 * code to client when creation fails.
368 */
369 CRITICAL_SECTION_ENTER(cs_assert);
370 connect_handle = tfm_spm_create_conn_handle(service, client_id);
371 CRITICAL_SECTION_LEAVE(cs_assert);
372 if (!connect_handle) {
373 return PSA_ERROR_CONNECTION_BUSY;
374 }
375
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800376 handle = tfm_spm_to_user_handle(connect_handle);
377 /* No input or output needed for connect message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800378 spm_fill_message(connect_handle, service, handle, PSA_IPC_CONNECT,
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800379 client_id, NULL, 0, NULL, 0, NULL);
380
Ken Liu0bed7e02022-02-10 12:38:07 +0800381 return backend_instance.messaging(service, connect_handle);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800382}
383
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800384psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800385{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800386 struct service_t *service;
Ken Liu0bed7e02022-02-10 12:38:07 +0800387 struct conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800388 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800389 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800390
391 /* It will have no effect if called with the NULL handle */
392 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800393 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800394 }
395
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800396 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800397 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800398 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800399 }
400
Kevin Peng385fda82021-08-18 10:41:19 +0800401 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800402
Summer Qin373feb12020-03-27 15:35:33 +0800403 conn_handle = tfm_spm_to_handle_instance(handle);
David Hu733d8f92019-09-23 15:32:40 +0800404 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800405 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
406 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800407 */
Ken Liubcae38b2021-01-20 15:47:44 +0800408 if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800409 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800410 }
Shawn Shanb222d892021-01-04 17:41:48 +0800411
Ken Liu0bed7e02022-02-10 12:38:07 +0800412 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800413 if (!service) {
414 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800415 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800416 }
417
Shawn Shanb222d892021-01-04 17:41:48 +0800418 /*
419 * It is a PROGRAMMER ERROR if the connection is currently handling a
420 * request.
421 */
Summer Qin630c76b2020-05-20 10:32:58 +0800422 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800423 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800424 }
425
David Hu733d8f92019-09-23 15:32:40 +0800426 /* No input or output needed for close message */
Ken Liu0bed7e02022-02-10 12:38:07 +0800427 spm_fill_message(conn_handle, service, handle, PSA_IPC_DISCONNECT,
428 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800429
Ken Liu0bed7e02022-02-10 12:38:07 +0800430 return backend_instance.messaging(service, conn_handle);
David Hu733d8f92019-09-23 15:32:40 +0800431}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800432
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800433#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
434
Mingyang Suneeca4652021-07-15 15:19:16 +0800435/* PSA Partition API function body */
436
Mingyang Sunb26b2802021-07-07 11:25:00 +0800437psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
438 uint32_t timeout)
439{
440 struct partition_t *partition = NULL;
441
442 /*
443 * Timeout[30:0] are reserved for future use.
444 * SPM must ignore the value of RES.
445 */
446 timeout &= PSA_TIMEOUT_MASK;
447
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800448 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800449
450 /*
451 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
452 * signals.
453 */
454 if ((partition->signals_allowed & signal_mask) == 0) {
455 tfm_core_panic();
456 }
457
458 /*
Ken Liu5d73c872021-08-19 19:23:17 +0800459 * thrd_wait_on() blocks the caller thread if no signals are available.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800460 * In this case, the return value of this function is temporary set into
461 * runtime context. After new signal(s) are available, the return value
462 * is updated with the available signal(s) and blocked thread gets to run.
463 */
464 if (timeout == PSA_BLOCK &&
465 (partition->signals_asserted & signal_mask) == 0) {
466 partition->signals_waiting = signal_mask;
Ken Liuf39d8eb2021-10-07 12:55:33 +0800467 thrd_wait_on(&partition->waitobj, CURRENT_THREAD);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800468 }
469
470 return partition->signals_asserted & signal_mask;
471}
472
473psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
474{
Ken Liu0bed7e02022-02-10 12:38:07 +0800475 struct conn_handle_t *tmp_msg = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800476 struct partition_t *partition = NULL;
477 uint32_t privileged;
478
479 /*
480 * Only one message could be retrieved every time for psa_get(). It is a
481 * fatal error if the input signal has more than a signal bit set.
482 */
483 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
484 tfm_core_panic();
485 }
486
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800487 partition = GET_CURRENT_COMPONENT();
488
Kevin Penga40d29f2022-01-19 14:44:34 +0800489 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800490
491 /*
492 * Write the message to the service buffer. It is a fatal error if the
493 * input msg pointer is not a valid memory reference or not read-write.
494 */
495 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
496 privileged) != SPM_SUCCESS) {
497 tfm_core_panic();
498 }
499
500 /*
501 * It is a fatal error if the caller call psa_get() when no message has
502 * been set. The caller must call this function after an RoT Service signal
503 * is returned by psa_wait().
504 */
505 if (partition->signals_asserted == 0) {
506 tfm_core_panic();
507 }
508
509 /*
510 * It is a fatal error if the RoT Service signal is not currently asserted.
511 */
512 if ((partition->signals_asserted & signal) == 0) {
513 tfm_core_panic();
514 }
515
516 /*
517 * Get message by signal from partition. It is a fatal error if getting
518 * failed, which means the input signal is not correspond to an RoT service.
519 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800520 tmp_msg = spm_get_handle_by_signal(partition, signal);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800521 if (!tmp_msg) {
522 return PSA_ERROR_DOES_NOT_EXIST;
523 }
524
Ken Liu0bed7e02022-02-10 12:38:07 +0800525 tmp_msg->status = TFM_HANDLE_STATUS_ACTIVE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800526
527 spm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t));
528
529 return PSA_SUCCESS;
530}
531
Mingyang Sunb26b2802021-07-07 11:25:00 +0800532size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
533 void *buffer, size_t num_bytes)
534{
535 size_t bytes;
Ken Liu0bed7e02022-02-10 12:38:07 +0800536 struct conn_handle_t *msg = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800537 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800538
539 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800540 msg = spm_get_handle_by_user_handle(msg_handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800541 if (!msg) {
542 tfm_core_panic();
543 }
544
Kevin Penga40d29f2022-01-19 14:44:34 +0800545 priv_mode = GET_PARTITION_PRIVILEGED_MODE(msg->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800546
547 /*
548 * It is a fatal error if message handle does not refer to a request
549 * message
550 */
551 if (msg->msg.type < PSA_IPC_CALL) {
552 tfm_core_panic();
553 }
554
555 /*
556 * It is a fatal error if invec_idx is equal to or greater than
557 * PSA_MAX_IOVEC
558 */
559 if (invec_idx >= PSA_MAX_IOVEC) {
560 tfm_core_panic();
561 }
562
563 /* There was no remaining data in this input vector */
564 if (msg->msg.in_size[invec_idx] == 0) {
565 return 0;
566 }
567
Shawn Shan038348e2021-09-08 17:11:04 +0800568#if PSA_FRAMEWORK_HAS_MM_IOVEC
569 /*
570 * It is a fatal error if the input vector has already been mapped using
571 * psa_map_invec().
572 */
573 if (IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
574 tfm_core_panic();
575 }
576
577 SET_IOVEC_ACCESSED(msg, (invec_idx + INVEC_IDX_BASE));
578#endif
579
Mingyang Sunb26b2802021-07-07 11:25:00 +0800580 /*
581 * Copy the client data to the service buffer. It is a fatal error
582 * if the memory reference for buffer is invalid or not read-write.
583 */
584 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800585 TFM_MEMORY_ACCESS_RW, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800586 tfm_core_panic();
587 }
588
589 bytes = num_bytes > msg->msg.in_size[invec_idx] ?
590 msg->msg.in_size[invec_idx] : num_bytes;
591
592 spm_memcpy(buffer, msg->invec[invec_idx].base, bytes);
593
594 /* There maybe some remaining data */
595 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base + bytes;
596 msg->msg.in_size[invec_idx] -= bytes;
597
598 return bytes;
599}
600
601size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
602 size_t num_bytes)
603{
Ken Liu0bed7e02022-02-10 12:38:07 +0800604 struct conn_handle_t *msg = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800605
606 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800607 msg = spm_get_handle_by_user_handle(msg_handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800608 if (!msg) {
609 tfm_core_panic();
610 }
611
612 /*
613 * It is a fatal error if message handle does not refer to a request
614 * message
615 */
616 if (msg->msg.type < PSA_IPC_CALL) {
617 tfm_core_panic();
618 }
619
620 /*
621 * It is a fatal error if invec_idx is equal to or greater than
622 * PSA_MAX_IOVEC
623 */
624 if (invec_idx >= PSA_MAX_IOVEC) {
625 tfm_core_panic();
626 }
627
628 /* There was no remaining data in this input vector */
629 if (msg->msg.in_size[invec_idx] == 0) {
630 return 0;
631 }
632
Shawn Shan038348e2021-09-08 17:11:04 +0800633#if PSA_FRAMEWORK_HAS_MM_IOVEC
634 /*
635 * It is a fatal error if the input vector has already been mapped using
636 * psa_map_invec().
637 */
638 if (IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
639 tfm_core_panic();
640 }
641
642 SET_IOVEC_ACCESSED(msg, (invec_idx + INVEC_IDX_BASE));
643#endif
644
Mingyang Sunb26b2802021-07-07 11:25:00 +0800645 /*
646 * If num_bytes is greater than the remaining size of the input vector then
647 * the remaining size of the input vector is used.
648 */
649 if (num_bytes > msg->msg.in_size[invec_idx]) {
650 num_bytes = msg->msg.in_size[invec_idx];
651 }
652
653 /* There maybe some remaining data */
654 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base +
655 num_bytes;
656 msg->msg.in_size[invec_idx] -= num_bytes;
657
658 return num_bytes;
659}
660
661void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
662 const void *buffer, size_t num_bytes)
663{
Ken Liu0bed7e02022-02-10 12:38:07 +0800664 struct conn_handle_t *msg = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800665 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800666
667 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800668 msg = spm_get_handle_by_user_handle(msg_handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800669 if (!msg) {
670 tfm_core_panic();
671 }
672
Kevin Penga40d29f2022-01-19 14:44:34 +0800673 priv_mode = GET_PARTITION_PRIVILEGED_MODE(msg->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800674
675 /*
676 * It is a fatal error if message handle does not refer to a request
677 * message
678 */
679 if (msg->msg.type < PSA_IPC_CALL) {
680 tfm_core_panic();
681 }
682
683 /*
684 * It is a fatal error if outvec_idx is equal to or greater than
685 * PSA_MAX_IOVEC
686 */
687 if (outvec_idx >= PSA_MAX_IOVEC) {
688 tfm_core_panic();
689 }
690
691 /*
692 * It is a fatal error if the call attempts to write data past the end of
693 * the client output vector
694 */
695 if (num_bytes > msg->msg.out_size[outvec_idx] -
696 msg->outvec[outvec_idx].len) {
697 tfm_core_panic();
698 }
699
Shawn Shan038348e2021-09-08 17:11:04 +0800700#if PSA_FRAMEWORK_HAS_MM_IOVEC
701 /*
702 * It is a fatal error if the output vector has already been mapped using
703 * psa_map_outvec().
704 */
705 if (IOVEC_IS_MAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE))) {
706 tfm_core_panic();
707 }
708
709 SET_IOVEC_ACCESSED(msg, (outvec_idx + OUTVEC_IDX_BASE));
710#endif
711
Mingyang Sunb26b2802021-07-07 11:25:00 +0800712 /*
713 * Copy the service buffer to client outvecs. It is a fatal error
714 * if the memory reference for buffer is invalid or not readable.
715 */
716 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800717 TFM_MEMORY_ACCESS_RO, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800718 tfm_core_panic();
719 }
720
721 spm_memcpy((char *)msg->outvec[outvec_idx].base +
722 msg->outvec[outvec_idx].len, buffer, num_bytes);
723
724 /* Update the write number */
725 msg->outvec[outvec_idx].len += num_bytes;
726}
727
Ken Liuf39d8eb2021-10-07 12:55:33 +0800728int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
729 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800730{
Ken Liu0bed7e02022-02-10 12:38:07 +0800731 struct service_t *service;
732 struct conn_handle_t *hdl;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800733 int32_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800734 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800735
736 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800737 hdl = spm_get_handle_by_user_handle(msg_handle);
738 if (!hdl) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800739 tfm_core_panic();
740 }
741
742 /*
743 * RoT Service information is needed in this function, stored it in message
744 * body structure. Only two parameters are passed in this function: handle
745 * and status, so it is useful and simply to do like this.
746 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800747 service = hdl->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800748 if (!service) {
749 tfm_core_panic();
750 }
751
Ken Liu0bed7e02022-02-10 12:38:07 +0800752 switch (hdl->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800753 case PSA_IPC_CONNECT:
754 /*
755 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
756 * input status is PSA_SUCCESS. Others return values are based on the
757 * input status.
758 */
759 if (status == PSA_SUCCESS) {
760 ret = msg_handle;
761 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
762 /* Refuse the client connection, indicating a permanent error. */
Ken Liu0bed7e02022-02-10 12:38:07 +0800763 tfm_spm_free_conn_handle(service, hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800764 ret = PSA_ERROR_CONNECTION_REFUSED;
765 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
766 /* Fail the client connection, indicating a transient error. */
767 ret = PSA_ERROR_CONNECTION_BUSY;
768 } else {
769 tfm_core_panic();
770 }
771 break;
772 case PSA_IPC_DISCONNECT:
773 /* Service handle is not used anymore */
Ken Liu0bed7e02022-02-10 12:38:07 +0800774 tfm_spm_free_conn_handle(service, hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800775
776 /*
777 * If the message type is PSA_IPC_DISCONNECT, then the status code is
778 * ignored
779 */
780 break;
781 default:
Ken Liu0bed7e02022-02-10 12:38:07 +0800782 if (hdl->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800783
784#if PSA_FRAMEWORK_HAS_MM_IOVEC
785
786 /*
787 * If the unmapped function is not called for an input/output vector
788 * that has been mapped, the framework will remove the mapping.
789 */
790 int i;
791
792 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Ken Liu0bed7e02022-02-10 12:38:07 +0800793 if (IOVEC_IS_MAPPED(hdl, i) && (!IOVEC_IS_UNMAPPED(hdl, i))) {
794 SET_IOVEC_UNMAPPED(hdl, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800795 /*
796 * Any output vectors that are still mapped will report that
797 * zero bytes have been written.
798 */
799 if (i >= OUTVEC_IDX_BASE) {
Ken Liu0bed7e02022-02-10 12:38:07 +0800800 hdl->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800801 }
802 }
803 }
804
805#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800806 /* Reply to a request message. Return values are based on status */
807 ret = status;
808 /*
809 * The total number of bytes written to a single parameter must be
810 * reported to the client by updating the len member of the
811 * psa_outvec structure for the parameter before returning from
812 * psa_call().
813 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800814 update_caller_outvec_len(hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800815 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Ken Liu0bed7e02022-02-10 12:38:07 +0800816 tfm_spm_free_conn_handle(service, hdl);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800817 }
818 } else {
819 tfm_core_panic();
820 }
821 }
822
823 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
824 /*
825 * If the source of the programmer error is a Secure Partition, the SPM
826 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
827 */
Ken Liu0bed7e02022-02-10 12:38:07 +0800828 if (TFM_CLIENT_ID_IS_NS(hdl->msg.client_id)) {
829 hdl->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800830 } else {
831 tfm_core_panic();
832 }
833 } else {
Ken Liu0bed7e02022-02-10 12:38:07 +0800834 hdl->status = TFM_HANDLE_STATUS_IDLE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800835 }
836
Mingyang Sun620c8562021-11-10 11:44:58 +0800837 /*
838 * TODO: It can be optimized further by moving critical section protection
839 * to mailbox. Also need to check implementation when secure context is
840 * involved.
841 */
842 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu0bed7e02022-02-10 12:38:07 +0800843 ret = backend_instance.replying(hdl, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800844 CRITICAL_SECTION_LEAVE(cs_assert);
845
846 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800847}
848
849void tfm_spm_partition_psa_notify(int32_t partition_id)
850{
Ken Liu5d73c872021-08-19 19:23:17 +0800851 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
852
853 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800854}
855
856void tfm_spm_partition_psa_clear(void)
857{
Ken Liu92ede9f2021-10-20 09:35:00 +0800858 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800859 struct partition_t *partition = NULL;
860
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800861 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800862
863 /*
864 * It is a fatal error if the Secure Partition's doorbell signal is not
865 * currently asserted.
866 */
867 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
868 tfm_core_panic();
869 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800870
871 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800872 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800873 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800874}
875
876void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
877{
Ken Liu92ede9f2021-10-20 09:35:00 +0800878 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800879 struct irq_load_info_t *irq_info = NULL;
880 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 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
885 /* It is a fatal error if passed signal is not an interrupt signal. */
886 if (!irq_info) {
887 tfm_core_panic();
888 }
889
890 if (irq_info->flih_func) {
891 /* This API is for SLIH IRQs only */
Ken Liuf39d8eb2021-10-07 12:55:33 +0800892 tfm_core_panic();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800893 }
894
895 /* It is a fatal error if passed signal is not currently asserted */
896 if ((partition->signals_asserted & irq_signal) == 0) {
897 tfm_core_panic();
898 }
899
Ken Liu92ede9f2021-10-20 09:35:00 +0800900 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800901 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800902 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800903
Kevin Pengd399a1f2021-09-08 15:33:14 +0800904 tfm_hal_irq_clear_pending(irq_info->source);
905 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800906}
907
908void tfm_spm_partition_psa_panic(void)
909{
910 /*
911 * PSA FF recommends that the SPM causes the system to restart when a secure
912 * partition panics.
913 */
914 tfm_hal_system_reset();
915}
916
Kevin Peng67a89fd2021-11-25 11:22:02 +0800917void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800918{
919 struct partition_t *partition;
920 struct irq_load_info_t *irq_info;
921
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800922 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800923
924 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
925 if (!irq_info) {
926 tfm_core_panic();
927 }
928
Kevin Pengd399a1f2021-09-08 15:33:14 +0800929 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800930}
931
Kevin Peng67a89fd2021-11-25 11:22:02 +0800932psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800933{
934 struct partition_t *partition;
935 struct irq_load_info_t *irq_info;
936
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800937 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800938
939 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
940 if (!irq_info) {
941 tfm_core_panic();
942 }
943
Kevin Pengd399a1f2021-09-08 15:33:14 +0800944 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800945
946 return 1;
947}
948
949void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
950{
Ken Liu92ede9f2021-10-20 09:35:00 +0800951 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800952 struct irq_load_info_t *irq_info;
953 struct partition_t *partition;
954
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800955 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800956
957 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
958 if (!irq_info) {
959 tfm_core_panic();
960 }
961
962 if (!irq_info->flih_func) {
963 /* This API is for FLIH IRQs only */
964 tfm_core_panic();
965 }
966
967 if ((partition->signals_asserted & irq_signal) == 0) {
968 /* The signal is not asserted */
969 tfm_core_panic();
970 }
971
Ken Liu92ede9f2021-10-20 09:35:00 +0800972 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800973 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800974 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800975}
Shawn Shan038348e2021-09-08 17:11:04 +0800976
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800977/* psa_set_rhandle is only needed by connection-based services */
978#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
979
980void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
981{
Ken Liu0bed7e02022-02-10 12:38:07 +0800982 struct conn_handle_t *hdl;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800983
984 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +0800985 hdl = spm_get_handle_by_user_handle(msg_handle);
986 if (!hdl) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800987 tfm_core_panic();
988 }
989
990 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
Ken Liu0bed7e02022-02-10 12:38:07 +0800991 if (SERVICE_IS_STATELESS(hdl->service->p_ldinf->flags)) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800992 tfm_core_panic();
993 }
994
Ken Liu0bed7e02022-02-10 12:38:07 +0800995 hdl->msg.rhandle = rhandle;
996 hdl->rhandle = rhandle;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800997}
998
999#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
1000
Shawn Shan038348e2021-09-08 17:11:04 +08001001#if PSA_FRAMEWORK_HAS_MM_IOVEC
1002
1003const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1004 uint32_t invec_idx)
1005{
Ken Liu0bed7e02022-02-10 12:38:07 +08001006 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001007 uint32_t privileged;
1008 struct partition_t *partition = NULL;
1009
1010 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001011 hdl = spm_get_handle_by_user_handle(msg_handle);
1012 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001013 tfm_core_panic();
1014 }
1015
Ken Liu0bed7e02022-02-10 12:38:07 +08001016 partition = hdl->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001017 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001018
1019 /*
1020 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1021 * Service that received the message.
1022 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001023 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001024 tfm_core_panic();
1025 }
1026
1027 /*
1028 * It is a fatal error if message handle does not refer to a request
1029 * message.
1030 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001031 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001032 tfm_core_panic();
1033 }
1034
1035 /*
1036 * It is a fatal error if invec_idx is equal to or greater than
1037 * PSA_MAX_IOVEC.
1038 */
1039 if (invec_idx >= PSA_MAX_IOVEC) {
1040 tfm_core_panic();
1041 }
1042
1043 /* It is a fatal error if the input vector has length zero. */
Ken Liu0bed7e02022-02-10 12:38:07 +08001044 if (hdl->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001045 tfm_core_panic();
1046 }
1047
1048 /*
1049 * It is a fatal error if the input vector has already been mapped using
1050 * psa_map_invec().
1051 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001052 if (IOVEC_IS_MAPPED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001053 tfm_core_panic();
1054 }
1055
1056 /*
1057 * It is a fatal error if the input vector has already been accessed
1058 * using psa_read() or psa_skip().
1059 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001060 if (IOVEC_IS_ACCESSED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001061 tfm_core_panic();
1062 }
1063
1064 /*
1065 * It is a fatal error if the memory reference for the wrap input vector is
1066 * invalid or not readable.
1067 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001068 if (tfm_memory_check(hdl->invec[invec_idx].base, hdl->invec[invec_idx].len,
Shawn Shan038348e2021-09-08 17:11:04 +08001069 false, TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
1070 tfm_core_panic();
1071 }
1072
Ken Liu0bed7e02022-02-10 12:38:07 +08001073 SET_IOVEC_MAPPED(hdl, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001074
Ken Liu0bed7e02022-02-10 12:38:07 +08001075 return hdl->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001076}
1077
1078void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1079 uint32_t invec_idx)
1080{
Ken Liu0bed7e02022-02-10 12:38:07 +08001081 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001082
1083 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001084 hdl = spm_get_handle_by_user_handle(msg_handle);
1085 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001086 tfm_core_panic();
1087 }
1088
1089 /*
1090 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1091 * Service that received the message.
1092 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001093 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001094 tfm_core_panic();
1095 }
1096
1097 /*
1098 * It is a fatal error if message handle does not refer to a request
1099 * message.
1100 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001101 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001102 tfm_core_panic();
1103 }
1104
1105 /*
1106 * It is a fatal error if invec_idx is equal to or greater than
1107 * PSA_MAX_IOVEC.
1108 */
1109 if (invec_idx >= PSA_MAX_IOVEC) {
1110 tfm_core_panic();
1111 }
1112
1113 /*
1114 * It is a fatal error if The input vector has not been mapped by a call to
1115 * psa_map_invec().
1116 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001117 if (!IOVEC_IS_MAPPED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001118 tfm_core_panic();
1119 }
1120
1121 /*
1122 * It is a fatal error if the input vector has already been unmapped by a
1123 * call to psa_unmap_invec().
1124 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001125 if (IOVEC_IS_UNMAPPED(hdl, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001126 tfm_core_panic();
1127 }
1128
Ken Liu0bed7e02022-02-10 12:38:07 +08001129 SET_IOVEC_UNMAPPED(hdl, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001130}
1131
1132void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1133 uint32_t outvec_idx)
1134{
Ken Liu0bed7e02022-02-10 12:38:07 +08001135 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001136 uint32_t privileged;
1137 struct partition_t *partition = NULL;
1138
1139 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001140 hdl = spm_get_handle_by_user_handle(msg_handle);
1141 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001142 tfm_core_panic();
1143 }
1144
Ken Liu0bed7e02022-02-10 12:38:07 +08001145 partition = hdl->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001146 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001147
1148 /*
1149 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1150 * Service that received the message.
1151 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001152 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001153 tfm_core_panic();
1154 }
1155
1156 /*
1157 * It is a fatal error if message handle does not refer to a request
1158 * message.
1159 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001160 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001161 tfm_core_panic();
1162 }
1163
1164 /*
1165 * It is a fatal error if outvec_idx is equal to or greater than
1166 * PSA_MAX_IOVEC.
1167 */
1168 if (outvec_idx >= PSA_MAX_IOVEC) {
1169 tfm_core_panic();
1170 }
1171
1172 /* It is a fatal error if the output vector has length zero. */
Ken Liu0bed7e02022-02-10 12:38:07 +08001173 if (hdl->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +08001174 tfm_core_panic();
1175 }
1176
1177 /*
1178 * It is a fatal error if the output vector has already been mapped using
1179 * psa_map_outvec().
1180 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001181 if (IOVEC_IS_MAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001182 tfm_core_panic();
1183 }
1184
1185 /*
1186 * It is a fatal error if the output vector has already been accessed
1187 * using psa_write().
1188 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001189 if (IOVEC_IS_ACCESSED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001190 tfm_core_panic();
1191 }
1192
1193 /*
1194 * It is a fatal error if the output vector is invalid or not read-write.
1195 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001196 if (tfm_memory_check(hdl->outvec[outvec_idx].base,
1197 hdl->outvec[outvec_idx].len, false,
Shawn Shan038348e2021-09-08 17:11:04 +08001198 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
1199 tfm_core_panic();
1200 }
Ken Liu0bed7e02022-02-10 12:38:07 +08001201 SET_IOVEC_MAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001202
Ken Liu0bed7e02022-02-10 12:38:07 +08001203 return hdl->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +08001204}
1205
1206void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1207 uint32_t outvec_idx, size_t len)
1208{
Ken Liu0bed7e02022-02-10 12:38:07 +08001209 struct conn_handle_t *hdl;
Shawn Shan038348e2021-09-08 17:11:04 +08001210
1211 /* It is a fatal error if message handle is invalid */
Ken Liu0bed7e02022-02-10 12:38:07 +08001212 hdl = spm_get_handle_by_user_handle(msg_handle);
1213 if (!hdl) {
Shawn Shan038348e2021-09-08 17:11:04 +08001214 tfm_core_panic();
1215 }
1216
1217 /*
1218 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1219 * Service that received the message.
1220 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001221 if (!SERVICE_ENABLED_MM_IOVEC(hdl->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +08001222 tfm_core_panic();
1223 }
1224
1225 /*
1226 * It is a fatal error if message handle does not refer to a request
1227 * message.
1228 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001229 if (hdl->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +08001230 tfm_core_panic();
1231 }
1232
1233 /*
1234 * It is a fatal error if outvec_idx is equal to or greater than
1235 * PSA_MAX_IOVEC.
1236 */
1237 if (outvec_idx >= PSA_MAX_IOVEC) {
1238 tfm_core_panic();
1239 }
1240
1241 /*
1242 * It is a fatal error if len is greater than the output vector size.
1243 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001244 if (len > hdl->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +08001245 tfm_core_panic();
1246 }
1247
1248 /*
1249 * It is a fatal error if The output vector has not been mapped by a call to
1250 * psa_map_outvec().
1251 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001252 if (!IOVEC_IS_MAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001253 tfm_core_panic();
1254 }
1255
1256 /*
1257 * It is a fatal error if the output vector has already been unmapped by a
1258 * call to psa_unmap_outvec().
1259 */
Ken Liu0bed7e02022-02-10 12:38:07 +08001260 if (IOVEC_IS_UNMAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +08001261 tfm_core_panic();
1262 }
1263
Ken Liu0bed7e02022-02-10 12:38:07 +08001264 SET_IOVEC_UNMAPPED(hdl, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +08001265
1266 /* Update the write number */
Ken Liu0bed7e02022-02-10 12:38:07 +08001267 hdl->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +08001268}
1269
1270#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */