1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "tzdebug.h"
33 #include <securec.h>
34 #include <stdarg.h>
35 #include "cmdmonitor.h"
36 #include "mailbox_mempool.h"
37 #include "smc.h"
38 #include "tc_client_sub_driver.h"
39 #include "tc_ns_log.h"
40 #include "teek_client_api.h"
41 #include "teek_client_constants.h"
42 #include "teek_ns_client.h"
43 #include "tzdriver_compat.h"
44
45 typedef void (*TzdebugOptFunc)(const char *param);
46
47 struct OptOps {
48 char *name;
49 TzdebugOptFunc func;
50 };
51
52 static DEFINE_MUTEX(g_meminfoLock);
53 static struct TeeMem g_teeMeminfo = {0};
54 static int SendDumpMem(int flag, const struct TeeMem *statmem);
55 static void TzMemDump(const char *param);
56
TeeDumpMem(void)57 void TeeDumpMem(void)
58 {
59 TzMemDump(NULL);
60 }
61
62 /* get meminfo (TeeMem + N * ta_mem < 4Kbyte) from tee */
GetTeeMemInfoCmd(void)63 static int GetTeeMemInfoCmd(void)
64 {
65 int ret;
66 int sret;
67 struct TeeMem *mem = (struct TeeMem *)MailboxAlloc(sizeof(*mem), MB_FLAG_ZERO);
68
69 if (mem == NULL) {
70 return -1;
71 }
72 ret = SendDumpMem(0, mem);
73 mutex_lock(&g_meminfoLock);
74 sret = memcpy_s((void *)&g_teeMeminfo, sizeof(g_teeMeminfo), mem, sizeof(*mem));
75 if (sret != EOK) {
76 tloge("sret=%d\n", sret);
77 }
78 mutex_unlock(&g_meminfoLock);
79 MailboxFree(mem);
80 return ret;
81 }
82
83 static atomic_t g_cmdSend = ATOMIC_INIT(1);
84
SetCmdSendState(void)85 void SetCmdSendState(void)
86 {
87 atomic_set(&g_cmdSend, 1);
88 }
89
GetTeeMeminfo(struct TeeMem * meminfo)90 int GetTeeMeminfo(struct TeeMem *meminfo)
91 {
92 errno_t ret;
93
94 if (meminfo == NULL) {
95 return -1;
96 }
97 if (atomic_read(&g_cmdSend)) {
98 if (GetTeeMemInfoCmd() != 0) {
99 return -1;
100 }
101 } else {
102 atomic_set(&g_cmdSend, 0);
103 }
104 mutex_lock(&g_meminfoLock);
105 ret = memcpy_s((void *)meminfo, sizeof(*meminfo),
106 (void *)&g_teeMeminfo, sizeof(g_teeMeminfo));
107 mutex_unlock(&g_meminfoLock);
108 if (ret != EOK) {
109 return -1;
110 }
111
112 return 0;
113 }
114 EXPORT_SYMBOL(GetTeeMeminfo);
115
SendDumpMem(int flag,const struct TeeMem * statmem)116 static int SendDumpMem(int flag, const struct TeeMem *statmem)
117 {
118 TcNsSmcCmd smcCmd = { {0}, 0 };
119 struct MbCmdPack *mbPack = NULL;
120 int ret;
121
122 if (statmem == NULL) {
123 tloge("statmem is NULL\n");
124 return -1;
125 }
126 mbPack = MailboxAllocCmdPack();
127 if (mbPack == NULL) {
128 return -ENOMEM;
129 }
130 smcCmd.cmdId = GLOBAL_CMD_ID_DUMP_MEMINFO;
131 smcCmd.globalCmd = true;
132 mbPack->operation.paramTypes = TEEC_PARAM_TYPES(
133 TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_INPUT,
134 TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE);
135 mbPack->operation.params[TEE_PARAM_ONE].memref.buffer = LOS_PaddrQuery((void *)statmem);
136 mbPack->operation.params[TEE_PARAM_ONE].memref.size = sizeof(*statmem);
137 mbPack->operation.bufferHaddr[TEE_PARAM_ONE] = 0;
138 mbPack->operation.params[TEE_PARAM_TWO].value.a = flag;
139 smcCmd.operationPhys =
140 (unsigned int)LOS_PaddrQuery(&mbPack->operation);
141 smcCmd.operationHphys = 0;
142 ret = TcNsSmc(&smcCmd);
143 if (ret) {
144 tloge("SendDumpMem failed.\n");
145 }
146 MailboxFree(mbPack);
147 return ret;
148 }
149
ArchiveLog(const char * param)150 static void ArchiveLog(const char *param)
151 {
152 (void)param;
153 TzDebugArchiveLog();
154 }
155
TzDump(const char * param)156 static void TzDump(const char *param)
157 {
158 (void)param;
159 ShowCmdBitmap();
160 WakeupTcSiq();
161 }
162
TzMemDump(const char * param)163 static void TzMemDump(const char *param)
164 {
165 struct TeeMem *mem = NULL;
166
167 (void)param;
168 mem = (struct TeeMem *)MailboxAlloc(sizeof(*mem), MB_FLAG_ZERO);
169 if (mem == NULL) {
170 tloge("mailbox alloc failed\n");
171 return;
172 }
173 if (SendDumpMem(1, mem) != 0) {
174 tloge("send dump mem failed\n");
175 }
176
177 MailboxFree(mem);
178 }
179
MemstatThread(UINTPTR arg,int len)180 static int MemstatThread(UINTPTR arg, int len)
181 {
182 (void)len;
183 (void)arg;
184 return 0;
185 }
186
TzMemStat(const char * param)187 static void TzMemStat(const char *param)
188 {
189 LosTaskCB *stat_tsk = NULL;
190 (void)param;
191 stat_tsk = KthreadRun(MemstatThread, NULL, 0, "tzmemstat");
192 if (IS_ERR(stat_tsk)) {
193 tloge("memstat failed\n");
194 }
195 }
196
TzLogWriteDbg(const char * param)197 static void TzLogWriteDbg(const char *param)
198 {
199 (void)param;
200 }
201
202 static void TzHelp(const char *param);
203
204 static struct OptOps g_optArr[] = {
205 {"help", TzHelp},
206 {"archivelog", ArchiveLog},
207 {"dump", TzDump},
208 {"memdump", TzMemDump},
209 {"logwrite", TzLogWriteDbg},
210 {"dump_service", DumpServicesStatus},
211 {"memstat", TzMemStat},
212 };
213
TzHelp(const char * param)214 static void TzHelp(const char *param)
215 {
216 uint32_t i;
217 (void)param;
218
219 for (i = 0; i < sizeof(g_optArr) / sizeof(struct OptOps); i++) {
220 tloge("cmd:%s\n", g_optArr[i].name);
221 }
222 }
223
TzDbgOptWrite(struct file * filp,const char __user * ubuf,size_t cnt)224 static ssize_t TzDbgOptWrite(struct file *filp,
225 const char __user *ubuf, size_t cnt)
226 {
227 char buf[128] = {0}; /* 128, size of copy from ubuf */
228 char *value = NULL;
229 char *p = NULL;
230 uint32_t i = 0;
231
232 if ((ubuf == NULL) || (filp == NULL)) {
233 return -EINVAL;
234 }
235
236 if (cnt >= sizeof(buf)) {
237 return -EINVAL;
238 }
239
240 if (cnt == 0) {
241 return -EINVAL;
242 }
243
244 if (copy_from_user(buf, ubuf, cnt)) {
245 return -EFAULT;
246 }
247 buf[cnt] = 0;
248 if (cnt > 0 && buf[cnt - 1] == '\n') {
249 buf[cnt - 1] = 0;
250 }
251 value = buf;
252 p = strsep(&value, ":");
253 if (p == NULL) {
254 return -EINVAL;
255 }
256 for (i = 0; i < sizeof(g_optArr) / sizeof(struct OptOps); i++) {
257 if (!strncmp(p, g_optArr[i].name, strlen(g_optArr[i].name)) &&
258 strlen(p) == strlen(g_optArr[i].name)) {
259 g_optArr[i].func(value);
260 return cnt;
261 }
262 }
263 return -EFAULT;
264 }
265
266 static const struct file_operations_vfs g_tzDbgOptFops = {
267 .write = TzDbgOptWrite,
268 };
269
270 #define TC_NS_CLIENT_TZDEBUG "/dev/tzdebug"
271
TzdebugInit(void)272 int TzdebugInit(void)
273 {
274 int ret = CreateTcClientDevice(TC_NS_CLIENT_TZDEBUG, &g_tzDbgOptFops);
275 if (ret != EOK) {
276 return ret;
277 }
278 return 0;
279 }
280