/* * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* ------------ includes ------------ */ #include "los_blackbox_system_adapter.h" #include "los_blackbox_common.h" #include "los_blackbox_detector.h" #ifdef LOSCFG_LIB_LIBC #include "stdlib.h" #include "unistd.h" #endif #include "los_base.h" #include "los_config.h" #ifdef LOSCFG_SAVE_EXCINFO #include "los_excinfo_pri.h" #endif #include "los_hw.h" #include "los_init.h" #include "los_memory.h" #include "los_vm_common.h" #include "los_vm_phys.h" #include "los_vm_zone.h" #include "securec.h" /* ------------ local macroes ------------ */ #define LOG_FLAG "GOODLOG" /* ------------ local prototypes ------------ */ struct FaultLogInfo { char flag[8]; /* 8 is the length of the flag */ int len; /* length of the fault log saved by the module excinfo */ struct ErrorInfo info; }; /* ------------ local function declarations ------------ */ /* ------------ global function declarations ------------ */ /* ------------ local variables ------------ */ static char *g_logBuffer = NULL; /* ------------ function definitions ------------ */ static void SaveFaultLog(const char *filePath, const char *dataBuf, size_t bufSize, struct ErrorInfo *info) { (void)SaveBasicErrorInfo(filePath, info); (void)FullWriteFile(filePath, dataBuf, bufSize, 1); } #ifdef LOSCFG_SAVE_EXCINFO static void WriteExcFile(UINT32 startAddr, UINT32 space, UINT32 rwFlag, char *buf) { (void)startAddr; (void)space; (void)rwFlag; (void)buf; } #endif static void RegisterExcInfoHook(void) { if (g_logBuffer != NULL) { #ifdef LOSCFG_SAVE_EXCINFO LOS_ExcInfoRegHook(0, LOSCFG_BLACKBOX_LOG_SIZE - sizeof(struct FaultLogInfo), g_logBuffer + sizeof(struct FaultLogInfo), WriteExcFile); #endif } else { BBOX_PRINT_ERR("Alloc mem failed!\n"); } } static int AllocLogBuffer(void) { if (LOSCFG_BLACKBOX_LOG_SIZE < sizeof(struct FaultLogInfo)) { BBOX_PRINT_ERR("LOSCFG_BLACKBOX_LOG_SIZE [%d] is too short, it must be >= %u\n", LOSCFG_BLACKBOX_LOG_SIZE, sizeof(struct FaultLogInfo)); return -1; } /* * The physical memory pointed to by LOSCFG_BLACKBOX_RESERVE_MEM_ADDR is * exclusive to blackbox and cannot be occupied by other modules during * system running and cannot overlap with the memory area of other systems * during startup. */ g_logBuffer = (char *)MEM_CACHED_ADDR(LOSCFG_BLACKBOX_RESERVE_MEM_ADDR); BBOX_PRINT_INFO("g_logBuffer: %p, len: 0x%x for blackbox!\n", g_logBuffer, (UINT32)LOSCFG_BLACKBOX_LOG_SIZE); return (g_logBuffer != NULL) ? 0 : -1; } static void Dump(const char *logDir, struct ErrorInfo *info) { struct FaultLogInfo *pLogInfo = NULL; if (logDir == NULL || info == NULL) { BBOX_PRINT_ERR("logDir: %p, info: %p!\n", logDir, info); return; } if (g_logBuffer == NULL) { BBOX_PRINT_ERR("g_logBuffer is NULL, alloc physical pages failed!\n"); return; } if (strcmp(info->event, EVENT_PANIC) == 0) { pLogInfo = (struct FaultLogInfo *)g_logBuffer; (void)memset_s(pLogInfo, sizeof(*pLogInfo), 0, sizeof(*pLogInfo)); #ifdef LOSCFG_SAVE_EXCINFO pLogInfo->len = GetExcInfoIndex(); #else pLogInfo->len = 0; #endif (void)memcpy_s(&pLogInfo->flag, sizeof(pLogInfo->flag), LOG_FLAG, strlen(LOG_FLAG)); (void)memcpy_s(&pLogInfo->info, sizeof(pLogInfo->info), info, sizeof(*info)); DCacheFlushRange((UINTPTR)g_logBuffer, (UINTPTR)(g_logBuffer + LOSCFG_BLACKBOX_LOG_SIZE)); } else { #ifdef LOSCFG_SAVE_EXCINFO SaveFaultLog(USER_FAULT_LOG_PATH, g_logBuffer + sizeof(struct FaultLogInfo), Min(LOSCFG_BLACKBOX_LOG_SIZE - sizeof(struct FaultLogInfo), GetExcInfoIndex()), info); #else SaveFaultLog(USER_FAULT_LOG_PATH, g_logBuffer + sizeof(struct FaultLogInfo), 0, info); #endif } } static void Reset(struct ErrorInfo *info) { if (info == NULL) { BBOX_PRINT_ERR("info is NULL!\n"); return; } if (strcmp(info->event, EVENT_PANIC) != 0) { BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event); (void)UploadEventByFile(USER_FAULT_LOG_PATH); BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event); } } static int GetLastLogInfo(struct ErrorInfo *info) { struct FaultLogInfo *pLogInfo = NULL; if (info == NULL) { BBOX_PRINT_ERR("info is NULL!\n"); return -1; } if (g_logBuffer == NULL) { BBOX_PRINT_ERR("g_logBuffer is NULL, alloc physical pages failed!\n"); return -1; } pLogInfo = (struct FaultLogInfo *)g_logBuffer; if (memcmp(pLogInfo->flag, LOG_FLAG, strlen(LOG_FLAG)) == 0) { (void)memcpy_s(info, sizeof(*info), &pLogInfo->info, sizeof(pLogInfo->info)); return 0; } return -1; } static int SaveLastLog(const char *logDir, struct ErrorInfo *info) { #ifdef LOSCFG_FS_VFS struct FaultLogInfo *pLogInfo = NULL; if (logDir == NULL || info == NULL) { BBOX_PRINT_ERR("logDir: %p, info: %p!\n", logDir, info); return -1; } if (g_logBuffer == NULL) { BBOX_PRINT_ERR("g_logBuffer is NULL, alloc physical pages failed!\n"); return -1; } pLogInfo = (struct FaultLogInfo *)g_logBuffer; if (memcmp(pLogInfo->flag, LOG_FLAG, strlen(LOG_FLAG)) == 0) { SaveFaultLog(KERNEL_FAULT_LOG_PATH, g_logBuffer + sizeof(*pLogInfo), Min(LOSCFG_BLACKBOX_LOG_SIZE - sizeof(*pLogInfo), pLogInfo->len), info); } (void)memset_s(g_logBuffer, LOSCFG_BLACKBOX_LOG_SIZE, 0, LOSCFG_BLACKBOX_LOG_SIZE); BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event); (void)UploadEventByFile(KERNEL_FAULT_LOG_PATH); BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event); return 0; #else (VOID)logDir; (VOID)info; BBOX_PRINT_ERR("LOSCFG_FS_VFS isn't defined!\n"); return -1; #endif } #ifdef LOSCFG_BLACKBOX_TEST static void BBoxTest(void) { struct ModuleOps ops = { .module = "MODULE_TEST", .Dump = NULL, .Reset = NULL, .GetLastLogInfo = NULL, .SaveLastLog = NULL, }; if (BBoxRegisterModuleOps(&ops) != 0) { BBOX_PRINT_ERR("BBoxRegisterModuleOps failed!\n"); return; } BBoxNotifyError("EVENT_TEST1", "MODULE_TEST", "Test BBoxNotifyError111", 0); } #endif int OsBBoxSystemAdapterInit(void) { struct ModuleOps ops = { .module = MODULE_SYSTEM, .Dump = Dump, .Reset = Reset, .GetLastLogInfo = GetLastLogInfo, .SaveLastLog = SaveLastLog, }; /* allocate buffer for kmsg */ if (AllocLogBuffer() == 0) { RegisterExcInfoHook(); if (BBoxRegisterModuleOps(&ops) != 0) { BBOX_PRINT_ERR("BBoxRegisterModuleOps failed!\n"); g_logBuffer = NULL; return LOS_NOK; } } else { BBOX_PRINT_ERR("AllocLogBuffer failed!\n"); } #ifdef LOSCFG_BLACKBOX_TEST BBoxTest(); #endif return LOS_OK; } LOS_MODULE_INIT(OsBBoxSystemAdapterInit, LOS_INIT_LEVEL_PLATFORM);