blob: 1588263226e8f30db6ce564813644142098024d0 [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];
Summer Qin630c76b2020-05-20 10:32:58 +0800149 struct tfm_conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800150 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +0800151 struct tfm_msg_body_t *msg;
Summer Qinba2346e2019-11-12 16:26:31 +0800152 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800153 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800154 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800155 uint32_t privileged;
Mingyang Sun620c8562021-11-10 11:44:58 +0800156 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800157 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800158 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
159 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
160 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800161
162 /* The request type must be zero or positive. */
163 if (type < 0) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800164 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800165 }
David Hu733d8f92019-09-23 15:32:40 +0800166
Shawn Shanb222d892021-01-04 17:41:48 +0800167 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800168 if ((in_num > PSA_MAX_IOVEC) ||
169 (out_num > PSA_MAX_IOVEC) ||
170 (in_num + out_num > PSA_MAX_IOVEC)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800171 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800172 }
173
Kevin Peng385fda82021-08-18 10:41:19 +0800174 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800175
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800176 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800177 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800178 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800179
180 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800181 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sune8d38082021-03-30 18:34:40 +0800182 }
183
Mingyang Sun453ad402021-03-17 17:58:33 +0800184 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800185 if (!service) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800186 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun86213242021-07-14 10:26:43 +0800187 }
188
Ken Liub3b2cb62021-05-22 00:39:28 +0800189 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800190
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800191 /*
192 * It is a PROGRAMMER ERROR if the caller is not authorized to access
193 * the RoT Service.
194 */
195 if (tfm_spm_check_authorization(sid, service, ns_caller)
196 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800197 return PSA_ERROR_CONNECTION_REFUSED;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800198 }
199
Mingyang Sun453ad402021-03-17 17:58:33 +0800200 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
201
202 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800203 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun453ad402021-03-17 17:58:33 +0800204 }
205
Mingyang Sun620c8562021-11-10 11:44:58 +0800206 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800207 conn_handle = tfm_spm_create_conn_handle(service, client_id);
Mingyang Sun620c8562021-11-10 11:44:58 +0800208 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800209
210 if (!conn_handle) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800211 return PSA_ERROR_CONNECTION_BUSY;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800212 }
213
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800214 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800215 handle = tfm_spm_to_user_handle(conn_handle);
216 } else {
217 conn_handle = tfm_spm_to_handle_instance(handle);
218
219 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
220 if (tfm_spm_validate_conn_handle(conn_handle, client_id)
221 != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800222 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800223 }
224
225 /*
226 * It is a PROGRAMMER ERROR if the connection is currently
227 * handling a request.
228 */
229 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800230 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800231 }
232
233 /*
234 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
235 * has been terminated by the RoT Service.
236 */
237 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
238 return PSA_ERROR_PROGRAMMER_ERROR;
239 }
240
Ken Liuf39d8eb2021-10-07 12:55:33 +0800241 service = conn_handle->internal_msg.service;
Shawn Shanb222d892021-01-04 17:41:48 +0800242
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800243 if (!service) {
244 /* FixMe: Need to implement a mechanism to resolve this failure. */
245 return PSA_ERROR_PROGRAMMER_ERROR;
246 }
David Hu733d8f92019-09-23 15:32:40 +0800247 }
248
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800249 privileged = GET_CURRENT_PARTITION_PRIVILEGED_MODE();
Mingyang Sune529e3b2021-07-12 14:46:30 +0800250
Kevin Pengedb8ee42021-03-09 16:50:11 +0800251 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800252 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800253 * if the memory reference for the wrap input vector is invalid or not
254 * readable.
255 */
256 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800257 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800258 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800259 }
Summer Qinba2346e2019-11-12 16:26:31 +0800260
David Hu733d8f92019-09-23 15:32:40 +0800261 /*
262 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800263 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800264 * the wrap output vector is invalid or not read-write.
265 */
266 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800267 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800268 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800269 }
270
Summer Qinf24dbb52020-07-23 14:53:54 +0800271 spm_memset(invecs, 0, sizeof(invecs));
272 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800273
274 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800275 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
276 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800277
278 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800279 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800280 * memory reference was invalid or not readable.
281 */
282 for (i = 0; i < in_num; i++) {
283 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800284 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800285 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800286 }
287 }
Summer Qinba2346e2019-11-12 16:26:31 +0800288
289 /*
290 * Clients must never overlap input parameters because of the risk of a
291 * double-fetch inconsistency.
292 * Overflow is checked in tfm_memory_check functions.
293 */
294 for (i = 0; i + 1 < in_num; i++) {
295 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100296 if (!((char *) invecs[j].base + invecs[j].len <=
297 (char *) invecs[i].base ||
298 (char *) invecs[j].base >=
299 (char *) invecs[i].base + invecs[i].len)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800300 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qinba2346e2019-11-12 16:26:31 +0800301 }
302 }
303 }
304
David Hu733d8f92019-09-23 15:32:40 +0800305 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800306 * For client output vector, it is a PROGRAMMER ERROR if the provided
307 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800308 */
309 for (i = 0; i < out_num; i++) {
310 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800311 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800312 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800313 }
314 }
315
Kevin Pengbaa7f5b2022-01-19 15:20:56 +0800316 msg = &(conn_handle->internal_msg);
David Hu733d8f92019-09-23 15:32:40 +0800317
Ken Liu505b1702020-05-29 13:19:58 +0800318 tfm_spm_fill_msg(msg, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800319 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800320
Mingyang Sundeae45d2021-09-06 15:31:07 +0800321 return backend_instance.messaging(service, msg);
David Hu733d8f92019-09-23 15:32:40 +0800322}
323
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800324/* Following PSA APIs are only needed by connection-based services */
325#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
326
327psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
328{
329 struct service_t *service;
330 struct tfm_msg_body_t *msg;
331 struct tfm_conn_handle_t *connect_handle;
332 int32_t client_id;
333 psa_handle_t handle;
334 bool ns_caller = tfm_spm_is_ns_caller();
335 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
336
337 /*
338 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
339 * platform.
340 */
341 service = tfm_spm_get_service_by_sid(sid);
342 if (!service) {
343 return PSA_ERROR_CONNECTION_REFUSED;
344 }
345
346 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
347 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
348 return PSA_ERROR_PROGRAMMER_ERROR;
349 }
350
351 /*
352 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
353 * RoT Service.
354 */
355 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
356 return PSA_ERROR_CONNECTION_REFUSED;
357 }
358
359 /*
360 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
361 * not supported on the platform.
362 */
363 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
364 return PSA_ERROR_CONNECTION_REFUSED;
365 }
366
367 client_id = tfm_spm_get_client_id(ns_caller);
368
369 /*
370 * Create connection handle here since it is possible to return the error
371 * code to client when creation fails.
372 */
373 CRITICAL_SECTION_ENTER(cs_assert);
374 connect_handle = tfm_spm_create_conn_handle(service, client_id);
375 CRITICAL_SECTION_LEAVE(cs_assert);
376 if (!connect_handle) {
377 return PSA_ERROR_CONNECTION_BUSY;
378 }
379
Kevin Pengbaa7f5b2022-01-19 15:20:56 +0800380 msg = &(connect_handle->internal_msg);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800381
382 handle = tfm_spm_to_user_handle(connect_handle);
383 /* No input or output needed for connect message */
384 tfm_spm_fill_msg(msg, service, handle, PSA_IPC_CONNECT,
385 client_id, NULL, 0, NULL, 0, NULL);
386
387 return backend_instance.messaging(service, msg);
388}
389
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800390psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800391{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800392 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +0800393 struct tfm_msg_body_t *msg;
Summer Qin630c76b2020-05-20 10:32:58 +0800394 struct tfm_conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800395 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800396 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800397
398 /* It will have no effect if called with the NULL handle */
399 if (handle == PSA_NULL_HANDLE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800400 return PSA_SUCCESS;
David Hu733d8f92019-09-23 15:32:40 +0800401 }
402
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800403 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800404 if (IS_STATIC_HANDLE(handle)) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800405 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800406 }
407
Kevin Peng385fda82021-08-18 10:41:19 +0800408 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800409
Summer Qin373feb12020-03-27 15:35:33 +0800410 conn_handle = tfm_spm_to_handle_instance(handle);
David Hu733d8f92019-09-23 15:32:40 +0800411 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800412 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
413 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800414 */
Ken Liubcae38b2021-01-20 15:47:44 +0800415 if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800416 return PSA_ERROR_PROGRAMMER_ERROR;
Summer Qin1ce712a2019-10-14 18:04:05 +0800417 }
Shawn Shanb222d892021-01-04 17:41:48 +0800418
Ken Liuf39d8eb2021-10-07 12:55:33 +0800419 service = conn_handle->internal_msg.service;
David Hu733d8f92019-09-23 15:32:40 +0800420 if (!service) {
421 /* FixMe: Need to implement one mechanism to resolve this failure. */
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800422 return PSA_ERROR_PROGRAMMER_ERROR;
David Hu733d8f92019-09-23 15:32:40 +0800423 }
424
Kevin Pengbaa7f5b2022-01-19 15:20:56 +0800425 msg = &(conn_handle->internal_msg);
David Hu733d8f92019-09-23 15:32:40 +0800426
Shawn Shanb222d892021-01-04 17:41:48 +0800427 /*
428 * It is a PROGRAMMER ERROR if the connection is currently handling a
429 * request.
430 */
Summer Qin630c76b2020-05-20 10:32:58 +0800431 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800432 return PSA_ERROR_PROGRAMMER_ERROR;
Shawn Shancc39fcb2019-11-13 15:38:16 +0800433 }
434
David Hu733d8f92019-09-23 15:32:40 +0800435 /* No input or output needed for close message */
Ken Liu505b1702020-05-29 13:19:58 +0800436 tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, client_id,
David Hu733d8f92019-09-23 15:32:40 +0800437 NULL, 0, NULL, 0, NULL);
438
Xinyu Zhangb287ef82021-11-03 18:38:50 +0800439 return backend_instance.messaging(service, msg);
David Hu733d8f92019-09-23 15:32:40 +0800440}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800441
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800442#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
443
Mingyang Suneeca4652021-07-15 15:19:16 +0800444/* PSA Partition API function body */
445
Mingyang Sunb26b2802021-07-07 11:25:00 +0800446psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
447 uint32_t timeout)
448{
449 struct partition_t *partition = NULL;
450
451 /*
452 * Timeout[30:0] are reserved for future use.
453 * SPM must ignore the value of RES.
454 */
455 timeout &= PSA_TIMEOUT_MASK;
456
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800457 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800458
459 /*
460 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
461 * signals.
462 */
463 if ((partition->signals_allowed & signal_mask) == 0) {
464 tfm_core_panic();
465 }
466
467 /*
Ken Liu5d73c872021-08-19 19:23:17 +0800468 * thrd_wait_on() blocks the caller thread if no signals are available.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800469 * In this case, the return value of this function is temporary set into
470 * runtime context. After new signal(s) are available, the return value
471 * is updated with the available signal(s) and blocked thread gets to run.
472 */
473 if (timeout == PSA_BLOCK &&
474 (partition->signals_asserted & signal_mask) == 0) {
475 partition->signals_waiting = signal_mask;
Ken Liuf39d8eb2021-10-07 12:55:33 +0800476 thrd_wait_on(&partition->waitobj, CURRENT_THREAD);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800477 }
478
479 return partition->signals_asserted & signal_mask;
480}
481
482psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
483{
484 struct tfm_msg_body_t *tmp_msg = NULL;
485 struct partition_t *partition = NULL;
486 uint32_t privileged;
487
488 /*
489 * Only one message could be retrieved every time for psa_get(). It is a
490 * fatal error if the input signal has more than a signal bit set.
491 */
492 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
493 tfm_core_panic();
494 }
495
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800496 partition = GET_CURRENT_COMPONENT();
497
Kevin Penga40d29f2022-01-19 14:44:34 +0800498 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800499
500 /*
501 * Write the message to the service buffer. It is a fatal error if the
502 * input msg pointer is not a valid memory reference or not read-write.
503 */
504 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
505 privileged) != SPM_SUCCESS) {
506 tfm_core_panic();
507 }
508
509 /*
510 * It is a fatal error if the caller call psa_get() when no message has
511 * been set. The caller must call this function after an RoT Service signal
512 * is returned by psa_wait().
513 */
514 if (partition->signals_asserted == 0) {
515 tfm_core_panic();
516 }
517
518 /*
519 * It is a fatal error if the RoT Service signal is not currently asserted.
520 */
521 if ((partition->signals_asserted & signal) == 0) {
522 tfm_core_panic();
523 }
524
525 /*
526 * Get message by signal from partition. It is a fatal error if getting
527 * failed, which means the input signal is not correspond to an RoT service.
528 */
Ken Liu5a28da32022-01-19 14:37:05 +0800529 tmp_msg = spm_get_msg_with_signal(partition, signal);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800530 if (!tmp_msg) {
531 return PSA_ERROR_DOES_NOT_EXIST;
532 }
533
534 (TO_CONTAINER(tmp_msg,
535 struct tfm_conn_handle_t,
536 internal_msg))->status = TFM_HANDLE_STATUS_ACTIVE;
537
538 spm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t));
539
540 return PSA_SUCCESS;
541}
542
Mingyang Sunb26b2802021-07-07 11:25:00 +0800543size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
544 void *buffer, size_t num_bytes)
545{
546 size_t bytes;
547 struct tfm_msg_body_t *msg = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800548 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800549
550 /* It is a fatal error if message handle is invalid */
551 msg = tfm_spm_get_msg_from_handle(msg_handle);
552 if (!msg) {
553 tfm_core_panic();
554 }
555
Kevin Penga40d29f2022-01-19 14:44:34 +0800556 priv_mode = GET_PARTITION_PRIVILEGED_MODE(msg->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800557
558 /*
559 * It is a fatal error if message handle does not refer to a request
560 * message
561 */
562 if (msg->msg.type < PSA_IPC_CALL) {
563 tfm_core_panic();
564 }
565
566 /*
567 * It is a fatal error if invec_idx is equal to or greater than
568 * PSA_MAX_IOVEC
569 */
570 if (invec_idx >= PSA_MAX_IOVEC) {
571 tfm_core_panic();
572 }
573
574 /* There was no remaining data in this input vector */
575 if (msg->msg.in_size[invec_idx] == 0) {
576 return 0;
577 }
578
Shawn Shan038348e2021-09-08 17:11:04 +0800579#if PSA_FRAMEWORK_HAS_MM_IOVEC
580 /*
581 * It is a fatal error if the input vector has already been mapped using
582 * psa_map_invec().
583 */
584 if (IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
585 tfm_core_panic();
586 }
587
588 SET_IOVEC_ACCESSED(msg, (invec_idx + INVEC_IDX_BASE));
589#endif
590
Mingyang Sunb26b2802021-07-07 11:25:00 +0800591 /*
592 * Copy the client data to the service buffer. It is a fatal error
593 * if the memory reference for buffer is invalid or not read-write.
594 */
595 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800596 TFM_MEMORY_ACCESS_RW, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800597 tfm_core_panic();
598 }
599
600 bytes = num_bytes > msg->msg.in_size[invec_idx] ?
601 msg->msg.in_size[invec_idx] : num_bytes;
602
603 spm_memcpy(buffer, msg->invec[invec_idx].base, bytes);
604
605 /* There maybe some remaining data */
606 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base + bytes;
607 msg->msg.in_size[invec_idx] -= bytes;
608
609 return bytes;
610}
611
612size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
613 size_t num_bytes)
614{
615 struct tfm_msg_body_t *msg = NULL;
616
617 /* It is a fatal error if message handle is invalid */
618 msg = tfm_spm_get_msg_from_handle(msg_handle);
619 if (!msg) {
620 tfm_core_panic();
621 }
622
623 /*
624 * It is a fatal error if message handle does not refer to a request
625 * message
626 */
627 if (msg->msg.type < PSA_IPC_CALL) {
628 tfm_core_panic();
629 }
630
631 /*
632 * It is a fatal error if invec_idx is equal to or greater than
633 * PSA_MAX_IOVEC
634 */
635 if (invec_idx >= PSA_MAX_IOVEC) {
636 tfm_core_panic();
637 }
638
639 /* There was no remaining data in this input vector */
640 if (msg->msg.in_size[invec_idx] == 0) {
641 return 0;
642 }
643
Shawn Shan038348e2021-09-08 17:11:04 +0800644#if PSA_FRAMEWORK_HAS_MM_IOVEC
645 /*
646 * It is a fatal error if the input vector has already been mapped using
647 * psa_map_invec().
648 */
649 if (IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
650 tfm_core_panic();
651 }
652
653 SET_IOVEC_ACCESSED(msg, (invec_idx + INVEC_IDX_BASE));
654#endif
655
Mingyang Sunb26b2802021-07-07 11:25:00 +0800656 /*
657 * If num_bytes is greater than the remaining size of the input vector then
658 * the remaining size of the input vector is used.
659 */
660 if (num_bytes > msg->msg.in_size[invec_idx]) {
661 num_bytes = msg->msg.in_size[invec_idx];
662 }
663
664 /* There maybe some remaining data */
665 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base +
666 num_bytes;
667 msg->msg.in_size[invec_idx] -= num_bytes;
668
669 return num_bytes;
670}
671
672void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
673 const void *buffer, size_t num_bytes)
674{
675 struct tfm_msg_body_t *msg = NULL;
Kevin Penga40d29f2022-01-19 14:44:34 +0800676 uint32_t priv_mode;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800677
678 /* It is a fatal error if message handle is invalid */
679 msg = tfm_spm_get_msg_from_handle(msg_handle);
680 if (!msg) {
681 tfm_core_panic();
682 }
683
Kevin Penga40d29f2022-01-19 14:44:34 +0800684 priv_mode = GET_PARTITION_PRIVILEGED_MODE(msg->service->partition->p_ldinf);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800685
686 /*
687 * It is a fatal error if message handle does not refer to a request
688 * message
689 */
690 if (msg->msg.type < PSA_IPC_CALL) {
691 tfm_core_panic();
692 }
693
694 /*
695 * It is a fatal error if outvec_idx is equal to or greater than
696 * PSA_MAX_IOVEC
697 */
698 if (outvec_idx >= PSA_MAX_IOVEC) {
699 tfm_core_panic();
700 }
701
702 /*
703 * It is a fatal error if the call attempts to write data past the end of
704 * the client output vector
705 */
706 if (num_bytes > msg->msg.out_size[outvec_idx] -
707 msg->outvec[outvec_idx].len) {
708 tfm_core_panic();
709 }
710
Shawn Shan038348e2021-09-08 17:11:04 +0800711#if PSA_FRAMEWORK_HAS_MM_IOVEC
712 /*
713 * It is a fatal error if the output vector has already been mapped using
714 * psa_map_outvec().
715 */
716 if (IOVEC_IS_MAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE))) {
717 tfm_core_panic();
718 }
719
720 SET_IOVEC_ACCESSED(msg, (outvec_idx + OUTVEC_IDX_BASE));
721#endif
722
Mingyang Sunb26b2802021-07-07 11:25:00 +0800723 /*
724 * Copy the service buffer to client outvecs. It is a fatal error
725 * if the memory reference for buffer is invalid or not readable.
726 */
727 if (tfm_memory_check(buffer, num_bytes, false,
Kevin Penga40d29f2022-01-19 14:44:34 +0800728 TFM_MEMORY_ACCESS_RO, priv_mode) != SPM_SUCCESS) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800729 tfm_core_panic();
730 }
731
732 spm_memcpy((char *)msg->outvec[outvec_idx].base +
733 msg->outvec[outvec_idx].len, buffer, num_bytes);
734
735 /* Update the write number */
736 msg->outvec[outvec_idx].len += num_bytes;
737}
738
Ken Liuf39d8eb2021-10-07 12:55:33 +0800739int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
740 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800741{
742 struct service_t *service = NULL;
743 struct tfm_msg_body_t *msg = NULL;
744 int32_t ret = PSA_SUCCESS;
745 struct tfm_conn_handle_t *conn_handle;
Mingyang Sun620c8562021-11-10 11:44:58 +0800746 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800747
748 /* It is a fatal error if message handle is invalid */
749 msg = tfm_spm_get_msg_from_handle(msg_handle);
750 if (!msg) {
751 tfm_core_panic();
752 }
753
754 /*
755 * RoT Service information is needed in this function, stored it in message
756 * body structure. Only two parameters are passed in this function: handle
757 * and status, so it is useful and simply to do like this.
758 */
759 service = msg->service;
760 if (!service) {
761 tfm_core_panic();
762 }
763
764 /*
765 * Three type of message are passed in this function: CONNECTION, REQUEST,
766 * DISCONNECTION. It needs to process differently for each type.
767 */
768 conn_handle = tfm_spm_to_handle_instance(msg_handle);
769 switch (msg->msg.type) {
770 case PSA_IPC_CONNECT:
771 /*
772 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
773 * input status is PSA_SUCCESS. Others return values are based on the
774 * input status.
775 */
776 if (status == PSA_SUCCESS) {
777 ret = msg_handle;
778 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
779 /* Refuse the client connection, indicating a permanent error. */
780 tfm_spm_free_conn_handle(service, conn_handle);
781 ret = PSA_ERROR_CONNECTION_REFUSED;
782 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
783 /* Fail the client connection, indicating a transient error. */
784 ret = PSA_ERROR_CONNECTION_BUSY;
785 } else {
786 tfm_core_panic();
787 }
788 break;
789 case PSA_IPC_DISCONNECT:
790 /* Service handle is not used anymore */
791 tfm_spm_free_conn_handle(service, conn_handle);
792
793 /*
794 * If the message type is PSA_IPC_DISCONNECT, then the status code is
795 * ignored
796 */
797 break;
798 default:
799 if (msg->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800800
801#if PSA_FRAMEWORK_HAS_MM_IOVEC
802
803 /*
804 * If the unmapped function is not called for an input/output vector
805 * that has been mapped, the framework will remove the mapping.
806 */
807 int i;
808
809 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
810 if (IOVEC_IS_MAPPED(msg, i) && (!IOVEC_IS_UNMAPPED(msg, i))) {
811 SET_IOVEC_UNMAPPED(msg, i);
812 /*
813 * Any output vectors that are still mapped will report that
814 * zero bytes have been written.
815 */
816 if (i >= OUTVEC_IDX_BASE) {
817 msg->outvec[i - OUTVEC_IDX_BASE].len = 0;
818 }
819 }
820 }
821
822#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800823 /* Reply to a request message. Return values are based on status */
824 ret = status;
825 /*
826 * The total number of bytes written to a single parameter must be
827 * reported to the client by updating the len member of the
828 * psa_outvec structure for the parameter before returning from
829 * psa_call().
830 */
831 update_caller_outvec_len(msg);
832 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
833 tfm_spm_free_conn_handle(service, conn_handle);
834 }
835 } else {
836 tfm_core_panic();
837 }
838 }
839
840 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
841 /*
842 * If the source of the programmer error is a Secure Partition, the SPM
843 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
844 */
845 if (TFM_CLIENT_ID_IS_NS(msg->msg.client_id)) {
846 conn_handle->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
847 } else {
848 tfm_core_panic();
849 }
850 } else {
851 conn_handle->status = TFM_HANDLE_STATUS_IDLE;
852 }
853
Mingyang Sun620c8562021-11-10 11:44:58 +0800854 /*
855 * TODO: It can be optimized further by moving critical section protection
856 * to mailbox. Also need to check implementation when secure context is
857 * involved.
858 */
859 CRITICAL_SECTION_ENTER(cs_assert);
860 ret = backend_instance.replying(msg, ret);
861 CRITICAL_SECTION_LEAVE(cs_assert);
862
863 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800864}
865
866void tfm_spm_partition_psa_notify(int32_t partition_id)
867{
Ken Liu5d73c872021-08-19 19:23:17 +0800868 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
869
870 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800871}
872
873void tfm_spm_partition_psa_clear(void)
874{
Ken Liu92ede9f2021-10-20 09:35:00 +0800875 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800876 struct partition_t *partition = NULL;
877
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800878 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800879
880 /*
881 * It is a fatal error if the Secure Partition's doorbell signal is not
882 * currently asserted.
883 */
884 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
885 tfm_core_panic();
886 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800887
888 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800889 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800890 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800891}
892
893void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
894{
Ken Liu92ede9f2021-10-20 09:35:00 +0800895 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800896 struct irq_load_info_t *irq_info = NULL;
897 struct partition_t *partition = NULL;
898
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800899 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800900
901 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
902 /* It is a fatal error if passed signal is not an interrupt signal. */
903 if (!irq_info) {
904 tfm_core_panic();
905 }
906
907 if (irq_info->flih_func) {
908 /* This API is for SLIH IRQs only */
Ken Liuf39d8eb2021-10-07 12:55:33 +0800909 tfm_core_panic();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800910 }
911
912 /* It is a fatal error if passed signal is not currently asserted */
913 if ((partition->signals_asserted & irq_signal) == 0) {
914 tfm_core_panic();
915 }
916
Ken Liu92ede9f2021-10-20 09:35:00 +0800917 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800918 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800919 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800920
Kevin Pengd399a1f2021-09-08 15:33:14 +0800921 tfm_hal_irq_clear_pending(irq_info->source);
922 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800923}
924
925void tfm_spm_partition_psa_panic(void)
926{
927 /*
928 * PSA FF recommends that the SPM causes the system to restart when a secure
929 * partition panics.
930 */
931 tfm_hal_system_reset();
932}
933
Kevin Peng67a89fd2021-11-25 11:22:02 +0800934void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800935{
936 struct partition_t *partition;
937 struct irq_load_info_t *irq_info;
938
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800939 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800940
941 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
942 if (!irq_info) {
943 tfm_core_panic();
944 }
945
Kevin Pengd399a1f2021-09-08 15:33:14 +0800946 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800947}
948
Kevin Peng67a89fd2021-11-25 11:22:02 +0800949psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800950{
951 struct partition_t *partition;
952 struct irq_load_info_t *irq_info;
953
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800954 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800955
956 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
957 if (!irq_info) {
958 tfm_core_panic();
959 }
960
Kevin Pengd399a1f2021-09-08 15:33:14 +0800961 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800962
963 return 1;
964}
965
966void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
967{
Ken Liu92ede9f2021-10-20 09:35:00 +0800968 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800969 struct irq_load_info_t *irq_info;
970 struct partition_t *partition;
971
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800972 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800973
974 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
975 if (!irq_info) {
976 tfm_core_panic();
977 }
978
979 if (!irq_info->flih_func) {
980 /* This API is for FLIH IRQs only */
981 tfm_core_panic();
982 }
983
984 if ((partition->signals_asserted & irq_signal) == 0) {
985 /* The signal is not asserted */
986 tfm_core_panic();
987 }
988
Ken Liu92ede9f2021-10-20 09:35:00 +0800989 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800990 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800991 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800992}
Shawn Shan038348e2021-09-08 17:11:04 +0800993
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800994/* psa_set_rhandle is only needed by connection-based services */
995#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
996
997void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
998{
999 struct tfm_msg_body_t *msg = NULL;
1000 struct tfm_conn_handle_t *conn_handle;
1001
1002 /* It is a fatal error if message handle is invalid */
1003 msg = tfm_spm_get_msg_from_handle(msg_handle);
1004 if (!msg) {
1005 tfm_core_panic();
1006 }
1007
1008 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
1009 if (SERVICE_IS_STATELESS(msg->service->p_ldinf->flags)) {
1010 tfm_core_panic();
1011 }
1012
1013 msg->msg.rhandle = rhandle;
1014 conn_handle = tfm_spm_to_handle_instance(msg_handle);
1015
1016 /* Store reverse handle for following client calls. */
1017 tfm_spm_set_rhandle(msg->service, conn_handle, rhandle);
1018}
1019
1020#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
1021
Shawn Shan038348e2021-09-08 17:11:04 +08001022#if PSA_FRAMEWORK_HAS_MM_IOVEC
1023
1024const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
1025 uint32_t invec_idx)
1026{
1027 struct tfm_msg_body_t *msg = NULL;
1028 uint32_t privileged;
1029 struct partition_t *partition = NULL;
1030
1031 /* It is a fatal error if message handle is invalid */
1032 msg = tfm_spm_get_msg_from_handle(msg_handle);
1033 if (!msg) {
1034 tfm_core_panic();
1035 }
1036
1037 partition = msg->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001038 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001039
1040 /*
1041 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1042 * Service that received the message.
1043 */
1044 if (!SERVICE_ENABLED_MM_IOVEC(msg->service->p_ldinf->flags)) {
1045 tfm_core_panic();
1046 }
1047
1048 /*
1049 * It is a fatal error if message handle does not refer to a request
1050 * message.
1051 */
1052 if (msg->msg.type < PSA_IPC_CALL) {
1053 tfm_core_panic();
1054 }
1055
1056 /*
1057 * It is a fatal error if invec_idx is equal to or greater than
1058 * PSA_MAX_IOVEC.
1059 */
1060 if (invec_idx >= PSA_MAX_IOVEC) {
1061 tfm_core_panic();
1062 }
1063
1064 /* It is a fatal error if the input vector has length zero. */
1065 if (msg->msg.in_size[invec_idx] == 0) {
1066 tfm_core_panic();
1067 }
1068
1069 /*
1070 * It is a fatal error if the input vector has already been mapped using
1071 * psa_map_invec().
1072 */
1073 if (IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
1074 tfm_core_panic();
1075 }
1076
1077 /*
1078 * It is a fatal error if the input vector has already been accessed
1079 * using psa_read() or psa_skip().
1080 */
1081 if (IOVEC_IS_ACCESSED(msg, (invec_idx + INVEC_IDX_BASE))) {
1082 tfm_core_panic();
1083 }
1084
1085 /*
1086 * It is a fatal error if the memory reference for the wrap input vector is
1087 * invalid or not readable.
1088 */
1089 if (tfm_memory_check(msg->invec[invec_idx].base, msg->invec[invec_idx].len,
1090 false, TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
1091 tfm_core_panic();
1092 }
1093
1094 SET_IOVEC_MAPPED(msg, (invec_idx + INVEC_IDX_BASE));
1095
1096 return msg->invec[invec_idx].base;
1097}
1098
1099void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
1100 uint32_t invec_idx)
1101{
1102 struct tfm_msg_body_t *msg = NULL;
1103
1104 /* It is a fatal error if message handle is invalid */
1105 msg = tfm_spm_get_msg_from_handle(msg_handle);
1106 if (!msg) {
1107 tfm_core_panic();
1108 }
1109
1110 /*
1111 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1112 * Service that received the message.
1113 */
1114 if (!SERVICE_ENABLED_MM_IOVEC(msg->service->p_ldinf->flags)) {
1115 tfm_core_panic();
1116 }
1117
1118 /*
1119 * It is a fatal error if message handle does not refer to a request
1120 * message.
1121 */
1122 if (msg->msg.type < PSA_IPC_CALL) {
1123 tfm_core_panic();
1124 }
1125
1126 /*
1127 * It is a fatal error if invec_idx is equal to or greater than
1128 * PSA_MAX_IOVEC.
1129 */
1130 if (invec_idx >= PSA_MAX_IOVEC) {
1131 tfm_core_panic();
1132 }
1133
1134 /*
1135 * It is a fatal error if The input vector has not been mapped by a call to
1136 * psa_map_invec().
1137 */
1138 if (!IOVEC_IS_MAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
1139 tfm_core_panic();
1140 }
1141
1142 /*
1143 * It is a fatal error if the input vector has already been unmapped by a
1144 * call to psa_unmap_invec().
1145 */
1146 if (IOVEC_IS_UNMAPPED(msg, (invec_idx + INVEC_IDX_BASE))) {
1147 tfm_core_panic();
1148 }
1149
1150 SET_IOVEC_UNMAPPED(msg, (invec_idx + INVEC_IDX_BASE));
1151}
1152
1153void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
1154 uint32_t outvec_idx)
1155{
1156 struct tfm_msg_body_t *msg = NULL;
1157 uint32_t privileged;
1158 struct partition_t *partition = NULL;
1159
1160 /* It is a fatal error if message handle is invalid */
1161 msg = tfm_spm_get_msg_from_handle(msg_handle);
1162 if (!msg) {
1163 tfm_core_panic();
1164 }
1165
1166 partition = msg->service->partition;
Kevin Penga40d29f2022-01-19 14:44:34 +08001167 privileged = GET_PARTITION_PRIVILEGED_MODE(partition->p_ldinf);
Shawn Shan038348e2021-09-08 17:11:04 +08001168
1169 /*
1170 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1171 * Service that received the message.
1172 */
1173 if (!SERVICE_ENABLED_MM_IOVEC(msg->service->p_ldinf->flags)) {
1174 tfm_core_panic();
1175 }
1176
1177 /*
1178 * It is a fatal error if message handle does not refer to a request
1179 * message.
1180 */
1181 if (msg->msg.type < PSA_IPC_CALL) {
1182 tfm_core_panic();
1183 }
1184
1185 /*
1186 * It is a fatal error if outvec_idx is equal to or greater than
1187 * PSA_MAX_IOVEC.
1188 */
1189 if (outvec_idx >= PSA_MAX_IOVEC) {
1190 tfm_core_panic();
1191 }
1192
1193 /* It is a fatal error if the output vector has length zero. */
1194 if (msg->msg.out_size[outvec_idx] == 0) {
1195 tfm_core_panic();
1196 }
1197
1198 /*
1199 * It is a fatal error if the output vector has already been mapped using
1200 * psa_map_outvec().
1201 */
1202 if (IOVEC_IS_MAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE))) {
1203 tfm_core_panic();
1204 }
1205
1206 /*
1207 * It is a fatal error if the output vector has already been accessed
1208 * using psa_write().
1209 */
1210 if (IOVEC_IS_ACCESSED(msg, (outvec_idx + OUTVEC_IDX_BASE))) {
1211 tfm_core_panic();
1212 }
1213
1214 /*
1215 * It is a fatal error if the output vector is invalid or not read-write.
1216 */
1217 if (tfm_memory_check(msg->outvec[outvec_idx].base,
1218 msg->outvec[outvec_idx].len, false,
1219 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
1220 tfm_core_panic();
1221 }
1222 SET_IOVEC_MAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE));
1223
1224 return msg->outvec[outvec_idx].base;
1225}
1226
1227void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
1228 uint32_t outvec_idx, size_t len)
1229{
1230 struct tfm_msg_body_t *msg = NULL;
1231
1232 /* It is a fatal error if message handle is invalid */
1233 msg = tfm_spm_get_msg_from_handle(msg_handle);
1234 if (!msg) {
1235 tfm_core_panic();
1236 }
1237
1238 /*
1239 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
1240 * Service that received the message.
1241 */
1242 if (!SERVICE_ENABLED_MM_IOVEC(msg->service->p_ldinf->flags)) {
1243 tfm_core_panic();
1244 }
1245
1246 /*
1247 * It is a fatal error if message handle does not refer to a request
1248 * message.
1249 */
1250 if (msg->msg.type < PSA_IPC_CALL) {
1251 tfm_core_panic();
1252 }
1253
1254 /*
1255 * It is a fatal error if outvec_idx is equal to or greater than
1256 * PSA_MAX_IOVEC.
1257 */
1258 if (outvec_idx >= PSA_MAX_IOVEC) {
1259 tfm_core_panic();
1260 }
1261
1262 /*
1263 * It is a fatal error if len is greater than the output vector size.
1264 */
1265 if (len > msg->msg.out_size[outvec_idx]) {
1266 tfm_core_panic();
1267 }
1268
1269 /*
1270 * It is a fatal error if The output vector has not been mapped by a call to
1271 * psa_map_outvec().
1272 */
1273 if (!IOVEC_IS_MAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE))) {
1274 tfm_core_panic();
1275 }
1276
1277 /*
1278 * It is a fatal error if the output vector has already been unmapped by a
1279 * call to psa_unmap_outvec().
1280 */
1281 if (IOVEC_IS_UNMAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE))) {
1282 tfm_core_panic();
1283 }
1284
1285 SET_IOVEC_UNMAPPED(msg, (outvec_idx + OUTVEC_IDX_BASE));
1286
1287 /* Update the write number */
1288 msg->outvec[outvec_idx].len = len;
1289}
1290
1291#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */