Home | History | Annotate | Download | only in common
      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