1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include <stddef.h>
14 #include <string.h>
15 #include <dlist.h>
16 #include "tee_log.h"
17 #include "tee_mem_mgmt_api.h"
18 #include "ta_framework.h"
19 #include "gtask_inner.h"
20 #include "tee_ext_api.h"
21 #include "tee_config.h"
22 #include "gtask_config_hal.h"
23 #include "mem_page_ops.h" // PAGE_ALIGN_UP
24 #include "securec.h"
25 #include "tee_load_lib.h"
26 #include "gtask_core.h" /* for find_service */
27 #include "dynload.h"
28 #include "tee_bitmap.h"
29 #include "gtask_inner.h"
30 #include "service_manager.h"
31 #include "session_manager.h"
32 #include "mem_manager.h"
33 #include "agent_manager.h"
34 #include <signal.h>
35 #include "ipclib.h"
36 #include "tee_task.h"
37 #include "tee_time_api.h"
38 #include "task_adaptor_pub.h"
39 #include "sys_timer.h"
40 #include "tee_load_lib.h"
41 #include "tee_drv_internal.h"
42 #include "drvcall_dyn_conf_builder.h"
43
44 #define SERVICE_AGED_TIME_LIMIT 2000U /* unit: millis */
45
46 /* defined in trustedcore/TEE_ext/tee_config.c */
47 extern struct service_struct *g_cur_service;
48 extern struct session_struct *g_cur_session;
49
50 #define INDEX_MAP_LEN (SERVICE_INDEX_MAX / 8)
51 #define FIRST_INDEX 1
52 static uint32_t g_cur_index = FIRST_INDEX;
53 static uint8_t g_service_index_map[INDEX_MAP_LEN] = {0};
54
55 /* service list head */
56 struct dlist_node g_service_head;
57 bool find_task(uint32_t task_id, struct service_struct **service, struct session_struct **session);
58
get_service_head_ptr(void)59 struct dlist_node *get_service_head_ptr(void)
60 {
61 return &g_service_head;
62 }
63
is_gtask_by_uuid(const TEE_UUID * task_uuid)64 bool is_gtask_by_uuid(const TEE_UUID *task_uuid)
65 {
66 TEE_UUID uuid = TEE_SERVICE_GLOBAL;
67
68 if (TEE_MemCompare(&uuid, task_uuid, sizeof(TEE_UUID)) == 0)
69 return true;
70
71 return false;
72 }
73
find_service(const TEE_UUID * uuid,uint32_t service_index,struct service_struct ** entry)74 int32_t find_service(const TEE_UUID *uuid, uint32_t service_index, struct service_struct **entry)
75 {
76 struct service_struct *service_entry = NULL;
77 int32_t index = -1;
78
79 if (uuid == NULL || entry == NULL)
80 return -1;
81
82 dlist_for_each_entry(service_entry, &g_service_head, struct service_struct, service_list) {
83 tlogd("iterate service %s \n", service_entry->name);
84 if ((TEE_MemCompare(&service_entry->property.uuid, uuid, sizeof(TEE_UUID)) == 0) &&
85 !service_entry->is_service_dead) {
86 tlogd("call service : %s\n", service_entry->name);
87 if (service_index == 0 || service_index == service_entry->index) {
88 index = (int32_t)service_entry->index;
89 *entry = service_entry;
90 break;
91 } else {
92 tloge("service(%s) uuid match but service_index miss match:0x%x <--> 0x%x\n", service_entry->name,
93 service_index, service_entry->index);
94 }
95 }
96 }
97 return index;
98 }
99
find_service_dead(const TEE_UUID * uuid,uint32_t service_index)100 struct service_struct *find_service_dead(const TEE_UUID *uuid, uint32_t service_index)
101 {
102 struct service_struct *service_entry = NULL;
103
104 if (uuid == NULL || service_index == 0)
105 return NULL;
106
107 dlist_for_each_entry(service_entry, &g_service_head, struct service_struct, service_list) {
108 if ((TEE_MemCompare(&service_entry->property.uuid, uuid, sizeof(TEE_UUID)) == 0) &&
109 service_entry->is_service_dead) {
110 if (service_index == service_entry->index)
111 return service_entry;
112 else
113 tloge("service(%s) uuid match but service_index miss match:0x%x <--> 0x%x\n", service_entry->name,
114 service_index, service_entry->index);
115 }
116 }
117 return NULL;
118 }
119
find_service_by_task_id(uint32_t task_id)120 struct service_struct *find_service_by_task_id(uint32_t task_id)
121 {
122 struct service_struct *service_entry = NULL;
123
124 dlist_for_each_entry(service_entry, &g_service_head, struct service_struct, service_list) {
125 if ((taskid_to_pid(service_entry->service_thread) == taskid_to_pid(task_id)) &&
126 !service_entry->is_service_dead)
127 return service_entry;
128 }
129 return NULL;
130 }
131
dynamic_service_exist(const TEE_UUID * uuid,bool build_in)132 bool dynamic_service_exist(const TEE_UUID *uuid, bool build_in)
133 {
134 struct service_struct *tmp_service = NULL;
135
136 if (uuid == NULL)
137 return false;
138
139 if (build_in == false || !is_build_in_service(uuid)) {
140 if (find_service(uuid, 0, &tmp_service) != -1 && tmp_service->elf_state == ELF_EXIST) {
141 tlogi("dynamic service already exist, no need load elf again!\n");
142 return true;
143 }
144 }
145 return false;
146 }
147
get_service_index(void)148 static int32_t get_service_index(void)
149 {
150 int32_t cnt = 0;
151
152 while (1) {
153 if (cnt == SERVICE_INDEX_MAX)
154 return -1;
155
156 if (g_cur_index >= SERVICE_INDEX_MAX)
157 g_cur_index = FIRST_INDEX;
158
159 if (!is_bit_seted(g_service_index_map, SERVICE_INDEX_MAX, g_cur_index)) {
160 set_bitmap(g_service_index_map, SERVICE_INDEX_MAX, g_cur_index);
161 break;
162 }
163 g_cur_index++;
164 cnt++;
165 }
166 return (int32_t)(g_cur_index++);
167 }
168
add_to_service_list(struct service_struct * service,const char * name,const TEE_UUID * uuid)169 static TEE_Result add_to_service_list(struct service_struct *service, const char *name, const TEE_UUID *uuid)
170 {
171 int32_t index = get_service_index();
172 if (index < 0) {
173 tloge("get service index fail\n");
174 return TEE_ERROR_OUT_OF_MEMORY;
175 }
176 service->index = (uint32_t)index;
177 service->init_build = 0;
178 if (strlen(name) < SERVICE_NAME_MAX) {
179 if (memmove_s(service->name, sizeof(service->name), (const void *)name, strlen(name)) != TEE_SUCCESS) {
180 tloge("memmove service name failed\n");
181 return TEE_ERROR_GENERIC;
182 }
183 } else {
184 if (memmove_s(service->name, sizeof(service->name),
185 (const void *)name, sizeof(service->name) - 1) != TEE_SUCCESS) {
186 tloge("memmove service name failed\n");
187 return TEE_ERROR_GENERIC;
188 }
189 }
190 if (memmove_s(&service->property.uuid, sizeof(service->property.uuid), uuid, sizeof(*uuid)) != TEE_SUCCESS)
191 return TEE_ERROR_GENERIC;
192
193 dlist_init(&service->session_head);
194
195 dlist_insert_tail(&service->service_list, &g_service_head);
196 return TEE_SUCCESS;
197 }
198
register_service(const char * name,const TEE_UUID * uuid,bool dyn_conf_registed,const struct service_attr * service_attr)199 TEE_Result register_service(const char *name, const TEE_UUID *uuid, bool dyn_conf_registed,
200 const struct service_attr *service_attr)
201 {
202 struct service_struct *service = NULL;
203 struct service_struct *tmp_service = NULL;
204
205 if (name == NULL || uuid == NULL || service_attr == NULL)
206 return TEE_ERROR_BAD_PARAMETERS;
207
208 tlogd("register_service : %s\n", name);
209 /* build in service can't be register after boot */
210 if (!service_attr->build_in && is_build_in_service(uuid))
211 return TEE_ERROR_REGISTER_EXIST_SERVICE;
212
213 /* have registered service but elf have been deleted, only need load elf */
214 if (find_service(uuid, 0, &tmp_service) != INVALID_SERVICE_INDEX) {
215 tmp_service->elf_state = ELF_EXIST;
216 return TEE_SUCCESS;
217 }
218
219 service = TEE_Malloc(sizeof(*service), 0);
220 if (service == NULL)
221 return TEE_ERROR_OUT_OF_MEMORY;
222 service->elf_state = ELF_EXIST;
223 service->ta_64bit = service_attr->ta_64bit;
224 service->first_open = true;
225 service->lib_list_head.next = NULL;
226 service->is_service_dead = false;
227 service->is_dyn_conf_registed = dyn_conf_registed;
228 service->img_type = service_attr->img_type;
229 /* we record load elf time for all service */
230 TEE_GetSystemTime(&service->load_elf_time);
231
232 if (!service_attr->build_in)
233 service->ref_cnt = 1;
234
235 TEE_Result ret = add_to_service_list(service, name, uuid);
236 if (ret != TEE_SUCCESS) {
237 TEE_Free(service);
238 return ret;
239 }
240
241 tlogd("register_service %s, index=%u ref_cnt=%d\n", name, service->index, service->ref_cnt);
242 return TEE_SUCCESS;
243 }
244
service_manager_init(void)245 TEE_Result service_manager_init(void)
246 {
247 TEE_UUID uuid_global = TEE_SERVICE_GLOBAL;
248 struct service_attr service_attr = { 0 };
249
250 service_attr.build_in = true;
251 #ifdef __aarch64__
252 service_attr.ta_64bit = true;
253 #else
254 service_attr.ta_64bit = false;
255 #endif
256
257 dlist_init(&g_service_head);
258 return register_service("global_task", &uuid_global, false, &service_attr);
259 }
260
261 /*
262 * init global data and install built-in services
263 */
ta_framework_init(void)264 TEE_Result ta_framework_init(void)
265 {
266 TEE_Result ret;
267 ret = service_manager_init();
268 if (ret != 0) {
269 tloge("service manager init failed:%u\n", ret);
270 return ret;
271 }
272
273 agent_manager_init();
274 mem_manager_init();
275
276 return TEE_SUCCESS;
277 }
278
279 /*
280 * If page align is true, it means we shoud multiply 4K for size,
281 * or we use origin size by 4k align up. The page align is declared
282 * in manifext.
283 */
get_heap_stack_size(bool page_align,uint32_t size)284 static uint64_t get_heap_stack_size(bool page_align, uint32_t size)
285 {
286 if (!page_align)
287 return PAGE_ALIGN_UP(size);
288 uint64_t mem_size = (uint64_t)size * PAGE_SIZE;
289 tlogd("page aligned so multi page size, %llu,%u", mem_size, size);
290 return mem_size;
291 }
292
init_service_property(const TEE_UUID * uuid,uint32_t stack,uint32_t heap,bool single_instance,bool multi_session,bool keep_alive,bool ssa_enum_enable,bool mem_page_align,const char * other_buff,uint32_t other_len)293 void init_service_property(const TEE_UUID *uuid, uint32_t stack, uint32_t heap,
294 bool single_instance, bool multi_session, bool keep_alive,
295 bool ssa_enum_enable, bool mem_page_align, const char *other_buff,
296 uint32_t other_len)
297 {
298 struct service_struct *service_entry = NULL;
299
300 if (uuid == NULL)
301 return;
302
303 dlist_for_each_entry(service_entry, &g_service_head, struct service_struct, service_list) {
304 if (!TEE_MemCompare(&service_entry->property.uuid, uuid, sizeof(TEE_UUID)) &&
305 !service_entry->is_service_dead) {
306 service_entry->property.stack_size = get_heap_stack_size(mem_page_align, stack);
307 service_entry->property.heap_size = get_heap_stack_size(mem_page_align, heap);
308 service_entry->property.single_instance = single_instance;
309 service_entry->property.multi_session = multi_session;
310 service_entry->property.keep_alive = keep_alive;
311 service_entry->property.ssa_enum_enable = ssa_enum_enable;
312
313 if (other_buff != NULL && other_len != 0) {
314 service_entry->property.other_buff = (char *)TEE_Malloc(other_len, 0);
315 if (service_entry->property.other_buff != NULL) {
316 if (memmove_s(service_entry->property.other_buff, other_len,
317 (void *)other_buff, other_len) != TEE_SUCCESS) {
318 TEE_Free(service_entry->property.other_buff);
319 service_entry->property.other_buff = NULL;
320 } else
321 service_entry->property.other_len = other_len;
322 } else {
323 tloge("failed to allocate for service_entry->property.other_buff, other_len is %u\n", other_len);
324 }
325 }
326 break;
327 }
328 }
329 }
330
do_find_task(uint32_t task_id,bool dead_status,struct service_struct ** entry,struct session_struct ** session)331 static bool do_find_task(uint32_t task_id, bool dead_status,
332 struct service_struct **entry, struct session_struct **session)
333 {
334 struct session_struct *sess_context = NULL;
335 struct service_struct *service_entry = NULL;
336
337 if (entry == NULL || session == NULL)
338 return false;
339
340 /* Go through all the services and all sessions */
341 dlist_for_each_entry(service_entry, &g_service_head, struct service_struct, service_list) {
342 if (service_entry->is_service_dead != dead_status)
343 continue;
344 dlist_for_each_entry(sess_context, &service_entry->session_head, struct session_struct, session_list) {
345 if (sess_context->task_id == task_id) {
346 *entry = service_entry;
347 *session = sess_context;
348 return true;
349 }
350 }
351 }
352
353 return false;
354 }
355
find_task(uint32_t task_id,struct service_struct ** service,struct session_struct ** session)356 bool find_task(uint32_t task_id, struct service_struct **service, struct session_struct **session)
357 {
358 return do_find_task(task_id, false, service, session);
359 }
360
find_task_dead(uint32_t task_id,struct service_struct ** service,struct session_struct ** session)361 bool find_task_dead(uint32_t task_id, struct service_struct **service, struct session_struct **session)
362 {
363 return do_find_task(task_id, true, service, session);
364 }
365
is_system_service(const struct service_struct * service)366 bool is_system_service(const struct service_struct *service)
367 {
368 TEE_UUID reet_uuid = TEE_SERVICE_REET;
369 TEE_UUID gtask_uuid = TEE_SERVICE_GLOBAL;
370
371 if (service == NULL)
372 return false;
373
374 if ((TEE_MemCompare(&reet_uuid, &service->property.uuid, sizeof(TEE_UUID)) == 0) ||
375 (TEE_MemCompare(>ask_uuid, &service->property.uuid, sizeof(TEE_UUID)) == 0) ||
376 is_internal_task_by_uuid(&service->property.uuid))
377 return true;
378 return false;
379 }
380
incr_ref_cnt(struct service_struct * service)381 static void incr_ref_cnt(struct service_struct *service)
382 {
383 if (service == NULL)
384 return;
385
386 /* in case of overflow */
387 if ((service->ref_cnt + 1) < 0) {
388 tloge("invalid ref cnt when incr\n");
389 return;
390 }
391
392 service->ref_cnt++;
393 }
394
decr_ref_cnt(struct service_struct * service)395 void decr_ref_cnt(struct service_struct *service)
396 {
397 if (service == NULL)
398 return;
399
400 /* in case of overflow */
401 if (service->ref_cnt <= 0) {
402 tloge("invalid ref cnt when decr\n");
403 return;
404 }
405
406 service->ref_cnt--;
407 }
408
need_load_srv(const TEE_UUID * uuid)409 bool need_load_srv(const TEE_UUID *uuid)
410 {
411 struct service_struct *service = NULL;
412
413 if (uuid == NULL)
414 return false;
415
416 if (is_build_in_service(uuid))
417 return false;
418
419 if (find_service(uuid, 0, &service) == INVALID_SERVICE_INDEX)
420 return true;
421
422 if (!service->property.single_instance) {
423 tloge("only support singleInstance as true\n");
424 return false;
425 }
426 incr_ref_cnt(service);
427
428 TEE_GetSystemTime(&service->load_elf_time);
429 tlogd("service %s, session count is %d ref_cnt++ is %d\n", service->name, service->session_count, service->ref_cnt);
430
431 return false;
432 }
433
434 #define S_TO_MILLIS 1000U
435
get_interval(const TEE_Time * cur,const TEE_Time * base,uint64_t * interval)436 void get_interval(const TEE_Time *cur, const TEE_Time *base, uint64_t *interval)
437 {
438 if (cur == NULL || base == NULL || interval == NULL)
439 return;
440
441 *interval = 0;
442 if (cur->seconds < base->seconds) {
443 tloge("error: incorrect time\n");
444 return;
445 }
446 /*
447 * 0xffffffffffffffff millis is more than 650000 year,
448 * interval will never overflow when seconds multiplicate 1000
449 */
450 *interval = ((uint64_t)cur->seconds - (uint64_t)base->seconds) * S_TO_MILLIS;
451
452 if (cur->millis >= base->millis)
453 *interval += (uint64_t)cur->millis - (uint64_t)base->millis;
454 else
455 *interval -= (uint64_t)base->millis - (uint64_t)cur->millis;
456 }
457
is_aged_service(const struct service_struct * service)458 static bool is_aged_service(const struct service_struct *service)
459 {
460 TEE_Time current = { 0, 0 };
461 uint64_t interval;
462
463 if (service == NULL) {
464 tloge("invalid param\n");
465 return false;
466 }
467
468 TEE_GetSystemTime(¤t);
469
470 get_interval(¤t, &service->load_elf_time, &interval);
471 if (interval > SERVICE_AGED_TIME_LIMIT) {
472 tlogi("aged service: uuid is 0x%x, and seconds interval =%llu, max interval = %u\n",
473 service->property.uuid.timeLow, (unsigned long long)interval, SERVICE_AGED_TIME_LIMIT);
474 return true;
475 }
476 return false;
477 }
478
do_age_service(struct service_struct * service_entry)479 static void do_age_service(struct service_struct *service_entry)
480 {
481 if (is_aged_service(service_entry)) {
482 tlogi("uuid 0x%x is aged, ref_cnt: %d\n", service_entry->property.uuid.timeLow, service_entry->ref_cnt);
483 process_release_service(service_entry, TA_REGION_RELEASE);
484 }
485 return;
486 }
487
age_timeout_lib(void)488 void age_timeout_lib(void)
489 {
490 struct service_struct *service_entry = NULL;
491
492 dlist_for_each_entry(service_entry, &g_service_head, struct service_struct, service_list) {
493 if (service_entry->lib_list_head.next == NULL)
494 continue;
495
496 do_age_timeout_lib(service_entry);
497 }
498 }
499
age_service(void)500 TEE_Result age_service(void)
501 {
502 struct service_struct *service_entry = NULL;
503 struct service_struct *service_entry_tmp = NULL;
504
505 dlist_for_each_entry_safe(service_entry, service_entry_tmp, &g_service_head, struct service_struct, service_list) {
506 if (service_entry->is_service_dead)
507 continue;
508 // builtin TA no need to age
509 if (is_build_in_service(&service_entry->property.uuid))
510 continue;
511
512 // non keepalive, session count is 0; keepalive, session count is 0, first_open is true; we age it
513 if (service_entry->session_count == 0 &&
514 (!service_entry->property.keep_alive || service_entry->first_open))
515 do_age_service(service_entry);
516 }
517
518 return TEE_SUCCESS;
519 }
520
recycle_srvc_thread(struct service_struct * service)521 void recycle_srvc_thread(struct service_struct *service)
522 {
523 if (service == NULL) {
524 tloge("service is null!\n");
525 return;
526 }
527
528 if (service->service_thread != 0) {
529 /*
530 * gtask directly set TA process as zombie,
531 * in case of service thread of TA is blocked and won't exit by itself
532 */
533 if (kill((int)taskid_to_pid(service->service_thread), 0) == 0)
534 gt_wait_process(service->service_thread);
535 service->service_thread = 0;
536 /* send msg to internal service */
537 task_adapt_ta_release(&service->property.uuid);
538 }
539 }
540
process_release_service(struct service_struct * service,uint32_t if_reuse_elf)541 void process_release_service(struct service_struct *service, uint32_t if_reuse_elf)
542 {
543 if (service == NULL) {
544 tloge("service is null!\n");
545 return;
546 }
547
548 // for non-builtin TA, elf has be released when open session success.
549 if (service->elf_state == ELF_EXIST) {
550 if (sre_release_dynamic_region(&service->property.uuid, if_reuse_elf) != 0)
551 tloge("release elf failed\n");
552 }
553
554 /* if TA's dyn conf has been registed, we should unregist that */
555 if (service->is_dyn_conf_registed) {
556 unregister_conf(uninstall_drvcall_permission, &service->property.uuid, sizeof(service->property.uuid));
557 service->is_dyn_conf_registed = false;
558 }
559
560 release_timer_event(&service->property.uuid);
561 recycle_srvc_thread(service);
562 tee_delete_all_libinfo(service);
563 dlist_delete(&service->service_list);
564 clear_bitmap(g_service_index_map, SERVICE_INDEX_MAX, service->index);
565 tlogd("release service: %s, service index is %d\n", service->name, service->index);
566 if (service->property.other_buff != NULL) {
567 TEE_Free(service->property.other_buff);
568 service->property.other_buff = NULL;
569 }
570 TEE_Free(service);
571 }
572
573 /* for internal service, such as SSA, we only release session node */
create_internal_task_fail(void)574 static void create_internal_task_fail(void)
575 {
576 if (g_cur_session != NULL) {
577 if (g_cur_service != NULL) {
578 CLR_BIT(g_cur_service->session_bitmap[get_index_by_uint32(g_cur_session->session_id - 1)],
579 get_bit_by_uint32(g_cur_session->session_id - 1));
580 g_cur_service->session_count--;
581 }
582 release_pam_node(g_cur_session->pam_node);
583 dlist_delete(&g_cur_session->session_list);
584 TEE_Free(g_cur_session);
585 g_cur_session = NULL;
586 }
587 }
588
589 /* init this secure call's context and set the cmd and cmd_type to the current session */
start_internal_task(const TEE_UUID * uuid,uint16_t task_prio,const char * task_name,uint32_t * task_id)590 TEE_Result start_internal_task(const TEE_UUID *uuid, uint16_t task_prio, const char *task_name, uint32_t *task_id)
591 {
592 TEE_Result ret;
593 struct session_struct *session = (struct session_struct *)NULL;
594 uint32_t session_id;
595 int32_t index;
596 struct tsk_init_param task_param;
597
598 if (task_id == NULL)
599 return TEE_ERROR_BAD_PARAMETERS;
600
601 index = find_service(uuid, 0, &g_cur_service);
602 tlogd(" SS Agent handle = %d\n", index);
603 if (index <= 0) {
604 tloge("Service not found!\n");
605 return TEE_ERROR_GENERIC;
606 }
607
608 ret = add_new_session_into_list(&session, &session_id, 0);
609 if (ret != TEE_SUCCESS)
610 return ret;
611
612 g_cur_service->session_count++;
613
614 /* Init task parameters */
615 task_param.task_prior = task_prio;
616 task_param.task_name = task_name;
617 task_param.que_num = DEFAULT_MSG_QUEUE_NUM;
618
619 if (memcpy_s(&task_param.uuid, sizeof(task_param.uuid), &(g_cur_service->property.uuid), sizeof(TEE_UUID)) != EOK) {
620 tloge("copy uuid failed\n");
621 ret = TEE_ERROR_GENERIC;
622 goto create_task_fail;
623 }
624
625 /* Create task */
626 int sre_ret = sre_task_create(&task_param, task_id);
627 if (sre_ret != 0) {
628 tloge("create task fail : errorno = 0x%x\n", sre_ret);
629 ret = TEE_ERROR_GENERIC;
630 goto create_task_fail;
631 }
632
633 session->task_id = *task_id;
634
635 session->cmd_type = CMD_TYPE_SECURE_TO_SECURE;
636 return ret;
637
638 create_task_fail:
639 create_internal_task_fail();
640 return ret;
641 }
642
release_ion_empty_service(const TEE_UUID * uuid)643 TEE_Result release_ion_empty_service(const TEE_UUID *uuid)
644 {
645 struct service_struct *service_context = NULL;
646 if (uuid == NULL) {
647 tloge("uuid is null\n");
648 return TEE_ERROR_GENERIC;
649 }
650 if (find_service(uuid, 0, &service_context) == -1)
651 return TEE_SUCCESS;
652
653 if (service_context->session_count == 0 && service_context->ref_cnt == 0) {
654 if (!is_build_in_service(uuid)) {
655 if (!service_context->property.keep_alive) {
656 process_release_service(service_context, TA_REGION_RELEASE);
657 service_context = NULL;
658 tlogi("release third party ta success\n");
659 }
660 }
661 } else {
662 tloge("UUID: %x session count =%u, ref cnt=%d\n", uuid->timeLow,
663 service_context->session_count, service_context->ref_cnt);
664 return TEE_ERROR_GENERIC;
665 }
666 return TEE_SUCCESS;
667 }
668
669 #ifdef CONFIG_ENABLE_DUMP_SRV_SESS
dump_agent_info(const struct agent_control * agent,const char * prefix_str)670 static void dump_agent_info(const struct agent_control *agent, const char *prefix_str)
671 {
672 struct session_struct *sess_context = NULL;
673
674 tlogi("%s agent id: 0x%x, locked: %u, size: %u\n",
675 prefix_str, agent->id, (uint32_t)agent->locked, agent->size);
676 tlogi("%s waiting_sessions: %s\n", prefix_str, (dlist_empty(&agent->waiting_sessions) ? "(empty)" : ""));
677 dlist_for_each_entry(sess_context, &agent->waiting_sessions, struct session_struct, waiting_agent)
678 tlogi("%s session name: %s, id: 0x%x, task_id: 0x%x\n", prefix_str,
679 sess_context->name, sess_context->session_id, sess_context->task_id);
680 }
681
682 #define MAX_PREFIX 12
683 #define PREFIX_PER_DEPTH 4
dump_session_info(const struct session_struct * sess_context,int depth)684 static void dump_session_info(const struct session_struct *sess_context, int depth)
685 {
686 struct session_struct *child_sess = NULL;
687 struct agent_control *agent = NULL;
688
689 /* base session infos */
690 int prefix_len = depth * PREFIX_PER_DEPTH;
691 if (prefix_len > MAX_PREFIX)
692 return;
693 char prefix_str[MAX_PREFIX + 1] = " ";
694 prefix_str[prefix_len] = '\0';
695 tlogi("%ssession name: %s, sess_id: 0x%x, task_id: 0x%x, login_method: 0x%x,\n", prefix_str,
696 sess_context->name, sess_context->session_id, sess_context->task_id,
697 sess_context->login_method);
698 tlogi("%sta2ta_from_taskid: 0x%x, cancelable: %u, agent_pending: 0x%x, ta2ta_level: %u, cmd_type: %u,\n",
699 prefix_str, sess_context->ta2ta_from_taskid, (uint32_t)sess_context->cancelable,
700 (uint32_t)sess_context->agent_pending, sess_context->ta2ta_level, sess_context->cmd_type);
701 tlogi("%swait_ta_back_msg: 0x%x, session_status: 0x%x\n", prefix_str,
702 (uint32_t)sess_context->wait_ta_back_msg, sess_context->session_status);
703
704 /* agents */
705 tlogi("%slocked_agents: %s\n", prefix_str, (dlist_empty(&sess_context->locked_agents) ? "(empty)" : ""));
706 dlist_for_each_entry(agent, &sess_context->locked_agents, struct agent_control, session_list)
707 dump_agent_info(agent, prefix_str);
708
709 /* child session info */
710 tlogi("%schild sessions: %s\n", prefix_str, (dlist_empty(&sess_context->child_ta_sess_head) ? "(empty)" : ""));
711 dlist_for_each_entry(child_sess, &sess_context->child_ta_sess_head, struct session_struct, child_ta_sess_list)
712 dump_session_info(child_sess, depth + 1);
713 }
714
dump_service_session_info(const smc_cmd_t * cmd)715 TEE_Result dump_service_session_info(const smc_cmd_t *cmd)
716 {
717 TEE_Result ret = TEE_SUCCESS;
718 struct service_struct *service_entry = NULL;
719 struct lib_info *libinfo = NULL;
720 struct session_struct *sess_context = NULL;
721 (void)cmd;
722
723 tlogi("dump all services:\n");
724 dlist_for_each_entry(service_entry, &g_service_head, struct service_struct, service_list) {
725 /* base info */
726 tlogi("service index: %u, name: %s\n", service_entry->index, service_entry->name);
727 tlogi("ref_cnt: %d, init_build: %u, first_open: %d, ta_64bit: %d, is_dead: %d, elf_state: 0x%x,",
728 service_entry->ref_cnt, service_entry->init_build, (int32_t)service_entry->first_open,
729 (int32_t)service_entry->ta_64bit,
730 (int32_t)service_entry->is_service_dead, service_entry->elf_state);
731 tlogi("service_thread: 0x%x, load elf time: %u.%us\n", service_entry->service_thread,
732 service_entry->load_elf_time.seconds, service_entry->load_elf_time.millis);
733
734 /* lib info */
735 libinfo = service_entry->lib_list_head.next;
736 tlogi("libs : %s\n", (libinfo == NULL ? "(empty)" : ""));
737 while (libinfo != NULL) {
738 tlogi(" libname: %s, load_elf_time: %u.%us, type: 0x%x\n", libinfo->name, libinfo->load_elf_time.seconds,
739 libinfo->load_elf_time.millis, (uint32_t)libinfo->type);
740 libinfo = libinfo->next;
741 }
742
743 /* session info */
744 tlogi("session count: %u \n", service_entry->session_count);
745 dlist_for_each_entry(sess_context, &service_entry->session_head, struct session_struct, session_list)
746 dump_session_info(sess_context, 1);
747 tlogi("\n");
748 }
749
750 return ret;
751 }
752 #endif
753