diff --git a/Kconfig b/Kconfig index 8bce9860..491abbe2 100644 --- a/Kconfig +++ b/Kconfig @@ -61,6 +61,8 @@ source "../../kernel/liteos_a/arch/Kconfig" source "../../kernel/liteos_a/kernel/common/Kconfig" ######################### config options of patchfs ##################### source "../../kernel/liteos_a/kernel/common/patchfs/Kconfig" +######################### config options of blackbox ##################### +source "../../kernel/liteos_a/kernel/common/blackbox/Kconfig" config QUICK_START bool "Enable QUICK_START" @@ -175,7 +177,7 @@ config PLATFORM_DVFS config SAVE_EXCINFO bool "Enable Saving Exception Information" - default n + default y if BLACKBOX help Answer Y to enable LiteOS support saving exception information to storage medium. diff --git a/arch/arm/arm/src/los_exc.c b/arch/arm/arm/src/los_exc.c index d944caaf..06bbdb39 100644 --- a/arch/arm/arm/src/los_exc.c +++ b/arch/arm/arm/src/los_exc.c @@ -62,6 +62,9 @@ #ifdef LOSCFG_FS_VFS #include "console.h" #endif +#ifdef LOSCFG_BLACKBOX +#include "los_blackbox.h" +#endif #define INVALID_CPUID 0xFFFF @@ -589,6 +592,9 @@ STATIC VOID OsUserExcHandle(ExcContext *excBufAddr) /* Exception handling All operations should be kept prior to that operation */ OsExcRestore(); /* kill user exc process */ +#ifdef LOSCFG_BLACKBOX + BBoxNotifyError("USER_CRASH", MODULE_SYSTEM, "Crash in user", 0); +#endif LOS_Exit(OS_PRO_EXIT_OK); } @@ -1058,6 +1064,9 @@ LITE_OS_SEC_TEXT VOID STATIC OsExcPriorDisposal(ExcContext *excBufAddr) LITE_OS_SEC_TEXT_INIT STATIC VOID OsPrintExcHead(UINT32 far) { +#ifdef LOSCFG_BLACKBOX + SetExcInfoIndex(0); +#endif #ifdef LOSCFG_KERNEL_VM /* You are not allowed to add any other print information before this exception information */ if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) { @@ -1125,7 +1134,9 @@ LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAd if (g_curNestCount[ArchCurrCpuid()] == 1) { #ifdef LOSCFG_SAVE_EXCINFO if (func != NULL) { +#ifndef LOSCFG_BLACKBOX SetExcInfoIndex(0); +#endif OsSysStateSave(&intCount, &lockCount); OsRecordExcInfoTime(); OsSysStateRestore(intCount, lockCount); @@ -1154,6 +1165,9 @@ LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAd } #endif +#ifdef LOSCFG_BLACKBOX + BBoxNotifyError(EVENT_PANIC, MODULE_SYSTEM, "Crash in kernel", 1); +#endif while (1) {} } diff --git a/kernel/base/misc/task_shellcmd.c b/kernel/base/misc/task_shellcmd.c index 05623a56..9b0d678e 100644 --- a/kernel/base/misc/task_shellcmd.c +++ b/kernel/base/misc/task_shellcmd.c @@ -85,12 +85,18 @@ STATIC UINT32 *taskWaterLine = NULL; #define OS_TASK_ALL_INFO_LEN (g_taskMaxNum * (sizeof(LosTaskCB) + sizeof(UINT32))) #ifdef LOSCFG_FS_VFS +#ifdef LOSCFG_BLACKBOX +#define SaveExcInfo(arg, ...) WriteExcInfoToBuf(arg, ##__VA_ARGS__) +#else +#define SaveExcInfo(arg, ...) +#endif #define PROCESS_INFO_SHOW(seqBuf, arg...) do { \ if (seqBuf != NULL) { \ (void)LosBufPrintf((struct SeqBuf *)seqBuf, ##arg); \ } else { \ PRINTK(arg); \ } \ + SaveExcInfo(arg); \ } while (0) #else #define PROCESS_INFO_SHOW(seqBuf, arg...) PRINTK(arg) diff --git a/kernel/common/blackbox/Kconfig b/kernel/common/blackbox/Kconfig new file mode 100644 index 00000000..0c1e4f07 --- /dev/null +++ b/kernel/common/blackbox/Kconfig @@ -0,0 +1,11 @@ +config BLACKBOX + bool "Enable BlackBox" + default y + help + Answer Y to enable LiteOS support blackbox + +config LOG_ROOT_PATH + string + default "/storage/data/log" if BLACKBOX + help + define the default log path of blackbox \ No newline at end of file diff --git a/kernel/common/blackbox/Makefile b/kernel/common/blackbox/Makefile new file mode 100644 index 00000000..e67f8794 --- /dev/null +++ b/kernel/common/blackbox/Makefile @@ -0,0 +1,14 @@ +include $(LITEOSTOPDIR)/config.mk + +MODULE_NAME := $(notdir $(shell pwd)) + +LOCAL_SRCS := $(wildcard *.c) + +LOCAL_INCLUDE := \ + -I $(LITEOSTOPDIR)/kernel/common \ + -I $(LITEOSTOPDIR)/kernel/common/blackbox \ + -I $(LITEOSTOPDIR)/syscall \ + +LOCAL_FLAGS := $(LOCAL_INCLUDE) $(LITEOS_GCOV_OPTS) + +include $(MODULE) diff --git a/kernel/common/blackbox/los_blackbox.h b/kernel/common/blackbox/los_blackbox.h new file mode 100644 index 00000000..b60460ca --- /dev/null +++ b/kernel/common/blackbox/los_blackbox.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + +#ifndef LOS_BLACKBOX_H +#define LOS_BLACKBOX_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifndef __user +#define __user +#endif + +#include "stdarg.h" +#include "los_typedef.h" + +#define PATH_MAX_LEN 256 +#define EVENT_MAX_LEN 32 +#define MODULE_MAX_LEN 32 +#define ERROR_DESC_MAX_LEN 512 +#ifndef LOSCFG_LOG_ROOT_PATH +#define LOSCFG_LOG_ROOT_PATH "/storage/data/log" +#endif +#define KERNEL_FAULT_LOG_PATH LOSCFG_LOG_ROOT_PATH "/kernel_fault.log" +#define USER_FAULT_LOG_PATH LOSCFG_LOG_ROOT_PATH "/user_fault.log" + +#define MODULE_SYSTEM "SYSTEM" +#define EVENT_SYSREBOOT "SYSREBOOT" +#define EVENT_LONGPRESS "LONGPRESS" +#define EVENT_COMBINATIONKEY "COMBINATIONKEY" +#define EVENT_SUBSYSREBOOT "SUBSYSREBOOT" +#define EVENT_POWEROFF "POWEROFF" +#define EVENT_PANIC "PANIC" +#define EVENT_SYS_WATCHDOG "SYSWATCHDOG" +#define EVENT_HUNGTASK "HUNGTASK" +#define EVENT_BOOTFAIL "BOOTFAIL" + +struct ErrorInfo { + char event[EVENT_MAX_LEN]; + char module[MODULE_MAX_LEN]; + char errorDesc[ERROR_DESC_MAX_LEN]; +}; + +struct ModuleOps { + char module[MODULE_MAX_LEN]; + void (*Dump)(const char *logDir, struct ErrorInfo *info); + void (*Reset)(struct ErrorInfo *info); + int (*GetLastLogInfo)(struct ErrorInfo *info); + int (*SaveLastLog)(const char *logDir, struct ErrorInfo *info); +}; + +int BBoxRegisterModuleOps(struct ModuleOps *ops); +int BBoxNotifyError(const char event[EVENT_MAX_LEN], + const char module[MODULE_MAX_LEN], + const char errorDesc[ERROR_DESC_MAX_LEN], + int needSysReset); +int OsBBoxDriverInit(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/kernel/common/blackbox/los_blackbox_common.c b/kernel/common/blackbox/los_blackbox_common.c new file mode 100644 index 00000000..074f7e7d --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_common.c @@ -0,0 +1,101 @@ +/* + * 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_common.h" +#ifdef LOSCFG_LIB_LIBC +#include "stdlib.h" +#include "unistd.h" +#endif +#include "fs/fs.h" +#include "securec.h" +#include "los_memory.h" + +/* ------------ local macroes ------------ */ +/* ------------ local prototypes ------------ */ +/* ------------ local function declarations ------------ */ +/* ------------ global function declarations ------------ */ +/* ------------ local variables ------------ */ +/* ------------ function definitions ------------ */ +int FullWriteFile(const char *filePath, const char *buf, size_t bufSize, int isAppend) +{ + int fd; + int totalToWrite = (int)bufSize; + int totalWrite = 0; + + if (filePath == NULL || buf == NULL || bufSize == 0) { + BBOX_PRINT_ERR("filePath: %p, buf: %p, bufSize: %lu!\n", filePath, buf, bufSize); + return -1; + } + + fd = open(filePath, O_CREAT | O_RDWR | (isAppend ? O_APPEND : O_TRUNC), 0644); + if (fd < 0) { + BBOX_PRINT_ERR("Create file [%s] failed, fd: %d!\n", filePath, fd); + return -1; + } + while (totalToWrite > 0) { + int writeThisTime = write(fd, buf, totalToWrite); + if (writeThisTime < 0) { + BBOX_PRINT_ERR("Failed to write file [%s]!\n", filePath); + (void)close(fd); + return -1; + } + buf += writeThisTime; + totalToWrite -= writeThisTime; + totalWrite += writeThisTime; + } + (void)close(fd); + + return (totalWrite == (int)bufSize) ? 0 : -1; +} + +int SaveBasicErrorInfo(const char *filePath, struct ErrorInfo *info) +{ + char *buf; + + if (filePath == NULL || info == NULL) { + BBOX_PRINT_ERR("filePath: %p, event: %p!\n", filePath, info); + return -1; + } + + buf = LOS_MemAlloc(m_aucSysMem1, ERROR_INFO_MAX_LEN); + if (buf == NULL) { + BBOX_PRINT_ERR("LOS_MemAlloc failed!\n"); + return -1; + } + (void)memset_s(buf, ERROR_INFO_MAX_LEN, 0, ERROR_INFO_MAX_LEN); + (void)snprintf_s(buf, ERROR_INFO_MAX_LEN, ERROR_INFO_MAX_LEN - 1, + ERROR_INFO_HEADER ERROR_INFO_HEADER_FORMAT, info->event, info->module, info->errorDesc); + *(buf + ERROR_INFO_MAX_LEN - 1) = '\0'; + (void)FullWriteFile(filePath, buf, strlen(buf), 0); + (void)LOS_MemFree(m_aucSysMem1, buf); + + return 0; +} \ No newline at end of file diff --git a/kernel/common/blackbox/los_blackbox_common.h b/kernel/common/blackbox/los_blackbox_common.h new file mode 100644 index 00000000..b6e76e9d --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_common.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef LOS_BLACKBOX_COMMON_H +#define LOS_BLACKBOX_COMMON_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifndef __user +#define __user +#endif + +#include "los_blackbox.h" +#include "los_printf.h" +#include "los_typedef.h" + +#define ERROR_INFO_HEADER "#### error info ####\n" +#define ERROR_INFO_HEADER_FORMAT "event: %s\nmodule: %s\nerrorDesc: %s\n" +#define ERROR_INFO_MAX_LEN 768 +#define Min(a, b) (((a) > (b)) ? (b) : (a)) +#define BBOX_PRINT_ERR(format, ...) PRINTK("bbox: func: %s, line: %d, Err: " \ + format, __func__, __LINE__, ##__VA_ARGS__) +#define BBOX_PRINT_INFO(format, ...) PRINTK("bbox: Info: " format, ##__VA_ARGS__) + +int FullWriteFile(const char *filePath, const char *buf, size_t bufSize, int isAppend); +int SaveBasicErrorInfo(const char *filePath, struct ErrorInfo *info); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/kernel/common/blackbox/los_blackbox_core.c b/kernel/common/blackbox/los_blackbox_core.c new file mode 100644 index 00000000..64199683 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_core.c @@ -0,0 +1,454 @@ +/* + * 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.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" +#include "los_excinfo_pri.h" +#include "los_hw.h" +#include "los_init.h" +#include "los_memory.h" +#include "los_sem.h" +#include "los_syscall.h" +#include "securec.h" +#include "sys/reboot.h" + +/* ------------ local macroes ------------ */ +#define LOG_WAIT_TIMES 10 +#define LOG_PART_WAIT_TIME 1000 + +/* ------------ local prototypes ------------ */ +typedef struct BBoxOps { + LOS_DL_LIST opsList; + struct ModuleOps ops; +} BBoxOps; + +/* ------------ local function declarations ------------ */ +/* ------------ global function declarations ------------ */ +/* ------------ local variables ------------ */ +static UINT32 g_opsListSem = 0; +static UINT32 g_tempErrInfoSem = 0; +static LOS_DL_LIST_HEAD(g_opsList); +struct ErrorInfo *g_tempErrInfo; + +/* ------------ function definitions ------------ */ +static void FormatErrorInfo(struct ErrorInfo *info, + const char event[EVENT_MAX_LEN], + const char module[MODULE_MAX_LEN], + const char errorDesc[ERROR_DESC_MAX_LEN]) +{ + if (info == NULL || event == NULL || module == NULL || errorDesc == NULL) { + BBOX_PRINT_ERR("info: %p, event: %p, module: %p, errorDesc: %p!\n", info, event, module, errorDesc); + return; + } + + (void)memset_s(info, sizeof(*info), 0, sizeof(*info)); + (void)strncpy_s(info->event, sizeof(info->event), event, Min(strlen(event), sizeof(info->event) - 1)); + info->event[sizeof(info->event) - 1] = '\0'; + (void)strncpy_s(info->module, sizeof(info->module), module, Min(strlen(module), sizeof(info->module) - 1)); + info->module[sizeof(info->module) - 1] = '\0'; + (void)strncpy_s(info->errorDesc, sizeof(info->errorDesc), errorDesc, + Min(strlen(errorDesc), sizeof(info->errorDesc) - 1)); + info->errorDesc[sizeof(info->errorDesc) - 1] = '\0'; +} + +#ifdef LOSCFG_FS_VFS +static bool IsLogPartReady(void) +{ + return access(LOSCFG_LOG_ROOT_PATH, 0) == 0; +} + +static void WaitForLogPart(void) +{ + BBOX_PRINT_INFO("wait for log part [%s] begin!\n", LOSCFG_LOG_ROOT_PATH); + while (!IsLogPartReady()) { + LOS_Msleep(LOG_PART_WAIT_TIME); + } + BBOX_PRINT_INFO("wait for log part [%s] end!\n", LOSCFG_LOG_ROOT_PATH); +} +#else +static bool IsLogPartReady(void) +{ + return TRUE; +} + +static void WaitForLogPart(void) +{ + int i = 0; + + BBOX_PRINT_INFO("wait for log part [%s] begin!\n", LOSCFG_LOG_ROOT_PATH); + while (i++ < LOG_WAIT_TIMES) { + LOS_Msleep(LOG_PART_WAIT_TIME); + } + BBOX_PRINT_INFO("wait for log part [%s] end!\n", LOSCFG_LOG_ROOT_PATH); +} +#endif + +static bool FindModuleOps(struct ErrorInfo *info, BBoxOps **ops) +{ + bool found = false; + + if (info == NULL || ops == NULL) { + BBOX_PRINT_ERR("info: %p, ops: %p!\n", info, ops); + return found; + } + + LOS_DL_LIST_FOR_EACH_ENTRY(*ops, &g_opsList, BBoxOps, opsList) { + if (*ops != NULL && strcmp((*ops)->ops.module, info->module) == 0) { + found = true; + break; + } + } + if (!found) { + BBOX_PRINT_ERR("[%s] hasn't been registered!\n", info->module); + } + + return found; +} + +static void InvokeModuleOps(struct ErrorInfo *info, BBoxOps *ops) +{ + if (info == NULL || ops == NULL) { + BBOX_PRINT_ERR("info: %p, ops: %p!\n", info, ops); + return; + } + + if (ops->ops.Dump != NULL) { + BBOX_PRINT_INFO("[%s] starts dumping log!\n", ops->ops.module); + ops->ops.Dump(LOSCFG_LOG_ROOT_PATH, info); + BBOX_PRINT_INFO("[%s] ends dumping log!\n", ops->ops.module); + } + if (ops->ops.Reset != NULL) { + BBOX_PRINT_INFO("[%s] starts resetting!\n", ops->ops.module); + ops->ops.Reset(info); + BBOX_PRINT_INFO("[%s] ends resetting!\n", ops->ops.module); + } +} + +static void SaveLastLog(const char *logDir) +{ + struct ErrorInfo *info; + BBoxOps *ops; + + info = LOS_MemAlloc(m_aucSysMem1, sizeof(*info)); + if (info == NULL) { + BBOX_PRINT_ERR("LOS_MemAlloc failed!\n"); + return; + } + + if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != LOS_OK) { + BBOX_PRINT_ERR("Request g_opsListSem failed!\n"); + (void)LOS_MemFree(m_aucSysMem1, info); + return; + } + + LOS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, BBoxOps, opsList) { + if (ops == NULL) { + BBOX_PRINT_ERR("ops: NULL, please check it!\n"); + continue; + } + if (ops->ops.GetLastLogInfo != NULL && ops->ops.SaveLastLog != NULL) { + (void)memset_s(info, sizeof(*info), 0, sizeof(*info)); + if (ops->ops.GetLastLogInfo(info) != 0) { + BBOX_PRINT_ERR("[%s] failed to get log info!\n", ops->ops.module); + continue; + } + BBOX_PRINT_INFO("[%s] starts saving log!\n", ops->ops.module); + if (ops->ops.SaveLastLog(logDir, info) != 0) { + BBOX_PRINT_ERR("[%s] failed to save log!\n", ops->ops.module); + } else { + BBOX_PRINT_INFO("[%s] ends saving log!\n", ops->ops.module); + BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event); +#ifdef LOSCFG_FS_VFS + (void)UploadEventByFile(KERNEL_FAULT_LOG_PATH); +#else + BBOX_PRINT_INFO("LOSCFG_FS_VFS isn't defined!\n"); +#endif + BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event); + } + } else { + BBOX_PRINT_ERR("module [%s], GetLastLogInfo: %p, SaveLastLog: %p!\n", + ops->ops.module, ops->ops.GetLastLogInfo, ops->ops.SaveLastLog); + } + } + (void)LOS_SemPost(g_opsListSem); + (void)LOS_MemFree(m_aucSysMem1, info); +} + +static void SaveLogWithoutReset(struct ErrorInfo *info) +{ + BBoxOps *ops; + + if (info == NULL) { + BBOX_PRINT_ERR("info: %p!\n", info); + return; + } + + if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != LOS_OK) { + BBOX_PRINT_ERR("Request g_opsListSem failed!\n"); + return; + } + if (!FindModuleOps(info, &ops)) { + (void)LOS_SemPost(g_opsListSem); + return; + } + if (ops->ops.Dump == NULL && ops->ops.Reset == NULL) { + (void)LOS_SemPost(g_opsListSem); + if (SaveBasicErrorInfo(USER_FAULT_LOG_PATH, info) == 0) { + BBOX_PRINT_INFO("[%s] starts uploading event [%s]\n", info->module, info->event); +#ifdef LOSCFG_FS_VFS + (void)UploadEventByFile(USER_FAULT_LOG_PATH); +#else + BBOX_PRINT_INFO("LOSCFG_FS_VFS isn't defined!\n"); +#endif + BBOX_PRINT_INFO("[%s] ends uploading event [%s]\n", info->module, info->event); + } + return; + } + InvokeModuleOps(info, ops); + (void)LOS_SemPost(g_opsListSem); +} + +static void SaveTempErrorLog(void) +{ + if (LOS_SemPend(g_tempErrInfoSem, LOS_WAIT_FOREVER) != LOS_OK) { + BBOX_PRINT_ERR("Request g_tempErrInfoSem failed!\n"); + return; + } + if (g_tempErrInfo == NULL) { + BBOX_PRINT_ERR("g_tempErrInfo: %p!\n", g_tempErrInfo); + (void)LOS_SemPost(g_tempErrInfoSem); + return; + } + if (strlen(g_tempErrInfo->event) != 0) { + SaveLogWithoutReset(g_tempErrInfo); + } + (void)LOS_MemFree(m_aucSysMem1, g_tempErrInfo); + g_tempErrInfo = NULL; + (void)LOS_SemPost(g_tempErrInfoSem); +} + +static void SaveLogWithReset(struct ErrorInfo *info) +{ + int ret; + BBoxOps *ops; + + if (info == NULL) { + BBOX_PRINT_ERR("info: %p!\n", info); + return; + } + + if (!FindModuleOps(info, &ops)) { + return; + } + InvokeModuleOps(info, ops); + ret = SysReboot(0, 0, RB_AUTOBOOT); + BBOX_PRINT_INFO("SysReboot, ret: %d\n", ret); +} + +static void SaveTempErrorInfo(const char event[EVENT_MAX_LEN], + const char module[MODULE_MAX_LEN], + const char errorDesc[ERROR_DESC_MAX_LEN]) +{ + if (event == NULL || module == NULL || errorDesc == NULL) { + BBOX_PRINT_ERR("event: %p, module: %p, errorDesc: %p!\n", event, module, errorDesc); + return; + } + if (LOS_SemPend(g_tempErrInfoSem, LOS_WAIT_FOREVER) != LOS_OK) { + BBOX_PRINT_ERR("Request g_tempErrInfoSem failed!\n"); + return; + } + FormatErrorInfo(g_tempErrInfo, event, module, errorDesc); + (void)LOS_SemPost(g_tempErrInfoSem); +} + +static int SaveErrorLog(UINTPTR uwParam1, UINTPTR uwParam2, UINTPTR uwParam3, UINTPTR uwParam4) +{ + const char *logDir = (const char *)uwParam1; + (void)uwParam2; + (void)uwParam3; + (void)uwParam4; + +#ifdef LOSCFG_FS_VFS + WaitForLogPart(); +#endif + SaveLastLog(logDir); + SaveTempErrorLog(); + + return 0; +} + +#ifdef LOSCFG_BLACKBOX_DEBUG +static void PrintModuleOps(void) +{ + struct BBoxOps *ops; + + BBOX_PRINT_INFO("The following modules have been registered!\n"); + LOS_DL_LIST_FOR_EACH_ENTRY(ops, &g_opsList, BBoxOps, opsList) { + if (ops == NULL) { + continue; + } + BBOX_PRINT_INFO("module: %s, Dump: %p, Reset: %p, GetLastLogInfo: %p, SaveLastLog: %p\n", + ops->ops.module, ops->ops.Dump, ops->ops.Reset, ops->ops.GetLastLogInfo, ops->ops.SaveLastLog); + } +} +#endif + +int BBoxRegisterModuleOps(struct ModuleOps *ops) +{ + BBoxOps *newOps; + BBoxOps *temp; + + if (ops == NULL) { + BBOX_PRINT_ERR("ops: %p!\n", ops); + return -1; + } + + newOps = LOS_MemAlloc(m_aucSysMem1, sizeof(*newOps)); + if (newOps == NULL) { + BBOX_PRINT_ERR("LOS_MemAlloc failed!\n"); + return -1; + } + (void)memset_s(newOps, sizeof(*newOps), 0, sizeof(*newOps)); + (void)memcpy_s(&newOps->ops, sizeof(newOps->ops), ops, sizeof(*ops)); + if (LOS_SemPend(g_opsListSem, LOS_WAIT_FOREVER) != LOS_OK) { + BBOX_PRINT_ERR("Request g_opsListSem failed!\n"); + (void)LOS_MemFree(m_aucSysMem1, newOps); + return -1; + } + if (LOS_ListEmpty(&g_opsList)) { + goto __out; + } + + LOS_DL_LIST_FOR_EACH_ENTRY(temp, &g_opsList, BBoxOps, opsList) { + if (temp == NULL) { + continue; + } + if (strcmp(temp->ops.module, ops->module) == 0) { + BBOX_PRINT_ERR("module [%s] has been registered!\n", ops->module); + (void)LOS_SemPost(g_opsListSem); + (void)LOS_MemFree(m_aucSysMem1, newOps); + return -1; + } + } + +__out: + LOS_ListTailInsert(&g_opsList, &newOps->opsList); + (void)LOS_SemPost(g_opsListSem); + BBOX_PRINT_INFO("module [%s] is registered successfully!\n", ops->module); +#ifdef LOSCFG_BLACKBOX_DEBUG + PrintModuleOps(); +#endif + + return 0; +} + +int BBoxNotifyError(const char event[EVENT_MAX_LEN], + const char module[MODULE_MAX_LEN], + const char errorDesc[ERROR_DESC_MAX_LEN], + int needSysReset) +{ + struct ErrorInfo *info; + + if (event == NULL || module == NULL || errorDesc == NULL) { + BBOX_PRINT_ERR("event: %p, module: %p, errorDesc: %p!\n", event, module, errorDesc); + return -1; + } + info = LOS_MemAlloc(m_aucSysMem1, sizeof(*info)); + if (info == NULL) { + BBOX_PRINT_ERR("LOS_MemAlloc failed!\n"); + return -1; + } + FormatErrorInfo(info, event, module, errorDesc); + if (needSysReset == 0) { + if (!IsLogPartReady()) { + SaveTempErrorInfo(event, module, errorDesc); + } else { + SaveLogWithoutReset(info); + } + } else { + SaveLogWithReset(info); + } + (void)LOS_MemFree(m_aucSysMem1, info); + + return 0; +} + +int OsBBoxDriverInit(void) +{ + UINT32 taskID; + TSK_INIT_PARAM_S taskParam; + + if (LOS_BinarySemCreate(1, &g_opsListSem) != LOS_OK) { + BBOX_PRINT_ERR("Create g_opsListSem failed!\n"); + return -1; + } + if (LOS_BinarySemCreate(1, &g_tempErrInfoSem) != LOS_OK) { + BBOX_PRINT_ERR("Create g_tempErrInfoSem failed!\n"); + goto __err; + } + LOS_ListInit(&g_opsList); + g_tempErrInfo = LOS_MemAlloc(m_aucSysMem1, sizeof(*g_tempErrInfo)); + if (g_tempErrInfo == NULL) { + BBOX_PRINT_ERR("LOS_MemAlloc failed!\n"); + goto __err; + } + (void)memset_s(g_tempErrInfo, sizeof(*g_tempErrInfo), 0, sizeof(*g_tempErrInfo)); + (void)memset_s(&taskParam, sizeof(taskParam), 0, sizeof(taskParam)); + taskParam.auwArgs[0] = (UINTPTR)LOSCFG_LOG_ROOT_PATH; + taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SaveErrorLog; + taskParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + taskParam.pcName = "SaveErrorLog"; + taskParam.usTaskPrio = LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO; + taskParam.uwResved = LOS_TASK_STATUS_DETACHED; +#ifdef LOSCFG_KERNEL_SMP + taskParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid()); +#endif + (void)LOS_TaskCreate(&taskID, &taskParam); + return 0; + +__err: + if (g_opsListSem != 0) { + (void)LOS_SemDelete(g_opsListSem); + } + if (g_tempErrInfoSem != 0) { + (void)LOS_SemDelete(g_tempErrInfoSem); + } + + return -1; +} +LOS_MODULE_INIT(OsBBoxDriverInit, LOS_INIT_LEVEL_ARCH); \ No newline at end of file diff --git a/kernel/common/blackbox/los_blackbox_detector.c b/kernel/common/blackbox/los_blackbox_detector.c new file mode 100644 index 00000000..5d91ef9d --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_detector.c @@ -0,0 +1,63 @@ +/* + * 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_detector.h" +#include "los_blackbox_common.h" +#ifdef LOSCFG_LIB_LIBC +#include "stdlib.h" +#include "unistd.h" +#endif + +/* ------------ local macroes ------------ */ +/* ------------ local prototypes ------------ */ +/* ------------ local function declarations ------------ */ +/* ------------ global function declarations ------------ */ +/* ------------ local variables ------------ */ +/* ------------ function definitions ------------ */ +int UploadEventByFile(const char *filePath) +{ + if (filePath == NULL) { + BBOX_PRINT_ERR("filePath: %p\n", filePath); + return -1; + } + + return 0; +} + +int UploadEventByStream(const char *buf, size_t bufSize) +{ + if (buf == NULL || bufSize == 0) { + BBOX_PRINT_ERR("buf: %p, bufSize: %u\n", buf, (UINT32)bufSize); + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/kernel/common/blackbox/los_blackbox_detector.h b/kernel/common/blackbox/los_blackbox_detector.h new file mode 100644 index 00000000..a424f7a6 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_detector.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef LOS_BLACKBOX_DETECTOR_H +#define LOS_BLACKBOX_DETECTOR_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifndef __user +#define __user +#endif + +#include "los_typedef.h" + +int UploadEventByFile(const char *filePath); +int UploadEventByStream(const char *buf, size_t bufSize); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/kernel/common/blackbox/los_blackbox_system_adapter.c b/kernel/common/blackbox/los_blackbox_system_adapter.c new file mode 100644 index 00000000..11a85907 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_system_adapter.c @@ -0,0 +1,247 @@ +/* + * 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" +#include "los_excinfo_pri.h" +#include "los_hw.h" +#include "los_init.h" +#include "los_memory.h" +#include "los_vm_phys.h" +#include "fs/fs.h" +#include "securec.h" + +/* ------------ local macroes ------------ */ +#define MEM_OVERLAP_COUNT 50 +#define LOG_FLAG "GOODLOG" +#define FAULT_LOG_SIZE 0x4000 /* 16KB */ + +/* ------------ 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); +} + +static void WriteExcFile(UINT32 startAddr, UINT32 space, UINT32 rwFlag, char *buf) +{ + (void)startAddr; + (void)space; + (void)rwFlag; + (void)buf; +} + +static void RegisterExcInfoHook(void) +{ + if (g_logBuffer != NULL) { + LOS_ExcInfoRegHook(0, FAULT_LOG_SIZE - sizeof(struct FaultLogInfo), + g_logBuffer + sizeof(struct FaultLogInfo), WriteExcFile); + } else { + BBOX_PRINT_ERR("Alloc mem failed!\n"); + } +} + +static INT32 AllocLogBuffer(void) +{ + INT32 i; + size_t nPages = ROUNDUP(FAULT_LOG_SIZE, PAGE_SIZE) >> PAGE_SHIFT; + void *tempBuffer[MEM_OVERLAP_COUNT]; + + for (i = 0; i < MEM_OVERLAP_COUNT; i++) { + g_logBuffer = LOS_PhysPagesAllocContiguous(nPages); + tempBuffer[i] = g_logBuffer; + } + for (i = 0; i < MEM_OVERLAP_COUNT - 1; i++) { + LOS_PhysPagesFreeContiguous(tempBuffer[i], nPages); + } + + return (g_logBuffer != NULL) ? 0 : -1; +} + +static void Dump(const char *logDir, struct ErrorInfo *info) +{ + struct FaultLogInfo *pInfo; + + 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: %p!\n", g_logBuffer); + return; + } + + if (strcmp(info->event, EVENT_PANIC) == 0) { + pInfo = (struct FaultLogInfo *)g_logBuffer; + (void)memset_s(pInfo, sizeof(*pInfo), 0, sizeof(*pInfo)); + pInfo->len = GetExcInfoLen(); + (void)memcpy_s(&pInfo->flag, sizeof(pInfo->flag), LOG_FLAG, strlen(LOG_FLAG)); + (void)memcpy_s(&pInfo->info, sizeof(pInfo->info), info, sizeof(*info)); + DCacheFlushRange((UINTPTR)g_logBuffer, (UINTPTR)(g_logBuffer + FAULT_LOG_SIZE)); + } else { + SaveFaultLog(USER_FAULT_LOG_PATH, g_logBuffer + sizeof(struct FaultLogInfo), + Min(FAULT_LOG_SIZE - sizeof(struct FaultLogInfo), GetExcInfoLen()), info); + } +} + +static void Reset(struct ErrorInfo *info) +{ + if (info == NULL) { + BBOX_PRINT_ERR("info: %p!\n", info); + 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 *pInfo; + + if (info == NULL) { + BBOX_PRINT_ERR("info: %p!\n", info); + return -1; + } + if (g_logBuffer == NULL) { + BBOX_PRINT_ERR("Alloc physical page failed!\n"); + return -1; + } + + pInfo = (struct FaultLogInfo *)g_logBuffer; + if (memcmp(pInfo->flag, LOG_FLAG, strlen(LOG_FLAG)) == 0) { + (void)memcpy_s(info, sizeof(*info), &pInfo->info, sizeof(pInfo->info)); + return 0; + } + + return -1; +} + +static int SaveLastLog(const char *logDir, struct ErrorInfo *info) +{ +#ifdef LOSCFG_FS_VFS + struct FaultLogInfo *pInfo; + + if (logDir == NULL || info == NULL) { + BBOX_PRINT_ERR("logDir: %p, info: %p!\n", logDir, info); + return -1; + } + if (g_logBuffer == NULL) { + BBOX_PRINT_ERR("Alloc physical page failed!\n"); + return -1; + } + + pInfo = (struct FaultLogInfo *)g_logBuffer; + if (memcmp(pInfo->flag, LOG_FLAG, strlen(LOG_FLAG)) == 0) { + SaveFaultLog(KERNEL_FAULT_LOG_PATH, g_logBuffer + sizeof(*pInfo), + Min(FAULT_LOG_SIZE - sizeof(*pInfo), pInfo->len), info); + } +#endif + (void)memset_s(g_logBuffer, FAULT_LOG_SIZE, 0, FAULT_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; +} + +#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) { + BBOX_PRINT_INFO("g_logBuffer: %p for blackbox!\n", g_logBuffer); + RegisterExcInfoHook(); + if (BBoxRegisterModuleOps(&ops) != 0) { + BBOX_PRINT_ERR("BBoxRegisterModuleOps failed!\n"); + LOS_PhysPagesFreeContiguous(g_logBuffer, ROUNDUP(FAULT_LOG_SIZE, PAGE_SIZE) >> PAGE_SHIFT); + g_logBuffer = NULL; + return -1; + } + } else { + BBOX_PRINT_ERR("AllocLogBuffer failed!\n"); + } + +#ifdef LOSCFG_BLACKBOX_TEST + BBoxTest(); +#endif + + return 0; +} +LOS_MODULE_INIT(OsBBoxSystemAdapterInit, LOS_INIT_LEVEL_ARCH); \ No newline at end of file diff --git a/kernel/common/blackbox/los_blackbox_system_adapter.h b/kernel/common/blackbox/los_blackbox_system_adapter.h new file mode 100644 index 00000000..e4fbf2cc --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_system_adapter.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef LOS_BLACKBOX_SYSTEM_ADAPTER_H +#define LOS_BLACKBOX_SYSTEM_ADAPTER_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifndef __user +#define __user +#endif + +#include "los_blackbox.h" +#include "los_blackbox_common.h" + +int OsBBoxSystemAdapterInit(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/kernel/common/los_excinfo.c b/kernel/common/los_excinfo.c index b18ee23b..f605c186 100644 --- a/kernel/common/los_excinfo.c +++ b/kernel/common/los_excinfo.c @@ -34,13 +34,29 @@ #ifdef LOSCFG_SHELL #include "shcmd.h" #endif +#ifdef LOSCFG_BLACKBOX +#include "fs/fs.h" +#include "fs/fs_operation.h" +#endif + +#ifdef LOSCFG_BLACKBOX +#define TEMP_EXC_INFO_SIZE 0x400 +#endif #ifdef LOSCFG_SAVE_EXCINFO STATIC log_read_write_fn g_excInfoRW = NULL; /* the hook of read-writing exception information */ STATIC CHAR *g_excInfoBuf = NULL; /* pointer to the buffer for storing the exception information */ +#ifdef LOSCFG_BLACKBOX +STATIC UINT32 g_excInfoIndex = 0; /* the index of the buffer for storing the exception information */ +#else STATIC UINT32 g_excInfoIndex = 0xFFFFFFFF; /* the index of the buffer for storing the exception information */ +#endif STATIC UINT32 g_recordAddr = 0; /* the address of storing the exception information */ STATIC UINT32 g_recordSpace = 0; /* the size of storing the exception information */ +#ifdef LOSCFG_BLACKBOX +STATIC UINT32 g_excLogLen = 0; /* the length of the exception information */ +STATIC CHAR *g_tempExcInfoBuf = NULL; /* pointer to the buffer for storing the temp exception information */ +#endif VOID SetExcInfoRW(log_read_write_fn func) { @@ -65,6 +81,11 @@ CHAR *GetExcInfoBuf(VOID) VOID SetExcInfoIndex(UINT32 index) { g_excInfoIndex = index; +#ifdef LOSCFG_BLACKBOX + if (g_excInfoIndex == 0) { + g_excLogLen = 0; + } +#endif } UINT32 GetExcInfoIndex(VOID) @@ -72,6 +93,13 @@ UINT32 GetExcInfoIndex(VOID) return g_excInfoIndex; } +#ifdef LOSCFG_BLACKBOX +UINT32 GetExcInfoLen(VOID) +{ + return g_excLogLen; +} +#endif + VOID SetRecordAddr(UINT32 addr) { g_recordAddr = addr; @@ -92,8 +120,35 @@ UINT32 GetRecordSpace(VOID) return g_recordSpace; } +#ifdef LOSCFG_BLACKBOX +STATIC VOID SaveExcInfoUnsafe(CHAR *buf, INT32 size) +{ + for (INT32 i = 0; i < size; i++) { + *(g_excInfoBuf + g_excInfoIndex) = *(buf + i); + g_excInfoIndex++; + if (g_excLogLen < g_recordSpace) { + g_excLogLen++; + } + if (g_excInfoIndex >= g_recordSpace) { + g_excInfoIndex = 0; + } + } +} +#endif + VOID WriteExcBufVa(const CHAR *format, va_list arglist) { +#ifdef LOSCFG_BLACKBOX + if (g_tempExcInfoBuf != NULL) { + (VOID)memset_s(g_tempExcInfoBuf, TEMP_EXC_INFO_SIZE, 0, TEMP_EXC_INFO_SIZE); + INT32 ret = vsnprintf_s(g_tempExcInfoBuf, TEMP_EXC_INFO_SIZE, TEMP_EXC_INFO_SIZE - 1, format, arglist); + if (ret == -1) { + PRINT_ERR("g_tempExcInfoBuf is not enough or vsnprintf_s is error.\n"); + return; + } + SaveExcInfoUnsafe(g_tempExcInfoBuf, ret); + } +#else errno_t ret; if (g_recordSpace > g_excInfoIndex) { @@ -105,6 +160,7 @@ VOID WriteExcBufVa(const CHAR *format, va_list arglist) } g_excInfoIndex += ret; } +#endif } VOID WriteExcInfoToBuf(const CHAR *format, ...) @@ -131,6 +187,9 @@ VOID LOS_ExcInfoRegHook(UINT32 startAddr, UINT32 space, CHAR *buf, log_read_writ #ifdef LOSCFG_FS_VFS los_vfs_init(); #endif +#ifdef LOSCFG_BLACKBOX + g_tempExcInfoBuf = LOS_VMalloc(TEMP_EXC_INFO_SIZE); +#endif } /* Be called in the exception. */ diff --git a/kernel/common/los_excinfo_pri.h b/kernel/common/los_excinfo_pri.h index ba68d5f4..a30597d1 100644 --- a/kernel/common/los_excinfo_pri.h +++ b/kernel/common/los_excinfo_pri.h @@ -47,6 +47,9 @@ extern VOID SetExcInfoBuf(CHAR *buf); extern CHAR *GetExcInfoBuf(VOID); extern VOID SetExcInfoIndex(UINT32 index); extern UINT32 GetExcInfoIndex(VOID); +#ifdef LOSCFG_BLACKBOX +extern UINT32 GetExcInfoLen(VOID); +#endif extern VOID SetRecordAddr(UINT32 addr); extern UINT32 GetRecordAddr(VOID); extern VOID SetRecordSpace(UINT32 space); diff --git a/tools/build/mk/liteos_tables_ldflags.mk b/tools/build/mk/liteos_tables_ldflags.mk index dd670571..af5aa945 100644 --- a/tools/build/mk/liteos_tables_ldflags.mk +++ b/tools/build/mk/liteos_tables_ldflags.mk @@ -135,7 +135,9 @@ LITEOS_TABLES_KERNEL_INIT_LDFLAGS := \ -uOsCpupGuardCreator \ -uOsMpInit \ -uOsResourceFreeTaskCreate \ - -uOsSystemInit + -uOsSystemInit \ + -uOsBBoxSystemAdapterInit \ + -uOsBBoxDriverInit LITEOS_TABLES_DRIVER_LDFLAGS := \ -ui2c_init \ diff --git a/tools/build/mk/los_config.mk b/tools/build/mk/los_config.mk index 9c3923bd..ad304b7f 100644 --- a/tools/build/mk/los_config.mk +++ b/tools/build/mk/los_config.mk @@ -441,6 +441,12 @@ ifeq ($(LOSCFG_BASE_CORE_HILOG), y) LITEOS_HILOG_INCLUDE += -I $(LITEOSTOPDIR)/../../base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog LITEOS_CMACRO += -DLOSCFG_BASE_CORE_HILOG endif +ifeq ($(LOSCFG_BLACKBOX), y) + LITEOS_BASELIB += -lblackbox + LIB_SUBDIRS += $(LITEOSTOPDIR)/kernel/common/blackbox + LITEOS_BLACKBOX_INCLUDE += -I $(LITEOSTOPDIR)/kernel/common/blackbox + LITEOS_CMACRO += -DLOSCFG_BLACKBOX +endif ############################## Dfx Option End ####################################### ############################# Tools && Debug Option Begin ############################## @@ -637,7 +643,8 @@ LITEOS_DRIVERS_INCLUDE := $(LITEOS_CELLWISE_INCLUDE) $(LITEOS_GPIO_INCLUDE $(LITEOS_DRIVERS_HDF_INCLUDE) $(LITEOS_TZDRIVER_INCLUDE) \ $(LITEOS_HIEVENT_INCLUDE) $(LITEOS_DEV_MEM_INCLUDE) \ $(LITEOS_DEV_QUICKSTART_INCLUDE) -LITEOS_DFX_INCLUDE := $(LITEOS_HILOG_INCLUDE) +LITEOS_DFX_INCLUDE := $(LITEOS_HILOG_INCLUDE) \ + $(LITEOS_BLACKBOX_INCLUDE) LITEOS_SECURITY_INCLUDE := $(LITEOS_SECURITY_CAP_INC) $(LITEOS_SECURITY_VID_INC) LOSCFG_TOOLS_DEBUG_INCLUDE := $(LITEOS_SHELL_INCLUDE) $(LITEOS_UART_INCLUDE) \