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