]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - lib/vsprintf.c
ARM: imx6ul: add support for mxsfb on i.MX6UL
[karo-tx-uboot.git] / lib / vsprintf.c
index 92a9232c2a1421fd3033f9248d23749cce9d07b0..4c82837cc41e8e55899d945e8f27d399a0b0be71 100644 (file)
 #endif
 
 #include <div64.h>
-# define NUM_TYPE long long
 #define noinline __attribute__((noinline))
 
-/* some reluctance to put this into a new limits.h, so it is here */
-#define INT_MAX                ((int)(~0U>>1))
-
-const char hex_asc[] = "0123456789abcdef";
-#define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
-#define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
-
-static inline char *pack_hex_byte(char *buf, u8 byte)
-{
-       *buf++ = hex_asc_hi(byte);
-       *buf++ = hex_asc_lo(byte);
-       return buf;
-}
-
 unsigned long simple_strtoul(const char *cp, char **endp,
                                unsigned int base)
 {
@@ -104,7 +89,7 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
        return simple_strtoul(cp, endp, base);
 }
 
-int ustrtoul(const char *cp, char **endp, unsigned int base)
+unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
 {
        unsigned long result = simple_strtoul(cp, endp, base);
        switch (**endp) {
@@ -127,6 +112,29 @@ int ustrtoul(const char *cp, char **endp, unsigned int base)
        return result;
 }
 
+unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
+{
+       unsigned long long result = simple_strtoull(cp, endp, base);
+       switch (**endp) {
+       case 'G':
+               result *= 1024;
+               /* fall through */
+       case 'M':
+               result *= 1024;
+               /* fall through */
+       case 'K':
+       case 'k':
+               result *= 1024;
+               if ((*endp)[1] == 'i') {
+                       if ((*endp)[2] == 'B')
+                               (*endp) += 3;
+                       else
+                               (*endp) += 2;
+               }
+       }
+       return result;
+}
+
 unsigned long long simple_strtoull(const char *cp, char **endp,
                                        unsigned int base)
 {
@@ -158,6 +166,25 @@ unsigned long long simple_strtoull(const char *cp, char **endp,
        return result;
 }
 
+long trailing_strtoln(const char *str, const char *end)
+{
+       const char *p;
+
+       if (!end)
+               end = str + strlen(str);
+       for (p = end - 1; p > str; p--) {
+               if (!isdigit(*p))
+                       return simple_strtoul(p + 1, NULL, 10);
+       }
+
+       return -1;
+}
+
+long trailing_strtol(const char *str)
+{
+       return trailing_strtoln(str, NULL);
+}
+
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)    ((c) >= '0' && (c) <= '9')
 
@@ -259,7 +286,7 @@ static char *put_dec_full(char *buf, unsigned q)
        return buf;
 }
 /* No inlining helps gcc to use registers better */
