• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "blackbox.h"
17 #include "blackbox_adapter.h"
18 #include "blackbox_detector.h"
19 #include "ohos_init.h"
20 #include "ohos_types.h"
21 #include "pthread.h"
22 #include "securec.h"
23 #include "utils_list.h"
24 
25 /******************local macroes*********************/
26 #define LOG_ROOT_DIR_WAIT_TIME  1000
27 #define LOG_ROOT_DIR_WAIT_COUNT 1
28 #ifndef LOS_WAIT_FOREVER
29 #define LOS_WAIT_FOREVER        0xFFFFFFFF
30 #endif
31 #ifndef LOS_NO_WAIT
32 #define LOS_NO_WAIT             0
33 #endif
34 #ifndef LOS_OK
35 #define LOS_OK                  0
36 #endif
37 
38 /******************local prototypes******************/
39 struct BBoxOps {
40     UTILS_DL_LIST opsList;
41     struct ModuleOps ops;
42 };
43 
44 /******************global functions*******************/
45 /******************local variables*******************/
46 static UTILS_DL_LIST_HEAD(g_opsList);
47 static unsigned int g_opsListSem;
48 
49 /******************function definitions*******************/
GetDirName(char * dirBuf,unsigned int dirBufSize,const char * path)50 static void GetDirName(char *dirBuf, unsigned int dirBufSize, const char *path)
51 {
52     if (dirBuf == NULL || dirBufSize == 0 || path == NULL) {
53         BBOX_PRINT_ERR("dirBuf: %p, dirBufSize: %u, path: %p!\n", dirBuf, dirBufSize, path);
54         return;
55     }
56 
57     char *end = path + strlen(path);
58     while (*end != '/' && end >= path) {
59         end--;
60     }
61     if (end >= path) {
62         (void)memset_s(dirBuf, dirBufSize, 0, dirBufSize);
63         if (strncpy_s(dirBuf, dirBufSize - 1, path, end - path + strlen("/")) != EOK) {
64             BBOX_PRINT_ERR("strncpy_s failed or the dirBuf is not enough!\n");
65         }
66     } else {
67         BBOX_PRINT_ERR("no / has been found!\n");
68     }
69 }
70 
FormatErrorInfo(struct ErrorInfo * info,const char event[EVENT_MAX_LEN],const char module[MODULE_MAX_LEN],const char errorDesc[ERROR_DESC_MAX_LEN])71 static void FormatErrorInfo(struct ErrorInfo *info,
72     const char event[EVENT_MAX_LEN],
73     const char module[MODULE_MAX_LEN],
74     const char errorDesc[ERROR_DESC_MAX_LEN])
75 {
76     if (info == NULL || event == NULL || module == NULL || errorDesc == NULL) {
77         BBOX_PRINT_ERR("info: %p, event: %p, module: %p, errorDesc: %p\n",
78             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,
84         Min(strlen(event), sizeof(info->event) - 1)) != EOK) {
85         BBOX_PRINT_ERR("strncpy_s failed or the info->event is not enough!\n");
86     }
87     if (strncpy_s(info->module, sizeof(info->module), module,
88         Min(strlen(module), sizeof(info->module) - 1)) != EOK) {
89         BBOX_PRINT_ERR("strncpy_s failed or the info->module is not enough!\n");
90     }
91     if (strncpy_s(info->errorDesc, sizeof(info->errorDesc), errorDesc,
92         Min(strlen(errorDesc), sizeof(info->errorDesc) - 1)) != EOK) {
93         BBOX_PRINT_ERR("strncpy_s failed or the info->errorDesc is not enough!\n");
94     }
95 }
96 
WaitForLogRootDir(const char * rootDir)97 static void WaitForLogRootDir(const char *rootDir)
98 {
99     int i = 0;
100 
101     if (rootDir == NULL) {
102         BBOX_PRINT_ERR("rootDir: %p\n", rootDir);
103         return;
104     }
105     BBOX_PRINT_INFO("wait for log root dir [%s] begin!\n", rootDir);
106     while (i++ < LOG_ROOT_DIR_WAIT_COUNT) {
107         LOS_Msleep(LOG_ROOT_DIR_WAIT_TIME);
108     }
109     BBOX_PRINT_INFO("wait for log root dir [%s] end!\n", rootDir);
110 }
111 
SaveBasicErrorInfo(const char * filePath,struct ErrorInfo * info)112 static void SaveBasicErrorInfo(const char *filePath, struct ErrorInfo *info)
113 {
114     char *buf = NULL;
115 
116     if (filePath == NULL || info == NULL) {
117         BBOX_PRINT_ERR("filePath: %p, info: %p!\n", filePath, info);
118         return;
119     }
120 
121     buf = malloc(ERROR_INFO_MAX_LEN);
122     if (buf == NULL) {
123         BBOX_PRINT_ERR("malloc failed!\n");
124         return;
125     }
126     (void)memset_s(buf, ERROR_INFO_MAX_LEN, 0, ERROR_INFO_MAX_LEN);
127     if (snprintf_s(buf, ERROR_INFO_MAX_LEN, ERROR_INFO_MAX_LEN - 1,
128         ERROR_INFO_HEADER ERROR_INFO_HEADER_FORMAT,
129         info->event, info->module, info->errorDesc) != -1) {
130         *(buf + ERROR_INFO_MAX_LEN - 1) = '\0';
131         (void)FullWriteFile(filePath, buf, strlen(buf), 0);
132     } else {
133         PRINT_ERR("buf is not enough or snprintf_s failed\n");
134     }
135     free(buf);
136     BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n",
137         info->module, info->event);
138     (void)UploadEventByFile(filePath);
139     BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n",
140         info->module, info->event);
141 }
142 
SaveErrorLog(void * param)143 static void* SaveErrorLog(void *param)
144 {
145     struct ErrorInfo *info = NULL;
146     struct BBoxOps *ops = NULL;
147     char dirName[PATH_MAX_LEN] = { 0 };
148 
149     info = malloc(sizeof(*info));
150     if (info == NULL) {
151         BBOX_PRINT_ERR("malloc failed!\n");
152         return NULL;
153     }
154 
155     GetDirName(dirName, sizeof(dirName), GetFaultLogPath());
156     WaitForLogRootDir(dirName);
157     if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != 0) {
158         BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
159         free(info);
160         return NULL;
161     }
162     UTILS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, struct BBoxOps, opsList) {
163         if (ops == NULL) {
164             continue;
165         }
166         if (ops->ops.GetLastLogInfo != NULL && ops->ops.SaveLastLog != NULL) {
167             (void)memset_s(info, sizeof(*info), 0, sizeof(*info));
168             if (ops->ops.GetLastLogInfo(info) != 0) {
169                 BBOX_PRINT_ERR("[%s] failed to get log info!\n",
170                     ops->ops.module);
171                     continue;
172             }
173             BBOX_PRINT_INFO("[%s] starts saving log!\n", ops->ops.module);
174             if (ops->ops.SaveLastLog(dirName, info) != 0) {
175                 BBOX_PRINT_ERR("[%s] failed to save log!\n", ops->ops.module);
176             } else {
177                 BBOX_PRINT_INFO("[%s] ends saving log!\n", ops->ops.module);
178                 BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event);
179                 (void)UploadEventByFile(GetFaultLogPath());
180                 BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event);
181             }
182         }
183     }
184     (void)LOS_SemPost(g_opsListSem);
185     free(info);
186 
187     return NULL;
188 }
189 
190 #ifdef BLACKBOX_DEBUG
PrintModuleOps(void)191 static void PrintModuleOps(void)
192 {
193     struct BBoxOps *temp = NULL;
194 
195     BBOX_PRINT_INFO("The following modules have been registered!\n");
196     UTILS_DL_LIST_FOR_EACH_ENTRY(temp, &g_opsList, struct BBoxOps, opsList) {
197         BBOX_PRINT_INFO("module: %s, Dump: %p, Reset: %p, "
198             "GetLastLogInfo: %p, SaveLastLog: %p\n",
199             temp->ops.module, temp->ops.Dump, temp->ops.Reset,
200             temp->ops.GetLastLogInfo, temp->ops.SaveLastLog);
201     }
202 }
203 #endif
204 
BBoxRegisterModuleOps(struct ModuleOps * ops)205 int BBoxRegisterModuleOps(struct ModuleOps *ops)
206 {
207     struct BBoxOps *newOps = NULL;
208     struct BBoxOps *temp = NULL;
209 
210     if (ops == NULL) {
211         BBOX_PRINT_ERR("ops: %p!\n", ops);
212         return -1;
213     }
214 
215     /* Use malloc to avoid the stack overflow */
216     newOps = malloc(sizeof(*newOps));
217     if (newOps == NULL) {
218         BBOX_PRINT_ERR("malloc failed!\n");
219         return -1;
220     }
221     (void)memset_s(newOps, sizeof(*newOps), 0, sizeof(*newOps));
222     (void)memcpy_s(&newOps->ops, sizeof(newOps->ops), ops, sizeof(*ops));
223     if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != 0) {
224         BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
225         free(newOps);
226         return -1;
227     }
228     if (UtilsListEmpty(&g_opsList)) {
229         goto __out;
230     }
231     UTILS_DL_LIST_FOR_EACH_ENTRY(temp, &g_opsList, struct BBoxOps, opsList) {
232         if (strcmp(temp->ops.module, ops->module) == 0) {
233             BBOX_PRINT_ERR("[%s] has been registered!\n", ops->module);
234             (void)LOS_SemPost(g_opsListSem);
235             free(newOps);
236             return -1;
237         }
238     }
239 
240 __out:
241     BBOX_PRINT_INFO("[%s] is registered successfully!\n", ops->module);
242     UtilsListTailInsert(&g_opsList, &newOps->opsList);
243     (void)LOS_SemPost(g_opsListSem);
244 #ifdef BLACKBOX_DEBUG
245     PrintModuleOps();
246 #endif
247 
248     return 0;
249 }
250 
BBoxNotifyError(const char event[EVENT_MAX_LEN],const char module[MODULE_MAX_LEN],const char errorDesc[ERROR_DESC_MAX_LEN],int needSysReset)251 int BBoxNotifyError(const char event[EVENT_MAX_LEN],
252     const char module[MODULE_MAX_LEN],
253     const char errorDesc[ERROR_DESC_MAX_LEN],
254     int needSysReset)
255 {
256     int findModule = 0;
257     struct BBoxOps *ops = NULL;
258     struct ErrorInfo *info = NULL;
259     char dirName[PATH_MAX_LEN] = { 0 };
260 
261     info = malloc(sizeof(*info));
262     if (info == NULL) {
263         BBOX_PRINT_ERR("malloc failed!\n");
264         return -1;
265     }
266 
267     GetDirName(dirName, sizeof(dirName), GetFaultLogPath());
268     if (needSysReset == 0) {
269         WaitForLogRootDir(dirName);
270         if (LOS_SemPend(g_opsListSem, LOS_NO_WAIT) != 0) {
271             BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
272             goto __out;
273         }
274     }
275 
276     UTILS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, struct BBoxOps, opsList) {
277         if (ops == NULL) {
278             BBOX_PRINT_ERR("ops: %p!\n", ops);
279             continue;
280         }
281         if (strcmp(ops->ops.module, module) != 0) {
282             continue;
283         }
284         FormatErrorInfo(info, event, module, errorDesc);
285         if (ops->ops.Dump == NULL && ops->ops.Reset == NULL) {
286             SaveBasicErrorInfo(GetFaultLogPath(), info);
287             break;
288         }
289         if (ops->ops.Dump != NULL) {
290             BBOX_PRINT_INFO("[%s] starts dumping data!\n", ops->ops.module);
291             ops->ops.Dump(dirName, info);
292             BBOX_PRINT_INFO("[%s] ends dumping data!\n", ops->ops.module);
293         }
294         if (ops->ops.Reset != NULL) {
295             BBOX_PRINT_INFO("[%s] starts resetting!\n", ops->ops.module);
296             ops->ops.Reset(info);
297             BBOX_PRINT_INFO("[%s] ends resetting!\n", ops->ops.module);
298         }
299         findModule = 1;
300         break;
301     }
302     if (needSysReset == 0) {
303         (void)LOS_SemPost(g_opsListSem);
304     }
305 
306 __out:
307     if (info != NULL) {
308         free(info);
309     }
310     if (needSysReset != 0 && findModule != 0) {
311         RebootSystem();
312     }
313 
314     return 0;
315 }
316 
BBoxInit(void)317 static void BBoxInit(void)
318 {
319     int ret = -1;
320     pthread_t taskId = 0;
321 
322     if (LOS_BinarySemCreate(1, &g_opsListSem) != LOS_OK) {
323         BBOX_PRINT_ERR("Create binary semaphore failed!\n");
324         return;
325     }
326     UtilsListInit(&g_opsList);
327     ret = pthread_create(&taskId, NULL, SaveErrorLog, NULL);
328     if (ret != 0) {
329         BBOX_PRINT_ERR("Falied to create SaveErrorLog task, ret: %d\n", ret);
330     }
331 }
332 CORE_INIT_PRI(BBoxInit, 1);