1 /* 2 * (C) Copyright 2000-2002 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <config.h> 25 #include <common.h> 26 #include <version.h> 27 #include <linux/ctype.h> 28 #include <asm/io.h> 29 30 int display_options (void) 31 { 32 #if defined(BUILD_TAG) 33 printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); 34 #else 35 printf ("\n\n%s\n\n", version_string); 36 #endif 37 return 0; 38 } 39 40 /* 41 * print sizes as "xxx KiB", "xxx.y KiB", "xxx MiB", "xxx.y MiB", 42 * xxx GiB, xxx.y GiB, etc as needed; allow for optional trailing string 43 * (like "\n") 44 */ 45 void print_size(unsigned long long size, const char *s) 46 { 47 unsigned long m = 0, n; 48 unsigned long long f; 49 static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; 50 unsigned long d = 10 * ARRAY_SIZE(names); 51 char c = 0; 52 unsigned int i; 53 54 for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { 55 if (size >> d) { 56 c = names[i]; 57 break; 58 } 59 } 60 61 if (!c) { 62 printf("%llu Bytes%s", size, s); 63 return; 64 } 65 66 n = size >> d; 67 f = size & ((1ULL << d) - 1); 68 69 /* If there's a remainder, deal with it */ 70 if (f) { 71 m = (10ULL * f + (1ULL << (d - 1))) >> d; 72 73 if (m >= 10) { 74 m -= 10; 75 n += 1; 76 } 77 } 78 79 printf ("%lu", n); 80 if (m) { 81 printf (".%ld", m); 82 } 83 printf (" %ciB%s", c, s); 84 } 85 86 /* 87 * Print data buffer in hex and ascii form to the terminal. 88 * 89 * data reads are buffered so that each memory address is only read once. 90 * Useful when displaying the contents of volatile registers. 91 * 92 * parameters: 93 * addr: Starting address to display at start of line 94 * data: pointer to data buffer 95 * width: data value width. May be 1, 2, or 4. 96 * count: number of values to display 97 * linelen: Number of values to print per line; specify 0 for default length 98 */ 99 #define MAX_LINE_LENGTH_BYTES (64) 100 #define DEFAULT_LINE_LENGTH_BYTES (16) 101 int print_buffer(ulong addr, const void *data, uint width, uint count, 102 uint linelen) 103 { 104 /* linebuf as a union causes proper alignment */ 105 union linebuf { 106 uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1]; 107 uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1]; 108 uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1]; 109 } lb; 110 int i; 111 112 if (linelen*width > MAX_LINE_LENGTH_BYTES) 113 linelen = MAX_LINE_LENGTH_BYTES / width; 114 if (linelen < 1) 115 linelen = DEFAULT_LINE_LENGTH_BYTES / width; 116 117 while (count) { 118 uint thislinelen = linelen; 119 printf("%08lx:", addr); 120 121 /* check for overflow condition */ 122 if (count < thislinelen) 123 thislinelen = count; 124 125 /* Copy from memory into linebuf and print hex values */ 126 for (i = 0; i < thislinelen; i++) { 127 uint32_t x; 128 if (width == 4) 129 x = lb.ui[i] = *(volatile uint32_t *)data; 130 else if (width == 2) 131 x = lb.us[i] = *(volatile uint16_t *)data; 132 else 133 x = lb.uc[i] = *(volatile uint8_t *)data; 134 printf(" %0*x", width * 2, x); 135 data += width; 136 } 137 138 while (thislinelen < linelen) { 139 /* fill line with whitespace for nice ASCII print */ 140 for (i=0; i<width*2+1; i++) 141 puts(" "); 142 linelen--; 143 } 144 145 /* Print data in ASCII characters */ 146 for (i = 0; i < thislinelen * width; i++) { 147 if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80) 148 lb.uc[i] = '.'; 149 } 150 lb.uc[i] = '\0'; 151 printf(" %s\n", lb.uc); 152 153 /* update references */ 154 addr += thislinelen * width; 155 count -= thislinelen; 156 157 if (ctrlc()) 158 return -1; 159 } 160 161 return 0; 162 } 163