/* * (C) Copyright 2000-2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include #include int display_options (void) { #if defined(BUILD_TAG) printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); #else printf ("\n\n%s\n\n", version_string); #endif return 0; } /* * print sizes as "xxx KiB", "xxx.y KiB", "xxx MiB", "xxx.y MiB", * xxx GiB, xxx.y GiB, etc as needed; allow for optional trailing string * (like "\n") */ void print_size(unsigned long long size, const char *s) { unsigned long m = 0, n; unsigned long long f; static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; unsigned long d = 10 * ARRAY_SIZE(names); char c = 0; unsigned int i; for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { if (size >> d) { c = names[i]; break; } } if (!c) { printf("%llu Bytes%s", size, s); return; } n = size >> d; f = size & ((1ULL << d) - 1); /* If there's a remainder, deal with it */ if (f) { m = (10ULL * f + (1ULL << (d - 1))) >> d; if (m >= 10) { m -= 10; n += 1; } } printf ("%lu", n); if (m) { printf (".%ld", m); } printf (" %ciB%s", c, s); } /* * Print data buffer in hex and ascii form to the terminal. * * data reads are buffered so that each memory address is only read once. * Useful when displaying the contents of volatile registers. * * parameters: * addr: Starting address to display at start of line * data: pointer to data buffer * width: data value width. May be 1, 2, or 4. * count: number of values to display * linelen: Number of values to print per line; specify 0 for default length */ #define MAX_LINE_LENGTH_BYTES (64) #define DEFAULT_LINE_LENGTH_BYTES (16) int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen) { /* linebuf as a union causes proper alignment */ union linebuf { uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1]; uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1]; uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1]; } lb; int i; if (linelen*width > MAX_LINE_LENGTH_BYTES) linelen = MAX_LINE_LENGTH_BYTES / width; if (linelen < 1) linelen = DEFAULT_LINE_LENGTH_BYTES / width; while (count) { printf("%08lx:", addr); /* check for overflow condition */ if (count < linelen) linelen = count; /* Copy from memory into linebuf and print hex values */ for (i = 0; i < linelen; i++) { uint32_t x; if (width == 4) x = lb.ui[i] = *(volatile uint32_t *)data; else if (width == 2) x = lb.us[i] = *(volatile uint16_t *)data; else x = lb.uc[i] = *(volatile uint8_t *)data; printf(" %0*x", width * 2, x); data += width; } /* Print data in ASCII characters */ for (i = 0; i < linelen * width; i++) { if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80) lb.uc[i] = '.'; } lb.uc[i] = '\0'; printf(" %s\n", lb.uc); /* update references */ addr += linelen * width; count -= linelen; if (ctrlc()) return -1; } return 0; }