blob: 16e0d041125ec4bd5dd70ac831fb60fc563262a7 [file] [log] [blame]
David Hu733d8f92019-09-23 15:32:40 +08001/*
Shawn Shanb222d892021-01-04 17:41:48 +08002 * Copyright (c) 2019-2021, 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"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080013#include "spm_ipc.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080014#include "tfm_arch.h"
David Hu733d8f92019-09-23 15:32:40 +080015#include "tfm_core_utils.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080016#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080017#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080018#include "load/interrupt_defs.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080019#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080020#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080021#include "ffm/psa_api.h"
Ken Liubcae38b2021-01-20 15:47:44 +080022#include "ffm/spm_error_base.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080023#include "tfm_rpc.h"
24#include "tfm_spm_hal.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080025#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080026#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080027#include "tfm_psa_call_pack.h"
David Hu733d8f92019-09-23 15:32:40 +080028
Ken Liub3b2cb62021-05-22 00:39:28 +080029#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080030extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080031
Mingyang Suneeca4652021-07-15 15:19:16 +080032uint32_t tfm_spm_get_lifecycle_state(void)
33{
34 /*
35 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
36 * implemented in the future.
37 */
38 return PSA_LIFECYCLE_UNKNOWN;
39}
40
41/* PSA Client API function body */
42
Mingyang Sund44522a2020-01-16 16:48:37 +080043uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +080044{
45 return PSA_FRAMEWORK_VERSION;
46}
47
Mingyang Sun22a3faf2021-07-09 15:32:47 +080048uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +080049{
Mingyang Sun783a59b2021-04-20 15:52:18 +080050 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +080051 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +080052
53 /*
54 * It should return PSA_VERSION_NONE if the RoT Service is not
55 * implemented.
56 */
57 service = tfm_spm_get_service_by_sid(sid);
58 if (!service) {
59 return PSA_VERSION_NONE;
60 }
61
62 /*
Shawn Shan2365c902019-12-19 18:35:36 +080063 * It should return PSA_VERSION_NONE if the caller is not authorized
64 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +080065 */
Ken Liubcae38b2021-01-20 15:47:44 +080066 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +080067 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +080068 }
69
Ken Liuacd2a572021-05-12 16:19:04 +080070 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +080071}
72
Mingyang Sun22a3faf2021-07-09 15:32:47 +080073psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
David Hu733d8f92019-09-23 15:32:40 +080074{
Mingyang Sun783a59b2021-04-20 15:52:18 +080075 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +080076 struct tfm_msg_body_t *msg;
Summer Qin630c76b2020-05-20 10:32:58 +080077 struct tfm_conn_handle_t *connect_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +080078 int32_t client_id;
Ken Liu505b1702020-05-29 13:19:58 +080079 psa_handle_t handle;
Mingyang Sun22a3faf2021-07-09 15:32:47 +080080 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +080081
Kevin Pengedb8ee42021-03-09 16:50:11 +080082 /*
83 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
84 * platform.
85 */
David Hu733d8f92019-09-23 15:32:40 +080086 service = tfm_spm_get_service_by_sid(sid);
87 if (!service) {
Shawn Shanb222d892021-01-04 17:41:48 +080088 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
David Hu733d8f92019-09-23 15:32:40 +080089 }
90
Mingyang Sunef42f442021-06-11 15:07:58 +080091 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
92 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
93 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
94 }
95
Kevin Pengedb8ee42021-03-09 16:50:11 +080096 /*
97 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
98 * RoT Service.
99 */
100 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
101 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
102 }
103
104 /*
105 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
106 * not supported on the platform.
107 */
108 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
109 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
110 }
111
Kevin Peng385fda82021-08-18 10:41:19 +0800112 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800113
David Hu733d8f92019-09-23 15:32:40 +0800114 /*
115 * Create connection handle here since it is possible to return the error
116 * code to client when creation fails.
117 */
Summer Qin1ce712a2019-10-14 18:04:05 +0800118 connect_handle = tfm_spm_create_conn_handle(service, client_id);
Summer Qin630c76b2020-05-20 10:32:58 +0800119 if (!connect_handle) {
David Hu733d8f92019-09-23 15:32:40 +0800120 return PSA_ERROR_CONNECTION_BUSY;
121 }
122
Kevin Pengdf6aa292021-03-11 17:58:50 +0800123 msg = tfm_spm_get_msg_buffer_from_conn_handle(connect_handle);
124 if (!msg) {
125 /* Have no enough resource to create message */
126 return PSA_ERROR_CONNECTION_BUSY;
127 }
David Hu733d8f92019-09-23 15:32:40 +0800128
Ken Liu505b1702020-05-29 13:19:58 +0800129 handle = tfm_spm_to_user_handle(connect_handle);
David Hu733d8f92019-09-23 15:32:40 +0800130 /* No input or output needed for connect message */
Ken Liu505b1702020-05-29 13:19:58 +0800131 tfm_spm_fill_msg(msg, service, handle, PSA_IPC_CONNECT,
Summer Qin1ce712a2019-10-14 18:04:05 +0800132 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800133
David Hu733d8f92019-09-23 15:32:40 +0800134
Mingyang Sundeae45d2021-09-06 15:31:07 +0800135 return backend_instance.messaging(service, msg);
David Hu733d8f92019-09-23 15:32:40 +0800136}
137
Mingyang Suneeca4652021-07-15 15:19:16 +0800138psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
139 uint32_t ctrl_param,
140 const psa_invec *inptr,
141 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800142{
143 psa_invec invecs[PSA_MAX_IOVEC];
144 psa_outvec outvecs[PSA_MAX_IOVEC];
Summer Qin630c76b2020-05-20 10:32:58 +0800145 struct tfm_conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800146 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +0800147 struct tfm_msg_body_t *msg;
Summer Qinba2346e2019-11-12 16:26:31 +0800148 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800149 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800150 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800151 uint32_t privileged;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800152 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800153 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
154 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
155 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800156
157 /* The request type must be zero or positive. */
158 if (type < 0) {
159 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
160 }
David Hu733d8f92019-09-23 15:32:40 +0800161
Shawn Shanb222d892021-01-04 17:41:48 +0800162 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800163 if ((in_num > PSA_MAX_IOVEC) ||
164 (out_num > PSA_MAX_IOVEC) ||
165 (in_num + out_num > PSA_MAX_IOVEC)) {
Shawn Shanb222d892021-01-04 17:41:48 +0800166 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800167 }
168
Kevin Peng385fda82021-08-18 10:41:19 +0800169 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800170
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800171 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800172 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800173 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800174
175 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
176 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
177 }
178
Mingyang Sun453ad402021-03-17 17:58:33 +0800179 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800180 if (!service) {
181 tfm_core_panic();
182 }
183
Ken Liub3b2cb62021-05-22 00:39:28 +0800184 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800185
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800186 /*
187 * It is a PROGRAMMER ERROR if the caller is not authorized to access
188 * the RoT Service.
189 */
190 if (tfm_spm_check_authorization(sid, service, ns_caller)
191 != SPM_SUCCESS) {
192 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
193 }
194
Mingyang Sun453ad402021-03-17 17:58:33 +0800195 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
196
197 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
198 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
199 }
200
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800201 conn_handle = tfm_spm_create_conn_handle(service, client_id);
202
203 if (!conn_handle) {
204 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_BUSY);
205 }
206
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800207 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800208 handle = tfm_spm_to_user_handle(conn_handle);
209 } else {
210 conn_handle = tfm_spm_to_handle_instance(handle);
211
212 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
213 if (tfm_spm_validate_conn_handle(conn_handle, client_id)
214 != SPM_SUCCESS) {
215 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
216 }
217
218 /*
219 * It is a PROGRAMMER ERROR if the connection is currently
220 * handling a request.
221 */
222 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
223 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
224 }
225
226 /*
227 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
228 * has been terminated by the RoT Service.
229 */
230 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
231 return PSA_ERROR_PROGRAMMER_ERROR;
232 }
233
234 service = conn_handle->service;
Summer Qin1ce712a2019-10-14 18:04:05 +0800235 }
Shawn Shanb222d892021-01-04 17:41:48 +0800236
David Hu733d8f92019-09-23 15:32:40 +0800237 if (!service) {
238 /* FixMe: Need to implement one mechanism to resolve this failure. */
Edison Ai9059ea02019-11-28 13:46:14 +0800239 tfm_core_panic();
David Hu733d8f92019-09-23 15:32:40 +0800240 }
241
Mingyang Sune529e3b2021-07-12 14:46:30 +0800242 privileged = tfm_spm_get_caller_privilege_mode();
243
Kevin Pengedb8ee42021-03-09 16:50:11 +0800244 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800245 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800246 * if the memory reference for the wrap input vector is invalid or not
247 * readable.
248 */
249 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800250 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800251 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800252 }
Summer Qinba2346e2019-11-12 16:26:31 +0800253
David Hu733d8f92019-09-23 15:32:40 +0800254 /*
255 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800256 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800257 * the wrap output vector is invalid or not read-write.
258 */
259 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800260 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800261 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800262 }
263
Summer Qinf24dbb52020-07-23 14:53:54 +0800264 spm_memset(invecs, 0, sizeof(invecs));
265 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800266
267 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800268 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
269 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800270
271 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800272 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800273 * memory reference was invalid or not readable.
274 */
275 for (i = 0; i < in_num; i++) {
276 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800277 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800278 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800279 }
280 }
Summer Qinba2346e2019-11-12 16:26:31 +0800281
282 /*
283 * Clients must never overlap input parameters because of the risk of a
284 * double-fetch inconsistency.
285 * Overflow is checked in tfm_memory_check functions.
286 */
287 for (i = 0; i + 1 < in_num; i++) {
288 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100289 if (!((char *) invecs[j].base + invecs[j].len <=
290 (char *) invecs[i].base ||
291 (char *) invecs[j].base >=
292 (char *) invecs[i].base + invecs[i].len)) {
Shawn Shanb222d892021-01-04 17:41:48 +0800293 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
Summer Qinba2346e2019-11-12 16:26:31 +0800294 }
295 }
296 }
297
David Hu733d8f92019-09-23 15:32:40 +0800298 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800299 * For client output vector, it is a PROGRAMMER ERROR if the provided
300 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800301 */
302 for (i = 0; i < out_num; i++) {
303 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800304 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800305 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800306 }
307 }
308
309 /*
310 * FixMe: Need to check if the message is unrecognized by the RoT
311 * Service or incorrectly formatted.
312 */
Kevin Pengdf6aa292021-03-11 17:58:50 +0800313 msg = tfm_spm_get_msg_buffer_from_conn_handle(conn_handle);
314 if (!msg) {
315 /* FixMe: Need to implement one mechanism to resolve this failure. */
316 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
317 }
David Hu733d8f92019-09-23 15:32:40 +0800318
Ken Liu505b1702020-05-29 13:19:58 +0800319 tfm_spm_fill_msg(msg, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800320 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800321
Mingyang Sundeae45d2021-09-06 15:31:07 +0800322 return backend_instance.messaging(service, msg);
David Hu733d8f92019-09-23 15:32:40 +0800323}
324
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800325void tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800326{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800327 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +0800328 struct tfm_msg_body_t *msg;
Summer Qin630c76b2020-05-20 10:32:58 +0800329 struct tfm_conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800330 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800331 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800332
333 /* It will have no effect if called with the NULL handle */
334 if (handle == PSA_NULL_HANDLE) {
335 return;
336 }
337
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800338 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800339 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800340 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
341 }
342
Kevin Peng385fda82021-08-18 10:41:19 +0800343 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800344
Summer Qin373feb12020-03-27 15:35:33 +0800345 conn_handle = tfm_spm_to_handle_instance(handle);
David Hu733d8f92019-09-23 15:32:40 +0800346 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800347 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
348 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800349 */
Ken Liubcae38b2021-01-20 15:47:44 +0800350 if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800351 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
Summer Qin1ce712a2019-10-14 18:04:05 +0800352 }
Shawn Shanb222d892021-01-04 17:41:48 +0800353
Summer Qin630c76b2020-05-20 10:32:58 +0800354 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800355 if (!service) {
356 /* FixMe: Need to implement one mechanism to resolve this failure. */
Edison Ai9059ea02019-11-28 13:46:14 +0800357 tfm_core_panic();
David Hu733d8f92019-09-23 15:32:40 +0800358 }
359
Kevin Pengdf6aa292021-03-11 17:58:50 +0800360 msg = tfm_spm_get_msg_buffer_from_conn_handle(conn_handle);
361 if (!msg) {
362 /* FixMe: Need to implement one mechanism to resolve this failure. */
363 tfm_core_panic();
364 }
David Hu733d8f92019-09-23 15:32:40 +0800365
Shawn Shanb222d892021-01-04 17:41:48 +0800366 /*
367 * It is a PROGRAMMER ERROR if the connection is currently handling a
368 * request.
369 */
Summer Qin630c76b2020-05-20 10:32:58 +0800370 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Shawn Shanb222d892021-01-04 17:41:48 +0800371 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
Shawn Shancc39fcb2019-11-13 15:38:16 +0800372 }
373
David Hu733d8f92019-09-23 15:32:40 +0800374 /* No input or output needed for close message */
Ken Liu505b1702020-05-29 13:19:58 +0800375 tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, client_id,
David Hu733d8f92019-09-23 15:32:40 +0800376 NULL, 0, NULL, 0, NULL);
377
Mingyang Sundeae45d2021-09-06 15:31:07 +0800378 (void)backend_instance.messaging(service, msg);
David Hu733d8f92019-09-23 15:32:40 +0800379}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800380
Mingyang Suneeca4652021-07-15 15:19:16 +0800381/* PSA Partition API function body */
382
Mingyang Sunb26b2802021-07-07 11:25:00 +0800383psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
384 uint32_t timeout)
385{
386 struct partition_t *partition = NULL;
387
388 /*
389 * Timeout[30:0] are reserved for future use.
390 * SPM must ignore the value of RES.
391 */
392 timeout &= PSA_TIMEOUT_MASK;
393
394 partition = tfm_spm_get_running_partition();
395 if (!partition) {
396 tfm_core_panic();
397 }
398
399 /*
400 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
401 * signals.
402 */
403 if ((partition->signals_allowed & signal_mask) == 0) {
404 tfm_core_panic();
405 }
406
407 /*
Ken Liu5d73c872021-08-19 19:23:17 +0800408 * thrd_wait_on() blocks the caller thread if no signals are available.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800409 * In this case, the return value of this function is temporary set into
410 * runtime context. After new signal(s) are available, the return value
411 * is updated with the available signal(s) and blocked thread gets to run.
412 */
413 if (timeout == PSA_BLOCK &&
414 (partition->signals_asserted & signal_mask) == 0) {
415 partition->signals_waiting = signal_mask;
Ken Liu5d73c872021-08-19 19:23:17 +0800416 thrd_wait_on(&partition->waitobj,
417 &(tfm_spm_get_running_partition()->thrd));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800418 }
419
420 return partition->signals_asserted & signal_mask;
421}
422
423psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
424{
425 struct tfm_msg_body_t *tmp_msg = NULL;
426 struct partition_t *partition = NULL;
427 uint32_t privileged;
428
429 /*
430 * Only one message could be retrieved every time for psa_get(). It is a
431 * fatal error if the input signal has more than a signal bit set.
432 */
433 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
434 tfm_core_panic();
435 }
436
437 partition = tfm_spm_get_running_partition();
438 if (!partition) {
439 tfm_core_panic();
440 }
441 privileged = tfm_spm_partition_get_privileged_mode(
442 partition->p_ldinf->flags);
443
444 /*
445 * Write the message to the service buffer. It is a fatal error if the
446 * input msg pointer is not a valid memory reference or not read-write.
447 */
448 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
449 privileged) != SPM_SUCCESS) {
450 tfm_core_panic();
451 }
452
453 /*
454 * It is a fatal error if the caller call psa_get() when no message has
455 * been set. The caller must call this function after an RoT Service signal
456 * is returned by psa_wait().
457 */
458 if (partition->signals_asserted == 0) {
459 tfm_core_panic();
460 }
461
462 /*
463 * It is a fatal error if the RoT Service signal is not currently asserted.
464 */
465 if ((partition->signals_asserted & signal) == 0) {
466 tfm_core_panic();
467 }
468
469 /*
470 * Get message by signal from partition. It is a fatal error if getting
471 * failed, which means the input signal is not correspond to an RoT service.
472 */
473 tmp_msg = tfm_spm_get_msg_by_signal(partition, signal);
474 if (!tmp_msg) {
475 return PSA_ERROR_DOES_NOT_EXIST;
476 }
477
478 (TO_CONTAINER(tmp_msg,
479 struct tfm_conn_handle_t,
480 internal_msg))->status = TFM_HANDLE_STATUS_ACTIVE;
481
482 spm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t));
483
484 return PSA_SUCCESS;
485}
486
487void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
488{
489 struct tfm_msg_body_t *msg = NULL;
490 struct tfm_conn_handle_t *conn_handle;
491
492 /* It is a fatal error if message handle is invalid */
493 msg = tfm_spm_get_msg_from_handle(msg_handle);
494 if (!msg) {
495 tfm_core_panic();
496 }
497
498 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
499 if (SERVICE_IS_STATELESS(msg->service->p_ldinf->flags)) {
500 tfm_core_panic();
501 }
502
503 msg->msg.rhandle = rhandle;
504 conn_handle = tfm_spm_to_handle_instance(msg_handle);
505
506 /* Store reverse handle for following client calls. */
507 tfm_spm_set_rhandle(msg->service, conn_handle, rhandle);
508}
509
510size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
511 void *buffer, size_t num_bytes)
512{
513 size_t bytes;
514 struct tfm_msg_body_t *msg = NULL;
515 uint32_t privileged;
516 struct partition_t *partition = NULL;
517
518 /* It is a fatal error if message handle is invalid */
519 msg = tfm_spm_get_msg_from_handle(msg_handle);
520 if (!msg) {
521 tfm_core_panic();
522 }
523
524 partition = msg->service->partition;
525 privileged = tfm_spm_partition_get_privileged_mode(
526 partition->p_ldinf->flags);
527
528 /*
529 * It is a fatal error if message handle does not refer to a request
530 * message
531 */
532 if (msg->msg.type < PSA_IPC_CALL) {
533 tfm_core_panic();
534 }
535
536 /*
537 * It is a fatal error if invec_idx is equal to or greater than
538 * PSA_MAX_IOVEC
539 */
540 if (invec_idx >= PSA_MAX_IOVEC) {
541 tfm_core_panic();
542 }
543
544 /* There was no remaining data in this input vector */
545 if (msg->msg.in_size[invec_idx] == 0) {
546 return 0;
547 }
548
549 /*
550 * Copy the client data to the service buffer. It is a fatal error
551 * if the memory reference for buffer is invalid or not read-write.
552 */
553 if (tfm_memory_check(buffer, num_bytes, false,
554 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
555 tfm_core_panic();
556 }
557
558 bytes = num_bytes > msg->msg.in_size[invec_idx] ?
559 msg->msg.in_size[invec_idx] : num_bytes;
560
561 spm_memcpy(buffer, msg->invec[invec_idx].base, bytes);
562
563 /* There maybe some remaining data */
564 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base + bytes;
565 msg->msg.in_size[invec_idx] -= bytes;
566
567 return bytes;
568}
569
570size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
571 size_t num_bytes)
572{
573 struct tfm_msg_body_t *msg = NULL;
574
575 /* It is a fatal error if message handle is invalid */
576 msg = tfm_spm_get_msg_from_handle(msg_handle);
577 if (!msg) {
578 tfm_core_panic();
579 }
580
581 /*
582 * It is a fatal error if message handle does not refer to a request
583 * message
584 */
585 if (msg->msg.type < PSA_IPC_CALL) {
586 tfm_core_panic();
587 }
588
589 /*
590 * It is a fatal error if invec_idx is equal to or greater than
591 * PSA_MAX_IOVEC
592 */
593 if (invec_idx >= PSA_MAX_IOVEC) {
594 tfm_core_panic();
595 }
596
597 /* There was no remaining data in this input vector */
598 if (msg->msg.in_size[invec_idx] == 0) {
599 return 0;
600 }
601
602 /*
603 * If num_bytes is greater than the remaining size of the input vector then
604 * the remaining size of the input vector is used.
605 */
606 if (num_bytes > msg->msg.in_size[invec_idx]) {
607 num_bytes = msg->msg.in_size[invec_idx];
608 }
609
610 /* There maybe some remaining data */
611 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base +
612 num_bytes;
613 msg->msg.in_size[invec_idx] -= num_bytes;
614
615 return num_bytes;
616}
617
618void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
619 const void *buffer, size_t num_bytes)
620{
621 struct tfm_msg_body_t *msg = NULL;
622 uint32_t privileged;
623 struct partition_t *partition = NULL;
624
625 /* It is a fatal error if message handle is invalid */
626 msg = tfm_spm_get_msg_from_handle(msg_handle);
627 if (!msg) {
628 tfm_core_panic();
629 }
630
631 partition = msg->service->partition;
632 privileged = tfm_spm_partition_get_privileged_mode(
633 partition->p_ldinf->flags);
634
635 /*
636 * It is a fatal error if message handle does not refer to a request
637 * message
638 */
639 if (msg->msg.type < PSA_IPC_CALL) {
640 tfm_core_panic();
641 }
642
643 /*
644 * It is a fatal error if outvec_idx is equal to or greater than
645 * PSA_MAX_IOVEC
646 */
647 if (outvec_idx >= PSA_MAX_IOVEC) {
648 tfm_core_panic();
649 }
650
651 /*
652 * It is a fatal error if the call attempts to write data past the end of
653 * the client output vector
654 */
655 if (num_bytes > msg->msg.out_size[outvec_idx] -
656 msg->outvec[outvec_idx].len) {
657 tfm_core_panic();
658 }
659
660 /*
661 * Copy the service buffer to client outvecs. It is a fatal error
662 * if the memory reference for buffer is invalid or not readable.
663 */
664 if (tfm_memory_check(buffer, num_bytes, false,
665 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
666 tfm_core_panic();
667 }
668
669 spm_memcpy((char *)msg->outvec[outvec_idx].base +
670 msg->outvec[outvec_idx].len, buffer, num_bytes);
671
672 /* Update the write number */
673 msg->outvec[outvec_idx].len += num_bytes;
674}
675
676void tfm_spm_partition_psa_reply(psa_handle_t msg_handle, psa_status_t status)
677{
678 struct service_t *service = NULL;
679 struct tfm_msg_body_t *msg = NULL;
680 int32_t ret = PSA_SUCCESS;
681 struct tfm_conn_handle_t *conn_handle;
682
683 /* It is a fatal error if message handle is invalid */
684 msg = tfm_spm_get_msg_from_handle(msg_handle);
685 if (!msg) {
686 tfm_core_panic();
687 }
688
689 /*
690 * RoT Service information is needed in this function, stored it in message
691 * body structure. Only two parameters are passed in this function: handle
692 * and status, so it is useful and simply to do like this.
693 */
694 service = msg->service;
695 if (!service) {
696 tfm_core_panic();
697 }
698
699 /*
700 * Three type of message are passed in this function: CONNECTION, REQUEST,
701 * DISCONNECTION. It needs to process differently for each type.
702 */
703 conn_handle = tfm_spm_to_handle_instance(msg_handle);
704 switch (msg->msg.type) {
705 case PSA_IPC_CONNECT:
706 /*
707 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
708 * input status is PSA_SUCCESS. Others return values are based on the
709 * input status.
710 */
711 if (status == PSA_SUCCESS) {
712 ret = msg_handle;
713 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
714 /* Refuse the client connection, indicating a permanent error. */
715 tfm_spm_free_conn_handle(service, conn_handle);
716 ret = PSA_ERROR_CONNECTION_REFUSED;
717 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
718 /* Fail the client connection, indicating a transient error. */
719 ret = PSA_ERROR_CONNECTION_BUSY;
720 } else {
721 tfm_core_panic();
722 }
723 break;
724 case PSA_IPC_DISCONNECT:
725 /* Service handle is not used anymore */
726 tfm_spm_free_conn_handle(service, conn_handle);
727
728 /*
729 * If the message type is PSA_IPC_DISCONNECT, then the status code is
730 * ignored
731 */
732 break;
733 default:
734 if (msg->msg.type >= PSA_IPC_CALL) {
735 /* Reply to a request message. Return values are based on status */
736 ret = status;
737 /*
738 * The total number of bytes written to a single parameter must be
739 * reported to the client by updating the len member of the
740 * psa_outvec structure for the parameter before returning from
741 * psa_call().
742 */
743 update_caller_outvec_len(msg);
744 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
745 tfm_spm_free_conn_handle(service, conn_handle);
746 }
747 } else {
748 tfm_core_panic();
749 }
750 }
751
752 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
753 /*
754 * If the source of the programmer error is a Secure Partition, the SPM
755 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
756 */
757 if (TFM_CLIENT_ID_IS_NS(msg->msg.client_id)) {
758 conn_handle->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
759 } else {
760 tfm_core_panic();
761 }
762 } else {
763 conn_handle->status = TFM_HANDLE_STATUS_IDLE;
764 }
765
766 if (is_tfm_rpc_msg(msg)) {
767 tfm_rpc_client_call_reply(msg, ret);
768 } else {
Ken Liu5d73c872021-08-19 19:23:17 +0800769 thrd_wake_up(&msg->ack_evnt, ret);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800770 }
771}
772
773void tfm_spm_partition_psa_notify(int32_t partition_id)
774{
Ken Liu5d73c872021-08-19 19:23:17 +0800775 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
776
777 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800778}
779
780void tfm_spm_partition_psa_clear(void)
781{
Ken Liu92ede9f2021-10-20 09:35:00 +0800782 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800783 struct partition_t *partition = NULL;
784
785 partition = tfm_spm_get_running_partition();
786 if (!partition) {
787 tfm_core_panic();
788 }
789
790 /*
791 * It is a fatal error if the Secure Partition's doorbell signal is not
792 * currently asserted.
793 */
794 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
795 tfm_core_panic();
796 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800797
798 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800799 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800800 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800801}
802
803void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
804{
Ken Liu92ede9f2021-10-20 09:35:00 +0800805 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800806 struct irq_load_info_t *irq_info = NULL;
807 struct partition_t *partition = NULL;
808
809 partition = tfm_spm_get_running_partition();
810 if (!partition) {
811 tfm_core_panic();
812 }
813
814 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
815 /* It is a fatal error if passed signal is not an interrupt signal. */
816 if (!irq_info) {
817 tfm_core_panic();
818 }
819
820 if (irq_info->flih_func) {
821 /* This API is for SLIH IRQs only */
822 psa_panic();
823 }
824
825 /* It is a fatal error if passed signal is not currently asserted */
826 if ((partition->signals_asserted & irq_signal) == 0) {
827 tfm_core_panic();
828 }
829
Ken Liu92ede9f2021-10-20 09:35:00 +0800830 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800831 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800832 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800833
Kevin Pengd399a1f2021-09-08 15:33:14 +0800834 tfm_hal_irq_clear_pending(irq_info->source);
835 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800836}
837
838void tfm_spm_partition_psa_panic(void)
839{
840 /*
841 * PSA FF recommends that the SPM causes the system to restart when a secure
842 * partition panics.
843 */
844 tfm_hal_system_reset();
845}
846
847void tfm_spm_partition_irq_enable(psa_signal_t irq_signal)
848{
849 struct partition_t *partition;
850 struct irq_load_info_t *irq_info;
851
852 partition = tfm_spm_get_running_partition();
853 if (!partition) {
854 tfm_core_panic();
855 }
856
857 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
858 if (!irq_info) {
859 tfm_core_panic();
860 }
861
Kevin Pengd399a1f2021-09-08 15:33:14 +0800862 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800863}
864
865psa_irq_status_t tfm_spm_partition_irq_disable(psa_signal_t irq_signal)
866{
867 struct partition_t *partition;
868 struct irq_load_info_t *irq_info;
869
870 partition = tfm_spm_get_running_partition();
871 if (!partition) {
872 tfm_core_panic();
873 }
874
875 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
876 if (!irq_info) {
877 tfm_core_panic();
878 }
879
Kevin Pengd399a1f2021-09-08 15:33:14 +0800880 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800881
882 return 1;
883}
884
885void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
886{
Ken Liu92ede9f2021-10-20 09:35:00 +0800887 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800888 struct irq_load_info_t *irq_info;
889 struct partition_t *partition;
890
891 partition = tfm_spm_get_running_partition();
892 if (!partition) {
893 tfm_core_panic();
894 }
895
896 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
897 if (!irq_info) {
898 tfm_core_panic();
899 }
900
901 if (!irq_info->flih_func) {
902 /* This API is for FLIH IRQs only */
903 tfm_core_panic();
904 }
905
906 if ((partition->signals_asserted & irq_signal) == 0) {
907 /* The signal is not asserted */
908 tfm_core_panic();
909 }
910
Ken Liu92ede9f2021-10-20 09:35:00 +0800911 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800912 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800913 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800914}