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 <common.h> 9 #include <console.h> 10 #include <div64.h> 11 #include <inttypes.h> 12 #include <version.h> 13 #include <linux/ctype.h> 14 #include <asm/io.h> 15 16 char *display_options_get_banner_priv(bool newlines, const char *build_tag, 17 char *buf, int size) 18 { 19 int len; 20 21 len = snprintf(buf, size, "%s%s", newlines ? "\n\n" : "", 22 version_string); 23 if (build_tag && len < size) 24 len += snprintf(buf + len, size - len, ", Build: %s", 25 build_tag); 26 if (len > size - 3) 27 len = size - 3; 28 strcpy(buf + len, "\n\n"); 29 30 return buf; 31 } 32 33 #ifndef BUILD_TAG 34 #define BUILD_TAG NULL 35 #endif 36 37 char *display_options_get_banner(bool newlines, char *buf, int size) 38 { 39 return display_options_get_banner_priv(newlines, BUILD_TAG, buf, size); 40 } 41 42 int display_options(void) 43 { 44 char buf[DISPLAY_OPTIONS_BANNER_LENGTH]; 45 46 display_options_get_banner(true, buf, sizeof(buf)); 47 printf("%s", buf); 48 49 return 0; 50 } 51 52 void print_freq(uint64_t freq, const char *s) 53 { 54 unsigned long m = 0; 55 uint32_t f; 56 static const char names[] = {'G', 'M', 'K'}; 57 unsigned long d = 1e9; 58 char c = 0; 59 unsigned int i; 60 61 for (i = 0; i < ARRAY_SIZE(names); i++, d /= 1000) { 62 if (freq >= d) { 63 c = names[i]; 64 break; 65 } 66 } 67 68 if (!c) { 69 printf("%" PRIu64 " Hz%s", freq, s); 70 return; 71 } 72 73 f = do_div(freq, d); 74 75 /* If there's a remainder, show the first few digits */ 76 if (f) { 77 m = f; 78 while (m > 1000) 79 m /= 10; 80 while (m && !(m % 10)) 81 m /= 10; 82 if (m >= 100) 83 m = (m / 10) + (m % 100 >= 50); 84 } 85 86 printf("%lu", (unsigned long) freq); 87 if (m) 88 printf(".%ld", m); 89 printf(" %cHz%s", c, s); 90 } 91 92 void print_size(uint64_t size, const char *s) 93 { 94 unsigned long m = 0, n; 95 uint64_t f; 96 static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; 97 unsigned long d = 10 * ARRAY_SIZE(names); 98 char c = 0; 99 unsigned int i; 100 101 for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { 102 if (size >> d) { 103 c = names[i]; 104 break; 105 } 106 } 107 108 if (!c) { 109 printf("%" PRIu64 " Bytes%s", size, s); 110 return; 111 } 112 113 n = size >> d; 114 f = size & ((1ULL << d) - 1); 115 116 /* If there's a remainder, deal with it */ 117 if (f) { 118 m = (10ULL * f + (1ULL << (d - 1))) >> d; 119 120 if (m >= 10) { 121 m -= 10; 122 n += 1; 123 } 124 } 125 126 printf ("%lu", n); 127 if (m) { 128 printf (".%ld", m); 129 } 130 printf (" %ciB%s", c, s); 131 } 132 133 #define MAX_LINE_LENGTH_BYTES (64) 134 #define DEFAULT_LINE_LENGTH_BYTES (16) 135 int print_buffer(ulong addr, const void *data, uint width, uint count, 136 uint linelen) 137 { 138 /* linebuf as a union causes proper alignment */ 139 union linebuf { 140 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 141 uint64_t uq[MAX_LINE_LENGTH_BYTES/sizeof(uint64_t) + 1]; 142 #endif 143 uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1]; 144 uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1]; 145 uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1]; 146 } lb; 147 int i; 148 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 149 uint64_t __maybe_unused x; 150 #else 151 uint32_t __maybe_unused x; 152 #endif 153 154 if (linelen*width > MAX_LINE_LENGTH_BYTES) 155 linelen = MAX_LINE_LENGTH_BYTES / width; 156 if (linelen < 1) 157 linelen = DEFAULT_LINE_LENGTH_BYTES / width; 158 159 while (count) { 160 uint thislinelen = linelen; 161 printf("%08lx:", addr); 162 163 /* check for overflow condition */ 164 if (count < thislinelen) 165 thislinelen = count; 166 167 /* Copy from memory into linebuf and print hex values */ 168 for (i = 0; i < thislinelen; i++) { 169 if (width == 4) 170 x = lb.ui[i] = *(volatile uint32_t *)data; 171 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 172 else if (width == 8) 173 x = lb.uq[i] = *(volatile uint64_t *)data; 174 #endif 175 else if (width == 2) 176 x = lb.us[i] = *(volatile uint16_t *)data; 177 else 178 x = lb.uc[i] = *(volatile uint8_t *)data; 179 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA 180 printf(" %0*llx", width * 2, (long long)x); 181 #else 182 printf(" %0*x", width * 2, x); 183 #endif 184 data += width; 185 } 186 187 while (thislinelen < linelen) { 188 /* fill line with whitespace for nice ASCII print */ 189 for (i=0; i<width*2+1; i++) 190 puts(" "); 191 linelen--; 192 } 193 194 /* Print data in ASCII characters */ 195 for (i = 0; i < thislinelen * width; i++) { 196 if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80) 197 lb.uc[i] = '.'; 198 } 199 lb.uc[i] = '\0'; 200 printf(" %s\n", lb.uc); 201 202 /* update references */ 203 addr += thislinelen * width; 204 count -= thislinelen; 205 206 if (ctrlc()) 207 return -1; 208 } 209 210 return 0; 211 } 212