blob: d385fd546099cc50254fe46b2fc4c70eeca51e38 [file] [log] [blame]
Monika Singh86658d72018-02-07 12:33:10 +05301/* Copyright (c) 2012-2015,2017-2018 The Linux Foundation. All rights reserved.
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#define pr_fmt(fmt) "QSEECOM: %s: " fmt, __func__
30
31#include <partition_parser.h>
32#include <qseecom_lk.h>
33#include <scm.h>
34#include <qseecomi_lk.h>
35#include "qseecom_lk_api.h"
36#include <debug.h>
37#include <kernel/mutex.h>
38#include <malloc.h>
39#include <stdlib.h>
40#include <arch/defines.h>
41#include <string.h>
42#include <platform/iomap.h>
43#include <platform.h>
44
Dinesh K Garg6bbbb702015-01-30 11:13:31 -080045#define QSEOS_CHECK_VERSION_CMD 0x00001803
46
47#define MAX_SCM_ARGS 10
48#define N_EXT_SCM_ARGS 7
49#define FIRST_EXT_ARG_IDX 3
Monika Singh86658d72018-02-07 12:33:10 +053050#define MAX_TA_PARTITION_SIZE 0x00100000
Dinesh K Garg6bbbb702015-01-30 11:13:31 -080051#define N_REGISTER_ARGS (MAX_SCM_ARGS - N_EXT_SCM_ARGS + 1)
52
53#define QSEE_LOG_BUF_SIZE (4096)
54#define GENERIC_ERROR -1
55#define LISTENER_ALREADY_PRESENT_ERROR -2
56
Parth Dixite58fce02015-10-15 11:58:30 +053057#define TZ_FVER_QSEE 10
Dinesh K Garg6bbbb702015-01-30 11:13:31 -080058#define TZ_CALL 6
59enum qseecom_client_handle_type {
60 QSEECOM_CLIENT_APP = 1,
61 QSEECOM_LISTENER_SERVICE,
62 QSEECOM_SECURE_SERVICE,
63 QSEECOM_GENERIC,
64 QSEECOM_UNAVAILABLE_CLIENT_APP,
65};
66
67struct qseecom_registered_listener_list {
68 struct list_node node;
69 struct qseecom_register_listener_req svc;
70 ListenerCallback CallbackFn;
71};
72
73struct qseecom_registered_app_list {
74 struct list_node node;
75 uint32_t app_id;
76 uint32_t ref_cnt;
77 char app_name[MAX_APP_NAME_SIZE];
78 int handle;
79};
80
81struct qseecom_control {
82 struct list_node registered_listener_list_head;
83 mutex_t registered_listener_list_lock;
84
85 struct list_node registered_app_list_head;
86 mutex_t registered_app_list_lock;
87
88 uint32_t qseos_version;
89 uint32_t qsee_version;
90 int handle;
91 bool commonlib_loaded;
92 mutex_t global_data_lock;
93 uint32_t cmnlib_loaded;
94 uint32_t qseecom_init_done;
95 uint32_t qseecom_tz_init_done;
96};
97
98struct qseecom_listener_handle {
99 uint32_t id;
100};
101
Zhen Kong91657682015-09-30 16:27:16 -0700102static struct qseecom_reg_log_buf_ireq logbuf_req = {0};
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800103static struct qseecom_control qseecom;
104static int __qseecom_process_incomplete_cmd(struct qseecom_command_scm_resp *resp,
105 struct qseecom_client_listener_data_irsp *send_data_rsp);
106
107/*
108 * Appsbl runs in Aarch32 when this is ported for Aarch64,
109 * change return type for uint64_t.
110 */
111static uint32_t __qseecom_uvirt_to_kphys(uint64_t virt)
112{
113 dprintf(SPEW, "%s called\n", __func__);
114 return (uint32_t)platform_get_virt_to_phys_mapping((addr_t)virt);
115}
116
117static int _disp_log_stats(struct tzdbg_log_t *log, uint32_t log_len,
118 uint32_t startOffset, uint32_t endOffset)
119{
120 uint32_t MaxBufSize = 0;
121 uint32_t LogBufSize = 0;
122 uint32_t LogBufFirstHalf = 0;
123 uint32_t len = 0;
124 char *pCurPos, *pPrintPos = NULL;
125 void *pLogBuf = NULL;
126 int ret = GENERIC_ERROR;
127
128 MaxBufSize = QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t);
129
130 dprintf(SPEW, "%s called\n", __func__);
131 if (startOffset < endOffset)
132 {
133 LogBufSize = endOffset - startOffset;
134 pLogBuf = malloc(LogBufSize);
135 if (NULL == pLogBuf)
136 {
137 ret = GENERIC_ERROR;
138 dprintf(CRITICAL, "Failed to alloc buffer to print TZ Log:%u\n", LogBufSize);
139 goto err;
140 }
141 memset(pLogBuf, 0, LogBufSize);
142 memscpy(pLogBuf, LogBufSize, (char *)((uint32_t)log->log_buf + startOffset), LogBufSize);
143 }
144 else if ( endOffset < startOffset)
145 {
146 LogBufSize = MaxBufSize - (startOffset - endOffset);
147 LogBufFirstHalf = MaxBufSize - startOffset;
148 pLogBuf = malloc(LogBufSize);
149 if (NULL == pLogBuf)
150 {
151 ret = GENERIC_ERROR;
152 dprintf(CRITICAL, "Failed to alloc buffer to print TZ Log:%u\n", LogBufSize);
153 goto err;
154 }
155 memset(pLogBuf, 0, LogBufSize);
156 memscpy(pLogBuf, LogBufSize, (char *)((uint32_t)log->log_buf + startOffset), LogBufFirstHalf);
157 memscpy((char *)((uint32_t)pLogBuf+ LogBufFirstHalf), (LogBufSize - LogBufFirstHalf), log->log_buf, endOffset);
158 }
159 else //endOffset == startOffset
160 {
161 ret = 0;
162 goto err;
163 }
164
165 /*
166 * Read from ring buff while there is data and space in return buff
167 */
168 pCurPos = pLogBuf;
169 pPrintPos = pCurPos;
170 while (len < LogBufSize)
171 {
172 //QSEE separate each line by "\r \n"
173 if ((*pCurPos == '\r')&&(*(pCurPos+1) == '\n'))
174 {
175 //update the line to dump
176 *pCurPos = '\0';
177 len++;
178 pCurPos++;
179 *pCurPos = '\0';
180 len++;
181 pCurPos++;
182 dprintf(ALWAYS, "%s\n", pPrintPos);
183 pPrintPos = pCurPos;
184 continue;
185 }
186 len++;
187 pCurPos++;
188 }
189 ret = 0;
190 free(pLogBuf);
191err:
192 return ret;
193}
194
195static int allocate_extra_arg_buffer(uint32_t fn_id, struct scm_desc *desc)
196{
197 int i;
198 int ret = GENERIC_ERROR;
199 scmcall_arg arg = {0};
200 scmcall_ret ret_arg = {0};
201 int arglen = 0;
202
203 if (!desc) {
204 dprintf(CRITICAL, "%s: Invalid input\n", __func__);
205 return GENERIC_ERROR;
206 }
207
208 dprintf(SPEW, "%s called\n", __func__);
209 arglen = desc->arginfo & 0xf;
210
211 dprintf(SPEW, "%s:fn_id:%u, desc->arginfo:%u desc->args[0]:%u desc->args[1]:%u desc->args[2]:%u desc->args[3]:%u desc->args[4]:%u\n",
212 __func__, fn_id, desc->arginfo, desc->args[0], desc->args[1], desc->args[2], desc->args[3], desc->args[4]);
213
214 arg.x0 = fn_id;
215 arg.x1 = desc->arginfo;
216 arg.x2 = desc->args[0];
217 arg.x3 = desc->args[1];
218 arg.x4 = desc->args[2];
219
220 if (arglen > FIRST_EXT_ARG_IDX) {
221 for (i = 0; i < (arglen - FIRST_EXT_ARG_IDX); i++) {
222 arg.x5[i] = desc->args[i + FIRST_EXT_ARG_IDX];
223 }
224 }
225 ret = scm_call2(&arg, &ret_arg);
226 desc->ret[0] = ret_arg.x1;
227 desc->ret[1] = ret_arg.x2;
228 desc->ret[2] = ret_arg.x3;
229
230 dprintf(SPEW, "%s:ret:%d, desc->ret[0]]:%u desc->ret[1]:%u desc->ret[2]:%u\n",
231 __func__, ret, desc->ret[0], desc->ret[1], desc->ret[2]);
232 return ret;
233}
234
235static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
236 const void *req_buf, void *resp_buf)
237{
238 int ret = 0;
239 uint32_t smc_id = 0;
240 uint32_t qseos_cmd_id = 0;
241 struct scm_desc desc = {0};
242 struct qseecom_command_scm_resp *scm_resp = NULL;
243
244 if (!req_buf || !resp_buf) {
245 dprintf(CRITICAL, "Invalid buffer pointer\n");
246 return GENERIC_ERROR;
247 }
248 dprintf(SPEW, "%s called\n", __func__);
249
250 qseos_cmd_id = *(uint32_t *)req_buf;
251 scm_resp = (struct qseecom_command_scm_resp *)resp_buf;
252
253 switch (svc_id) {
254 case TZ_CALL: {
255 if (tz_cmd_id == 1) {
256 smc_id = TZ_INFO_IS_SVC_AVAILABLE_ID;
257 desc.arginfo = TZ_INFO_IS_SVC_AVAILABLE_ID_PARAM_ID;
258 desc.args[0] = TZ_INFO_GET_FEATURE_VERSION_ID;
259 } else if (tz_cmd_id == 3) {
260 smc_id = TZ_INFO_GET_FEATURE_VERSION_ID;
261 desc.arginfo = TZ_INFO_GET_FEATURE_VERSION_ID_PARAM_ID;
262 desc.args[0] = *(uint32_t *)req_buf;
263 }
264 ret = allocate_extra_arg_buffer(smc_id, &desc);
265 break;
266 }
267
268 case SCM_SVC_TZSCHEDULER: {
269 switch (qseos_cmd_id) {
270 case QSEE_APP_START_COMMAND: {
271 struct qseecom_load_app_ireq *req;
272 req = (struct qseecom_load_app_ireq *)req_buf;
273 smc_id = TZ_OS_APP_START_ID;
274 desc.arginfo = TZ_OS_APP_START_ID_PARAM_ID;
275 desc.args[0] = req->mdt_len;
276 desc.args[1] = req->img_len;
277 desc.args[2] = req->phy_addr;
278 dprintf(SPEW, "args[0]:%u args[1]:%u args[2]:%u\n",
279 desc.args[0], desc.args[1], desc.args[2]);
280 dprintf(SPEW, "mdt_len:%u img_len:%u phy_addr:%u\n",
281 req->mdt_len, req->img_len, req->phy_addr);
282 ret = allocate_extra_arg_buffer(smc_id, &desc);
283
284 break;
285 }
286 case QSEE_APP_SHUTDOWN_COMMAND: {
287 struct qseecom_unload_app_ireq *req;
288 req = (struct qseecom_unload_app_ireq *)req_buf;
289 smc_id = TZ_OS_APP_SHUTDOWN_ID;
290 desc.arginfo = TZ_OS_APP_SHUTDOWN_ID_PARAM_ID;
291 desc.args[0] = req->app_id;
292 ret = allocate_extra_arg_buffer(smc_id, &desc);
293 break;
294 }
295 case QSEE_APP_REGION_NOTIFICATION: {
296 struct qsee_apps_region_info_ireq *req;
297 req = (struct qsee_apps_region_info_ireq *)req_buf;
298 smc_id = TZ_OS_APP_REGION_NOTIFICATION_ID;
299 desc.arginfo =
300 TZ_OS_APP_REGION_NOTIFICATION_ID_PARAM_ID;
301 desc.args[0] = req->addr;
302 desc.args[1] = req->size;
303 ret = allocate_extra_arg_buffer(smc_id, &desc);
304 break;
305 }
306 case QSEE_LOAD_SERV_IMAGE_COMMAND: {
307 struct qseecom_load_app_ireq *req;
308 req = (struct qseecom_load_app_ireq *)req_buf;
309 smc_id = TZ_OS_LOAD_SERVICES_IMAGE_ID;
310 desc.arginfo = TZ_OS_LOAD_SERVICES_IMAGE_ID_PARAM_ID;
311 desc.args[0] = req->mdt_len;
312 desc.args[1] = req->img_len;
313 desc.args[2] = req->phy_addr;
314 dprintf(SPEW, "QSEE_LOAD_SERV_IMAGE_COMMAND mdt_len:%u img_len:%u phy_addr:%u\n",
315 req->mdt_len, req->img_len, req->phy_addr);
316 ret = allocate_extra_arg_buffer(smc_id, &desc);
317 break;
318 }
319 case QSEE_UNLOAD_SERV_IMAGE_COMMAND: {
320 smc_id = TZ_OS_UNLOAD_SERVICES_IMAGE_ID;
321 desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
322 ret = allocate_extra_arg_buffer(smc_id, &desc);
323 break;
324 }
325 case QSEE_REGISTER_LISTENER: {
326 struct qseecom_register_listener_ireq *req;
327 req = (struct qseecom_register_listener_ireq *)req_buf;
328 smc_id = TZ_OS_REGISTER_LISTENER_ID;
329 desc.arginfo =
330 TZ_OS_REGISTER_LISTENER_ID_PARAM_ID;
331 desc.args[0] = req->listener_id;
332 desc.args[1] = req->sb_ptr;
333 desc.args[2] = req->sb_len;
334 ret = allocate_extra_arg_buffer(smc_id, &desc);
335 break;
336 }
337 case QSEE_DEREGISTER_LISTENER: {
338 struct qseecom_unregister_listener_ireq *req;
339 req = (struct qseecom_unregister_listener_ireq *)
340 req_buf;
341 smc_id = TZ_OS_DEREGISTER_LISTENER_ID;
342 desc.arginfo = TZ_OS_DEREGISTER_LISTENER_ID_PARAM_ID;
343 desc.args[0] = req->listener_id;
344 ret = allocate_extra_arg_buffer(smc_id, &desc);
345 break;
346 }
347 case QSEE_LISTENER_DATA_RSP_COMMAND: {
348 struct qseecom_client_listener_data_irsp *req;
349 req = (struct qseecom_client_listener_data_irsp *)
350 req_buf;
351 smc_id = TZ_OS_LISTENER_RESPONSE_HANDLER_ID;
352 desc.arginfo =
353 TZ_OS_LISTENER_RESPONSE_HANDLER_ID_PARAM_ID;
354 desc.args[0] = req->listener_id;
355 desc.args[1] = req->status;
356 ret = allocate_extra_arg_buffer(smc_id, &desc);
357 break;
358 }
359 case QSEE_CLIENT_SEND_DATA_COMMAND: {
360 struct qseecom_client_send_data_ireq *req;
361 req = (struct qseecom_client_send_data_ireq *)req_buf;
362 smc_id = TZ_APP_QSAPP_SEND_DATA_ID;
363 desc.arginfo = TZ_APP_QSAPP_SEND_DATA_ID_PARAM_ID;
364 desc.args[0] = req->app_id;
365 desc.args[1] = req->req_ptr;
366 desc.args[2] = req->req_len;
367 desc.args[3] = req->rsp_ptr;
368 desc.args[4] = req->rsp_len;
369 ret = allocate_extra_arg_buffer(smc_id, &desc);
370 break;
371 }
372 case QSEE_RPMB_PROVISION_KEY_COMMAND: {
373 struct qseecom_client_send_service_ireq *req;
374 req = (struct qseecom_client_send_service_ireq *)
375 req_buf;
376 smc_id = TZ_OS_RPMB_PROVISION_KEY_ID;
377 desc.arginfo = TZ_OS_RPMB_PROVISION_KEY_ID_PARAM_ID;
378 desc.args[0] = req->key_type;
379 ret = allocate_extra_arg_buffer(smc_id, &desc);
380 break;
381 }
382 case QSEE_RPMB_ERASE_COMMAND: {
383 smc_id = TZ_OS_RPMB_ERASE_ID;
384 desc.arginfo = TZ_OS_RPMB_ERASE_ID_PARAM_ID;
385 ret = allocate_extra_arg_buffer(smc_id, &desc);
386 break;
387 }
388
389 case QSEE_REGISTER_LOG_BUF_COMMAND: {
390 struct qseecom_reg_log_buf_ireq *req;
391 req = (struct qseecom_reg_log_buf_ireq *)req_buf;
392 smc_id = TZ_OS_REGISTER_LOG_BUFFER_ID;
393 desc.arginfo = TZ_OS_REGISTER_LOG_BUFFER_ID_PARAM_ID;
394 desc.args[0] = req->phy_addr;
395 desc.args[1] = req->len;
396 ret = allocate_extra_arg_buffer(smc_id, &desc);
397 break;
398 }
399 default: {
400 dprintf(CRITICAL, "qseos_cmd_id 0x%d is not supported by armv8 scm_call2.\n",
401 qseos_cmd_id);
402 ret = GENERIC_ERROR;
403 break;
404 }
405 } /*end of switch (qsee_cmd_id) */
406 break;
407 } /*end of case SCM_SVC_TZSCHEDULER*/
408 default: {
409 dprintf(CRITICAL, "svc_id 0x%x is not supported by armv8 scm_call2.\n",
410 svc_id);
411 ret = GENERIC_ERROR;
412 break;
413 }
414 } /*end of switch svc_id */
415 scm_resp->result = desc.ret[0];
416 scm_resp->resp_type = desc.ret[1];
417 scm_resp->data = desc.ret[2];
418 dprintf(SPEW, "svc_id = 0x%x, tz_cmd_id = 0x%x, qseos_cmd_id = 0x%x, smc_id = 0x%x, param_id = 0x%x\n",
419 svc_id, tz_cmd_id, qseos_cmd_id, smc_id, desc.arginfo);
420 dprintf(SPEW, "scm_resp->result = 0x%x, scm_resp->resp_type = 0x%x, scm_resp->data = 0x%x\n",
421 scm_resp->result, scm_resp->resp_type, scm_resp->data);
422 return ret;
423}
424
425static int qseecom_scm_call(uint32_t svc_id, uint32_t tz_cmd_id, void *cmd_buf,
426 size_t cmd_len, void *resp_buf, size_t resp_len)
427{
428 void *req = NULL;
429 struct qseecom_command_scm_resp *resp = NULL;
430 struct qseecom_client_listener_data_irsp send_data_rsp = {0};
431 int ret = GENERIC_ERROR;
432 uint32_t qseos_cmd_id = 0;
Zhen Kong91657682015-09-30 16:27:16 -0700433 struct tzdbg_log_t *log = NULL;
434 uint32_t QseeLogStart = 0;
435 uint32_t QseeLogNewStart = 0;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800436
437 if ((!cmd_buf) || (!resp_buf))
438 return GENERIC_ERROR;
439
440 dprintf(SPEW, "%s called\n", __func__);
441 mutex_acquire(&qseecom.registered_app_list_lock);
442 req = cmd_buf;
443 qseos_cmd_id = *(uint32_t *)req;
444 resp = (struct qseecom_command_scm_resp *) resp_buf;
445
446 do {
447 if (!is_scm_armv8_support()) {
448 ret = scm_call(svc_id, tz_cmd_id, req, cmd_len,
449 resp_buf, resp_len);
450 } else {
Zhen Kong91657682015-09-30 16:27:16 -0700451 if(logbuf_req.phy_addr)
452 {
453 log = (struct tzdbg_log_t *)logbuf_req.phy_addr;
454 arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
455 QseeLogStart = (uint32_t) log->log_pos.offset;
456 }
457
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800458 ret = qseecom_scm_call2(svc_id, tz_cmd_id, req, resp);
Zhen Kong91657682015-09-30 16:27:16 -0700459 if(logbuf_req.phy_addr)
460 {
461 arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
462 QseeLogNewStart = (uint32_t) log->log_pos.offset;
463 _disp_log_stats((struct tzdbg_log_t *) logbuf_req.phy_addr,
464 QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t),
465 QseeLogStart, QseeLogNewStart);
466 }
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800467 }
468
469 if (ret) {
470 dprintf(CRITICAL, "ERROR: scm_call to load failed : ret %d\n", ret);
471 ret = GENERIC_ERROR;
472 goto err;
473 }
474
475 if (svc_id == TZ_CALL) {
476 goto err;
477 }
478
479 switch (resp->result) {
480 case QSEOS_RESULT_SUCCESS:
481 if(((resp->resp_type != QSEOS_APP_ID) || (resp->data <= 0)) &&
Zhen Kong91657682015-09-30 16:27:16 -0700482 (qseos_cmd_id == QSEE_CLIENT_SEND_DATA_COMMAND))
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800483 {
484 dprintf(CRITICAL, "ERROR: Resp type %d or Resp Data %d incorrect\n",
485 resp->resp_type, resp->data);
486 ret = GENERIC_ERROR;
487 goto err;
488 }
489 goto err;
490 case QSEOS_RESULT_FAILURE:
491 dprintf(CRITICAL, "scm call failed w/response result%d\n", resp->result);
492 ret = GENERIC_ERROR;
493 goto err;
494 case QSEOS_RESULT_INCOMPLETE:
495 if(resp->resp_type != QSEOS_LISTENER_ID)
496 {
497 ret = GENERIC_ERROR;
498 dprintf(CRITICAL, "Listener service incorrect resp->result:%d resp->resp_type:%d\n",
499 resp->result, resp->resp_type);
500 goto err;
501 }
502 __qseecom_process_incomplete_cmd(resp, &send_data_rsp);
503 req = (void *)&send_data_rsp;
504 qseos_cmd_id = QSEE_LISTENER_DATA_RSP_COMMAND;
505 break;
506 default:
507 dprintf(CRITICAL, "scm call return unknown response %d\n", resp->result);
508 ret = GENERIC_ERROR;
509 goto err;
510 }
511 } while(true);
512
513err:
514 mutex_release(&qseecom.registered_app_list_lock);
515 return ret;
516
517}
518
519static int __qseecom_process_incomplete_cmd(struct qseecom_command_scm_resp *resp,
520 struct qseecom_client_listener_data_irsp *send_data_rsp)
521{
522 int ret = 0;
523 struct qseecom_registered_listener_list *entry;
524
525 if ((!resp) || (!send_data_rsp))
526 {
527 return GENERIC_ERROR;
528 }
529
530 dprintf(SPEW, "%s called\n", __func__);
531 mutex_acquire(&qseecom.global_data_lock);
532
533 list_for_every_entry(&qseecom.registered_listener_list_head,
534 entry, struct qseecom_registered_listener_list, node) {
535 if (resp->data == entry->svc.listener_id) {
536 arch_invalidate_cache_range((addr_t) entry->svc.virt_sb_base, entry->svc.sb_size);
537 entry->CallbackFn(entry->svc.virt_sb_base, entry->svc.sb_size);
538 arch_clean_invalidate_cache_range((addr_t) entry->svc.virt_sb_base, entry->svc.sb_size);
539 break;
540 }
541 }
542 send_data_rsp->qsee_cmd_id = QSEE_LISTENER_DATA_RSP_COMMAND;
543 send_data_rsp->listener_id = entry->svc.listener_id;
544 send_data_rsp->status = 0;
545 mutex_release(&qseecom.global_data_lock);
546 return ret;
547}
548
549static int __qseecom_load_app(const char *app_name, unsigned int *app_id)
550{
551 int index = INVALID_PTN;
552 unsigned long long ptn = 0;
553 unsigned long long size = 0;
Monika Singh86658d72018-02-07 12:33:10 +0530554 unsigned long rounded_size = 0;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800555 void *buf = NULL;
556 void *req = NULL;
557 struct qseecom_load_app_ireq load_req = {0};
558 struct qseecom_command_scm_resp resp;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800559
560 int ret = GENERIC_ERROR;
561 uint8_t lun = 0;
562
563 if (!app_name)
564 return GENERIC_ERROR;
565
566 dprintf(SPEW, "%s called\n", __func__);
567 index = partition_get_index(app_name);
568 lun = partition_get_lun(index);
569 mmc_set_lun(lun);
570
571 size = partition_get_size(index);
Monika Singh86658d72018-02-07 12:33:10 +0530572 if (MAX_TA_PARTITION_SIZE < size) {
573 dprintf(CRITICAL, "Invalid TA partition size!");
Kishor PKbe2a9fa2017-07-27 13:26:52 +0530574 ret = GENERIC_ERROR;
575 goto err;
576 }
577 rounded_size = ROUNDUP(size, PAGE_SIZE);
578 buf = memalign(PAGE_SIZE, rounded_size);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800579 if (!buf) {
580 dprintf(CRITICAL, "%s: Aloc failed for %s image\n",
581 __func__, app_name);
582 ret = GENERIC_ERROR;
583 goto err;
584 }
585
586 ptn = partition_get_offset(index);
587 if(ptn == 0) {
588 dprintf(CRITICAL, "ERROR: No %s found\n", app_name);
589 ret = GENERIC_ERROR;
590 goto err;
591 }
592 if (mmc_read(ptn, (unsigned int *) buf, size)) {
593 dprintf(CRITICAL, "ERROR: Cannot read %s image\n", app_name);
594 ret = GENERIC_ERROR;
595 goto err;
596 }
597
598 /* Currently on 8994 only 32-bit phy addr is supported
599 * Hence downcasting is okay
600 */
601 load_req.phy_addr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
602 load_req.qsee_cmd_id = QSEE_APP_START_COMMAND;
603 load_req.img_len = size;
604 load_req.mdt_len = 0;
605 dprintf(SPEW, "phy_addr:%u img_len:%u\n", load_req.phy_addr, load_req.img_len);
606
607 memscpy(&load_req.app_name, MAX_APP_NAME_SIZE, app_name, MAX_APP_NAME_SIZE);
608 req = (void *)&load_req;
609
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800610 arch_clean_invalidate_cache_range((addr_t) load_req.phy_addr, load_req.img_len);
611 ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, req,
612 sizeof(struct qseecom_load_lib_image_ireq),
613 &resp, sizeof(resp));
614 if(ret == 0)
615 *app_id = resp.data;
616 else
617 *app_id = 0;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800618err:
619 if (buf)
620 free(buf);
621 return ret;
622}
623
624static int qseecom_load_commonlib_image(char * app_name)
625{
626 int index = INVALID_PTN;
627 unsigned long long ptn = 0;
628 unsigned long long size = 0;
Monika Singh86658d72018-02-07 12:33:10 +0530629 unsigned long rounded_size = 0;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800630 void *buf = NULL;
631 void *req = NULL;
632 struct qseecom_load_app_ireq load_req = {0};
633 struct qseecom_command_scm_resp resp = {0};
634 int ret = GENERIC_ERROR;
635 uint8_t lun = 0;
636
637 dprintf(SPEW, "%s called\n", __func__);
638 index = partition_get_index(app_name);
639 lun = partition_get_lun(index);
640 mmc_set_lun(lun);
641
642 size = partition_get_size(index);
Monika Singh86658d72018-02-07 12:33:10 +0530643 if (MAX_TA_PARTITION_SIZE < size) {
644 dprintf(CRITICAL, "Invalid cmnlib partition size!");
Kishor PKbe2a9fa2017-07-27 13:26:52 +0530645 ret = GENERIC_ERROR;
646 goto err;
647 }
648 rounded_size = ROUNDUP(size, PAGE_SIZE);
649 buf = memalign(PAGE_SIZE, rounded_size);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800650 if (!buf) {
651 dprintf(CRITICAL, "%s: Aloc failed for %s image\n",
652 __func__, app_name);
653 ret = GENERIC_ERROR;
654 goto err;
655 }
656
657 ptn = partition_get_offset(index);
658 if(ptn == 0) {
659 dprintf(CRITICAL, "ERROR: No %s found\n", app_name);
660 ret = GENERIC_ERROR;
661 goto err;
662 }
663 if (mmc_read(ptn, (unsigned int *) buf, size)) {
664 dprintf(CRITICAL, "ERROR: Cannot read %s image\n", app_name);
665 ret = GENERIC_ERROR;
666 goto err;
667 }
668
669 /* Currently on 8994 only 32-bit phy addr is supported
670 * Hence downcasting is okay
671 */
672 load_req.phy_addr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
673 load_req.qsee_cmd_id = QSEE_LOAD_SERV_IMAGE_COMMAND;
674 load_req.img_len = size;
675 load_req.mdt_len = 0;
676
677 memscpy(load_req.app_name, MAX_APP_NAME_SIZE, app_name, MAX_APP_NAME_SIZE);
678 req = (void *)&load_req;
679
680 arch_clean_invalidate_cache_range((addr_t) load_req.phy_addr, load_req.img_len);
681 ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, req,
682 sizeof(struct qseecom_load_lib_image_ireq),
683 &resp, sizeof(resp));
684 if(ret == 0)
685 ret = resp.data;
686
687err:
688 if (buf)
689 free(buf);
690 return ret;
691}
692
693static int qseecom_unload_commonlib_image(void)
694{
695 int ret = GENERIC_ERROR;
696 struct qseecom_unload_lib_image_ireq unload_req = {0};
697 struct qseecom_command_scm_resp resp;
698
699 dprintf(SPEW, "%s called\n", __func__);
700 /* Populate the remaining parameters */
701 unload_req.qsee_cmd_id = QSEE_UNLOAD_SERV_IMAGE_COMMAND;
702 /* SCM_CALL to load the image */
703 ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &unload_req,
704 sizeof(struct qseecom_unload_lib_image_ireq),
705 &resp, sizeof(resp));
706 return ret;
707}
708
709/*
710 * This function is called with the global
711 * data mutex acquired.
712 */
713static struct qseecom_registered_app_list *
714 __qseecom_add_app_entry(char *app_name, uint32_t app_id)
715{
716 struct qseecom_registered_app_list *entry = NULL;
717 int32_t ret = GENERIC_ERROR;
718
719 if ((!app_name) || (app_id == 0)) {
720 dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
721 return NULL;
722 }
723 dprintf(SPEW, "%s called\n", __func__);
724
725 entry = malloc(sizeof(*entry));
726 if (!entry) {
727 dprintf(CRITICAL, "malloc for app entry failed\n");
728 ret = GENERIC_ERROR;
729 goto err;
730 }
731 entry->app_id = app_id;
732 entry->ref_cnt = 1;
733 strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE);
734
735 dprintf(SPEW, "%s: Adding app:%s app_id:%u to list\n", __func__, entry->app_name, entry->app_id);
736 list_add_tail(&qseecom.registered_app_list_head, &entry->node);
737 ret = 0;
738err:
739 if (entry && (ret < 0)) {
740 free(entry);
741 return NULL;
742 }
743 return entry;
744}
745
746/*
747 * This function is called with the global
748 * data mutex acquired.
749 */
750static int
751 __qseecom_remove_app_entry(struct qseecom_registered_app_list *entry)
752{
753 if (!entry) {
754 dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
755 return GENERIC_ERROR;
756 }
757 dprintf(SPEW, "%s called\n", __func__);
758 list_delete(&entry->node);
759 free(entry);
760
761 return 0;
762}
763
764/*
765 * This function is called with the global
766 * data mutex acquired.
767 */
768struct qseecom_registered_listener_list *
769 __qseecom_check_listener_exists(uint32_t listener_id)
770{
771 struct qseecom_registered_listener_list *entry = NULL;
772 bool listener_present = false;
773
774 if (!listener_id) {
775 dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
776 return NULL;
777 }
778 dprintf(SPEW, "%s called\n", __func__);
779
780 list_for_every_entry(&qseecom.registered_listener_list_head,
781 entry, struct qseecom_registered_listener_list, node) {
782 if (entry->svc.listener_id == listener_id) {
783 listener_present = true;
784 break;
785 }
786 }
787 if (listener_present)
788 return entry;
789 else
790 return NULL;
791}
792
793/*
794 * This function is called with the global
795 * data mutex acquired.
796 */
797static struct qseecom_registered_app_list
798 *__qseecom_check_handle_exists(int handle)
799{
800 struct qseecom_registered_app_list *entry;
801 bool app_present = false;
802
803 if (handle <= 0) {
804 dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
805 return NULL;
806 }
807 dprintf(SPEW, "%s called\n", __func__);
808 list_for_every_entry(&qseecom.registered_app_list_head,
809 entry, struct qseecom_registered_app_list, node) {
810 if (entry->handle == handle) {
811 app_present = true;
812 break;
813 }
814 }
815
816 if (app_present == true)
817 return entry;
818 else
819 return NULL;
820
821}
822
823
824static struct qseecom_registered_app_list *
825 __qseecom_check_app_exists(char *app_name)
826{
827 struct qseecom_registered_app_list *entry = NULL;
828
829 dprintf(SPEW, "%s called\n", __func__);
830 list_for_every_entry(&qseecom.registered_app_list_head,
831 entry, struct qseecom_registered_app_list, node) {
832 if (!strncmp(app_name, entry->app_name, 32)) {
833 dprintf(SPEW, "%s: app_name:%s\n", __func__, app_name);
834 return entry;
835 }
836 }
837 return NULL;
838}
839
840static int qseecom_unload_app(uint32_t app_id)
841{
842 int ret = 0;
843 struct qseecom_command_scm_resp resp;
844 struct qseecom_unload_app_ireq req;
845
846 dprintf(SPEW, "%s called\n", __func__);
847 /* Populate the structure for sending scm call to load image */
848 req.qsee_cmd_id = QSEE_APP_SHUTDOWN_COMMAND;
849 req.app_id = app_id;
850
851 /* SCM_CALL to unload the app */
852 ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
853 sizeof(struct qseecom_unload_app_ireq),
854 &resp, sizeof(resp));
855
856 return ret;
857}
858
859
860static int __qseecom_send_cmd(uint32_t app_id, struct qseecom_send_cmd_req *req)
861{
862 int ret = 0;
863 struct qseecom_client_send_data_ireq send_data_req;
864 struct qseecom_command_scm_resp resp;
865 void *buf = NULL;
Zhen Kongab19b062015-10-08 18:33:05 -0700866 void *rsp_buf_temp = NULL;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800867 uint32_t size = 0;
868
869 if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
870 dprintf(CRITICAL, "%s: cmd buffer or response buffer is null\n",
871 __func__);
872 return GENERIC_ERROR;
873 }
874 dprintf(SPEW, "%s called\n", __func__);
875
Zhen Kongab19b062015-10-08 18:33:05 -0700876 if (req->cmd_req_len > (UINT_MAX - req->resp_len)) {
877 dprintf(CRITICAL, "%s:Integer overflow\n", __func__);
878 dprintf(CRITICAL, "req->cmd_req_len: %u\n", req->cmd_req_len);
879 dprintf(CRITICAL, "req->resp_len: %u\n", req->resp_len);
880 return GENERIC_ERROR;
881 }
882
883 if ((req->cmd_req_len + req->resp_len) > (RPMB_SND_RCV_BUF_SZ * 1024 * 1024)) {
884 dprintf(CRITICAL, "%s:Cmd + Rsp len greater than TA buf\n", __func__);
885 dprintf(CRITICAL, "req->cmd_req_len: %u\n", req->cmd_req_len);
886 dprintf(CRITICAL, "req->resp_len: %u\n", req->resp_len);
887 return GENERIC_ERROR;
888 }
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800889
890 /* The req rsp buffer will be xPU protected by TZ during a TZ APP call
891 * This will still be protected during a listener call and there is a
892 * possibility of prefetching happening, which will cause xPU violation.
893 * Hence using (device memory with xN set) to prevent I or D prefetching.
894 * This is a contiguous region of 1MB used only for this, hence will not
895 * free this.
896 */
897 buf = (void *)RPMB_SND_RCV_BUF;
898 if (!buf) {
899 dprintf(CRITICAL, "%s: Aloc failed for app_id:%d of size:%d\n",
900 __func__, app_id, size);
901 return GENERIC_ERROR;
902 }
903
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800904 send_data_req.qsee_cmd_id = QSEE_CLIENT_SEND_DATA_COMMAND;
905 send_data_req.app_id = app_id;
906
907 /* Currently on 8994 only 32-bit phy addr is supported
908 * Hence downcasting is okay
909 */
910 send_data_req.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
911 send_data_req.req_len = req->cmd_req_len;
Zhen Kongab19b062015-10-08 18:33:05 -0700912 size = ROUNDUP(req->cmd_req_len, PAGE_SIZE);
913 rsp_buf_temp = (uint8_t *)buf + size;
914 send_data_req.rsp_ptr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t)rsp_buf_temp);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800915 send_data_req.rsp_len = req->resp_len;
916
Zhen Kongab19b062015-10-08 18:33:05 -0700917 memscpy(buf, (RPMB_SND_RCV_BUF_SZ * 1024 * 1024), req->cmd_req_buf, req->cmd_req_len);
918 memscpy(rsp_buf_temp, req->resp_len, req->resp_buf, req->resp_len);
919
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800920 ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
921 (void *)&send_data_req,
922 sizeof(send_data_req), (void *)&resp, sizeof(resp));
923
Zhen Kongab19b062015-10-08 18:33:05 -0700924 memscpy(req->cmd_req_buf, req->cmd_req_len, (void *)buf, send_data_req.req_len);
925 memscpy(req->resp_buf, req->resp_len, (void *)rsp_buf_temp, send_data_req.rsp_len);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800926 return ret;
927}
928
929/**
930* Start a Secure App
931*
932* @param char* app_name
933* App name of the Secure App to be started
934*
935* @return int
936* Success: handle to be used for all calls to
937* Secure app. Always greater than zero.
938* Failure: Error code (negative only).
939*/
940int qseecom_start_app(char *app_name)
941{
942 int32_t ret = GENERIC_ERROR;
943 int handle = 0;
944 struct qseecom_registered_app_list *entry = NULL;
945 unsigned int app_id = 0;
946
947 if (!app_name) {
948 dprintf(CRITICAL, "%s: Input error\n", __func__);
949 goto err;
950 }
951 dprintf(SPEW, "%s called\n", __func__);
952
953
954 mutex_acquire(&qseecom.global_data_lock);
955 if ((!qseecom.qseecom_init_done)
956 || (!qseecom.qseecom_tz_init_done)){
957 dprintf(CRITICAL, "%s qseecom_init not done\n",
958 __func__);
959 mutex_release(&qseecom.global_data_lock);
960 return ret;
961 }
Zhen Kong91657682015-09-30 16:27:16 -0700962 mutex_release(&qseecom.global_data_lock);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800963 /* Load commonlib image*/
964 if (!qseecom.cmnlib_loaded) {
965 ret = qseecom_load_commonlib_image("cmnlib");
966 if (ret) {
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800967 dprintf(CRITICAL, "%s qseecom_load_commonlib_image failed with status:%d\n",
968 __func__, ret);
969 goto err;
970 }
Zhen Kongab19b062015-10-08 18:33:05 -0700971 dprintf(DEBUG, "Loading cmnlib done\n");
972#if ENABLE_CMNLIB64_LOADING
973 ret = qseecom_load_commonlib_image("cmnlib64");
974 if (ret) {
975 dprintf(CRITICAL, "%s qseecom_load_commonlib_image failed with status:%d\n",
976 __func__, ret);
977 goto err;
978 }
979 dprintf(DEBUG, "Loading cmnlib64 done\n");
980#endif
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800981 qseecom.cmnlib_loaded = 1;
982 }
983 /* Check if App already exits, if exits increase ref_cnt
984 * and return handle, else load the app from partition,
985 * call into TZ to load it, add to list and then return
986 * handle.
987 */
Zhen Kong91657682015-09-30 16:27:16 -0700988 mutex_acquire(&qseecom.global_data_lock);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -0800989 entry = __qseecom_check_app_exists(app_name);
990 if (!entry) {
991 mutex_release(&qseecom.global_data_lock);
992 /* load the app and get the app_id */
993 dprintf(INFO, "%s: Loading app %s for the first time'\n",
994 __func__, app_name);
995
996 ret = __qseecom_load_app(app_name, &app_id);
997 if ((ret < 0) || (app_id ==0)) {
998 dprintf(CRITICAL, "%s: __qseecom_load_app failed with err:%d for app:%s\n",
999 __func__, ret, app_name);
1000 ret = GENERIC_ERROR;
1001 goto err;
1002 }
1003 mutex_acquire(&qseecom.global_data_lock);
1004 entry = __qseecom_add_app_entry(app_name, app_id);
1005 if (!entry)
1006 {
1007 dprintf(CRITICAL, "%s: __qseecom_add_app_entry failed\n", __func__);
1008 ret = GENERIC_ERROR;
1009 mutex_release(&qseecom.global_data_lock);
1010 goto err;
1011 }
1012 qseecom.handle++;
1013 entry->handle = qseecom.handle;
1014 handle = entry->handle;
1015 mutex_release(&qseecom.global_data_lock);
1016 }
1017 else {
1018 entry->ref_cnt++;
1019 handle = entry->handle;
1020 mutex_release(&qseecom.global_data_lock);
1021 }
1022 return handle;
1023err:
1024 return ret;
1025}
1026
1027/**
1028* Shutdown a Secure App
1029*
1030* @param int handle
1031* Handle of the Secure App to be shutdown
1032*
1033* @return int
1034* Status:
1035* 0 - Success
1036* Negative value indicates failure.
1037*/
1038int qseecom_shutdown_app(int handle)
1039{
1040 int ret = GENERIC_ERROR;
1041 int ref_cnt = 0;
1042 struct qseecom_registered_app_list *entry = NULL;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001043
1044 if (handle <= 0) {
1045 dprintf(CRITICAL, "%s: Invalid Handle %d\n", __func__, handle);
1046 goto err;
1047 }
1048 dprintf(SPEW, "%s called\n", __func__);
1049 mutex_acquire(&qseecom.global_data_lock);
1050 if ((!qseecom.qseecom_init_done)
1051 || (!qseecom.qseecom_tz_init_done)) {
1052 dprintf(CRITICAL, "%s qseecom_init not done\n",
1053 __func__);
1054 mutex_release(&qseecom.global_data_lock);
1055 return ret;
1056 }
1057 entry = __qseecom_check_handle_exists(handle);
1058 if (!entry) {
1059 dprintf(CRITICAL, "%s: Shutdown on an app that was never loaded handle:%d\n",
1060 __func__, handle);
1061 ret = GENERIC_ERROR;
1062 mutex_release(&qseecom.global_data_lock);
1063 goto err;
1064 }
1065
1066 /* Decrement ref_cnt by 1, if ref_cnt is 0 after
1067 * decrementing unload the app by calling into
1068 * TZ else just return.
1069 */
1070
1071 if(entry->ref_cnt != 0)
1072 entry->ref_cnt--;
1073 ref_cnt = entry->ref_cnt;
1074 mutex_release(&qseecom.global_data_lock);
1075 if (ref_cnt == 0) {
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001076 ret = qseecom_unload_app(entry->app_id);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001077 if(ret) {
1078 dprintf(CRITICAL, "%s: qseecom_unload_app failed with err:%d for handle:%d\n",
1079 __func__, ret, handle);
1080 goto err;
1081 }
1082 mutex_acquire(&qseecom.global_data_lock);
1083 ret = __qseecom_remove_app_entry(entry);
1084 mutex_release(&qseecom.global_data_lock);
1085 if(ret) {
1086 dprintf(CRITICAL, "%s: __qseecom_remove_app_entry failed with err:%d for handle:%d\n",
1087 __func__, ret, handle);
1088 goto err;
1089 }
1090 }
1091 ret = 0;
1092err:
1093 return ret;
1094}
1095
1096/**
1097* Send cmd to a Secure App
1098*
1099* @param int handle
1100* Handle of the Secure App to send the cmd
1101*
1102* @param void *send_buf
1103* Pointer to the App request buffer
1104*
1105* @param uint32_t sbuf_len
1106* Size of the request buffer
1107*
1108* @param void *resp_buf
1109* Pointer to the App response buffer
1110*
1111* @param uint32_t rbuf_len
1112* Size of the response buffer
1113*
1114* @return int
1115* Status:
1116* 0 - Success
1117* Negative value indicates failure.
1118*/
1119int qseecom_send_command(int handle, void *send_buf,
1120 uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len)
1121{
1122 int ret = GENERIC_ERROR;
1123 uint32_t app_id = 0;
1124 struct qseecom_registered_app_list *entry = NULL;
1125 struct qseecom_send_cmd_req req = {0, 0, 0, 0};
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001126
1127 if (handle <= 0) {
1128 dprintf(CRITICAL, "%s Handle is Invalid\n", __func__);
1129 return GENERIC_ERROR;
1130 }
1131
1132 if((!send_buf) || (!resp_buf)) {
1133 dprintf(CRITICAL, "%s: Input Buffers invalid\n", __func__);
1134 return GENERIC_ERROR;
1135 }
1136 dprintf(SPEW, "%s called\n", __func__);
1137 mutex_acquire(&qseecom.global_data_lock);
1138 if ((!qseecom.qseecom_init_done)
1139 || (!qseecom.qseecom_tz_init_done)) {
1140 dprintf(CRITICAL, "%s qseecom_init not done\n",
1141 __func__);
1142 mutex_release(&qseecom.global_data_lock);
1143 return ret;
1144 }
1145 entry = __qseecom_check_handle_exists(handle);
1146 if (!entry) {
1147 dprintf(CRITICAL, "%s: Send cmd on an app that was never loaded handle:%d\n",
1148 __func__, handle);
1149 ret = GENERIC_ERROR;
1150 mutex_release(&qseecom.global_data_lock);
1151 goto err;
1152 }
1153
1154 app_id = entry->app_id;
1155 mutex_release(&qseecom.global_data_lock);
1156
1157 req.cmd_req_len = sbuf_len;
1158 req.resp_len = rbuf_len;
1159 req.cmd_req_buf = send_buf;
1160 req.resp_buf = resp_buf;
1161
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001162 ret = __qseecom_send_cmd(app_id, &req);
1163 if (ret) {
1164 dprintf(CRITICAL, "%s __qseecom_send_cmd failed with err:%d for handle:%d\n",
1165 __func__, ret, handle);
1166 goto err;
1167 }
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001168
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001169 ret = 0;
1170 dprintf(SPEW, "sending cmd_req->rsp size: %u, ptr: 0x%p\n",
1171 req.resp_len, req.resp_buf);
1172err:
1173 return ret;
1174}
1175
1176/**
1177* Registers a Listener Service with QSEE
1178*
1179* @param uint32_t listnr_id
1180* Pre-defined Listener ID to be registered
1181*
1182* @param uint32_t sb_size
1183* Shared buffer size required for the listener
1184* service.
1185*
1186* @return int
1187* Status:
1188* 0 - Success
1189* Negative value indicates failure.
1190*/
1191int qseecom_register_listener(struct qseecom_listener_services *listnr)
1192{
1193 int ret = GENERIC_ERROR;
1194 struct qseecom_registered_listener_list *new_entry = NULL;
1195 struct qseecom_register_listener_ireq req;
1196 struct qseecom_command_scm_resp resp;
1197
1198 mutex_acquire(&qseecom.global_data_lock);
1199 if (!qseecom.qseecom_init_done) {
1200 dprintf(CRITICAL, "%s qseecom_init not done\n",
1201 __func__);
1202 mutex_release(&qseecom.global_data_lock);
1203 return ret;
1204 }
1205 mutex_release(&qseecom.global_data_lock);
1206
1207 mutex_acquire(&qseecom.registered_listener_list_lock);
1208
1209 if ((!listnr)) {
1210 dprintf(CRITICAL, "%s Invalid Input listnr\n", __func__);
1211 return GENERIC_ERROR;
1212 }
1213
1214 if ((!listnr->id) || (!listnr->sb_size) || (!listnr->service_cmd_handler)) {
1215 dprintf(CRITICAL, "%s Invalid Input listnr_id:%d sb_size:%d\n",
1216 __func__, listnr->id, listnr->sb_size);
1217 return GENERIC_ERROR;
1218 }
1219 dprintf(SPEW, "%s called\n", __func__);
1220 new_entry = __qseecom_check_listener_exists(listnr->id);
1221 if (new_entry) {
1222 dprintf(CRITICAL, "Service is not unique and is already registered\n");
1223 ret = LISTENER_ALREADY_PRESENT_ERROR;
1224 goto err;
1225 }
1226
1227 new_entry = malloc(sizeof(*new_entry));
1228 if (!new_entry) {
1229 dprintf(CRITICAL, "%s new_entry malloc failed for size:%d\n", __func__, sizeof(*new_entry));
1230 ret = GENERIC_ERROR;
1231 goto err;
1232 }
1233 memset(new_entry, 0, sizeof(*new_entry));
1234 new_entry->svc.listener_id = listnr->id;
1235 new_entry->svc.sb_size = listnr->sb_size;
1236 new_entry->CallbackFn = listnr->service_cmd_handler;
1237
1238 new_entry->svc.virt_sb_base = memalign(PAGE_SIZE, ROUNDUP(listnr->sb_size, PAGE_SIZE));
1239 if (!new_entry->svc.virt_sb_base) {
1240 dprintf(CRITICAL, "%s virt_sb_base malloc failed for size:%d\n", __func__, listnr->sb_size);
1241 ret = GENERIC_ERROR;
1242 goto err;
1243 }
1244 memset(new_entry->svc.virt_sb_base, 0, ROUNDUP(listnr->sb_size, PAGE_SIZE));
1245 arch_clean_invalidate_cache_range((addr_t) new_entry->svc.virt_sb_base, ROUNDUP(listnr->sb_size, PAGE_SIZE));
1246
1247 req.qsee_cmd_id = QSEE_REGISTER_LISTENER;
1248 req.listener_id = new_entry->svc.listener_id;
1249 req.sb_len = new_entry->svc.sb_size;
1250 /* convert to 32bit addr for tz */
1251 req.sb_ptr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) new_entry->svc.virt_sb_base);
1252
1253 resp.result = QSEOS_RESULT_INCOMPLETE;
1254
1255 ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
1256 sizeof(req), &resp, sizeof(resp));
1257 if (ret) {
1258 dprintf(CRITICAL, "qseecom_scm_call failed with err: %d\n", ret);
1259 ret = GENERIC_ERROR;
1260 goto err;
1261 }
1262 /* Add entry to Listener list */
1263 list_add_tail(&qseecom.registered_listener_list_head, &new_entry->node);
1264err:
1265 if ((ret) &&
1266 (ret != LISTENER_ALREADY_PRESENT_ERROR)) {
1267 if ((new_entry) &&
1268 (new_entry->svc.virt_sb_base))
1269 free(new_entry->svc.virt_sb_base);
1270 if (new_entry)
1271 free(new_entry);
1272 }
1273 mutex_release(&qseecom.registered_listener_list_lock);
1274 return ret;
1275}
1276
1277/**
1278* De-Registers a Listener Service with QSEE
1279*
1280* @param uint32_t listnr_id
1281* Pre-defined Listener ID to be de-registered
1282*
1283* @return int
1284* Status:
1285* 0 - Success
1286* Negative value indicates failure.
1287*/
1288int qseecom_deregister_listener(uint32_t listnr_id)
1289{
1290 int ret = GENERIC_ERROR;
1291 struct qseecom_registered_listener_list *new_entry = NULL;
1292 struct qseecom_unregister_listener_ireq req;
1293 struct qseecom_command_scm_resp resp;
1294
1295 mutex_acquire(&qseecom.global_data_lock);
1296 if (!qseecom.qseecom_init_done) {
1297 dprintf(CRITICAL, "%s qseecom_init not done\n",
1298 __func__);
1299 mutex_release(&qseecom.global_data_lock);
1300 return ret;
1301 }
1302 mutex_release(&qseecom.global_data_lock);
1303
1304 mutex_acquire(&qseecom.registered_listener_list_lock);
1305 dprintf(SPEW, "%s called\n", __func__);
1306 new_entry = __qseecom_check_listener_exists(listnr_id);
1307 if (!new_entry) {
1308 dprintf(CRITICAL, "Service not present\n");
1309 ret = GENERIC_ERROR;
1310 goto err;
1311 }
1312
1313 req.qsee_cmd_id = QSEE_DEREGISTER_LISTENER;
1314 req.listener_id = listnr_id;
1315 resp.result = QSEOS_RESULT_INCOMPLETE;
1316
1317 ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
1318 sizeof(req), &resp, sizeof(resp));
1319 if (ret) {
1320 dprintf(CRITICAL, "scm_call() failed with err: %d (lstnr id=%d)\n",
1321 ret, req.listener_id);
1322 ret = GENERIC_ERROR;
1323 goto err;
1324 }
1325
1326 list_delete(&new_entry->node);
1327
1328err:
1329 if (ret == 0) {
1330 if (new_entry)
1331 free(new_entry);
1332 }
1333 mutex_release(&qseecom.registered_listener_list_lock);
1334 return ret;
1335}
1336
1337int qseecom_tz_init()
1338{
1339 struct qsee_apps_region_info_ireq req;
1340 struct qseecom_command_scm_resp resp;
1341 int rc = GENERIC_ERROR;
1342 /* register log buffer scm request */
1343 void *buf = NULL;
1344 /* Register app region with TZ */
1345 req.qsee_cmd_id = QSEE_APP_REGION_NOTIFICATION;
1346 req.addr = APP_REGION_ADDR;
1347 req.size = APP_REGION_SIZE;
1348 dprintf(ALWAYS, "secure app region addr=0x%x size=0x%x",
1349 req.addr, req.size);
1350 rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
1351 &req, sizeof(req),
1352 &resp, sizeof(resp));
1353 dprintf(ALWAYS, "TZ App region notif returned with status:%d addr:%x size:%d\n",
1354 rc, req.addr, req.size);
1355 if (rc)
1356 goto err;
1357 buf = memalign(PAGE_SIZE, ROUNDUP(QSEE_LOG_BUF_SIZE, PAGE_SIZE));
1358 if (!buf) {
1359 rc = GENERIC_ERROR;
1360 goto err;
1361 }
1362 memset(buf, 0, ROUNDUP(QSEE_LOG_BUF_SIZE, PAGE_SIZE));
Channagoud Kadabicf3afe42015-08-07 16:08:08 -07001363 /* Make sure the buffer given to TZ is flushed */
1364 arch_clean_invalidate_cache_range((addr_t) buf, QSEE_LOG_BUF_SIZE);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001365 logbuf_req.qsee_cmd_id = QSEE_REGISTER_LOG_BUF_COMMAND;
1366 logbuf_req.phy_addr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
1367 logbuf_req.len = QSEE_LOG_BUF_SIZE;
1368
1369 rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
1370 &logbuf_req, sizeof(logbuf_req),
1371 &resp, sizeof(resp));
1372 dprintf(ALWAYS, "TZ App log region register returned with status:%d addr:%x size:%d\n",
1373 rc, logbuf_req.phy_addr, logbuf_req.len);
1374 if (rc)
1375 goto err;
1376err:
1377 if (!rc) {
1378 qseecom.qseecom_tz_init_done = 1;
1379 dprintf(ALWAYS, "Qseecom TZ Init Done in Appsbl\n");
1380 }
1381 return rc;
1382}
1383
1384int qseecom_init()
1385{
1386 int rc = GENERIC_ERROR;
Parth Dixite58fce02015-10-15 11:58:30 +05301387 struct qseecom_command_scm_resp resp;
1388 uint32_t ver = TZ_FVER_QSEE;
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001389
1390 memset (&qseecom, 0, sizeof(struct qseecom_control));
1391 dprintf(SPEW, "%s called\n", __func__);
1392 mutex_init(&(qseecom.global_data_lock));
1393 mutex_init(&(qseecom.registered_app_list_lock));
1394 mutex_init(&(qseecom.registered_listener_list_lock));
1395
1396 list_initialize(&(qseecom.registered_app_list_head));
1397 list_initialize(&(qseecom.registered_listener_list_head));
1398
Parth Dixite58fce02015-10-15 11:58:30 +05301399 rc = qseecom_scm_call(TZ_SVC_INFO, 3,
1400 &ver, sizeof(ver),
1401 &resp, sizeof(resp));
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001402
1403 if (!rc) {
1404 qseecom.qseecom_init_done = 1;
Parth Dixite58fce02015-10-15 11:58:30 +05301405 qseecom.qseos_version = resp.result;
1406 dprintf(ALWAYS, "Qseecom Init Done in Appsbl version is 0x%x\n",resp.result);
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001407 }
1408 return rc;
1409}
1410
Parth Dixite58fce02015-10-15 11:58:30 +05301411unsigned int qseecom_get_version()
1412{
1413 return qseecom.qseos_version;
1414}
1415
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001416int qseecom_exit()
1417{
1418 dprintf(SPEW, "%s called\n", __func__);
1419
1420 if (logbuf_req.phy_addr)
1421 free((void *)logbuf_req.phy_addr);
1422 qseecom.qseecom_init_done = 0;
1423 dprintf(ALWAYS, "Qseecom De-Init Done in Appsbl\n");
1424 return 0;
1425}