blob: 4f4a722f7829f91a6702101212d5803caf1ab141 [file] [log] [blame]
Soby Mathewafe7e2f2014-06-12 17:23:58 +01001/*
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +01002 * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
Soby Mathewafe7e2f2014-06-12 17:23:58 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soby Mathewafe7e2f2014-06-12 17:23:58 +01005 */
Soby Mathew0691d972016-05-05 12:34:41 +01006#include <assert.h>
Soby Mathewafe7e2f2014-06-12 17:23:58 +01007#include <debug.h>
8#include <stdarg.h>
9#include <stdint.h>
10
11/***********************************************************
Antonio Nino Diaz00086e32018-08-16 16:46:06 +010012 * The printf implementation for all BL stages
Soby Mathewafe7e2f2014-06-12 17:23:58 +010013 ***********************************************************/
Soby Mathewf62d5462016-03-22 17:38:00 +000014
Daniel Boulbyfef5d2d2018-05-04 14:04:07 +010015#define get_num_va_args(_args, _lcount) \
16 (((_lcount) > 1) ? va_arg(_args, long long int) : \
17 ((_lcount) ? va_arg(_args, long int) : va_arg(_args, int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000018
Daniel Boulbyfef5d2d2018-05-04 14:04:07 +010019#define get_unum_va_args(_args, _lcount) \
20 (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \
21 ((_lcount) ? va_arg(_args, unsigned long int) : va_arg(_args, unsigned int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000022
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +010023static int string_print(const char *str)
Soby Mathewf62d5462016-03-22 17:38:00 +000024{
Antonio Nino Diazf4407082018-08-15 16:52:32 +010025 int count = 0;
26
Soby Mathewf583a062017-09-04 11:45:52 +010027 assert(str);
28
Antonio Nino Diazf4407082018-08-15 16:52:32 +010029 while (*str) {
Soby Mathewf62d5462016-03-22 17:38:00 +000030 putchar(*str++);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010031 count++;
32 }
33
34 return count;
Soby Mathewf62d5462016-03-22 17:38:00 +000035}
36
Antonio Nino Diazf4407082018-08-15 16:52:32 +010037static int unsigned_num_print(unsigned long long int unum, unsigned int radix,
38 char padc, int padn)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010039{
40 /* Just need enough space to store 64 bit decimal integer */
41 unsigned char num_buf[20];
Antonio Nino Diazf4407082018-08-15 16:52:32 +010042 int i = 0, rem, count = 0;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010043
44 do {
45 rem = unum % radix;
46 if (rem < 0xa)
47 num_buf[i++] = '0' + rem;
48 else
49 num_buf[i++] = 'a' + (rem - 0xa);
50 } while (unum /= radix);
51
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000052 if (padn > 0) {
53 while (i < padn--) {
54 putchar(padc);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010055 count++;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000056 }
57 }
58
Antonio Nino Diazf4407082018-08-15 16:52:32 +010059 while (--i >= 0) {
Soby Mathewafe7e2f2014-06-12 17:23:58 +010060 putchar(num_buf[i]);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010061 count++;
62 }
63
64 return count;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010065}
66
Soby Mathewafe7e2f2014-06-12 17:23:58 +010067/*******************************************************************
68 * Reduced format print for Trusted firmware.
Soby Mathewf62d5462016-03-22 17:38:00 +000069 * The following type specifiers are supported by this print
70 * %x - hexadecimal format
Soby Mathewafe7e2f2014-06-12 17:23:58 +010071 * %s - string format
Soby Mathewf62d5462016-03-22 17:38:00 +000072 * %d or %i - signed decimal format
73 * %u - unsigned decimal format
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +000074 * %p - pointer format
Soby Mathewf62d5462016-03-22 17:38:00 +000075 *
76 * The following length specifiers are supported by this print
77 * %l - long int (64-bit on AArch64)
78 * %ll - long long int (64-bit on AArch64)
79 * %z - size_t sized integer formats (64 bit on AArch64)
80 *
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000081 * The following padding specifiers are supported by this print
82 * %0NN - Left-pad the number with 0s (NN is a decimal number)
83 *
Soby Mathewf62d5462016-03-22 17:38:00 +000084 * The print exits on all other formats specifiers other than valid
85 * combinations of the above specifiers.
Soby Mathewafe7e2f2014-06-12 17:23:58 +010086 *******************************************************************/
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +010087int vprintf(const char *fmt, va_list args)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010088{
Soby Mathewf62d5462016-03-22 17:38:00 +000089 int l_count;
90 long long int num;
91 unsigned long long int unum;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010092 char *str;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000093 char padc = 0; /* Padding character */
94 int padn; /* Number of characters to pad */
Antonio Nino Diazf4407082018-08-15 16:52:32 +010095 int count = 0; /* Number of printed characters */
Soby Mathewafe7e2f2014-06-12 17:23:58 +010096
Soby Mathewafe7e2f2014-06-12 17:23:58 +010097 while (*fmt) {
Soby Mathewf62d5462016-03-22 17:38:00 +000098 l_count = 0;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000099 padn = 0;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100100
101 if (*fmt == '%') {
102 fmt++;
103 /* Check the format specifier */
104loop:
105 switch (*fmt) {
106 case 'i': /* Fall through to next one */
107 case 'd':
Soby Mathewf62d5462016-03-22 17:38:00 +0000108 num = get_num_va_args(args, l_count);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100109 if (num < 0) {
110 putchar('-');
Soby Mathewf62d5462016-03-22 17:38:00 +0000111 unum = (unsigned long long int)-num;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000112 padn--;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100113 } else
Soby Mathewf62d5462016-03-22 17:38:00 +0000114 unum = (unsigned long long int)num;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100115
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100116 count += unsigned_num_print(unum, 10,
117 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100118 break;
119 case 's':
120 str = va_arg(args, char *);
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100121 count += string_print(str);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100122 break;
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000123 case 'p':
Soby Mathewf62d5462016-03-22 17:38:00 +0000124 unum = (uintptr_t)va_arg(args, void *);
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000125 if (unum) {
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100126 count += string_print("0x");
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000127 padn -= 2;
128 }
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000129
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100130 count += unsigned_num_print(unum, 16,
131 padc, padn);
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000132 break;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100133 case 'x':
Soby Mathewf62d5462016-03-22 17:38:00 +0000134 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100135 count += unsigned_num_print(unum, 16,
136 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100137 break;
Scott Branden57bd75c2016-03-23 13:37:33 -0700138 case 'z':
139 if (sizeof(size_t) == 8)
Soby Mathewf62d5462016-03-22 17:38:00 +0000140 l_count = 2;
141
Scott Branden57bd75c2016-03-23 13:37:33 -0700142 fmt++;
143 goto loop;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100144 case 'l':
Soby Mathewf62d5462016-03-22 17:38:00 +0000145 l_count++;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100146 fmt++;
147 goto loop;
148 case 'u':
Soby Mathewf62d5462016-03-22 17:38:00 +0000149 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100150 count += unsigned_num_print(unum, 10,
151 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100152 break;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000153 case '0':
154 padc = '0';
155 padn = 0;
156 fmt++;
157
158 while (1) {
159 char ch = *fmt;
160 if (ch < '0' || ch > '9') {
161 goto loop;
162 }
163 padn = (padn * 10) + (ch - '0');
164 fmt++;
165 }
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100166 default:
167 /* Exit on any other format specifier */
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100168 return -1;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100169 }
170 fmt++;
171 continue;
172 }
173 putchar(*fmt++);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100174 count++;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100175 }
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100176
177 return count;
Soby Mathewf583a062017-09-04 11:45:52 +0100178}
179
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100180int printf(const char *fmt, ...)
Soby Mathewf583a062017-09-04 11:45:52 +0100181{
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100182 int count;
Soby Mathewf583a062017-09-04 11:45:52 +0100183 va_list va;
184
185 va_start(va, fmt);
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100186 count = vprintf(fmt, va);
Soby Mathewf583a062017-09-04 11:45:52 +0100187 va_end(va);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100188
189 return count;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100190}