blob: 9d8333a6b0811dde334e188e8830c557524bb3fe [file] [log] [blame]
Soby Mathewafe7e2f2014-06-12 17:23:58 +01001/*
Antonio Nino Diaz18c73532017-12-15 10:36:20 +00002 * Copyright (c) 2014-2017, 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 <arch.h>
7#include <arch_helpers.h>
8#include <assert.h>
Soby Mathewafe7e2f2014-06-12 17:23:58 +01009#include <debug.h>
Soby Mathew0691d972016-05-05 12:34:41 +010010#include <limits.h>
Soby Mathewafe7e2f2014-06-12 17:23:58 +010011#include <stdarg.h>
12#include <stdint.h>
13
14/***********************************************************
15 * The tf_printf implementation for all BL stages
16 ***********************************************************/
Soby Mathewf62d5462016-03-22 17:38:00 +000017
Daniel Boulbyfef5d2d2018-05-04 14:04:07 +010018#define get_num_va_args(_args, _lcount) \
19 (((_lcount) > 1) ? va_arg(_args, long long int) : \
20 ((_lcount) ? va_arg(_args, long int) : va_arg(_args, int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000021
Daniel Boulbyfef5d2d2018-05-04 14:04:07 +010022#define get_unum_va_args(_args, _lcount) \
23 (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \
24 ((_lcount) ? va_arg(_args, unsigned long int) : va_arg(_args, unsigned int)))
Soby Mathewf62d5462016-03-22 17:38:00 +000025
Soby Mathewf583a062017-09-04 11:45:52 +010026void tf_string_print(const char *str)
Soby Mathewf62d5462016-03-22 17:38:00 +000027{
Soby Mathewf583a062017-09-04 11:45:52 +010028 assert(str);
29
Soby Mathewf62d5462016-03-22 17:38:00 +000030 while (*str)
31 putchar(*str++);
32}
33
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000034static void unsigned_num_print(unsigned long long int unum, unsigned int radix,
35 char padc, int padn)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010036{
37 /* Just need enough space to store 64 bit decimal integer */
38 unsigned char num_buf[20];
Sandrine Bailleuxa64a8542015-03-05 10:54:34 +000039 int i = 0, rem;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010040
41 do {
42 rem = unum % radix;
43 if (rem < 0xa)
44 num_buf[i++] = '0' + rem;
45 else
46 num_buf[i++] = 'a' + (rem - 0xa);
47 } while (unum /= radix);
48
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000049 if (padn > 0) {
50 while (i < padn--) {
51 putchar(padc);
52 }
53 }
54
Soby Mathewafe7e2f2014-06-12 17:23:58 +010055 while (--i >= 0)
56 putchar(num_buf[i]);
57}
58
Soby Mathewafe7e2f2014-06-12 17:23:58 +010059/*******************************************************************
60 * Reduced format print for Trusted firmware.
Soby Mathewf62d5462016-03-22 17:38:00 +000061 * The following type specifiers are supported by this print
62 * %x - hexadecimal format
Soby Mathewafe7e2f2014-06-12 17:23:58 +010063 * %s - string format
Soby Mathewf62d5462016-03-22 17:38:00 +000064 * %d or %i - signed decimal format
65 * %u - unsigned decimal format
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +000066 * %p - pointer format
Soby Mathewf62d5462016-03-22 17:38:00 +000067 *
68 * The following length specifiers are supported by this print
69 * %l - long int (64-bit on AArch64)
70 * %ll - long long int (64-bit on AArch64)
71 * %z - size_t sized integer formats (64 bit on AArch64)
72 *
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000073 * The following padding specifiers are supported by this print
74 * %0NN - Left-pad the number with 0s (NN is a decimal number)
75 *
Soby Mathewf62d5462016-03-22 17:38:00 +000076 * The print exits on all other formats specifiers other than valid
77 * combinations of the above specifiers.
Soby Mathewafe7e2f2014-06-12 17:23:58 +010078 *******************************************************************/
Soby Mathewf583a062017-09-04 11:45:52 +010079void tf_vprintf(const char *fmt, va_list args)
Soby Mathewafe7e2f2014-06-12 17:23:58 +010080{
Soby Mathewf62d5462016-03-22 17:38:00 +000081 int l_count;
82 long long int num;
83 unsigned long long int unum;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010084 char *str;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000085 char padc = 0; /* Padding character */
86 int padn; /* Number of characters to pad */
Soby Mathewafe7e2f2014-06-12 17:23:58 +010087
Soby Mathewafe7e2f2014-06-12 17:23:58 +010088 while (*fmt) {
Soby Mathewf62d5462016-03-22 17:38:00 +000089 l_count = 0;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +000090 padn = 0;
Soby Mathewafe7e2f2014-06-12 17:23:58 +010091
92 if (*fmt == '%') {
93 fmt++;
94 /* Check the format specifier */
95loop:
96 switch (*fmt) {
97 case 'i': /* Fall through to next one */
98 case 'd':
Soby Mathewf62d5462016-03-22 17:38:00 +000099 num = get_num_va_args(args, l_count);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100100 if (num < 0) {
101 putchar('-');
Soby Mathewf62d5462016-03-22 17:38:00 +0000102 unum = (unsigned long long int)-num;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000103 padn--;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100104 } else
Soby Mathewf62d5462016-03-22 17:38:00 +0000105 unum = (unsigned long long int)num;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100106
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000107 unsigned_num_print(unum, 10, padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100108 break;
109 case 's':
110 str = va_arg(args, char *);
Soby Mathewf583a062017-09-04 11:45:52 +0100111 tf_string_print(str);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100112 break;
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000113 case 'p':
Soby Mathewf62d5462016-03-22 17:38:00 +0000114 unum = (uintptr_t)va_arg(args, void *);
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000115 if (unum) {
Soby Mathewf583a062017-09-04 11:45:52 +0100116 tf_string_print("0x");
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000117 padn -= 2;
118 }
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000119
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000120 unsigned_num_print(unum, 16, padc, padn);
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000121 break;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100122 case 'x':
Soby Mathewf62d5462016-03-22 17:38:00 +0000123 unum = get_unum_va_args(args, l_count);
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000124 unsigned_num_print(unum, 16, padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100125 break;
Scott Branden57bd75c2016-03-23 13:37:33 -0700126 case 'z':
127 if (sizeof(size_t) == 8)
Soby Mathewf62d5462016-03-22 17:38:00 +0000128 l_count = 2;
129
Scott Branden57bd75c2016-03-23 13:37:33 -0700130 fmt++;
131 goto loop;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100132 case 'l':
Soby Mathewf62d5462016-03-22 17:38:00 +0000133 l_count++;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100134 fmt++;
135 goto loop;
136 case 'u':
Soby Mathewf62d5462016-03-22 17:38:00 +0000137 unum = get_unum_va_args(args, l_count);
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000138 unsigned_num_print(unum, 10, padc, padn);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100139 break;
Antonio Nino Diaz18c73532017-12-15 10:36:20 +0000140 case '0':
141 padc = '0';
142 padn = 0;
143 fmt++;
144
145 while (1) {
146 char ch = *fmt;
147 if (ch < '0' || ch > '9') {
148 goto loop;
149 }
150 padn = (padn * 10) + (ch - '0');
151 fmt++;
152 }
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100153 default:
154 /* Exit on any other format specifier */
Soby Mathewf583a062017-09-04 11:45:52 +0100155 return;
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100156 }
157 fmt++;
158 continue;
159 }
160 putchar(*fmt++);
161 }
Soby Mathewf583a062017-09-04 11:45:52 +0100162}
163
164void tf_printf(const char *fmt, ...)
165{
166 va_list va;
167
168 va_start(va, fmt);
169 tf_vprintf(fmt, va);
170 va_end(va);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100171}