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