178acc472SPeter Tyser /* 278acc472SPeter Tyser * (C) Copyright 2000-2002 378acc472SPeter Tyser * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 478acc472SPeter Tyser * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 678acc472SPeter Tyser */ 778acc472SPeter Tyser 878acc472SPeter Tyser #include <config.h> 978acc472SPeter Tyser #include <common.h> 10*c6da9ae8SSimon Glass #include <inttypes.h> 1109c2e90cSAndreas Bießmann #include <version.h> 1278acc472SPeter Tyser #include <linux/ctype.h> 1378acc472SPeter Tyser #include <asm/io.h> 1478acc472SPeter Tyser 1578acc472SPeter Tyser int display_options (void) 1678acc472SPeter Tyser { 1778acc472SPeter Tyser #if defined(BUILD_TAG) 1878acc472SPeter Tyser printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); 1978acc472SPeter Tyser #else 2078acc472SPeter Tyser printf ("\n\n%s\n\n", version_string); 2178acc472SPeter Tyser #endif 2278acc472SPeter Tyser return 0; 2378acc472SPeter Tyser } 2478acc472SPeter Tyser 25*c6da9ae8SSimon Glass void print_size(uint64_t size, const char *s) 2678acc472SPeter Tyser { 2752dbac69STimur Tabi unsigned long m = 0, n; 28*c6da9ae8SSimon Glass uint64_t f; 294b42c905STimur Tabi static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; 30f2d76ae4SNick Thompson unsigned long d = 10 * ARRAY_SIZE(names); 314b42c905STimur Tabi char c = 0; 324b42c905STimur Tabi unsigned int i; 3378acc472SPeter Tyser 34f2d76ae4SNick Thompson for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { 35f2d76ae4SNick Thompson if (size >> d) { 364b42c905STimur Tabi c = names[i]; 374b42c905STimur Tabi break; 3878acc472SPeter Tyser } 3978acc472SPeter Tyser } 4078acc472SPeter Tyser 414b42c905STimur Tabi if (!c) { 42*c6da9ae8SSimon Glass printf("%" PRIu64 " Bytes%s", size, s); 434b42c905STimur Tabi return; 444b42c905STimur Tabi } 454b42c905STimur Tabi 46f2d76ae4SNick Thompson n = size >> d; 47f2d76ae4SNick Thompson f = size & ((1ULL << d) - 1); 4878acc472SPeter Tyser 4978acc472SPeter Tyser /* If there's a remainder, deal with it */ 50f2d76ae4SNick Thompson if (f) { 51f2d76ae4SNick Thompson m = (10ULL * f + (1ULL << (d - 1))) >> d; 5278acc472SPeter Tyser 5378acc472SPeter Tyser if (m >= 10) { 5478acc472SPeter Tyser m -= 10; 5578acc472SPeter Tyser n += 1; 5678acc472SPeter Tyser } 5778acc472SPeter Tyser } 5878acc472SPeter Tyser 594b42c905STimur Tabi printf ("%lu", n); 6078acc472SPeter Tyser if (m) { 6178acc472SPeter Tyser printf (".%ld", m); 6278acc472SPeter Tyser } 634b42c905STimur Tabi printf (" %ciB%s", c, s); 6478acc472SPeter Tyser } 6578acc472SPeter Tyser 6678acc472SPeter Tyser /* 6778acc472SPeter Tyser * Print data buffer in hex and ascii form to the terminal. 6878acc472SPeter Tyser * 6978acc472SPeter Tyser * data reads are buffered so that each memory address is only read once. 7078acc472SPeter Tyser * Useful when displaying the contents of volatile registers. 7178acc472SPeter Tyser * 7278acc472SPeter Tyser * parameters: 7378acc472SPeter Tyser * addr: Starting address to display at start of line 7478acc472SPeter Tyser * data: pointer to data buffer 7578acc472SPeter Tyser * width: data value width. May be 1, 2, or 4. 7678acc472SPeter Tyser * count: number of values to display 7778acc472SPeter Tyser * linelen: Number of values to print per line; specify 0 for default length 7878acc472SPeter Tyser */ 7978acc472SPeter Tyser #define MAX_LINE_LENGTH_BYTES (64) 8078acc472SPeter Tyser #define DEFAULT_LINE_LENGTH_BYTES (16) 81bda32ffcSSimon Glass int print_buffer(ulong addr, const void *data, uint width, uint count, 82bda32ffcSSimon Glass uint linelen) 8378acc472SPeter Tyser { 84150f7236SReinhard Meyer /* linebuf as a union causes proper alignment */ 85150f7236SReinhard Meyer union linebuf { 864d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 874d1fd7f1SYork Sun uint64_t uq[MAX_LINE_LENGTH_BYTES/sizeof(uint64_t) + 1]; 884d1fd7f1SYork Sun #endif 89150f7236SReinhard Meyer uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1]; 90150f7236SReinhard Meyer uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1]; 91150f7236SReinhard Meyer uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1]; 92150f7236SReinhard Meyer } lb; 9378acc472SPeter Tyser int i; 944d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 954d1fd7f1SYork Sun uint64_t x; 964d1fd7f1SYork Sun #else 974d1fd7f1SYork Sun uint32_t x; 984d1fd7f1SYork Sun #endif 9978acc472SPeter Tyser 10078acc472SPeter Tyser if (linelen*width > MAX_LINE_LENGTH_BYTES) 10178acc472SPeter Tyser linelen = MAX_LINE_LENGTH_BYTES / width; 10278acc472SPeter Tyser if (linelen < 1) 10378acc472SPeter Tyser linelen = DEFAULT_LINE_LENGTH_BYTES / width; 10478acc472SPeter Tyser 10578acc472SPeter Tyser while (count) { 106efd7c114SAndreas Bießmann uint thislinelen = linelen; 10778acc472SPeter Tyser printf("%08lx:", addr); 10878acc472SPeter Tyser 10978acc472SPeter Tyser /* check for overflow condition */ 110efd7c114SAndreas Bießmann if (count < thislinelen) 111efd7c114SAndreas Bießmann thislinelen = count; 11278acc472SPeter Tyser 11378acc472SPeter Tyser /* Copy from memory into linebuf and print hex values */ 114efd7c114SAndreas Bießmann for (i = 0; i < thislinelen; i++) { 11564419e47SMike Frysinger if (width == 4) 116150f7236SReinhard Meyer x = lb.ui[i] = *(volatile uint32_t *)data; 1174d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 1184d1fd7f1SYork Sun else if (width == 8) 1194d1fd7f1SYork Sun x = lb.uq[i] = *(volatile uint64_t *)data; 1204d1fd7f1SYork Sun #endif 12164419e47SMike Frysinger else if (width == 2) 122150f7236SReinhard Meyer x = lb.us[i] = *(volatile uint16_t *)data; 12364419e47SMike Frysinger else 124150f7236SReinhard Meyer x = lb.uc[i] = *(volatile uint8_t *)data; 1254d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 126*c6da9ae8SSimon Glass printf(" %0*" PRIx64, width * 2, x); 1274d1fd7f1SYork Sun #else 12864419e47SMike Frysinger printf(" %0*x", width * 2, x); 1294d1fd7f1SYork Sun #endif 13078acc472SPeter Tyser data += width; 13178acc472SPeter Tyser } 13278acc472SPeter Tyser 133efd7c114SAndreas Bießmann while (thislinelen < linelen) { 134efd7c114SAndreas Bießmann /* fill line with whitespace for nice ASCII print */ 135efd7c114SAndreas Bießmann for (i=0; i<width*2+1; i++) 136efd7c114SAndreas Bießmann puts(" "); 137efd7c114SAndreas Bießmann linelen--; 138efd7c114SAndreas Bießmann } 139efd7c114SAndreas Bießmann 14078acc472SPeter Tyser /* Print data in ASCII characters */ 141efd7c114SAndreas Bießmann for (i = 0; i < thislinelen * width; i++) { 142150f7236SReinhard Meyer if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80) 143150f7236SReinhard Meyer lb.uc[i] = '.'; 144150f7236SReinhard Meyer } 145150f7236SReinhard Meyer lb.uc[i] = '\0'; 146150f7236SReinhard Meyer printf(" %s\n", lb.uc); 14778acc472SPeter Tyser 14878acc472SPeter Tyser /* update references */ 149efd7c114SAndreas Bießmann addr += thislinelen * width; 150efd7c114SAndreas Bießmann count -= thislinelen; 15178acc472SPeter Tyser 15278acc472SPeter Tyser if (ctrlc()) 15378acc472SPeter Tyser return -1; 15478acc472SPeter Tyser } 15578acc472SPeter Tyser 15678acc472SPeter Tyser return 0; 15778acc472SPeter Tyser } 158