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>
This commit is contained in:
parent
735dd6ef89
commit
0cceb99ac5
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
uint thislinelen;
|
||||
char buf[HEXDUMP_MAX_BUF_LENGTH(width * linelen)];
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -227,6 +227,32 @@ static int print_display_buffer(struct unit_test_state *uts)
|
||||
}
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user