summaryrefslogtreecommitdiffstats
path: root/common/console_common.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-09-30 10:26:20 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-09-30 15:33:22 +0200
commit930ce6e142354268d11ec9fe5cf6f4fc66a8f1f0 (patch)
treed924b3a215a8dac31e35c1e83ebf3440545d353e /common/console_common.c
parent6ae9a40c799dd341db985c95cc906ae2e0aacf97 (diff)
downloadbarebox-930ce6e142354268d11ec9fe5cf6f4fc66a8f1f0.tar.gz
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 <s.hauer@pengutronix.de>
Diffstat (limited to 'common/console_common.c')
-rw-r--r--common/console_common.c129
1 files changed, 126 insertions, 3 deletions
diff --git a/common/console_common.c b/common/console_common.c
index cc184df..cc25f97 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -27,6 +27,9 @@
#include <globalvar.h>
#include <magicvar.h>
#include <password.h>
+#include <clock.h>
+#include <malloc.h>
+#include <asm-generic/div64.h>
#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;