blob: 2715a72d4f4a7d790dab0826be0672b8e92e1aea [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 */
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00006
Soby Mathew0691d972016-05-05 12:34:41 +01007#include <assert.h>
Soby Mathewafe7e2f2014-06-12 17:23:58 +01008#include <stdarg.h>
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +01009#include <stdbool.h>
Soby Mathewafe7e2f2014-06-12 17:23:58 +010010#include <stdint.h>
11
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000012#include <common/debug.h>
13
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010014#define get_num_va_args(_args, _lcount) \
15 (((_lcount) > 1) ? va_arg(_args, long long int) : \
16 (((_lcount) == 1) ? va_arg(_args, long int) : \
17 va_arg(_args, int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000018
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010019#define get_unum_va_args(_args, _lcount) \
20 (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \
21 (((_lcount) == 1) ? va_arg(_args, unsigned long int) : \
22 va_arg(_args, unsigned int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000023
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +010024static int string_print(const char *str)
Soby Mathewf62d5462016-03-22 17:38:00 +000025{
Antonio Nino Diazf4407082018-08-15 16:52:32 +010026 int count = 0;
27
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010028 assert(str != NULL);
Soby Mathewf583a062017-09-04 11:45:52 +010029
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010030 for ( ; *str != '\0'; str++) {
31 (void)putchar(*str);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010032 count++;
33 }
34
35 return count;
Soby Mathewf62d5462016-03-22 17:38:00 +000036}
37
Antonio Nino Diazf4407082018-08-15 16:52:32 +010038static int unsigned_num_print(unsigned long long int unum, unsigned int radix,
39 char padc, int padn)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010040{
41 /* Just need enough space to store 64 bit decimal integer */
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010042 char num_buf[20];
43 int i = 0, count = 0;
44 unsigned int rem;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010045
46 do {
47 rem = unum % radix;
48 if (rem < 0xa)
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010049 num_buf[i] = '0' + rem;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010050 else
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010051 num_buf[i] = 'a' + (rem - 0xa);
52 i++;
53 unum /= radix;
54 } while (unum > 0U);
Soby Mathewafe7e2f2014-06-12 17:23:58 +010055
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000056 if (padn > 0) {
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010057 while (i < padn) {
58 (void)putchar(padc);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010059 count++;
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010060 padn--;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000061 }
62 }
63
Antonio Nino Diazf4407082018-08-15 16:52:32 +010064 while (--i >= 0) {
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010065 (void)putchar(num_buf[i]);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010066 count++;
67 }
68
69 return count;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010070}
71
Soby Mathewafe7e2f2014-06-12 17:23:58 +010072/*******************************************************************
73 * Reduced format print for Trusted firmware.
Soby Mathewf62d5462016-03-22 17:38:00 +000074 * The following type specifiers are supported by this print
75 * %x - hexadecimal format
Soby Mathewafe7e2f2014-06-12 17:23:58 +010076 * %s - string format
Soby Mathewf62d5462016-03-22 17:38:00 +000077 * %d or %i - signed decimal format
78 * %u - unsigned decimal format
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +000079 * %p - pointer format
Soby Mathewf62d5462016-03-22 17:38:00 +000080 *
81 * The following length specifiers are supported by this print
82 * %l - long int (64-bit on AArch64)
83 * %ll - long long int (64-bit on AArch64)
84 * %z - size_t sized integer formats (64 bit on AArch64)
85 *
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000086 * The following padding specifiers are supported by this print
87 * %0NN - Left-pad the number with 0s (NN is a decimal number)
88 *
Soby Mathewf62d5462016-03-22 17:38:00 +000089 * The print exits on all other formats specifiers other than valid
90 * combinations of the above specifiers.
Soby Mathewafe7e2f2014-06-12 17:23:58 +010091 *******************************************************************/
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +010092int vprintf(const char *fmt, va_list args)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010093{
Soby Mathewf62d5462016-03-22 17:38:00 +000094 int l_count;
95 long long int num;
96 unsigned long long int unum;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010097 char *str;
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010098 char padc = '\0'; /* Padding character */
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000099 int padn; /* Number of characters to pad */
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100100 int count = 0; /* Number of printed characters */
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100101
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100102 while (*fmt != '\0') {
Soby Mathewf62d5462016-03-22 17:38:00 +0000103 l_count = 0;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000104 padn = 0;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100105
106 if (*fmt == '%') {
107 fmt++;
108 /* Check the format specifier */
109loop:
110 switch (*fmt) {
111 case 'i': /* Fall through to next one */
112 case 'd':
Soby Mathewf62d5462016-03-22 17:38:00 +0000113 num = get_num_va_args(args, l_count);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100114 if (num < 0) {
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100115 (void)putchar('-');
Soby Mathewf62d5462016-03-22 17:38:00 +0000116 unum = (unsigned long long int)-num;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000117 padn--;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100118 } else
Soby Mathewf62d5462016-03-22 17:38:00 +0000119 unum = (unsigned long long int)num;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100120
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100121 count += unsigned_num_print(unum, 10,
122 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100123 break;
124 case 's':
125 str = va_arg(args, char *);
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100126 count += string_print(str);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100127 break;
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000128 case 'p':
Soby Mathewf62d5462016-03-22 17:38:00 +0000129 unum = (uintptr_t)va_arg(args, void *);
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100130 if (unum > 0U) {
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100131 count += string_print("0x");
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000132 padn -= 2;
133 }
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000134
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100135 count += unsigned_num_print(unum, 16,
136 padc, padn);
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000137 break;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100138 case 'x':
Soby Mathewf62d5462016-03-22 17:38:00 +0000139 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100140 count += unsigned_num_print(unum, 16,
141 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100142 break;
Scott Branden57bd75c2016-03-23 13:37:33 -0700143 case 'z':
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100144 if (sizeof(size_t) == 8U)
Soby Mathewf62d5462016-03-22 17:38:00 +0000145 l_count = 2;
146
Scott Branden57bd75c2016-03-23 13:37:33 -0700147 fmt++;
148 goto loop;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100149 case 'l':
Soby Mathewf62d5462016-03-22 17:38:00 +0000150 l_count++;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100151 fmt++;
152 goto loop;
153 case 'u':
Soby Mathewf62d5462016-03-22 17:38:00 +0000154 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100155 count += unsigned_num_print(unum, 10,
156 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100157 break;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000158 case '0':
159 padc = '0';
160 padn = 0;
161 fmt++;
162
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100163 for (;;) {
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000164 char ch = *fmt;
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100165 if ((ch < '0') || (ch > '9')) {
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000166 goto loop;
167 }
168 padn = (padn * 10) + (ch - '0');
169 fmt++;
170 }
Daniel Boulby8942a1b2018-06-22 14:16:03 +0100171 assert(0); /* Unreachable */
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100172 default:
173 /* Exit on any other format specifier */
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100174 return -1;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100175 }
176 fmt++;
177 continue;
178 }
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100179 (void)putchar(*fmt);
180 fmt++;
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100181 count++;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100182 }
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100183
184 return count;
Soby Mathewf583a062017-09-04 11:45:52 +0100185}
186
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100187int printf(const char *fmt, ...)
Soby Mathewf583a062017-09-04 11:45:52 +0100188{
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100189 int count;
Soby Mathewf583a062017-09-04 11:45:52 +0100190 va_list va;
191
192 va_start(va, fmt);
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100193 count = vprintf(fmt, va);
Soby Mathewf583a062017-09-04 11:45:52 +0100194 va_end(va);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100195
196 return count;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100197}