summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/console.c18
-rw-r--r--common/log.c30
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--doc/develop/logging.rst6
-rw-r--r--include/asm-generic/global_data.h16
-rw-r--r--include/console.h3
-rw-r--r--include/display_options.h25
-rw-r--r--include/hexdump.h81
-rw-r--r--include/log.h69
-rw-r--r--include/test/suites.h1
-rw-r--r--include/test/test.h4
-rw-r--r--lib/display_options.c115
-rw-r--r--lib/hexdump.c104
-rw-r--r--test/cmd/mem_search.c26
-rw-r--r--test/cmd_ut.c2
-rw-r--r--test/dm/rtc.c6
-rw-r--r--test/log/Makefile2
-rw-r--r--test/log/log_test.c27
-rw-r--r--test/log/nolog_ndebug.c39
-rw-r--r--test/log/nolog_test.c3
-rw-r--r--test/print_ut.c284
-rw-r--r--test/ut.c55
22 files changed, 681 insertions, 236 deletions
diff --git a/common/console.c b/common/console.c
index 561cdf36a7..73edb28799 100644
--- a/common/console.c
+++ b/common/console.c
@@ -95,16 +95,22 @@ static void console_record_putc(const char c)
{
if (!(gd->flags & GD_FLG_RECORD))
return;
- if (gd->console_out.start)
- membuff_putbyte((struct membuff *)&gd->console_out, c);
+ if (gd->console_out.start &&
+ !membuff_putbyte((struct membuff *)&gd->console_out, c))
+ gd->flags |= GD_FLG_RECORD_OVF;
}
static void console_record_puts(const char *s)
{
if (!(gd->flags & GD_FLG_RECORD))
return;
- if (gd->console_out.start)
- membuff_put((struct membuff *)&gd->console_out, s, strlen(s));
+ if (gd->console_out.start) {
+ int len = strlen(s);
+
+ if (membuff_put((struct membuff *)&gd->console_out, s, len) !=
+ len)
+ gd->flags |= GD_FLG_RECORD_OVF;
+ }
}
static int console_record_getc(void)
@@ -742,6 +748,7 @@ void console_record_reset(void)
{
membuff_purge((struct membuff *)&gd->console_out);
membuff_purge((struct membuff *)&gd->console_in);
+ gd->flags &= ~GD_FLG_RECORD_OVF;
}
int console_record_reset_enable(void)
@@ -754,6 +761,9 @@ int console_record_reset_enable(void)
int console_record_readline(char *str, int maxlen)
{
+ if (gd->flags & GD_FLG_RECORD_OVF)
+ return -ENOSPC;
+
return membuff_readline((struct membuff *)&gd->console_out, str,
maxlen, ' ');
}
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/configs/sandbox_defconfig b/configs/sandbox_defconfig
index bdbf714e2b..60cdad1084 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -21,6 +21,7 @@ CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
CONFIG_CONSOLE_RECORD=y
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
CONFIG_PRE_CONSOLE_BUFFER=y
+CONFIG_LOG=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_MISC_INIT_F=y
CONFIG_STACKPROTECTOR=y
diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst
index f4e925048e..51095b05ba 100644
--- a/doc/develop/logging.rst
+++ b/doc/develop/logging.rst
@@ -52,6 +52,10 @@ If CONFIG_LOG is not set, then no logging will be available.
The above have SPL and TPL versions also, e.g. CONFIG_SPL_LOG_MAX_LEVEL and
CONFIG_TPL_LOG_MAX_LEVEL.
+If logging is disabled, the default behaviour is to output any message at
+level LOGL_INFO and below. If logging is disabled and DEBUG is defined (at
+the very top of a C file) then any message at LOGL_DEBUG will be written.
+
Temporary logging within a single file
--------------------------------------
@@ -291,8 +295,6 @@ More logging destinations:
Convert debug() statements in the code to log() statements
-Support making printf() emit log statements at L_INFO level
-
Convert error() statements in the code to log() statements
Figure out what to do with BUG(), BUG_ON() and warn_non_spl()
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 47921d27b1..e278d4c941 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -572,29 +572,33 @@ enum gd_flags {
*/
GD_FLG_RECORD = 0x01000,
/**
+ * @GD_FLG_RECORD_OVF: record console overflow
+ */
+ GD_FLG_RECORD_OVF = 0x02000,
+ /**
* @GD_FLG_ENV_DEFAULT: default variable flag
*/
- GD_FLG_ENV_DEFAULT = 0x02000,
+ GD_FLG_ENV_DEFAULT = 0x04000,
/**
* @GD_FLG_SPL_EARLY_INIT: early SPL initialization is done
*/
- GD_FLG_SPL_EARLY_INIT = 0x04000,
+ GD_FLG_SPL_EARLY_INIT = 0x08000,
/**
* @GD_FLG_LOG_READY: log system is ready for use
*/
- GD_FLG_LOG_READY = 0x08000,
+ GD_FLG_LOG_READY = 0x10000,
/**
* @GD_FLG_WDT_READY: watchdog is ready for use
*/
- GD_FLG_WDT_READY = 0x10000,
+ GD_FLG_WDT_READY = 0x20000,
/**
* @GD_FLG_SKIP_LL_INIT: don't perform low-level initialization
*/
- GD_FLG_SKIP_LL_INIT = 0x20000,
+ GD_FLG_SKIP_LL_INIT = 0x40000,
/**
* @GD_FLG_SMP_READY: SMP initialization is complete
*/
- GD_FLG_SMP_READY = 0x40000,
+ GD_FLG_SMP_READY = 0x80000,
};
#endif /* __ASSEMBLY__ */
diff --git a/include/console.h b/include/console.h
index 7e628c0cf8..f848bcbf03 100644
--- a/include/console.h
+++ b/include/console.h
@@ -72,7 +72,8 @@ int console_record_reset_enable(void);
*
* @str: Place to put string
* @maxlen: Maximum length of @str including nul terminator
- * @return length of string returned
+ * @return length of string returned, or -ENOSPC if the console buffer was
+ * overflowed by the output
*/
int console_record_readline(char *str, int maxlen);
diff --git a/include/display_options.h b/include/display_options.h
index 049688e39e..43810cbe22 100644
--- a/include/display_options.h
+++ b/include/display_options.h
@@ -47,6 +47,31 @@ void print_freq(uint64_t freq, const char *suffix);
int print_buffer(ulong addr, const void *data, uint width, uint count,
uint linelen);
+/*
+ * Maximum length of an output line is when width == 1
+ * 9 for address,
+ * a space, two hex digits and an ASCII character for each byte
+ * 2 spaces between the hex and ASCII
+ * \0 terminator
+ */
+#define HEXDUMP_MAX_BUF_LENGTH(bytes) (9 + (bytes) * 4 + 3)
+
+/**
+ * hexdump_line() - Print out a single line of a hex dump
+ *
+ * @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
+ * @out: Output buffer to hold the dump
+ * @size: Size of output buffer in bytes
+ * @return number of bytes processed, if OK, -ENOSPC if buffer too small
+ *
+ */
+int hexdump_line(ulong addr, const void *data, uint width, uint count,
+ uint linelen, char *out, int size);
+
/**
* display_options() - display the version string / build tag
*
diff --git a/include/hexdump.h b/include/hexdump.h
index f7b76ff712..f2ca4793d6 100644
--- a/include/hexdump.h
+++ b/include/hexdump.h
@@ -10,7 +10,7 @@
#include <linux/ctype.h>
#include <linux/types.h>
-enum {
+enum dump_prefix_t {
DUMP_PREFIX_NONE,
DUMP_PREFIX_ADDRESS,
DUMP_PREFIX_OFFSET
@@ -81,10 +81,85 @@ static inline char *bin2hex(char *dst, const void *src, size_t count)
return dst;
}
+/**
+ * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; max 64
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @linebuf: where to put the converted data
+ * @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
+ *
+ * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ *
+ * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
+ * to a hex + ASCII dump at the supplied memory location.
+ * The converted output is always NUL-terminated.
+ *
+ * E.g.:
+ * hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ * linebuf, sizeof(linebuf), true);
+ *
+ * example output buffer:
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ *
+ * Return:
+ * The amount of bytes placed in the buffer without terminating NUL. If the
+ * output was truncated, then the return value is the number of bytes
+ * (excluding the terminating NUL) which would have been written to the final
+ * string if enough space had been available.
+ */
int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
char *linebuf, size_t linebuflen, bool ascii);
-void print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
- int groupsize, const void *buf, size_t len, bool ascii);
+
+/**
+ * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (see enum dump_prefix_t)
+ * @rowsize: number of bytes to print per line; max 64
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
+ * Returns: 0 if finished normally, -EINTR if Ctrl-C was pressed, -ENOSYS if not
+ * supported
+ *
+ * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
+ * to the stdio, with an optional leading prefix.
+ *
+ * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
+ *
+ * E.g.:
+ * print_hex_dump("raw data: ", DUMP_PREFIX_ADDRESS, 16, 1, frame->data,
+ * frame->len, true);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
+ */
+int print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
+ int groupsize, const void *buf, size_t len, bool ascii);
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (see enum dump_prefix_t)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), rowsize of 16, groupsize of 1,
+ * and ASCII output included.
+ */
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len);
diff --git a/include/log.h b/include/log.h
index add3a1e4a0..e0e12ce194 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
@@ -156,6 +174,10 @@ static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
*/
#if CONFIG_IS_ENABLED(LOG)
#define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL)
+#else
+#define _LOG_MAX_LEVEL LOGL_INFO
+#endif
+
#define log_emer(_fmt...) log(LOG_CATEGORY, LOGL_EMERG, ##_fmt)
#define log_alert(_fmt...) log(LOG_CATEGORY, LOGL_ALERT, ##_fmt)
#define log_crit(_fmt...) log(LOG_CATEGORY, LOGL_CRIT, ##_fmt)
@@ -167,41 +189,50 @@ static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
#define log_content(_fmt...) log(LOG_CATEGORY, LOGL_DEBUG_CONTENT, ##_fmt)
#define log_io(_fmt...) log(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt)
#define log_cont(_fmt...) log(LOGC_CONT, LOGL_CONT, ##_fmt)
-#else
-#define _LOG_MAX_LEVEL LOGL_INFO
-#define log_emerg(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_alert(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_crit(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_err(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_warning(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_notice(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_info(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_cont(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_debug(_fmt, ...) debug(_fmt, ##__VA_ARGS__)
-#define log_content(_fmt...) log_nop(LOG_CATEGORY, \
- LOGL_DEBUG_CONTENT, ##_fmt)
-#define log_io(_fmt...) log_nop(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt)
-#endif
-#if CONFIG_IS_ENABLED(LOG)
#ifdef LOG_DEBUG
#define _LOG_DEBUG LOGL_FORCE_DEBUG
#else
#define _LOG_DEBUG 0
#endif
+#if CONFIG_IS_ENABLED(LOG)
+
/* Emit a log record if the level is less that the maximum */
#define log(_cat, _level, _fmt, _args...) ({ \
int _l = _level; \
- if (CONFIG_IS_ENABLED(LOG) && \
- (_LOG_DEBUG != 0 || _l <= _LOG_MAX_LEVEL)) \
+ if (_LOG_DEBUG != 0 || _l <= _LOG_MAX_LEVEL) \
_log((enum log_category_t)(_cat), \
(enum log_level_t)(_l | _LOG_DEBUG), __FILE__, \
__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...)
+
+/* Note: _LOG_DEBUG != 0 avoids a warning with clang */
+#define log(_cat, _level, _fmt, _args...) ({ \
+ int _l = _level; \
+ if (_LOG_DEBUG != 0 || _l <= LOGL_INFO || \
+ (_DEBUG && _l == LOGL_DEBUG)) \
+ printf(_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/include/test/suites.h b/include/test/suites.h
index f5d8e139ce..80b41f188c 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -41,6 +41,7 @@ int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
+int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
diff --git a/include/test/test.h b/include/test/test.h
index bf7d785d8e..0104e189f6 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -32,8 +32,8 @@ struct unit_test_state {
struct udevice *testdev;
int force_fail_alloc;
int skip_post_probe;
- char expect_str[256];
- char actual_str[256];
+ char expect_str[512];
+ char actual_str[512];
};
/* Test flags for each test */
diff --git a/lib/display_options.c b/lib/display_options.c
index cd48998b6d..c08a87e316 100644
--- a/lib/display_options.c
+++ b/lib/display_options.c
@@ -131,10 +131,11 @@ void print_size(uint64_t size, const char *s)
printf (" %ciB%s", c, s);
}
-#define MAX_LINE_LENGTH_BYTES (64)
-#define DEFAULT_LINE_LENGTH_BYTES (16)
-int print_buffer(ulong addr, const void *data, uint width, uint count,
- uint linelen)
+#define MAX_LINE_LENGTH_BYTES 64
+#define DEFAULT_LINE_LENGTH_BYTES 16
+
+int hexdump_line(ulong addr, const void *data, uint width, uint count,
+ uint linelen, char *out, int size)
{
/* linebuf as a union causes proper alignment */
union linebuf {
@@ -143,62 +144,86 @@ int print_buffer(ulong addr, const void *data, uint width, uint count,
uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1];
uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1];
} lb;
+ uint thislinelen;
int i;
ulong x;
+ if (linelen * width > MAX_LINE_LENGTH_BYTES)
+ linelen = MAX_LINE_LENGTH_BYTES / width;
+ if (linelen < 1)
+ linelen = DEFAULT_LINE_LENGTH_BYTES / width;
+
+ /*
+ * Check the size here so that we don't need to use snprintf(). This
+ * helps to reduce code size
+ */
+ if (size < HEXDUMP_MAX_BUF_LENGTH(linelen * width))
+ return -ENOSPC;
+
+ thislinelen = linelen;
+ out += sprintf(out, "%08lx:", addr);
+
+ /* check for overflow condition */
+ if (count < thislinelen)
+ thislinelen = count;
+
+ /* Copy from memory into linebuf and print hex values */
+ for (i = 0; i < thislinelen; i++) {
+ if (width == 4)
+ x = lb.ui[i] = *(volatile uint32_t *)data;
+ else if (MEM_SUPPORT_64BIT_DATA && width == 8)
+ x = lb.uq[i] = *(volatile ulong *)data;
+ else if (width == 2)
+ x = lb.us[i] = *(volatile uint16_t *)data;
+ else
+ x = lb.uc[i] = *(volatile uint8_t *)data;
+ if (CONFIG_IS_ENABLED(USE_TINY_PRINTF))
+ out += sprintf(out, " %x", (uint)x);
+ else
+ out += sprintf(out, " %0*lx", width * 2, x);
+ data += width;
+ }
+
+ /* fill line with whitespace for nice ASCII print */
+ for (i = 0; i < (linelen - thislinelen) * (width * 2 + 1); i++)
+ *out++ = ' ';
+
+ /* Print data in ASCII characters */
+ for (i = 0; i < thislinelen * width; i++) {
+ if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80)
+ lb.uc[i] = '.';
+ }
+ lb.uc[i] = '\0';
+ out += sprintf(out, " %s", lb.uc);
+
+ return thislinelen;
+}
+
+int print_buffer(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 = linelen;
- printf("%08lx:", addr);
-
- /* check for overflow condition */
- if (count < thislinelen)
- thislinelen = count;
-
- /* Copy from memory into linebuf and print hex values */
- for (i = 0; i < thislinelen; i++) {
- if (width == 4)
- x = lb.ui[i] = *(volatile uint32_t *)data;
- else if (MEM_SUPPORT_64BIT_DATA && width == 8)
- x = lb.uq[i] = *(volatile ulong *)data;
- else if (width == 2)
- x = lb.us[i] = *(volatile uint16_t *)data;
- else
- x = lb.uc[i] = *(volatile uint8_t *)data;
- if (CONFIG_IS_ENABLED(USE_TINY_PRINTF))
- printf(" %x", (uint)x);
- else
- printf(" %0*lx", width * 2, x);
- data += width;
- }
+ uint thislinelen;
+ char buf[HEXDUMP_MAX_BUF_LENGTH(width * linelen)];
- while (thislinelen < linelen) {
- /* fill line with whitespace for nice ASCII print */
- for (i=0; i<width*2+1; i++)
- puts(" ");
- linelen--;
- }
-
- /* Print data in ASCII characters */
- for (i = 0; i < thislinelen * width; i++) {
- if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80)
- lb.uc[i] = '.';
- }
- lb.uc[i] = '\0';
- printf(" %s\n", lb.uc);
+ thislinelen = hexdump_line(addr, data, width, count, linelen,
+ buf, sizeof(buf));
+ assert(thislinelen >= 0);
+ puts(buf);
+ putc('\n');
/* update references */
+ data += thislinelen * width;
addr += thislinelen * width;
count -= thislinelen;
-#ifndef CONFIG_SPL_BUILD
- if (ctrlc())
- return -1;
-#endif
+ if (!IS_ENABLED(CONFIG_SPL_BUILD) && ctrlc())
+ return -EINTR;
}
return 0;
diff --git a/lib/hexdump.c b/lib/hexdump.c
index a3f219a874..149c93ead8 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -10,45 +10,18 @@
#include <common.h>
#include <hexdump.h>
+#include <mapmem.h>
#include <linux/ctype.h>
#include <linux/compat.h>
#include <linux/log2.h>
#include <asm/unaligned.h>
+#define MAX_LINE_LENGTH_BYTES 64
+
const char hex_asc[] = "0123456789abcdef";
const char hex_asc_upper[] = "0123456789ABCDEF";
#if CONFIG_IS_ENABLED(HEXDUMP)
-/**
- * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
- * @buf: data blob to dump
- * @len: number of bytes in the @buf
- * @rowsize: number of bytes to print per line; must be 16 or 32
- * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
- * @linebuf: where to put the converted data
- * @linebuflen: total size of @linebuf, including space for terminating NUL
- * @ascii: include ASCII after the hex output
- *
- * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
- * 16 or 32 bytes of input data converted to hex + ASCII output.
- *
- * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
- * to a hex + ASCII dump at the supplied memory location.
- * The converted output is always NUL-terminated.
- *
- * E.g.:
- * hex_dump_to_buffer(frame->data, frame->len, 16, 1,
- * linebuf, sizeof(linebuf), true);
- *
- * example output buffer:
- * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
- *
- * Return:
- * The amount of bytes placed in the buffer without terminating NUL. If the
- * output was truncated, then the return value is the number of bytes
- * (excluding the terminating NUL) which would have been written to the final
- * string if enough space had been available.
- */
int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
char *linebuf, size_t linebuflen, bool ascii)
{
@@ -59,8 +32,10 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
int ascii_column;
int ret;
- if (rowsize != 16 && rowsize != 32)
+ if (!rowsize)
rowsize = 16;
+ else
+ rowsize = min(rowsize, MAX_LINE_LENGTH_BYTES);
if (len > rowsize) /* limit to one line at a time */
len = rowsize;
@@ -150,44 +125,17 @@ overflow1:
return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
}
-/**
- * print_hex_dump - print a text hex dump to syslog for a binary blob of data
- * @prefix_str: string to prefix each line with;
- * caller supplies trailing spaces for alignment if desired
- * @prefix_type: controls whether prefix of an offset, address, or none
- * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
- * @rowsize: number of bytes to print per line; must be 16 or 32
- * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
- * @buf: data blob to dump
- * @len: number of bytes in the @buf
- * @ascii: include ASCII after the hex output
- *
- * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
- * to the stdio, with an optional leading prefix.
- *
- * print_hex_dump() works on one "line" of output at a time, i.e.,
- * 16 or 32 bytes of input data converted to hex + ASCII output.
- * print_hex_dump() iterates over the entire input @buf, breaking it into
- * "line size" chunks to format and print.
- *
- * E.g.:
- * print_hex_dump("raw data: ", DUMP_PREFIX_ADDRESS, 16, 1, frame->data,
- * frame->len, true);
- *
- * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
- * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
- * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
- * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
- */
-void print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
- int groupsize, const void *buf, size_t len, bool ascii)
+int print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
+ int groupsize, const void *buf, size_t len, bool ascii)
{
const u8 *ptr = buf;
int i, linelen, remaining = len;
- char linebuf[32 * 3 + 2 + 32 + 1];
+ char linebuf[MAX_LINE_LENGTH_BYTES * 3 + 2 + MAX_LINE_LENGTH_BYTES + 1];
- if (rowsize != 16 && rowsize != 32)
+ if (!rowsize)
rowsize = 16;
+ else
+ rowsize = min(rowsize, MAX_LINE_LENGTH_BYTES);
for (i = 0; i < len; i += rowsize) {
linelen = min(remaining, rowsize);
@@ -198,7 +146,9 @@ void print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
switch (prefix_type) {
case DUMP_PREFIX_ADDRESS:
- printf("%s%p: %s\n", prefix_str, ptr + i, linebuf);
+ printf("%s%0*lx: %s\n", prefix_str,
+ IS_ENABLED(CONFIG_PHYS_64BIT) ? 16 : 8,
+ (ulong)map_to_sysmem(ptr) + i, linebuf);
break;
case DUMP_PREFIX_OFFSET:
printf("%s%.8x: %s\n", prefix_str, i, linebuf);
@@ -207,21 +157,13 @@ void print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
printf("%s%s\n", prefix_str, linebuf);
break;
}
+ if (!IS_ENABLED(CONFIG_SPL_BUILD) && ctrlc())
+ return -EINTR;
}
+
+ return 0;
}
-/**
- * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
- * @prefix_str: string to prefix each line with;
- * caller supplies trailing spaces for alignment if desired
- * @prefix_type: controls whether prefix of an offset, address, or none
- * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
- * @buf: data blob to dump
- * @len: number of bytes in the @buf
- *
- * Calls print_hex_dump(), rowsize of 16, groupsize of 1,
- * and ASCII output included.
- */
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len)
{
@@ -232,14 +174,14 @@ void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
* Some code in U-Boot copy-pasted from Linux kernel uses both
* functions below so to keep stuff compilable we keep these stubs here.
*/
-void print_hex_dump(const char *prefix_str, int prefix_type,
- int rowsize, int groupsize, const void *buf,
- size_t len, bool ascii)
+int print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
+ int groupsize, const void *buf, size_t len, bool ascii)
{
+ return -ENOSYS;
}
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
- const void *buf, size_t len)
+ const void *buf, size_t len)
{
}
#endif /* CONFIG_HEXDUMP */
diff --git a/test/cmd/mem_search.c b/test/cmd/mem_search.c
index 94942793a4..f80c9c4068 100644
--- a/test/cmd/mem_search.c
+++ b/test/cmd/mem_search.c
@@ -30,9 +30,9 @@ static int mem_test_ms_b(struct unit_test_state *uts)
buf[0x100] = 0x12;
ut_assertok(console_record_reset_enable());
run_command("ms.b 1 ff 12", 0);
- ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................");
+ ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................");
ut_assert_nextline("--");
- ut_assert_nextline("000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 ................");
+ ut_assert_nextline("000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 ................");
ut_assert_nextline("2 matches");
ut_assert_console_end();
@@ -57,7 +57,7 @@ static int mem_test_ms_w(struct unit_test_state *uts)
buf[BUF_SIZE / 2] = 0x1234;
ut_assertok(console_record_reset_enable());
run_command("ms.w 0 80 1234", 0);
- ut_assert_nextline("00000030: 0000 0000 1234 0000 0000 0000 0000 0000 ....4...........");
+ ut_assert_nextline("00000030: 0000 0000 1234 0000 0000 0000 0000 0000 ....4...........");
ut_assert_nextline("1 match");
ut_assert_console_end();
@@ -82,7 +82,7 @@ static int mem_test_ms_l(struct unit_test_state *uts)
buf[BUF_SIZE / 4] = 0x12345678;
ut_assertok(console_record_reset_enable());
run_command("ms 0 40 12345678", 0);
- ut_assert_nextline("00000030: 00000000 00000000 12345678 00000000 ........xV4.....");
+ ut_assert_nextline("00000030: 00000000 00000000 12345678 00000000 ........xV4.....");
ut_assert_nextline("1 match");
ut_assert_console_end();
@@ -212,10 +212,10 @@ static int mem_test_ms_mult(struct unit_test_state *uts)
strcpy(buf + BUF_SIZE - strlen(str) + 1, str);
ut_assertok(console_record_reset_enable());
run_command("ms.b 0 100 68 65 6c 6c 6f", 0);
- ut_assert_nextline("00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 65 ..............he");
- ut_assert_nextline("00000020: 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 llo.............");
+ ut_assert_nextline("00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 65 ..............he");
+ ut_assert_nextline("00000020: 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 llo.............");
ut_assert_nextline("--");
- ut_assert_nextline("00000060: 00 00 00 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 ...hello........");
+ ut_assert_nextline("00000060: 00 00 00 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 ...hello........");
ut_assert_nextline("2 matches");
ut_assert_console_end();
unmap_sysmem(buf);
@@ -242,12 +242,12 @@ static int mem_test_ms_s(struct unit_test_state *uts)
strcpy(buf + 0xa1, str2);
ut_assertok(console_record_reset_enable());
run_command("ms.s 0 100 hello", 0);
- ut_assert_nextline("00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 65 ..............he");
- ut_assert_nextline("00000020: 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 llo.............");
+ ut_assert_nextline("00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 65 ..............he");
+ ut_assert_nextline("00000020: 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 llo.............");
ut_assert_nextline("--");
- ut_assert_nextline("00000060: 00 00 00 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 ...hello........");
+ ut_assert_nextline("00000060: 00 00 00 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 ...hello........");
ut_assert_nextline("--");
- ut_assert_nextline("000000a0: 00 68 65 6c 6c 6f 74 68 65 72 65 00 00 00 00 00 .hellothere.....");
+ ut_assert_nextline("000000a0: 00 68 65 6c 6c 6f 74 68 65 72 65 00 00 00 00 00 .hellothere.....");
ut_assert_nextline("3 matches");
ut_assert_console_end();
@@ -257,7 +257,7 @@ static int mem_test_ms_s(struct unit_test_state *uts)
ut_assertok(console_record_reset_enable());
run_command("ms.s 0 100 hello there", 0);
- ut_assert_nextline("000000a0: 00 68 65 6c 6c 6f 74 68 65 72 65 00 00 00 00 00 .hellothere.....");
+ ut_assert_nextline("000000a0: 00 68 65 6c 6c 6f 74 68 65 72 65 00 00 00 00 00 .hellothere.....");
ut_assert_nextline("1 match");
ut_assert_console_end();
@@ -284,7 +284,7 @@ static int mem_test_ms_limit(struct unit_test_state *uts)
buf[0x76] = 0x12;
ut_assertok(console_record_reset_enable());
run_command("ms.b -l2 1 ff 12", 0);
- ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................");
+ ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................");
ut_assert_nextline("--");
ut_assert_nextlinen("00000060: 00 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00");
ut_assert_nextline("2 matches (repeat command to check for more)");
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index b9c166045d..6f174c6a07 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -51,6 +51,7 @@ static struct cmd_tbl cmd_ut_sub[] = {
U_BOOT_CMD_MKENT(setexpr, CONFIG_SYS_MAXARGS, 1, do_ut_setexpr, "",
""),
#endif
+ U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_ut_print, "", ""),
#ifdef CONFIG_UT_TIME
U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
#endif
@@ -132,6 +133,7 @@ static char ut_help_text[] =
#ifdef CONFIG_UT_OVERLAY
"ut overlay [test-name]\n"
#endif
+ "ut print [test-name] - test printing\n"
"ut setexpr [test-name] - test setexpr command\n"
#ifdef CONFIG_SANDBOX
"ut str - Basic test of string functions\n"
diff --git a/test/dm/rtc.c b/test/dm/rtc.c
index 8ab997c87d..c7f9f8f0ce 100644
--- a/test/dm/rtc.c
+++ b/test/dm/rtc.c
@@ -204,7 +204,7 @@ static int dm_test_rtc_cmd_rw(struct unit_test_state *uts)
ut_assert_console_end();
run_command("rtc read 0x30 2", 0);
- ut_assert_nextline("00000030: aa bb ..");
+ ut_assert_nextline("00000030: aa bb ..");
ut_assert_console_end();
run_command("rtc dev 1", 0);
@@ -215,7 +215,7 @@ static int dm_test_rtc_cmd_rw(struct unit_test_state *uts)
ut_assert_console_end();
run_command("rtc read 0x30 2", 0);
- ut_assert_nextline("00000030: cc dd ..");
+ ut_assert_nextline("00000030: cc dd ..");
ut_assert_console_end();
/*
@@ -227,7 +227,7 @@ static int dm_test_rtc_cmd_rw(struct unit_test_state *uts)
ut_assert_console_end();
run_command("rtc read 0x30 2", 0);
- ut_assert_nextline("00000030: aa bb ..");
+ ut_assert_nextline("00000030: aa bb ..");
ut_assert_console_end();
return 0;
diff --git a/test/log/Makefile b/test/log/Makefile
index a3dedace04..08eea70e34 100644
--- a/test/log/Makefile
+++ b/test/log/Makefile
@@ -17,8 +17,10 @@ endif
ifdef CONFIG_LOG
obj-y += pr_cont_test.o
obj-$(CONFIG_CONSOLE_RECORD) += cont_test.o
+obj-y += pr_cont_test.o
else
obj-$(CONFIG_CONSOLE_RECORD) += nolog_test.o
+obj-$(CONFIG_CONSOLE_RECORD) += nolog_ndebug.o
endif
endif # CONFIG_UT_LOG
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);
diff --git a/test/log/nolog_ndebug.c b/test/log/nolog_ndebug.c
new file mode 100644
index 0000000000..bd9a4f408e
--- /dev/null
+++ b/test/log/nolog_ndebug.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Logging function tests for CONFIG_LOG=n without #define DEBUG
+ */
+
+#include <common.h>
+#include <console.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <test/log.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BUFFSIZE 32
+
+static int log_test_log_disabled_ndebug(struct unit_test_state *uts)
+{
+ char buf[BUFFSIZE];
+ int i;
+
+ memset(buf, 0, BUFFSIZE);
+ console_record_reset_enable();
+
+ /* Output a log record at every level */
+ for (i = LOGL_EMERG; i < LOGL_COUNT; i++)
+ log(LOGC_NONE, i, "testing level %i\n", i);
+ gd->flags &= ~GD_FLG_RECORD;
+
+ /* Since DEBUG is not defined, we expect to not get debug output */
+ for (i = LOGL_EMERG; i < LOGL_DEBUG; i++)
+ ut_assertok(ut_check_console_line(uts, "testing level %d", i));
+ ut_assertok(ut_check_console_end(uts));
+
+ return 0;
+}
+LOG_TEST(log_test_log_disabled_ndebug);
diff --git a/test/log/nolog_test.c b/test/log/nolog_test.c
index cb4fb3db9a..4e52e5bed8 100644
--- a/test/log/nolog_test.c
+++ b/test/log/nolog_test.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <console.h>
+#include <log.h>
#include <asm/global_data.h>
#include <test/log.h>
#include <test/test.h>
@@ -128,8 +129,10 @@ static int log_test_nolog_debug(struct unit_test_state *uts)
memset(buf, 0, BUFFSIZE);
console_record_reset_enable();
log_debug("testing %s\n", "log_debug");
+ log(LOGC_NONE, LOGL_DEBUG, "more %s\n", "log_debug");
gd->flags &= ~GD_FLG_RECORD;
ut_assertok(ut_check_console_line(uts, "testing log_debug"));
+ ut_assertok(ut_check_console_line(uts, "more log_debug"));
ut_assertok(ut_check_console_end(uts));
return 0;
}
diff --git a/test/print_ut.c b/test/print_ut.c
index 5b0a46de9c..e2bcfbef00 100644
--- a/test/print_ut.c
+++ b/test/print_ut.c
@@ -3,42 +3,52 @@
* Copyright (c) 2012, The Chromium Authors
*/
-#define DEBUG
-
#include <common.h>
#include <command.h>
#include <efi_api.h>
#include <display_options.h>
#include <log.h>
+#include <mapmem.h>
#include <version.h>
+#include <test/suites.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define BUF_SIZE 0x100
#define FAKE_BUILD_TAG "jenkins-u-boot-denx_uboot_dm-master-build-aarch64" \
"and a lot more text to come"
+/* Declare a new print test */
+#define PRINT_TEST(_name, _flags) UNIT_TEST(_name, _flags, print_test)
+
+#if CONFIG_IS_ENABLED(LIB_UUID)
/* Test printing GUIDs */
-static void guid_ut_print(void)
+static int print_guid(struct unit_test_state *uts)
{
-#if CONFIG_IS_ENABLED(LIB_UUID)
unsigned char guid[16] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
char str[40];
sprintf(str, "%pUb", guid);
- assert(!strcmp("01020304-0506-0708-090a-0b0c0d0e0f10", str));
+ ut_assertok(strcmp("01020304-0506-0708-090a-0b0c0d0e0f10", str));
sprintf(str, "%pUB", guid);
- assert(!strcmp("01020304-0506-0708-090A-0B0C0D0E0F10", str));
+ ut_assertok(strcmp("01020304-0506-0708-090A-0B0C0D0E0F10", str));
sprintf(str, "%pUl", guid);
- assert(!strcmp("04030201-0605-0807-090a-0b0c0d0e0f10", str));
+ ut_assertok(strcmp("04030201-0605-0807-090a-0b0c0d0e0f10", str));
sprintf(str, "%pUL", guid);
- assert(!strcmp("04030201-0605-0807-090A-0B0C0D0E0F10", str));
-#endif
+ ut_assertok(strcmp("04030201-0605-0807-090A-0B0C0D0E0F10", str));
+
+ return 0;
}
+PRINT_TEST(print_guid, 0);
+#endif
+#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
/* Test efi_loader specific printing */
-static void efi_ut_print(void)
+static int print_efi_ut(struct unit_test_state *uts)
{
-#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
char str[10];
u8 buf[sizeof(struct efi_device_path_sd_mmc_path) +
sizeof(struct efi_device_path)];
@@ -60,92 +70,268 @@ static void efi_ut_print(void)
dp_end->length = sizeof(struct efi_device_path);
snprintf(str, sizeof(str), "_%pD_", buf);
- assert(!strcmp("_/SD(3)_", str));
+ ut_assertok(strcmp("_/SD(3)_", str));
/* NULL device path */
snprintf(str, sizeof(str), "_%pD_", NULL);
- assert(!strcmp("_<NULL>_", str));
-#endif
+ ut_assertok(strcmp("_<NULL>_", str));
+
+ return 0;
}
+PRINT_TEST(print_efi_ut, 0);
+#endif
-static int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
+static int print_printf(struct unit_test_state *uts)
{
char big_str[400];
int big_str_len;
char str[10], *s;
int len;
- printf("%s: Testing print\n", __func__);
-
snprintf(str, sizeof(str), "testing");
- assert(!strcmp("testing", str));
+ ut_assertok(strcmp("testing", str));
snprintf(str, sizeof(str), "testing but too long");
- assert(!strcmp("testing b", str));
+ ut_assertok(strcmp("testing b", str));
snprintf(str, 1, "testing none");
- assert(!strcmp("", str));
+ ut_assertok(strcmp("", str));
*str = 'x';
snprintf(str, 0, "testing none");
- assert(*str == 'x');
+ ut_asserteq('x', *str);
sprintf(big_str, "_%ls_", L"foo");
- assert(!strcmp("_foo_", big_str));
+ ut_assertok(strcmp("_foo_", big_str));
/* Test the banner function */
s = display_options_get_banner(true, str, sizeof(str));
- assert(s == str);
- assert(!strcmp("\n\nU-Boo\n\n", s));
+ ut_asserteq_ptr(str, s);
+ ut_assertok(strcmp("\n\nU-Boo\n\n", s));
/* Assert that we do not overwrite memory before the buffer */
str[0] = '`';
s = display_options_get_banner(true, str + 1, 1);
- assert(s == str + 1);
- assert(!strcmp("`", str));
+ ut_asserteq_ptr(str + 1, s);
+ ut_assertok(strcmp("`", str));
str[0] = '~';
s = display_options_get_banner(true, str + 1, 2);
- assert(s == str + 1);
- assert(!strcmp("~\n", str));
+ ut_asserteq_ptr(str + 1, s);
+ ut_assertok(strcmp("~\n", str));
/* The last two characters are set to \n\n for all buffer sizes > 2 */
s = display_options_get_banner(false, str, sizeof(str));
- assert(s == str);
- assert(!strcmp("U-Boot \n\n", s));
+ ut_asserteq_ptr(str, s);
+ ut_assertok(strcmp("U-Boot \n\n", s));
/* Give it enough space for some of the version */
big_str_len = strlen(version_string) - 5;
s = display_options_get_banner_priv(false, FAKE_BUILD_TAG, big_str,
big_str_len);
- assert(s == big_str);
- assert(!strncmp(version_string, s, big_str_len - 3));
- assert(!strcmp("\n\n", s + big_str_len - 3));
+ ut_asserteq_ptr(big_str, s);
+ ut_assertok(strncmp(version_string, s, big_str_len - 3));
+ ut_assertok(strcmp("\n\n", s + big_str_len - 3));
/* Give it enough space for the version and some of the build tag */
big_str_len = strlen(version_string) + 9 + 20;
s = display_options_get_banner_priv(false, FAKE_BUILD_TAG, big_str,
big_str_len);
- assert(s == big_str);
+ ut_asserteq_ptr(big_str, s);
len = strlen(version_string);
- assert(!strncmp(version_string, s, len));
- assert(!strncmp(", Build: ", s + len, 9));
- assert(!strncmp(FAKE_BUILD_TAG, s + 9 + len, 12));
- assert(!strcmp("\n\n", s + big_str_len - 3));
+ ut_assertok(strncmp(version_string, s, len));
+ ut_assertok(strncmp(", Build: ", s + len, 9));
+ ut_assertok(strncmp(FAKE_BUILD_TAG, s + 9 + len, 12));
+ ut_assertok(strcmp("\n\n", s + big_str_len - 3));
+
+ return 0;
+}
+PRINT_TEST(print_printf, 0);
+
+static int print_display_buffer(struct unit_test_state *uts)
+{
+ u8 *buf;
+ int i;
+
+ buf = map_sysmem(0, BUF_SIZE);
+ memset(buf, '\0', BUF_SIZE);
+ for (i = 0; i < 0x11; i++)
+ buf[i] = i * 0x11;
+
+ /* bytes */
+ console_record_reset();
+ print_buffer(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();
+
+ /* line length */
+ console_record_reset();
+ print_buffer(0, buf, 1, 0x12, 8);
+ ut_assert_nextline("00000000: 00 11 22 33 44 55 66 77 ..\"3DUfw");
+ ut_assert_nextline("00000008: 88 99 aa bb cc dd ee ff ........");
+ ut_assert_nextline("00000010: 10 00 ..");
+ ut_assert_console_end();
+
+ /* long line */
+ console_record_reset();
+ buf[0x41] = 0x41;
+ print_buffer(0, buf, 1, 0x42, 0x40);
+ ut_assert_nextline("00000000: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..\"3DUfw........................................................");
+ ut_assert_nextline("00000040: 00 41 .A");
+ ut_assert_console_end();
+
+ /* address */
+ console_record_reset();
+ print_buffer(0x12345678, buf, 1, 0x12, 0);
+ ut_assert_nextline("12345678: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ..\"3DUfw........");
+ ut_assert_nextline("12345688: 10 00 ..");
+ ut_assert_console_end();
+
+ /* 16-bit */
+ console_record_reset();
+ print_buffer(0, buf, 2, 9, 0);
+ ut_assert_nextline("00000000: 1100 3322 5544 7766 9988 bbaa ddcc ffee ..\"3DUfw........");
+ ut_assert_nextline("00000010: 0010 ..");
+ ut_assert_console_end();
- /* Test efi_loader specific printing */
- efi_ut_print();
+ /* 32-bit */
+ console_record_reset();
+ print_buffer(0, buf, 4, 5, 0);
+ ut_assert_nextline("00000000: 33221100 77665544 bbaa9988 ffeeddcc ..\"3DUfw........");
+ ut_assert_nextline("00000010: 00000010 ....");
+ ut_assert_console_end();
- /* Test printing GUIDs */
- guid_ut_print();
+ /* 64-bit */
+ console_record_reset();
+ print_buffer(0, buf, 8, 3, 0);
+ ut_assert_nextline("00000000: 7766554433221100 ffeeddccbbaa9988 ..\"3DUfw........");
+ ut_assert_nextline("00000010: 0000000000000010 ........");
+ ut_assert_console_end();
+
+ /* ASCII */
+ console_record_reset();
+ buf[1] = 31;
+ buf[2] = 32;
+ buf[3] = 33;
+ for (i = 0; i < 4; i++)
+ buf[4 + i] = 126 + i;
+ buf[8] = 255;
+ print_buffer(0, buf, 1, 10, 0);
+ ut_assert_nextline("00000000: 00 1f 20 21 7e 7f 80 81 ff 99 .. !~.....");
+ ut_assert_console_end();
+
+ unmap_sysmem(buf);
+
+ return 0;
+}
+PRINT_TEST(print_display_buffer, UT_TESTF_CONSOLE_REC);
+
+static int print_hexdump_line(struct unit_test_state *uts)
+{
+ char *linebuf;
+ u8 *buf;
+ int i;
+
+ buf = map_sysmem(0, BUF_SIZE);
+ memset(buf, '\0', BUF_SIZE);
+ for (i = 0; i < 0x11; i++)
+ buf[i] = i * 0x11;
+
+ /* Check buffer size calculations */
+ linebuf = map_sysmem(0x400, BUF_SIZE);
+ memset(linebuf, '\xff', BUF_SIZE);
+ ut_asserteq(-ENOSPC, hexdump_line(0, buf, 1, 0x10, 0, linebuf, 75));
+ ut_asserteq(-1, linebuf[0]);
+ ut_asserteq(0x10, hexdump_line(0, buf, 1, 0x10, 0, linebuf, 76));
+ ut_asserteq(0, linebuf[75]);
+ ut_asserteq(-1, linebuf[76]);
+
+ unmap_sysmem(buf);
+
+ return 0;
+}
+PRINT_TEST(print_hexdump_line, UT_TESTF_CONSOLE_REC);
+
+static int print_do_hex_dump(struct unit_test_state *uts)
+{
+ u8 *buf;
+ int i;
+
+ buf = map_sysmem(0, BUF_SIZE);
+ memset(buf, '\0', BUF_SIZE);
+ for (i = 0; i < 0x11; i++)
+ buf[i] = i * 0x11;
+
+ /* bytes */
+ console_record_reset();
+ print_hex_dump_bytes("", DUMP_PREFIX_ADDRESS, buf, 0x12);
+ 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();
+
+ /* line length */
+ console_record_reset();
+ print_hex_dump("", DUMP_PREFIX_ADDRESS, 8, 1, buf, 0x12, true);
+ ut_assert_nextline("00000000: 00 11 22 33 44 55 66 77 ..\"3DUfw");
+ ut_assert_nextline("00000008: 88 99 aa bb cc dd ee ff ........");
+ ut_assert_nextline("00000010: 10 00 ..");
+ ut_assert_console_end();
+ unmap_sysmem(buf);
+
+ /* long line */
+ console_record_reset();
+ buf[0x41] = 0x41;
+ print_hex_dump("", DUMP_PREFIX_ADDRESS, 0x40, 1, buf, 0x42, true);
+ ut_assert_nextline("00000000: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..\"3DUfw........................................................");
+ ut_assert_nextline("00000040: 00 41 .A");
+ ut_assert_console_end();
+
+ /* 16-bit */
+ console_record_reset();
+ print_hex_dump("", DUMP_PREFIX_ADDRESS, 0, 2, buf, 0x12, true);
+ ut_assert_nextline("00000000: 1100 3322 5544 7766 9988 bbaa ddcc ffee ..\"3DUfw........");
+ ut_assert_nextline("00000010: 0010 ..");
+ ut_assert_console_end();
+ unmap_sysmem(buf);
+
+ /* 32-bit */
+ console_record_reset();
+ print_hex_dump("", DUMP_PREFIX_ADDRESS, 0, 4, buf, 0x14, true);
+ ut_assert_nextline("00000000: 33221100 77665544 bbaa9988 ffeeddcc ..\"3DUfw........");
+ ut_assert_nextline("00000010: 00000010 ....");
+ ut_assert_console_end();
+ unmap_sysmem(buf);
+
+ /* 64-bit */
+ console_record_reset();
+ print_hex_dump("", DUMP_PREFIX_ADDRESS, 16, 8, buf, 0x18, true);
+ ut_assert_nextline("00000000: 7766554433221100 ffeeddccbbaa9988 ..\"3DUfw........");
+ ut_assert_nextline("00000010: 0000000000000010 ........");
+ ut_assert_console_end();
+ unmap_sysmem(buf);
+
+ /* ASCII */
+ console_record_reset();
+ buf[1] = 31;
+ buf[2] = 32;
+ buf[3] = 33;
+ for (i = 0; i < 4; i++)
+ buf[4 + i] = 126 + i;
+ buf[8] = 255;
+ print_hex_dump("", DUMP_PREFIX_ADDRESS, 0, 1, buf, 10, true);
+ ut_assert_nextline("00000000: 00 1f 20 21 7e 7f 80 81 ff 99 .. !~.....");
+ ut_assert_console_end();
+ unmap_sysmem(buf);
- printf("%s: Everything went swimmingly\n", __func__);
return 0;
}
+PRINT_TEST(print_do_hex_dump, UT_TESTF_CONSOLE_REC);
-U_BOOT_CMD(
- ut_print, 1, 1, do_ut_print,
- "Very basic test of printf(), etc.",
- ""
-);
+int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct unit_test *tests = UNIT_TEST_SUITE_START(print_test);
+ const int n_ents = UNIT_TEST_SUITE_COUNT(print_test);
+
+ return cmd_ut_category("print", "print_", tests, n_ents, argc, argv);
+}
diff --git a/test/ut.c b/test/ut.c
index ea0af153e4..1eec2a57df 100644
--- a/test/ut.c
+++ b/test/ut.c
@@ -51,14 +51,37 @@ long ut_check_delta(ulong last)
return ut_check_free() - last;
}
+static int readline_check(struct unit_test_state *uts)
+{
+ int ret;
+
+ ret = console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ if (ret == -ENOSPC) {
+ ut_fail(uts, __FILE__, __LINE__, __func__,
+ "Console record buffer too small - increase CONFIG_CONSOLE_RECORD_OUT_SIZE");
+ return ret;
+ }
+
+ return 0;
+}
+
int ut_check_console_line(struct unit_test_state *uts, const char *fmt, ...)
{
va_list args;
+ int len;
+ int ret;
va_start(args, fmt);
- vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args);
+ len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args);
va_end(args);
- console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ if (len >= sizeof(uts->expect_str)) {
+ ut_fail(uts, __FILE__, __LINE__, __func__,
+ "unit_test_state->expect_str too small");
+ return -EOVERFLOW;
+ }
+ ret = readline_check(uts);
+ if (ret < 0)
+ return ret;
return strcmp(uts->expect_str, uts->actual_str);
}
@@ -66,11 +89,20 @@ int ut_check_console_line(struct unit_test_state *uts, const char *fmt, ...)
int ut_check_console_linen(struct unit_test_state *uts, const char *fmt, ...)
{
va_list args;
+ int len;
+ int ret;
va_start(args, fmt);
- vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args);
+ len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args);
va_end(args);
- console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ if (len >= sizeof(uts->expect_str)) {
+ ut_fail(uts, __FILE__, __LINE__, __func__,
+ "unit_test_state->expect_str too small");
+ return -EOVERFLOW;
+ }
+ ret = readline_check(uts);
+ if (ret < 0)
+ return ret;
return strncmp(uts->expect_str, uts->actual_str,
strlen(uts->expect_str));
@@ -78,19 +110,26 @@ int ut_check_console_linen(struct unit_test_state *uts, const char *fmt, ...)
int ut_check_skipline(struct unit_test_state *uts)
{
+ int ret;
+
if (!console_record_avail())
return -ENFILE;
- console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ ret = readline_check(uts);
+ if (ret < 0)
+ return ret;
return 0;
}
int ut_check_console_end(struct unit_test_state *uts)
{
+ int ret;
+
if (!console_record_avail())
return 0;
-
- console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ ret = readline_check(uts);
+ if (ret < 0)
+ return ret;
return 1;
}
@@ -112,7 +151,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes)
if (str[8] != ':' || str[9] != ' ')
return 1;
- bytes = len - 8 - 2 - 3 * 16 - 4;
+ bytes = len - 8 - 2 - 3 * 16 - 2;
upto += bytes;
}