diff options
author | Simon Glass | 2021-05-08 07:00:05 -0600 |
---|---|---|
committer | Tom Rini | 2021-06-08 11:39:09 -0400 |
commit | 0cceb99ac59b1d383488ea3ce6511ffc01da5332 (patch) | |
tree | 67dc9eb75f3aa6a469eb4c57bfd432139a7958aa /lib | |
parent | 735dd6ef89ebd3e05c1dfaef06aca61046503c63 (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.c | 115 |
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; |