/* * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include static void unsigned_dec_print(char **s, size_t n, size_t *chars_printed, unsigned int unum) { /* Enough for a 32-bit unsigned decimal integer (4294967295). */ unsigned char num_buf[10]; int i = 0, rem; do { rem = unum % 10; num_buf[i++] = '0' + rem; } while (unum /= 10); while (--i >= 0) { if (*chars_printed < n) *(*s)++ = num_buf[i]; (*chars_printed)++; } } /******************************************************************* * Reduced snprintf to be used for Trusted firmware. * The following type specifiers are supported: * * %d or %i - signed decimal format * %u - unsigned decimal format * * The function panics on all other formats specifiers. * * It returns the number of characters that would be written if the * buffer was big enough. If it returns a value lower than n, the * whole string has been written. *******************************************************************/ int tf_snprintf(char *s, size_t n, const char *fmt, ...) { va_list args; int num; unsigned int unum; size_t chars_printed = 0; if (n == 1) { /* Buffer is too small to actually write anything else. */ *s = '\0'; n = 0; } else if (n >= 2) { /* Reserve space for the terminator character. */ n--; } va_start(args, fmt); while (*fmt) { if (*fmt == '%') { fmt++; /* Check the format specifier. */ switch (*fmt) { case 'i': case 'd': num = va_arg(args, int); if (num < 0) { if (chars_printed < n) *s++ = '-'; chars_printed++; unum = (unsigned int)-num; } else { unum = (unsigned int)num; } unsigned_dec_print(&s, n, &chars_printed, unum); break; case 'u': unum = va_arg(args, unsigned int); unsigned_dec_print(&s, n, &chars_printed, unum); break; default: /* Panic on any other format specifier. */ ERROR("tf_snprintf: specifier with ASCII code '%d' not supported.", *fmt); plat_panic_handler(); } fmt++; continue; } if (chars_printed < n) *s++ = *fmt; fmt++; chars_printed++; } va_end(args); if (n > 0) *s = '\0'; return chars_printed; }