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> 1009c2e90cSAndreas Bießmann #include <version.h> 1178acc472SPeter Tyser #include <linux/ctype.h> 1278acc472SPeter Tyser #include <asm/io.h> 1378acc472SPeter Tyser 1478acc472SPeter Tyser int display_options (void) 1578acc472SPeter Tyser { 1678acc472SPeter Tyser #if defined(BUILD_TAG) 1778acc472SPeter Tyser printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); 1878acc472SPeter Tyser #else 1978acc472SPeter Tyser printf ("\n\n%s\n\n", version_string); 2078acc472SPeter Tyser #endif 2178acc472SPeter Tyser return 0; 2278acc472SPeter Tyser } 2378acc472SPeter Tyser 2478acc472SPeter Tyser /* 254b42c905STimur Tabi * print sizes as "xxx KiB", "xxx.y KiB", "xxx MiB", "xxx.y MiB", 264b42c905STimur Tabi * xxx GiB, xxx.y GiB, etc as needed; allow for optional trailing string 2778acc472SPeter Tyser * (like "\n") 2878acc472SPeter Tyser */ 294b42c905STimur Tabi void print_size(unsigned long long size, const char *s) 3078acc472SPeter Tyser { 3152dbac69STimur Tabi unsigned long m = 0, n; 32f2d76ae4SNick Thompson unsigned long long f; 334b42c905STimur Tabi static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; 34f2d76ae4SNick Thompson unsigned long d = 10 * ARRAY_SIZE(names); 354b42c905STimur Tabi char c = 0; 364b42c905STimur Tabi unsigned int i; 3778acc472SPeter Tyser 38f2d76ae4SNick Thompson for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { 39f2d76ae4SNick Thompson if (size >> d) { 404b42c905STimur Tabi c = names[i]; 414b42c905STimur Tabi break; 4278acc472SPeter Tyser } 4378acc472SPeter Tyser } 4478acc472SPeter Tyser 454b42c905STimur Tabi if (!c) { 464b42c905STimur Tabi printf("%llu Bytes%s", size, s); 474b42c905STimur Tabi return; 484b42c905STimur Tabi } 494b42c905STimur Tabi 50f2d76ae4SNick Thompson n = size >> d; 51f2d76ae4SNick Thompson f = size & ((1ULL << d) - 1); 5278acc472SPeter Tyser 5378acc472SPeter Tyser /* If there's a remainder, deal with it */ 54f2d76ae4SNick Thompson if (f) { 55f2d76ae4SNick Thompson m = (10ULL * f + (1ULL << (d - 1))) >> d; 5678acc472SPeter Tyser 5778acc472SPeter Tyser if (m >= 10) { 5878acc472SPeter Tyser m -= 10; 5978acc472SPeter Tyser n += 1; 6078acc472SPeter Tyser } 6178acc472SPeter Tyser } 6278acc472SPeter Tyser 634b42c905STimur Tabi printf ("%lu", n); 6478acc472SPeter Tyser if (m) { 6578acc472SPeter Tyser printf (".%ld", m); 6678acc472SPeter Tyser } 674b42c905STimur Tabi printf (" %ciB%s", c, s); 6878acc472SPeter Tyser } 6978acc472SPeter Tyser 7078acc472SPeter Tyser /* 7178acc472SPeter Tyser * Print data buffer in hex and ascii form to the terminal. 7278acc472SPeter Tyser * 7378acc472SPeter Tyser * data reads are buffered so that each memory address is only read once. 7478acc472SPeter Tyser * Useful when displaying the contents of volatile registers. 7578acc472SPeter Tyser * 7678acc472SPeter Tyser * parameters: 7778acc472SPeter Tyser * addr: Starting address to display at start of line 7878acc472SPeter Tyser * data: pointer to data buffer 7978acc472SPeter Tyser * width: data value width. May be 1, 2, or 4. 8078acc472SPeter Tyser * count: number of values to display 8178acc472SPeter Tyser * linelen: Number of values to print per line; specify 0 for default length 8278acc472SPeter Tyser */ 8378acc472SPeter Tyser #define MAX_LINE_LENGTH_BYTES (64) 8478acc472SPeter Tyser #define DEFAULT_LINE_LENGTH_BYTES (16) 85bda32ffcSSimon Glass int print_buffer(ulong addr, const void *data, uint width, uint count, 86bda32ffcSSimon Glass uint linelen) 8778acc472SPeter Tyser { 88150f7236SReinhard Meyer /* linebuf as a union causes proper alignment */ 89150f7236SReinhard Meyer union linebuf { 90*4d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 91*4d1fd7f1SYork Sun uint64_t uq[MAX_LINE_LENGTH_BYTES/sizeof(uint64_t) + 1]; 92*4d1fd7f1SYork Sun #endif 93150f7236SReinhard Meyer uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1]; 94150f7236SReinhard Meyer uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1]; 95150f7236SReinhard Meyer uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1]; 96150f7236SReinhard Meyer } lb; 9778acc472SPeter Tyser int i; 98*4d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 99*4d1fd7f1SYork Sun uint64_t x; 100*4d1fd7f1SYork Sun #else 101*4d1fd7f1SYork Sun uint32_t x; 102*4d1fd7f1SYork Sun #endif 10378acc472SPeter Tyser 10478acc472SPeter Tyser if (linelen*width > MAX_LINE_LENGTH_BYTES) 10578acc472SPeter Tyser linelen = MAX_LINE_LENGTH_BYTES / width; 10678acc472SPeter Tyser if (linelen < 1) 10778acc472SPeter Tyser linelen = DEFAULT_LINE_LENGTH_BYTES / width; 10878acc472SPeter Tyser 10978acc472SPeter Tyser while (count) { 110efd7c114SAndreas Bießmann uint thislinelen = linelen; 11178acc472SPeter Tyser printf("%08lx:", addr); 11278acc472SPeter Tyser 11378acc472SPeter Tyser /* check for overflow condition */ 114efd7c114SAndreas Bießmann if (count < thislinelen) 115efd7c114SAndreas Bießmann thislinelen = count; 11678acc472SPeter Tyser 11778acc472SPeter Tyser /* Copy from memory into linebuf and print hex values */ 118efd7c114SAndreas Bießmann for (i = 0; i < thislinelen; i++) { 11964419e47SMike Frysinger if (width == 4) 120150f7236SReinhard Meyer x = lb.ui[i] = *(volatile uint32_t *)data; 121*4d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 122*4d1fd7f1SYork Sun else if (width == 8) 123*4d1fd7f1SYork Sun x = lb.uq[i] = *(volatile uint64_t *)data; 124*4d1fd7f1SYork Sun #endif 12564419e47SMike Frysinger else if (width == 2) 126150f7236SReinhard Meyer x = lb.us[i] = *(volatile uint16_t *)data; 12764419e47SMike Frysinger else 128150f7236SReinhard Meyer x = lb.uc[i] = *(volatile uint8_t *)data; 129*4d1fd7f1SYork Sun #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 130*4d1fd7f1SYork Sun printf(" %0*llx", width * 2, x); 131*4d1fd7f1SYork Sun #else 13264419e47SMike Frysinger printf(" %0*x", width * 2, x); 133*4d1fd7f1SYork Sun #endif 13478acc472SPeter Tyser data += width; 13578acc472SPeter Tyser } 13678acc472SPeter Tyser 137efd7c114SAndreas Bießmann while (thislinelen < linelen) { 138efd7c114SAndreas Bießmann /* fill line with whitespace for nice ASCII print */ 139efd7c114SAndreas Bießmann for (i=0; i<width*2+1; i++) 140efd7c114SAndreas Bießmann puts(" "); 141efd7c114SAndreas Bießmann linelen--; 142efd7c114SAndreas Bießmann } 143efd7c114SAndreas Bießmann 14478acc472SPeter Tyser /* Print data in ASCII characters */ 145efd7c114SAndreas Bießmann for (i = 0; i < thislinelen * width; i++) { 146150f7236SReinhard Meyer if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80) 147150f7236SReinhard Meyer lb.uc[i] = '.'; 148150f7236SReinhard Meyer } 149150f7236SReinhard Meyer lb.uc[i] = '\0'; 150150f7236SReinhard Meyer printf(" %s\n", lb.uc); 15178acc472SPeter Tyser 15278acc472SPeter Tyser /* update references */ 153efd7c114SAndreas Bießmann addr += thislinelen * width; 154efd7c114SAndreas Bießmann count -= thislinelen; 15578acc472SPeter Tyser 15678acc472SPeter Tyser if (ctrlc()) 15778acc472SPeter Tyser return -1; 15878acc472SPeter Tyser } 15978acc472SPeter Tyser 16078acc472SPeter Tyser return 0; 16178acc472SPeter Tyser } 162