/* * (C) Copyright 2000-2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * SPDX-License-Identifier: GPL-2.0+ */ #include <config.h> #include <common.h> #include <version.h> #include <linux/ctype.h> #include <asm/io.h> 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, const 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) { uint thislinelen = linelen; printf("%08lx:", addr); /* check for overflow condition */ if (count < thislinelen) thislinelen = count; /* Copy from memory into linebuf and print hex values */ for (i = 0; i < thislinelen; 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; } while (thislinelen < linelen) { /* fill line with whitespace for nice ASCII print */ for (i=0; i<width*2+1; i++) puts(" "); linelen--; } /* Print data in ASCII characters */ for (i = 0; i < thislinelen * 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 += thislinelen * width; count -= thislinelen; if (ctrlc()) return -1; } return 0; }