1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include "tee_log.h"
13 #include <stdio.h>
14 #include <stdarg.h>
15 #include <securec.h>
16 #include "tee_mem_mgmt_api.h"
17 #include "tee_init.h"
18 #include "timer_export.h"
19 #include "tee_tag.h"
20 #include "teecall.h"
21
22 enum log_source_type {
23 COMMON_SOURCE = 0,
24 DRIVER_SOURCE = 1,
25 MAX_SOURCE = 2,
26 };
27
28 /*
29 * HEAD
30 * 32 Bytes New head of record 4 Bytes 0x5A5AA5A5
31 * UUID 16 Bytes TEE_UUID
32 * effect length of data 2 Bytes real length of characters
33 * total length of data 2 Bytes total length, multiple of 16 Bytes
34 * operation mark of log file 1 Byte 0x00000001 means have written to log file
35 * reserve segment 7 Bytes default is 0
36 * data segment description of log terminated with \0, total length is multiple of 16
37 * using 0 to pad the data length
38 */
39 #define LOG_ITEM_MAGIC 0x5A5A
40 #define LOG_ITEM_LEN_ALIGN 64
41 #define LOG_ITEM_MAX_LEN 384
42
43 enum {
44 LOG_OPER_NEW,
45 LOG_OPER_READ,
46 };
47 #define LOG_ITEM_NEVER_USED_SIZE 32
48 #define LOG_ITEM_UUID_SIZE 16
49 #define LOG_ITEM_RESERVED_SIZE 1
50 /* 64 Bytes of head + logs of user */
51 typedef struct {
52 uint8_t never_used[LOG_ITEM_NEVER_USED_SIZE];
53
54 uint16_t magic;
55 uint16_t reserved0;
56
57 uint32_t serial_no;
58
59 uint16_t log_real_len; /* real length of log */
60 uint16_t log_buffer_len; /* length of log buffer multiple of 32 bytes */
61
62 uint8_t uuid[LOG_ITEM_UUID_SIZE];
63 uint8_t log_source_type;
64 uint8_t reserved[LOG_ITEM_RESERVED_SIZE];
65 uint8_t log_level;
66 uint8_t new_line; /* it is \n,which makes it easier to read log from bbox.bin */
67
68 uint8_t log_buffer[0];
69 } log_item_t;
70
tee_log_init(const TEE_UUID * uuid)71 void tee_log_init(const TEE_UUID *uuid)
72 {
73 (void)uuid;
74 }
75
tee_log_exit(void)76 void tee_log_exit(void)
77 {
78 }
79
is_ta_uuid(const uint8_t * uuid,size_t len)80 static bool is_ta_uuid(const uint8_t *uuid, size_t len)
81 {
82 uint32_t i;
83 const uint8_t *p = uuid;
84
85 for (i = 0; i < len; i++) {
86 if (p[i] != 0)
87 return true;
88 }
89
90 return false;
91 }
92
fill_uuid(log_item_t * m_logitem,bool * is_ta)93 static void fill_uuid(log_item_t *m_logitem, bool *is_ta)
94 {
95 TEE_UUID uuid = { 0 };
96
97 *is_ta = false;
98
99 void *current_uuid = get_current_uuid();
100 if (current_uuid == NULL) {
101 printf("current uuid is NULL\n");
102 current_uuid = &uuid;
103 }
104
105 if (memmove_s((void *)m_logitem->uuid, sizeof(m_logitem->uuid), current_uuid, sizeof(TEE_UUID)) != EOK) {
106 printf("memmove_s uuid ret is not EOK\n");
107 current_uuid = &uuid;
108 return;
109 }
110 *is_ta = is_ta_uuid(m_logitem->uuid, sizeof(m_logitem->uuid));
111 }
112
113 #ifdef CONFIG_KLOG_TIMESTAMP
fill_tee_log_buffer(char * log_buffer,size_t log_max_len,const char * log_tag)114 static int32_t fill_tee_log_buffer(char *log_buffer, size_t log_max_len, const char *log_tag)
115 {
116 int32_t count;
117 uint16_t thread_tag = get_log_thread_tag() & 0xffff;
118 if (thread_tag != 0)
119 count = snprintf_s(log_buffer, log_max_len, log_max_len - 1,
120 " [%s-%u] ", log_tag, thread_tag);
121 else
122 count = snprintf_s(log_buffer, log_max_len, log_max_len - 1,
123 " [%s] ", log_tag);
124
125 return count;
126 }
127 #else
fill_tee_log_buffer(char * log_buffer,size_t log_max_len,const char * log_tag)128 static int32_t fill_tee_log_buffer(char *log_buffer, size_t log_max_len, const char *log_tag)
129 {
130 int32_t count;
131 tee_date_time_kernel time = { 0 };
132 uint16_t thread_tag = get_log_thread_tag() & 0xffff;
133
134 get_sys_date_time(&time);
135
136 if (thread_tag != 0)
137 count = snprintf_s(log_buffer, log_max_len, log_max_len - 1,
138 " %02d/%02d %02d:%02d:%02d.%03d [%s-%u] ", time.month, time.day, time.hour,
139 time.min, time.seconds, time.millis, log_tag, thread_tag);
140 else
141 count = snprintf_s(log_buffer, log_max_len, log_max_len - 1,
142 " %02d/%02d %02d:%02d:%02d.%03d [%s] ", time.month, time.day, time.hour, time.min,
143 time.seconds, time.millis, log_tag);
144
145 return count;
146 }
147 #endif
148
fill_logitem(log_item_t * m_logitem,size_t m_logmaxlen,int count,int real_len)149 static void fill_logitem(log_item_t *m_logitem, size_t m_logmaxlen, int count, int real_len)
150 {
151 m_logitem->log_real_len = (uint16_t)(real_len + count);
152
153 if (m_logitem->log_real_len + 1 >= m_logmaxlen) {
154 printf("print too long %d\n", (int)m_logitem->log_real_len);
155 return;
156 }
157
158 while (m_logitem->log_real_len > 1 && m_logitem->log_buffer[m_logitem->log_real_len - 1] == (uint8_t)' ') {
159 m_logitem->log_buffer[m_logitem->log_real_len - 1] = 0;
160 m_logitem->log_real_len--;
161 }
162
163 if (m_logitem->log_buffer[m_logitem->log_real_len - 1] != (uint8_t)'\n')
164 m_logitem->log_buffer[m_logitem->log_real_len++] = (uint8_t)'\n';
165
166 m_logitem->log_buffer_len =
167 (m_logitem->log_real_len + LOG_ITEM_LEN_ALIGN - 1) / LOG_ITEM_LEN_ALIGN * LOG_ITEM_LEN_ALIGN;
168
169 m_logitem->magic = LOG_ITEM_MAGIC;
170
171 /* append in the rdr memory */
172 if (debug_rdr_logitem((char *)m_logitem, sizeof(log_item_t) + m_logitem->log_buffer_len) != 0)
173 printf("append rdr logitem debug_rdr_logitem ret is not successful\n");
174 }
175 #define LOG_RESERVED_SIZE 1
tee_print_helper(const char * log_tag,enum log_source_type source_type,LOG_LEVEL log_level,const char * fmt,va_list arglist)176 static void tee_print_helper(const char *log_tag, enum log_source_type source_type, LOG_LEVEL log_level,
177 const char *fmt, va_list arglist)
178 {
179 int32_t count;
180 int32_t real_len;
181 uint8_t log_buffer[LOG_ITEM_MAX_LEN] = { 0 };
182 log_item_t *log_item = NULL;
183 size_t log_max_len;
184 bool is_ta = false;
185
186 if (fmt == NULL)
187 return;
188
189 log_item = (log_item_t *)log_buffer;
190 log_max_len = LOG_ITEM_MAX_LEN - sizeof(log_item_t);
191
192 log_item->log_level = log_level;
193 fill_uuid(log_item, &is_ta);
194
195 /* ta not support this source category */
196 if (!is_ta && (source_type > COMMON_SOURCE && source_type < MAX_SOURCE)) {
197 log_item->log_source_type = get_log_source(log_tag);
198
199 char *final_tag = get_log_tag(log_tag, g_debug_prefix);
200 final_tag = ((final_tag == NULL) ? ((char *)log_tag) : final_tag);
201 count = fill_tee_log_buffer((char *)log_item->log_buffer, log_max_len, final_tag);
202
203 if (final_tag != log_tag) {
204 TEE_Free(final_tag);
205 final_tag = NULL;
206 }
207 } else {
208 count = fill_tee_log_buffer((char *)log_item->log_buffer, log_max_len, log_tag);
209 }
210 if (count < 0)
211 return;
212
213 real_len = vsnprintf_s((char *)log_item->log_buffer + count, (size_t)(log_max_len - count - LOG_RESERVED_SIZE),
214 (size_t)(log_max_len - count - LOG_RESERVED_SIZE - 1), fmt, arglist);
215 /* vsnprintf_s returns -1 directly when it fails */
216 if (real_len == -1) {
217 printf("vsnprintf_s failed: format string is \"%s\"\n", fmt);
218 return;
219 }
220
221 fill_logitem(log_item, log_max_len, count, real_len);
222 }
223
tee_print(LOG_LEVEL log_level,const char * fmt,...)224 void __attribute__((weak)) tee_print(LOG_LEVEL log_level, const char *fmt, ...)
225 {
226 va_list ap;
227
228 if (fmt == NULL)
229 return;
230 va_start(ap, fmt);
231
232 tee_print_helper(g_debug_prefix, COMMON_SOURCE, log_level, fmt, ap);
233
234 va_end(ap);
235 }
236
tee_print_driver(LOG_LEVEL log_level,const char * log_tag,const char * fmt,...)237 void __attribute__((weak)) tee_print_driver(LOG_LEVEL log_level, const char *log_tag, const char *fmt, ...)
238 {
239 va_list ap;
240
241 if (log_tag == NULL || fmt == NULL)
242 return;
243 va_start(ap, fmt);
244
245 tee_print_helper(log_tag, DRIVER_SOURCE, log_level, fmt, ap);
246
247 va_end(ap);
248 }
249
uart_cprintf(const char * fmt,...)250 void uart_cprintf(const char *fmt, ...)
251 {
252 va_list ap;
253 if (fmt == NULL)
254 return;
255 va_start(ap, fmt);
256
257 tee_print_helper(g_debug_prefix, COMMON_SOURCE, LOG_LEVEL_INFO, fmt, ap);
258
259 va_end(ap);
260 }
uart_printf_func(const char * fmt,...)261 void uart_printf_func(const char *fmt, ...)
262 {
263 va_list ap;
264 if (fmt == NULL)
265 return;
266 va_start(ap, fmt);
267
268 tee_print_helper(g_debug_prefix, COMMON_SOURCE, LOG_LEVEL_INFO, fmt, ap);
269
270 va_end(ap);
271 }
272
tee_report(const char * domain,const char * event,HISYSEVENT_TYPE event_type,const char * fmt,...)273 void tee_report(const char *domain, const char *event, HISYSEVENT_TYPE event_type, const char *fmt, ...)
274 {
275 (void)domain;
276 (void)event;
277 (void)event_type;
278 (void)fmt;
279 }
280