[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/libc/printf.c b/src/bsp/lk/lib/libc/printf.c
new file mode 100644
index 0000000..14e7cd1
--- /dev/null
+++ b/src/bsp/lk/lib/libc/printf.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 2008-2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <assert.h>
+#include <limits.h>
+#include <printf.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <platform/debug.h>
+
+#if WITH_NO_FP
+#define FLOAT_PRINTF 0
+#else
+#define FLOAT_PRINTF 1
+#endif
+
+int sprintf(char *str, const char *fmt, ...)
+{
+    int err;
+
+    va_list ap;
+    va_start(ap, fmt);
+    err = vsprintf(str, fmt, ap);
+    va_end(ap);
+
+    return err;
+}
+
+int snprintf(char *str, size_t len, const char *fmt, ...)
+{
+    int err;
+
+    va_list ap;
+    va_start(ap, fmt);
+    err = vsnprintf(str, len, fmt, ap);
+    va_end(ap);
+
+    return err;
+}
+
+
+#define LONGFLAG       0x00000001
+#define LONGLONGFLAG   0x00000002
+#define HALFFLAG       0x00000004
+#define HALFHALFFLAG   0x00000008
+#define SIZETFLAG      0x00000010
+#define INTMAXFLAG     0x00000020
+#define PTRDIFFFLAG    0x00000040
+#define ALTFLAG        0x00000080
+#define CAPSFLAG       0x00000100
+#define SHOWSIGNFLAG   0x00000200
+#define SIGNEDFLAG     0x00000400
+#define LEFTFORMATFLAG 0x00000800
+#define LEADZEROFLAG   0x00001000
+#define BLANKPOSFLAG   0x00002000
+
+__NO_INLINE static char *longlong_to_string(char *buf, unsigned long long n, size_t len, uint flag, char *signchar)
+{
+    size_t pos = len;
+    int negative = 0;
+
+    if ((flag & SIGNEDFLAG) && (long long)n < 0) {
+        negative = 1;
+        n = -n;
+    }
+
+    buf[--pos] = 0;
+
+    /* only do the math if the number is >= 10 */
+    while (n >= 10) {
+        int digit = n % 10;
+
+        n /= 10;
+
+        buf[--pos] = digit + '0';
+    }
+    buf[--pos] = n + '0';
+
+    if (negative)
+        *signchar = '-';
+    else if ((flag & SHOWSIGNFLAG))
+        *signchar = '+';
+    else if ((flag & BLANKPOSFLAG))
+        *signchar = ' ';
+    else
+        *signchar = '\0';
+
+    return &buf[pos];
+}
+
+static const char hextable[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+static const char hextable_caps[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+__NO_INLINE static char *longlong_to_hexstring(char *buf, unsigned long long u, size_t len, uint flag)
+{
+    size_t pos = len;
+    const char *table = (flag & CAPSFLAG) ? hextable_caps : hextable;
+
+    buf[--pos] = 0;
+    do {
+        unsigned int digit = u % 16;
+        u /= 16;
+
+        buf[--pos] = table[digit];
+    } while (u != 0);
+
+    return &buf[pos];
+}
+
+#if FLOAT_PRINTF
+union double_int {
+    double d;
+    uint64_t i;
+};
+
+#define OUT(c) buf[pos++] = (c)
+#define OUTSTR(str) do { for (size_t i = 0; (str)[i] != 0; i++) OUT((str)[i]); } while (0)
+
+/* print up to a 4 digit exponent as string, with sign */
+__NO_INLINE static size_t exponent_to_string(char *buf, int32_t exponent)
+{
+    size_t pos = 0;
+
+    /* handle sign */
+    if (exponent < 0) {
+        OUT('-');
+        exponent = -exponent;
+    } else {
+        OUT('+');
+    }
+
+    /* see how far we need to bump into the string to print from the right */
+    if (exponent >= 1000) pos += 4;
+    else if (exponent >= 100) pos += 3;
+    else if (exponent >= 10) pos += 2;
+    else pos++;
+
+    /* print decimal string, from the right */
+    uint i = pos;
+    do {
+        uint digit = (uint32_t)exponent % 10;
+
+        buf[--i] = digit + '0';
+
+        exponent /= 10;
+    } while (exponent != 0);
+
+    /* return number of characters printed */
+    return pos;
+}
+
+__NO_INLINE static char *double_to_string(char *buf, size_t len, double d, uint flag)
+{
+    size_t pos = 0;
+    union double_int u = { d };
+
+    uint32_t exponent = (u.i >> 52) & 0x7ff;
+    uint64_t fraction = (u.i & ((1ULL << 52) - 1));
+    bool neg = !!(u.i & (1ULL << 63));
+
+    /* start constructing the string */
+    if (neg) {
+        OUT('-');
+        d = -d;
+    }
+
+    /* longest:
+     * 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000o
+     */
+
+    /* look for special cases */
+    if (exponent == 0x7ff) {
+        if (fraction == 0) {
+            /* infinity */
+            if (flag & CAPSFLAG) OUTSTR("INF");
+            else OUTSTR("inf");
+        } else {
+            /* NaN */
+            if (flag & CAPSFLAG) OUTSTR("NAN");
+            else OUTSTR("nan");
+        }
+    } else if (exponent == 0) {
+        if (fraction == 0) {
+            /* zero */
+            OUTSTR("0.000000");
+        } else {
+            /* denormalized */
+            /* XXX does not handle */
+            if (flag & CAPSFLAG) OUTSTR("DEN");
+            else OUTSTR("den");
+        }
+    } else {
+        /* see if it's in the range of floats we can easily print */
+        int exponent_signed = exponent - 1023;
+        if (exponent_signed < -52 || exponent_signed > 52) {
+            OUTSTR("<range>");
+        } else {
+            /* start by walking backwards through the string */
+#define OUTREV(c) do { if (&buf[pos] == buf) goto done; else buf[--pos] = (c); } while (0)
+            pos = len;
+            OUTREV(0);
+
+            /* reserve space for the fractional component first */
+            for (int i = 0; i <= 6; i++)
+                OUTREV('0');
+            size_t decimal_spot = pos;
+
+            /* print the integer portion */
+            uint64_t u;
+            if (exponent_signed >= 0) {
+                u = fraction;
+                u |= (1ULL<<52);
+                u >>= (52 - exponent_signed);
+
+                char *s = longlong_to_string(buf, u, pos + 1, flag, &(char) {0});
+
+                pos = s - buf;
+            } else {
+                /* exponent is negative */
+                u = 0;
+                OUTREV('0');
+            }
+
+            buf[decimal_spot] = '.';
+
+            /* handle the fractional part */
+            uint32_t frac = ((d - u) * 1000000) + .5;
+
+            uint i = decimal_spot + 6 + 1;
+            while (frac != 0) {
+                uint digit = frac % 10;
+
+                buf[--i] = digit + '0';
+
+                frac /= 10;
+            }
+
+            if (neg)
+                OUTREV('-');
+
+done:
+            /* separate return path, since we've been walking backwards through the string */
+            return &buf[pos];
+        }
+#undef OUTREV
+    }
+
+    buf[pos] = 0;
+    return buf;
+}
+
+__NO_INLINE static char *double_to_hexstring(char *buf, size_t len, double d, uint flag)
+{
+    size_t pos = 0;
+    union double_int u = { d };
+
+    uint32_t exponent = (u.i >> 52) & 0x7ff;
+    uint64_t fraction = (u.i & ((1ULL << 52) - 1));
+    bool neg = !!(u.i & (1ULL << 63));
+
+    /* start constructing the string */
+    if (neg) {
+        OUT('-');
+    }
+
+    /* look for special cases */
+    if (exponent == 0x7ff) {
+        if (fraction == 0) {
+            /* infinity */
+            if (flag & CAPSFLAG) OUTSTR("INF");
+            else OUTSTR("inf");
+        } else {
+            /* NaN */
+            if (flag & CAPSFLAG) OUTSTR("NAN");
+            else OUTSTR("nan");
+        }
+    } else if (exponent == 0) {
+        if (fraction == 0) {
+            /* zero */
+            if (flag & CAPSFLAG) OUTSTR("0X0P+0");
+            else OUTSTR("0x0p+0");
+        } else {
+            /* denormalized */
+            /* XXX does not handle */
+            if (flag & CAPSFLAG) OUTSTR("DEN");
+            else OUTSTR("den");
+        }
+    } else {
+        /* regular normalized numbers:
+         * 0x1p+1
+         * 0x1.0000000000001p+1
+         * 0X1.FFFFFFFFFFFFFP+1023
+         * 0x1.FFFFFFFFFFFFFP+1023
+         */
+        int exponent_signed = exponent - 1023;
+
+        /* implicit 1. */
+        if (flag & CAPSFLAG) OUTSTR("0X1");
+        else OUTSTR("0x1");
+
+        /* select the appropriate hex case table */
+        const char *table = (flag & CAPSFLAG) ? hextable_caps : hextable;
+
+        int zero_count = 0;
+        bool output_dot = false;
+        for (int i = 52 - 4; i >= 0; i -= 4) {
+            uint digit = (fraction >> i) & 0xf;
+
+            if (digit == 0) {
+                zero_count++;
+            } else {
+                /* output a . the first time we output a char */
+                if (!output_dot) {
+                    OUT('.');
+                    output_dot = true;
+                }
+                /* if we have a non zero digit, see if we need to output a string of zeros */
+                while (zero_count > 0) {
+                    OUT('0');
+                    zero_count--;
+                }
+                buf[pos++] = table[digit];
+            }
+        }
+
+        /* handle the exponent */
+        buf[pos++] = (flag & CAPSFLAG) ? 'P' : 'p';
+        pos += exponent_to_string(&buf[pos], exponent_signed);
+    }
+
+    buf[pos] = 0;
+    return buf;
+}
+
+#undef OUT
+#undef OUTSTR
+
+#endif // FLOAT_PRINTF
+
+int vsprintf(char *str, const char *fmt, va_list ap)
+{
+    return vsnprintf(str, INT_MAX, fmt, ap);
+}
+
+struct _output_args {
+    char *outstr;
+    size_t len;
+    size_t pos;
+};
+
+static int _vsnprintf_output(const char *str, size_t len, void *state)
+{
+    struct _output_args *args = state;
+
+    size_t count = 0;
+    while (count < len) {
+        if (args->pos < args->len) {
+            args->outstr[args->pos++] = *str;
+        }
+
+        str++;
+        count++;
+    }
+
+    return count;
+}
+
+int vsnprintf(char *str, size_t len, const char *fmt, va_list ap)
+{
+    struct _output_args args;
+    int wlen;
+
+    args.outstr = str;
+    args.len = len;
+    args.pos = 0;
+
+    wlen = _printf_engine(&_vsnprintf_output, (void *)&args, fmt, ap);
+    if (args.pos >= len)
+        str[len-1] = '\0';
+    else
+        str[wlen] = '\0';
+    return wlen;
+}
+
+int _printf_engine(_printf_engine_output_func out, void *state, const char *fmt, va_list ap)
+{
+    int err = 0;
+    char c;
+    unsigned char uc;
+    const char *s;
+    size_t string_len;
+    unsigned long long n;
+    void *ptr;
+    int flags;
+    unsigned int format_num;
+    char signchar;
+    size_t chars_written = 0;
+    char num_buffer[32];
+
+#define OUTPUT_STRING(str, len) do { err = out(str, len, state); if (err < 0) { goto exit; } else { chars_written += err; } } while(0)
+#define OUTPUT_CHAR(c) do { char __temp[1] = { c }; OUTPUT_STRING(__temp, 1); } while (0)
+
+    for (;;) {
+        /* reset the format state */
+        flags = 0;
+        format_num = 0;
+        signchar = '\0';
+
+        /* handle regular chars that aren't format related */
+        s = fmt;
+        string_len = 0;
+        while ((c = *fmt++) != 0) {
+            if (c == '%')
+                break; /* we saw a '%', break and start parsing format */
+            string_len++;
+        }
+
+        /* output the string we've accumulated */
+        OUTPUT_STRING(s, string_len);
+
+        /* make sure we haven't just hit the end of the string */
+        if (c == 0)
+            break;
+
+next_format:
+        /* grab the next format character */
+        c = *fmt++;
+        if (c == 0)
+            break;
+
+        switch (c) {
+            case '0'...'9':
+                if (c == '0' && format_num == 0)
+                    flags |= LEADZEROFLAG;
+                format_num *= 10;
+                format_num += c - '0';
+                goto next_format;
+            case '.':
+                /* XXX for now eat numeric formatting */
+                goto next_format;
+            case '%':
+                OUTPUT_CHAR('%');
+                break;
+            case 'c':
+                uc = va_arg(ap, unsigned int);
+                OUTPUT_CHAR(uc);
+                break;
+            case 's':
+                s = va_arg(ap, const char *);
+                if (s == 0)
+                    s = "<null>";
+                flags &= ~LEADZEROFLAG; /* doesn't make sense for strings */
+                goto _output_string;
+            case '-':
+                flags |= LEFTFORMATFLAG;
+                goto next_format;
+            case '+':
+                flags |= SHOWSIGNFLAG;
+                goto next_format;
+            case ' ':
+                flags |= BLANKPOSFLAG;
+                goto next_format;
+            case '#':
+                flags |= ALTFLAG;
+                goto next_format;
+            case 'l':
+                if (flags & LONGFLAG)
+                    flags |= LONGLONGFLAG;
+                flags |= LONGFLAG;
+                goto next_format;
+            case 'h':
+                if (flags & HALFFLAG)
+                    flags |= HALFHALFFLAG;
+                flags |= HALFFLAG;
+                goto next_format;
+            case 'z':
+                flags |= SIZETFLAG;
+                goto next_format;
+            case 'j':
+                flags |= INTMAXFLAG;
+                goto next_format;
+            case 't':
+                flags |= PTRDIFFFLAG;
+                goto next_format;
+            case 'i':
+            case 'd':
+                n = (flags & LONGLONGFLAG) ? va_arg(ap, long long) :
+                    (flags & LONGFLAG) ? va_arg(ap, long) :
+                    (flags & HALFHALFFLAG) ? (signed char)va_arg(ap, int) :
+                    (flags & HALFFLAG) ? (short)va_arg(ap, int) :
+                    (flags & SIZETFLAG) ? va_arg(ap, ssize_t) :
+                    (flags & INTMAXFLAG) ? va_arg(ap, intmax_t) :
+                    (flags & PTRDIFFFLAG) ? va_arg(ap, ptrdiff_t) :
+                    va_arg(ap, int);
+                flags |= SIGNEDFLAG;
+                s = longlong_to_string(num_buffer, n, sizeof(num_buffer), flags, &signchar);
+                goto _output_string;
+            case 'u':
+                n = (flags & LONGLONGFLAG) ? va_arg(ap, unsigned long long) :
+                    (flags & LONGFLAG) ? va_arg(ap, unsigned long) :
+                    (flags & HALFHALFFLAG) ? (unsigned char)va_arg(ap, unsigned int) :
+                    (flags & HALFFLAG) ? (unsigned short)va_arg(ap, unsigned int) :
+                    (flags & SIZETFLAG) ? va_arg(ap, size_t) :
+                    (flags & INTMAXFLAG) ? va_arg(ap, uintmax_t) :
+                    (flags & PTRDIFFFLAG) ? (uintptr_t)va_arg(ap, ptrdiff_t) :
+                    va_arg(ap, unsigned int);
+                s = longlong_to_string(num_buffer, n, sizeof(num_buffer), flags, &signchar);
+                goto _output_string;
+            case 'p':
+                flags |= LONGFLAG | ALTFLAG;
+                goto hex;
+            case 'X':
+                flags |= CAPSFLAG;
+                /* fallthrough */
+hex:
+            case 'x':
+                n = (flags & LONGLONGFLAG) ? va_arg(ap, unsigned long long) :
+                    (flags & LONGFLAG) ? va_arg(ap, unsigned long) :
+                    (flags & HALFHALFFLAG) ? (unsigned char)va_arg(ap, unsigned int) :
+                    (flags & HALFFLAG) ? (unsigned short)va_arg(ap, unsigned int) :
+                    (flags & SIZETFLAG) ? va_arg(ap, size_t) :
+                    (flags & INTMAXFLAG) ? va_arg(ap, uintmax_t) :
+                    (flags & PTRDIFFFLAG) ? (uintptr_t)va_arg(ap, ptrdiff_t) :
+                    va_arg(ap, unsigned int);
+                s = longlong_to_hexstring(num_buffer, n, sizeof(num_buffer), flags);
+                if (flags & ALTFLAG) {
+                    OUTPUT_CHAR('0');
+                    OUTPUT_CHAR((flags & CAPSFLAG) ? 'X': 'x');
+                }
+                goto _output_string;
+            case 'n':
+                ptr = va_arg(ap, void *);
+                if (flags & LONGLONGFLAG)
+                    *(long long *)ptr = chars_written;
+                else if (flags & LONGFLAG)
+                    *(long *)ptr = chars_written;
+                else if (flags & HALFHALFFLAG)
+                    *(signed char *)ptr = chars_written;
+                else if (flags & HALFFLAG)
+                    *(short *)ptr = chars_written;
+                else if (flags & SIZETFLAG)
+                    *(size_t *)ptr = chars_written;
+                else
+                    *(int *)ptr = chars_written;
+                break;
+#if FLOAT_PRINTF
+            case 'F':
+                flags |= CAPSFLAG;
+            /* fallthrough */
+            case 'f': {
+                double d = va_arg(ap, double);
+                s = double_to_string(num_buffer, sizeof(num_buffer), d, flags);
+                goto _output_string;
+            }
+            case 'A':
+                flags |= CAPSFLAG;
+            /* fallthrough */
+            case 'a': {
+                double d = va_arg(ap, double);
+                s = double_to_hexstring(num_buffer, sizeof(num_buffer), d, flags);
+                goto _output_string;
+            }
+#endif
+            default:
+                OUTPUT_CHAR('%');
+                OUTPUT_CHAR(c);
+                break;
+        }
+
+        /* move on to the next field */
+        continue;
+
+        /* shared output code */
+_output_string:
+        string_len = strlen(s);
+
+        if (flags & LEFTFORMATFLAG) {
+            /* left justify the text */
+            OUTPUT_STRING(s, string_len);
+            uint written = err;
+
+            /* pad to the right (if necessary) */
+            for (; format_num > written; format_num--)
+                OUTPUT_CHAR(' ');
+        } else {
+            /* right justify the text (digits) */
+
+            /* if we're going to print a sign digit,
+               it'll chew up one byte of the format size */
+            if (signchar != '\0' && format_num > 0)
+                format_num--;
+
+            /* output the sign char before the leading zeros */
+            if (flags & LEADZEROFLAG && signchar != '\0')
+                OUTPUT_CHAR(signchar);
+
+            /* pad according to the format string */
+            for (; format_num > string_len; format_num--)
+                OUTPUT_CHAR(flags & LEADZEROFLAG ? '0' : ' ');
+
+            /* if not leading zeros, output the sign char just before the number */
+            if (!(flags & LEADZEROFLAG) && signchar != '\0')
+                OUTPUT_CHAR(signchar);
+
+            /* output the string */
+            OUTPUT_STRING(s, string_len);
+        }
+        continue;
+    }
+
+#undef OUTPUT_STRING
+#undef OUTPUT_CHAR
+
+exit:
+    return (err < 0) ? err : (int)chars_written;
+}