• 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 #include "ta_framework.h"
13 #include "tee_log.h"
14 #include "tee_init.h"
15 #include "tee_ext_api.h"
16 #include "tee_ss_agent_api.h"
17 #include "sfs_internal.h"
18 #include "agent.h"
19 #include "securec.h"
20 #include "tee_internal_task_pub.h"
21 #include <ipclib_hal.h>
22 
ssa_msgqueue_add(uint32_t cmd,const union ssa_agent_msg * msg,uint32_t sndr)23 static void ssa_msgqueue_add(uint32_t cmd, const union ssa_agent_msg *msg, uint32_t sndr)
24 {
25     errno_t rc;
26     ssa_cmd_t *cmd_oper = NULL;
27     struct ssa_agent_rsp rsp   = {0};
28 
29     uint32_t in = g_ssa_msg_queue.in;
30     tlogd("put msg %x to SSqueue[%u]\n", cmd, in);
31 
32     if (in >= SS_AGENT_MSG_QUEUE_SIZE) {
33         tloge("invalid ssa msg queue in : [%u]\n", in);
34         goto send_msg_to_ta;
35     }
36 
37     if (g_ssa_msg_queue.msg[in].msg_id == 0xFFFFFFFF) {
38         g_ssa_msg_queue.msg[in].msg_id = cmd;
39         g_ssa_msg_queue.msg[in].sender = sndr;
40         rc = memmove_s(&g_ssa_msg_queue.msg[in].msg, sizeof(g_ssa_msg_queue.msg[in].msg), msg,
41             sizeof(union ssa_agent_msg));
42         if (rc != EOK) {
43             g_ssa_msg_queue.msg[in].msg_id = 0xFFFFFFFF;
44 
45             tloge("memmove ssa msg queue error %x\n", rc);
46         } else {
47             if (++in >= SS_AGENT_MSG_QUEUE_SIZE)
48                 in = 0;
49 
50             g_ssa_msg_queue.in = in;
51         }
52     } else {
53         tloge("SSqueue overflow\n");
54         for (uint32_t i = 0; i < SS_AGENT_MSG_QUEUE_SIZE; i++)
55             tloge("ssa queue:%u, cmd:0x%x, taskid:0x%x", i,
56                 g_ssa_msg_queue.msg[i].msg_id, g_ssa_msg_queue.msg[i].sender);
57 
58         goto send_msg_to_ta;
59     }
60 
61     return;
62 
63 send_msg_to_ta:
64         /* when set caller info failed, a message should be sent to TA
65          * to prevent TA from being suspended */
66         cmd_oper = ssa_find_cmd(cmd);
67         if (cmd_oper != NULL && cmd_oper->need_ack == 1) {
68             rsp.ret = TEE_ERROR_MSG_QUEUE_OVERFLOW;
69             TEE_Result ret_ack = (uint32_t)ipc_msg_snd(cmd, sndr, (void *)&rsp, sizeof(rsp));
70             if (ret_ack != SRE_OK)
71                 tloge("msg snd error %x\n", ret_ack);
72         }
73 }
ssa_not_file_operate(uint32_t cmd,uint8_t * msg,uint32_t sndr)74 static TEE_Result ssa_not_file_operate(uint32_t cmd, uint8_t *msg, uint32_t sndr)
75 {
76     uint32_t need_ack;
77     uint32_t res_code;
78     ssa_cmd_t *cmd_oper = NULL;
79     struct ssa_agent_rsp rsp   = { 0 };
80 
81     tlogd("ssa_not_file_operate, cmd=%x", cmd);
82 
83     cmd_oper = ssa_find_cmd(cmd);
84     if (cmd_oper == NULL) {
85         tloge("ssa_find_cmd failed : %x , from %x\n", cmd, sndr);
86         return TEE_ERROR_GENERIC;
87     }
88 
89     if (cmd_oper->is_file_oper != NOT_FILE_OPERATION) {
90         tlogd("cmd is file operate: %x , from %x\n", cmd, sndr);
91         return TEE_ERROR_GENERIC;
92     }
93 
94     rsp.ret  = TEE_ERROR_GENERIC;
95     need_ack = cmd_oper->need_ack;
96     if (cmd_oper->fn != NULL) {
97         cmd_oper->fn((union ssa_agent_msg *)msg, sndr, &rsp);
98     } else {
99         tlogw("no process func for cmd %x, from %x", cmd, sndr);
100     }
101 
102     if (need_ack) {
103         tlogd("send msg to %x\n", sndr);
104         res_code = (uint32_t)ipc_msg_snd(cmd, sndr, (void *)&rsp, sizeof(struct ssa_agent_rsp));
105         if (res_code != SRE_OK)
106             tlogw("msg snd error %x\n", res_code);
107     }
108 
109     return TEE_SUCCESS;
110 }
ssa_deal_msg(uint32_t cmd,uint8_t * ret_msg,size_t msg_len,uint32_t sdr)111 static void ssa_deal_msg(uint32_t cmd, uint8_t *ret_msg, size_t msg_len, uint32_t sdr)
112 {
113     union ssa_agent_msg tmp_msg;
114     errno_t rc;
115 
116     (void)memset_s(&tmp_msg, sizeof(tmp_msg), 0, sizeof(tmp_msg));
117     if (cmd == TEE_TASK_OPEN_TA_SESSION) {
118         rc = memcpy_s(&tmp_msg, sizeof(tmp_msg), ret_msg, msg_len);
119         if (rc != EOK) {
120             tloge("memcpy_s ssa msg failed, ret 0x%x\n", rc);
121             return;
122         }
123 
124         tlogd("register task: %x-%x\n", tmp_msg.reg.taskid, tmp_msg.reg.uuid.timeLow);
125         ssa_register_uuid(&tmp_msg, sdr, NULL);
126 
127         return;
128     } else if (cmd == TEE_TASK_CLOSE_TA_SESSION) {
129         rc = memcpy_s(&tmp_msg, sizeof(tmp_msg), ret_msg, msg_len);
130         if (rc != EOK) {
131             tloge("memcpy_s ssa msg failed, ret 0x%x\n", rc);
132             return;
133         }
134         if (pre_unregister_uuid(&tmp_msg, sdr) == 0) {
135             return; /* not mark as dead, has been remove the client directly. */
136         } else {
137             /* mark as dead, so need add msg to the queue */
138         }
139     } else {
140         if (ssa_not_file_operate(cmd, ret_msg, sdr) == TEE_SUCCESS)
141             return;
142     }
143 
144     if (!is_client_register(sdr)) {
145         tloge("client is not registered, taskid:0x%x", sdr);
146         return;
147     }
148 
149     ssa_msgqueue_add(cmd, (const union ssa_agent_msg *)ret_msg, sdr);
150 }
151 
ssa_receive_msg(uint32_t uw_timeout,uint32_t * puw_msg_id,void * msgp,uint16_t size,uint32_t * puw_sender_pid)152 static uint32_t ssa_receive_msg(uint32_t uw_timeout, uint32_t *puw_msg_id, void *msgp,
153                                 uint16_t size, uint32_t *puw_sender_pid)
154 {
155     return (uint32_t)ipc_msg_rcv_a(uw_timeout, puw_msg_id, msgp, size, puw_sender_pid);
156 }
157 
158 /* globaltask and TA's msgs will go here when SSA wait REE agent.
159  * 1. globaltask's msg which can goes here are either null msg, or send with struct union ssa_agent_msg.
160  * 2. TA's msgs are all use union ssa_agent_msg.
161  * 3. globaltask's msgs which use struct global_to_ta_msg are processed in ssa_obtain_agent_work_lock
162  *    and ssa_agent_work_unlock, that means 'struct global_to_ta_msg' will never be used in this function.
163  */
ssa_wait_msg(uint32_t want_cmd,uint8_t * msg,uint32_t size,uint32_t want_sdr)164 static void ssa_wait_msg(uint32_t want_cmd, uint8_t *msg, uint32_t size, uint32_t want_sdr)
165 {
166     uint32_t cmd;
167     uint32_t sdr;
168     uint32_t ret;
169     uint32_t cp_size;
170     uint8_t ret_msg[sizeof(union ssa_agent_msg)];
171     errno_t rc;
172 
173     while (1) {
174         cmd = 0;
175         sdr = 0;
176         rc  = memset_s((void *)ret_msg, sizeof(union ssa_agent_msg), 0, sizeof(union ssa_agent_msg));
177         if (rc != EOK)
178             tloge("memset ret_msg failed %x\n", rc);
179 
180         ret = ssa_receive_msg(OS_WAIT_FOREVER, (UINT32 *)(&cmd), (void *)ret_msg, sizeof(union ssa_agent_msg), &sdr);
181         if (ret != SRE_OK) {
182             tloge("ssa msg rcv error %x\n", ret);
183             continue;
184         }
185 
186         tlogd("got msg %x from %x\n", cmd, sdr);
187 
188         if (want_cmd == cmd && want_sdr == sdr) {
189             if (msg == NULL)
190                 break;
191 
192             cp_size = (size < sizeof(union ssa_agent_msg)) ? size : sizeof(union ssa_agent_msg);
193             rc      = memmove_s(msg, size, ret_msg, cp_size);
194             if (rc != EOK)
195                 tloge("memmove ssa msg, size %u error, ret %x\n", cp_size, rc);
196 
197             break;
198         }
199 
200         ssa_deal_msg(cmd, ret_msg, sizeof(union ssa_agent_msg), sdr);
201     }
202 
203     return;
204 }
205 
ssa_send_agent_cmd(uint32_t id,uint32_t cmd,uint32_t * cmd_buff)206 void ssa_send_agent_cmd(uint32_t id, uint32_t cmd, uint32_t *cmd_buff)
207 {
208     struct ta_to_global_msg send_msg;
209     errno_t rc;
210     uint32_t ret;
211 
212     if (cmd_buff != NULL)
213         *cmd_buff = cmd;
214 
215     rc = memset_s((void *)&send_msg, sizeof(send_msg), 0, sizeof(send_msg));
216     if (rc != EOK) {
217         tloge("memset send_msg failed %x\n", rc);
218         return;
219     }
220 
221     send_msg.ret             = TEE_PENDING2;
222     send_msg.agent_id        = id;
223     send_msg.session_context = (void *)NULL;
224 
225     __asm__ volatile("isb");
226     __asm__ volatile("dsb sy");
227 
228     ret = ipc_msg_snd(TEE_TASK_AGENT_SMC_CMD, get_global_handle(), &send_msg, sizeof(send_msg));
229     if (ret != SRE_OK) {
230         tloge("msg snd error %x\n", ret);
231         return;
232     }
233 
234     tlogd("ready to wait for rsp from nwd\n");
235 
236     /* no need to verify return value here */
237     ssa_wait_msg(TEE_TASK_AGENT_SMC_ACK, NULL, 0, get_global_handle());
238 }
239 
ssa_agent_lock_handler(uint32_t id,uint32_t lock_type)240 static void ssa_agent_lock_handler(uint32_t id, uint32_t lock_type)
241 {
242     struct ta_to_global_msg send_msg;
243     struct global_to_ta_msg ret_msg;
244     errno_t rc;
245     uint32_t i, ret;
246     uint8_t *ret_data = NULL;
247 
248     rc = memset_s((void *)&send_msg, sizeof(send_msg), 0, sizeof(send_msg));
249     if (rc != EOK) {
250         tloge("memset failed %x\n", rc);
251         return;
252     }
253 
254     send_msg.ret             = TEE_PENDING2;
255     send_msg.agent_id        = id;
256     send_msg.session_context = NULL;
257     /* Ask global task to lock the agent for us till the next invoke */
258     ret = (uint32_t)ipc_msg_snd(lock_type, get_global_handle(), &send_msg, sizeof(send_msg));
259     if (ret != SRE_OK) {
260         tloge("msg snd error %x\n", ret);
261         return;
262     }
263     /* Some form of error .... */
264     tlogd("ready to wait for locking agent\n");
265 
266     do {
267         rc = memset_s((void *)&ret_msg, sizeof(ret_msg), 0, sizeof(ret_msg));
268         if (rc != EOK)
269             tlogw("memset fail");
270 
271         ssa_wait_msg(TA_LOCK_ACK, (uint8_t *)&ret_msg, sizeof(ret_msg), get_global_handle());
272         /* Couldn't get lock... */
273         if (ret_msg.cmd_id != TEE_AGENT_LOCK) {
274             tloge("ssa get agent lock exception:msg %x, cmd 0x%x, sender 0x%x\n", TA_LOCK_ACK, ret_msg.cmd_id,
275                   get_global_handle());
276 
277             ret_data = (uint8_t *)(&ret_msg);
278             for (i = 0; i < sizeof(ret_msg); i++)
279                 tloge("msg get from gtask is ret_data[%u] = 0x%x\n", i, ret_data[i]);
280 
281             continue; /* rcv the ta_lock agent ack msg */
282         }
283 
284         break;
285     } while (1);
286 
287     return;
288 }
289 
ssa_obtain_agent_work_lock(uint32_t id)290 void ssa_obtain_agent_work_lock(uint32_t id)
291 {
292     ssa_agent_lock_handler(id, TA_LOCK_AGENT);
293 }
294 
295 /* In many cases we know when the agent can be unlocked so make sure to allow other tasks
296  * to use the agent ASAP */
ssa_agent_work_unlock(uint32_t id)297 void ssa_agent_work_unlock(uint32_t id)
298 {
299     ssa_agent_lock_handler(id, TA_UNLOCK_AGENT);
300 }
301 
ssa_get_msg(uint32_t * cmd,uint8_t * msg,uint32_t size,uint32_t * sender)302 TEE_Result ssa_get_msg(uint32_t *cmd, uint8_t *msg, uint32_t size, uint32_t *sender)
303 {
304     uint32_t cp_size;
305     uint8_t buf[sizeof(union ssa_agent_msg)];
306     errno_t rc;
307     uint32_t out = g_ssa_msg_queue.out;
308 
309     tlogd("start to get msg  %u %u\n", g_ssa_msg_queue.in, g_ssa_msg_queue.out);
310 
311     if (sender == NULL || cmd == NULL || msg == NULL)
312         return TEE_ERROR_BAD_PARAMETERS;
313 
314     /* check if there are queued messages */
315     if (g_ssa_msg_queue.msg[out].msg_id != 0xFFFFFFFF) {
316         /* if there are, read them first */
317         tlogd("get msg %x from SSqueue[%u]\n", g_ssa_msg_queue.msg[out].msg_id, out);
318         *cmd    = g_ssa_msg_queue.msg[out].msg_id;
319         *sender = g_ssa_msg_queue.msg[out].sender;
320 
321         cp_size = (size < sizeof(union ssa_agent_msg)) ? size : sizeof(union ssa_agent_msg);
322 
323         rc = memmove_s((void *)msg, size, (void *)(&g_ssa_msg_queue.msg[out].msg), cp_size);
324         if (rc != EOK)
325             return TEE_ERROR_SECURITY;
326 
327         g_ssa_msg_queue.msg[out].msg_id = (uint32_t)0xFFFFFFFF;
328         if (++out >= SS_AGENT_MSG_QUEUE_SIZE)
329             out = 0;
330 
331         g_ssa_msg_queue.out = out;
332         return TEE_SUCCESS;
333     }
334 
335     do {
336         rc = memset_s((void *)buf, sizeof(union ssa_agent_msg), 0, sizeof(union ssa_agent_msg));
337         if (rc != EOK)
338             tlogw("memset failed %x\n", rc);
339 
340         uint32_t ret =
341             (uint32_t)ipc_msg_rcv_a(OS_WAIT_FOREVER, (UINT32 *)(cmd), (void *)buf, sizeof(union ssa_agent_msg), sender);
342         if (ret != SRE_OK) {
343             tloge("ssa msg rcv error %x\n", ret);
344             continue;
345         }
346         tlogd("got msg %x from %x\n", *cmd, *sender);
347 
348         cp_size = (size < sizeof(buf)) ? size : sizeof(buf);
349         rc      = memmove_s(msg, size, buf, cp_size);
350         if (rc != EOK)
351             continue;
352 
353         break;
354     } while (1);
355 
356     return TEE_SUCCESS;
357 }
358 
set_caller_info_proc(uint32_t task_id,uint32_t cmd)359 TEE_Result set_caller_info_proc(uint32_t task_id, uint32_t cmd)
360 {
361     uint32_t ret;
362     struct task_caller_info caller_proc_info;
363     ssa_cmd_t *cmd_oper = NULL;
364     uint8_t ret_msg[sizeof(union ssa_agent_msg)];
365     struct ssa_agent_rsp rsp;
366 
367     caller_proc_info.taskid = task_id;
368     caller_proc_info.cmd = cmd;
369     ret = ipc_msg_snd(TEE_TASK_SET_CALLER_INFO, get_global_handle(), &caller_proc_info, sizeof(caller_proc_info));
370     if (ret != SRE_OK) {
371         tloge("ssa send caller info failed 0x%x\n", ret);
372         goto send_msg_to_ta;
373     } else {
374         (void)ssa_wait_msg(TEE_TASK_SET_CALLER_INFO_ACK, ret_msg, sizeof(ret_msg), get_global_handle());
375         if (((union ssa_agent_msg *)ret_msg)->ret != TEE_SUCCESS) {
376             tloge("set callerinfo fail, recv_ret:0x%x", ((union ssa_agent_msg *)ret_msg)->ret);
377             goto send_msg_to_ta;
378         }
379     }
380 
381     return TEE_SUCCESS;
382 
383 send_msg_to_ta:
384     /* when set caller info failed, a message should be sent to TA
385      * to prevent TA from being suspended */
386     cmd_oper = ssa_find_cmd(cmd);
387     if (cmd_oper != NULL && cmd_oper->need_ack == 1) {
388         rsp.ret = TEE_ERROR_GENERIC;
389         ret = (uint32_t)ipc_msg_snd(cmd, task_id, (void *)&rsp, sizeof(rsp));
390         if (ret != SRE_OK)
391             tloge("msg snd error %x\n", ret);
392     }
393     return TEE_ERROR_COMMUNICATION;
394 }
395 
396