/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2009-2020. All rights reserved. * Description: log drv * Author: Hisilicon * Create: 2009-12-17 */ #include "drv_log.h" #include #include #include #include "td_type.h" #include "soc_log.h" #include "osal_ext.h" #include "drv_dev_ext.h" #include "drv_module_ext.h" #include "drv_log_ext.h" #include "drv_sys_ext.h" #include "drv_ioctl_log.h" #include "drv_log.h" typedef struct { struct dma_buf *dmabuf; td_u8 *virt_addr; } log_ion_buf; #define LOG_MSG_BUF_RESERVE (4 * 1024) static log_ion_buf g_log_cfg_buf; /* kernel-state pointer of log control info */ /* CNcomment: 打印控制信息的内核态指针 */ static log_cfg_info *g_log_cfg_info; static td_bool g_log_init = TD_FALSE; #define LOG_MAX_FILE_SIZE 120U /* 120M */ #define LOG_MIN_FILE_SIZE 1U /* 1M */ #define LOG_DEFAULT_FILE_SIZE 12U /* 12M */ #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) #define LOG_MAX_FILE_CNT (4) /* Save up to 5 log files */ static log_ion_buf g_log_msg_buf; static td_u64 g_log_write_len_count = 0; static td_u32 g_log_file_count = 0; #endif static log_buf_info g_log_msg_info; static osal_semaphore g_log_k_mutex; osal_semaphore g_log_store_mutex; DEFINE_SPINLOCK(g_log_lock); #define log_file_lock() osal_sem_down_interruptible(&g_log_k_mutex) #define log_file_unlock() osal_sem_up(&g_log_k_mutex) #define log_store_lock() osal_sem_down_interruptible(&g_log_store_mutex) #define log_store_unlock() osal_sem_up(&g_log_store_mutex) #define STORE_LOG_WAKE_UP_SIZE 1000 #define LOG_RTC_TIME_LENGH 19 #define LOG_WAIT_DATA_TIMEOUT 1000 /* 1s */ /* this variable will be used by /kmod/load script */ static td_u32 g_log_buf_size = 10 * 256 * LOG_MSG_BUF_RESERVE; /* Multiply by 256 means buf_size is 1M,10M total */ static td_char g_log_path_buf[LOG_MAX_FILE_NAME_LENTH] = "/tmp"; static td_char *g_udisk_log_file = g_log_path_buf; static td_bool g_set_log_file_flag = TD_FALSE; static td_char g_store_path_buf[LOG_MAX_FILE_NAME_LENTH] = "/mnt"; td_char *g_store_path = g_store_path_buf; static td_u32 g_default_log_size = LOG_DEFAULT_FILE_SIZE * 1024 * 1024; /* Multiply by 1024 means buf_size is 16M */ td_char *g_debug_level_name[SOC_LOG_LEVEL_MAX + 1] = { "ALERT", "FATAL", "ERROR", "WARN", "NOTICE", "INFO", "DEBUG", "TRACE", "MAX" }; static td_u32 g_default_log_level = SOC_LOG_LEVEL_ERROR; static log_store_info_t g_log_store_info = { .store_log_enable = TD_FALSE, .store_log_thread_exist = TD_FALSE, .store_log_poll_new = TD_FALSE, .store_log_len = 0, }; td_void drv_log_store_enable(const td_bool *enable) { if (enable == TD_NULL) { return; } if (g_set_log_file_flag == TD_TRUE) { g_log_store_info.store_log_enable = TD_FALSE; } else { g_log_store_info.store_log_enable = *enable; } g_log_store_info.store_log_thread_exist = *enable; return; } td_void drv_log_get_store_status(td_bool *store_enable, td_bool *store_thread_exist) { if (store_enable == TD_NULL || store_thread_exist == TD_NULL) { return; } *store_enable = g_log_store_info.store_log_enable; *store_thread_exist = g_log_store_info.store_log_thread_exist; return; } unsigned int drv_log_store_poll(osal_poll *osal_poll) { unsigned int poll_mask = 0; if (g_log_store_info.store_log_thread_exist == TD_TRUE) { if (g_log_store_info.store_log_poll_new == TD_TRUE) { poll_mask |= OSAL_POLLIN; g_log_store_info.store_log_poll_new = TD_FALSE; } else { osal_poll_wait(osal_poll, &g_log_store_info.poll_wait_queue); } } return poll_mask; } static td_void drv_log_reset_buf(td_void) { td_ulong flags; spin_lock_irqsave(&g_log_lock, flags); g_log_msg_info.read = g_log_msg_info.write; g_log_msg_info.reset_cnt++; spin_unlock_irqrestore(&g_log_lock, flags); } static td_s32 drv_log_wait_condition(const td_void *param) { return (((log_buf_info *)param)->write != ((log_buf_info *)param)->read); } static td_s32 log_data_buf_copy(td_u8 *buf, td_u32 buf_size, const td_u8 *src, td_u32 copy_len, td_bool b_kernel_copy) { errno_t err_ret; if (b_kernel_copy == TD_FALSE) { if (osal_copy_to_user(buf, src, copy_len)) { soc_log_err("copy_to_user error\n"); return TD_FAILURE; } } else { err_ret = memcpy_s(buf, buf_size, src, copy_len); if (err_ret != EOK) { soc_log_err("secure func call error\n"); return TD_FAILURE; } } return TD_SUCCESS; } static td_s32 log_read_data(td_u8 *buf, td_u32 buf_len, log_buf_info *msg_info_now, td_u32 *copy_len, td_bool b_kernel_copy) { td_u32 buf_used, data_part_one, data_part_two, data_len, new_read_addr; td_s32 ret; /* not support log when uart close or user version */ #if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER) return TD_SUCCESS; #endif if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) { return TD_SUCCESS; } if (msg_info_now->write < msg_info_now->read) { buf_used = msg_info_now->buf_size - msg_info_now->read + msg_info_now->write; data_part_one = msg_info_now->buf_size - msg_info_now->read; data_part_two = msg_info_now->write; } else { buf_used = msg_info_now->write - msg_info_now->read; data_part_one = buf_used; data_part_two = 0; } *copy_len = (buf_len <= (data_part_one + data_part_two)) ? (buf_len) : (data_part_one + data_part_two); data_len = (data_part_one >= *copy_len) ? (*copy_len) : (data_part_one); ret = log_data_buf_copy(buf, buf_len, msg_info_now->start_virt_addr + msg_info_now->read, data_len, b_kernel_copy); if (ret != TD_SUCCESS) { return TD_FAILURE; } if (data_part_one < *copy_len) { ret = log_data_buf_copy(buf + data_part_one, buf_len - data_part_one, msg_info_now->start_virt_addr, *copy_len - data_part_one, b_kernel_copy); if (ret != TD_SUCCESS) { soc_log_err("log data copy error\n"); return TD_FAILURE; } } new_read_addr = (data_part_one >= *copy_len) ? (msg_info_now->read + *copy_len) : (*copy_len - data_part_one); new_read_addr = (new_read_addr >= msg_info_now->buf_size) ? (0) : (new_read_addr); return new_read_addr; } static td_s32 log_buffer_read(td_u8 *buf, td_u32 buf_len, td_u32 *p_copy_len, td_bool b_kernel_copy) { log_buf_info msg_info_now; unsigned long flags; td_s32 ret; errno_t err_ret; spin_lock_irqsave(&g_log_lock, flags); err_ret = memcpy_s(&msg_info_now, sizeof(log_buf_info), &g_log_msg_info, sizeof(g_log_msg_info)); spin_unlock_irqrestore(&g_log_lock, flags); if (err_ret != EOK) { soc_log_err("secure func call error\n"); return TD_FAILURE; } ret = log_read_data(buf, buf_len, &msg_info_now, p_copy_len, b_kernel_copy); if (ret < 0) { soc_log_err("call log_read_data error\n"); return TD_FAILURE; } spin_lock_irqsave(&g_log_lock, flags); g_log_store_info.store_log_len -= *p_copy_len; if (msg_info_now.reset_cnt == g_log_msg_info.reset_cnt) { g_log_msg_info.read = (td_u32)ret; } spin_unlock_irqrestore(&g_log_lock, flags); return TD_SUCCESS; } td_s32 ext_drv_log_read_buf(td_u8 *buf, td_u32 buf_len, td_u32 *copy_len, td_bool *status, td_bool is_kernel_copy) { td_s32 ret; if (g_log_msg_info.buf_size == 0) { soc_log_err("Log Buffer size is 0, Please confige the Buffer size, for example:"); soc_log_err(" Config buffer size 500K: insmod soc_cmpi.ko g_log_buf_size = 0x80000"); return TD_FAILURE; } if (buf == TD_NULL) { soc_log_err("buf is null\n"); return TD_FAILURE; } if (status == TD_NULL) { soc_log_err("status is null\n"); return TD_FAILURE; } *status = g_log_store_info.store_log_enable; if (g_log_msg_info.write == g_log_msg_info.read) { if (g_set_log_file_flag == TD_TRUE || g_log_store_info.store_log_enable == TD_TRUE) { return TD_FAILURE; } else { /* the following code segment will pending when reboot or reload ko */ ret = osal_wait_timeout_interruptible(&g_log_msg_info.wq_no_data, drv_log_wait_condition, &g_log_msg_info, LOG_WAIT_DATA_TIMEOUT); if (ret == 0 && (g_log_msg_info.write == g_log_msg_info.read)) { return TD_FAILURE; } } } ret = log_buffer_read(buf, buf_len, copy_len, is_kernel_copy); if (ret != TD_SUCCESS) { soc_log_err("call log_buffer_read failed !\n"); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 drv_log_write(const td_u8 *buf, td_u32 copy_len1, td_u32 copy_len2, td_u32 msg_from_pos, td_u32 new_write_addr) { td_s32 ret; if (copy_len1 > 0) { if (msg_from_pos == LOG_MSG_FROM_KERNEL) { ret = memcpy_s((g_log_msg_info.write + g_log_msg_info.start_virt_addr), g_log_msg_info.buf_size - g_log_msg_info.write, buf, copy_len1); if (ret != EOK) { soc_log_err("memcpy_s error !\n"); return TD_FAILURE; } } else { if (osal_copy_from_user((g_log_msg_info.write + g_log_msg_info.start_virt_addr), buf, copy_len1)) { soc_log_err("copy_from_user error\n"); return TD_FAILURE; } } } if (copy_len2 > 0) { if (msg_from_pos == LOG_MSG_FROM_KERNEL) { ret = memcpy_s(g_log_msg_info.start_virt_addr, g_log_msg_info.buf_size, (buf + copy_len1), copy_len2); if (ret != EOK) { soc_log_err("memcpy_s error !\n"); return TD_FAILURE; } } else { if (osal_copy_from_user(g_log_msg_info.start_virt_addr, (buf + copy_len1), copy_len2)) { soc_log_err("copy_from_user error\n"); return TD_FAILURE; } } } g_log_msg_info.write = new_write_addr; if (g_set_log_file_flag != TD_TRUE || g_log_store_info.store_log_enable != TD_TRUE) { osal_wait_wakeup(&g_log_msg_info.wq_no_data); } return TD_SUCCESS; } td_s32 ext_drv_log_write_buf(const td_u8 *buf, td_u32 msg_len, td_u32 msg_from_pos) { td_u32 copy_len1, copy_len2, new_write_addr, cond; td_ulong flags; td_s32 ret; /* not support log when uart close or user version */ #if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER) return TD_SUCCESS; #endif if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) { return TD_SUCCESS; } cond = ((g_log_msg_info.buf_size == 0) || (buf == TD_NULL || msg_len >= g_log_buf_size)); if (cond) { soc_log_err("param invalid!\n"); return TD_FAILURE; } spin_lock_irqsave(&g_log_lock, flags); g_log_store_info.store_log_len += msg_len; spin_unlock_irqrestore(&g_log_lock, flags); if (g_log_store_info.store_log_len > STORE_LOG_WAKE_UP_SIZE) { g_log_store_info.store_log_poll_new = TD_TRUE; osal_wait_wakeup(&g_log_store_info.poll_wait_queue); } if (g_log_msg_info.write < g_log_msg_info.read) { if ((g_log_msg_info.read - g_log_msg_info.write) < LOG_MSG_BUF_RESERVE) { drv_log_reset_buf(); } } else { if ((g_log_msg_info.write - g_log_msg_info.read) > (g_log_msg_info.buf_size - LOG_MSG_BUF_RESERVE)) { drv_log_reset_buf(); } } if ((msg_len + g_log_msg_info.write) >= g_log_msg_info.buf_size) { copy_len1 = g_log_msg_info.buf_size - g_log_msg_info.write; copy_len2 = msg_len - copy_len1; new_write_addr = copy_len2; } else { copy_len1 = msg_len; copy_len2 = 0; new_write_addr = msg_len + g_log_msg_info.write; } /* * protect with semaphore while two module write at the same time * CNcomment: 两个模块同时写要做信号量保护 */ spin_lock_irqsave(&g_log_lock, flags); ret = drv_log_write(buf, copy_len1, copy_len2, msg_from_pos, new_write_addr); if (ret != TD_SUCCESS) { spin_unlock_irqrestore(&g_log_lock, flags); return TD_FAILURE; } spin_unlock_irqrestore(&g_log_lock, flags); return TD_SUCCESS; } td_void log_get_rtc_time(td_char *rtc_time, td_u32 len) { osal_rtc_time tm = {0}; osal_timeval tv; td_u32 cur_usec; td_s32 ret; if (rtc_time == TD_NULL) { soc_log_err("rtc_time is null\n"); return; } /* 获取当前的UTC时间 */ osal_gettimeofday(&tv); /* 把UTC时间调整为本地时间 */ tv.tv_sec -= sys_tz.tz_minuteswest * 60; /* 60 表示min与s的换算关系 */ /* 算出时间中的年月日等数值到tm中 */ osal_rtc_time_to_tm(tv.tv_sec, &tm); cur_usec = (td_u32)tv.tv_usec / 1000; /* 1000 表示s/ms/us的换算关系 */ ret = snprintf_s(rtc_time, len, LOG_RTC_TIME_LENGH, "%02d-%02d %02d:%02d:%02d.%03d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, cur_usec); if (ret < 0) { soc_print("call snprintf_s failed!\n"); return; } rtc_time[LOG_RTC_TIME_LENGH - 1] = ' '; return; } td_s32 drv_log_add_module(const td_char *name, td_u32 mod_id) { td_s32 ret; if (name == TD_NULL || g_log_cfg_info == TD_NULL || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) { return TD_FAILURE; } ret = strncpy_s(g_log_cfg_info[mod_id].module_name, sizeof(g_log_cfg_info[mod_id].module_name), name, strlen(name)); if (ret != EOK) { soc_log_err("strncpy_s failed\n"); return TD_FAILURE; } g_log_cfg_info[mod_id].module_name[sizeof(g_log_cfg_info[mod_id].module_name) - 1] = '\0'; return TD_SUCCESS; } #define DEFAULT_LOG_QUOTA (12288) td_s32 drv_log_remove_module(td_u32 mod_id) { td_s32 ret; if (g_log_cfg_info == TD_NULL || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) { return TD_FAILURE; } g_log_cfg_info[mod_id].log_level = (td_u8)g_default_log_level; g_log_cfg_info[mod_id].log_print_pos = LOG_OUTPUT_SERIAL; g_log_cfg_info[mod_id].log_quota = DEFAULT_LOG_QUOTA; ret = snprintf_s(g_log_cfg_info[mod_id].module_name, sizeof(g_log_cfg_info[mod_id].module_name), strlen("Invalid"), "Invalid"); if (ret < 0) { soc_log_err("snprintf_s failed\n"); return TD_FAILURE; } g_log_cfg_info[mod_id].module_name[sizeof(g_log_cfg_info[mod_id].module_name) - 1] = '\0'; return TD_SUCCESS; } td_void drv_log_set_module(td_u32 mod_id) { td_s32 ret; module_detail_info module_data; if (g_log_cfg_info == TD_NULL || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) { return; } ret = ext_drv_module_get_data(mod_id, &module_data); if (ret != TD_SUCCESS) { (td_void)drv_log_remove_module(mod_id); /* use log info debug, beacuse of the module number is larger than register so some module id we cannot find. */ soc_log_info("invaild or do not register module id :%d \n", mod_id); return; } ret = drv_log_add_module(module_data.name, mod_id); if (ret != TD_SUCCESS) { soc_log_info("add module failed. mod_id:%d, name :%s\n", module_data.name, mod_id); } } /* TD_TRUE: need print; TD_FALSE: not print */ static td_void log_level_check(td_u32 level, td_u32 mod_id, log_level_t *log_level) { td_u8 current_level; if (mod_id >= (LOG_CFG_BUF_SIZE / sizeof(log_cfg_info))) { soc_print("mod_id invalid !\n"); return; } /* log module has initialized yet */ if (likely(g_log_init)) { log_level->bbox_level = (level == SOC_LOG_LEVEL_ALERT) ? (TD_TRUE) : (TD_FALSE); current_level = g_log_cfg_info[mod_id].log_level; if (current_level == SOC_LOG_LEVEL_TRACE) { log_level->general_level = (level == SOC_LOG_LEVEL_TRACE) ? (TD_TRUE) : (TD_FALSE); log_level->memory_level = log_level->general_level; return; } if (likely(current_level <= g_default_log_level)) { if (likely(level > SOC_LOG_LEVEL_INFO)) { return; } if (level <= current_level) { log_level->memory_level = TD_TRUE; log_level->general_level = TD_TRUE; } } else { if (level <= current_level) { log_level->general_level = TD_TRUE; log_level->memory_level = TD_TRUE; } } } else { /* log module has not initialized yet */ if (level <= g_default_log_level) { log_level->general_level = TD_TRUE; log_level->memory_level = TD_TRUE; } } return; } /* 0: seria port, 1: network */ static td_u32 drv_log_get_print_pos(td_u32 mod_id) { td_u32 pos; if (mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) { return LOG_OUTPUT_SERIAL; } if (g_log_init == TD_FALSE) { return LOG_OUTPUT_SERIAL; } if (g_set_log_file_flag == TD_TRUE) { pos = LOG_OUTPUT_UDISK; } else { pos = g_log_cfg_info[mod_id].log_print_pos; } return pos; } #ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT td_s32 drv_log_udisk_save(const td_s8 *file_name, const td_s8 *data, td_u32 data_len) { td_s32 write_len, ret; void *file = NULL; errno_t err_ret; static td_char cur_file_name[LOG_MAX_FILE_NAME_LENTH] = {0}; if (file_name == TD_NULL) { soc_log_err("file_name is null\n"); return TD_FAILURE; } if (strlen(file_name) < strlen(cur_file_name)) { err_ret = memset_s(cur_file_name, LOG_MAX_FILE_NAME_LENTH, 0, sizeof(cur_file_name)); if (err_ret != EOK) { soc_log_err("secure func call error\n"); return TD_FAILURE; } } if (g_log_write_len_count > g_default_log_size) { g_log_file_count++; g_log_file_count = (g_log_file_count > LOG_MAX_FILE_CNT) ? (0) : (g_log_file_count); } ret = snprintf_s(cur_file_name, LOG_MAX_FILE_NAME_LENTH, LOG_MAX_FILE_NAME_LENTH - 1, "%s.%d", file_name, g_log_file_count); if (ret < 0) { soc_log_err("call snprintf_s failed.\n"); return TD_FAILURE; } if (g_log_write_len_count > g_default_log_size) { file = osal_klib_fopen(cur_file_name, OSAL_O_RDWR | OSAL_O_CREAT | OSAL_O_TRUNC, 0644); /* 0644 is authority */ if (file == NULL) { soc_log_err("osal_klib_fopen %s failure...................\n", cur_file_name); return TD_FAILURE; } osal_klib_fclose(file); g_log_write_len_count = 0; } file = osal_klib_fopen(cur_file_name, OSAL_O_RDWR | OSAL_O_CREAT | OSAL_O_APPEND, 0644); /* 0644 is authority */ if (file == NULL) { soc_log_err("osal_klib_fopen %s failure...................\n", cur_file_name); return TD_FAILURE; } write_len = osal_klib_fwrite(data, data_len, file); g_log_write_len_count += (unsigned int)write_len; osal_klib_fclose(file); return TD_SUCCESS; } static osal_task *g_udisk_task = TD_NULL; static td_u8 g_udisk_buf[LOG_MSG_BUF_RESERVE] = {0}; static td_u8 g_udisk_file_name[LOG_MAX_FILE_NAME_LENTH] = {0}; td_s32 drv_log_udisk_write_thread(td_void *arg) { td_u32 read_len = 0; td_s32 ret; td_bool set_file_flag; td_bool status = TD_FALSE; errno_t err_ret; td_u8 *udisk_log_file = (td_u8 *)arg; if (udisk_log_file == TD_NULL) { soc_log_err("input arg udisk_log_file is NULL.. \n"); return TD_FAILURE; } ret = snprintf_s(g_udisk_file_name, sizeof(g_udisk_file_name), sizeof(g_udisk_file_name) - 1, "%s/stb.log", (const td_s8*)udisk_log_file); if (ret < 0 || (strlen(g_udisk_file_name) - strlen("stb.log")) < 0 || strncmp(g_udisk_file_name + (strlen(g_udisk_file_name) - strlen("stb.log")), "stb.log", strlen("stb.log")) != 0) { soc_log_err("snprintf_s fail or file_name invalid [%s]!\n", g_udisk_file_name); return TD_FAILURE; } while (1) { set_file_flag = g_set_log_file_flag; set_current_state(TASK_INTERRUPTIBLE); if (osal_kthread_should_stop()) { break; } if (set_file_flag == TD_FALSE) { osal_msleep(10); /* 10ms polling */ continue; } ret = log_store_lock(); err_ret = memset_s(g_udisk_buf, sizeof(g_udisk_buf), 0, sizeof(g_udisk_buf)); if (err_ret != EOK) { soc_log_err("secure func call error\n"); log_store_unlock(); return TD_FAILURE; } ret = ext_drv_log_read_buf(g_udisk_buf, sizeof(g_udisk_buf) - 1, &read_len, &status, TD_TRUE); if (ret == TD_SUCCESS) { drv_log_udisk_save((const td_s8 *)g_udisk_file_name, g_udisk_buf, read_len); soc_log_info("b_status = %d\n", status); } log_store_unlock(); osal_msleep(10); /* save log every 10ms */ } return TD_SUCCESS; } td_s32 drv_log_udisk_init(const td_u8 *disk_folder) { if (disk_folder == TD_NULL) { return TD_FAILURE; } if (g_udisk_task == TD_NULL) { g_udisk_task = osal_kthread_create(drv_log_udisk_write_thread, (td_void *)disk_folder, "g_udisk_task", 0); if (g_udisk_task == TD_NULL) { soc_log_err("create new kernel thread failed\n"); return TD_FAILURE; } } return TD_SUCCESS; } td_s32 drv_log_udisk_exit(td_void) { if (g_udisk_task != TD_NULL) { osal_kthread_destroy(g_udisk_task, TD_TRUE); g_udisk_task = TD_NULL; } return TD_SUCCESS; } #endif td_void soc_log_simple_print(const td_char *format, ...) { va_list args; td_u32 msg_len; td_char log_str[LOG_MAX_TRACE_LEN] = {'a'}; log_str[LOG_MAX_TRACE_LEN - 0x1] = 'b'; log_str[LOG_MAX_TRACE_LEN - 0x2] = 'c'; va_start(args, format); msg_len = (td_u32)vsnprintf_s(log_str, sizeof(log_str), LOG_MAX_TRACE_LEN - 1, format, args); va_end(args); if (msg_len < 0) { return; } if (msg_len >= LOG_MAX_TRACE_LEN) { log_str[LOG_MAX_TRACE_LEN - 0x1] = '\0'; /* even the 'vsnprintf' commond will do it */ log_str[LOG_MAX_TRACE_LEN - 0x2] = '\n'; log_str[LOG_MAX_TRACE_LEN - 0x3] = '.'; log_str[LOG_MAX_TRACE_LEN - 0x4] = '.'; log_str[LOG_MAX_TRACE_LEN - 0x5] = '.'; } soc_print("%s", log_str); } td_void soc_log_print_block(td_u32 level, td_u32 module_id, const td_char *block, td_u32 size) { errno_t err_ret; td_s32 ret; td_u32 i; td_char str_out[LOG_BLOCK_BUFSIZE] = {0}; if (block == NULL) { return; } for (i = 0; i < size; i++) { ret = snprintf_s(&str_out[(i % LOG_BLOCK_PERLINE) * 3], /* 3 is offset */ (LOG_BLOCK_BUFSIZE - (i % LOG_BLOCK_PERLINE) * 3), 4, " %02X", block[i]); /* 4,3 is countsize */ if (ret == -1) { soc_print("snprintf_s failed!!!"); return; } if (((i + 1) % LOG_BLOCK_PERLINE) == 0) { soc_trace(level, module_id, " %s\n", str_out); err_ret = memset_s(str_out, sizeof(str_out), 0x00, sizeof(str_out)); if (err_ret != EOK) { soc_print("memset_s failed!!!"); return; } } } if (((i % LOG_BLOCK_PERLINE) != 0) && (i != 0)) { soc_trace(level, module_id, " %s\n", str_out); } } static td_void drv_log_adjust_str(char *log_str, td_u32 str_len, td_u32 log_cnt) { if ((log_str != TD_NULL) && (unlikely(log_cnt >= str_len))) { log_str[LOG_MAX_TRACE_LEN - 1] = '\0'; /* even the 'vsnprintf' commond will do it */ log_str[LOG_MAX_TRACE_LEN - 2] = '\n'; /* 2 表示log_str向左偏移2个字节 */ log_str[LOG_MAX_TRACE_LEN - 3] = '.'; /* 3 表示log_str向左偏移3个字节 */ log_str[LOG_MAX_TRACE_LEN - 4] = '.'; /* 4 表示log_str向左偏移4个字节 */ log_str[LOG_MAX_TRACE_LEN - 5] = '.'; /* 5 表示log_str向左偏移5个字节 */ log_cnt = LOG_MAX_TRACE_LEN; } return; } static td_void drv_log_print(soc_mod_id mod_id, log_level_t *log_level, char *log_str, td_u32 str_len, td_u32 log_cnt) { td_u32 n_pos; if (log_level->bbox_level == TD_TRUE) { log_get_rtc_time(log_str, str_len); rdr_print_to_file("%s", log_str); return; } n_pos = drv_log_get_print_pos(mod_id); switch (n_pos) { case LOG_OUTPUT_SERIAL: if ((mod_id == SOC_ID_VSYNC) || (mod_id == SOC_ID_ASYNC)) { break; } if (g_log_store_info.store_log_enable == TD_TRUE && log_level->memory_level == TD_TRUE) { log_get_rtc_time(log_str, str_len); ext_drv_log_write_buf((td_u8 *)log_str, log_cnt, LOG_MSG_FROM_KERNEL); } if (log_level->general_level == TD_TRUE) { log_get_rtc_time(log_str, str_len); soc_print("%s", log_str); } break; case LOG_OUTPUT_NETWORK: case LOG_OUTPUT_UDISK: #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) if (log_level->general_level == TD_TRUE) { log_get_rtc_time(log_str, str_len); ext_drv_log_write_buf((td_u8 *)log_str, log_cnt, LOG_MSG_FROM_KERNEL); } #endif break; default: soc_print("output pos %d invalid!\n", n_pos); } return; } static td_u32 soc_log_print_msg_process(char *log_serial, td_u32 level, td_u32 mod_id, const td_u8 *fn_name, td_u32 line_num) { td_s32 msg_len = 0; td_u32 buff_len = LOG_MAX_TRACE_LEN - LOG_RTC_TIME_LENGH; if (log_serial == NULL || fn_name == NULL) { soc_print("soc_log_print_msg_process input null\n"); return 0; } if (likely(g_log_init)) { msg_len = snprintf_s(log_serial, buff_len, buff_len - 1, "[%s-%s]:%s[%d]:", g_debug_level_name[level], g_log_cfg_info[mod_id].module_name, fn_name, line_num); if (msg_len < 0) { soc_print("soc_log_print_msg_process snprintf_s --failed\n"); return 0; } } return (td_u32)msg_len; } td_void soc_log_print(td_u32 level, td_u32 mod_id, const td_u8 *fn_name, td_u32 line_num, const td_char *format, ...) { va_list args; td_u32 msg_len; char log_str[LOG_MAX_TRACE_LEN] = {'a'}; td_u32 log_cnt = LOG_RTC_TIME_LENGH; char *log_serial = log_str + LOG_RTC_TIME_LENGH; char *log_msg_pos = TD_NULL; td_u32 buff_len = LOG_MAX_TRACE_LEN - LOG_RTC_TIME_LENGH; log_level_t log_level = { TD_FALSE, TD_FALSE, TD_FALSE }; if ((level > SOC_LOG_LEVEL_MAX) || (mod_id >= (LOG_CFG_BUF_SIZE / sizeof(log_cfg_info))) || (fn_name == TD_NULL)) { soc_print("ERR: invalid param, level:%#x, mod_id:%#x, fn_name:%p\n", level, mod_id, fn_name); return; } log_level_check(level, mod_id, &log_level); if (unlikely(log_level.memory_level == TD_TRUE || log_level.general_level == TD_TRUE)) { msg_len = soc_log_print_msg_process(log_serial, level, mod_id, fn_name, line_num); log_cnt += msg_len; log_str[LOG_MAX_TRACE_LEN - 1] = 'b'; log_str[LOG_MAX_TRACE_LEN - 2] = 'c'; /* 2 表示log_str向左偏移2个字节 */ if (likely(buff_len > msg_len)) { log_msg_pos = log_serial + msg_len; buff_len = buff_len - msg_len; va_start(args, format); msg_len = (td_u32)vsnprintf_s(log_msg_pos, buff_len, buff_len - 1, format, args); if (msg_len < 0) { va_end(args); return; } va_end(args); log_cnt += msg_len; } drv_log_adjust_str(log_str, LOG_MAX_TRACE_LEN, log_cnt); if (unlikely(g_log_init == 0)) { /* log module has not Initialized. */ soc_print("[%s-Unknow]: %s[%d]:%s", g_debug_level_name[level], fn_name, line_num, log_msg_pos); return; } /* log module has initialized. */ drv_log_print(mod_id, &log_level, log_str, LOG_MAX_TRACE_LEN, log_cnt); } return; } td_s32 drv_log_set_path(const td_char *path, td_u32 path_len, td_bool is_user_state) { td_s32 ret; if (path == TD_NULL || path_len >= sizeof(g_log_path_buf)) { return TD_FAILURE; } ret = log_file_lock(); if (ret != 0) { soc_log_err("down_interruptible failed\n"); return TD_FAILURE; } (td_void)memset_s(g_log_path_buf, sizeof(g_log_path_buf), 0, sizeof(g_log_path_buf)); if (is_user_state == TD_TRUE) { ret = (td_s32)osal_copy_from_user(g_log_path_buf, path, path_len); } else { ret = memcpy_s(g_log_path_buf, sizeof(g_log_path_buf), path, path_len); } if (ret != 0) { log_file_unlock(); return TD_FAILURE; } if (memcmp(g_log_path_buf, "/dev/null", strlen("/dev/null")) == 0) { g_set_log_file_flag = TD_FALSE; } else { g_set_log_file_flag = TD_TRUE; } g_log_cfg_info->udisk_flag = (td_u8)g_set_log_file_flag; g_udisk_log_file = g_log_path_buf; log_file_unlock(); return TD_SUCCESS; } td_s32 ext_drv_log_get_path(td_s8 *buf, td_u32 buf_len) { td_u32 path_len; td_s32 ret; /* not support log when uart close or user version */ #if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER) return TD_SUCCESS; #endif if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) { return TD_SUCCESS; } if (g_udisk_log_file == TD_NULL) { soc_log_err("g_udisk_log_file is NULL!\n"); return TD_FAILURE; } if (buf == TD_NULL) { soc_log_err("buf is NULL!\n"); return TD_FAILURE; } path_len = strlen(g_udisk_log_file) + 1; if (path_len > buf_len) { soc_log_err("path len is lager than buf len!\n"); return TD_FAILURE; } if (path_len == 1) { soc_log_info("no redirect to file!\n"); return TD_SUCCESS; } ret = memcpy_s(buf, buf_len, g_udisk_log_file, path_len); if (ret != EOK) { soc_log_err("memcpy_s fail\n"); return TD_FAILURE; } return TD_SUCCESS; } td_s32 drv_log_set_store_path(const td_char *path, td_u32 path_len, td_bool is_user_state) { td_s32 ret; /* not support log when uart close or user version */ #if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER) return TD_SUCCESS; #endif if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) { return TD_SUCCESS; } if (path == TD_NULL || path_len >= sizeof(g_store_path_buf)) { return TD_FAILURE; } ret = log_file_lock(); if (ret != 0) { soc_log_err("down_interruptible failed\n"); return TD_FAILURE; } (td_void)memset_s(g_store_path_buf, sizeof(g_store_path_buf), 0, sizeof(g_store_path_buf)); if (is_user_state == TD_TRUE) { ret = (td_s32)osal_copy_from_user(g_store_path_buf, path, path_len); } else { ret = memcpy_s(g_store_path_buf, sizeof(g_store_path_buf), path, path_len); } if (ret != 0) { log_file_unlock(); return TD_FAILURE; } g_store_path = g_store_path_buf; log_file_unlock(); return TD_SUCCESS; } td_s32 ext_drv_log_get_store_path(td_s8 *buf, td_u32 buf_len) { td_u32 path_len; td_s32 ret; if (g_store_path == TD_NULL || buf == TD_NULL) { return TD_FAILURE; } path_len = strlen(g_store_path) + 1; if (path_len > buf_len || path_len <= 1) { return TD_FAILURE; } ret = memcpy_s(buf, buf_len, g_store_path, path_len); if (ret != EOK) { return TD_FAILURE; } return TD_SUCCESS; } td_s32 ext_drv_log_set_size(td_u32 size) { td_s32 ret; if (size > LOG_MAX_FILE_SIZE || size < LOG_MIN_FILE_SIZE) { soc_log_err("Logsize(%dMB) is out of range(%dMB~%dMB)\n", size, LOG_MIN_FILE_SIZE, LOG_MAX_FILE_SIZE); return TD_FAILURE; } ret = log_file_lock(); if (ret != 0) { soc_log_err("down_interruptible failed\n"); return TD_FAILURE; } g_default_log_size = size * 1024 * 1024; /* 1024 * 1024 means 1k */ log_file_unlock(); soc_log_info("set log file size as %d MB\n", g_default_log_size); return TD_SUCCESS; } td_s32 ext_drv_log_get_level(td_u32 mod_id, soc_log_level *log_level) { if (g_log_init == TD_FALSE || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info) || log_level == TD_NULL) { return TD_FAILURE; } *log_level = (soc_log_level)g_log_cfg_info[mod_id].log_level; return TD_SUCCESS; } static td_s32 drv_log_cfg_info_init(td_void) { td_u32 i; td_s32 ret; g_log_cfg_buf.dmabuf = osal_mem_alloc("CMN_LogInfo", LOG_CFG_BUF_SIZE, OSAL_MMZ_TYPE, TD_NULL, 0); if (IS_ERR_OR_NULL(g_log_cfg_buf.dmabuf)) { soc_log_err("osal_mem_alloc failed!\n"); return TD_FAILURE; } g_log_cfg_buf.virt_addr = (td_u8 *)osal_mem_kmap(g_log_cfg_buf.dmabuf, 0, TD_FALSE); if (IS_ERR_OR_NULL(g_log_cfg_buf.virt_addr)) { osal_mem_free(g_log_cfg_buf.dmabuf); soc_log_err("dma_buf_kmap failed!\n"); return TD_FAILURE; } osal_mem_flush(g_log_cfg_buf.dmabuf); ret = memset_s(g_log_cfg_buf.virt_addr, LOG_CFG_BUF_SIZE, 0, LOG_CFG_BUF_SIZE); if (ret != EOK) { osal_mem_free(g_log_cfg_buf.dmabuf); soc_log_err("memset_s error!\n"); return TD_FAILURE; } g_log_cfg_info = (log_cfg_info *)g_log_cfg_buf.virt_addr; g_log_cfg_info->udisk_flag = 0; /* max debug module number: 8192/28 = 341/292 */ for (i = 0; i < LOG_CFG_BUF_SIZE / sizeof(log_cfg_info); i++) { g_log_cfg_info[i].log_level = (td_u8)g_default_log_level; g_log_cfg_info[i].log_print_pos = LOG_OUTPUT_SERIAL; g_log_cfg_info[i].log_quota = DEFAULT_LOG_QUOTA; ret = snprintf_s(g_log_cfg_info[i].module_name, sizeof(g_log_cfg_info[i].module_name), sizeof(g_log_cfg_info[i].module_name) - 1, "Invalid"); if (ret < 0) { osal_mem_free(g_log_cfg_buf.dmabuf); soc_log_err("snprintf_s error!\n"); return TD_FAILURE; } } return TD_SUCCESS; } static td_s32 drv_log_cfg_info_exit(td_void) { if (g_log_cfg_buf.virt_addr != 0) { osal_mem_kunmap(g_log_cfg_buf.dmabuf, (td_void *)g_log_cfg_buf.virt_addr, 0); osal_mem_free(g_log_cfg_buf.dmabuf); g_log_cfg_info = TD_NULL; } return TD_SUCCESS; } #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) static td_s32 drv_log_buf_init(td_u32 size) { (td_void)memset_s(&g_log_msg_info, sizeof(g_log_msg_info), 0, sizeof(g_log_msg_info)); g_log_msg_info.buf_size = size; osal_wait_init(&g_log_msg_info.wq_no_data); g_log_msg_buf.dmabuf = osal_mem_alloc("CMN_LogTrace", size, OSAL_MMZ_TYPE, TD_NULL, 0); if (IS_ERR_OR_NULL(g_log_msg_buf.dmabuf)) { soc_log_err("ion_alloc_dmabuf failed!\n"); osal_wait_destroy(&g_log_msg_info.wq_no_data); return TD_FAILURE; } g_log_msg_buf.virt_addr = (td_u8 *)osal_mem_kmap(g_log_msg_buf.dmabuf, 0, TD_FALSE); if (IS_ERR_OR_NULL(g_log_msg_buf.virt_addr)) { soc_log_err("dma_buf_kmap failed!\n"); osal_mem_free(g_log_msg_buf.dmabuf); osal_wait_destroy(&g_log_msg_info.wq_no_data); return TD_FAILURE; } (td_void)memset_s(g_log_msg_buf.virt_addr, size, 0, size); g_log_msg_info.start_virt_addr = g_log_msg_buf.virt_addr; return TD_SUCCESS; } static td_s32 drv_log_buf_exit(td_void) { if (g_log_msg_buf.virt_addr != TD_NULL) { osal_mem_kunmap(g_log_msg_buf.dmabuf, (td_void *)g_log_msg_buf.virt_addr, 0); osal_mem_free(g_log_msg_buf.dmabuf); osal_wait_destroy(&g_log_msg_info.wq_no_data); g_log_msg_info.start_virt_addr = TD_NULL; } return TD_SUCCESS; } #endif static td_s32 drv_log_get_cfg_buf_fd(td_mem_handle_t *fd) { td_s32 ret = TD_FAILURE; td_mem_handle_t buf_fd; td_u32 idx; td_u32 module_num = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info); /* process register module log feature */ for (idx = 0; idx < module_num; idx++) { drv_log_set_module(idx); } if (g_log_init == TD_TRUE && g_log_cfg_buf.dmabuf != TD_NULL) { buf_fd = osal_mem_create_fd(g_log_cfg_buf.dmabuf, O_CLOEXEC); if (buf_fd < 0) { soc_log_err("ext_dma_buf_fd failed!\n"); *fd = 0; } else { *fd = buf_fd; ret = TD_SUCCESS; } } else { soc_log_err("Log is not init!\n"); *fd = 0; } return ret; } static td_s32 drv_log_put_cfg_buf_fd(td_mem_handle_t fd) { if (fd < 0) { soc_log_err("invalid fd!\n"); return TD_FAILURE; } osal_mem_close_fd((long)fd); return TD_SUCCESS; } td_s32 drv_log_init(td_void) { #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) ext_chip_name_id chip_name_id; #endif osal_dts_get_u32_byname("huanglong,common", "log_level", &g_default_log_level); if (drv_log_cfg_info_init() != TD_SUCCESS) { return TD_FAILURE; } #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) ext_drv_sys_get_chip_name_id(&chip_name_id); /* on reserved5, MMZ size is only 8M, therfore, the size of log MMZ reduce to 512K */ if ((chip_name_id == CHIP_NAME_RESERVED5) || (chip_name_id == CHIP_NAME_RESERVED2)) { g_log_buf_size = 0x80 * LOG_MSG_BUF_RESERVE; } else if ((chip_name_id == CHIP_NAME_RESERVED13) || (chip_name_id == CHIP_NAME_RESERVED9) || (chip_name_id == CHIP_NAME_RESERVED6) || (chip_name_id == CHIP_NAME_RESERVED8)) { g_log_buf_size = 0xa * 0x100 * LOG_MSG_BUF_RESERVE; /* 10M buf size for NPU save log */ } else { soc_log_info("unspport chip_type chip_version, g_log_bu_size use default value 10M. \n"); g_log_buf_size = LOG_MSG_BUF_RESERVE; } if (drv_log_buf_init(g_log_buf_size) != TD_SUCCESS) { drv_log_cfg_info_exit(); return TD_FAILURE; } #endif if (drv_log_add_module("ASYNC", (td_u32)SOC_ID_ASYNC) != TD_SUCCESS) { #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) drv_log_buf_exit(); #endif drv_log_cfg_info_exit(); return TD_FAILURE; } if (drv_log_add_module("VSYNC", (td_u32)SOC_ID_VSYNC) != TD_SUCCESS) { drv_log_remove_module((td_u32)SOC_ID_ASYNC); #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) drv_log_buf_exit(); #endif drv_log_cfg_info_exit(); return TD_FAILURE; } g_log_init = TD_TRUE; osal_sem_init(&g_log_k_mutex, 1); osal_sem_init(&g_log_store_mutex, 1); osal_wait_init(&g_log_store_info.poll_wait_queue); osal_klib_set_store_path(g_store_path); return TD_SUCCESS; } td_void drv_log_exit(td_void) { g_log_init = TD_FALSE; osal_sem_destroy(&g_log_k_mutex); osal_sem_destroy(&g_log_store_mutex); osal_wait_destroy(&g_log_store_info.poll_wait_queue); #ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT if (drv_log_udisk_exit() != TD_SUCCESS) { soc_log_err("drv_log_udisk_exit error!\n"); return; } #endif #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) if (drv_log_buf_exit() != TD_SUCCESS) { soc_log_err("drv_log_buf_exit error!\n"); return; } #endif if (drv_log_cfg_info_exit() != TD_SUCCESS) { soc_log_err("drv_log_cfg_info_exit error!\n"); return; } } #ifndef MODULE /* Legacy boot options - nonmodular */ static td_s32 __init drv_log_get_buf_size(td_char *str) { g_log_buf_size = simple_strtol(str, TD_NULL, 0); soc_log_info("g_log_buf_size = 0x%x\n", g_log_buf_size); return 1; } __setup("g_log_buf_size=", drv_log_get_buf_size); #endif EXPORT_SYMBOL(ext_drv_log_read_buf); EXPORT_SYMBOL(ext_drv_log_write_buf); EXPORT_SYMBOL(ext_drv_log_get_store_path); EXPORT_SYMBOL(ext_drv_log_get_level); EXPORT_SYMBOL(soc_log_print); EXPORT_SYMBOL(soc_log_print_block); EXPORT_SYMBOL(soc_log_simple_print); #ifdef MODULE module_param(g_log_buf_size, int, S_IRUGO); module_param(g_udisk_log_file, charp, S_IRUGO); module_param(g_store_path, charp, S_IRUGO); EXPORT_SYMBOL(g_store_path); #endif static td_s32 drv_log_find_module(const td_char *s) { td_u32 i; td_u32 cnt = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info); for (i = 0; i < cnt; i++) { if (!strncasecmp(g_log_cfg_info[i].module_name, s, sizeof(g_log_cfg_info[i].module_name))) { return i; } } return -1; } static td_s32 drv_log_process_proc_help(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { if (g_log_init == TD_FALSE) { soc_log_err("Log is not init!\n"); return TD_FAILURE; } osal_proc_echo("\n=========================================================log" "=============================================================================================\n"); osal_proc_echo("echo command para1 para2 path " "explanation\n"); osal_proc_echo("echo loglevel SOC_DEMUX 2 >/proc/msp/log " "modify the log level of the SOC_DEMUX to 2\n"); osal_proc_echo(" " "para1(module_name) para2(0:ALERT 1:FATAL 2:ERROR WARN:3 NOTICE:4 INFO:5 DEBUG:6 TRACE:7)\n"); osal_proc_echo("echo loglevel all 2 >/proc/msp/log " "modify the log level of all module to 2\n"); osal_proc_echo(" " "para1(module_name) para2(0:ALERT 1:FATAL 2:ERROR WARN:3 NOTICE:4 INFO:5 DEBUG:6 TRACE:7)\n"); osal_proc_echo("echo logsize 12 >/proc/msp/log " "set log size as 12 MB para1(1M~120MB)\n"); osal_proc_echo("echo logpath /tmp >/proc/msp/log " "set log path as /tmp para1(log path)\n"); osal_proc_echo("echo logpath /dev/null >/proc/msp/log " "close log udisk output para1(log path)\n"); osal_proc_echo("echo storepath /mnt >/proc/msp/log " "set the debug file store path as /mnt para1(store path)\n"); osal_proc_echo("============================================================" "=============================================================================================\n"); return TD_SUCCESS; } static td_s32 drv_log_process_proc_level(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { td_char *module = TD_NULL; td_u8 level; td_s32 idx; td_u32 module_num = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info); if (g_log_init == TD_FALSE) { soc_log_err("Log is not init!\n"); return TD_FAILURE; } if (argc != 3) { /* the number of required paras is 3 */ soc_log_err("argc is invalid!\n"); return TD_FAILURE; } module = argv[1]; /* the first para(1) is module name */ level = argv[2][0] - '0'; /* the second para(2) is log level */ if (level >= SOC_LOG_LEVEL_MAX) { soc_log_err("level is invalid!\n"); return TD_FAILURE; } if (!strncasecmp("all", module, sizeof("all"))) { for (idx = 0; idx < module_num; idx++) { g_log_cfg_info[idx].log_level = level; } return TD_SUCCESS; } idx = drv_log_find_module(module); if (idx == -1) { soc_log_err("%s is not registered!\n", module); return TD_FAILURE; } g_log_cfg_info[idx].log_level = level; return TD_SUCCESS; } static td_s32 drv_log_process_proc_size(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { td_u32 log_size; if (g_log_init == TD_FALSE) { soc_log_err("Log is not init!\n"); return TD_FAILURE; } if (argc != 2) { /* the number of required paras is 2 */ soc_log_err("argc is invalid!\n"); return TD_FAILURE; } if (strstr(argv[1], "0x") || strstr(argv[1], "0X")) { log_size = simple_strtoul(argv[1], TD_NULL, 16); /* the first para(1) is log size, 16 base conversion */ } else { log_size = simple_strtoul(argv[1], TD_NULL, 10); /* the first para(1) is log size, 10 base conversion */ } if (log_size > LOG_MAX_FILE_SIZE || log_size < LOG_MIN_FILE_SIZE) { soc_log_err("size is invalid!\n"); return TD_FAILURE; } return ext_drv_log_set_size(log_size); } td_s32 log_drv_udisk_store_init(td_void) { #ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT td_s32 ret; ret = drv_log_udisk_init(g_udisk_log_file); if (ret != TD_SUCCESS) { soc_log_err("call log_udisk_init failed!\n"); return TD_FAILURE; } #endif return TD_SUCCESS; } td_s32 log_drv_udisk_store_deinit(td_void) { #ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT td_s32 ret; g_log_cfg_info->udisk_flag = (td_u8)g_set_log_file_flag; soc_log_info("set log path is g_log_path_buf = %s\n", g_udisk_log_file); ret = drv_log_udisk_exit(); if (ret != TD_SUCCESS) { soc_log_err("call drv_log_udisk_exit failed!\n"); return TD_FAILURE; } #endif return TD_SUCCESS; } static td_s32 drv_log_process_proc_path(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { td_s32 ret; errno_t err_ret; if (argc < 2) { /* argc at least 2 */ soc_log_err("param invalid! argc = %d\n", argc); return TD_FAILURE; } if (strlen(argv[1]) >= sizeof(g_log_path_buf)) { /* 命令的第1个参数 */ soc_log_err("log path length is over than %d!\n", sizeof(g_log_path_buf)); return TD_FAILURE; } ret = log_file_lock(); if (ret != 0) { soc_log_err("down_interruptible failed\n"); return TD_FAILURE; } err_ret = memcpy_s(g_log_path_buf, LOG_MAX_FILE_NAME_LENTH, argv[1], strlen(argv[1]) + 1); /* 命令的第1个参数 */ if (err_ret != EOK) { log_file_unlock(); soc_log_err("secure func call error\n"); return TD_FAILURE; } g_udisk_log_file = g_log_path_buf; if (memcmp(g_log_path_buf, "/dev/null", strlen("/dev/null")) != 0) { ret = log_drv_udisk_store_init(); if (ret != TD_SUCCESS) { log_file_unlock(); soc_log_err("log_drv_udisk_store_init failed ... \n"); return ret; } g_set_log_file_flag = TD_TRUE; if (g_log_store_info.store_log_thread_exist == TD_TRUE) { g_log_store_info.store_log_enable = TD_FALSE; } } else { g_set_log_file_flag = TD_FALSE; if (g_log_store_info.store_log_thread_exist == TD_TRUE) { g_log_store_info.store_log_enable = TD_TRUE; } ret = log_drv_udisk_store_deinit(); log_file_unlock(); return ret; } g_log_cfg_info->udisk_flag = (td_u8)g_set_log_file_flag; log_file_unlock(); soc_log_info("set log path is g_log_path_buf = %s\n", g_udisk_log_file); return TD_SUCCESS; } static td_s32 drv_log_process_proc_store_path(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { errno_t err_ret; if (argc < 2) { /* argc at least 2 */ soc_log_err("param invalid! argc = %d\n", argc); return TD_FAILURE; } if (strlen(argv[1]) >= sizeof(g_store_path_buf)) { /* 命令的第1个参数 */ soc_log_err("store path length is over than %d!\n", sizeof(g_store_path_buf)); return TD_FAILURE; } log_file_lock(); err_ret = memset_s(g_store_path_buf, LOG_MAX_FILE_NAME_LENTH, 0, sizeof(g_store_path_buf)); if (err_ret != EOK) { log_file_unlock(); soc_log_err("secure func call error\n"); return TD_FAILURE; } err_ret = memcpy_s(g_store_path_buf, LOG_MAX_FILE_NAME_LENTH, argv[1], strlen(argv[1])); /* 命令的第1个参数 */ if (err_ret != EOK) { log_file_unlock(); soc_log_err("secure func call error\n"); return TD_FAILURE; } g_store_path = g_store_path_buf; log_file_unlock(); soc_log_info("set log path is store_path = %s\n", g_store_path_buf); return TD_SUCCESS; } static osal_proc_cmd g_proc_cmd[] = { {"help", drv_log_process_proc_help}, {"loglevel", drv_log_process_proc_level}, {"logsize", drv_log_process_proc_size}, {"logpath", drv_log_process_proc_path}, {"storepath", drv_log_process_proc_store_path} }; static td_void print_loglevel_helpinfo(td_void *s) { td_u32 i; osal_seq_printf(s, "------------------support_log_level -----------------\n"); osal_seq_printf(s, "loglevel |level_val |\n"); for (i = 0; i < SOC_LOG_LEVEL_MAX; i++) { osal_seq_printf(s, "%-18s|%-33d|\n", g_debug_level_name[i], i); } return; } td_s32 drv_log_read_proc(td_void *s, td_void *arg) { td_u32 i; td_u8 level; td_char path[LOG_MAX_FILE_NAME_LENTH] = {0}; td_u32 cnt = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info); if (g_log_init == TD_FALSE) { osal_seq_printf(s, "Log is not init!\n"); return TD_SUCCESS; } if (ext_drv_log_get_path(path, sizeof(path)) != TD_SUCCESS) { soc_log_err("ext_drv_log_get_path failed!\n"); return TD_FAILURE; } osal_seq_printf(s, "\n[log] %s\n", VERSION_STRING); osal_seq_printf(s, "------------------log_path---------------------------\n"); osal_seq_printf(s, "log_path :%-33s|\n", path); if (ext_drv_log_get_store_path(path, sizeof(path)) != TD_SUCCESS) { soc_log_err("ext_drv_log_get_store_path failed!\n"); return TD_FAILURE; } osal_seq_printf(s, "------------------store_path-------------------------\n"); osal_seq_printf(s, "store_path :%-33s|\n", path); osal_seq_printf(s, "------------------Store Path-------------------------\n"); osal_seq_printf(s, "maxlogsize(MB) :%-33u|\n", (g_default_log_size / 1024U / 1024U)); osal_seq_printf(s, "------------------module_log_level-------------------\n"); osal_seq_printf(s, "Log_module |Level |\n"); for (i = 0; i < cnt; i++) { drv_log_set_module(i); if (strncmp(g_log_cfg_info[i].module_name, "Invalid", 0x8)) { level = g_log_cfg_info[i].log_level; if (level <= SOC_LOG_LEVEL_MAX) { osal_seq_printf(s, "%-18s|%1d(%-6s) |\n", g_log_cfg_info[i].module_name, level, g_debug_level_name[level]); } } } print_loglevel_helpinfo(s); osal_seq_printf(s, "=====================================================\n"); return TD_SUCCESS; } td_s32 drv_log_add_proc(td_void) { osal_proc_entry *item = TD_NULL; item = osal_proc_add(SOC_MOD_LOG_NAME, strlen(SOC_MOD_LOG_NAME)); if (item == TD_NULL) { soc_log_err("add proc failed!\n"); return TD_FAILURE; } item->read = drv_log_read_proc; item->cmd_cnt = sizeof(g_proc_cmd) / sizeof(osal_proc_cmd); item->cmd_list = g_proc_cmd; return TD_SUCCESS; } td_void drv_log_remove_proc(td_void) { osal_proc_remove(SOC_MOD_LOG_NAME, strlen(SOC_MOD_LOG_NAME)); } td_s32 drv_log_network_or_udisk_read(td_u32 cmd, td_void *arg) { log_read_buf *para = (log_read_buf *)arg; if (cmd != LOG_CMPI_READ) { soc_log_err("cmd is not LOG_CMPI_READ.\n"); return TD_FAILURE; } if (para == TD_NULL || para->msg_addr == TD_NULL) { soc_log_err("User buffer is null!\n"); return TD_FAILURE; } if (para->magic_num != LOG_MAGIC_NUM) { soc_log_err("User buffer is likely illegal!\n"); return TD_FAILURE; } return ext_drv_log_read_buf(para->msg_addr, para->buf_len, ¶->copy_len, ¶->task_status, TD_FALSE); } td_s32 drv_log_network_or_udisk_write(td_u32 cmd, const td_void *arg) { log_write_buf *para = (log_write_buf *)arg; if (cmd != LOG_CMPI_WRITE) { soc_log_err("cmd is not LOG_CMPI_WRITE \n"); return TD_FAILURE; } if (para == TD_NULL || para->msg_addr == TD_NULL) { soc_log_err("User buffer is null!\n"); return TD_FAILURE; } return ext_drv_log_write_buf(para->msg_addr, para->msg_len, LOG_MSG_FROM_USER); } td_s32 drv_log_ioctl(td_u32 cmd, td_void *arg, td_void *private_data) { if (arg == TD_NULL) { soc_log_err("param arg invalid!\n"); return TD_FAILURE; } switch (cmd) { case LOG_CMPI_INIT: { td_mem_handle_t *fd = (td_mem_handle_t *)arg; return drv_log_get_cfg_buf_fd(fd); } case LOG_CMPI_EXIT: { td_mem_handle_t *fd = (td_mem_handle_t *)arg; return drv_log_put_cfg_buf_fd(*fd); } #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) case LOG_CMPI_READ: { return drv_log_network_or_udisk_read(cmd, arg); } case LOG_CMPI_WRITE: { return drv_log_network_or_udisk_write(cmd, arg); } #endif case LOG_CMPI_SET_SIZE: { td_u32 *size = (td_u32 *)arg; return ext_drv_log_set_size(*size); } case LOG_CMPI_STORE_ENABLE: { drv_log_store_enable((td_bool *)arg); return TD_SUCCESS; } case LOG_CMPI_GET_STORE_STATUS: { log_store_status *param = (log_store_status *)arg; drv_log_get_store_status(&(param->log_store_enable), &(param->log_store_thread_exist)); return TD_SUCCESS; } default: soc_log_err("unknown command 0x%x\n", cmd); return TD_FAILURE; } } #ifdef CONFIG_COMPAT td_s32 drv_log_compat_ioctl(unsigned int cmd, td_void *arg, td_void *private_data) { switch (cmd) { #if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT) case LOG_CMPI_COMPAT_READ: { log_compat_read_buf *para = (log_compat_read_buf *)arg; if (para == TD_NULL || (td_u8 *)compat_ptr(para->msg_addr) == TD_NULL) { soc_log_err("User buffer is null!\n"); return TD_FAILURE; } if (para->magic_num != LOG_MAGIC_NUM) { soc_log_err("User buffer is likely illegal!\n"); return TD_FAILURE; } return ext_drv_log_read_buf((td_u8 *)compat_ptr(para->msg_addr), para->buf_len, ¶->copy_len, ¶->task_status, TD_FALSE); } case LOG_CMPI_COMPAT_WRITE: { log_compat_write_buf *para = (log_compat_write_buf *)arg; if (para == TD_NULL || (td_u8 *)compat_ptr(para->msg_addr) == TD_NULL) { soc_log_err("User buffer is null!\n"); return TD_FAILURE; } return ext_drv_log_write_buf((td_u8 *)compat_ptr(para->msg_addr), para->msg_len, LOG_MSG_FROM_USER); } #endif default: return drv_log_ioctl(cmd, arg, private_data); } return -ENOIOCTLCMD; } #endif