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