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 "drv_ipc_mgr.h"
13 #include <securec.h>
14 #include <tee_log.h>
15 #include <drv.h>
16 #include <tee_drv_internal.h>
17 #include "task_mgr.h"
18 #include <ipclib.h>
19
get_drv_param(const struct tee_drv_param * params,char ** param,uint32_t * len)20 static int32_t get_drv_param(const struct tee_drv_param *params, char **param, uint32_t *len)
21 {
22 uint64_t *args = (uint64_t *)(uintptr_t)params->args;
23 char *indata = (char *)(uintptr_t)(params->data);
24 uint64_t param_len = args[DRV_PARAM_LEN_INDEX];
25 uint64_t param_offset = args[DRV_PARAM_INDEX];
26
27 if (param_len == 0) {
28 tlogd("input null param\n");
29 *param = NULL;
30 *len = 0;
31 return 0;
32 }
33
34 if (param_len > (SYSCAL_MSG_BUFFER_SIZE - sizeof(struct drv_req_msg_t))) {
35 tloge("param_len:0x%llx is invalid\n", param_len);
36 return -1;
37 }
38
39 if (param_offset != 0) {
40 tloge("invalid param_offset:0x%llx\n", param_offset);
41 return -1;
42 }
43
44 if (indata == NULL) {
45 tloge("invalid param_indata\n");
46 return -1;
47 }
48
49 *param = indata;
50 *len = param_len;
51
52 return 0;
53 }
54
trans_uuid_to_ul(const struct tee_uuid * uuid,uint64_t * uuid_time,uint64_t * uuid_clock)55 static void trans_uuid_to_ul(const struct tee_uuid *uuid, uint64_t *uuid_time, uint64_t *uuid_clock)
56 {
57 uint64_t uuid_c = 0;
58
59 uint64_t uuid_t = uuid->timeLow;
60 uuid_t = (uuid_t << UUID_TIME_LOW_OFFSET) |
61 ((uint64_t)uuid->timeMid << UUID_TIME_MID_OFFSET) |
62 ((uint64_t)uuid->timeHiAndVersion);
63
64 uint32_t i;
65 for (i = 0; i < NODE_LEN; i++)
66 uuid_c = (uuid_c << BITS_NUM_PER_BYTE) | uuid->clockSeqAndNode[i];
67
68 *uuid_time = uuid_t;
69 *uuid_clock = uuid_c;
70
71 tlogd("tran uuid:0x%x uuid_time:0x%llx uuid_clock:0x%llx\n", uuid->timeLow, *uuid_time, *uuid_clock);
72 }
73
call_drv_open(const struct tee_drv_param * params,cref_t channel,uint64_t perm)74 static int64_t call_drv_open(const struct tee_drv_param *params, cref_t channel, uint64_t perm)
75 {
76 char buf[SYSCAL_MSG_BUFFER_SIZE] = { 0 };
77 struct drv_req_msg_t *msg = (struct drv_req_msg_t *)buf;
78 struct drv_reply_msg_t *rmsg = (struct drv_reply_msg_t *)buf;
79
80 uint32_t ext_data = SYSCAL_MSG_BUFFER_SIZE - sizeof(struct drv_req_msg_t);
81 char *param = NULL;
82 uint32_t param_len;
83
84 int32_t ret = get_drv_param(params, ¶m, ¶m_len);
85 if (ret != 0)
86 return -1;
87
88 msg->args[DRV_FRAM_CMD_INDEX] = CALL_DRV_OPEN;
89 msg->args[DRV_PARAM_INDEX] = 0; /* offset */
90 msg->args[DRV_PARAM_LEN_INDEX] = param_len; /* buffer len */
91 msg->args[DRV_PERM_INDEX] = perm;
92 msg->args[DRV_CALLER_PID_INDEX] = params->caller_pid;
93 trans_uuid_to_ul(¶ms->uuid, &msg->args[DRV_UUID_TIME_INDEX], &msg->args[DRV_UUID_CLOCK_INDEX]);
94
95 if (param != NULL && param_len != 0 && memcpy_s(msg->data, ext_data, param, param_len) != 0) {
96 tloge("copy param to data failed\n");
97 return -1;
98 }
99
100 msg->header.send.msg_id = 0;
101 msg->header.send.msg_size = sizeof(struct drv_req_msg_t) + param_len;
102
103 ret = ipc_msg_call(channel, msg, msg->header.send.msg_size, rmsg, SYSCAL_MSG_BUFFER_SIZE, DRV_IPC_MAX_TIMEOUT);
104 if (ret == E_EX_TIMER_TIMEOUT) {
105 tloge("open msg call open timeout:%u\n", DRV_IPC_MAX_TIMEOUT);
106 return -1;
107 }
108
109 if (ret != 0) {
110 tloge("open msg call fail ret:0x%x\n", ret);
111 return -1;
112 }
113
114 return rmsg->header.reply.ret_val;
115 }
116
drv_open_handle(const struct tee_drv_param * params,const struct task_node * node,uint64_t perm)117 int64_t drv_open_handle(const struct tee_drv_param *params, const struct task_node *node, uint64_t perm)
118 {
119 if (params == NULL || params->args == 0 || node == NULL) {
120 tloge("open invalid param\n");
121 return -1;
122 }
123
124 int64_t ret = call_drv_open(params, node->drv_task.channel, perm);
125 if (ret <= 0 || ret > FD_COUNT_MAX) {
126 tloge("call drv open fail ret:0x%llx\n", ret);
127 return -1;
128 }
129
130 return (int64_t)(((uint64_t)node->drv_task.drv_index << DRV_INDEX_OFFSET) | (uint64_t)ret);
131 }
132
call_drv_close(uint32_t taskid,const struct tee_uuid * caller_uuid,int64_t fd,cref_t channel)133 int64_t call_drv_close(uint32_t taskid, const struct tee_uuid *caller_uuid, int64_t fd, cref_t channel)
134 {
135 if (caller_uuid == NULL) {
136 tloge("invalid close uuid\n");
137 return -1;
138 }
139
140 if (fd < 0) {
141 tloge("close invalid fd\n");
142 return -1;
143 }
144
145 char buf[SYSCAL_MSG_BUFFER_SIZE] = { 0 };
146 struct drv_req_msg_t *msg = (struct drv_req_msg_t *)buf;
147 struct drv_reply_msg_t *rmsg = (struct drv_reply_msg_t *)buf;
148
149 msg->args[DRV_FRAM_CMD_INDEX] = CALL_DRV_CLOSE;
150 msg->args[DRV_CLOSE_FD_INDEX] = (uint64_t)fd;
151 msg->args[DRV_CALLER_PID_INDEX] = taskid;
152 trans_uuid_to_ul(caller_uuid, &msg->args[DRV_UUID_TIME_INDEX], &msg->args[DRV_UUID_CLOCK_INDEX]);
153
154 msg->header.send.msg_id = 0;
155 msg->header.send.msg_size = sizeof(struct drv_req_msg_t);
156
157 int32_t ret = ipc_msg_call(channel, msg, msg->header.send.msg_size, rmsg,
158 SYSCAL_MSG_BUFFER_SIZE, DRV_IPC_MAX_TIMEOUT);
159 if (ret == E_EX_TIMER_TIMEOUT) {
160 tloge("close msg call close timeout:%u\n", DRV_IPC_MAX_TIMEOUT);
161 return -1;
162 }
163
164 if (ret != 0) {
165 tloge("close msg call fail ret:0x%x\n", ret);
166 return -1;
167 }
168
169 return rmsg->header.reply.ret_val;
170 }
171
172 #ifdef TEE_SUPPORT_DRV_FD_DUMP
call_drv_dump(cref_t channel)173 void call_drv_dump(cref_t channel)
174 {
175 char buf[SYSCAL_MSG_BUFFER_SIZE] = { 0 };
176 struct drv_req_msg_t *msg = (struct drv_req_msg_t *)buf;
177 struct drv_reply_msg_t *rmsg = (struct drv_reply_msg_t *)buf;
178
179 msg->header.send.msg_id = DRV_DUMP_CMD_ID;
180 msg->header.send.msg_size = sizeof(struct drv_req_msg_t);
181
182 int32_t ret = ipc_msg_call(channel, msg, msg->header.send.msg_size, rmsg,
183 SYSCAL_MSG_BUFFER_SIZE, -1);
184 if (ret != 0)
185 tloge("dump msg call fail ret:0x%x\n", ret);
186 }
187 #endif
188