blob: ecf058ca9b8c3f67ade4877fa46574737807fa69 [file] [log] [blame]
Soby Mathewb79af932014-06-12 17:23:58 +01001/*
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +00002 * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
Soby Mathewb79af932014-06-12 17:23:58 +01003 *
dp-arm82cb2c12017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soby Mathewb79af932014-06-12 17:23:58 +01005 */
Soby Mathewbc202b42016-05-05 12:34:41 +01006#include <arch.h>
7#include <arch_helpers.h>
8#include <assert.h>
Soby Mathewb79af932014-06-12 17:23:58 +01009#include <debug.h>
Soby Mathewbc202b42016-05-05 12:34:41 +010010#include <limits.h>
Soby Mathewb79af932014-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 Mathewf2f5a7b2016-03-22 17:38:00 +000017
Daniel Boulby896a5902018-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 Mathewf2f5a7b2016-03-22 17:38:00 +000021
Daniel Boulby896a5902018-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 Mathewf2f5a7b2016-03-22 17:38:00 +000025
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010026int tf_string_print(const char *str)
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000027{
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010028 int count = 0;
29
Soby Mathew2d7e8282017-09-04 11:45:52 +010030 assert(str);
31
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010032 while (*str) {
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000033 putchar(*str++);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010034 count++;
35 }
36
37 return count;
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000038}
39
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010040static int unsigned_num_print(unsigned long long int unum, unsigned int radix,
41 char padc, int padn)
Soby Mathewb79af932014-06-12 17:23:58 +010042{
43 /* Just need enough space to store 64 bit decimal integer */
44 unsigned char num_buf[20];
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010045 int i = 0, rem, count = 0;
Soby Mathewb79af932014-06-12 17:23:58 +010046
47 do {
48 rem = unum % radix;
49 if (rem < 0xa)
50 num_buf[i++] = '0' + rem;
51 else
52 num_buf[i++] = 'a' + (rem - 0xa);
53 } while (unum /= radix);
54
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +000055 if (padn > 0) {
56 while (i < padn--) {
57 putchar(padc);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010058 count++;
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +000059 }
60 }
61
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010062 while (--i >= 0) {
Soby Mathewb79af932014-06-12 17:23:58 +010063 putchar(num_buf[i]);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010064 count++;
65 }
66
67 return count;
Soby Mathewb79af932014-06-12 17:23:58 +010068}
69
Soby Mathewb79af932014-06-12 17:23:58 +010070/*******************************************************************
71 * Reduced format print for Trusted firmware.
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000072 * The following type specifiers are supported by this print
73 * %x - hexadecimal format
Soby Mathewb79af932014-06-12 17:23:58 +010074 * %s - string format
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000075 * %d or %i - signed decimal format
76 * %u - unsigned decimal format
Antonio Nino Diazf0dd0612016-02-02 12:03:38 +000077 * %p - pointer format
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000078 *
79 * The following length specifiers are supported by this print
80 * %l - long int (64-bit on AArch64)
81 * %ll - long long int (64-bit on AArch64)
82 * %z - size_t sized integer formats (64 bit on AArch64)
83 *
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +000084 * The following padding specifiers are supported by this print
85 * %0NN - Left-pad the number with 0s (NN is a decimal number)
86 *
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000087 * The print exits on all other formats specifiers other than valid
88 * combinations of the above specifiers.
Soby Mathewb79af932014-06-12 17:23:58 +010089 *******************************************************************/
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010090int tf_vprintf(const char *fmt, va_list args)
Soby Mathewb79af932014-06-12 17:23:58 +010091{
Soby Mathewf2f5a7b2016-03-22 17:38:00 +000092 int l_count;
93 long long int num;
94 unsigned long long int unum;
Soby Mathewb79af932014-06-12 17:23:58 +010095 char *str;
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +000096 char padc = 0; /* Padding character */
97 int padn; /* Number of characters to pad */
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +010098 int count = 0; /* Number of printed characters */
Soby Mathewb79af932014-06-12 17:23:58 +010099
Soby Mathewb79af932014-06-12 17:23:58 +0100100 while (*fmt) {
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000101 l_count = 0;
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +0000102 padn = 0;
Soby Mathewb79af932014-06-12 17:23:58 +0100103
104 if (*fmt == '%') {
105 fmt++;
106 /* Check the format specifier */
107loop:
108 switch (*fmt) {
109 case 'i': /* Fall through to next one */
110 case 'd':
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000111 num = get_num_va_args(args, l_count);
Soby Mathewb79af932014-06-12 17:23:58 +0100112 if (num < 0) {
113 putchar('-');
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000114 unum = (unsigned long long int)-num;
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +0000115 padn--;
Soby Mathewb79af932014-06-12 17:23:58 +0100116 } else
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000117 unum = (unsigned long long int)num;
Soby Mathewb79af932014-06-12 17:23:58 +0100118
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100119 count += unsigned_num_print(unum, 10,
120 padc, padn);
Soby Mathewb79af932014-06-12 17:23:58 +0100121 break;
122 case 's':
123 str = va_arg(args, char *);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100124 count += tf_string_print(str);
Soby Mathewb79af932014-06-12 17:23:58 +0100125 break;
Antonio Nino Diazf0dd0612016-02-02 12:03:38 +0000126 case 'p':
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000127 unum = (uintptr_t)va_arg(args, void *);
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +0000128 if (unum) {
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100129 count += tf_string_print("0x");
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +0000130 padn -= 2;
131 }
Antonio Nino Diazf0dd0612016-02-02 12:03:38 +0000132
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100133 count += unsigned_num_print(unum, 16,
134 padc, padn);
Antonio Nino Diazf0dd0612016-02-02 12:03:38 +0000135 break;
Soby Mathewb79af932014-06-12 17:23:58 +0100136 case 'x':
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000137 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100138 count += unsigned_num_print(unum, 16,
139 padc, padn);
Soby Mathewb79af932014-06-12 17:23:58 +0100140 break;
Scott Brandenbda77012016-03-23 13:37:33 -0700141 case 'z':
142 if (sizeof(size_t) == 8)
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000143 l_count = 2;
144
Scott Brandenbda77012016-03-23 13:37:33 -0700145 fmt++;
146 goto loop;
Soby Mathewb79af932014-06-12 17:23:58 +0100147 case 'l':
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000148 l_count++;
Soby Mathewb79af932014-06-12 17:23:58 +0100149 fmt++;
150 goto loop;
151 case 'u':
Soby Mathewf2f5a7b2016-03-22 17:38:00 +0000152 unum = get_unum_va_args(args, l_count);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100153 count += unsigned_num_print(unum, 10,
154 padc, padn);
Soby Mathewb79af932014-06-12 17:23:58 +0100155 break;
Antonio Nino Diaz84816dc2017-12-15 10:36:20 +0000156 case '0':
157 padc = '0';
158 padn = 0;
159 fmt++;
160
161 while (1) {
162 char ch = *fmt;
163 if (ch < '0' || ch > '9') {
164 goto loop;
165 }
166 padn = (padn * 10) + (ch - '0');
167 fmt++;
168 }
Soby Mathewb79af932014-06-12 17:23:58 +0100169 default:
170 /* Exit on any other format specifier */
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100171 return -1;
Soby Mathewb79af932014-06-12 17:23:58 +0100172 }
173 fmt++;
174 continue;
175 }
176 putchar(*fmt++);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100177 count++;
Soby Mathewb79af932014-06-12 17:23:58 +0100178 }
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100179
180 return count;
Soby Mathew2d7e8282017-09-04 11:45:52 +0100181}
182
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100183int tf_printf(const char *fmt, ...)
Soby Mathew2d7e8282017-09-04 11:45:52 +0100184{
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100185 int count;
Soby Mathew2d7e8282017-09-04 11:45:52 +0100186 va_list va;
187
188 va_start(va, fmt);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100189 count = tf_vprintf(fmt, va);
Soby Mathew2d7e8282017-09-04 11:45:52 +0100190 va_end(va);
Antonio Nino Diazcb6dbfe2018-08-15 16:52:32 +0100191
192 return count;
Soby Mathewb79af932014-06-12 17:23:58 +0100193}