blob: ea6a098837ed407e274830b34d2cb82bd53fdde8 [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"
Mingyang Sunb26b2802021-07-07 11:25:00 +080017#include "load/irq_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"
David Hu733d8f92019-09-23 15:32:40 +080020#include "tfm_wait.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"
24#include "tfm_hal_platform.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080025#include "tfm_psa_call_param.h"
David Hu733d8f92019-09-23 15:32:40 +080026
Ken Liub3b2cb62021-05-22 00:39:28 +080027#define GET_STATELESS_SERVICE(index) (stateless_services_ref_tbl[index])
Xinyu Zhanga38e9b52021-06-02 17:48:01 +080028extern struct service_t *stateless_services_ref_tbl[];
Mingyang Suncb6f70e2021-03-05 23:30:25 +080029
Mingyang Suneeca4652021-07-15 15:19:16 +080030
31uint32_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
133 /*
134 * Send message and wake up the SP who is waiting on message queue,
135 * and scheduler triggered
136 */
137 tfm_spm_send_event(service, msg);
138
139 return PSA_SUCCESS;
140}
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 Sun22a3faf2021-07-09 15:32:47 +0800156 bool ns_caller = tfm_spm_is_ns_caller();
Mingyang Suneeca4652021-07-15 15:19:16 +0800157 int32_t type = (int32_t)(int16_t)((ctrl_param & TYPE_MASK) >> TYPE_OFFSET);
158 size_t in_num = (size_t)((ctrl_param & IN_LEN_MASK) >> IN_LEN_OFFSET);
159 size_t out_num = (size_t)((ctrl_param & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800160
161 /* The request type must be zero or positive. */
162 if (type < 0) {
163 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
164 }
David Hu733d8f92019-09-23 15:32:40 +0800165
Shawn Shanb222d892021-01-04 17:41:48 +0800166 /* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
David Hu733d8f92019-09-23 15:32:40 +0800167 if ((in_num > PSA_MAX_IOVEC) ||
168 (out_num > PSA_MAX_IOVEC) ||
169 (in_num + out_num > PSA_MAX_IOVEC)) {
Shawn Shanb222d892021-01-04 17:41:48 +0800170 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800171 }
172
Kevin Peng385fda82021-08-18 10:41:19 +0800173 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800174
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800175 /* Allocate space from handle pool for static handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800176 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun453ad402021-03-17 17:58:33 +0800177 index = GET_INDEX_FROM_STATIC_HANDLE(handle);
Mingyang Sune8d38082021-03-30 18:34:40 +0800178
179 if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
180 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
181 }
182
Mingyang Sun453ad402021-03-17 17:58:33 +0800183 service = GET_STATELESS_SERVICE(index);
Mingyang Sun86213242021-07-14 10:26:43 +0800184 if (!service) {
185 tfm_core_panic();
186 }
187
Ken Liub3b2cb62021-05-22 00:39:28 +0800188 sid = service->p_ldinf->sid;
Mingyang Sun453ad402021-03-17 17:58:33 +0800189
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800190 /*
191 * It is a PROGRAMMER ERROR if the caller is not authorized to access
192 * the RoT Service.
193 */
194 if (tfm_spm_check_authorization(sid, service, ns_caller)
195 != SPM_SUCCESS) {
196 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
197 }
198
Mingyang Sun453ad402021-03-17 17:58:33 +0800199 version = GET_VERSION_FROM_STATIC_HANDLE(handle);
200
201 if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
202 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
203 }
204
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800205 conn_handle = tfm_spm_create_conn_handle(service, client_id);
206
207 if (!conn_handle) {
208 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_BUSY);
209 }
210
Mingyang Sun6d5dc3d2021-03-15 15:34:44 +0800211 conn_handle->rhandle = NULL;
Mingyang Suncb6f70e2021-03-05 23:30:25 +0800212 handle = tfm_spm_to_user_handle(conn_handle);
213 } else {
214 conn_handle = tfm_spm_to_handle_instance(handle);
215
216 /* It is a PROGRAMMER ERROR if an invalid handle was passed. */
217 if (tfm_spm_validate_conn_handle(conn_handle, client_id)
218 != SPM_SUCCESS) {
219 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
220 }
221
222 /*
223 * It is a PROGRAMMER ERROR if the connection is currently
224 * handling a request.
225 */
226 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
227 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
228 }
229
230 /*
231 * Return PSA_ERROR_PROGRAMMER_ERROR immediately for the connection
232 * has been terminated by the RoT Service.
233 */
234 if (conn_handle->status == TFM_HANDLE_STATUS_CONNECT_ERROR) {
235 return PSA_ERROR_PROGRAMMER_ERROR;
236 }
237
238 service = conn_handle->service;
Summer Qin1ce712a2019-10-14 18:04:05 +0800239 }
Shawn Shanb222d892021-01-04 17:41:48 +0800240
David Hu733d8f92019-09-23 15:32:40 +0800241 if (!service) {
242 /* FixMe: Need to implement one mechanism to resolve this failure. */
Edison Ai9059ea02019-11-28 13:46:14 +0800243 tfm_core_panic();
David Hu733d8f92019-09-23 15:32:40 +0800244 }
245
Mingyang Sune529e3b2021-07-12 14:46:30 +0800246 privileged = tfm_spm_get_caller_privilege_mode();
247
Kevin Pengedb8ee42021-03-09 16:50:11 +0800248 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800249 * Read client invecs from the wrap input vector. It is a PROGRAMMER ERROR
David Hu733d8f92019-09-23 15:32:40 +0800250 * if the memory reference for the wrap input vector is invalid or not
251 * readable.
252 */
253 if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800254 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800255 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800256 }
Summer Qinba2346e2019-11-12 16:26:31 +0800257
David Hu733d8f92019-09-23 15:32:40 +0800258 /*
259 * Read client outvecs from the wrap output vector and will update the
Shawn Shanb222d892021-01-04 17:41:48 +0800260 * actual length later. It is a PROGRAMMER ERROR if the memory reference for
David Hu733d8f92019-09-23 15:32:40 +0800261 * the wrap output vector is invalid or not read-write.
262 */
263 if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800264 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800265 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800266 }
267
Summer Qinf24dbb52020-07-23 14:53:54 +0800268 spm_memset(invecs, 0, sizeof(invecs));
269 spm_memset(outvecs, 0, sizeof(outvecs));
David Hu733d8f92019-09-23 15:32:40 +0800270
271 /* Copy the address out to avoid TOCTOU attacks. */
Summer Qinf24dbb52020-07-23 14:53:54 +0800272 spm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
273 spm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
David Hu733d8f92019-09-23 15:32:40 +0800274
275 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800276 * For client input vector, it is a PROGRAMMER ERROR if the provided payload
David Hu733d8f92019-09-23 15:32:40 +0800277 * memory reference was invalid or not readable.
278 */
279 for (i = 0; i < in_num; i++) {
280 if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
Ken Liubcae38b2021-01-20 15:47:44 +0800281 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800282 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800283 }
284 }
Summer Qinba2346e2019-11-12 16:26:31 +0800285
286 /*
287 * Clients must never overlap input parameters because of the risk of a
288 * double-fetch inconsistency.
289 * Overflow is checked in tfm_memory_check functions.
290 */
291 for (i = 0; i + 1 < in_num; i++) {
292 for (j = i+1; j < in_num; j++) {
TTornblom83d96372019-11-19 12:53:16 +0100293 if (!((char *) invecs[j].base + invecs[j].len <=
294 (char *) invecs[i].base ||
295 (char *) invecs[j].base >=
296 (char *) invecs[i].base + invecs[i].len)) {
Shawn Shanb222d892021-01-04 17:41:48 +0800297 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
Summer Qinba2346e2019-11-12 16:26:31 +0800298 }
299 }
300 }
301
David Hu733d8f92019-09-23 15:32:40 +0800302 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800303 * For client output vector, it is a PROGRAMMER ERROR if the provided
304 * payload memory reference was invalid or not read-write.
David Hu733d8f92019-09-23 15:32:40 +0800305 */
306 for (i = 0; i < out_num; i++) {
307 if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
Ken Liubcae38b2021-01-20 15:47:44 +0800308 ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800309 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
David Hu733d8f92019-09-23 15:32:40 +0800310 }
311 }
312
313 /*
314 * FixMe: Need to check if the message is unrecognized by the RoT
315 * Service or incorrectly formatted.
316 */
Kevin Pengdf6aa292021-03-11 17:58:50 +0800317 msg = tfm_spm_get_msg_buffer_from_conn_handle(conn_handle);
318 if (!msg) {
319 /* FixMe: Need to implement one mechanism to resolve this failure. */
320 TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
321 }
David Hu733d8f92019-09-23 15:32:40 +0800322
Ken Liu505b1702020-05-29 13:19:58 +0800323 tfm_spm_fill_msg(msg, service, handle, type, client_id,
Summer Qin630c76b2020-05-20 10:32:58 +0800324 invecs, in_num, outvecs, out_num, outptr);
David Hu733d8f92019-09-23 15:32:40 +0800325
326 /*
327 * Send message and wake up the SP who is waiting on message queue,
328 * and scheduler triggered
329 */
Kevin Peng8dac6102021-03-09 16:44:00 +0800330 tfm_spm_send_event(service, msg);
331
David Hu733d8f92019-09-23 15:32:40 +0800332 return PSA_SUCCESS;
333}
334
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800335void tfm_spm_client_psa_close(psa_handle_t handle)
David Hu733d8f92019-09-23 15:32:40 +0800336{
Mingyang Sun783a59b2021-04-20 15:52:18 +0800337 struct service_t *service;
David Hu733d8f92019-09-23 15:32:40 +0800338 struct tfm_msg_body_t *msg;
Summer Qin630c76b2020-05-20 10:32:58 +0800339 struct tfm_conn_handle_t *conn_handle;
Summer Qin1ce712a2019-10-14 18:04:05 +0800340 int32_t client_id;
Mingyang Sun22a3faf2021-07-09 15:32:47 +0800341 bool ns_caller = tfm_spm_is_ns_caller();
David Hu733d8f92019-09-23 15:32:40 +0800342
343 /* It will have no effect if called with the NULL handle */
344 if (handle == PSA_NULL_HANDLE) {
345 return;
346 }
347
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800348 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
Mingyang Sune8d38082021-03-30 18:34:40 +0800349 if (IS_STATIC_HANDLE(handle)) {
Mingyang Sun00cef5e2021-03-04 13:41:56 +0800350 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
351 }
352
Kevin Peng385fda82021-08-18 10:41:19 +0800353 client_id = tfm_spm_get_client_id(ns_caller);
Summer Qin1ce712a2019-10-14 18:04:05 +0800354
Summer Qin373feb12020-03-27 15:35:33 +0800355 conn_handle = tfm_spm_to_handle_instance(handle);
David Hu733d8f92019-09-23 15:32:40 +0800356 /*
Shawn Shanb222d892021-01-04 17:41:48 +0800357 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
358 * the null handle.
David Hu733d8f92019-09-23 15:32:40 +0800359 */
Ken Liubcae38b2021-01-20 15:47:44 +0800360 if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
Shawn Shanb222d892021-01-04 17:41:48 +0800361 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
Summer Qin1ce712a2019-10-14 18:04:05 +0800362 }
Shawn Shanb222d892021-01-04 17:41:48 +0800363
Summer Qin630c76b2020-05-20 10:32:58 +0800364 service = conn_handle->service;
David Hu733d8f92019-09-23 15:32:40 +0800365 if (!service) {
366 /* FixMe: Need to implement one mechanism to resolve this failure. */
Edison Ai9059ea02019-11-28 13:46:14 +0800367 tfm_core_panic();
David Hu733d8f92019-09-23 15:32:40 +0800368 }
369
Kevin Pengdf6aa292021-03-11 17:58:50 +0800370 msg = tfm_spm_get_msg_buffer_from_conn_handle(conn_handle);
371 if (!msg) {
372 /* FixMe: Need to implement one mechanism to resolve this failure. */
373 tfm_core_panic();
374 }
David Hu733d8f92019-09-23 15:32:40 +0800375
Shawn Shanb222d892021-01-04 17:41:48 +0800376 /*
377 * It is a PROGRAMMER ERROR if the connection is currently handling a
378 * request.
379 */
Summer Qin630c76b2020-05-20 10:32:58 +0800380 if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
Shawn Shanb222d892021-01-04 17:41:48 +0800381 TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
Shawn Shancc39fcb2019-11-13 15:38:16 +0800382 }
383
David Hu733d8f92019-09-23 15:32:40 +0800384 /* No input or output needed for close message */
Ken Liu505b1702020-05-29 13:19:58 +0800385 tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, client_id,
David Hu733d8f92019-09-23 15:32:40 +0800386 NULL, 0, NULL, 0, NULL);
387
388 /*
389 * Send message and wake up the SP who is waiting on message queue,
390 * and scheduler triggered
391 */
392 tfm_spm_send_event(service, msg);
393}
Mingyang Sunb26b2802021-07-07 11:25:00 +0800394
Mingyang Suneeca4652021-07-15 15:19:16 +0800395/* PSA Partition API function body */
396
Mingyang Sunb26b2802021-07-07 11:25:00 +0800397psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
398 uint32_t timeout)
399{
400 struct partition_t *partition = NULL;
401
402 /*
403 * Timeout[30:0] are reserved for future use.
404 * SPM must ignore the value of RES.
405 */
406 timeout &= PSA_TIMEOUT_MASK;
407
408 partition = tfm_spm_get_running_partition();
409 if (!partition) {
410 tfm_core_panic();
411 }
412
413 /*
414 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
415 * signals.
416 */
417 if ((partition->signals_allowed & signal_mask) == 0) {
418 tfm_core_panic();
419 }
420
421 /*
422 * tfm_event_wait() blocks the caller thread if no signals are available.
423 * In this case, the return value of this function is temporary set into
424 * runtime context. After new signal(s) are available, the return value
425 * is updated with the available signal(s) and blocked thread gets to run.
426 */
427 if (timeout == PSA_BLOCK &&
428 (partition->signals_asserted & signal_mask) == 0) {
429 partition->signals_waiting = signal_mask;
430 tfm_event_wait(&partition->event);
431 } else if ((partition->signals_asserted & signal_mask) == 0) {
432 /* Activate scheduler to check if any higher priority thread to run */
433 tfm_core_thrd_activate_schedule();
434 }
435
436 return partition->signals_asserted & signal_mask;
437}
438
439psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
440{
441 struct tfm_msg_body_t *tmp_msg = NULL;
442 struct partition_t *partition = NULL;
443 uint32_t privileged;
444
445 /*
446 * Only one message could be retrieved every time for psa_get(). It is a
447 * fatal error if the input signal has more than a signal bit set.
448 */
449 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
450 tfm_core_panic();
451 }
452
453 partition = tfm_spm_get_running_partition();
454 if (!partition) {
455 tfm_core_panic();
456 }
457 privileged = tfm_spm_partition_get_privileged_mode(
458 partition->p_ldinf->flags);
459
460 /*
461 * Write the message to the service buffer. It is a fatal error if the
462 * input msg pointer is not a valid memory reference or not read-write.
463 */
464 if (tfm_memory_check(msg, sizeof(psa_msg_t), false, TFM_MEMORY_ACCESS_RW,
465 privileged) != SPM_SUCCESS) {
466 tfm_core_panic();
467 }
468
469 /*
470 * It is a fatal error if the caller call psa_get() when no message has
471 * been set. The caller must call this function after an RoT Service signal
472 * is returned by psa_wait().
473 */
474 if (partition->signals_asserted == 0) {
475 tfm_core_panic();
476 }
477
478 /*
479 * It is a fatal error if the RoT Service signal is not currently asserted.
480 */
481 if ((partition->signals_asserted & signal) == 0) {
482 tfm_core_panic();
483 }
484
485 /*
486 * Get message by signal from partition. It is a fatal error if getting
487 * failed, which means the input signal is not correspond to an RoT service.
488 */
489 tmp_msg = tfm_spm_get_msg_by_signal(partition, signal);
490 if (!tmp_msg) {
491 return PSA_ERROR_DOES_NOT_EXIST;
492 }
493
494 (TO_CONTAINER(tmp_msg,
495 struct tfm_conn_handle_t,
496 internal_msg))->status = TFM_HANDLE_STATUS_ACTIVE;
497
498 spm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t));
499
500 return PSA_SUCCESS;
501}
502
503void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
504{
505 struct tfm_msg_body_t *msg = NULL;
506 struct tfm_conn_handle_t *conn_handle;
507
508 /* It is a fatal error if message handle is invalid */
509 msg = tfm_spm_get_msg_from_handle(msg_handle);
510 if (!msg) {
511 tfm_core_panic();
512 }
513
514 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
515 if (SERVICE_IS_STATELESS(msg->service->p_ldinf->flags)) {
516 tfm_core_panic();
517 }
518
519 msg->msg.rhandle = rhandle;
520 conn_handle = tfm_spm_to_handle_instance(msg_handle);
521
522 /* Store reverse handle for following client calls. */
523 tfm_spm_set_rhandle(msg->service, conn_handle, rhandle);
524}
525
526size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
527 void *buffer, size_t num_bytes)
528{
529 size_t bytes;
530 struct tfm_msg_body_t *msg = NULL;
531 uint32_t privileged;
532 struct partition_t *partition = NULL;
533
534 /* It is a fatal error if message handle is invalid */
535 msg = tfm_spm_get_msg_from_handle(msg_handle);
536 if (!msg) {
537 tfm_core_panic();
538 }
539
540 partition = msg->service->partition;
541 privileged = tfm_spm_partition_get_privileged_mode(
542 partition->p_ldinf->flags);
543
544 /*
545 * It is a fatal error if message handle does not refer to a request
546 * message
547 */
548 if (msg->msg.type < PSA_IPC_CALL) {
549 tfm_core_panic();
550 }
551
552 /*
553 * It is a fatal error if invec_idx is equal to or greater than
554 * PSA_MAX_IOVEC
555 */
556 if (invec_idx >= PSA_MAX_IOVEC) {
557 tfm_core_panic();
558 }
559
560 /* There was no remaining data in this input vector */
561 if (msg->msg.in_size[invec_idx] == 0) {
562 return 0;
563 }
564
565 /*
566 * Copy the client data to the service buffer. It is a fatal error
567 * if the memory reference for buffer is invalid or not read-write.
568 */
569 if (tfm_memory_check(buffer, num_bytes, false,
570 TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
571 tfm_core_panic();
572 }
573
574 bytes = num_bytes > msg->msg.in_size[invec_idx] ?
575 msg->msg.in_size[invec_idx] : num_bytes;
576
577 spm_memcpy(buffer, msg->invec[invec_idx].base, bytes);
578
579 /* There maybe some remaining data */
580 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base + bytes;
581 msg->msg.in_size[invec_idx] -= bytes;
582
583 return bytes;
584}
585
586size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
587 size_t num_bytes)
588{
589 struct tfm_msg_body_t *msg = NULL;
590
591 /* It is a fatal error if message handle is invalid */
592 msg = tfm_spm_get_msg_from_handle(msg_handle);
593 if (!msg) {
594 tfm_core_panic();
595 }
596
597 /*
598 * It is a fatal error if message handle does not refer to a request
599 * message
600 */
601 if (msg->msg.type < PSA_IPC_CALL) {
602 tfm_core_panic();
603 }
604
605 /*
606 * It is a fatal error if invec_idx is equal to or greater than
607 * PSA_MAX_IOVEC
608 */
609 if (invec_idx >= PSA_MAX_IOVEC) {
610 tfm_core_panic();
611 }
612
613 /* There was no remaining data in this input vector */
614 if (msg->msg.in_size[invec_idx] == 0) {
615 return 0;
616 }
617
618 /*
619 * If num_bytes is greater than the remaining size of the input vector then
620 * the remaining size of the input vector is used.
621 */
622 if (num_bytes > msg->msg.in_size[invec_idx]) {
623 num_bytes = msg->msg.in_size[invec_idx];
624 }
625
626 /* There maybe some remaining data */
627 msg->invec[invec_idx].base = (char *)msg->invec[invec_idx].base +
628 num_bytes;
629 msg->msg.in_size[invec_idx] -= num_bytes;
630
631 return num_bytes;
632}
633
634void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
635 const void *buffer, size_t num_bytes)
636{
637 struct tfm_msg_body_t *msg = NULL;
638 uint32_t privileged;
639 struct partition_t *partition = NULL;
640
641 /* It is a fatal error if message handle is invalid */
642 msg = tfm_spm_get_msg_from_handle(msg_handle);
643 if (!msg) {
644 tfm_core_panic();
645 }
646
647 partition = msg->service->partition;
648 privileged = tfm_spm_partition_get_privileged_mode(
649 partition->p_ldinf->flags);
650
651 /*
652 * It is a fatal error if message handle does not refer to a request
653 * message
654 */
655 if (msg->msg.type < PSA_IPC_CALL) {
656 tfm_core_panic();
657 }
658
659 /*
660 * It is a fatal error if outvec_idx is equal to or greater than
661 * PSA_MAX_IOVEC
662 */
663 if (outvec_idx >= PSA_MAX_IOVEC) {
664 tfm_core_panic();
665 }
666
667 /*
668 * It is a fatal error if the call attempts to write data past the end of
669 * the client output vector
670 */
671 if (num_bytes > msg->msg.out_size[outvec_idx] -
672 msg->outvec[outvec_idx].len) {
673 tfm_core_panic();
674 }
675
676 /*
677 * Copy the service buffer to client outvecs. It is a fatal error
678 * if the memory reference for buffer is invalid or not readable.
679 */
680 if (tfm_memory_check(buffer, num_bytes, false,
681 TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
682 tfm_core_panic();
683 }
684
685 spm_memcpy((char *)msg->outvec[outvec_idx].base +
686 msg->outvec[outvec_idx].len, buffer, num_bytes);
687
688 /* Update the write number */
689 msg->outvec[outvec_idx].len += num_bytes;
690}
691
692void tfm_spm_partition_psa_reply(psa_handle_t msg_handle, psa_status_t status)
693{
694 struct service_t *service = NULL;
695 struct tfm_msg_body_t *msg = NULL;
696 int32_t ret = PSA_SUCCESS;
697 struct tfm_conn_handle_t *conn_handle;
698
699 /* It is a fatal error if message handle is invalid */
700 msg = tfm_spm_get_msg_from_handle(msg_handle);
701 if (!msg) {
702 tfm_core_panic();
703 }
704
705 /*
706 * RoT Service information is needed in this function, stored it in message
707 * body structure. Only two parameters are passed in this function: handle
708 * and status, so it is useful and simply to do like this.
709 */
710 service = msg->service;
711 if (!service) {
712 tfm_core_panic();
713 }
714
715 /*
716 * Three type of message are passed in this function: CONNECTION, REQUEST,
717 * DISCONNECTION. It needs to process differently for each type.
718 */
719 conn_handle = tfm_spm_to_handle_instance(msg_handle);
720 switch (msg->msg.type) {
721 case PSA_IPC_CONNECT:
722 /*
723 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
724 * input status is PSA_SUCCESS. Others return values are based on the
725 * input status.
726 */
727 if (status == PSA_SUCCESS) {
728 ret = msg_handle;
729 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
730 /* Refuse the client connection, indicating a permanent error. */
731 tfm_spm_free_conn_handle(service, conn_handle);
732 ret = PSA_ERROR_CONNECTION_REFUSED;
733 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
734 /* Fail the client connection, indicating a transient error. */
735 ret = PSA_ERROR_CONNECTION_BUSY;
736 } else {
737 tfm_core_panic();
738 }
739 break;
740 case PSA_IPC_DISCONNECT:
741 /* Service handle is not used anymore */
742 tfm_spm_free_conn_handle(service, conn_handle);
743
744 /*
745 * If the message type is PSA_IPC_DISCONNECT, then the status code is
746 * ignored
747 */
748 break;
749 default:
750 if (msg->msg.type >= PSA_IPC_CALL) {
751 /* Reply to a request message. Return values are based on status */
752 ret = status;
753 /*
754 * The total number of bytes written to a single parameter must be
755 * reported to the client by updating the len member of the
756 * psa_outvec structure for the parameter before returning from
757 * psa_call().
758 */
759 update_caller_outvec_len(msg);
760 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
761 tfm_spm_free_conn_handle(service, conn_handle);
762 }
763 } else {
764 tfm_core_panic();
765 }
766 }
767
768 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
769 /*
770 * If the source of the programmer error is a Secure Partition, the SPM
771 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
772 */
773 if (TFM_CLIENT_ID_IS_NS(msg->msg.client_id)) {
774 conn_handle->status = TFM_HANDLE_STATUS_CONNECT_ERROR;
775 } else {
776 tfm_core_panic();
777 }
778 } else {
779 conn_handle->status = TFM_HANDLE_STATUS_IDLE;
780 }
781
782 if (is_tfm_rpc_msg(msg)) {
783 tfm_rpc_client_call_reply(msg, ret);
784 } else {
785 tfm_event_wake(&msg->ack_evnt, ret);
786 }
787}
788
789void tfm_spm_partition_psa_notify(int32_t partition_id)
790{
791 notify_with_signal(partition_id, PSA_DOORBELL);
792}
793
794void tfm_spm_partition_psa_clear(void)
795{
796 struct partition_t *partition = NULL;
797
798 partition = tfm_spm_get_running_partition();
799 if (!partition) {
800 tfm_core_panic();
801 }
802
803 /*
804 * It is a fatal error if the Secure Partition's doorbell signal is not
805 * currently asserted.
806 */
807 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
808 tfm_core_panic();
809 }
810 partition->signals_asserted &= ~PSA_DOORBELL;
811}
812
813void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
814{
815 struct irq_load_info_t *irq_info = NULL;
816 struct partition_t *partition = NULL;
817
818 partition = tfm_spm_get_running_partition();
819 if (!partition) {
820 tfm_core_panic();
821 }
822
823 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
824 /* It is a fatal error if passed signal is not an interrupt signal. */
825 if (!irq_info) {
826 tfm_core_panic();
827 }
828
829 if (irq_info->flih_func) {
830 /* This API is for SLIH IRQs only */
831 psa_panic();
832 }
833
834 /* It is a fatal error if passed signal is not currently asserted */
835 if ((partition->signals_asserted & irq_signal) == 0) {
836 tfm_core_panic();
837 }
838
839 partition->signals_asserted &= ~irq_signal;
840
841 tfm_spm_hal_clear_pending_irq((IRQn_Type)(irq_info->source));
842 tfm_spm_hal_enable_irq((IRQn_Type)(irq_info->source));
843}
844
845void tfm_spm_partition_psa_panic(void)
846{
847 /*
848 * PSA FF recommends that the SPM causes the system to restart when a secure
849 * partition panics.
850 */
851 tfm_hal_system_reset();
852}
853
854void tfm_spm_partition_irq_enable(psa_signal_t irq_signal)
855{
856 struct partition_t *partition;
857 struct irq_load_info_t *irq_info;
858
859 partition = tfm_spm_get_running_partition();
860 if (!partition) {
861 tfm_core_panic();
862 }
863
864 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
865 if (!irq_info) {
866 tfm_core_panic();
867 }
868
869 tfm_spm_hal_enable_irq((IRQn_Type)(irq_info->source));
870}
871
872psa_irq_status_t tfm_spm_partition_irq_disable(psa_signal_t irq_signal)
873{
874 struct partition_t *partition;
875 struct irq_load_info_t *irq_info;
876
877 partition = tfm_spm_get_running_partition();
878 if (!partition) {
879 tfm_core_panic();
880 }
881
882 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
883 if (!irq_info) {
884 tfm_core_panic();
885 }
886
887 tfm_spm_hal_disable_irq((IRQn_Type)(irq_info->source));
888
889 return 1;
890}
891
892void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
893{
894 struct irq_load_info_t *irq_info;
895 struct partition_t *partition;
896
897 partition = tfm_spm_get_running_partition();
898 if (!partition) {
899 tfm_core_panic();
900 }
901
902 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
903 if (!irq_info) {
904 tfm_core_panic();
905 }
906
907 if (!irq_info->flih_func) {
908 /* This API is for FLIH IRQs only */
909 tfm_core_panic();
910 }
911
912 if ((partition->signals_asserted & irq_signal) == 0) {
913 /* The signal is not asserted */
914 tfm_core_panic();
915 }
916
917 partition->signals_asserted &= ~irq_signal;
918}