• 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 <ipclib.h>
13 #include <ipclib_hal.h>
14 #include <tee_log.h>
15 #include <securec.h>
16 
17 #define MSG_MAX_LEN     512 /* same as GT_MSG_REV_SIZE */
18 #define GLOBAL_HANDLE     0 /* defined in tee_init.h */
19 #define GLOBAL_SERVICE_NAME "TEEGlobalTask"
20 
21 struct msg_st {
22     uint32_t msg_id;
23     char payload[MSG_MAX_LEN];
24 } __attribute__((__packed__));
25 
26 struct msgsent_st {
27     cref_t dst_ch;
28     uint32_t uw_msg_id;
29     taskid_t uw_dst_pid;
30     const void *msgp;
31     uint16_t size;
32 } __attribute__((__packed__));
33 
34 struct msgrcv_st {
35     cref_t ch;
36     cref_t timer;
37     int32_t timeout;
38     uint32_t *puw_msg_id;
39     void *msgp;
40     uint16_t size;
41     taskid_t *puw_sender_pid;
42 } __attribute__((__packed__));
43 
44 struct notify_st {
45     uint32_t msg_id;
46     char payload[NOTIFY_MAX_LEN];
47 } __attribute__((__packed__));
48 
49 struct reply_msg_st {
50     uint32_t status;
51 } __attribute__((__packed__));
52 
53 static taskid_t g_handle = SRE_PID_ERR;
global_handle_check(taskid_t * puw_dst_pid)54 static int32_t global_handle_check(taskid_t *puw_dst_pid)
55 {
56     if (puw_dst_pid == NULL)
57         return -EINVAL;
58 
59     if (*puw_dst_pid == GLOBAL_HANDLE) {
60         if (g_handle == SRE_PID_ERR) {
61             if (ipc_hunt_by_name(GLOBAL_SERVICE_NAME, &g_handle) != 0)
62                 return -1;
63         }
64         *puw_dst_pid = g_handle;
65     }
66     return 0;
67 }
68 
ipc_create_single_channel(const char * name,cref_t * pch,bool reg_pid,bool reg_name,bool reg_tamgr)69 int32_t ipc_create_single_channel(const char *name, cref_t *pch, bool reg_pid, bool reg_name, bool reg_tamgr)
70 {
71     struct reg_items_st reg_items;
72     reg_items.reg_pid   = reg_pid;
73     reg_items.reg_name  = reg_name;
74     reg_items.reg_tamgr = reg_tamgr;
75     return ipc_create_channel(name, 1, &pch, reg_items);
76 }
77 
ipc_create_channel_native(const char * name,cref_t * pch)78 int32_t ipc_create_channel_native(const char *name, cref_t *pch)
79 {
80     return ipc_create_single_channel(name, pch, false, true, false);
81 }
82 
ipc_msgsnd_core(struct msgsent_st msgsent)83 static uint32_t ipc_msgsnd_core(struct msgsent_st msgsent)
84 {
85     int32_t rc    = 0;
86     struct msg_st msg = { 0 };
87 
88     msg.msg_id = msgsent.uw_msg_id;
89 
90     if (msgsent.msgp != NULL) {
91         if (memcpy_s(msg.payload, sizeof(msg.payload), msgsent.msgp, msgsent.size) != 0)
92             return SRE_IPC_ERR;
93     }
94 
95     if (msgsent.size <= NOTIFY_MAX_LEN) {
96         struct notify_st *ntf_p = (struct notify_st *)&msg;
97         rc                         = ipc_msg_notification(msgsent.dst_ch, ntf_p, sizeof(struct notify_st));
98     } else {
99         tloge("msg_call failed, not support big msg in ipc_msg_snd/ipc_msg_qsnd, size = %u\n", msgsent.size);
100         return SRE_IPC_ERR;
101     }
102 
103     if (rc != 0) {
104         tloge("notify failed to 0x%x, size=%u, ret=%d\n", msg.msg_id, msgsent.size, rc);
105         return SRE_IPC_ERR;
106     }
107 
108     return 0;
109 }
110 
ipc_msgsnd_core_sync(struct msgsent_st msgsent)111 static uint32_t ipc_msgsnd_core_sync(struct msgsent_st msgsent)
112 {
113     int32_t rc;
114     struct msg_st msg     = { 0 };
115     struct reply_msg_st rmsg = { 0 };
116 
117     msg.msg_id = msgsent.uw_msg_id;
118 
119     if (msgsent.msgp != NULL) {
120         if (memcpy_s(msg.payload, sizeof(msg.payload), msgsent.msgp, msgsent.size) != 0)
121             return SRE_IPC_ERR;
122     }
123 
124     rc = ipc_msg_call(msgsent.dst_ch, &msg, sizeof(msg), &rmsg, sizeof(rmsg), -1);
125     if (rc != 0) {
126         tloge("msg_call to 0x%x failed, rc = %d\n", msgsent.uw_dst_pid, rc);
127         return SRE_IPC_ERR;
128     }
129 
130     return 0;
131 }
132 
ipc_msg_snd(uint32_t uw_msg_id,taskid_t uw_dst_pid,const void * msgp,uint16_t size)133 uint32_t ipc_msg_snd(uint32_t uw_msg_id, taskid_t uw_dst_pid, const void *msgp, uint16_t size)
134 {
135     cref_t dst_ch;
136     struct msgsent_st msgsent;
137     int32_t rc;
138     tlogd("MsgSend Start to 0x%x msgid = 0x%lx size = %u\n", uw_dst_pid, uw_msg_id, size);
139 
140     if (size > MSG_MAX_LEN) {
141         tloge("msg too long!\n");
142         return SRE_IPC_ERR;
143     }
144 
145     if (global_handle_check(&uw_dst_pid) != 0) {
146         tloge("check uwDstPID against global handle failed\n");
147     }
148 
149     rc =  ipc_get_ch_from_taskid(uw_dst_pid, 0, &dst_ch);
150     if (rc != 0) {
151         tloge("Cannot get dest channel, MsgSnd abort to 0x%x\n", uw_dst_pid);
152         return SRE_IPC_ERR;
153     }
154 
155     msgsent.dst_ch     = dst_ch;
156     msgsent.uw_msg_id  = uw_msg_id;
157     msgsent.uw_dst_pid = uw_dst_pid;
158     msgsent.msgp       = msgp;
159     msgsent.size       = size;
160     return ipc_msgsnd_core(msgsent);
161 }
162 
ipc_send_msg_sync(uint32_t msg_id,taskid_t dest_pid,const void * msgp,uint32_t size)163 uint32_t ipc_send_msg_sync(uint32_t msg_id, taskid_t dest_pid, const void *msgp, uint32_t size)
164 {
165     cref_t dst_ch;
166     struct msgsent_st msgsent;
167     int32_t rc;
168 
169     if (global_handle_check(&dest_pid) != 0) {
170         tloge("check uwDstPID against global handle failed\n");
171     }
172 
173     rc = ipc_get_ch_from_taskid(dest_pid, 0, &dst_ch);
174     if (rc != 0) {
175         tloge("Cannot get dest channel of pid(0x%x)\n", dest_pid);
176         return SRE_IPC_ERR;
177     }
178 
179     msgsent.dst_ch     = dst_ch;
180     msgsent.uw_msg_id  = msg_id;
181     msgsent.uw_dst_pid = dest_pid;
182     msgsent.msgp       = msgp;
183     msgsent.size       = size;
184     return ipc_msgsnd_core_sync(msgsent);
185 }
186 
ipc_msg_rcv(uint32_t uw_timeout,uint32_t * puw_msg_id,void * msgp,uint16_t size)187 uint32_t ipc_msg_rcv(uint32_t uw_timeout, uint32_t *puw_msg_id, void *msgp, uint16_t size)
188 {
189     taskid_t sender_pid;
190     return ipc_msg_rcv_a(uw_timeout, puw_msg_id, msgp, size, &sender_pid);
191 }
192 
ipc_msg_rcv_safe(uint32_t uw_timeout,uint32_t * puw_msg_id,void * msgp,uint16_t size,taskid_t wait_sender)193 uint32_t ipc_msg_rcv_safe(uint32_t uw_timeout, uint32_t *puw_msg_id, void *msgp, uint16_t size, taskid_t wait_sender)
194 {
195     taskid_t sender = SRE_PID_ERR;
196     uint32_t ret     = 0;
197 
198     while (wait_sender != sender) {
199         ret = ipc_msg_rcv_a(uw_timeout, puw_msg_id, msgp, (uint16_t)(size), &sender);
200         if (ret != 0) {
201             tloge("ipc msg Rcv failed, ret = 0x%x\n", ret);
202             return ret;
203         }
204 
205         if (wait_sender != sender)
206             tloge("recv msg from wrong sender %u/%u\n", sender, wait_sender);
207     }
208 
209     return ret;
210 }
211 
ipc_msgrcv_core(struct msgrcv_st msgrcv)212 static uint32_t ipc_msgrcv_core(struct msgrcv_st msgrcv)
213 {
214     struct msg_st msg;
215     struct reply_msg_st rmsg;
216     struct src_msginfo info = { 0 };
217     int32_t msg_ret;
218 
219     /* ipc_msg_receive would handle wrong msg_hdl */
220     cref_t msg_hdl = ipc_get_my_msghdl();
221 
222     msg_ret = ipc_msg_receive(msgrcv.ch, &msg, sizeof(msg), msg_hdl, &info, msgrcv.timeout);
223     if (msg_ret != 0) {
224         tloge("receive msg failed: %x\n", msg_ret);
225         return msg_ret == E_EX_TIMER_TIMEOUT ? SRE_IPC_TIMEOUT_ERR : SRE_IPC_ERR;
226     }
227 
228     if (msgrcv.puw_msg_id != NULL)
229         *(msgrcv.puw_msg_id) = msg.msg_id;
230     if (msgrcv.puw_sender_pid != NULL) {
231         if (info.src_pid == GLOBAL_HANDLE)
232             *(msgrcv.puw_sender_pid) = GLOBAL_HANDLE;
233         else
234             *(msgrcv.puw_sender_pid) = (uint32_t)pid_to_taskid(info.src_tid, info.src_pid);
235     }
236     if (msgrcv.msgp != NULL) {
237         if (memcpy_s(msgrcv.msgp, msgrcv.size, msg.payload,
238                      msgrcv.size < MSG_MAX_LEN ? msgrcv.size : MSG_MAX_LEN) != EOK) {
239             tloge("memcpy_s failed\n");
240             return SRE_IPC_ERR;
241         }
242     }
243 
244     if (info.msg_type == MSG_TYPE_CALL) {
245         int32_t rc  = ipc_msg_reply(msg_hdl, &rmsg, sizeof(rmsg));
246         if (rc < 0) {
247             tloge("reply msg error %d\n", rc);
248             return SRE_IPC_ERR;
249         }
250     } else if (info.msg_type == MSG_TYPE_NOTIF) {
251         tlogd("Notification received, DONOT need to reply ch = 0x%llx\n", msg_hdl);
252     } else {
253         tloge("Unexpected msg_recv %u\n", info.msg_type);
254         return SRE_IPC_ERR;
255     }
256 
257     return 0;
258 }
259 
ipc_msg_rcv_a(uint32_t uw_timeout,uint32_t * puw_msg_id,void * msgp,uint16_t size,taskid_t * puw_sender_pid)260 uint32_t ipc_msg_rcv_a(uint32_t uw_timeout, uint32_t *puw_msg_id, void *msgp, uint16_t size, taskid_t *puw_sender_pid)
261 {
262     cref_t ch;
263     uint32_t ret;
264     struct msgrcv_st msgrcv;
265     if (size > MSG_MAX_LEN) {
266         tloge(" msg too long!\n");
267         return SRE_IPC_ERR;
268     }
269 
270     ret = ipc_get_my_channel(0, &ch);
271     if (ret != 0) {
272         tloge("Cannot recv, channel haven't been created yet\n");
273         return SRE_IPC_NO_CHANNEL_ERR;
274     }
275 
276     msgrcv.ch             = ch;
277     msgrcv.timeout        = (int32_t)uw_timeout;
278     msgrcv.puw_msg_id     = puw_msg_id;
279     msgrcv.msgp           = msgp;
280     msgrcv.size           = size;
281     msgrcv.puw_sender_pid = puw_sender_pid;
282     ret = ipc_msgrcv_core(msgrcv);
283 
284     tlogd("MsgRcv OK: 0x%x <- 0x%x msgid = 0x%x, size = %u\n", get_self_taskid(), puw_sender_pid ? *puw_sender_pid : 0,
285              puw_msg_id ? *puw_msg_id : DEAD_MSG_ID, (uint32_t)size);
286 
287     return ret;
288 }
289 
ipc_msg_qsend(uint32_t uw_msg_id,taskid_t uw_dst_pid,uint8_t uc_dst_qid)290 uint32_t ipc_msg_qsend(uint32_t uw_msg_id, taskid_t uw_dst_pid, uint8_t uc_dst_qid)
291 {
292     cref_t dst_ch;
293     struct msgsent_st msgsent;
294     int32_t rc;
295     tlogd("MsgQSend to 0x%x ch = %u\n", uw_dst_pid, uc_dst_qid);
296 
297     if (uc_dst_qid >= CH_CNT_MAX) {
298         tloge("Send channel Number overflow: %u\n", uc_dst_qid);
299         return SRE_IPC_ERR;
300     }
301 
302     if (global_handle_check(&uw_dst_pid) != 0) {
303         tloge("check uwDstPID against global handle failed\n");
304     }
305 
306     rc = ipc_get_ch_from_taskid(uw_dst_pid, uc_dst_qid, &dst_ch);
307     if (rc != 0) {
308         tloge("Cannot get dest channel, MsgSnd abort to 0x%x\n", uw_dst_pid);
309         return SRE_IPC_ERR;
310     }
311     msgsent.dst_ch     = dst_ch;
312     msgsent.uw_msg_id  = uw_msg_id;
313     msgsent.uw_dst_pid = uw_dst_pid;
314     msgsent.msgp       = NULL;
315     msgsent.size       = 0;
316     return ipc_msgsnd_core(msgsent);
317 }
318 
ipc_msg_q_recv(uint32_t * puw_msg_id,taskid_t * puw_sender_pid,uint8_t uc_recv_qid,uint32_t uw_timeout)319 uint32_t ipc_msg_q_recv(uint32_t *puw_msg_id, taskid_t *puw_sender_pid,
320                         uint8_t uc_recv_qid, uint32_t uw_timeout)
321 {
322     cref_t ch;
323     uint32_t ret;
324     struct msgrcv_st msgrcv;
325     if (uc_recv_qid >= CH_CNT_MAX) {
326         tloge("Recv channel Number overflow: %d\n", uc_recv_qid);
327         return SRE_IPC_ERR;
328     }
329 
330     ret = ipc_get_my_channel(uc_recv_qid, &ch);
331     if (ret != 0) {
332         tloge("Cannot recv, channel haven't been created yet\n");
333         return SRE_IPC_NO_CHANNEL_ERR;
334     }
335 
336     msgrcv.ch             = ch;
337     msgrcv.timeout        = (int32_t)uw_timeout;
338     msgrcv.puw_msg_id     = puw_msg_id;
339     msgrcv.msgp           = NULL;
340     msgrcv.size           = 0;
341     msgrcv.puw_sender_pid = puw_sender_pid;
342     ret = ipc_msgrcv_core(msgrcv);
343 
344     tlogd("MsgQRcv OK: 0x%x <- 0x%x msgid = 0x%x\n", get_self_taskid(), puw_sender_pid ? *puw_sender_pid : 0,
345              puw_msg_id ? *puw_msg_id : DEAD_MSG_ID);
346 
347     return ret;
348 }
349