• 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     const 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     (void)param;
146     struct ErrorInfo *info = NULL;
147     struct BBoxOps *ops = NULL;
148     char dirName[PATH_MAX_LEN] = { 0 };
149 
150     info = malloc(sizeof(*info));
151     if (info == NULL) {
152         BBOX_PRINT_ERR("malloc failed!\n");
153         return NULL;
154     }
155 
156     GetDirName(dirName, sizeof(dirName), GetFaultLogPath());
157     WaitForLogRootDir(dirName);
158     if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != 0) {
159         BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
160         free(info);
161         return NULL;
162     }
163     UTILS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, struct BBoxOps, opsList) {
164         if (ops == NULL) {
165             continue;
166         }
167         if (ops->ops.GetLastLogInfo != NULL && ops->ops.SaveLastLog != NULL) {
168             (void)memset_s(info, sizeof(*info), 0, sizeof(*info));
169             if (ops->ops.GetLastLogInfo(info) != 0) {
170                 BBOX_PRINT_ERR("[%s] failed to get log info!\n",
171                     ops->ops.module);
172                     continue;
173             }
174             BBOX_PRINT_INFO("[%s] starts saving log!\n", ops->ops.module);
175             if (ops->ops.SaveLastLog(dirName, info) != 0) {
176                 BBOX_PRINT_ERR("[%s] failed to save log!\n", ops->ops.module);
177             } else {
178                 BBOX_PRINT_INFO("[%s] ends saving log!\n", ops->ops.module);
179                 BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event);
180                 (void)UploadEventByFile(GetFaultLogPath());
181                 BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event);
182             }
183         }
184     }
185     (void)LOS_SemPost(g_opsListSem);
186     free(info);
187 
188     return NULL;
189 }
190 
191 #ifdef BLACKBOX_DEBUG
PrintModuleOps(void)192 static void PrintModuleOps(void)
193 {
194     struct BBoxOps *temp = NULL;
195 
196     BBOX_PRINT_INFO("The following modules have been registered!\n");
197     UTILS_DL_LIST_FOR_EACH_ENTRY(temp, &g_opsList, struct BBoxOps, opsList) {
198         BBOX_PRINT_INFO("module: %s, Dump: %p, Reset: %p, "
199             "GetLastLogInfo: %p, SaveLastLog: %p\n",
200             temp->ops.module, temp->ops.Dump, temp->ops.Reset,
201             temp->ops.GetLastLogInfo, temp->ops.SaveLastLog);
202     }
203 }
204 #endif
205 
BBoxRegisterModuleOps(struct ModuleOps * ops)206 int BBoxRegisterModuleOps(struct ModuleOps *ops)
207 {
208     struct BBoxOps *newOps = NULL;
209     struct BBoxOps *temp = NULL;
210 
211     if (ops == NULL) {
212         BBOX_PRINT_ERR("ops: %p!\n", ops);
213         return -1;
214     }
215 
216     /* Use malloc to avoid the stack overflow */
217     newOps = malloc(sizeof(*newOps));
218     if (newOps == NULL) {
219         BBOX_PRINT_ERR("malloc failed!\n");
220         return -1;
221     }
222     (void)memset_s(newOps, sizeof(*newOps), 0, sizeof(*newOps));
223     (void)memcpy_s(&newOps->ops, sizeof(newOps->ops), ops, sizeof(*ops));
224     if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != 0) {
225         BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
226         free(newOps);
227         return -1;
228     }
229     if (UtilsListEmpty(&g_opsList)) {
230         goto __out;
231     }
232     UTILS_DL_LIST_FOR_EACH_ENTRY(temp, &g_opsList, struct BBoxOps, opsList) {
233         if (strcmp(temp->ops.module, ops->module) == 0) {
234             BBOX_PRINT_ERR("[%s] has been registered!\n", ops->module);
235             (void)LOS_SemPost(g_opsListSem);
236             free(newOps);
237             return -1;
238         }
239     }
240 
241 __out:
242     BBOX_PRINT_INFO("[%s] is registered successfully!\n", ops->module);
243     UtilsListTailInsert(&g_opsList, &newOps->opsList);
244     (void)LOS_SemPost(g_opsListSem);
245 #ifdef BLACKBOX_DEBUG
246     PrintModuleOps();
247 #endif
248 
249     return 0;
250 }
251 
BBoxNotifyError(const char event[EVENT_MAX_LEN],const char module[MODULE_MAX_LEN],const char errorDesc[ERROR_DESC_MAX_LEN],int needSysReset)252 int BBoxNotifyError(const char event[EVENT_MAX_LEN],
253     const char module[MODULE_MAX_LEN],
254     const char errorDesc[ERROR_DESC_MAX_LEN],
255     int needSysReset)
256 {
257     int findModule = 0;
258     struct BBoxOps *ops = NULL;
259     struct ErrorInfo *info = NULL;
260     char dirName[PATH_MAX_LEN] = { 0 };
261 
262     info = malloc(sizeof(*info));
263     if (info == NULL) {
264         BBOX_PRINT_ERR("malloc failed!\n");
265         return -1;
266     }
267 
268     GetDirName(dirName, sizeof(dirName), GetFaultLogPath());
269     if (needSysReset == 0) {
270         WaitForLogRootDir(dirName);
271         if (LOS_SemPend(g_opsListSem, LOS_NO_WAIT) != 0) {
272             BBOX_PRINT_ERR("Request g_opsListSem failed!\n");
273             goto __out;
274         }
275     }
276 
277     UTILS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, struct BBoxOps, opsList) {
278         if (ops == NULL) {
279             BBOX_PRINT_ERR("ops: %p!\n", ops);
280             continue;
281         }
282         if (strcmp(ops->ops.module, module) != 0) {
283             continue;
284         }
285         FormatErrorInfo(info, event, module, errorDesc);
286         if (ops->ops.Dump == NULL && ops->ops.Reset == NULL) {
287             SaveBasicErrorInfo(GetFaultLogPath(), info);
288             break;
289         }
290         if (ops->ops.Dump != NULL) {
291             BBOX_PRINT_INFO("[%s] starts dumping data!\n", ops->ops.module);
292             ops->ops.Dump(dirName, info);
293             BBOX_PRINT_INFO("[%s] ends dumping data!\n", ops->ops.module);
294         }
295         if (ops->ops.Reset != NULL) {
296             BBOX_PRINT_INFO("[%s] starts resetting!\n", ops->ops.module);
297             ops->ops.Reset(info);
298             BBOX_PRINT_INFO("[%s] ends resetting!\n", ops->ops.module);
299         }
300         findModule = 1;
301         break;
302     }
303     if (needSysReset == 0) {
304         (void)LOS_SemPost(g_opsListSem);
305     }
306 
307 __out:
308     if (info != NULL) {
309         free(info);
310     }
311     if (needSysReset != 0 && findModule != 0) {
312         RebootSystem();
313     }
314 
315     return 0;
316 }
317 
BBoxInit(void)318 static void BBoxInit(void)
319 {
320     int ret = -1;
321     pthread_t taskId = 0;
322 
323     if (LOS_BinarySemCreate(1, &g_opsListSem) != LOS_OK) {
324         BBOX_PRINT_ERR("Create binary semaphore failed!\n");
325         return;
326     }
327     UtilsListInit(&g_opsList);
328     ret = pthread_create(&taskId, NULL, SaveErrorLog, NULL);
329     if (ret != 0) {
330         BBOX_PRINT_ERR("Falied to create SaveErrorLog task, ret: %d\n", ret);
331     }
332 }
333 CORE_INIT_PRI(BBoxInit, 1);