efi: Add a hook to allow adding memory mapping
[oweals/u-boot.git] / lib / vsprintf.c
1 /*
2  *  linux/lib/vsprintf.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9  * Wirzenius wrote this portably, Torvalds fucked it up :-)
10  *
11  * from hush: simple_itoa() was lifted from boa-0.93.15
12  */
13
14 #include <stdarg.h>
15 #include <linux/types.h>
16 #include <linux/string.h>
17 #include <linux/ctype.h>
18
19 #include <common.h>
20
21 #include <div64.h>
22 #define noinline __attribute__((noinline))
23
24 /* we use this so that we can do without the ctype library */
25 #define is_digit(c)     ((c) >= '0' && (c) <= '9')
26
27 static int skip_atoi(const char **s)
28 {
29         int i = 0;
30
31         while (is_digit(**s))
32                 i = i * 10 + *((*s)++) - '0';
33
34         return i;
35 }
36
37 /* Decimal conversion is by far the most typical, and is used
38  * for /proc and /sys data. This directly impacts e.g. top performance
39  * with many processes running. We optimize it for speed
40  * using code from
41  * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
42  * (with permission from the author, Douglas W. Jones). */
43
44 /* Formats correctly any integer in [0,99999].
45  * Outputs from one to five digits depending on input.
46  * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
47 static char *put_dec_trunc(char *buf, unsigned q)
48 {
49         unsigned d3, d2, d1, d0;
50         d1 = (q>>4) & 0xf;
51         d2 = (q>>8) & 0xf;
52         d3 = (q>>12);
53
54         d0 = 6*(d3 + d2 + d1) + (q & 0xf);
55         q = (d0 * 0xcd) >> 11;
56         d0 = d0 - 10*q;
57         *buf++ = d0 + '0'; /* least significant digit */
58         d1 = q + 9*d3 + 5*d2 + d1;
59         if (d1 != 0) {
60                 q = (d1 * 0xcd) >> 11;
61                 d1 = d1 - 10*q;
62                 *buf++ = d1 + '0'; /* next digit */
63
64                 d2 = q + 2*d2;
65                 if ((d2 != 0) || (d3 != 0)) {
66                         q = (d2 * 0xd) >> 7;
67                         d2 = d2 - 10*q;
68                         *buf++ = d2 + '0'; /* next digit */
69
70                         d3 = q + 4*d3;
71                         if (d3 != 0) {
72                                 q = (d3 * 0xcd) >> 11;
73                                 d3 = d3 - 10*q;
74                                 *buf++ = d3 + '0';  /* next digit */
75                                 if (q != 0)
76                                         *buf++ = q + '0'; /* most sign. digit */
77                         }
78                 }
79         }
80         return buf;
81 }
82 /* Same with if's removed. Always emits five digits */
83 static char *put_dec_full(char *buf, unsigned q)
84 {
85         /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
86         /* but anyway, gcc produces better code with full-sized ints */
87         unsigned d3, d2, d1, d0;
88         d1 = (q>>4) & 0xf;
89         d2 = (q>>8) & 0xf;
90         d3 = (q>>12);
91
92         /*
93          * Possible ways to approx. divide by 10
94          * gcc -O2 replaces multiply with shifts and adds
95          * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
96          * (x * 0x67) >> 10:  1100111
97          * (x * 0x34) >> 9:    110100 - same
98          * (x * 0x1a) >> 8:     11010 - same
99          * (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
100          */
101
102         d0 = 6*(d3 + d2 + d1) + (q & 0xf);
103         q = (d0 * 0xcd) >> 11;
104         d0 = d0 - 10*q;
105         *buf++ = d0 + '0';
106         d1 = q + 9*d3 + 5*d2 + d1;
107                 q = (d1 * 0xcd) >> 11;
108                 d1 = d1 - 10*q;
109                 *buf++ = d1 + '0';
110
111                 d2 = q + 2*d2;
112                         q = (d2 * 0xd) >> 7;
113                         d2 = d2 - 10*q;
114                         *buf++ = d2 + '0';
115
116                         d3 = q + 4*d3;
117                                 q = (d3 * 0xcd) >> 11; /* - shorter code */
118                                 /* q = (d3 * 0x67) >> 10; - would also work */
119                                 d3 = d3 - 10*q;
120                                 *buf++ = d3 + '0';
121                                         *buf++ = q + '0';
122         return buf;
123 }
124 /* No inlining helps gcc to use registers better */
125 static noinline char *put_dec(char *buf, uint64_t num)
126 {
127         while (1) {
128                 unsigned rem;
129                 if (num < 100000)
130                         return put_dec_trunc(buf, num);
131                 rem = do_div(num, 100000);
132                 buf = put_dec_full(buf, rem);
133         }
134 }
135
136 #define ZEROPAD 1               /* pad with zero */
137 #define SIGN    2               /* unsigned/signed long */
138 #define PLUS    4               /* show plus */
139 #define SPACE   8               /* space if plus */
140 #define LEFT    16              /* left justified */
141 #define SMALL   32              /* Must be 32 == 0x20 */
142 #define SPECIAL 64              /* 0x */
143
144 /*
145  * Macro to add a new character to our output string, but only if it will
146  * fit. The macro moves to the next character position in the output string.
147  */
148 #define ADDCH(str, ch) do { \
149         if ((str) < end) \
150                 *(str) = (ch); \
151         ++str; \
152         } while (0)
153
154 static char *number(char *buf, char *end, u64 num,
155                 int base, int size, int precision, int type)
156 {
157         /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
158         static const char digits[16] = "0123456789ABCDEF";
159
160         char tmp[66];
161         char sign;
162         char locase;
163         int need_pfx = ((type & SPECIAL) && base != 10);
164         int i;
165
166         /* locase = 0 or 0x20. ORing digits or letters with 'locase'
167          * produces same digits or (maybe lowercased) letters */
168         locase = (type & SMALL);
169         if (type & LEFT)
170                 type &= ~ZEROPAD;
171         sign = 0;
172         if (type & SIGN) {
173                 if ((s64) num < 0) {
174                         sign = '-';
175                         num = -(s64) num;
176                         size--;
177                 } else if (type & PLUS) {
178                         sign = '+';
179                         size--;
180                 } else if (type & SPACE) {
181                         sign = ' ';
182                         size--;
183                 }
184         }
185         if (need_pfx) {
186                 size--;
187                 if (base == 16)
188                         size--;
189         }
190
191         /* generate full string in tmp[], in reverse order */
192         i = 0;
193         if (num == 0)
194                 tmp[i++] = '0';
195         /* Generic code, for any base:
196         else do {
197                 tmp[i++] = (digits[do_div(num,base)] | locase);
198         } while (num != 0);
199         */
200         else if (base != 10) { /* 8 or 16 */
201                 int mask = base - 1;
202                 int shift = 3;
203
204                 if (base == 16)
205                         shift = 4;
206
207                 do {
208                         tmp[i++] = (digits[((unsigned char)num) & mask]
209                                         | locase);
210                         num >>= shift;
211                 } while (num);
212         } else { /* base 10 */
213                 i = put_dec(tmp, num) - tmp;
214         }
215
216         /* printing 100 using %2d gives "100", not "00" */
217         if (i > precision)
218                 precision = i;
219         /* leading space padding */
220         size -= precision;
221         if (!(type & (ZEROPAD + LEFT))) {
222                 while (--size >= 0)
223                         ADDCH(buf, ' ');
224         }
225         /* sign */
226         if (sign)
227                 ADDCH(buf, sign);
228         /* "0x" / "0" prefix */
229         if (need_pfx) {
230                 ADDCH(buf, '0');
231                 if (base == 16)
232                         ADDCH(buf, 'X' | locase);
233         }
234         /* zero or space padding */
235         if (!(type & LEFT)) {
236                 char c = (type & ZEROPAD) ? '0' : ' ';
237
238                 while (--size >= 0)
239                         ADDCH(buf, c);
240         }
241         /* hmm even more zero padding? */
242         while (i <= --precision)
243                 ADDCH(buf, '0');
244         /* actual digits of result */
245         while (--i >= 0)
246                 ADDCH(buf, tmp[i]);
247         /* trailing space padding */
248         while (--size >= 0)
249                 ADDCH(buf, ' ');
250         return buf;
251 }
252
253 static char *string(char *buf, char *end, char *s, int field_width,
254                 int precision, int flags)
255 {
256         int len, i;
257
258         if (s == NULL)
259                 s = "<NULL>";
260
261         len = strnlen(s, precision);
262
263         if (!(flags & LEFT))
264                 while (len < field_width--)
265                         ADDCH(buf, ' ');
266         for (i = 0; i < len; ++i)
267                 ADDCH(buf, *s++);
268         while (len < field_width--)
269                 ADDCH(buf, ' ');
270         return buf;
271 }
272
273 #ifdef CONFIG_CMD_NET
274 static const char hex_asc[] = "0123456789abcdef";
275 #define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
276 #define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
277
278 static inline char *pack_hex_byte(char *buf, u8 byte)
279 {
280         *buf++ = hex_asc_hi(byte);
281         *buf++ = hex_asc_lo(byte);
282         return buf;
283 }
284
285 static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
286                                 int precision, int flags)
287 {
288         /* (6 * 2 hex digits), 5 colons and trailing zero */
289         char mac_addr[6 * 3];
290         char *p = mac_addr;
291         int i;
292
293         for (i = 0; i < 6; i++) {
294                 p = pack_hex_byte(p, addr[i]);
295                 if (!(flags & SPECIAL) && i != 5)
296                         *p++ = ':';
297         }
298         *p = '\0';
299
300         return string(buf, end, mac_addr, field_width, precision,
301                       flags & ~SPECIAL);
302 }
303
304 static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
305                          int precision, int flags)
306 {
307         /* (8 * 4 hex digits), 7 colons and trailing zero */
308         char ip6_addr[8 * 5];
309         char *p = ip6_addr;
310         int i;
311
312         for (i = 0; i < 8; i++) {
313                 p = pack_hex_byte(p, addr[2 * i]);
314                 p = pack_hex_byte(p, addr[2 * i + 1]);
315                 if (!(flags & SPECIAL) && i != 7)
316                         *p++ = ':';
317         }
318         *p = '\0';
319
320         return string(buf, end, ip6_addr, field_width, precision,
321                       flags & ~SPECIAL);
322 }
323
324 static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
325                          int precision, int flags)
326 {
327         /* (4 * 3 decimal digits), 3 dots and trailing zero */
328         char ip4_addr[4 * 4];
329         char temp[3];   /* hold each IP quad in reverse order */
330         char *p = ip4_addr;
331         int i, digits;
332
333         for (i = 0; i < 4; i++) {
334                 digits = put_dec_trunc(temp, addr[i]) - temp;
335                 /* reverse the digits in the quad */
336                 while (digits--)
337                         *p++ = temp[digits];
338                 if (i != 3)
339                         *p++ = '.';
340         }
341         *p = '\0';
342
343         return string(buf, end, ip4_addr, field_width, precision,
344                       flags & ~SPECIAL);
345 }
346 #endif
347
348 /*
349  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
350  * by an extra set of alphanumeric characters that are extended format
351  * specifiers.
352  *
353  * Right now we handle:
354  *
355  * - 'M' For a 6-byte MAC address, it prints the address in the
356  *       usual colon-separated hex notation
357  * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
358  *       decimal for v4 and colon separated network-order 16 bit hex for v6)
359  * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
360  *       currently the same
361  *
362  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
363  * function pointers are really function descriptors, which contain a
364  * pointer to the real address.
365  */
366 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
367                 int field_width, int precision, int flags)
368 {
369         u64 num = (uintptr_t)ptr;
370
371         /*
372          * Being a boot loader, we explicitly allow pointers to
373          * (physical) address null.
374          */
375 #if 0
376         if (!ptr)
377                 return string(buf, end, "(null)", field_width, precision,
378                               flags);
379 #endif
380
381 #ifdef CONFIG_CMD_NET
382         switch (*fmt) {
383         case 'a':
384                 flags |= SPECIAL | ZEROPAD;
385
386                 switch (fmt[1]) {
387                 case 'p':
388                 default:
389                         field_width = sizeof(phys_addr_t) * 2 + 2;
390                         num = *(phys_addr_t *)ptr;
391                         break;
392                 }
393                 break;
394         case 'm':
395                 flags |= SPECIAL;
396                 /* Fallthrough */
397         case 'M':
398                 return mac_address_string(buf, end, ptr, field_width,
399                                           precision, flags);
400         case 'i':
401                 flags |= SPECIAL;
402                 /* Fallthrough */
403         case 'I':
404                 if (fmt[1] == '6')
405                         return ip6_addr_string(buf, end, ptr, field_width,
406                                                precision, flags);
407                 if (fmt[1] == '4')
408                         return ip4_addr_string(buf, end, ptr, field_width,
409                                                precision, flags);
410                 flags &= ~SPECIAL;
411                 break;
412         }
413 #endif
414         flags |= SMALL;
415         if (field_width == -1) {
416                 field_width = 2*sizeof(void *);
417                 flags |= ZEROPAD;
418         }
419         return number(buf, end, num, 16, field_width, precision, flags);
420 }
421
422 static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
423                               va_list args)
424 {
425         u64 num;
426         int base;
427         char *str;
428
429         int flags;              /* flags to number() */
430
431         int field_width;        /* width of output field */
432         int precision;          /* min. # of digits for integers; max
433                                    number of chars for from string */
434         int qualifier;          /* 'h', 'l', or 'L' for integer fields */
435                                 /* 'z' support added 23/7/1999 S.H.    */
436                                 /* 'z' changed to 'Z' --davidm 1/25/99 */
437                                 /* 't' added for ptrdiff_t */
438         char *end = buf + size;
439
440         /* Make sure end is always >= buf - do we want this in U-Boot? */
441         if (end < buf) {
442                 end = ((void *)-1);
443                 size = end - buf;
444         }
445         str = buf;
446
447         for (; *fmt ; ++fmt) {
448                 if (*fmt != '%') {
449                         ADDCH(str, *fmt);
450                         continue;
451                 }
452
453                 /* process flags */
454                 flags = 0;
455 repeat:
456                         ++fmt;          /* this also skips first '%' */
457                         switch (*fmt) {
458                         case '-':
459                                 flags |= LEFT;
460                                 goto repeat;
461                         case '+':
462                                 flags |= PLUS;
463                                 goto repeat;
464                         case ' ':
465                                 flags |= SPACE;
466                                 goto repeat;
467                         case '#':
468                                 flags |= SPECIAL;
469                                 goto repeat;
470                         case '0':
471                                 flags |= ZEROPAD;
472                                 goto repeat;
473                         }
474
475                 /* get field width */
476                 field_width = -1;
477                 if (is_digit(*fmt))
478                         field_width = skip_atoi(&fmt);
479                 else if (*fmt == '*') {
480                         ++fmt;
481                         /* it's the next argument */
482                         field_width = va_arg(args, int);
483                         if (field_width < 0) {
484                                 field_width = -field_width;
485                                 flags |= LEFT;
486                         }
487                 }
488
489                 /* get the precision */
490                 precision = -1;
491                 if (*fmt == '.') {
492                         ++fmt;
493                         if (is_digit(*fmt))
494                                 precision = skip_atoi(&fmt);
495                         else if (*fmt == '*') {
496                                 ++fmt;
497                                 /* it's the next argument */
498                                 precision = va_arg(args, int);
499                         }
500                         if (precision < 0)
501                                 precision = 0;
502                 }
503
504                 /* get the conversion qualifier */
505                 qualifier = -1;
506                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
507                     *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
508                         qualifier = *fmt;
509                         ++fmt;
510                         if (qualifier == 'l' && *fmt == 'l') {
511                                 qualifier = 'L';
512                                 ++fmt;
513                         }
514                 }
515
516                 /* default base */
517                 base = 10;
518
519                 switch (*fmt) {
520                 case 'c':
521                         if (!(flags & LEFT)) {
522                                 while (--field_width > 0)
523                                         ADDCH(str, ' ');
524                         }
525                         ADDCH(str, (unsigned char) va_arg(args, int));
526                         while (--field_width > 0)
527                                 ADDCH(str, ' ');
528                         continue;
529
530                 case 's':
531                         str = string(str, end, va_arg(args, char *),
532                                      field_width, precision, flags);
533                         continue;
534
535                 case 'p':
536                         str = pointer(fmt + 1, str, end,
537                                         va_arg(args, void *),
538                                         field_width, precision, flags);
539                         /* Skip all alphanumeric pointer suffixes */
540                         while (isalnum(fmt[1]))
541                                 fmt++;
542                         continue;
543
544                 case 'n':
545                         if (qualifier == 'l') {
546                                 long *ip = va_arg(args, long *);
547                                 *ip = (str - buf);
548                         } else {
549                                 int *ip = va_arg(args, int *);
550                                 *ip = (str - buf);
551                         }
552                         continue;
553
554                 case '%':
555                         ADDCH(str, '%');
556                         continue;
557
558                 /* integer number formats - set up the flags and "break" */
559                 case 'o':
560                         base = 8;
561                         break;
562
563                 case 'x':
564                         flags |= SMALL;
565                 case 'X':
566                         base = 16;
567                         break;
568
569                 case 'd':
570                 case 'i':
571                         flags |= SIGN;
572                 case 'u':
573                         break;
574
575                 default:
576                         ADDCH(str, '%');
577                         if (*fmt)
578                                 ADDCH(str, *fmt);
579                         else
580                                 --fmt;
581                         continue;
582                 }
583                 if (qualifier == 'L')  /* "quad" for 64 bit variables */
584                         num = va_arg(args, unsigned long long);
585                 else if (qualifier == 'l') {
586                         num = va_arg(args, unsigned long);
587                         if (flags & SIGN)
588                                 num = (signed long) num;
589                 } else if (qualifier == 'Z' || qualifier == 'z') {
590                         num = va_arg(args, size_t);
591                 } else if (qualifier == 't') {
592                         num = va_arg(args, ptrdiff_t);
593                 } else if (qualifier == 'h') {
594                         num = (unsigned short) va_arg(args, int);
595                         if (flags & SIGN)
596                                 num = (signed short) num;
597                 } else {
598                         num = va_arg(args, unsigned int);
599                         if (flags & SIGN)
600                                 num = (signed int) num;
601                 }
602                 str = number(str, end, num, base, field_width, precision,
603                              flags);
604         }
605
606         if (size > 0) {
607                 ADDCH(str, '\0');
608                 if (str > end)
609                         end[-1] = '\0';
610                 --str;
611         }
612         /* the trailing null byte doesn't count towards the total */
613         return str - buf;
614 }
615
616 int vsnprintf(char *buf, size_t size, const char *fmt,
617                               va_list args)
618 {
619         return vsnprintf_internal(buf, size, fmt, args);
620 }
621
622 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
623 {
624         int i;
625
626         i = vsnprintf(buf, size, fmt, args);
627
628         if (likely(i < size))
629                 return i;
630         if (size != 0)
631                 return size - 1;
632         return 0;
633 }
634
635 int snprintf(char *buf, size_t size, const char *fmt, ...)
636 {
637         va_list args;
638         int i;
639
640         va_start(args, fmt);
641         i = vsnprintf(buf, size, fmt, args);
642         va_end(args);
643
644         return i;
645 }
646
647 int scnprintf(char *buf, size_t size, const char *fmt, ...)
648 {
649         va_list args;
650         int i;
651
652         va_start(args, fmt);
653         i = vscnprintf(buf, size, fmt, args);
654         va_end(args);
655
656         return i;
657 }
658
659 /**
660  * Format a string and place it in a buffer (va_list version)
661  *
662  * @param buf   The buffer to place the result into
663  * @param fmt   The format string to use
664  * @param args  Arguments for the format string
665  *
666  * The function returns the number of characters written
667  * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
668  * buffer overflows.
669  *
670  * If you're not already dealing with a va_list consider using sprintf().
671  */
672 int vsprintf(char *buf, const char *fmt, va_list args)
673 {
674         return vsnprintf_internal(buf, INT_MAX, fmt, args);
675 }
676
677 int sprintf(char *buf, const char *fmt, ...)
678 {
679         va_list args;
680         int i;
681
682         va_start(args, fmt);
683         i = vsprintf(buf, fmt, args);
684         va_end(args);
685         return i;
686 }
687
688 int printf(const char *fmt, ...)
689 {
690         va_list args;
691         uint i;
692         char printbuffer[CONFIG_SYS_PBSIZE];
693
694         va_start(args, fmt);
695
696         /*
697          * For this to work, printbuffer must be larger than
698          * anything we ever want to print.
699          */
700         i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
701         va_end(args);
702
703         /* Print the string */
704         puts(printbuffer);
705         return i;
706 }
707
708 int vprintf(const char *fmt, va_list args)
709 {
710         uint i;
711         char printbuffer[CONFIG_SYS_PBSIZE];
712
713         /*
714          * For this to work, printbuffer must be larger than
715          * anything we ever want to print.
716          */
717         i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
718
719         /* Print the string */
720         puts(printbuffer);
721         return i;
722 }
723
724
725 void __assert_fail(const char *assertion, const char *file, unsigned line,
726                    const char *function)
727 {
728         /* This will not return */
729         panic("%s:%u: %s: Assertion `%s' failed.", file, line, function,
730               assertion);
731 }
732
733 char *simple_itoa(ulong i)
734 {
735         /* 21 digits plus null terminator, good for 64-bit or smaller ints */
736         static char local[22];
737         char *p = &local[21];
738
739         *p-- = '\0';
740         do {
741                 *p-- = '0' + i % 10;
742                 i /= 10;
743         } while (i > 0);
744         return p + 1;
745 }
746
747 /* We don't seem to have %'d in U-Boot */
748 void print_grouped_ull(unsigned long long int_val, int digits)
749 {
750         char str[21], *s;
751         int grab = 3;
752
753         digits = (digits + 2) / 3;
754         sprintf(str, "%*llu", digits * 3, int_val);
755         for (s = str; *s; s += grab) {
756                 if (s != str)
757                         putc(s[-1] != ' ' ? ',' : ' ');
758                 printf("%.*s", grab, s);
759                 grab = 3;
760         }
761 }
762
763 bool str2off(const char *p, loff_t *num)
764 {
765         char *endptr;
766
767         *num = simple_strtoull(p, &endptr, 16);
768         return *p != '\0' && *endptr == '\0';
769 }
770
771 bool str2long(const char *p, ulong *num)
772 {
773         char *endptr;
774
775         *num = simple_strtoul(p, &endptr, 16);
776         return *p != '\0' && *endptr == '\0';
777 }