• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&gtask_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(&current);
469 
470     get_interval(&current, &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