• 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 "drv_dyn_conf_mgr.h"
14 #include <tee_log.h>
15 #include <libdrv_frame.h>
16 #include <ta_framework.h>
17 #include <dyn_conf_dispatch_inf.h>
18 #include <target_type.h>
19 #include "drv_fd_ops.h"
20 #include "drv_param_ops.h"
21 #include "drv_process_mgr.h"
22 
free_drv_conf_list(struct drv_conf_t * drv_conf,uint32_t receive_flag)23 void free_drv_conf_list(struct drv_conf_t *drv_conf, uint32_t receive_flag)
24 {
25     if (drv_conf == NULL) {
26         tloge("invalid drv conf\n");
27         return;
28     }
29 
30     if (receive_flag >= RECEIVE_IO_MAP_LIST && drv_conf->io_map_list != NULL) {
31         free(drv_conf->io_map_list);
32         drv_conf->io_map_list = NULL;
33         drv_conf->io_map_list_size = 0;
34     }
35 
36     if (receive_flag >= RECEIVE_IRQ_LIST && drv_conf->irq_list != NULL) {
37         free(drv_conf->irq_list);
38         drv_conf->irq_list = NULL;
39         drv_conf->irq_list_size = 0;
40     }
41 
42     if (receive_flag >= RECEIVE_MAP_SECURE_LIST && drv_conf->map_secure_list != NULL) {
43         free(drv_conf->map_secure_list);
44         drv_conf->map_secure_list = NULL;
45         drv_conf->map_secure_list_size = 0;
46     }
47 
48     if (receive_flag >= RECEIVE_MAP_NOSECURE_LIST && drv_conf->map_nosecure_list != NULL) {
49         free(drv_conf->map_nosecure_list);
50         drv_conf->map_nosecure_list = NULL;
51         drv_conf->map_nosecure_list_size = 0;
52     }
53 
54     if (receive_flag >= RECEIVE_MAC_INFO_LIST && drv_conf->mac_info_list != NULL) {
55         free(drv_conf->mac_info_list);
56         drv_conf->mac_info_list = NULL;
57         drv_conf->mac_info_list_size = 0;
58     }
59 
60     if (receive_flag >= RECEIVE_CMD_PERM_LIST && drv_conf->cmd_perm_list != NULL) {
61         free(drv_conf->cmd_perm_list);
62         drv_conf->cmd_perm_list = NULL;
63         drv_conf->cmd_perm_list_size = 0;
64     }
65 }
66 
67 #ifdef TEE_SUPPORT_DYN_CONF_DEBUG
dump_drv_basic_info(const struct drv_basic_info_t * drv_basic_info)68 static void dump_drv_basic_info(const struct drv_basic_info_t *drv_basic_info)
69 {
70     if (drv_basic_info->upgrade)
71         tlogi("[drv dyn conf] upgrade: true\n");
72     else
73         tlogi("[drv dyn conf] upgrade: false\n");
74 
75     if (drv_basic_info->virt2phys)
76         tlogi("[drv dyn conf] virt2phys: true\n");
77     else
78         tlogi("[drv dyn conf] virtphys: false\n");
79 
80     tlogi("[drv dyn conf] thread_limit: %u\n", drv_basic_info->thread_limit);
81 
82     if (drv_basic_info->exception_mode == DYN_CONF_SYSCRASH_TAG)
83         tlogi("[drv dyn conf] exception_mode: syscrash\n");
84     else if (drv_basic_info->exception_mode == DYN_CONF_RESTART_TAG)
85         tlogi("[drv dyn conf] exception_mode: restart\n");
86     else if (drv_basic_info->exception_mode == DYN_CONF_DDOS_TAG)
87         tlogi("[drv dyn conf] exception_mode: ddos\n");
88     else
89         tlogi("[drv dyn conf] exception_mode: unknown\n");
90 }
91 
dump_drv_mani(const struct drv_mani_t * mani)92 static void dump_drv_mani(const struct drv_mani_t *mani)
93 {
94     tlogi("[drv dyn conf] UUID %x\n", mani->srv_uuid.timeLow);
95     tlogi("[drv dyn conf] service name %s\n", mani->service_name);
96 
97     if (mani->keep_alive)
98         tlogi("[drv dyn conf] keep_alive is true\n");
99     else
100         tlogi("[drv dyn conf] keep_alive is false\n");
101 
102     tlogi("[drv dyn conf] data size 0x%x\n", mani->data_size);
103     tlogi("[drv dyn conf] stack size 0x%x\n", mani->stack_size);
104 }
105 
dump_drv_io_map_list(const struct drv_conf_t * drv_conf)106 static void dump_drv_io_map_list(const struct drv_conf_t *drv_conf)
107 {
108     tlogi("[drv dyn conf] io map list size %u\n", drv_conf->io_map_list_size);
109     uint32_t i;
110     for (i = 0; i < drv_conf->io_map_list_size; i++)
111         tlogi("[drv dyn conf] iomap region size %llx\n",
112               (unsigned long long)(drv_conf->io_map_list[i].end -
113                                    drv_conf->io_map_list[i].start));
114 }
115 
dump_drv_irq_list(const struct drv_conf_t * drv_conf)116 static void dump_drv_irq_list(const struct drv_conf_t *drv_conf)
117 {
118     tlogi("[drv dyn conf] irq list size %u\n", drv_conf->irq_list_size);
119     uint32_t i;
120     for (i = 0; i < drv_conf->irq_list_size; i++)
121         tlogi("[drv dyn conf] irq %llu\n", (unsigned long long)drv_conf->irq_list[i]);
122 }
123 
dump_drv_map_secure_list(const struct drv_conf_t * drv_conf)124 static void dump_drv_map_secure_list(const struct drv_conf_t *drv_conf)
125 {
126     tlogi("[drv dyn conf] map secure list size %u\n", drv_conf->map_secure_list_size);
127     uint32_t i;
128     for (i = 0; i < drv_conf->map_secure_list_size; i++) {
129         struct tee_uuid uuid = drv_conf->map_secure_list[i].uuid;
130         tlogi("[drv dyn conf] map_secure uuid %08x-%04x-%04x\n",
131               uuid.timeLow, uuid.timeMid, uuid.timeHiAndVersion);
132         tlogi("[drv dyn conf] map_secure region size %llx\n",
133               (unsigned long long)(drv_conf->map_secure_list[i].region.end -
134                                    drv_conf->map_secure_list[i].region.start));
135     }
136 }
137 
dump_drv_map_nosecure_list(const struct drv_conf_t * drv_conf)138 static void dump_drv_map_nosecure_list(const struct drv_conf_t *drv_conf)
139 {
140     tlogi("[drv dyn conf] map nosecure list size %u\n", drv_conf->map_nosecure_list_size);
141     uint32_t i;
142     for (i = 0; i < drv_conf->map_nosecure_list_size; i++) {
143         struct tee_uuid uuid = drv_conf->map_nosecure_list[i].uuid;
144         tlogi("[drv dyn conf] map_nosecure uuid %08x-%04x-%04x\n",
145               uuid.timeLow, uuid.timeMid, uuid.timeHiAndVersion);
146     }
147 }
148 
dump_drv_mac_info(const struct drv_conf_t * drv_conf)149 static void dump_drv_mac_info(const struct drv_conf_t *drv_conf)
150 {
151     tlogi("[drv dyn conf] drv mac list size %u\n", drv_conf->mac_info_list_size);
152     uint32_t i;
153     for (i = 0; i < drv_conf->mac_info_list_size; i++) {
154         struct tee_uuid uuid = drv_conf->mac_info_list[i].uuid;
155         tlogi("[drv dyn conf] mac info uuid %08x-%04x-%04x perm %llx\n",
156               uuid.timeLow, uuid.timeMid, uuid.timeHiAndVersion,
157               (unsigned long long)drv_conf->mac_info_list[i].perm);
158     }
159 }
160 
dump_drv_cmd_perm_info(const struct drv_conf_t * drv_conf)161 static void dump_drv_cmd_perm_info(const struct drv_conf_t *drv_conf)
162 {
163     tlogi("[drv dyn conf] drv cmd perm list size %u\n", drv_conf->cmd_perm_list_size);
164     uint32_t i;
165     for (i = 0; i < drv_conf->cmd_perm_list_size; i++)
166         tlogi("[drv dyn conf] cmd %llx permission %llx\n",
167               (unsigned long long)drv_conf->cmd_perm_list[i].cmd,
168               (unsigned long long)drv_conf->cmd_perm_list[i].perm);
169 }
170 
dump_drv_conf(const struct drv_conf_t * drv_conf)171 void dump_drv_conf(const struct drv_conf_t *drv_conf)
172 {
173     if (drv_conf == NULL) {
174         tloge("invalid drv conf\n");
175         return;
176     }
177 
178     dump_drv_mani(&drv_conf->mani);
179     dump_drv_basic_info(&drv_conf->drv_basic_info);
180     dump_drv_io_map_list(drv_conf);
181     dump_drv_irq_list(drv_conf);
182     dump_drv_map_secure_list(drv_conf);
183     dump_drv_map_nosecure_list(drv_conf);
184     dump_drv_mac_info(drv_conf);
185     dump_drv_cmd_perm_info(drv_conf);
186 }
187 #endif
188 
receive_drv_conf_list(void ** list,uint16_t list_size,uint32_t item_size)189 static int32_t receive_drv_conf_list(void **list, uint16_t list_size, uint32_t item_size)
190 {
191     if (list == NULL || item_size == 0 || item_size >= MAX_IMAGE_LEN) {
192         tloge("invalied params while receive drv conf list\n");
193         return TEE_ERROR_BAD_PARAMETERS;
194     }
195 
196     if (*list == NULL || list_size == 0)
197         return TEE_SUCCESS;
198 
199     /* list_size < 0xffff means tmp_size cannot larger than 0xFFFFFFFF */
200     uint32_t tmp_size = list_size * item_size;
201     if (tmp_size >= MAX_IMAGE_LEN || list_size * item_size < item_size) {
202         tloge("tmp size is too large or overflow while receive drv conf list %u\n", item_size);
203         return TEE_ERROR_BAD_PARAMETERS;
204     }
205 
206     void *tmp_list = malloc(tmp_size);
207     if (tmp_list == NULL) {
208         tloge("malloc tmp_list failed\n");
209         return TEE_ERROR_GENERIC;
210     }
211 
212     if (copy_from_client((uint64_t)(uintptr_t)(*list), tmp_size, (uintptr_t)tmp_list, tmp_size) != TEE_SUCCESS) {
213         tloge("copy_from_client tmp_list failed\n");
214         free(tmp_list);
215         return TEE_ERROR_GENERIC;
216     }
217 
218     *list = tmp_list;
219 
220     return TEE_SUCCESS;
221 }
222 
do_receive_drv_conf(struct drv_conf_t * drv_conf)223 int32_t do_receive_drv_conf(struct drv_conf_t *drv_conf)
224 {
225     uint32_t receive_flag = 0;
226     if (drv_conf == NULL) {
227         tloge("invalid receive param\n");
228         return -1;
229     }
230 
231     /* receive drv_conf iomap list */
232     if (receive_drv_conf_list((void **)&drv_conf->io_map_list,
233                               drv_conf->io_map_list_size, sizeof(struct addr_region_t)) != 0)
234         goto err_out;
235     receive_flag = RECEIVE_IO_MAP_LIST;
236 
237     /* receive irq list */
238     if (receive_drv_conf_list((void **)&drv_conf->irq_list,
239                               drv_conf->irq_list_size, sizeof(uint64_t)) != 0)
240         goto err_out;
241     receive_flag = RECEIVE_IRQ_LIST;
242 
243     /* receive map secure list */
244     if (receive_drv_conf_list((void **)&drv_conf->map_secure_list,
245                               drv_conf->map_secure_list_size, sizeof(struct drv_map_secure_t)) != 0)
246         goto err_out;
247     receive_flag = RECEIVE_MAP_SECURE_LIST;
248 
249     /* receive map nosecure list */
250     if (receive_drv_conf_list((void **)&drv_conf->map_nosecure_list,
251                               drv_conf->map_nosecure_list_size, sizeof(struct drv_map_nosecure_t)) != 0)
252         goto err_out;
253     receive_flag = RECEIVE_MAP_NOSECURE_LIST;
254 
255     /* receive mac info list */
256     if (receive_drv_conf_list((void **)&drv_conf->mac_info_list,
257                               drv_conf->mac_info_list_size, sizeof(struct drv_mac_info_t)) != 0)
258         goto err_out;
259     receive_flag = RECEIVE_MAC_INFO_LIST;
260 
261     /* receive cmd perm list */
262     if (receive_drv_conf_list((void **)&drv_conf->cmd_perm_list,
263                               drv_conf->cmd_perm_list_size, sizeof(struct drv_cmd_perm_info_t)) != 0)
264         goto err_out;
265 
266     return 0;
267 
268 err_out:
269     free_drv_conf_list(drv_conf, receive_flag);
270     return -1;
271 }
272 
check_drv_node_state(struct task_node * node)273 int32_t check_drv_node_state(struct task_node *node)
274 {
275     int32_t func_ret = DRV_FAIL;
276 
277     if (node == NULL || node->tlv.drv_conf == NULL) {
278         tloge("invalid node\n");
279         return DRV_FAIL;
280     }
281 
282     int32_t ret = drv_mutex_lock(&node->state_mtx);
283     if (ret != 0) {
284         tloge("get state mtx fail\n");
285         return DRV_FAIL;
286     }
287 
288     switch (node->state) {
289     case TASK_LOAD:
290         node->state = TASK_SPAWN;
291         func_ret = DRV_NEED_SPAWN;
292         break;
293     case TASK_SPAWN:
294         while (node->state == TASK_SPAWN) {
295             tloge("drv:%s is spawn by other thread, just wait\n", node->tlv.drv_conf->mani.service_name);
296             ret = pthread_cond_wait(&node->state_cond, &node->state_mtx);
297             if (ret != 0) {
298                 tloge("something wrong, drv:%s cond wait fail:0x%x\n", node->tlv.drv_conf->mani.service_name, ret);
299                 goto unlock_mtx;
300             }
301         }
302 
303         if (node->state == TASK_NORMAL)
304             func_ret = DRV_SUCC;
305         else
306             tloge("something wrong, wait spawn fail state:0x%x\n", node->state);
307         break;
308     case TASK_NORMAL:
309         func_ret = DRV_SUCC;
310         break;
311     default:
312         /* when drv spawn fail, just return fail */
313         tloge("something wrong, drv:%s state:%d\n", node->tlv.drv_conf->mani.service_name, node->state);
314     }
315 
316 unlock_mtx:
317     ret = pthread_mutex_unlock(&node->state_mtx);
318     if (ret != 0)
319         tloge("something wrong, unlock mtx in drv state fail\n");
320 
321     return func_ret;
322 }
323 
broadcast_drv_state(struct task_node * node,bool spawn_succ)324 void broadcast_drv_state(struct task_node *node, bool spawn_succ)
325 {
326     if (node == NULL) {
327         tloge("invalid node\n");
328         return;
329     }
330 
331     int32_t ret = drv_mutex_lock(&node->state_mtx);
332     if (ret != 0) {
333         tloge("get state mtx fail\n");
334         return;
335     }
336 
337     if (node->state != TASK_SPAWN)
338         tloge("something wrong, node->state:%d not DRV_SPAWN\n", node->state);
339 
340     if (spawn_succ)
341         node->state = TASK_NORMAL;
342     else
343         node->state = TASK_SPAWN_FAIL;
344 
345     pthread_cond_broadcast(&node->state_cond);
346 
347     ret = pthread_mutex_unlock(&node->state_mtx);
348     if (ret != 0)
349         tloge("something wrong, unlock stat mtx fail\n");
350 }
351