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