summaryrefslogtreecommitdiff
path: root/lib/display_options.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-06-08 17:18:35 -0400
committerTom Rini <trini@konsulko.com>2021-06-08 17:18:35 -0400
commitda29243251651e631d916b3554ad1ee57134793b (patch)
tree338db8b14138d67a2969b677258873c30aa8f03e /lib/display_options.c
parent24e1e8841c59956aaf0bd65720d0dbdd61aa3632 (diff)
parente1cbd916c86cbfdb87a7b2219624057428c285d4 (diff)
Merge branch '2021-06-08-display-and-logging-updates' into next
To quote Simon, first for the display changes: At present we have two ways of showing a hex dump. Once has been in U-Boot since the dawn of time and the other was recently added from Linux. They both have their own unique features. This series makes a few changes to bring them closer together. It also adds support for logging a buffer, which is useful since it can put it through the same log drivers as other logging output. Also it adds tests, so we can check the behaviour. And then the logging changes: At present when logging is not enabled, all log() calls become nops. This does not seem right, since if the log level is high enough then there should be some sort of message. So in that case, this series updates it to print the message if the log level is above LOGL_INFO. This mimics the behaviour for the log_...() macros like log_debug() and log_info(), so we can drop the special case for these. Also the current implementation does not support multiple log calls on the same line nicely. The tags are repeated so the line is very hard to read. This series adds that as a new feature.
Diffstat (limited to 'lib/display_options.c')
-rw-r--r--lib/display_options.c115
1 files changed, 70 insertions, 45 deletions
diff --git a/lib/display_options.c b/lib/display_options.c
index cd48998b6d4..c08a87e3162 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;