From a195aac9fb60b0163f9eebb29084287d226bd14c Mon Sep 17 00:00:00 2001 From: qidechun Date: Fri, 9 Jul 2021 18:46:19 +0800 Subject: [PATCH] feat: add blackbox for liteos_a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、在内核增加BlackBox核心框架,对外提供模块回调接口注册和故障处理接口。 2、增加默认的系统模块适配层,处理通用内核态和用户态故障日志抓取和保存。 3、BBOX特性默认关闭,若想使用此特性,请在内核配置文件中增加如下编译选项: LOSCFG_BLACKBOX=y LOSCFG_SAVE_EXCINFO=y LOSCFG_SAVE_EXCINFO可以帮助抓取更多的故障日志。 4、若已经打开BBOX特性,想快速验证此特性,请添加如下编译选项: LOSCFG_HIDUMPER=y Close #I406NP Signed-off-by: qidechun --- Kconfig | 2 + arch/arm/arm/src/los_exc.c | 16 + kernel/base/misc/task_shellcmd.c | 6 + kernel/common/blackbox/Kconfig | 10 + kernel/common/blackbox/Makefile | 14 + kernel/common/blackbox/los_blackbox.h | 91 ++++ kernel/common/blackbox/los_blackbox_common.c | 127 +++++ kernel/common/blackbox/los_blackbox_common.h | 61 +++ kernel/common/blackbox/los_blackbox_core.c | 458 ++++++++++++++++++ .../common/blackbox/los_blackbox_detector.c | 63 +++ .../common/blackbox/los_blackbox_detector.h | 51 ++ .../blackbox/los_blackbox_system_adapter.c | 265 ++++++++++ .../blackbox/los_blackbox_system_adapter.h | 51 ++ kernel/common/los_excinfo.c | 4 + tools/build/mk/liteos_tables_ldflags.mk | 4 +- tools/build/mk/los_config.mk | 8 +- 16 files changed, 1229 insertions(+), 2 deletions(-) create mode 100644 kernel/common/blackbox/Kconfig create mode 100644 kernel/common/blackbox/Makefile create mode 100644 kernel/common/blackbox/los_blackbox.h create mode 100644 kernel/common/blackbox/los_blackbox_common.c create mode 100644 kernel/common/blackbox/los_blackbox_common.h create mode 100644 kernel/common/blackbox/los_blackbox_core.c create mode 100644 kernel/common/blackbox/los_blackbox_detector.c create mode 100644 kernel/common/blackbox/los_blackbox_detector.h create mode 100644 kernel/common/blackbox/los_blackbox_system_adapter.c create mode 100644 kernel/common/blackbox/los_blackbox_system_adapter.h diff --git a/Kconfig b/Kconfig index d8cbaa97..d9f60a40 100644 --- a/Kconfig +++ b/Kconfig @@ -61,6 +61,8 @@ source "arch/Kconfig" source "kernel/common/Kconfig" ######################### config options of patchfs ##################### source "kernel/common/patchfs/Kconfig" +######################### config options of blackbox ##################### +source "kernel/common/blackbox/Kconfig" config QUICK_START bool "Enable QUICK_START" diff --git a/arch/arm/arm/src/los_exc.c b/arch/arm/arm/src/los_exc.c index 2c05b21a..c90f591f 100644 --- a/arch/arm/arm/src/los_exc.c +++ b/arch/arm/arm/src/los_exc.c @@ -61,6 +61,9 @@ #ifdef LOSCFG_FS_VFS #include "console.h" #endif +#ifdef LOSCFG_BLACKBOX +#include "los_blackbox.h" +#endif #define INVALID_CPUID 0xFFFF @@ -568,6 +571,9 @@ STATIC VOID OsUserExcHandle(ExcContext *excBufAddr) #endif #endif +#ifdef LOSCFG_BLACKBOX + BBoxNotifyError("USER_CRASH", MODULE_SYSTEM, "Crash in user", 0); +#endif SCHEDULER_LOCK(intSave); #ifdef LOSCFG_SAVE_EXCINFO OsProcessExitCodeCoreDumpSet(runProcess); @@ -1057,6 +1063,11 @@ LITE_OS_SEC_TEXT VOID STATIC OsExcPriorDisposal(ExcContext *excBufAddr) LITE_OS_SEC_TEXT_INIT STATIC VOID OsPrintExcHead(UINT32 far) { +#ifdef LOSCFG_BLACKBOX +#ifdef LOSCFG_SAVE_EXCINFO + SetExcInfoIndex(0); +#endif +#endif #ifdef LOSCFG_KERNEL_VM /* You are not allowed to add any other print information before this exception information */ if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) { @@ -1124,7 +1135,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); @@ -1153,6 +1166,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..854e2d6c 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 +#if defined(LOSCFG_BLACKBOX) && defined(LOSCFG_SAVE_EXCINFO) +#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..8298b923 --- /dev/null +++ b/kernel/common/blackbox/Kconfig @@ -0,0 +1,10 @@ +config BLACKBOX + bool "Enable BlackBox" + default n + help + Answer Y to enable LiteOS support blackbox + +config LOG_ROOT_PATH + string "unknown" + 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..3e611c90 --- /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..36a69820 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox.h @@ -0,0 +1,91 @@ +/* + * 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 */ + +#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..c7ae0795 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_common.c @@ -0,0 +1,127 @@ +/* + * 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 +#ifdef LOSCFG_FS_VFS +#include "fs/fs.h" +#endif +#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) +{ +#ifdef LOSCFG_FS_VFS + 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; + } + + if (!IsLogPartReady()) { + BBOX_PRINT_ERR("log path [%s] isn't ready to be written!\n", LOSCFG_LOG_ROOT_PATH); + 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; +#else + (VOID)filePath; + (VOID)buf; + (VOID)bufSize; + (VOID)isAppend; + return -1; +#endif +} + +int SaveBasicErrorInfo(const char *filePath, struct ErrorInfo *info) +{ + char *buf = NULL; + + 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_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; +} + +#ifdef LOSCFG_FS_VFS +bool IsLogPartReady(void) +{ + return access(LOSCFG_LOG_ROOT_PATH, W_OK) == 0; +} +#else +bool IsLogPartReady(void) +{ + return TRUE; +} +#endif \ 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..6d20a934 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_common.h @@ -0,0 +1,61 @@ +/* + * 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 */ + +#include "los_blackbox.h" +#include "los_printf.h" +#include "los_typedef.h" + +#define ERROR_INFO_HEADER_FORMAT "#### error info ####\nevent: %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); +bool IsLogPartReady(void); + +#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..1e283fea --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_core.c @@ -0,0 +1,458 @@ +/* + * 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 "los_task_pri.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 bool g_bboxInitSucc = FALSE; +static UINT32 g_opsListSem = 0; +static UINT32 g_tempErrInfoSem = 0; +static UINT32 g_tempErrLogSaveSem = 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)); + (void)strncpy_s(info->module, sizeof(info->module), module, Min(strlen(module), sizeof(info->module) - 1)); + (void)strncpy_s(info->errorDesc, sizeof(info->errorDesc), errorDesc, + Min(strlen(errorDesc), sizeof(info->errorDesc) - 1)); +} + +#ifdef LOSCFG_FS_VFS +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 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 = NULL; + BBoxOps *ops = NULL; + + 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 = NULL; + + if (info == NULL) { + BBOX_PRINT_ERR("info is NULL!\n"); + 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 is NULL!\n"); + (void)LOS_SemPost(g_tempErrInfoSem); + return; + } + if (strlen(g_tempErrInfo->event) != 0) { + SaveLogWithoutReset(g_tempErrInfo); + } + (void)LOS_SemPost(g_tempErrInfoSem); +} + +static void SaveLogWithReset(struct ErrorInfo *info) +{ + int ret; + BBoxOps *ops = NULL; + + if (info == NULL) { + BBOX_PRINT_ERR("info is NULL!\n"); + 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_NO_WAIT) != 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); + while (1) { + if (LOS_SemPend(g_tempErrLogSaveSem, LOS_WAIT_FOREVER) != LOS_OK) { + BBOX_PRINT_ERR("Request g_tempErrLogSaveSem failed!\n"); + continue; + } + SaveTempErrorLog(); + } + return 0; +} + +#ifdef LOSCFG_BLACKBOX_DEBUG +static void PrintModuleOps(void) +{ + struct BBoxOps *ops = NULL; + + 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 = NULL; + BBoxOps *temp = NULL; + + if (!g_bboxInitSucc) { + BBOX_PRINT_ERR("BlackBox isn't initialized successfully!\n"); + return -1; + } + if (ops == NULL) { + BBOX_PRINT_ERR("ops is NULL!\n"); + 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) +{ + if (event == NULL || module == NULL || errorDesc == NULL) { + BBOX_PRINT_ERR("event: %p, module: %p, errorDesc: %p!\n", event, module, errorDesc); + return -1; + } + if (!g_bboxInitSucc) { + BBOX_PRINT_ERR("BlackBox isn't initialized successfully!\n"); + return -1; + } + + if (needSysReset == 0) { + SaveTempErrorInfo(event, module, errorDesc); + (void)LOS_SemPost(g_tempErrLogSaveSem); + } else { + struct ErrorInfo *info = LOS_MemAlloc(m_aucSysMem1, sizeof(struct ErrorInfo)); + if (info == NULL) { + BBOX_PRINT_ERR("LOS_MemAlloc failed!\n"); + return -1; + } + FormatErrorInfo(info, event, module, errorDesc); + 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 LOS_NOK; + } + if (LOS_BinarySemCreate(1, &g_tempErrInfoSem) != LOS_OK) { + BBOX_PRINT_ERR("Create g_tempErrInfoSem failed!\n"); + goto __err; + } + if (LOS_BinarySemCreate(0, &g_tempErrLogSaveSem) != LOS_OK) { + BBOX_PRINT_ERR("Create g_tempErrLogSaveSem 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); + g_bboxInitSucc = TRUE; + return LOS_OK; + +__err: + if (g_opsListSem != 0) { + (void)LOS_SemDelete(g_opsListSem); + } + if (g_tempErrInfoSem != 0) { + (void)LOS_SemDelete(g_tempErrInfoSem); + } + if (g_tempErrLogSaveSem != 0) { + (void)LOS_SemDelete(g_tempErrLogSaveSem); + } + return LOS_NOK; +} +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..ea14c9ea --- /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 is NULL\n"); + 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..f6714aad --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_detector.h @@ -0,0 +1,51 @@ +/* + * 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 */ + +#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..6e5b87d6 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_system_adapter.c @@ -0,0 +1,265 @@ +/* + * 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_phys.h" +#include "los_vm_common.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); +} + +#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, FAULT_LOG_SIZE - sizeof(struct FaultLogInfo), + g_logBuffer + sizeof(struct FaultLogInfo), WriteExcFile); +#endif + } else { + BBOX_PRINT_ERR("Alloc mem failed!\n"); + } +} + +static int AllocLogBuffer(void) +{ + int i = 0; + size_t nPages = ROUNDUP(FAULT_LOG_SIZE, PAGE_SIZE) >> PAGE_SHIFT; + void *tempBuffer[MEM_OVERLAP_COUNT] = { NULL }; + + for (i = 0; i < MEM_OVERLAP_COUNT; i++) { + tempBuffer[i] = LOS_PhysPagesAllocContiguous(nPages); + } + for (i = 0; i < (MEM_OVERLAP_COUNT - 1); i++) { + LOS_PhysPagesFreeContiguous(tempBuffer[i], nPages); + } + g_logBuffer = tempBuffer[i]; + BBOX_PRINT_INFO("g_logBuffer: %p for blackbox!\n", g_logBuffer); + + 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 + FAULT_LOG_SIZE)); + } else { +#ifdef LOSCFG_SAVE_EXCINFO + SaveFaultLog(USER_FAULT_LOG_PATH, g_logBuffer + sizeof(struct FaultLogInfo), + Min(FAULT_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(FAULT_LOG_SIZE - sizeof(*pLogInfo), pLogInfo->len), info); + } + (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; +#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"); + LOS_PhysPagesFreeContiguous(g_logBuffer, ROUNDUP(FAULT_LOG_SIZE, PAGE_SIZE) >> PAGE_SHIFT); + 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); \ 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..eb61bf83 --- /dev/null +++ b/kernel/common/blackbox/los_blackbox_system_adapter.h @@ -0,0 +1,51 @@ +/* + * 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 */ + +#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..7bf01236 100644 --- a/kernel/common/los_excinfo.c +++ b/kernel/common/los_excinfo.c @@ -34,6 +34,10 @@ #ifdef LOSCFG_SHELL #include "shcmd.h" #endif +#ifdef LOSCFG_FS_VFS +#include "fs/fs.h" +#include "fs/fs_operation.h" +#endif #ifdef LOSCFG_SAVE_EXCINFO STATIC log_read_write_fn g_excInfoRW = NULL; /* the hook of read-writing exception information */ diff --git a/tools/build/mk/liteos_tables_ldflags.mk b/tools/build/mk/liteos_tables_ldflags.mk index dd670571..db8b93c9 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 \ + -uOsBBoxDriverInit \ + -uOsBBoxSystemAdapterInit LITEOS_TABLES_DRIVER_LDFLAGS := \ -ui2c_init \ diff --git a/tools/build/mk/los_config.mk b/tools/build/mk/los_config.mk index cbefe9c7..902f770a 100644 --- a/tools/build/mk/los_config.mk +++ b/tools/build/mk/los_config.mk @@ -443,6 +443,11 @@ 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 +endif ############################## Dfx Option End ####################################### ############################# Tools && Debug Option Begin ############################## @@ -639,7 +644,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) \