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