• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /* ------------ includes ------------ */
32 #include "los_blackbox.h"
33 #include "los_blackbox_common.h"
34 #include "los_blackbox_detector.h"
35 #ifdef LOSCFG_LIB_LIBC
36 #include "stdlib.h"
37 #include "unistd.h"
38 #endif
39 #include "los_base.h"
40 #include "los_config.h"
41 #include "los_excinfo_pri.h"
42 #include "los_hw.h"
43 #include "los_init.h"
44 #include "los_memory.h"
45 #include "los_sem.h"
46 #include "los_syscall.h"
47 #include "los_task_pri.h"
48 #include "securec.h"
49 #include "sys/reboot.h"
50 
51 /* ------------ local macroes ------------ */
52 #define LOG_WAIT_TIMES 10
53 #define LOG_PART_WAIT_TIME 1000
54 
55 /* ------------ local prototypes ------------ */
56 typedef struct BBoxOps {
57     LOS_DL_LIST opsList;
58     struct ModuleOps ops;
59 } BBoxOps;
60 
61 /* ------------ local function declarations ------------ */
62 /* ------------ global function declarations ------------ */
63 /* ------------ local variables ------------ */
64 static bool g_bboxInitSucc = FALSE;
65 static UINT32 g_opsListSem = 0;
66 static UINT32 g_tempErrInfoSem = 0;
67 static UINT32 g_tempErrLogSaveSem = 0;
68 static LOS_DL_LIST_HEAD(g_opsList);
69 struct ErrorInfo *g_tempErrInfo;
70 
71 /* ------------ function definitions ------------ */
FormatErrorInfo(struct ErrorInfo * info,const char event[EVENT_MAX_LEN],const char module[MODULE_MAX_LEN],const char errorDesc[ERROR_DESC_MAX_LEN])72 static void FormatErrorInfo(struct ErrorInfo *info,
73                             const char event[EVENT_MAX_LEN],
74                             const char module[MODULE_MAX_LEN],
75                             const char errorDesc[ERROR_DESC_MAX_LEN])
76 {
77     if (info == NULL || event == NULL || module == NULL || errorDesc == NULL) {
78         BBOX_PRINT_ERR("info: %p, event: %p, module: %p, errorDesc: %p!\n", info, event, module, errorDesc);
79         return;
80     }
81 
82     (void)memset_s(info, sizeof(*info), 0, sizeof(*info));
83     if (strncpy_s(info->event, sizeof(info->event), event, Min(strlen(event), sizeof(info->event) - 1)) != EOK) {
84         BBOX_PRINT_ERR("info->event is not enough or strncpy_s failed!\n");
85     }
86     if (strncpy_s(info->module, sizeof(info->module), module, Min(strlen(module), sizeof(info->module) - 1)) != EOK) {
87         BBOX_PRINT_ERR("info->module is not enough or strncpy_s failed!\n");
88     }
89     if (strncpy_s(info->errorDesc, sizeof(info->errorDesc), errorDesc,
90         Min(strlen(errorDesc), sizeof(info->errorDesc) - 1)) != EOK) {
91         BBOX_PRINT_ERR("info->errorDesc is not enough or strncpy_s failed!\n");
92     }
93 }
94 
95 #ifdef LOSCFG_FS_VFS
WaitForLogPart(void)96 static void WaitForLogPart(void)
97 {
98     BBOX_PRINT_INFO("wait for log part [%s] begin!\n", LOSCFG_BLACKBOX_LOG_PART_MOUNT_POINT);
99     while (!IsLogPartReady()) {
100         LOS_Msleep(LOG_PART_WAIT_TIME);
101     }
102     BBOX_PRINT_INFO("wait for log part [%s] end!\n", LOSCFG_BLACKBOX_LOG_PART_MOUNT_POINT);
103 }
104 #else
WaitForLogPart(void)105 static void WaitForLogPart(void)
106 {
107     int i = 0;
108 
109     BBOX_PRINT_INFO("wait for log part [%s] begin!\n", LOSCFG_BLACKBOX_LOG_PART_MOUNT_POINT);
110     while (i++ < LOG_WAIT_TIMES) {
111         LOS_Msleep(LOG_PART_WAIT_TIME);
112     }
113     BBOX_PRINT_INFO("wait for log part [%s] end!\n", LOSCFG_BLACKBOX_LOG_PART_MOUNT_POINT);
114 }
115 #endif
116 
FindModuleOps(struct ErrorInfo * info,BBoxOps ** ops)117 static bool FindModuleOps(struct ErrorInfo *info, BBoxOps **ops)
118 {
119     bool found = false;
120 
121     if (info == NULL || ops == NULL) {
122         BBOX_PRINT_ERR("info: %p, ops: %p!\n", info, ops);
123         return found;
124     }
125 
126     LOS_DL_LIST_FOR_EACH_ENTRY(*ops, &g_opsList, BBoxOps, opsList) {
127         if (*ops != NULL && strcmp((*ops)->ops.module, info->module) == 0) {
128             found = true;
129             break;
130         }
131     }
132     if (!found) {
133         BBOX_PRINT_ERR("[%s] hasn't been registered!\n", info->module);
134     }
135 
136     return found;
137 }
138 
InvokeModuleOps(struct ErrorInfo * info,const BBoxOps * ops)139 static void InvokeModuleOps(struct ErrorInfo *info, const BBoxOps *ops)
140 {
141     if (info == NULL || ops == NULL) {
142         BBOX_PRINT_ERR("info: %p, ops: %p!\n", info, ops);
143         return;
144     }
145 
146     if (ops->ops.Dump != NULL) {
147         BBOX_PRINT_INFO("[%s] starts dumping log!\n", ops->ops.module);
148         ops->ops.Dump(LOSCFG_BLACKBOX_LOG_ROOT_PATH, info);
149         BBOX_PRINT_INFO("[%s] ends dumping log!\n", ops->ops.module);
150     }
151     if (ops->ops.Reset != NULL) {
152         BBOX_PRINT_INFO("[%s] starts resetting!\n", ops->ops.module);
153         ops->ops.Reset(info);
154         BBOX_PRINT_INFO("[%s] ends resetting!\n", ops->ops.module);
155     }
156 }
157 
SaveLastLog(const char * logDir)158 static void SaveLastLog(const char *logDir)
159 {
160     struct ErrorInfo *info = NULL;
161     BBoxOps *ops = NULL;
162 
163     info = LOS_MemAlloc(m_aucSysMem1, sizeof(*info));
164     if (info == NULL) {
165         BBOX_PRINT_ERR("LOS_MemAlloc failed!\n");
166         return;
167     }
168 
169     if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != LOS_OK) {
170         BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
171         (void)LOS_MemFree(m_aucSysMem1, info);
172         return;
173     }
174     if (CreateLogDir(LOSCFG_BLACKBOX_LOG_ROOT_PATH) != 0) {
175         (void)LOS_SemPost(g_opsListSem);
176         (void)LOS_MemFree(m_aucSysMem1, info);
177         BBOX_PRINT_ERR("Create log dir [%s] failed!\n", LOSCFG_BLACKBOX_LOG_ROOT_PATH);
178         return;
179     }
180     LOS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, BBoxOps, opsList) {
181         if (ops == NULL) {
182             BBOX_PRINT_ERR("ops: NULL, please check it!\n");
183             continue;
184         }
185         if (ops->ops.GetLastLogInfo != NULL && ops->ops.SaveLastLog != NULL) {
186             (void)memset_s(info, sizeof(*info), 0, sizeof(*info));
187             if (ops->ops.GetLastLogInfo(info) != 0) {
188                 BBOX_PRINT_ERR("[%s] failed to get log info!\n", ops->ops.module);
189                 continue;
190             }
191             BBOX_PRINT_INFO("[%s] starts saving log!\n", ops->ops.module);
192             if (ops->ops.SaveLastLog(logDir, info) != 0) {
193                 BBOX_PRINT_ERR("[%s] failed to save log!\n", ops->ops.module);
194             } else {
195                 BBOX_PRINT_INFO("[%s] ends saving log!\n", ops->ops.module);
196                 BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event);
197 #ifdef LOSCFG_FS_VFS
198                 (void)UploadEventByFile(KERNEL_FAULT_LOG_PATH);
199 #else
200                 BBOX_PRINT_INFO("LOSCFG_FS_VFS isn't defined!\n");
201 #endif
202                 BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event);
203             }
204         } else {
205             BBOX_PRINT_ERR("module [%s], GetLastLogInfo: %p, SaveLastLog: %p!\n",
206                            ops->ops.module, ops->ops.GetLastLogInfo, ops->ops.SaveLastLog);
207         }
208     }
209     (void)LOS_SemPost(g_opsListSem);
210     (void)LOS_MemFree(m_aucSysMem1, info);
211 }
212 
SaveLogWithoutReset(struct ErrorInfo * info)213 static void SaveLogWithoutReset(struct ErrorInfo *info)
214 {
215     BBoxOps *ops = NULL;
216 
217     if (info == NULL) {
218         BBOX_PRINT_ERR("info is NULL!\n");
219         return;
220     }
221 
222     if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != LOS_OK) {
223         BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
224         return;
225     }
226     if (!FindModuleOps(info, &ops)) {
227         (void)LOS_SemPost(g_opsListSem);
228         return;
229     }
230     if (CreateLogDir(LOSCFG_BLACKBOX_LOG_ROOT_PATH) != 0) {
231         (void)LOS_SemPost(g_opsListSem);
232         BBOX_PRINT_ERR("Create log dir [%s] failed!\n", LOSCFG_BLACKBOX_LOG_ROOT_PATH);
233         return;
234     }
235     if (ops->ops.Dump == NULL && ops->ops.Reset == NULL) {
236         (void)LOS_SemPost(g_opsListSem);
237         if (SaveBasicErrorInfo(USER_FAULT_LOG_PATH, info) == 0) {
238             BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event);
239 #ifdef LOSCFG_FS_VFS
240             (void)UploadEventByFile(USER_FAULT_LOG_PATH);
241 #else
242             BBOX_PRINT_INFO("LOSCFG_FS_VFS isn't defined!\n");
243 #endif
244             BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event);
245         }
246         return;
247     }
248     InvokeModuleOps(info, ops);
249     (void)LOS_SemPost(g_opsListSem);
250 }
251 
SaveTempErrorLog(void)252 static void SaveTempErrorLog(void)
253 {
254     if (LOS_SemPend(g_tempErrInfoSem, LOS_WAIT_FOREVER) != LOS_OK) {
255         BBOX_PRINT_ERR("Request g_tempErrInfoSem failed!\n");
256         return;
257     }
258     if (g_tempErrInfo == NULL) {
259         BBOX_PRINT_ERR("g_tempErrInfo is NULL!\n");
260         (void)LOS_SemPost(g_tempErrInfoSem);
261         return;
262     }
263     if (strlen(g_tempErrInfo->event) != 0) {
264         SaveLogWithoutReset(g_tempErrInfo);
265     }
266     (void)LOS_SemPost(g_tempErrInfoSem);
267 }
268 
SaveLogWithReset(struct ErrorInfo * info)269 static void SaveLogWithReset(struct ErrorInfo *info)
270 {
271     int ret;
272     BBoxOps *ops = NULL;
273 
274     if (info == NULL) {
275         BBOX_PRINT_ERR("info is NULL!\n");
276         return;
277     }
278 
279     if (!FindModuleOps(info, &ops)) {
280         return;
281     }
282     InvokeModuleOps(info, ops);
283     ret = SysReboot(0, 0, RB_AUTOBOOT);
284     BBOX_PRINT_INFO("SysReboot, ret: %d\n", ret);
285 }
286 
SaveTempErrorInfo(const char event[EVENT_MAX_LEN],const char module[MODULE_MAX_LEN],const char errorDesc[ERROR_DESC_MAX_LEN])287 static void SaveTempErrorInfo(const char event[EVENT_MAX_LEN],
288     const char module[MODULE_MAX_LEN],
289     const char errorDesc[ERROR_DESC_MAX_LEN])
290 {
291     if (event == NULL || module == NULL || errorDesc == NULL) {
292         BBOX_PRINT_ERR("event: %p, module: %p, errorDesc: %p!\n", event, module, errorDesc);
293         return;
294     }
295     if (LOS_SemPend(g_tempErrInfoSem, LOS_NO_WAIT) != LOS_OK) {
296         BBOX_PRINT_ERR("Request g_tempErrInfoSem failed!\n");
297         return;
298     }
299     FormatErrorInfo(g_tempErrInfo, event, module, errorDesc);
300     (void)LOS_SemPost(g_tempErrInfoSem);
301 }
302 
SaveErrorLog(UINTPTR uwParam1,UINTPTR uwParam2,UINTPTR uwParam3,UINTPTR uwParam4)303 static int SaveErrorLog(UINTPTR uwParam1, UINTPTR uwParam2, UINTPTR uwParam3, UINTPTR uwParam4)
304 {
305     const char *logDir = (const char *)uwParam1;
306     (void)uwParam2;
307     (void)uwParam3;
308     (void)uwParam4;
309 
310 #ifdef LOSCFG_FS_VFS
311     WaitForLogPart();
312 #endif
313     SaveLastLog(logDir);
314     while (1) {
315         if (LOS_SemPend(g_tempErrLogSaveSem, LOS_WAIT_FOREVER) != LOS_OK) {
316             BBOX_PRINT_ERR("Request g_tempErrLogSaveSem failed!\n");
317             continue;
318         }
319         SaveTempErrorLog();
320     }
321     return 0;
322 }
323 
324 #ifdef LOSCFG_BLACKBOX_DEBUG
PrintModuleOps(void)325 static void PrintModuleOps(void)
326 {
327     struct BBoxOps *ops = NULL;
328 
329     BBOX_PRINT_INFO("The following modules have been registered!\n");
330     LOS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, BBoxOps, opsList) {
331         if (ops == NULL) {
332             continue;
333         }
334         BBOX_PRINT_INFO("module: %s, Dump: %p, Reset: %p, GetLastLogInfo: %p, SaveLastLog: %p\n",
335             ops->ops.module, ops->ops.Dump, ops->ops.Reset, ops->ops.GetLastLogInfo, ops->ops.SaveLastLog);
336     }
337 }
338 #endif
339 
BBoxRegisterModuleOps(struct ModuleOps * ops)340 int BBoxRegisterModuleOps(struct ModuleOps *ops)
341 {
342     BBoxOps *newOps = NULL;
343     BBoxOps *temp = NULL;
344 
345     if (!g_bboxInitSucc) {
346         BBOX_PRINT_ERR("BlackBox isn't initialized successfully!\n");
347         return -1;
348     }
349     if (ops == NULL) {
350         BBOX_PRINT_ERR("ops is NULL!\n");
351         return -1;
352     }
353 
354     newOps = LOS_MemAlloc(m_aucSysMem1, sizeof(*newOps));
355     if (newOps == NULL) {
356         BBOX_PRINT_ERR("LOS_MemAlloc failed!\n");
357         return -1;
358     }
359     (void)memset_s(newOps, sizeof(*newOps), 0, sizeof(*newOps));
360     if (memcpy_s(&newOps->ops, sizeof(newOps->ops), ops, sizeof(*ops)) != EOK) {
361         BBOX_PRINT_ERR("newOps->ops is not enough or memcpy_s failed!\n");
362         (void)LOS_MemFree(m_aucSysMem1, newOps);
363         return -1;
364     }
365     if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != LOS_OK) {
366         BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
367         (void)LOS_MemFree(m_aucSysMem1, newOps);
368         return -1;
369     }
370     if (LOS_ListEmpty(&g_opsList)) {
371         goto __out;
372     }
373 
374     LOS_DL_LIST_FOR_EACH_ENTRY(temp, &g_opsList, BBoxOps, opsList) {
375         if (temp == NULL) {
376             continue;
377         }
378         if (strcmp(temp->ops.module, ops->module) == 0) {
379             BBOX_PRINT_ERR("module [%s] has been registered!\n", ops->module);
380             (void)LOS_SemPost(g_opsListSem);
381             (void)LOS_MemFree(m_aucSysMem1, newOps);
382             return -1;
383         }
384     }
385 
386 __out:
387     LOS_ListTailInsert(&g_opsList, &newOps->opsList);
388     (void)LOS_SemPost(g_opsListSem);
389     BBOX_PRINT_INFO("module [%s] is registered successfully!\n", ops->module);
390 #ifdef LOSCFG_BLACKBOX_DEBUG
391     PrintModuleOps();
392 #endif
393 
394     return 0;
395 }
396 
BBoxNotifyError(const char event[EVENT_MAX_LEN],const char module[MODULE_MAX_LEN],const char errorDesc[ERROR_DESC_MAX_LEN],int needSysReset)397 int BBoxNotifyError(const char event[EVENT_MAX_LEN],
398     const char module[MODULE_MAX_LEN],
399     const char errorDesc[ERROR_DESC_MAX_LEN],
400     int needSysReset)
401 {
402     if (event == NULL || module == NULL || errorDesc == NULL) {
403         BBOX_PRINT_ERR("event: %p, module: %p, errorDesc: %p!\n", event, module, errorDesc);
404         return -1;
405     }
406     if (!g_bboxInitSucc) {
407         BBOX_PRINT_ERR("BlackBox isn't initialized successfully!\n");
408         return -1;
409     }
410 
411     if (needSysReset == 0) {
412         SaveTempErrorInfo(event, module, errorDesc);
413         (void)LOS_SemPost(g_tempErrLogSaveSem);
414     } else {
415         struct ErrorInfo *info = LOS_MemAlloc(m_aucSysMem1, sizeof(struct ErrorInfo));
416         if (info == NULL) {
417             BBOX_PRINT_ERR("LOS_MemAlloc failed!\n");
418             return -1;
419         }
420         FormatErrorInfo(info, event, module, errorDesc);
421         SaveLogWithReset(info);
422         (void)LOS_MemFree(m_aucSysMem1, info);
423     }
424 
425     return 0;
426 }
427 
OsBBoxDriverInit(void)428 int OsBBoxDriverInit(void)
429 {
430     UINT32 taskID;
431     TSK_INIT_PARAM_S taskParam;
432 
433     if (LOS_BinarySemCreate(1, &g_opsListSem) != LOS_OK) {
434         BBOX_PRINT_ERR("Create g_opsListSem failed!\n");
435         return LOS_NOK;
436     }
437     if (LOS_BinarySemCreate(1, &g_tempErrInfoSem) != LOS_OK) {
438         BBOX_PRINT_ERR("Create g_tempErrInfoSem failed!\n");
439         goto __err;
440     }
441     if (LOS_BinarySemCreate(0, &g_tempErrLogSaveSem) != LOS_OK) {
442         BBOX_PRINT_ERR("Create g_tempErrLogSaveSem failed!\n");
443         goto __err;
444     }
445     LOS_ListInit(&g_opsList);
446     g_tempErrInfo = LOS_MemAlloc(m_aucSysMem1, sizeof(*g_tempErrInfo));
447     if (g_tempErrInfo == NULL) {
448         BBOX_PRINT_ERR("LOS_MemAlloc failed!\n");
449         goto __err;
450     }
451     (void)memset_s(g_tempErrInfo, sizeof(*g_tempErrInfo), 0, sizeof(*g_tempErrInfo));
452     (void)memset_s(&taskParam, sizeof(taskParam), 0, sizeof(taskParam));
453     taskParam.auwArgs[0] = (UINTPTR)LOSCFG_BLACKBOX_LOG_ROOT_PATH;
454     taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SaveErrorLog;
455     taskParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
456     taskParam.pcName = "SaveErrorLog";
457     taskParam.usTaskPrio = LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO;
458     taskParam.uwResved = LOS_TASK_STATUS_DETACHED;
459 #ifdef LOSCFG_KERNEL_SMP
460     taskParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());
461 #endif
462     (void)LOS_TaskCreate(&taskID, &taskParam);
463     g_bboxInitSucc = TRUE;
464     return LOS_OK;
465 
466 __err:
467     if (g_opsListSem != 0) {
468         (void)LOS_SemDelete(g_opsListSem);
469     }
470     if (g_tempErrInfoSem != 0) {
471         (void)LOS_SemDelete(g_tempErrInfoSem);
472     }
473     if (g_tempErrLogSaveSem != 0) {
474         (void)LOS_SemDelete(g_tempErrLogSaveSem);
475     }
476     return LOS_NOK;
477 }
478 LOS_MODULE_INIT(OsBBoxDriverInit, LOS_INIT_LEVEL_ARCH);