* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <pthread.h>
#include <sys/mman.h>
#include "securec.h"
#include "drv_log_user_kernel_api.h"
#include "dmc/dmc_log_user.h"
#define BUFF_LENTH (64U)
#define DRV_LOG_START_TIME (1900)
#define ERROR_NUN_MAX (EHWPOISON + 1U)
#ifdef STATIC_SKIP
# define STATIC
#else
# define STATIC static
#endif
#define DRV_LOG_LEVEL_MAX (LOG_DEBUG + 1U)
STATIC const char *drv_log_level_default_str[DRV_LOG_LEVEL_MAX] = {
[LOG_EMERG] = "[EMERG]",
[LOG_ALERT] = "[ALERT]",
[LOG_CRIT] = "[EVENT]",
[LOG_ERR] = "[ERROR]",
[LOG_WARNING] = "[WARNING]",
[LOG_NOTICE] = "[NOTICE]",
[LOG_INFO] = "[INFO]",
[LOG_DEBUG] = "[DEBUG]",
};
#define EDEADLOCK_VALUE (58U)
#define EWOULDBLOCK_VALUE (41U)
#define DRV_KERNEL_ERROR_RESUME (150)
#define DRV_KERNEL_ERROR_DUP_CONFIG (151)
#define DRV_KERNEL_ERROR_POWER_OP_FAIL (152)
#define DRV_NSEC_PER_USECOND (1000)
struct drv_log_print_info {
uint32_t *con_log_level;
const char *(*log_get_level_string)(uint32_t level);
const char *(*log_get_print_time)(void);
uint32_t (*log_level_shift)(uint32_t level);
void (*log_print)(int32_t module_id, int32_t level, const char *fmt, ...);
};
static int32_t user_err[ERROR_NUN_MAX] = {
[0] = DRV_ERROR_NONE,
[EPERM] = DRV_ERROR_OPER_NOT_PERMITTED,
[ENOENT] = DRV_ERROR_FILE_OPS,
[ESRCH] = DRV_ERROR_IOCRL_FAIL,
[EINTR] = DRV_ERROR_IOCRL_FAIL,
[EIO] = DRV_ERROR_IOCRL_FAIL,
[ENXIO] = DRV_ERROR_NO_DEVICE,
[E2BIG] = DRV_ERROR_OVER_LIMIT,
[ENOEXEC] = DRV_ERROR_IOCRL_FAIL,
[EBADF] = DRV_ERROR_IOCRL_FAIL,
[ECHILD] = DRV_ERROR_IOCRL_FAIL,
[EAGAIN] = DRV_ERROR_TRY_AGAIN,
[ENOMEM] = DRV_ERROR_OUT_OF_MEMORY,
[EACCES] = DRV_ERROR_IOCRL_FAIL,
[EFAULT] = DRV_ERROR_INVALID_HANDLE,
[ENOTBLK] = DRV_ERROR_IOCRL_FAIL,
[EBUSY] = DRV_ERROR_BUSY,
[EEXIST] = DRV_ERROR_FILE_OPS,
[EXDEV] = DRV_ERROR_IOCRL_FAIL,
[ENODEV] = DRV_ERROR_NO_DEVICE,
[ENOTDIR] = DRV_ERROR_IOCRL_FAIL,
[EISDIR] = DRV_ERROR_IOCRL_FAIL,
[EINVAL] = DRV_ERROR_PARA_ERROR,
[ENFILE] = DRV_ERROR_IOCRL_FAIL,
[EMFILE] = DRV_ERROR_IOCRL_FAIL,
[ENOTTY] = DRV_ERROR_IOCRL_FAIL,
[ETXTBSY] = DRV_ERROR_IOCRL_FAIL,
[EFBIG] = DRV_ERROR_IOCRL_FAIL,
[ENOSPC] = DRV_ERROR_NO_RESOURCES,
[ESPIPE] = DRV_ERROR_IOCRL_FAIL,
[EROFS] = DRV_ERROR_IOCRL_FAIL,
[EMLINK] = DRV_ERROR_IOCRL_FAIL,
[EPIPE] = DRV_ERROR_IOCRL_FAIL,
[EDOM] = DRV_ERROR_IOCRL_FAIL,
[ERANGE] = DRV_ERROR_IOCRL_FAIL,
[EDEADLK] = DRV_ERROR_IOCRL_FAIL,
[ENAMETOOLONG] = DRV_ERROR_IOCRL_FAIL,
[ENOLCK] = DRV_ERROR_IOCRL_FAIL,
[ENOSYS] = DRV_ERROR_IOCRL_FAIL,
[ENOTEMPTY] = DRV_ERROR_IOCRL_FAIL,
[ELOOP] = DRV_ERROR_IOCRL_FAIL,
[EWOULDBLOCK_VALUE] = DRV_ERROR_IOCRL_FAIL,
[ENOMSG] = DRV_ERROR_IOCRL_FAIL,
[EIDRM] = DRV_ERROR_IOCRL_FAIL,
[ECHRNG] = DRV_ERROR_IOCRL_FAIL,
[EL2NSYNC] = DRV_ERROR_IOCRL_FAIL,
[EL3HLT] = DRV_ERROR_IOCRL_FAIL,
[EL3RST] = DRV_ERROR_IOCRL_FAIL,
[ELNRNG] = DRV_ERROR_IOCRL_FAIL,
[EUNATCH] = DRV_ERROR_IOCRL_FAIL,
[ENOCSI] = DRV_ERROR_IOCRL_FAIL,
[EL2HLT] = DRV_ERROR_IOCRL_FAIL,
[EBADE] = DRV_ERROR_IOCRL_FAIL,
[EBADR] = DRV_ERROR_IOCRL_FAIL,
[EXFULL] = DRV_ERROR_IOCRL_FAIL,
[ENOANO] = DRV_ERROR_IOCRL_FAIL,
[EBADRQC] = DRV_ERROR_IOCRL_FAIL,
[EBADSLT] = DRV_ERROR_IOCRL_FAIL,
[EDEADLOCK_VALUE] = DRV_ERROR_IOCRL_FAIL,
[EBFONT] = DRV_ERROR_IOCRL_FAIL,
[ENOSTR] = DRV_ERROR_IOCRL_FAIL,
[ENODATA] = DRV_ERROR_IOCRL_FAIL,
[ETIME] = DRV_ERROR_IOCRL_FAIL,
[ENOSR] = DRV_ERROR_IOCRL_FAIL,
[ENONET] = DRV_ERROR_IOCRL_FAIL,
[ENOPKG] = DRV_ERROR_IOCRL_FAIL,
[EREMOTE] = DRV_ERROR_IOCRL_FAIL,
[ENOLINK] = DRV_ERROR_IOCRL_FAIL,
[EADV] = DRV_ERROR_IOCRL_FAIL,
[ESRMNT] = DRV_ERROR_IOCRL_FAIL,
[ECOMM] = DRV_ERROR_IOCRL_FAIL,
[EPROTO] = DRV_ERROR_IOCRL_FAIL,
[EMULTIHOP] = DRV_ERROR_IOCRL_FAIL,
[EDOTDOT] = DRV_ERROR_IOCRL_FAIL,
[EBADMSG] = DRV_ERROR_IOCRL_FAIL,
[EOVERFLOW] = DRV_ERROR_IOCRL_FAIL,
[ENOTUNIQ] = DRV_ERROR_IOCRL_FAIL,
[EBADFD] = DRV_ERROR_IOCRL_FAIL,
[EREMCHG] = DRV_ERROR_IOCRL_FAIL,
[ELIBACC] = DRV_ERROR_IOCRL_FAIL,
[ELIBBAD] = DRV_ERROR_IOCRL_FAIL,
[ELIBSCN] = DRV_ERROR_IOCRL_FAIL,
[ELIBMAX] = DRV_ERROR_IOCRL_FAIL,
[ELIBEXEC] = DRV_ERROR_IOCRL_FAIL,
[EILSEQ] = DRV_ERROR_IOCRL_FAIL,
[ERESTART] = DRV_ERROR_IOCRL_FAIL,
[ESTRPIPE] = DRV_ERROR_IOCRL_FAIL,
[EUSERS] = DRV_ERROR_IOCRL_FAIL,
[ENOTSOCK] = DRV_ERROR_IOCRL_FAIL,
[EDESTADDRREQ] = DRV_ERROR_IOCRL_FAIL,
[EMSGSIZE] = DRV_ERROR_IOCRL_FAIL,
[EPROTOTYPE] = DRV_ERROR_IOCRL_FAIL,
[ENOPROTOOPT] = DRV_ERROR_IOCRL_FAIL,
[EPROTONOSUPPORT] = DRV_ERROR_IOCRL_FAIL,
[ESOCKTNOSUPPORT] = DRV_ERROR_IOCRL_FAIL,
[EOPNOTSUPP] = DRV_ERROR_NOT_SUPPORT,
[EPFNOSUPPORT] = DRV_ERROR_IOCRL_FAIL,
[EAFNOSUPPORT] = DRV_ERROR_IOCRL_FAIL,
[EADDRINUSE] = DRV_ERROR_IOCRL_FAIL,
[EADDRNOTAVAIL] = DRV_ERROR_IOCRL_FAIL,
[ENETDOWN] = DRV_ERROR_IOCRL_FAIL,
[ENETUNREACH] = DRV_ERROR_IOCRL_FAIL,
[ENETRESET] = DRV_ERROR_IOCRL_FAIL,
[ECONNABORTED] = DRV_ERROR_IOCRL_FAIL,
[ECONNRESET] = DRV_ERROR_IOCRL_FAIL,
[ENOBUFS] = DRV_ERROR_IOCRL_FAIL,
[EISCONN] = DRV_ERROR_IOCRL_FAIL,
[ENOTCONN] = DRV_ERROR_IOCRL_FAIL,
[ESHUTDOWN] = DRV_ERROR_IOCRL_FAIL,
[ETOOMANYREFS] = DRV_ERROR_IOCRL_FAIL,
[ETIMEDOUT] = DRV_ERROR_WAIT_TIMEOUT,
[ECONNREFUSED] = DRV_ERROR_IOCRL_FAIL,
[EHOSTDOWN] = DRV_ERROR_IOCRL_FAIL,
[EHOSTUNREACH] = DRV_ERROR_IOCRL_FAIL,
[EALREADY] = DRV_ERROR_IOCRL_FAIL,
[EINPROGRESS] = DRV_ERROR_IOCRL_FAIL,
[ESTALE] = DRV_ERROR_IOCRL_FAIL,
[EUCLEAN] = DRV_ERROR_IOCRL_FAIL,
[ENOTNAM] = DRV_ERROR_IOCRL_FAIL,
[ENAVAIL] = DRV_ERROR_IOCRL_FAIL,
[EISNAM] = DRV_ERROR_IOCRL_FAIL,
[EREMOTEIO] = DRV_ERROR_IOCRL_FAIL,
[EDQUOT] = DRV_ERROR_IOCRL_FAIL,
[ENOMEDIUM] = DRV_ERROR_IOCRL_FAIL,
[EMEDIUMTYPE] = DRV_ERROR_IOCRL_FAIL,
[ECANCELED] = DRV_ERROR_IOCRL_FAIL,
[ENOKEY] = DRV_ERROR_IOCRL_FAIL,
[EKEYEXPIRED] = DRV_ERROR_IOCRL_FAIL,
[EKEYREVOKED] = DRV_ERROR_IOCRL_FAIL,
[EKEYREJECTED] = DRV_ERROR_IOCRL_FAIL,
[EOWNERDEAD] = DRV_ERROR_IOCRL_FAIL,
[ENOTRECOVERABLE] = DRV_ERROR_IOCRL_FAIL,
[ERFKILL] = DRV_ERROR_IOCRL_FAIL,
[EHWPOISON] = DRV_ERROR_IOCRL_FAIL,
};
int32_t errno_to_user_errno_inner(int32_t kern_err_no)
{
uint32_t drv_kern_err_no = (uint32_t)kern_err_no;
if (kern_err_no < 0) {
if (kern_err_no == -1) {
return DRV_ERROR_IOCRL_FAIL;
}
drv_kern_err_no = (uint32_t)(-kern_err_no);
}
if (drv_kern_err_no >= ERROR_NUN_MAX) {
if (drv_kern_err_no == DRV_KERNEL_ERROR_RESUME) {
return DRV_ERROR_RESUME;
} else if (drv_kern_err_no == DRV_KERNEL_ERROR_DUP_CONFIG) {
return DEV_ERROR_DUP_CONFIG;
} else if (drv_kern_err_no == DRV_KERNEL_ERROR_POWER_OP_FAIL) {
return DRV_ERROR_POWER_OP_FAIL;
} else {
return DRV_ERROR_IOCRL_FAIL;
}
} else if (drv_kern_err_no == 0) {
return DRV_ERROR_NONE;
} else if (user_err[drv_kern_err_no] == 0) {
return DRV_ERROR_IOCRL_FAIL;
} else {
;
}
return user_err[drv_kern_err_no];
}
const char *drv_log_get_module_str_inner(enum devdrv_module_type module)
{
STATIC const char *drv_log_module_str[HAL_MODULE_TYPE_MAX] = {
[HAL_MODULE_TYPE_VNIC] = "vnic",
[HAL_MODULE_TYPE_HDC] = "hdc",
[HAL_MODULE_TYPE_DEVMM] = "devmm",
[HAL_MODULE_TYPE_DEV_MANAGER] = "devmng",
[HAL_MODULE_TYPE_DMP] = "dmp",
[HAL_MODULE_TYPE_FAULT] = "faultmng",
[HAL_MODULE_TYPE_UPGRADE] = "upgrade",
[HAL_MODULE_TYPE_PROCESS_MON] = "process-mon",
[HAL_MODULE_TYPE_LOG] = "log",
[HAL_MODULE_TYPE_PROF] = "prof",
[HAL_MODULE_TYPE_DVPP] = "dvpp",
[HAL_MODULE_TYPE_PCIE] = "pcie",
[HAL_MODULE_TYPE_IPC] = "ipc",
[HAL_MODULE_TYPE_TS_DRIVER] = "tsdrv",
[HAL_MODULE_TYPE_SAFETY_ISLAND] = "sis",
[HAL_MODULE_TYPE_BSP] = "bsp",
[HAL_MODULE_TYPE_USB] = "usb",
[HAL_MODULE_TYPE_NET] = "net",
[HAL_MODULE_TYPE_EVENT_SCHEDULE] = "event-sche",
[HAL_MODULE_TYPE_BUF_MANAGER] = "bufmng",
[HAL_MODULE_TYPE_QUEUE_MANAGER] = "queuemng",
[HAL_MODULE_TYPE_DP_PROC_MNG] = "dp-procmng",
[HAL_MODULE_TYPE_COMMON] = "common",
[HAL_MODULE_TYPE_LIDAR_DP] = "lidar_dp",
[HAL_MODULE_TYPE_ADSPC] = "adspc",
[HAL_MODULE_TYPE_APM] = "apm",
};
uint32_t module_type = (uint32_t)module;
if (module_type >= (uint32_t)(HAL_MODULE_TYPE_MAX)) {
return NULL;
}
return drv_log_module_str[module_type];
}
STATIC const char drv_log_level_str[] = "\0";
STATIC const char *drv_log_get_level_str(uint32_t level)
{
(void)level;
return drv_log_level_str;
}
STATIC const char *drv_log_get_level_str_default(uint32_t level)
{
if (level >= (uint32_t)(DRV_LOG_LEVEL_MAX)) {
return NULL;
}
return drv_log_level_default_str[level];
}
STATIC const char *drv_get_tm(void)
{
return drv_log_level_str;
}
STATIC const char *drv_get_tm_default(void)
{
static char tmbuf[BUFF_LENTH] = {0};
struct timespec ts;
struct tm *tm_now = NULL;
int32_t ret;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
(void)pthread_mutex_lock(&lock);
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
(void)pthread_mutex_unlock(&lock);
return NULL;
}
tm_now = localtime(&ts.tv_sec);
if (tm_now == NULL) {
(void)pthread_mutex_unlock(&lock);
return NULL;
}
ret = sprintf_s(tmbuf, BUFF_LENTH, "[%d-%02d-%02d-%02d:%02d:%02d:%06d]", tm_now->tm_year + DRV_LOG_START_TIME,
tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min,
tm_now->tm_sec, (int32_t)(ts.tv_nsec / DRV_NSEC_PER_USECOND));
if (ret < 0) {
(void)pthread_mutex_unlock(&lock);
return NULL;
}
(void)pthread_mutex_unlock(&lock);
return tmbuf;
}
#define LOG_GLIBC_LEVEL_TYPE_MAX (LOG_DEBUG + 1U)
static uint32_t drv_log_level_glibc_to_tool_table[LOG_GLIBC_LEVEL_TYPE_MAX] = {
[LOG_EMERG] = DLOG_ERROR,
[LOG_ALERT] = DLOG_ERROR,
[LOG_CRIT] = DLOG_EVENT,
[LOG_ERR] = DLOG_ERROR,
[LOG_WARNING] = DLOG_WARN,
[LOG_NOTICE] = DLOG_EVENT,
[LOG_INFO] = DLOG_INFO,
[LOG_DEBUG] = DLOG_DEBUG,
};
#define LOG_TOOL_LEVEL_TYPE_MAX (DLOG_NULL + 1U)
static uint32_t drv_log_level_tool_to_glibc_table[LOG_TOOL_LEVEL_TYPE_MAX] = {
[DLOG_DEBUG] = LOG_DEBUG,
[DLOG_INFO] = LOG_INFO,
[DLOG_WARN] = LOG_WARNING,
[DLOG_ERROR] = LOG_ERR,
[DLOG_NULL] = LOG_CRIT,
};
STATIC uint32_t drv_log_level_shift_default(uint32_t level)
{
return level;
}
STATIC uint32_t drv_log_level_glibc_to_tool(uint32_t level)
{
return drv_log_level_glibc_to_tool_table[level];
}
STATIC uint32_t drv_log_level_tool_to_glibc(uint32_t level)
{
return drv_log_level_tool_to_glibc_table[level];
}
STATIC void drv_syslog(int32_t module_id, int32_t priority, const char *format, ...)
{
(void)module_id;
va_list args;
va_start(args, format);
vsyslog(priority, format, args);
va_end(args);
}
STATIC uint32_t drv_log_rsyslog_console_level = LOG_ERR;
STATIC uint32_t drv_log_tool_console_level = LOG_ERR;
struct drv_log_print_info g_log_print_info = {
.con_log_level = &drv_log_rsyslog_console_level,
.log_get_level_string = drv_log_get_level_str_default,
.log_get_print_time = drv_get_tm_default,
.log_level_shift = drv_log_level_shift_default,
.log_print = drv_syslog,
};
STATIC uint32_t g_run_log_status;
int32_t drv_log_out_handle_register_inner(struct log_out_handle *handle, size_t input_size, uint32_t flag)
{
if (input_size != sizeof(struct log_out_handle)) {
(void)printf("Log_out_handle_register failed. (input_size=%zu; size_log_out_handle=%zu)\n",
input_size, sizeof(struct log_out_handle));
return DRV_ERROR_INVALID_VALUE;
}
if (handle == NULL) {
(void)printf("Log_out_handle_register failed, handle is NULL.\n");
return DRV_ERROR_INVALID_VALUE;
}
if (handle->DlogInner == NULL) {
(void)printf("Log_out_handle_register failed, the member DlogInner in handle is NULL.\n");
return DRV_ERROR_INVALID_VALUE;
}
if (handle->logLevel >= (uint32_t)LOG_TOOL_LEVEL_TYPE_MAX) {
(void)printf("Log_out_handle_register failed. (handle->logLevel=%u)\n", handle->logLevel);
return DRV_ERROR_INVALID_VALUE;
}
g_run_log_status = flag;
drv_log_tool_console_level = drv_log_level_tool_to_glibc(handle->logLevel);
g_log_print_info.con_log_level = &drv_log_tool_console_level;
g_log_print_info.log_get_level_string = drv_log_get_level_str;
g_log_print_info.log_get_print_time = drv_get_tm;
g_log_print_info.log_level_shift = drv_log_level_glibc_to_tool;
g_log_print_info.log_print = handle->DlogInner;
return DRV_ERROR_NONE;
}
int32_t is_run_log_inner(void)
{
return (int32_t)g_run_log_status;
}
int32_t drv_log_out_handle_unregister_inner(void)
{
g_log_print_info.con_log_level = &drv_log_rsyslog_console_level;
g_log_print_info.log_get_level_string = drv_log_get_level_str_default;
g_log_print_info.log_get_print_time = drv_get_tm_default;
g_log_print_info.log_level_shift = drv_log_level_shift_default;
g_log_print_info.log_print = drv_syslog;
return DRV_ERROR_NONE;
}
#ifdef DRV_HOST
static void __attribute__((constructor)) drv_log_base_init(void)
{
share_log_create(HAL_MODULE_TYPE_COMMON, SHARE_LOG_MAX_SIZE);
}
void drv_log_rsyslog_console_level_set(uint32_t level)
{
drv_log_rsyslog_console_level = level;
}
#endif
uint32_t get_con_log_level_inner(void)
{
return *(g_log_print_info.con_log_level);
}
const char *get_log_get_level_string_inner(uint32_t level)
{
return g_log_print_info.log_get_level_string(level);
}
const char *get_log_get_print_time_inner(void)
{
return g_log_print_info.log_get_print_time();
}
uint32_t get_log_level_shift_inner(uint32_t level)
{
return g_log_print_info.log_level_shift(level);
}
void (*get_log_print_inner(void))(int32_t, int32_t, const char *, ...) {
return g_log_print_info.log_print;
}
static struct err_msg_report_handle g_report_err_msg_info;
int32_t drv_log_report_err_msg_handle_register_impl(struct err_msg_report_handle *handle, size_t input_size)
{
if (input_size != sizeof(struct err_msg_report_handle) || handle == NULL) {
return DRV_ERROR_INVALID_VALUE;
}
if (handle->register_format_func == NULL || handle->predefined_report_func == NULL ||
handle->inner_report_func == NULL) {
return DRV_ERROR_INVALID_VALUE;
}
if (g_report_err_msg_info.is_registered == 1) {
return DRV_ERROR_REPEATED_INIT;
}
g_report_err_msg_info.register_format_func = handle->register_format_func;
g_report_err_msg_info.predefined_report_func = handle->predefined_report_func;
g_report_err_msg_info.inner_report_func = handle->inner_report_func;
g_report_err_msg_info.is_registered = 1;
return DRV_ERROR_NONE;
}
int32_t drv_log_report_err_msg_handle_unregister_impl(void)
{
g_report_err_msg_info.register_format_func = NULL;
g_report_err_msg_info.predefined_report_func = NULL;
g_report_err_msg_info.inner_report_func = NULL;
g_report_err_msg_info.is_registered = 0;
return DRV_ERROR_NONE;
}
register_format_err_msg_func get_format_err_msg_register_func_impl(void)
{
return g_report_err_msg_info.register_format_func;
}
report_predefined_err_msg_func get_predefined_err_msg_report_func_impl(void)
{
return g_report_err_msg_info.predefined_report_func;
}
report_inner_err_msg_func get_inner_err_msg_report_func_impl(void)
{
return g_report_err_msg_info.inner_report_func;
}