1 /* 2 * (C) Copyright 2000-2002 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <config.h> 9 #include <common.h> 10 #include <inttypes.h> 11 #include <version.h> 12 #include <linux/ctype.h> 13 #include <asm/io.h> 14 15 int display_options (void) 16 { 17 #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 25 void print_size(uint64_t size, const char *s) 26 { 27 unsigned long m = 0, n; 28 uint64_t f; 29 static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; 30 unsigned long d = 10 * ARRAY_SIZE(names); 31 char c = 0; 32 unsigned int i; 33 34 for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { 35 if (size >> d) { 36 c = names[i]; 37 break; 38 } 39 } 40 41 if (!c) { 42 printf("%" PRIu64 " Bytes%s", size, s); 43 return; 44 } 45 46 n = size >> d; 47 f = size & ((1ULL << d) - 1); 48 49 /* If there's a remainder, deal with it */ 50 if (f) { 51 m = (10ULL * f + (1ULL << (d - 1))) >> d; 52 53 if (m >= 10) { 54 m -= 10; 55 n += 1; 56 } 57 } 58 59 printf ("%lu", n); 60 if (m) { 61 printf (".%ld", m); 62 } 63 printf (" %ciB%s", c, s); 64 } 65 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) 81 int print_buffer(ulong addr, const void *data, uint width, uint count, 82 uint linelen) 83 { 84 /* linebuf as a union causes proper alignment */ 85 union linebuf { 86 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 87 uint64_t uq[MAX_LINE_LENGTH_BYTES/sizeof(uint64_t) + 1]; 88 #endif 89 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; 93 int i; 94 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 95 uint64_t x; 96 #else 97 uint32_t x; 98 #endif 99 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) { 106 uint thislinelen = linelen; 107 printf("%08lx:", addr); 108 109 /* check for overflow condition */ 110 if (count < thislinelen) 111 thislinelen = count; 112 113 /* Copy from memory into linebuf and print hex values */ 114 for (i = 0; i < thislinelen; i++) { 115 if (width == 4) 116 x = lb.ui[i] = *(volatile uint32_t *)data; 117 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 118 else if (width == 8) 119 x = lb.uq[i] = *(volatile uint64_t *)data; 120 #endif 121 else if (width == 2) 122 x = lb.us[i] = *(volatile uint16_t *)data; 123 else 124 x = lb.uc[i] = *(volatile uint8_t *)data; 125 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 126 printf(" %0*" PRIx64, width * 2, x); 127 #else 128 printf(" %0*x", width * 2, x); 129 #endif 130 data += width; 131 } 132 133 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 140 /* Print data in ASCII characters */ 141 for (i = 0; i < thislinelen * width; i++) { 142 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); 147 148 /* update references */ 149 addr += thislinelen * width; 150 count -= thislinelen; 151 152 if (ctrlc()) 153 return -1; 154 } 155 156 return 0; 157 } 158