blob: 0def148b7eeeb1f750120de6f062f53ed8f88831 [file] [log] [blame]
Soby Mathewafe7e2f2014-06-12 17:23:58 +01001/*
Heyi Guoeb250ed2020-10-27 08:36:40 +08002 * Copyright (c) 2014-2021, 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 Diaz2e74f9b2018-08-23 15:11:46 +010012#define get_num_va_args(_args, _lcount) \
13 (((_lcount) > 1) ? va_arg(_args, long long int) : \
14 (((_lcount) == 1) ? va_arg(_args, long int) : \
15 va_arg(_args, int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000016
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010017#define get_unum_va_args(_args, _lcount) \
18 (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \
19 (((_lcount) == 1) ? va_arg(_args, unsigned long int) : \
20 va_arg(_args, unsigned int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000021
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +010022static int string_print(const char *str)
Soby Mathewf62d5462016-03-22 17:38:00 +000023{
Antonio Nino Diazf4407082018-08-15 16:52:32 +010024 int count = 0;
25
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010026 assert(str != NULL);
Soby Mathewf583a062017-09-04 11:45:52 +010027
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010028 for ( ; *str != '\0'; str++) {
29 (void)putchar(*str);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010030 count++;
31 }
32
33 return count;
Soby Mathewf62d5462016-03-22 17:38:00 +000034}
35
Antonio Nino Diazf4407082018-08-15 16:52:32 +010036static int unsigned_num_print(unsigned long long int unum, unsigned int radix,
37 char padc, int padn)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010038{
39 /* Just need enough space to store 64 bit decimal integer */
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010040 char num_buf[20];
41 int i = 0, count = 0;
42 unsigned int rem;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010043
Claus Pedersen785e66c2022-09-12 22:42:58 +000044 /* num_buf is only large enough for radix >= 10 */
45 if (radix < 10) {
46 assert(0);
47 return 0;
48 }
49
Soby Mathewafe7e2f2014-06-12 17:23:58 +010050 do {
51 rem = unum % radix;
52 if (rem < 0xa)
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010053 num_buf[i] = '0' + rem;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010054 else
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010055 num_buf[i] = 'a' + (rem - 0xa);
56 i++;
57 unum /= radix;
58 } while (unum > 0U);
Soby Mathewafe7e2f2014-06-12 17:23:58 +010059
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000060 if (padn > 0) {
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010061 while (i < padn) {
62 (void)putchar(padc);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010063 count++;
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010064 padn--;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000065 }
66 }
67
Antonio Nino Diazf4407082018-08-15 16:52:32 +010068 while (--i >= 0) {
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +010069 (void)putchar(num_buf[i]);
Antonio Nino Diazf4407082018-08-15 16:52:32 +010070 count++;
71 }
72
73 return count;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010074}
75
Soby Mathewafe7e2f2014-06-12 17:23:58 +010076/*******************************************************************
77 * Reduced format print for Trusted firmware.
Soby Mathewf62d5462016-03-22 17:38:00 +000078 * The following type specifiers are supported by this print
79 * %x - hexadecimal format
Soby Mathewafe7e2f2014-06-12 17:23:58 +010080 * %s - string format
Soby Mathewf62d5462016-03-22 17:38:00 +000081 * %d or %i - signed decimal format
82 * %u - unsigned decimal format
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +000083 * %p - pointer format
Soby Mathewf62d5462016-03-22 17:38:00 +000084 *
85 * The following length specifiers are supported by this print
86 * %l - long int (64-bit on AArch64)
87 * %ll - long long int (64-bit on AArch64)
88 * %z - size_t sized integer formats (64 bit on AArch64)
89 *
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000090 * The following padding specifiers are supported by this print
91 * %0NN - Left-pad the number with 0s (NN is a decimal number)
92 *
Soby Mathewf62d5462016-03-22 17:38:00 +000093 * The print exits on all other formats specifiers other than valid
94 * combinations of the above specifiers.
Soby Mathewafe7e2f2014-06-12 17:23:58 +010095 *******************************************************************/
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +010096int vprintf(const char *fmt, va_list args)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010097{
Soby Mathewf62d5462016-03-22 17:38:00 +000098 int l_count;
99 long long int num;
100 unsigned long long int unum;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100101 char *str;
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100102 char padc = '\0'; /* Padding character */
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000103 int padn; /* Number of characters to pad */
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100104 int count = 0; /* Number of printed characters */
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100105
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100106 while (*fmt != '\0') {
Soby Mathewf62d5462016-03-22 17:38:00 +0000107 l_count = 0;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000108 padn = 0;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100109
110 if (*fmt == '%') {
111 fmt++;
112 /* Check the format specifier */
113loop:
114 switch (*fmt) {
Heyi Guoeb250ed2020-10-27 08:36:40 +0800115 case '%':
116 (void)putchar('%');
117 break;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100118 case 'i': /* Fall through to next one */
119 case 'd':
Soby Mathewf62d5462016-03-22 17:38:00 +0000120 num = get_num_va_args(args, l_count);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100121 if (num < 0) {
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100122 (void)putchar('-');
Soby Mathewf62d5462016-03-22 17:38:00 +0000123 unum = (unsigned long long int)-num;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000124 padn--;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100125 } else
Soby Mathewf62d5462016-03-22 17:38:00 +0000126 unum = (unsigned long long int)num;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100127
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100128 count += unsigned_num_print(unum, 10,
129 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100130 break;
131 case 's':
132 str = va_arg(args, char *);
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100133 count += string_print(str);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100134 break;
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000135 case 'p':
Soby Mathewf62d5462016-03-22 17:38:00 +0000136 unum = (uintptr_t)va_arg(args, void *);
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100137 if (unum > 0U) {
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100138 count += string_print("0x");
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000139 padn -= 2;
140 }
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000141
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100142 count += unsigned_num_print(unum, 16,
143 padc, padn);
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000144 break;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100145 case 'x':
Soby Mathewf62d5462016-03-22 17:38:00 +0000146 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100147 count += unsigned_num_print(unum, 16,
148 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100149 break;
Scott Branden57bd75c2016-03-23 13:37:33 -0700150 case 'z':
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100151 if (sizeof(size_t) == 8U)
Soby Mathewf62d5462016-03-22 17:38:00 +0000152 l_count = 2;
153
Scott Branden57bd75c2016-03-23 13:37:33 -0700154 fmt++;
155 goto loop;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100156 case 'l':
Soby Mathewf62d5462016-03-22 17:38:00 +0000157 l_count++;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100158 fmt++;
159 goto loop;
160 case 'u':
Soby Mathewf62d5462016-03-22 17:38:00 +0000161 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100162 count += unsigned_num_print(unum, 10,
163 padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100164 break;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000165 case '0':
166 padc = '0';
167 padn = 0;
168 fmt++;
169
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100170 for (;;) {
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000171 char ch = *fmt;
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100172 if ((ch < '0') || (ch > '9')) {
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000173 goto loop;
174 }
175 padn = (padn * 10) + (ch - '0');
176 fmt++;
177 }
Daniel Boulby8942a1b2018-06-22 14:16:03 +0100178 assert(0); /* Unreachable */
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100179 default:
180 /* Exit on any other format specifier */
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100181 return -1;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100182 }
183 fmt++;
184 continue;
185 }
Antonio Nino Diaz2e74f9b2018-08-23 15:11:46 +0100186 (void)putchar(*fmt);
187 fmt++;
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100188 count++;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100189 }
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100190
191 return count;
Soby Mathewf583a062017-09-04 11:45:52 +0100192}
193
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100194int printf(const char *fmt, ...)
Soby Mathewf583a062017-09-04 11:45:52 +0100195{
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100196 int count;
Soby Mathewf583a062017-09-04 11:45:52 +0100197 va_list va;
198
199 va_start(va, fmt);
Antonio Nino Diazc0c8eb62018-08-15 17:02:28 +0100200 count = vprintf(fmt, va);
Soby Mathewf583a062017-09-04 11:45:52 +0100201 va_end(va);
Antonio Nino Diazf4407082018-08-15 16:52:32 +0100202
203 return count;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100204}