summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2021-05-08 07:00:06 -0600
committerTom Rini <trini@konsulko.com>2021-06-08 11:39:09 -0400
commit58b4b7133aba6fbb2409a975478157f9277c2e91 (patch)
tree134665e40bcbbfd82b1e42729c11f00de345390d
parent0cceb99ac59b1d383488ea3ce6511ffc01da5332 (diff)
downloadu-boot-58b4b7133aba6fbb2409a975478157f9277c2e91.tar.gz
u-boot-58b4b7133aba6fbb2409a975478157f9277c2e91.tar.bz2
u-boot-58b4b7133aba6fbb2409a975478157f9277c2e91.zip
log: Add support for logging a buffer
The print_buffer() function is very useful for debugging. Add a version of this in the log system also. Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--common/log.c30
-rw-r--r--include/log.h35
-rw-r--r--test/log/log_test.c27
3 files changed, 92 insertions, 0 deletions
diff --git a/common/log.c b/common/log.c
index ea407c6db9..1aaa6c1527 100644
--- a/common/log.c
+++ b/common/log.c
@@ -284,6 +284,36 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
return 0;
}
+#define MAX_LINE_LENGTH_BYTES 64
+#define DEFAULT_LINE_LENGTH_BYTES 16
+
+int _log_buffer(enum log_category_t cat, enum log_level_t level,
+ const char *file, int line, const char *func, ulong addr,
+ const void *data, uint width, uint count, uint linelen)
+{
+ if (linelen * width > MAX_LINE_LENGTH_BYTES)
+ linelen = MAX_LINE_LENGTH_BYTES / width;
+ if (linelen < 1)
+ linelen = DEFAULT_LINE_LENGTH_BYTES / width;
+
+ while (count) {
+ uint thislinelen;
+ char buf[HEXDUMP_MAX_BUF_LENGTH(width * linelen)];
+
+ thislinelen = hexdump_line(addr, data, width, count, linelen,
+ buf, sizeof(buf));
+ assert(thislinelen >= 0);
+ _log(cat, level, file, line, func, "%s\n", buf);
+
+ /* update references */
+ data += thislinelen * width;
+ addr += thislinelen * width;
+ count -= thislinelen;
+ }
+
+ return 0;
+}
+
int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[],
enum log_level_t level, const char *file_list,
int flags)
diff --git a/include/log.h b/include/log.h
index add3a1e4a0..feb0204855 100644
--- a/include/log.h
+++ b/include/log.h
@@ -140,6 +140,24 @@ static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
return 0;
}
+/**
+ * _log_buffer - Internal function to print data buffer in hex and ascii form
+ *
+ * @cat: Category of log record (indicating which subsystem generated it)
+ * @level: Level of log record (indicating its severity)
+ * @file: File name of file where log record was generated
+ * @line: Line number in file where log record was generated
+ * @func: Function where log record was generated
+ * @addr: Starting address to display at start of line
+ * @data: pointer to data buffer
+ * @width: data value width. May be 1, 2, or 4.
+ * @count: number of values to display
+ * @linelen: Number of values to print per line; specify 0 for default length
+ */
+int _log_buffer(enum log_category_t cat, enum log_level_t level,
+ const char *file, int line, const char *func, ulong addr,
+ const void *data, uint width, uint count, uint linelen);
+
/* Define this at the top of a file to add a prefix to debug messages */
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
@@ -200,8 +218,25 @@ static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
__LINE__, __func__, \
pr_fmt(_fmt), ##_args); \
})
+
+/* Emit a dump if the level is less that the maximum */
+#define log_buffer(_cat, _level, _addr, _data, _width, _count, _linelen) ({ \
+ int _l = _level; \
+ if (_LOG_DEBUG != 0 || _l <= _LOG_MAX_LEVEL) \
+ _log_buffer((enum log_category_t)(_cat), \
+ (enum log_level_t)(_l | _LOG_DEBUG), __FILE__, \
+ __LINE__, __func__, _addr, _data, \
+ _width, _count, _linelen); \
+ })
#else
#define log(_cat, _level, _fmt, _args...)
+
+#define log_buffer(_cat, _level, _addr, _data, _width, _count, _linelen) ({ \
+ int _l = _level; \
+ if (_LOG_DEBUG != 0 || _l <= LOGL_INFO || \
+ (_DEBUG && _l == LOGL_DEBUG)) \
+ print_buffer(_addr, _data, _width, _count, _linelen); \
+ })
#endif
#define log_nop(_cat, _level, _fmt, _args...) ({ \
diff --git a/test/log/log_test.c b/test/log/log_test.c
index 4a814ff413..f1e67509c1 100644
--- a/test/log/log_test.c
+++ b/test/log/log_test.c
@@ -429,3 +429,30 @@ int log_test_dropped(struct unit_test_state *uts)
return 0;
}
LOG_TEST_FLAGS(log_test_dropped, UT_TESTF_CONSOLE_REC);
+
+/* Check log_buffer() */
+int log_test_buffer(struct unit_test_state *uts)
+{
+ u8 *buf;
+ int i;
+
+ buf = malloc(0x20);
+ ut_assertnonnull(buf);
+ memset(buf, '\0', 0x20);
+ for (i = 0; i < 0x11; i++)
+ buf[i] = i * 0x11;
+
+ ut_assertok(console_record_reset_enable());
+ log_buffer(LOGC_BOOT, LOGL_INFO, 0, buf, 1, 0x12, 0);
+
+ /* This one should product no output due to the debug level */
+ log_buffer(LOGC_BOOT, LOGL_DEBUG, 0, buf, 1, 0x12, 0);
+
+ ut_assert_nextline("00000000: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ..\"3DUfw........");
+ ut_assert_nextline("00000010: 10 00 ..");
+ ut_assert_console_end();
+ free(buf);
+
+ return 0;
+}
+LOG_TEST_FLAGS(log_test_buffer, UT_TESTF_CONSOLE_REC);