1 /* 2 * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <arch.h> 7 #include <arch_helpers.h> 8 #include <assert.h> 9 #include <debug.h> 10 #include <limits.h> 11 #include <stdarg.h> 12 #include <stdint.h> 13 14 /*********************************************************** 15 * The tf_printf implementation for all BL stages 16 ***********************************************************/ 17 18 #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))) 21 22 #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))) 25 26 void tf_string_print(const char *str) 27 { 28 assert(str); 29 30 while (*str) 31 putchar(*str++); 32 } 33 34 static void unsigned_num_print(unsigned long long int unum, unsigned int radix) 35 { 36 /* Just need enough space to store 64 bit decimal integer */ 37 unsigned char num_buf[20]; 38 int i = 0, rem; 39 40 do { 41 rem = unum % radix; 42 if (rem < 0xa) 43 num_buf[i++] = '0' + rem; 44 else 45 num_buf[i++] = 'a' + (rem - 0xa); 46 } while (unum /= radix); 47 48 while (--i >= 0) 49 putchar(num_buf[i]); 50 } 51 52 /******************************************************************* 53 * Reduced format print for Trusted firmware. 54 * The following type specifiers are supported by this print 55 * %x - hexadecimal format 56 * %s - string format 57 * %d or %i - signed decimal format 58 * %u - unsigned decimal format 59 * %p - pointer format 60 * 61 * The following length specifiers are supported by this print 62 * %l - long int (64-bit on AArch64) 63 * %ll - long long int (64-bit on AArch64) 64 * %z - size_t sized integer formats (64 bit on AArch64) 65 * 66 * The print exits on all other formats specifiers other than valid 67 * combinations of the above specifiers. 68 *******************************************************************/ 69 void tf_vprintf(const char *fmt, va_list args) 70 { 71 int l_count; 72 long long int num; 73 unsigned long long int unum; 74 char *str; 75 76 while (*fmt) { 77 l_count = 0; 78 79 if (*fmt == '%') { 80 fmt++; 81 /* Check the format specifier */ 82 loop: 83 switch (*fmt) { 84 case 'i': /* Fall through to next one */ 85 case 'd': 86 num = get_num_va_args(args, l_count); 87 if (num < 0) { 88 putchar('-'); 89 unum = (unsigned long long int)-num; 90 } else 91 unum = (unsigned long long int)num; 92 93 unsigned_num_print(unum, 10); 94 break; 95 case 's': 96 str = va_arg(args, char *); 97 tf_string_print(str); 98 break; 99 case 'p': 100 unum = (uintptr_t)va_arg(args, void *); 101 if (unum) 102 tf_string_print("0x"); 103 104 unsigned_num_print(unum, 16); 105 break; 106 case 'x': 107 unum = get_unum_va_args(args, l_count); 108 unsigned_num_print(unum, 16); 109 break; 110 case 'z': 111 if (sizeof(size_t) == 8) 112 l_count = 2; 113 114 fmt++; 115 goto loop; 116 case 'l': 117 l_count++; 118 fmt++; 119 goto loop; 120 case 'u': 121 unum = get_unum_va_args(args, l_count); 122 unsigned_num_print(unum, 10); 123 break; 124 default: 125 /* Exit on any other format specifier */ 126 return; 127 } 128 fmt++; 129 continue; 130 } 131 putchar(*fmt++); 132 } 133 } 134 135 void tf_printf(const char *fmt, ...) 136 { 137 va_list va; 138 139 va_start(va, fmt); 140 tf_vprintf(fmt, va); 141 va_end(va); 142 } 143