blob: d5d17b2818ea243598bb7fa32d8046a2e143b97e [file] [log] [blame]
wdenk20e0e232002-09-08 16:09:41 +00001/*
2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk20e0e232002-09-08 16:09:41 +00006 */
7
Grant Likely02a00782007-02-20 09:05:00 +01008#include <config.h>
wdenk20e0e232002-09-08 16:09:41 +00009#include <common.h>
Simon Glass08ea3732014-10-15 04:38:35 -060010#include <inttypes.h>
Andreas Bießmann61d01952011-07-18 20:24:04 +020011#include <version.h>
Grant Likely02a00782007-02-20 09:05:00 +010012#include <linux/ctype.h>
13#include <asm/io.h>
wdenk20e0e232002-09-08 16:09:41 +000014
15int display_options (void)
16{
wdenk20e0e232002-09-08 16:09:41 +000017#if defined(BUILD_TAG)
18 printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG);
19#else
20 printf ("\n\n%s\n\n", version_string);
21#endif
22 return 0;
23}
24
Simon Glass08ea3732014-10-15 04:38:35 -060025void print_size(uint64_t size, const char *s)
wdenk20e0e232002-09-08 16:09:41 +000026{
Timur Tabi508a4e72010-04-13 13:16:02 -050027 unsigned long m = 0, n;
Simon Glass08ea3732014-10-15 04:38:35 -060028 uint64_t f;
Timur Tabi53258da2010-04-13 13:16:03 -050029 static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'};
Nick Thompsondd7e6c12010-05-11 11:29:52 +010030 unsigned long d = 10 * ARRAY_SIZE(names);
Timur Tabi53258da2010-04-13 13:16:03 -050031 char c = 0;
32 unsigned int i;
wdenk20e0e232002-09-08 16:09:41 +000033
Nick Thompsondd7e6c12010-05-11 11:29:52 +010034 for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) {
35 if (size >> d) {
Timur Tabi53258da2010-04-13 13:16:03 -050036 c = names[i];
37 break;
Becky Brucee9954d42008-07-09 11:09:41 -050038 }
wdenk20e0e232002-09-08 16:09:41 +000039 }
40
Timur Tabi53258da2010-04-13 13:16:03 -050041 if (!c) {
Simon Glass08ea3732014-10-15 04:38:35 -060042 printf("%" PRIu64 " Bytes%s", size, s);
Timur Tabi53258da2010-04-13 13:16:03 -050043 return;
44 }
45
Nick Thompsondd7e6c12010-05-11 11:29:52 +010046 n = size >> d;
47 f = size & ((1ULL << d) - 1);
wdenk20e0e232002-09-08 16:09:41 +000048
Becky Brucee9954d42008-07-09 11:09:41 -050049 /* If there's a remainder, deal with it */
Nick Thompsondd7e6c12010-05-11 11:29:52 +010050 if (f) {
51 m = (10ULL * f + (1ULL << (d - 1))) >> d;
wdenk20e0e232002-09-08 16:09:41 +000052
Becky Brucee9954d42008-07-09 11:09:41 -050053 if (m >= 10) {
54 m -= 10;
55 n += 1;
56 }
wdenkf287a242003-07-01 21:06:45 +000057 }
58
Timur Tabi53258da2010-04-13 13:16:03 -050059 printf ("%lu", n);
wdenk20e0e232002-09-08 16:09:41 +000060 if (m) {
61 printf (".%ld", m);
62 }
Timur Tabi53258da2010-04-13 13:16:03 -050063 printf (" %ciB%s", c, s);
wdenk20e0e232002-09-08 16:09:41 +000064}
Grant Likely02a00782007-02-20 09:05:00 +010065
66/*
67 * Print data buffer in hex and ascii form to the terminal.
68 *
69 * data reads are buffered so that each memory address is only read once.
70 * Useful when displaying the contents of volatile registers.
71 *
72 * parameters:
73 * addr: Starting address to display at start of line
74 * data: pointer to data buffer
75 * width: data value width. May be 1, 2, or 4.
76 * count: number of values to display
77 * linelen: Number of values to print per line; specify 0 for default length
78 */
79#define MAX_LINE_LENGTH_BYTES (64)
80#define DEFAULT_LINE_LENGTH_BYTES (16)
Simon Glassd963b722013-02-24 17:33:12 +000081int print_buffer(ulong addr, const void *data, uint width, uint count,
82 uint linelen)
Grant Likely02a00782007-02-20 09:05:00 +010083{
Reinhard Meyerd9f13d02010-09-08 12:25:40 +020084 /* linebuf as a union causes proper alignment */
85 union linebuf {
York Sun6c480012014-02-26 17:03:19 -080086#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
87 uint64_t uq[MAX_LINE_LENGTH_BYTES/sizeof(uint64_t) + 1];
88#endif
Reinhard Meyerd9f13d02010-09-08 12:25:40 +020089 uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1];
90 uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1];
91 uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1];
92 } lb;
Grant Likely02a00782007-02-20 09:05:00 +010093 int i;
York Sun6c480012014-02-26 17:03:19 -080094#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
95 uint64_t x;
96#else
97 uint32_t x;
98#endif
Grant Likely02a00782007-02-20 09:05:00 +010099
100 if (linelen*width > MAX_LINE_LENGTH_BYTES)
101 linelen = MAX_LINE_LENGTH_BYTES / width;
102 if (linelen < 1)
103 linelen = DEFAULT_LINE_LENGTH_BYTES / width;
104
105 while (count) {
Andreas Bießmannb4ce02a2013-02-07 04:58:19 +0000106 uint thislinelen = linelen;
Grant Likely02a00782007-02-20 09:05:00 +0100107 printf("%08lx:", addr);
108
109 /* check for overflow condition */
Andreas Bießmannb4ce02a2013-02-07 04:58:19 +0000110 if (count < thislinelen)
111 thislinelen = count;
Grant Likely02a00782007-02-20 09:05:00 +0100112
113 /* Copy from memory into linebuf and print hex values */
Andreas Bießmannb4ce02a2013-02-07 04:58:19 +0000114 for (i = 0; i < thislinelen; i++) {
Mike Frysingera3a26fc2010-07-23 06:17:30 -0400115 if (width == 4)
Reinhard Meyerd9f13d02010-09-08 12:25:40 +0200116 x = lb.ui[i] = *(volatile uint32_t *)data;
York Sun6c480012014-02-26 17:03:19 -0800117#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
118 else if (width == 8)
119 x = lb.uq[i] = *(volatile uint64_t *)data;
120#endif
Mike Frysingera3a26fc2010-07-23 06:17:30 -0400121 else if (width == 2)
Reinhard Meyerd9f13d02010-09-08 12:25:40 +0200122 x = lb.us[i] = *(volatile uint16_t *)data;
Mike Frysingera3a26fc2010-07-23 06:17:30 -0400123 else
Reinhard Meyerd9f13d02010-09-08 12:25:40 +0200124 x = lb.uc[i] = *(volatile uint8_t *)data;
York Sun6c480012014-02-26 17:03:19 -0800125#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
Simon Glass08ea3732014-10-15 04:38:35 -0600126 printf(" %0*" PRIx64, width * 2, x);
York Sun6c480012014-02-26 17:03:19 -0800127#else
Mike Frysingera3a26fc2010-07-23 06:17:30 -0400128 printf(" %0*x", width * 2, x);
York Sun6c480012014-02-26 17:03:19 -0800129#endif
Grant Likely02a00782007-02-20 09:05:00 +0100130 data += width;
131 }
132
Andreas Bießmannb4ce02a2013-02-07 04:58:19 +0000133 while (thislinelen < linelen) {
134 /* fill line with whitespace for nice ASCII print */
135 for (i=0; i<width*2+1; i++)
136 puts(" ");
137 linelen--;
138 }
139
Grant Likely02a00782007-02-20 09:05:00 +0100140 /* Print data in ASCII characters */
Andreas Bießmannb4ce02a2013-02-07 04:58:19 +0000141 for (i = 0; i < thislinelen * width; i++) {
Reinhard Meyerd9f13d02010-09-08 12:25:40 +0200142 if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80)
143 lb.uc[i] = '.';
144 }
145 lb.uc[i] = '\0';
146 printf(" %s\n", lb.uc);
Grant Likely02a00782007-02-20 09:05:00 +0100147
148 /* update references */
Andreas Bießmannb4ce02a2013-02-07 04:58:19 +0000149 addr += thislinelen * width;
150 count -= thislinelen;
Grant Likely02a00782007-02-20 09:05:00 +0100151
152 if (ctrlc())
153 return -1;
154 }
155
156 return 0;
157}