blob: b38f85c9e94ac5e251dec635ef9a09f1deb0a171 [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"
Mingyang Suneeca4652021-07-15 15:19:16 +080010#include "psa/lifecycle.h"
David Hu733d8f92019-09-23 15:32:40 +080011#include "psa/service.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080012#include "spm_ipc.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080013#include "tfm_arch.h"
David Hu733d8f92019-09-23 15:32:40 +080014#include "tfm_core_utils.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080015#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080016#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080017#include "load/interrupt_defs.h"
Mingyang Sun133a7922021-07-08 16:01:26 +080018#include "psa_api.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 Liubcae38b2021-01-20 15:47:44 +080021#include "ffm/spm_error_base.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080022#include "tfm_rpc.h"
23#include "tfm_spm_hal.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080024#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080025#include "tfm_hal_platform.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080026#include "tfm_psa_call_param.h"
David Hu733d8f92019-09-23 15:32:40 +080027
Ken Liub3b2cb62021-05-22 00:39:28 +080028#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080029extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080030
Mingyang Suneeca4652021-07-15 15:19:16 +080031uint32_t tfm_spm_get_lifecycle_state(void)
32{
33 /*
34 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
35 * implemented in the future.
36 */
37 return PSA_LIFECYCLE_UNKNOWN;
38}
39
40/* PSA Client API function body */
41
Mingyang Sund44522a2020-01-16 16:48:37 +080042uint32_t tfm_spm_client_psa_framework_version(void)
David Hu733d8f92019-09-23 15:32:40 +080043{
44 return PSA_FRAMEWORK_VERSION;
45}
46
Mingyang Sun22a3faf2021-07-09 15:32:47 +080047uint32_t tfm_spm_client_psa_version(uint32_t sid)
David Hu733d8f92019-09-23 15:32:40 +080048{
Mingyang Sun783a59b2021-04-20 15:52:18 +080049 struct service_t *service;
Mingyang Sun22a3faf2021-07-09 15:32:47 +080050 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +080051
52 /*
53 * It should return PSA_VERSION_NONE if the RoT Service is not
54 * implemented.
55 */
56 service = tfm_spm_get_service_by_sid(sid);
57 if (!service) {
58 return PSA_VERSION_NONE;
59 }
60
61 /*
Shawn Shan2365c902019-12-19 18:35:36 +080062 * It should return PSA_VERSION_NONE if the caller is not authorized
63 * to access the RoT Service.
David Hu733d8f92019-09-23 15:32:40 +080064 */
Ken Liubcae38b2021-01-20 15:47:44 +080065 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
Shawn Shan2365c902019-12-19 18:35:36 +080066 return PSA_VERSION_NONE;
David Hu733d8f92019-09-23 15:32:40 +080067 }
68
Ken Liuacd2a572021-05-12 16:19:04 +080069 return service->p_ldinf->version;
David Hu733d8f92019-09-23 15:32:40 +080070}
71
Mingyang Sun22a3faf2021-07-09 15:32:47 +080072psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
David Hu733d8f92019-09-23 15:32:40 +080073{
Mingyang Sun783a59b2021-04-20 15:52:18 +080074 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +080075 struct tfm_msg_body_t *msg;
Summer Qin630c76b2020-05-20 10:32:58 +080076 struct tfm_conn_handle_t *connect_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +080077 int32_t client_id;
Ken Liu505b1702020-05-29 13:19:58 +080078 psa_handle_t handle;
Mingyang Sun22a3faf2021-07-09 15:32:47 +080079 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +080080
Kevin Pengedb8ee42021-03-09 16:50:11 +080081 /*
82 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
83 * platform.
84 */
David Hu733d8f92019-09-23 15:32:40 +080085 service = tfm_spm_get_service_by_sid(sid);
86 if (!service) {
Shawn Shanb222d892021-01-04 17:41:48 +080087 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
David Hu733d8f92019-09-23 15:32:40 +080088 }
89
Mingyang Sunef42f442021-06-11 15:07:58 +080090 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
91 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
92 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
93 }
94
Kevin Pengedb8ee42021-03-09 16:50:11 +080095 /*
96 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
97 * RoT Service.
98 */
99 if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
100 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
101 }
102
103 /*
104 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
105 * not supported on the platform.
106 */
107 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
108 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
109 }
110
Kevin Peng385fda82021-08-18 10:41:19 +0800111 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800112
David Hu733d8f92019-09-23 15:32:40 +0800113 /*
114 * Create connection handle here since it is possible to return the error
115 * code to client when creation fails.
116 */
Summer Qin1ce712a2019-10-14 18:04:05 +0800117 connect_handle = tfm_spm_create_conn_handle(service, client_id);
Summer Qin630c76b2020-05-20 10:32:58 +0800118 if (!connect_handle) {
David Hu733d8f92019-09-23 15:32:40 +0800119 return PSA_ERROR_CONNECTION_BUSY;
120 }
121
Kevin Pengdf6aa292021-03-11 17:58:50 +0800122 msg = tfm_spm_get_msg_buffer_from_conn_handle(connect_handle);
123 if (!msg) {
124 /* Have no enough resource to create message */
125 return PSA_ERROR_CONNECTION_BUSY;
126 }
David Hu733d8f92019-09-23 15:32:40 +0800127
Ken Liu505b1702020-05-29 13:19:58 +0800128 handle = tfm_spm_to_user_handle(connect_handle);
David Hu733d8f92019-09-23 15:32:40 +0800129 /* No input or output needed for connect message */
Ken Liu505b1702020-05-29 13:19:58 +0800130 tfm_spm_fill_msg(msg, service, handle, PSA_IPC_CONNECT,
Summer Qin1ce712a2019-10-14 18:04:05 +0800131 client_id, NULL, 0, NULL, 0, NULL);
David Hu733d8f92019-09-23 15:32:40 +0800132
David Hu733d8f92019-09-23 15:32:40 +0800133
Mingyang Sundeae45d2021-09-06 15:31:07 +0800134 return backend_instance.messaging(service, msg);
David Hu733d8f92019-09-23 15:32:40 +0800135}
136
Mingyang Suneeca4652021-07-15 15:19:16 +0800137psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
138 uint32_t ctrl_param,
139 const psa_invec *inptr,
140 psa_outvec *outptr)
David Hu733d8f92019-09-23 15:32:40 +0800141{
142 psa_invec invecs[PSA_MAX_IOVEC];
143 psa_outvec outvecs[PSA_MAX_IOVEC];
Summer Qin630c76b2020-05-20 10:32:58 +0800144 struct tfm_conn_handle_t *conn_handle;
Mingyang Sun783a59b2021-04-20 15:52:18 +0800145 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +0800146 struct tfm_msg_body_t *msg;
Summer Qinba2346e2019-11-12 16:26:31 +0800147 int i, j;
Summer Qin1ce712a2019-10-14 18:04:05 +0800148 int32_t client_id;
Mingyang Sun453ad402021-03-17 17:58:33 +0800149 uint32_t sid, version, index;
Mingyang Sune529e3b2021-07-12 14:46:30 +0800150 uint32_t privileged;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800151 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800152 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
153 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
154 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800155
156 /* The request type must be zero or positive. */
157 if (type < 0) {
158 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
159 }
David Hu733d8f92019-09-23 15:32:40 +0800160
Shawn Shanb222d892021-01-04 17:41:48 +0800161 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800162 if ((in_num > PSA_MAX_IOVEC) ||
163 (out_num > PSA_MAX_IOVEC) ||
164 (in_num + out_num > PSA_MAX_IOVEC)) {
Shawn Shanb222d892021-01-04 17:41:48 +0800165 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800166 }
167
Kevin Peng385fda82021-08-18 10:41:19 +0800168 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800169
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800170 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800171 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800172 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800173
174 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
175 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
176 }
177
Mingyang Sun453ad402021-03-17 17:58:33 +0800178 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800179 if (!service) {
180 tfm_core_panic();
181 }
182
Ken Liub3b2cb62021-05-22 00:39:28 +0800183 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800184
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800185 /*
186 * It is a PROGRAMMER ERROR if the caller is not authorized to access
187 * the RoT Service.
188 */
189 if (tfm_spm_check_authorization(sid, service, ns_caller)
190 != SPM_SUCCESS) {
191 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
192 }
193
Mingyang Sun453ad402021-03-17 17:58:33 +0800194 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
195
196 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
197 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
198 }
199
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800200 conn_handle = tfm_spm_create_conn_handle(service, client_id);
201
202 if (!conn_handle) {
203 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_BUSY);
204 }
205
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800206 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800207 handle = tfm_spm_to_user_handle(conn_handle);
208 } else {
209 conn_handle = tfm_spm_to_handle_instance(handle);
210
211 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
212 if (tfm_spm_validate_conn_handle(conn_handle, client_id)
213 != SPM_SUCCESS) {
214 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
215 }
216
217 /*
218 * It is a PROGRAMMER ERROR if the connection is currently
219 * handling a request.
220 */
221 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
222 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
223 }
224
225 /*
226 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
227 * has been terminated by the RoT Service.
228 */
229 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
230 return PSA_ERROR_PROGRAMMER_ERROR;
231 }
232
233 service = conn_handle->service;
Summer Qin1ce712a2019-10-14 18:04:05 +0800234 }
Shawn Shanb222d892021-01-04 17:41:48 +0800235
David Hu733d8f92019-09-23 15:32:40 +0800236 if (!service) {
237 /* FixMe: Need to implement one mechanism to resolve this failure. */
Edison Ai9059ea02019-11-28 13:46:14 +0800238 tfm_core_panic();
David Hu733d8f92019-09-23 15:32:40 +0800239 }
240
Mingyang Sune529e3b2021-07-12 14:46:30 +0800241 privileged = tfm_spm_get_caller_privilege_mode();
242
Kevin Pengedb8ee42021-03-09 16:50:11 +0800243 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800244 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800245 * if the memory reference for the wrap input vector is invalid or not
246 * readable.
247 */
248 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800249 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800250 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800251 }
Summer Qinba2346e2019-11-12 16:26:31 +0800252
David Hu733d8f92019-09-23 15:32:40 +0800253 /*
254 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800255 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800256 * the wrap output vector is invalid or not read-write.
257 */
258 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800259 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800260 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800261 }
262
Summer Qinf24dbb52020-07-23 14:53:54 +0800263 spm_memset(invecs, 0, sizeof(invecs));
264 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800265
266 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800267 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
268 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800269
270 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800271 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800272 * memory reference was invalid or not readable.
273 */
274 for (i = 0; i < in_num; i++) {
275 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800276 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800277 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800278 }
279 }
Summer Qinba2346e2019-11-12 16:26:31 +0800280
281 /*
282 * Clients must never overlap input parameters because of the risk of a
283 * double-fetch inconsistency.
284 * Overflow is checked in tfm_memory_check functions.
285 */
286 for (i = 0; i + 1 < in_num; i++) {
287 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100288 if (!((char *) invecs[j].base + invecs[j].len <=
289 (char *) invecs[i].base ||
290 (char *) invecs[j].base >=
291 (char *) invecs[i].base + invecs[i].len)) {
Shawn Shanb222d892021-01-04 17:41:48 +0800292 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
Summer Qinba2346e2019-11-12 16:26:31 +0800293 }
294 }
295 }
296
David Hu733d8f92019-09-23 15:32:40 +0800297 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800298 * For client output vector, it is a PROGRAMMER ERROR if the provided
299 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800300 */
301 for (i = 0; i < out_num; i++) {
302 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800303 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800304 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800305 }
306 }
307
308 /*
309 * FixMe: Need to check if the message is unrecognized by the RoT
310 * Service or incorrectly formatted.
311 */
Kevin Pengdf6aa292021-03-11 17:58:50 +0800312 msg = tfm_spm_get_msg_buffer_from_conn_handle(conn_handle);
313 if (!msg) {
314 /* FixMe: Need to implement one mechanism to resolve this failure. */
315 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
316 }
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
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800324void tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800325{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800326 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +0800327 struct tfm_msg_body_t *msg;
Summer Qin630c76b2020-05-20 10:32:58 +0800328 struct tfm_conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800329 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800330 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800331
332 /* It will have no effect if called with the NULL handle */
333 if (handle == PSA_NULL_HANDLE) {
334 return;
335 }
336
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800337 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800338 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800339 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
340 }
341
Kevin Peng385fda82021-08-18 10:41:19 +0800342 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800343
Summer Qin373feb12020-03-27 15:35:33 +0800344 conn_handle = tfm_spm_to_handle_instance(handle);
David Hu733d8f92019-09-23 15:32:40 +0800345 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800346 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
347 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800348 */
Ken Liubcae38b2021-01-20 15:47:44 +0800349 if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800350 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
Summer Qin1ce712a2019-10-14 18:04:05 +0800351 }
Shawn Shanb222d892021-01-04 17:41:48 +0800352
Summer Qin630c76b2020-05-20 10:32:58 +0800353 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800354 if (!service) {
355 /* FixMe: Need to implement one mechanism to resolve this failure. */
Edison Ai9059ea02019-11-28 13:46:14 +0800356 tfm_core_panic();
David Hu733d8f92019-09-23 15:32:40 +0800357 }
358
Kevin Pengdf6aa292021-03-11 17:58:50 +0800359 msg = tfm_spm_get_msg_buffer_from_conn_handle(conn_handle);
360 if (!msg) {
361 /* FixMe: Need to implement one mechanism to resolve this failure. */
362 tfm_core_panic();
363 }
David Hu733d8f92019-09-23 15:32:40 +0800364
Shawn Shanb222d892021-01-04 17:41:48 +0800365 /*
366 * It is a PROGRAMMER ERROR if the connection is currently handling a
367 * request.
368 */
Summer Qin630c76b2020-05-20 10:32:58 +0800369 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Shawn Shanb222d892021-01-04 17:41:48 +0800370 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
Shawn Shancc39fcb2019-11-13 15:38:16 +0800371 }
372
David Hu733d8f92019-09-23 15:32:40 +0800373 /* No input or output needed for close message */
Ken Liu505b1702020-05-29 13:19:58 +0800374 tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, client_id,
David Hu733d8f92019-09-23 15:32:40 +0800375 NULL, 0, NULL, 0, NULL);
376
Mingyang Sundeae45d2021-09-06 15:31:07 +0800377 (void)backend_instance.messaging(service, msg);
David Hu733d8f92019-09-23 15:32:40 +0800378}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800379
Mingyang Suneeca4652021-07-15 15:19:16 +0800380/* PSA Partition API function body */
381
Mingyang Sunb26b2802021-07-07 11:25:00 +0800382psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
383 uint32_t timeout)
384{
385 struct partition_t *partition = NULL;
386
387 /*
388 * Timeout[30:0] are reserved for future use.
389 * SPM must ignore the value of RES.
390 */
391 timeout &= PSA_TIMEOUT_MASK;
392
393 partition = tfm_spm_get_running_partition();
394 if (!partition) {
395 tfm_core_panic();
396 }
397
398 /*
399 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
400 * signals.
401 */
402 if ((partition->signals_allowed & signal_mask) == 0) {
403 tfm_core_panic();
404 }
405
406 /*
Ken Liu5d73c872021-08-19 19:23:17 +0800407 * thrd_wait_on() blocks the caller thread if no signals are available.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800408 * In this case, the return value of this function is temporary set into
409 * runtime context. After new signal(s) are available, the return value
410 * is updated with the available signal(s) and blocked thread gets to run.
411 */
412 if (timeout == PSA_BLOCK &&
413 (partition->signals_asserted & signal_mask) == 0) {
414 partition->signals_waiting = signal_mask;
Ken Liu5d73c872021-08-19 19:23:17 +0800415 thrd_wait_on(&partition->waitobj,
416 &(tfm_spm_get_running_partition()->thrd));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800417 } else if ((partition->signals_asserted & signal_mask) == 0) {
418 /* Activate scheduler to check if any higher priority thread to run */
Ken Liu5d73c872021-08-19 19:23:17 +0800419 tfm_arch_trigger_pendsv();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800420 }
421
422 return partition->signals_asserted & signal_mask;
423}
424
425psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
426{
427 struct tfm_msg_body_t *tmp_msg = NULL;
428 struct partition_t *partition = NULL;
429 uint32_t privileged;
430
431 /*
432 * Only one message could be retrieved every time for psa_get(). It is a
433 * fatal error if the input signal has more than a signal bit set.
434 */
435 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
436 tfm_core_panic();
437 }
438
439 partition = tfm_spm_get_running_partition();
440 if (!partition) {
441 tfm_core_panic();
442 }
443 privileged = tfm_spm_partition_get_privileged_mode(
444 partition->p_ldinf->flags);
445
446 /*
447 * Write the message to the service buffer. It is a fatal error if the
448 * input msg pointer is not a valid memory reference or not read-write.
449 */
450 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
451 privileged) != SPM_SUCCESS) {
452 tfm_core_panic();
453 }
454
455 /*
456 * It is a fatal error if the caller call psa_get() when no message has
457 * been set. The caller must call this function after an RoT Service signal
458 * is returned by psa_wait().
459 */
460 if (partition->signals_asserted == 0) {
461 tfm_core_panic();
462 }
463
464 /*
465 * It is a fatal error if the RoT Service signal is not currently asserted.
466 */
467 if ((partition->signals_asserted & signal) == 0) {
468 tfm_core_panic();
469 }
470
471 /*
472 * Get message by signal from partition. It is a fatal error if getting
473 * failed, which means the input signal is not correspond to an RoT service.
474 */
475 tmp_msg = tfm_spm_get_msg_by_signal(partition, signal);
476 if (!tmp_msg) {
477 return PSA_ERROR_DOES_NOT_EXIST;
478 }
479
480 (TO_CONTAINER(tmp_msg,
481 struct tfm_conn_handle_t,
482 internal_msg))->status = TFM_HANDLE_STATUS_ACTIVE;
483
484 spm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t));
485
486 return PSA_SUCCESS;
487}
488
489void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
490{
491 struct tfm_msg_body_t *msg = NULL;
492 struct tfm_conn_handle_t *conn_handle;
493
494 /* It is a fatal error if message handle is invalid */
495 msg = tfm_spm_get_msg_from_handle(msg_handle);
496 if (!msg) {
497 tfm_core_panic();
498 }
499
500 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
501 if (SERVICE_IS_STATELESS(msg->service->p_ldinf->flags)) {
502 tfm_core_panic();
503 }
504
505 msg->msg.rhandle = rhandle;
506 conn_handle = tfm_spm_to_handle_instance(msg_handle);
507
508 /* Store reverse handle for following client calls. */
509 tfm_spm_set_rhandle(msg->service, conn_handle, rhandle);
510}
511
512size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
513 void *buffer, size_t num_bytes)
514{
515 size_t bytes;
516 struct tfm_msg_body_t *msg = NULL;
517 uint32_t privileged;
518 struct partition_t *partition = NULL;
519
520 /* It is a fatal error if message handle is invalid */
521 msg = tfm_spm_get_msg_from_handle(msg_handle);
522 if (!msg) {
523 tfm_core_panic();
524 }
525
526 partition = msg->service->partition;
527 privileged = tfm_spm_partition_get_privileged_mode(
528 partition->p_ldinf->flags);
529
530 /*
531 * It is a fatal error if message handle does not refer to a request
532 * message
533 */
534 if (msg->msg.type < PSA_IPC_CALL) {
535 tfm_core_panic();
536 }
537
538 /*
539 * It is a fatal error if invec_idx is equal to or greater than
540 * PSA_MAX_IOVEC
541 */
542 if (invec_idx >= PSA_MAX_IOVEC) {
543 tfm_core_panic();
544 }
545
546 /* There was no remaining data in this input vector */
547 if (msg->msg.in_size[invec_idx] == 0) {
548 return 0;
549 }
550
551 /*
552 * Copy the client data to the service buffer. It is a fatal error
553 * if the memory reference for buffer is invalid or not read-write.
554 */
555 if (tfm_memory_check(buffer, num_bytes, false,
556 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
557 tfm_core_panic();
558 }
559
560 bytes = num_bytes > msg->msg.in_size[invec_idx] ?
561 msg->msg.in_size[invec_idx] : num_bytes;
562
563 spm_memcpy(buffer, msg->invec[invec_idx].base, bytes);
564
565 /* There maybe some remaining data */
566 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base + bytes;
567 msg->msg.in_size[invec_idx] -= bytes;
568
569 return bytes;
570}
571
572size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
573 size_t num_bytes)
574{
575 struct tfm_msg_body_t *msg = NULL;
576
577 /* It is a fatal error if message handle is invalid */
578 msg = tfm_spm_get_msg_from_handle(msg_handle);
579 if (!msg) {
580 tfm_core_panic();
581 }
582
583 /*
584 * It is a fatal error if message handle does not refer to a request
585 * message
586 */
587 if (msg->msg.type < PSA_IPC_CALL) {
588 tfm_core_panic();
589 }
590
591 /*
592 * It is a fatal error if invec_idx is equal to or greater than
593 * PSA_MAX_IOVEC
594 */
595 if (invec_idx >= PSA_MAX_IOVEC) {
596 tfm_core_panic();
597 }
598
599 /* There was no remaining data in this input vector */
600 if (msg->msg.in_size[invec_idx] == 0) {
601 return 0;
602 }
603
604 /*
605 * If num_bytes is greater than the remaining size of the input vector then
606 * the remaining size of the input vector is used.
607 */
608 if (num_bytes > msg->msg.in_size[invec_idx]) {
609 num_bytes = msg->msg.in_size[invec_idx];
610 }
611
612 /* There maybe some remaining data */
613 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base +
614 num_bytes;
615 msg->msg.in_size[invec_idx] -= num_bytes;
616
617 return num_bytes;
618}
619
620void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
621 const void *buffer, size_t num_bytes)
622{
623 struct tfm_msg_body_t *msg = NULL;
624 uint32_t privileged;
625 struct partition_t *partition = NULL;
626
627 /* It is a fatal error if message handle is invalid */
628 msg = tfm_spm_get_msg_from_handle(msg_handle);
629 if (!msg) {
630 tfm_core_panic();
631 }
632
633 partition = msg->service->partition;
634 privileged = tfm_spm_partition_get_privileged_mode(
635 partition->p_ldinf->flags);
636
637 /*
638 * It is a fatal error if message handle does not refer to a request
639 * message
640 */
641 if (msg->msg.type < PSA_IPC_CALL) {
642 tfm_core_panic();
643 }
644
645 /*
646 * It is a fatal error if outvec_idx is equal to or greater than
647 * PSA_MAX_IOVEC
648 */
649 if (outvec_idx >= PSA_MAX_IOVEC) {
650 tfm_core_panic();
651 }
652
653 /*
654 * It is a fatal error if the call attempts to write data past the end of
655 * the client output vector
656 */
657 if (num_bytes > msg->msg.out_size[outvec_idx] -
658 msg->outvec[outvec_idx].len) {
659 tfm_core_panic();
660 }
661
662 /*
663 * Copy the service buffer to client outvecs. It is a fatal error
664 * if the memory reference for buffer is invalid or not readable.
665 */
666 if (tfm_memory_check(buffer, num_bytes, false,
667 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
668 tfm_core_panic();
669 }
670
671 spm_memcpy((char *)msg->outvec[outvec_idx].base +
672 msg->outvec[outvec_idx].len, buffer, num_bytes);
673
674 /* Update the write number */
675 msg->outvec[outvec_idx].len += num_bytes;
676}
677
678void tfm_spm_partition_psa_reply(psa_handle_t msg_handle, psa_status_t status)
679{
680 struct service_t *service = NULL;
681 struct tfm_msg_body_t *msg = NULL;
682 int32_t ret = PSA_SUCCESS;
683 struct tfm_conn_handle_t *conn_handle;
684
685 /* It is a fatal error if message handle is invalid */
686 msg = tfm_spm_get_msg_from_handle(msg_handle);
687 if (!msg) {
688 tfm_core_panic();
689 }
690
691 /*
692 * RoT Service information is needed in this function, stored it in message
693 * body structure. Only two parameters are passed in this function: handle
694 * and status, so it is useful and simply to do like this.
695 */
696 service = msg->service;
697 if (!service) {
698 tfm_core_panic();
699 }
700
701 /*
702 * Three type of message are passed in this function: CONNECTION, REQUEST,
703 * DISCONNECTION. It needs to process differently for each type.
704 */
705 conn_handle = tfm_spm_to_handle_instance(msg_handle);
706 switch (msg->msg.type) {
707 case PSA_IPC_CONNECT:
708 /*
709 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
710 * input status is PSA_SUCCESS. Others return values are based on the
711 * input status.
712 */
713 if (status == PSA_SUCCESS) {
714 ret = msg_handle;
715 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
716 /* Refuse the client connection, indicating a permanent error. */
717 tfm_spm_free_conn_handle(service, conn_handle);
718 ret = PSA_ERROR_CONNECTION_REFUSED;
719 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
720 /* Fail the client connection, indicating a transient error. */
721 ret = PSA_ERROR_CONNECTION_BUSY;
722 } else {
723 tfm_core_panic();
724 }
725 break;
726 case PSA_IPC_DISCONNECT:
727 /* Service handle is not used anymore */
728 tfm_spm_free_conn_handle(service, conn_handle);
729
730 /*
731 * If the message type is PSA_IPC_DISCONNECT, then the status code is
732 * ignored
733 */
734 break;
735 default:
736 if (msg->msg.type >= PSA_IPC_CALL) {
737 /* Reply to a request message. Return values are based on status */
738 ret = status;
739 /*
740 * The total number of bytes written to a single parameter must be
741 * reported to the client by updating the len member of the
742 * psa_outvec structure for the parameter before returning from
743 * psa_call().
744 */
745 update_caller_outvec_len(msg);
746 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
747 tfm_spm_free_conn_handle(service, conn_handle);
748 }
749 } else {
750 tfm_core_panic();
751 }
752 }
753
754 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
755 /*
756 * If the source of the programmer error is a Secure Partition, the SPM
757 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
758 */
759 if (TFM_CLIENT_ID_IS_NS(msg->msg.client_id)) {
760 conn_handle->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
761 } else {
762 tfm_core_panic();
763 }
764 } else {
765 conn_handle->status = TFM_HANDLE_STATUS_IDLE;
766 }
767
768 if (is_tfm_rpc_msg(msg)) {
769 tfm_rpc_client_call_reply(msg, ret);
770 } else {
Ken Liu5d73c872021-08-19 19:23:17 +0800771 thrd_wake_up(&msg->ack_evnt, ret);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800772 }
773}
774
775void tfm_spm_partition_psa_notify(int32_t partition_id)
776{
Ken Liu5d73c872021-08-19 19:23:17 +0800777 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
778
779 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800780}
781
782void tfm_spm_partition_psa_clear(void)
783{
784 struct partition_t *partition = NULL;
785
786 partition = tfm_spm_get_running_partition();
787 if (!partition) {
788 tfm_core_panic();
789 }
790
791 /*
792 * It is a fatal error if the Secure Partition's doorbell signal is not
793 * currently asserted.
794 */
795 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
796 tfm_core_panic();
797 }
798 partition->signals_asserted &= ~PSA_DOORBELL;
799}
800
801void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
802{
803 struct irq_load_info_t *irq_info = NULL;
804 struct partition_t *partition = NULL;
805
806 partition = tfm_spm_get_running_partition();
807 if (!partition) {
808 tfm_core_panic();
809 }
810
811 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
812 /* It is a fatal error if passed signal is not an interrupt signal. */
813 if (!irq_info) {
814 tfm_core_panic();
815 }
816
817 if (irq_info->flih_func) {
818 /* This API is for SLIH IRQs only */
819 psa_panic();
820 }
821
822 /* It is a fatal error if passed signal is not currently asserted */
823 if ((partition->signals_asserted & irq_signal) == 0) {
824 tfm_core_panic();
825 }
826
827 partition->signals_asserted &= ~irq_signal;
828
Kevin Pengd399a1f2021-09-08 15:33:14 +0800829 tfm_hal_irq_clear_pending(irq_info->source);
830 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800831}
832
833void tfm_spm_partition_psa_panic(void)
834{
835 /*
836 * PSA FF recommends that the SPM causes the system to restart when a secure
837 * partition panics.
838 */
839 tfm_hal_system_reset();
840}
841
842void tfm_spm_partition_irq_enable(psa_signal_t irq_signal)
843{
844 struct partition_t *partition;
845 struct irq_load_info_t *irq_info;
846
847 partition = tfm_spm_get_running_partition();
848 if (!partition) {
849 tfm_core_panic();
850 }
851
852 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
853 if (!irq_info) {
854 tfm_core_panic();
855 }
856
Kevin Pengd399a1f2021-09-08 15:33:14 +0800857 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800858}
859
860psa_irq_status_t tfm_spm_partition_irq_disable(psa_signal_t irq_signal)
861{
862 struct partition_t *partition;
863 struct irq_load_info_t *irq_info;
864
865 partition = tfm_spm_get_running_partition();
866 if (!partition) {
867 tfm_core_panic();
868 }
869
870 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
871 if (!irq_info) {
872 tfm_core_panic();
873 }
874
Kevin Pengd399a1f2021-09-08 15:33:14 +0800875 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800876
877 return 1;
878}
879
880void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
881{
882 struct irq_load_info_t *irq_info;
883 struct partition_t *partition;
884
885 partition = tfm_spm_get_running_partition();
886 if (!partition) {
887 tfm_core_panic();
888 }
889
890 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
891 if (!irq_info) {
892 tfm_core_panic();
893 }
894
895 if (!irq_info->flih_func) {
896 /* This API is for FLIH IRQs only */
897 tfm_core_panic();
898 }
899
900 if ((partition->signals_asserted & irq_signal) == 0) {
901 /* The signal is not asserted */
902 tfm_core_panic();
903 }
904
905 partition->signals_asserted &= ~irq_signal;
906}