1 /* 2 * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 #include <debug.h> 31 #include <stdarg.h> 32 #include <stdint.h> 33 34 /*********************************************************** 35 * The tf_printf implementation for all BL stages 36 ***********************************************************/ 37 static void unsigned_num_print(unsigned long int unum, unsigned int radix) 38 { 39 /* Just need enough space to store 64 bit decimal integer */ 40 unsigned char num_buf[20]; 41 int i = 0 , rem; 42 43 do { 44 rem = unum % radix; 45 if (rem < 0xa) 46 num_buf[i++] = '0' + rem; 47 else 48 num_buf[i++] = 'a' + (rem - 0xa); 49 } while (unum /= radix); 50 51 while (--i >= 0) 52 putchar(num_buf[i]); 53 } 54 55 static void string_print(const char *str) 56 { 57 while (*str) 58 putchar(*str++); 59 } 60 61 /******************************************************************* 62 * Reduced format print for Trusted firmware. 63 * The following formats are supported by this print 64 * %x - 32 bit hexadecimal format 65 * %llx and %lx -64 bit hexadecimal format 66 * %s - string format 67 * %d or %i - signed 32 bit decimal format 68 * %u - unsigned 32 bit decimal format 69 * %ld and %lld - signed 64 bit decimal format 70 * %lu and %llu - unsigned 64 bit decimal format 71 * Exits on all other formats. 72 *******************************************************************/ 73 74 void tf_printf(const char *fmt, ...) 75 { 76 va_list args; 77 int bit64; 78 int64_t num; 79 uint64_t unum; 80 char *str; 81 82 va_start(args, fmt); 83 while (*fmt) { 84 bit64 = 0; 85 86 if (*fmt == '%') { 87 fmt++; 88 /* Check the format specifier */ 89 loop: 90 switch (*fmt) { 91 case 'i': /* Fall through to next one */ 92 case 'd': 93 if (bit64) 94 num = va_arg(args, int64_t); 95 else 96 num = va_arg(args, int32_t); 97 98 if (num < 0) { 99 putchar('-'); 100 unum = (unsigned long int)-num; 101 } else 102 unum = (unsigned long int)num; 103 104 unsigned_num_print(unum, 10); 105 break; 106 case 's': 107 str = va_arg(args, char *); 108 string_print(str); 109 break; 110 case 'x': 111 if (bit64) 112 unum = va_arg(args, uint64_t); 113 else 114 unum = va_arg(args, uint32_t); 115 116 unsigned_num_print(unum, 16); 117 break; 118 case 'l': 119 bit64 = 1; 120 fmt++; 121 goto loop; 122 case 'u': 123 if (bit64) 124 unum = va_arg(args, uint64_t); 125 else 126 unum = va_arg(args, uint32_t); 127 128 unsigned_num_print(unum, 10); 129 break; 130 default: 131 /* Exit on any other format specifier */ 132 goto exit; 133 } 134 fmt++; 135 continue; 136 } 137 putchar(*fmt++); 138 } 139 exit: 140 va_end(args); 141 } 142