blob: 1afb05be0c68afb34d32342240f9e45c1391a68c [file] [log] [blame]
Mingyang Sunc6b458b2019-12-19 15:07:34 +08001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <stdarg.h>
9#include <stddef.h>
10#include <stdint.h>
11#include "log/tfm_log_raw.h"
12#include "uart_stdout.h"
13
14#define PRINT_BUFF_SIZE 32
15#define NUM_BUFF_SIZE 12
16
17struct formatted_buffer_t {
18 size_t pos;
19 uint8_t buf[PRINT_BUFF_SIZE];
20};
21
22const char hex_digits_lo[] = {'0', '1', '2', '3', '4', '5', '6', '7',
23 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
24const char hex_digits_up[] = {'0', '1', '2', '3', '4', '5', '6', '7',
25 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
26
27static void _tfm_flush_formatted_buffer(struct formatted_buffer_t *pb,
28 uint8_t data)
29{
30 pb->buf[pb->pos++] = data;
31 if (pb->pos >= PRINT_BUFF_SIZE) {
32 pb->pos = 0;
33 /* uart flush and print here. */
34 stdio_output_string(pb->buf, PRINT_BUFF_SIZE);
35 }
36}
37
38static int _tfm_string_output(struct formatted_buffer_t *pb,
39 const char *str)
40{
41 int count = 0;
42
43 while (*str) {
44 _tfm_flush_formatted_buffer(pb, *str++);
45 count++;
46 }
47
48 return count;
49}
50
51static int _tfm_dec_num_output(struct formatted_buffer_t *pb,
52 int32_t num, uint8_t sign)
53{
54 int count = 0;
55 uint8_t num_buff[NUM_BUFF_SIZE] = {0};
56 uint32_t number = (uint32_t)num;
57 uint32_t k = 0;
58
59 if (sign == 'd' && num < 0) {
60 _tfm_flush_formatted_buffer(pb, '-');
61 count++;
62 number = -num;
63 }
64
65 do {
66 num_buff[k++] = '0' + number % 10;
67 number /= 10;
68 } while (number);
69
70 while (k) {
71 _tfm_flush_formatted_buffer(pb, num_buff[--k]);
72 count++;
73 }
74
75 return count;
76}
77
78static int _tfm_hex_num_output(struct formatted_buffer_t *pb, uint32_t num,
79 const char *hex_digits)
80{
81 int count = 0;
82 uint8_t num_buff[NUM_BUFF_SIZE] = {0};
83 uint32_t k = 0;
84
85 do {
86 num_buff[k++] = hex_digits[num & 0x0f];
87 num >>= 4;
88 } while (num);
89
90 while (k) {
91 _tfm_flush_formatted_buffer(pb, num_buff[--k]);
92 count++;
93 }
94
95 return count;
96}
97
98static int _tfm_log_vprintf(const char *fmt, va_list ap)
99{
100 int count = 0;
101 struct formatted_buffer_t outputbuf;
102
103 outputbuf.pos = 0;
104
105 while (*fmt) {
106 if (*fmt == '%') {
107 switch (*(++fmt)) {
108 case 'd':
109 case 'i':
110 count += _tfm_dec_num_output(&outputbuf,
111 va_arg(ap, int32_t), 'd');
112 break;
113 case 'u':
114 count += _tfm_dec_num_output(&outputbuf,
115 va_arg(ap, int32_t), 'u');
116 break;
117 case 'x':
118 count += _tfm_hex_num_output(&outputbuf, va_arg(ap, uint32_t),
119 hex_digits_lo);
120 break;
121 case 'X':
122 count += _tfm_hex_num_output(&outputbuf, va_arg(ap, uint32_t),
123 hex_digits_up);
124 break;
125 case 'p':
126 count += _tfm_string_output(&outputbuf, "0x");
127 count += _tfm_hex_num_output(&outputbuf, va_arg(ap, uint32_t),
128 hex_digits_lo);
129 break;
130 case 's':
131 count += _tfm_string_output(&outputbuf, va_arg(ap, char*));
132 break;
133 case 'c':
134 _tfm_flush_formatted_buffer(&outputbuf,
135 (uint8_t)va_arg(ap, int32_t));
136 count++;
137 break;
138 case '%':
139 _tfm_flush_formatted_buffer(&outputbuf, '%');
140 count++;
141 break;
142 default:
143 count += _tfm_string_output(&outputbuf, "[Unsupported Tag]");
144 continue;
145 }
146 fmt++;
147 } else {
148 _tfm_flush_formatted_buffer(&outputbuf, *fmt++);
149 count++;
150 }
151 }
152
153 /* End of printf, flush buf */
154 if (outputbuf.pos) {
155 count += stdio_output_string(outputbuf.buf, outputbuf.pos);
156 }
157
158 return count;
159}
160
161int tfm_log_printf(const char *fmt, ...)
162{
163 int count = 0;
164 va_list ap;
165
166 va_start(ap, fmt);
167 count = _tfm_log_vprintf(fmt, ap);
168 va_end(ap);
169
170 return count;
171}