1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8 #include "platform_dumper.h"
9 #include "hdf_log.h"
10 #include "osal_io.h"
11 #include "osal_mem.h"
12 #include "osal_sem.h"
13 #include "securec.h"
14
15 struct DumperDataMgrNode {
16 struct PlatformDumperData data;
17 const char *printFormat;
18 void (*printFunc)(const struct DumperDataMgrNode *data);
19 struct DListHead node;
20 };
21
22 struct PlatformDumper {
23 const char *name;
24 struct DListHead dumperDatas;
25 OsalSpinlock spin;
26 struct PlatformDumperMethod *ops;
27 };
28
29 #define DUMPER_INFO_FILE_LEN 256
30 #ifdef __LITEOS__
31 #define DUMPER_PRINT(fmt, args...) dprintf(fmt, ##args)
32 #else
33 #define DUMPER_PRINT(fmt, args...) printk(fmt, ##args)
34 #endif
35
OutputDumperInfo(const char * info)36 static void OutputDumperInfo(const char *info)
37 {
38 HDF_LOGE("%s", info);
39 #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_DUMPER_PRINT) || defined(CONFIG_DRIVERS_HDF_PLATFORM_DUMPER_PRINT)
40 DUMPER_PRINT("%s\r\n", info);
41 #endif
42 }
43
DumperPrintUint8Info(const struct DumperDataMgrNode * data)44 static void DumperPrintUint8Info(const struct DumperDataMgrNode *data)
45 {
46 uint8_t *val = (uint8_t *)(data->data.paddr);
47 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
48 int ret =
49 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
50 if (ret > 0) {
51 OutputDumperInfo(info);
52 }
53 }
54
DumperPrintUint16Info(const struct DumperDataMgrNode * data)55 static void DumperPrintUint16Info(const struct DumperDataMgrNode *data)
56 {
57 uint16_t *val = (uint16_t *)(data->data.paddr);
58 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
59 int ret =
60 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
61 if (ret > 0) {
62 OutputDumperInfo(info);
63 }
64 }
65
DumperPrintUint32Info(const struct DumperDataMgrNode * data)66 static void DumperPrintUint32Info(const struct DumperDataMgrNode *data)
67 {
68 uint32_t *val = (uint32_t *)(data->data.paddr);
69 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
70 int ret =
71 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
72 if (ret > 0) {
73 OutputDumperInfo(info);
74 }
75 }
76
DumperPrintUint64Info(const struct DumperDataMgrNode * data)77 static void DumperPrintUint64Info(const struct DumperDataMgrNode *data)
78 {
79 uint64_t *val = (uint64_t *)(data->data.paddr);
80 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
81 int ret =
82 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
83 if (ret > 0) {
84 OutputDumperInfo(info);
85 }
86 }
87
DumperPrintInt8Info(const struct DumperDataMgrNode * data)88 static void DumperPrintInt8Info(const struct DumperDataMgrNode *data)
89 {
90 int8_t *val = (int8_t *)(data->data.paddr);
91 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
92 int ret =
93 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
94 if (ret > 0) {
95 OutputDumperInfo(info);
96 }
97 }
98
DumperPrintInt16Info(const struct DumperDataMgrNode * data)99 static void DumperPrintInt16Info(const struct DumperDataMgrNode *data)
100 {
101 int16_t *val = (int16_t *)(data->data.paddr);
102 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
103 int ret =
104 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
105 if (ret > 0) {
106 OutputDumperInfo(info);
107 }
108 }
109
DumperPrintInt32Info(const struct DumperDataMgrNode * data)110 static void DumperPrintInt32Info(const struct DumperDataMgrNode *data)
111 {
112 int32_t *val = (int32_t *)(data->data.paddr);
113 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
114 int ret =
115 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
116 if (ret > 0) {
117 OutputDumperInfo(info);
118 }
119 }
120
DumperPrintInt64Info(const struct DumperDataMgrNode * data)121 static void DumperPrintInt64Info(const struct DumperDataMgrNode *data)
122 {
123 int64_t *val = (int64_t *)(data->data.paddr);
124 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
125 int ret =
126 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
127 if (ret > 0) {
128 OutputDumperInfo(info);
129 }
130 }
131
DumperPrintFloatInfo(const struct DumperDataMgrNode * data)132 static void DumperPrintFloatInfo(const struct DumperDataMgrNode *data)
133 {
134 #ifdef __LITEOS__
135 float *val = (float *)(data->data.paddr);
136 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
137 int ret =
138 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
139 if (ret > 0) {
140 OutputDumperInfo(info);
141 }
142 #endif
143 }
144
DumperPrintDoubleInfo(const struct DumperDataMgrNode * data)145 static void DumperPrintDoubleInfo(const struct DumperDataMgrNode *data)
146 {
147 #ifdef __LITEOS__
148 double *val = (double *)(data->data.paddr);
149 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
150 int ret =
151 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
152 if (ret > 0) {
153 OutputDumperInfo(info);
154 }
155 #endif
156 }
157
DumperPrintCharInfo(const struct DumperDataMgrNode * data)158 static void DumperPrintCharInfo(const struct DumperDataMgrNode *data)
159 {
160 char *val = (char *)(data->data.paddr);
161 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
162
163 int ret =
164 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, *val);
165 if (ret > 0) {
166 OutputDumperInfo(info);
167 }
168 }
169
DumperPrintStringInfo(const struct DumperDataMgrNode * data)170 static void DumperPrintStringInfo(const struct DumperDataMgrNode *data)
171 {
172 char *val = (char *)(data->data.paddr);
173 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
174 int ret = snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat,
175 data->data.name, val);
176 if (ret > 0) {
177 OutputDumperInfo(info);
178 }
179 }
180
DumperPrintRegisterInfo(const struct DumperDataMgrNode * data)181 static void DumperPrintRegisterInfo(const struct DumperDataMgrNode *data)
182 {
183 unsigned long value;
184 volatile uint8_t *regAddr = (volatile uint8_t *)data->data.paddr;
185 if (data->data.type == PLATFORM_DUMPER_REGISTERL) {
186 value = OSAL_READL(regAddr);
187 } else if (data->data.type == PLATFORM_DUMPER_REGISTERW) {
188 value = OSAL_READW(regAddr);
189 } else if (data->data.type == PLATFORM_DUMPER_REGISTERB) {
190 value = OSAL_READB(regAddr);
191 } else {
192 HDF_LOGE("DumperPrintRegisterInfo: illegal type: %d!", data->data.type);
193 return;
194 }
195
196 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
197 int ret =
198 snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, data->printFormat, data->data.name, value);
199 if (ret > 0) {
200 OutputDumperInfo(info);
201 }
202 }
203
204 struct PlatformDumperDataFormatter {
205 enum PlatformDumperDataType type;
206 const char *printFormat; // type/name/value
207 void (*printFunc)(const struct DumperDataMgrNode *data);
208 };
209
210 static const struct PlatformDumperDataFormatter g_printInfos[] = {
211 {PLATFORM_DUMPER_UINT8, "uint8 %-32s\t %hhu\r\n", DumperPrintUint8Info },
212 {PLATFORM_DUMPER_UINT16, "uint16 %-32s\t %hu\r\n", DumperPrintUint16Info },
213 {PLATFORM_DUMPER_UINT32, "uint32 %-32s\t %u\r\n", DumperPrintUint32Info },
214 {PLATFORM_DUMPER_UINT64, "uint64 %-32s\t %llu\r\n", DumperPrintUint64Info },
215 {PLATFORM_DUMPER_INT8, "int8 %-32s\t %hhd\r\n", DumperPrintInt8Info },
216 {PLATFORM_DUMPER_INT16, "int16 %-32s\t %hd\r\n", DumperPrintInt16Info },
217 {PLATFORM_DUMPER_INT32, "int32 %-32s\t %d\r\n", DumperPrintInt32Info },
218 {PLATFORM_DUMPER_INT64, "int64 %-32s\t %lld\r\n", DumperPrintInt64Info },
219 {PLATFORM_DUMPER_CHAR, "char %-32s\t %c\r\n", DumperPrintCharInfo },
220 {PLATFORM_DUMPER_STRING, "string %-32s\t %s\r\n", DumperPrintStringInfo },
221 {PLATFORM_DUMPER_FLOAT, "float %-32s\t %f\r\n", DumperPrintFloatInfo },
222 {PLATFORM_DUMPER_DOUBLE, "double %-32s\t %lf\r\n", DumperPrintDoubleInfo },
223 {PLATFORM_DUMPER_REGISTERL, "registerL %-32s\t %u\r\n", DumperPrintRegisterInfo},
224 {PLATFORM_DUMPER_REGISTERW, "registerW %-32s\t %hu\r\n", DumperPrintRegisterInfo},
225 {PLATFORM_DUMPER_REGISTERB, "registerB %-32s\t %hhu\r\n", DumperPrintRegisterInfo},
226 };
227
DumperNodeSetPrintInfo(struct DumperDataMgrNode * node)228 static int32_t DumperNodeSetPrintInfo(struct DumperDataMgrNode *node)
229 {
230 int i;
231 for (i = 0; i < sizeof(g_printInfos) / sizeof(g_printInfos[0]); i++) {
232 if (node->data.type == g_printInfos[i].type) {
233 node->printFormat = g_printInfos[i].printFormat;
234 node->printFunc = g_printInfos[i].printFunc;
235 return HDF_SUCCESS;
236 }
237 }
238
239 HDF_LOGE("DumperNodeSetPrintInfo: node [%s] type [%d] not find!", node->data.name, node->data.type);
240 return HDF_FAILURE;
241 }
242
PlatformDumperCreate(const char * name)243 struct PlatformDumper *PlatformDumperCreate(const char *name)
244 {
245 struct PlatformDumper *dumper = NULL;
246 int32_t ret;
247
248 if (name == NULL) {
249 HDF_LOGE("PlatformDumperCreate: name is null!");
250 return NULL;
251 }
252 dumper = OsalMemAlloc(sizeof(struct PlatformDumper));
253 if (dumper == NULL) {
254 HDF_LOGE("PlatformDumperCreate: malloc dumper for %s fail!", name);
255 return NULL;
256 }
257
258 dumper->name = name;
259 dumper->ops = NULL;
260 DListHeadInit(&dumper->dumperDatas);
261 ret = OsalSpinInit(&dumper->spin);
262 if (ret != HDF_SUCCESS) {
263 HDF_LOGE("PlatformDumperCreate: dumper %s OsalSpinInit fail, ret: %d!", name, ret);
264 OsalMemFree(dumper);
265 return NULL;
266 }
267
268 HDF_LOGD("PlatformDumperCreate: create dumper for %s success!", name);
269 return dumper;
270 }
271
DumperAddNode(struct PlatformDumper * dumper,const struct PlatformDumperData * data)272 static int32_t DumperAddNode(struct PlatformDumper *dumper, const struct PlatformDumperData *data)
273 {
274 struct DumperDataMgrNode *pos = NULL;
275 struct DumperDataMgrNode *node = NULL;
276
277 if (data == NULL || data->name == NULL || data->paddr == NULL) {
278 HDF_LOGE("DumperAddNode: input param illegal!");
279 return HDF_FAILURE;
280 }
281
282 DLIST_FOR_EACH_ENTRY(pos, &dumper->dumperDatas, struct DumperDataMgrNode, node) {
283 if ((strcmp(pos->data.name, data->name) == 0) && (pos->data.type == data->type)) {
284 HDF_LOGE("DumperAddNode: node [%s][%d] existed!", data->name, data->type);
285 return HDF_FAILURE;
286 }
287 }
288
289 node = OsalMemAlloc(sizeof(struct DumperDataMgrNode));
290 if (node == NULL) {
291 HDF_LOGE("DumperAddNode: OsalMemAlloc node [%s] fail!", data->name);
292 return HDF_FAILURE;
293 }
294
295 node->data.name = data->name;
296 node->data.type = data->type;
297 node->data.paddr = data->paddr;
298 if (DumperNodeSetPrintInfo(node) == HDF_FAILURE) {
299 HDF_LOGE("DumperAddNode: SetPrintInfo node [%s] fail", data->name);
300 OsalMemFree(node);
301 return HDF_FAILURE;
302 }
303 DListInsertTail(&node->node, &dumper->dumperDatas);
304
305 return HDF_SUCCESS;
306 }
307
PlatformDumperAddData(struct PlatformDumper * dumper,const struct PlatformDumperData * data)308 int32_t PlatformDumperAddData(struct PlatformDumper *dumper, const struct PlatformDumperData *data)
309 {
310 int32_t ret;
311
312 if (dumper == NULL) {
313 HDF_LOGE("PlatformDumperAddData: input param illegal!");
314 return HDF_FAILURE;
315 }
316 (void)OsalSpinLock(&dumper->spin);
317 ret = DumperAddNode(dumper, data);
318 (void)OsalSpinUnlock(&dumper->spin);
319
320 return ret;
321 }
322
PlatformDumperAddDatas(struct PlatformDumper * dumper,struct PlatformDumperData datas[],int size)323 int32_t PlatformDumperAddDatas(struct PlatformDumper *dumper, struct PlatformDumperData datas[], int size)
324 {
325 int i;
326
327 if (dumper == NULL || datas == NULL) {
328 HDF_LOGE("PlatformDumperAddDatas: input param illegal!");
329 return HDF_FAILURE;
330 }
331 (void)OsalSpinLock(&dumper->spin);
332 for (i = 0; i < size; i++) {
333 if (DumperAddNode(dumper, &datas[i]) != HDF_SUCCESS) {
334 HDF_LOGE("PlatformDumperAddDatas: [%s] add data [%s] fail", dumper->name, datas[i].name);
335 (void)OsalSpinUnlock(&dumper->spin);
336 return HDF_FAILURE;
337 }
338 }
339 (void)OsalSpinUnlock(&dumper->spin);
340
341 return HDF_SUCCESS;
342 }
343
PlatformDumperDelData(struct PlatformDumper * dumper,const char * name,enum PlatformDumperDataType type)344 int32_t PlatformDumperDelData(struct PlatformDumper *dumper, const char *name, enum PlatformDumperDataType type)
345 {
346 struct DumperDataMgrNode *pos = NULL;
347 struct DumperDataMgrNode *tmp = NULL;
348
349 if (dumper == NULL || name == NULL) {
350 HDF_LOGE("PlatformDumperDelData: input param illegal!");
351 return HDF_FAILURE;
352 }
353
354 (void)OsalSpinLock(&dumper->spin);
355 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &dumper->dumperDatas, struct DumperDataMgrNode, node) {
356 if ((strcmp(pos->data.name, name) == 0) && (pos->data.type == type)) {
357 HDF_LOGD("PlatformDumperDelData: node [%s][%d] find, then del", name, type);
358 DListRemove(&pos->node);
359 OsalMemFree(pos);
360 (void)OsalSpinUnlock(&dumper->spin);
361 return HDF_SUCCESS;
362 }
363 }
364
365 (void)OsalSpinUnlock(&dumper->spin);
366 return HDF_SUCCESS;
367 }
368
PlatformDumperClearDatas(struct PlatformDumper * dumper)369 int32_t PlatformDumperClearDatas(struct PlatformDumper *dumper)
370 {
371 struct DumperDataMgrNode *pos = NULL;
372 struct DumperDataMgrNode *tmp = NULL;
373
374 if (dumper == NULL) {
375 HDF_LOGE("PlatformDumperClearDatas: dumper is null!");
376 return HDF_FAILURE;
377 }
378
379 (void)OsalSpinLock(&dumper->spin);
380 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &dumper->dumperDatas, struct DumperDataMgrNode, node) {
381 DListRemove(&pos->node);
382 OsalMemFree(pos);
383 }
384
385 (void)OsalSpinUnlock(&dumper->spin);
386 return HDF_SUCCESS;
387 }
388
PlatformDumperDestroy(struct PlatformDumper * dumper)389 void PlatformDumperDestroy(struct PlatformDumper *dumper)
390 {
391 int32_t ret;
392
393 if (dumper == NULL) {
394 HDF_LOGE("PlatformDumperDestroy: dumper is null!");
395 return;
396 }
397
398 PlatformDumperClearDatas(dumper);
399 ret = OsalSpinDestroy(&dumper->spin);
400 if (ret != HDF_SUCCESS) {
401 HDF_LOGE("PlatformDumperDestroy: dumper %s OsalSpinDestroy fail, ret: %d!", dumper->name, ret);
402 }
403
404 OsalMemFree(dumper);
405 }
406
PlatformDumperSetMethod(struct PlatformDumper * dumper,struct PlatformDumperMethod * ops)407 int32_t PlatformDumperSetMethod(struct PlatformDumper *dumper, struct PlatformDumperMethod *ops)
408 {
409 if (dumper == NULL || ops == NULL) {
410 HDF_LOGE("PlatformDumperSetMethod: input param null!");
411 return HDF_FAILURE;
412 }
413 (void)OsalSpinLock(&dumper->spin);
414 dumper->ops = ops;
415 (void)OsalSpinUnlock(&dumper->spin);
416 return HDF_SUCCESS;
417 }
418
PlatformGetDumperOpsInfo(const struct PlatformDumperMethod * ops)419 static void PlatformGetDumperOpsInfo(const struct PlatformDumperMethod *ops)
420 {
421 if (ops == NULL) {
422 return;
423 }
424 if (ops->dumperCfgInfo != NULL) {
425 ops->dumperCfgInfo();
426 }
427 if (ops->dumperStatusInfo != NULL) {
428 ops->dumperStatusInfo();
429 }
430 if (ops->dumperRegisterInfo != NULL) {
431 ops->dumperRegisterInfo();
432 }
433 if (ops->dumperStatisInfo != NULL) {
434 ops->dumperStatisInfo();
435 }
436 }
437
PlatformDumperDump(struct PlatformDumper * dumper)438 int32_t PlatformDumperDump(struct PlatformDumper *dumper)
439 {
440 struct DumperDataMgrNode *pos = NULL;
441 char info[DUMPER_INFO_FILE_LEN + 1] = {0};
442 int ret;
443
444 if (dumper == NULL) {
445 HDF_LOGE("PlatformDumperDump: dumper null!");
446 return HDF_FAILURE;
447 }
448
449 PlatformGetDumperOpsInfo(dumper->ops);
450
451 ret = snprintf_s(info, DUMPER_INFO_FILE_LEN + 1, DUMPER_INFO_FILE_LEN, "The dumper %s's data list as follows:\r\n",
452 dumper->name);
453 if (ret > 0) {
454 OutputDumperInfo(info);
455 }
456 OutputDumperInfo("type name value\r\n");
457
458 (void)OsalSpinLock(&dumper->spin);
459 DLIST_FOR_EACH_ENTRY(pos, &dumper->dumperDatas, struct DumperDataMgrNode, node) {
460 pos->printFunc(pos);
461 }
462 (void)OsalSpinUnlock(&dumper->spin);
463 return HDF_SUCCESS;
464 }
465