aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSimon Glass2021-05-08 07:00:05 -0600
committerTom Rini2021-06-08 11:39:09 -0400
commit0cceb99ac59b1d383488ea3ce6511ffc01da5332 (patch)
tree67dc9eb75f3aa6a469eb4c57bfd432139a7958aa /lib
parent735dd6ef89ebd3e05c1dfaef06aca61046503c63 (diff)
display_options: Split print_buffer() into two functions
At present print_buffer() outputs a hex dump but it is not possible to place this dump in a string. Refactor it into a top-level function which does the printing and a utility function that dumps a line into a string. This makes the code more generally useful. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'lib')
-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 7752baba2bd..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;