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 <linux/ctype.h> 27 #include <asm/io.h> 28 29 int display_options (void) 30 { 31 extern char version_string[]; 32 33 #if defined(BUILD_TAG) 34 printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); 35 #else 36 printf ("\n\n%s\n\n", version_string); 37 #endif 38 return 0; 39 } 40 41 /* 42 * print sizes as "xxx KiB", "xxx.y KiB", "xxx MiB", "xxx.y MiB", 43 * xxx GiB, xxx.y GiB, etc as needed; allow for optional trailing string 44 * (like "\n") 45 */ 46 void print_size(unsigned long long size, const char *s) 47 { 48 unsigned long m = 0, n; 49 unsigned long long f; 50 static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; 51 unsigned long d = 10 * ARRAY_SIZE(names); 52 char c = 0; 53 unsigned int i; 54 55 for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { 56 if (size >> d) { 57 c = names[i]; 58 break; 59 } 60 } 61 62 if (!c) { 63 printf("%llu Bytes%s", size, s); 64 return; 65 } 66 67 n = size >> d; 68 f = size & ((1ULL << d) - 1); 69 70 /* If there's a remainder, deal with it */ 71 if (f) { 72 m = (10ULL * f + (1ULL << (d - 1))) >> d; 73 74 if (m >= 10) { 75 m -= 10; 76 n += 1; 77 } 78 } 79 80 printf ("%lu", n); 81 if (m) { 82 printf (".%ld", m); 83 } 84 printf (" %ciB%s", c, s); 85 } 86 87 /* 88 * Print data buffer in hex and ascii form to the terminal. 89 * 90 * data reads are buffered so that each memory address is only read once. 91 * Useful when displaying the contents of volatile registers. 92 * 93 * parameters: 94 * addr: Starting address to display at start of line 95 * data: pointer to data buffer 96 * width: data value width. May be 1, 2, or 4. 97 * count: number of values to display 98 * linelen: Number of values to print per line; specify 0 for default length 99 */ 100 #define MAX_LINE_LENGTH_BYTES (64) 101 #define DEFAULT_LINE_LENGTH_BYTES (16) 102 int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen) 103 { 104 uint8_t linebuf[MAX_LINE_LENGTH_BYTES]; 105 uint32_t *uip = (void*)linebuf; 106 uint16_t *usp = (void*)linebuf; 107 uint8_t *ucp = (void*)linebuf; 108 int i; 109 110 if (linelen*width > MAX_LINE_LENGTH_BYTES) 111 linelen = MAX_LINE_LENGTH_BYTES / width; 112 if (linelen < 1) 113 linelen = DEFAULT_LINE_LENGTH_BYTES / width; 114 115 while (count) { 116 printf("%08lx:", addr); 117 118 /* check for overflow condition */ 119 if (count < linelen) 120 linelen = count; 121 122 /* Copy from memory into linebuf and print hex values */ 123 for (i = 0; i < linelen; i++) { 124 if (width == 4) { 125 uip[i] = *(volatile uint32_t *)data; 126 printf(" %08x", uip[i]); 127 } else if (width == 2) { 128 usp[i] = *(volatile uint16_t *)data; 129 printf(" %04x", usp[i]); 130 } else { 131 ucp[i] = *(volatile uint8_t *)data; 132 printf(" %02x", ucp[i]); 133 } 134 data += width; 135 } 136 137 /* Print data in ASCII characters */ 138 puts(" "); 139 for (i = 0; i < linelen * width; i++) 140 putc(isprint(ucp[i]) && (ucp[i] < 0x80) ? ucp[i] : '.'); 141 putc ('\n'); 142 143 /* update references */ 144 addr += linelen * width; 145 count -= linelen; 146 147 if (ctrlc()) 148 return -1; 149 } 150 151 return 0; 152 } 153