From 930ce6e142354268d11ec9fe5cf6f4fc66a8f1f0 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Sep 2014 10:26:20 +0200 Subject: Introduce message logging support This adds a buffer for log messages and a 'dmesg' command to print the messages. The log buffer is implemented as log objects rather than a string buffer. This makes it easy to implement limiting the messages, cleaning the buffer and timestamping the messages. Signed-off-by: Sascha Hauer --- common/console_common.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 126 insertions(+), 3 deletions(-) (limited to 'common/console_common.c') diff --git a/common/console_common.c b/common/console_common.c index cc184dfaef..cc25f97d9d 100644 --- a/common/console_common.c +++ b/common/console_common.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #ifndef CONFIG_CONSOLE_NONE @@ -59,31 +62,151 @@ void console_allow_input(bool val) int barebox_loglevel = CONFIG_DEFAULT_LOGLEVEL; +LIST_HEAD(barebox_logbuf); +static int barebox_logbuf_num_messages; +static int barebox_log_max_messages = 1000; + +static void log_del(struct log_entry *log) +{ + free(log->msg); + list_del(&log->list); + free(log); + barebox_logbuf_num_messages--; +} + +/** + * log_clean - delete log messages from buffer + * + * @limit: The maximum messages left in the buffer after + * calling this function. + * + * This function deletes all messages in the logbuf exeeding + * the limit. + */ +void log_clean(unsigned int limit) +{ + struct log_entry *log, *tmp; + + if (list_empty(&barebox_logbuf)) + return; + + list_for_each_entry_safe(log, tmp, &barebox_logbuf, list) { + if (barebox_logbuf_num_messages <= limit) + break; + log_del(log); + } +} + +void pr_puts(int level, const char *str) +{ + struct log_entry *log; + + if (IS_ENABLED(CONFIG_LOGBUF)) { + if (barebox_log_max_messages > 0) + log_clean(barebox_log_max_messages - 1); + + if (barebox_log_max_messages >= 0) { + log = xzalloc(sizeof(*log)); + log->msg = xstrdup(str); + log->timestamp = get_time_ns(); + log->level = level; + list_add_tail(&log->list, &barebox_logbuf); + barebox_logbuf_num_messages++; + } + } + + if (level > barebox_loglevel) + return; + + puts(str); +} + int pr_print(int level, const char *fmt, ...) { va_list args; uint i; char printbuffer[CFG_PBSIZE]; - if (level > barebox_loglevel) + if (!IS_ENABLED(CONFIG_LOGBUF) && level > barebox_loglevel) return 0; va_start(args, fmt); i = vsprintf(printbuffer, fmt, args); va_end(args); - /* Print the string */ - puts(printbuffer); + pr_puts(level, printbuffer); return i; } +int dev_printf(int level, const struct device_d *dev, const char *format, ...) +{ + va_list args; + int ret = 0; + char printbuffer[CFG_PBSIZE]; + + if (!IS_ENABLED(CONFIG_LOGBUF) && level > barebox_loglevel) + return 0; + + if (dev->driver && dev->driver->name) + ret += sprintf(printbuffer, "%s ", dev->driver->name); + + ret += sprintf(printbuffer + ret, "%s: ", dev_name(dev)); + + va_start(args, format); + + ret += vsprintf(printbuffer + ret, format, args); + + va_end(args); + + pr_puts(level, printbuffer); + + return ret; +} + static int loglevel_init(void) { + if (IS_ENABLED(CONFIG_LOGBUF)) + globalvar_add_simple_int("log_max_messages", + &barebox_log_max_messages, "%d"); + return globalvar_add_simple_int("loglevel", &barebox_loglevel, "%d"); } device_initcall(loglevel_init); +void log_print(unsigned flags) +{ + struct log_entry *log; + unsigned long last = 0; + + list_for_each_entry(log, &barebox_logbuf, list) { + uint64_t diff = log->timestamp - time_beginning; + unsigned long difful; + + do_div(diff, 1000); + difful = diff; + + if (!log->timestamp) + difful = 0; + + if (flags & (BAREBOX_LOG_PRINT_TIME | BAREBOX_LOG_DIFF_TIME)) + printf("["); + + if (flags & BAREBOX_LOG_PRINT_TIME) + printf("%10luus", difful); + + if (flags & BAREBOX_LOG_DIFF_TIME) { + printf(" < %10luus", difful - last); + last = difful; + } + + if (flags & (BAREBOX_LOG_PRINT_TIME | BAREBOX_LOG_DIFF_TIME)) + printf("] "); + + printf("%s", log->msg); + } +} + int printf(const char *fmt, ...) { va_list args; -- cgit v1.2.3