-static noinline char *put_dec(char *buf, unsigned NUM_TYPE num)
+static noinline char *put_dec(char *buf, uint64_t num)
 {
        while (1) {
                unsigned rem;
@@ -292,7 +319,7 @@ static noinline char *put_dec(char *buf, unsigned NUM_TYPE num)
 #define ADDCH(str, ch) (*(str)++ = (ch))
 #endif
 
-static char *number(char *buf, char *end, unsigned NUM_TYPE num,
+static char *number(char *buf, char *end, u64 num,
                int base, int size, int precision, int type)
 {
        /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
@@ -311,9 +338,9 @@ static char *number(char *buf, char *end, unsigned NUM_TYPE num,
                type &= ~ZEROPAD;
        sign = 0;
        if (type & SIGN) {
-               if ((signed NUM_TYPE) num < 0) {
+               if ((s64) num < 0) {
                        sign = '-';
-                       num = -(signed NUM_TYPE) num;
+                       num = -(s64) num;
                        size--;
                } else if (type & PLUS) {
                        sign = '+';
@@ -396,7 +423,7 @@ static char *string(char *buf, char *end, char *s, int field_width,
 {
        int len, i;
 
-       if (s == 0)
+       if (s == NULL)
                s = "<NULL>";
 
        len = strnlen(s, precision);
@@ -412,6 +439,17 @@ static char *string(char *buf, char *end, char *s, int field_width,
 }
 
 #ifdef CONFIG_CMD_NET
+static const char hex_asc[] = "0123456789abcdef";
+#define hex_asc_lo(x)  hex_asc[((x) & 0x0f)]
+#define hex_asc_hi(x)  hex_asc[((x) & 0xf0) >> 4]
+
+static inline char *pack_hex_byte(char *buf, u8 byte)
+{
+       *buf++ = hex_asc_hi(byte);
+       *buf++ = hex_asc_lo(byte);
+       return buf;
+}
+
 static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
                                int precision, int flags)
 {
@@ -496,12 +534,31 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                int field_width, int precision, int flags)
 {
+       u64 num = (uintptr_t)ptr;
+
+       /*
+        * Being a boot loader, we explicitly allow pointers to
+        * (physical) address null.
+        */
+#if 0
        if (!ptr)
                return string(buf, end, "(null)", field_width, precision,
                              flags);
+#endif
 
 #ifdef CONFIG_CMD_NET
        switch (*fmt) {
+       case 'a':
+               flags |= SPECIAL | ZEROPAD;
+
+               switch (fmt[1]) {
+               case 'p':
+               default:
+                       field_width = sizeof(phys_addr_t) * 2 + 2;
+                       num = *(phys_addr_t *)ptr;
+                       break;
+               }
+               break;
        case 'm':
                flags |= SPECIAL;
                /* Fallthrough */
@@ -527,14 +584,13 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                field_width = 2*sizeof(void *);
                flags |= ZEROPAD;
        }
-       return number(buf, end, (unsigned long)ptr, 16, field_width,
-                     precision, flags);
+       return number(buf, end, num, 16, field_width, precision, flags);
 }
 
 static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
                              va_list args)
 {
-       unsigned NUM_TYPE num;
+       u64 num;
        int base;
        char *str;
 
@@ -722,6 +778,7 @@ repeat:
                ADDCH(str, '\0');
                if (str > end)
                        end[-1] = '\0';
+               --str;
        }
 #else
        *str = '\0';
@@ -804,13 +861,11 @@ int sprintf(char *buf, const char *fmt, ...)
        return i;
 }
 
-void panic(const char *fmt, ...)
+static void panic_finish(void) __attribute__ ((noreturn));
+
+static void panic_finish(void)
 {
-       va_list args;
-       va_start(args, fmt);
-       vprintf(fmt, args);
        putc('\n');
-       va_end(args);
 #if defined(CONFIG_PANIC_HANG)
        hang();
 #else
@@ -821,6 +876,21 @@ void panic(const char *fmt, ...)
                ;
 }
 
+void panic_str(const char *str)
+{
+       puts(str);
+       panic_finish();
+}
+
+void panic(const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       va_end(args);
+       panic_finish();
+}
+
 void __assert_fail(const char *assertion, const char *file, unsigned line,
                   const char *function)
 {
@@ -842,3 +912,35 @@ char *simple_itoa(ulong i)
        } while (i > 0);
        return p + 1;
 }
+
+/* We don't seem to have %'d in U-Boot */
+void print_grouped_ull(unsigned long long int_val, int digits)
+{
+       char str[21], *s;
+       int grab = 3;
+
+       digits = (digits + 2) / 3;
+       sprintf(str, "%*llu", digits * 3, int_val);
+       for (s = str; *s; s += grab) {
+               if (s != str)
+                       putc(s[-1] != ' ' ? ',' : ' ');
+               printf("%.*s", grab, s);
+               grab = 3;
+       }
+}
+
+bool str2off(const char *p, loff_t *num)
+{
+       char *endptr;
+
+       *num = simple_strtoull(p, &endptr, 16);
+       return *p != '\0' && *endptr == '\0';
+}
+
+bool str2long(const char *p, ulong *num)
+{
+       char *endptr;
+
+       *num = simple_strtoul(p, &endptr, 16);
+       return *p != '\0' && *endptr == '\0';
+}