1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5 #include <stdarg.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <unistd.h>
9
10 #include "debug_api.h"
11
12 #define MIN(x,y) (((x)<(y))?(x):(y))
13
14 #if DEBUG_LAST_WORD_ENABLE
15 #ifdef CONFIG_VFS_LSOPEN
16 static void debug_paniclog_to_file(void);
17 #endif
18 static int panic_header_init(debug_panic_info_head_t *panic_header);
19 static int panic_header_show(debug_panic_info_head_t *panic_header);
20 static int panic_header_set(debug_panic_info_head_t *panic_header);
21 static int panic_header_get(debug_panic_info_head_t *panic_header);
22 static int panic_log_set(uint8_t *info, uint32_t len);
23 static int panic_log_get(uint8_t *info_buffer, uint32_t len);
24 static void panic_log_clean(void);
25
clear_silent_reboot_flag(void)26 __attribute__((weak)) int clear_silent_reboot_flag(void)
27 {
28 return 0;
29 }
30
set_silent_reboot_flag(void)31 __attribute__((weak)) int set_silent_reboot_flag(void)
32 {
33 return 0;
34 }
35
k_dcache_clean(uint32_t addr,uint32_t len)36 __attribute__((weak)) void k_dcache_clean(uint32_t addr, uint32_t len)
37 {
38 return;
39 }
40
41 /* set ram attributes for some mcu*/
alios_debug_lastword_init_hook()42 __attribute__((weak)) void alios_debug_lastword_init_hook()
43 {
44 return;
45 }
46
47 #define HEADER_START_ADDR (DEBUG_LASTWORD_RAM_ADDR)
48 #define LOG_START_ADDR (DEBUG_LASTWORD_RAM_ADDR + sizeof(debug_panic_info_head_t))
49 #define LOG_REGION_LEN (DEBUG_LASTWORD_REGION_LEN - sizeof(debug_panic_info_head_t))
50 #define LOG_END_ADDR (DEBUG_LASTWORD_RAM_ADDR + DEBUG_LASTWORD_REGION_LEN)
51 #define CRC_CALC_LEN (uint32_t)(&(((debug_panic_info_head_t *)0)->crc16))
52
53 static debug_panic_info_head_t panic_header_buffer;
54
55 #define POLY 0x1021
56
crc16_calc(uint8_t * addr,uint32_t num,uint16_t crc)57 uint16_t crc16_calc(uint8_t *addr, uint32_t num, uint16_t crc)
58 {
59 int i;
60 for (; num > 0; num--) {
61 crc = crc ^ (*addr++ << 8);
62 for (i = 0; i < 8; i++) {
63 if (crc & 0x8000) {
64 crc = (crc << 1) ^ POLY;
65 } else {
66 crc <<= 1;
67 }
68 }
69 crc &= 0xFFFF;
70 }
71 return (crc);
72 }
73
debug_lastword_init(void)74 void debug_lastword_init(void)
75 {
76 printf("init lastword\r\n");
77
78 #ifdef CONFIG_VFS_LSOPEN
79 mkdir(DEBUG_LOG_DIR_NAME, 0777);
80 #endif
81
82 panic_header_get(&panic_header_buffer);
83
84 if (crc16_calc((uint8_t *)&panic_header_buffer, CRC_CALC_LEN, 0xffff) != panic_header_buffer.crc16) {
85 panic_header_init(&panic_header_buffer);
86 panic_header_set(&panic_header_buffer);
87 panic_log_clean();
88 printf("[Error] lastword: init crc fail!\r\n");
89 return;
90 }
91
92 printf("lastword: CRC check is OK\r\n");
93 #ifdef CONFIG_VFS_LSOPEN
94 if (panic_header_buffer.log_magic == DEBUG_PANIC_LOG_MAGIC) {
95 char path[64];
96 int fd = -1;
97 printf("lastword: try to read lastword to file!\r\n");
98 /* open /data/smartbox_abort as a flag for panic */
99 memset(path, 0, sizeof(path));
100 snprintf(path, sizeof(path) - 1, "/data/smartbox_abort");
101 fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
102 if (fd < 0) {
103 printf("open panic flag file fail\r\n");
104 } else {
105 printf("open panic flag file fd %d\r\n", fd);
106 close(fd);
107 }
108 printf("store panic log to file\r\n");
109 debug_paniclog_to_file();
110 }
111 #endif
112 panic_log_clean();
113 panic_header_buffer.log_magic = 0;
114
115 if (panic_header_buffer.header_magic != DEBUG_PANIC_HEADER_MAGIC) {
116 panic_header_init(&panic_header_buffer);
117 } else {
118 panic_header_buffer.reboot_sum_count++;
119 }
120
121 panic_header_show(&panic_header_buffer);
122 panic_header_set(&panic_header_buffer);
123 clear_silent_reboot_flag();
124
125 alios_debug_lastword_init_hook();
126 }
127
debug_reboot_reason_update(unsigned int reason)128 void debug_reboot_reason_update(unsigned int reason)
129 {
130 int ret = -1;
131 static int reason_id_update_flag = 0;
132
133 panic_header_get(&panic_header_buffer);
134
135 if (reason_id_update_flag == 0) {
136 panic_header_buffer.reboot_reason_id++;
137 reason_id_update_flag = 1;
138 }
139
140 panic_header_buffer.reboot_reason = reason;
141
142 if ((DEBUG_REBOOT_REASON_PANIC == reason) || (DEBUG_REBOOT_REASON_FATAL_ERR == reason)) {
143 set_silent_reboot_flag();
144
145 panic_header_buffer.runtime_before_painc[panic_header_buffer.runtime_record_id] = krhino_ticks_to_ms(
146 krhino_sys_tick_get());
147 panic_header_buffer.runtime_record_id++;
148 if (panic_header_buffer.runtime_record_id >= RUNTIME_COUNT) {
149 panic_header_buffer.runtime_record_id = 0;
150 }
151 panic_header_buffer.panic_count++;
152 }
153
154 ret = panic_header_set(&panic_header_buffer);
155 if (ret) {
156 print_str("reboot reason set err\n");
157 }
158 }
159
debug_reboot_reason_get()160 unsigned int debug_reboot_reason_get()
161 {
162 panic_header_get(&panic_header_buffer);
163
164 if (panic_header_buffer.header_magic != DEBUG_PANIC_HEADER_MAGIC) {
165 panic_header_init(&panic_header_buffer);
166 panic_header_set(&panic_header_buffer);
167 return DEFAULT_REBOOT_REASON;
168 }
169
170 if (panic_header_buffer.reboot_sum_count > panic_header_buffer.reboot_reason_id) {
171 panic_header_buffer.reboot_reason_id = panic_header_buffer.reboot_sum_count;
172 panic_header_buffer.reboot_reason = DEBUG_REBOOT_UNKNOWN_REASON;
173 panic_header_set(&panic_header_buffer);
174 return DEBUG_REBOOT_UNKNOWN_REASON;
175 }
176
177 return panic_header_buffer.reboot_reason;
178 }
179
debug_get_painc_runtime(int panic_count,int * real_panic_count)180 int64_t debug_get_painc_runtime(int panic_count, int *real_panic_count)
181 {
182 int32_t idx = 0, count = 0;
183 int64_t duration = 0;
184
185 panic_header_get(&panic_header_buffer);
186
187 if (panic_header_buffer.header_magic != DEBUG_PANIC_HEADER_MAGIC) {
188 panic_header_init(&panic_header_buffer);
189 panic_header_set(&panic_header_buffer);
190 *real_panic_count = 0;
191 return -1;
192 }
193
194 if (panic_header_buffer.panic_count == 0) {
195 *real_panic_count = 0;
196 return -1;
197 }
198
199 if (panic_count > RUNTIME_COUNT) {
200 printf("panic count is larger than %d\r\n", RUNTIME_COUNT);
201 }
202
203 idx = panic_header_buffer.runtime_record_id;
204
205 for (count = 0; count < RUNTIME_COUNT; count++) {
206 if (count >= panic_count) {
207 break;
208 }
209
210 idx--;
211 if (idx < 0) {
212 idx = RUNTIME_COUNT - 1;
213 }
214 if (panic_header_buffer.runtime_before_painc[idx] != -1) {
215 duration += panic_header_buffer.runtime_before_painc[idx];
216 } else {
217 break;
218 }
219 }
220
221 *real_panic_count = count;
222 return duration;
223 }
224
225 #ifdef CONFIG_VFS_LSOPEN
debug_paniclog_to_file(void)226 static void debug_paniclog_to_file(void)
227 {
228 int i = 0, index = 0;
229 int fd = -1, indexfile_fd = -1;
230 char path[64];
231 char info_buffer[128], index_buffer[10];
232 int len;
233
234 if (panic_header_buffer.log_magic != DEBUG_PANIC_LOG_MAGIC) {
235 return;
236 }
237
238 for (i = 0; i < DEBUG_LOG_FILE_NUM; i++) {
239 memset(path, 0, sizeof(path));
240 snprintf(path, sizeof(path), "%s_%02d", DEBUG_LOG_FILE_NAME, i);
241 /* if file not exit, create it, and output debug info to it */
242 if (access(path, R_OK) != 0) {
243 fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
244 if (fd >= 0) {
245 break;
246 }
247 }
248 }
249
250 if (i == DEBUG_LOG_FILE_NUM) {
251 if (access(DEBUG_LOG_FILE_INDEX_NAME, R_OK) != 0) {
252 indexfile_fd = open(DEBUG_LOG_FILE_INDEX_NAME, O_CREAT | O_WRONLY | O_TRUNC, 0666);
253 index = 0;
254 } else {
255 indexfile_fd = open(DEBUG_LOG_FILE_INDEX_NAME, O_CREAT | O_RDWR, 0666);
256 read(indexfile_fd, index_buffer, sizeof(index_buffer));
257 sscanf(index_buffer, "%02d", &index);
258
259 if ((index < 0) || (index >= DEBUG_LOG_FILE_NUM)) {
260 index = 0;
261 } else {
262 index++;
263 if (index >= DEBUG_LOG_FILE_NUM) {
264 index = 0;
265 }
266 }
267 lseek(indexfile_fd, SEEK_SET, 0);
268 }
269
270 if (indexfile_fd >= 0) {
271 memset(index_buffer, 0, sizeof(index_buffer));
272 len = snprintf(index_buffer, sizeof(index_buffer), "%02d", index);
273 write(indexfile_fd, index_buffer, len);
274 close(indexfile_fd);
275 }
276
277 memset(path, 0, sizeof(path));
278 snprintf(path, sizeof(path), "%s_%02d", DEBUG_LOG_FILE_NAME, index);
279 fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
280 }
281
282 if (fd < 0) {
283 printf("open file %s error, %s, %d\r\n", path, __FILE__, __LINE__);
284 return;
285 }
286
287 while (1) {
288 len = sizeof(info_buffer);
289 len = panic_log_get((uint8_t *)info_buffer, len);
290 if (len <= 0) {
291 break;
292 }
293 len = write(fd, info_buffer, len);
294 if (len < 0) {
295 printf("write file %s error, %s, %d\r\n", path, __FILE__, __LINE__);
296 //break;
297 }
298 }
299
300 close(fd);
301 fd = -1;
302
303 return;
304 }
305 #endif
306
panic_header_init(debug_panic_info_head_t * panic_header)307 static int panic_header_init(debug_panic_info_head_t *panic_header)
308 {
309 uint32_t i;
310 panic_header->header_magic = DEBUG_PANIC_HEADER_MAGIC;
311 panic_header->log_magic = 0;
312 panic_header->reboot_reason = DEFAULT_REBOOT_REASON;
313 panic_header->reboot_sum_count = 0;
314 panic_header->reboot_reason_id = 0;
315 panic_header->panic_count = 0;
316 panic_header->runtime_record_id = 0;
317
318 for (i = 0; i < RUNTIME_COUNT; i++) {
319 panic_header->runtime_before_painc[i] = -1;
320 }
321 return 0;
322 }
323
panic_header_show(debug_panic_info_head_t * panic_header)324 static int panic_header_show(debug_panic_info_head_t *panic_header)
325 {
326 printf("===========show panic header===========\r\n");
327 printf("panic header reboot reason %d\r\n", (int)panic_header->reboot_reason);
328 printf("panic header reboot sum count %d\r\n", (int)panic_header->reboot_sum_count);
329 printf("panic header reboot reason reason id %d\r\n", (int)panic_header->reboot_reason_id);
330 printf("panic header panic count %d\r\n", (int)panic_header->panic_count);
331 printf("===========end===========\r\n");
332 return 0;
333 }
334
panic_header_set(debug_panic_info_head_t * panic_header)335 static int panic_header_set(debug_panic_info_head_t *panic_header)
336 {
337 if (panic_header == NULL) {
338 return -1;
339 }
340
341 debug_panic_info_head_t *log_header = (debug_panic_info_head_t *)HEADER_START_ADDR;
342 /* calculate the crc */
343 panic_header->crc16 = crc16_calc((uint8_t *)panic_header, CRC_CALC_LEN, 0xffff);
344
345 memcpy(log_header, panic_header, sizeof(debug_panic_info_head_t));
346 k_dcache_clean((uintptr_t)log_header, sizeof(debug_panic_info_head_t));
347
348 return 0;
349 }
350
panic_header_get(debug_panic_info_head_t * panic_header)351 static int panic_header_get(debug_panic_info_head_t *panic_header)
352 {
353 if (panic_header == NULL) {
354 return -1;
355 }
356
357 debug_panic_info_head_t *log_header = (debug_panic_info_head_t *)HEADER_START_ADDR;
358 memcpy(panic_header, log_header, sizeof(debug_panic_info_head_t));
359
360 return 0;
361 }
362
panic_log_set(uint8_t * info,uint32_t len)363 static int panic_log_set(uint8_t *info, uint32_t len)
364 {
365 if ((info == NULL) || (len == 0)) {
366 return -1;
367 }
368
369 static uint8_t *log_ram_addr_cur = (uint8_t *)LOG_START_ADDR;
370
371 if ((uintptr_t)(len + log_ram_addr_cur) <= (uintptr_t)LOG_END_ADDR) {
372 memcpy(log_ram_addr_cur, info, len);
373 k_dcache_clean((uintptr_t)log_ram_addr_cur, len);
374 log_ram_addr_cur += len;
375 return 0;
376 }
377
378 return -1;
379 }
380
panic_log_get(uint8_t * info_buffer,uint32_t len)381 static int panic_log_get(uint8_t *info_buffer, uint32_t len)
382 {
383 if (info_buffer == NULL) {
384 return -1;
385 }
386
387 static uint8_t *log_ram_addr_cur = (uint8_t *)LOG_START_ADDR;
388 int32_t len_tmp;
389
390 if (log_ram_addr_cur >= (uint8_t *)LOG_END_ADDR) {
391 return -1;
392 }
393
394 len = MIN(len, (uint8_t *)LOG_END_ADDR - log_ram_addr_cur);
395 memcpy(info_buffer, log_ram_addr_cur, len);
396 log_ram_addr_cur += len;
397
398 len_tmp = len - 1;
399 while (len_tmp >= 0) {
400 if (info_buffer[len_tmp] != 0) {
401 break;
402 }
403 len--;
404 len_tmp--;
405 }
406
407 return len;
408 }
409
panic_log_clean(void)410 static void panic_log_clean(void)
411 {
412 static uint8_t *log_ram_addr_cur = (uint8_t *)LOG_START_ADDR;
413 memset(log_ram_addr_cur, 0, LOG_REGION_LEN);
414 }
415
print_str(const char * fmt,...)416 int print_str(const char *fmt, ...)
417 {
418 int ret = -1;
419 char strbuf[400];
420
421 va_list args;
422
423 va_start(args, fmt);
424 ret = vsnprintf((char *)strbuf, sizeof(strbuf) - 1, fmt, args);
425 va_end(args);
426
427 if (ret > 0) {
428 panic_log_set((uint8_t *)strbuf, ret);
429 if (panic_header_buffer.log_magic != DEBUG_PANIC_LOG_MAGIC) {
430 panic_header_buffer.log_magic = DEBUG_PANIC_LOG_MAGIC;
431 panic_header_set(&panic_header_buffer);
432 }
433 }
434
435 return ret;
436 }
437
vprint_str(const char * fmt,va_list ap)438 int vprint_str(const char *fmt, va_list ap)
439 {
440 int ret = -1;
441 char strbuf[400];
442
443 ret = vsnprintf((char *)strbuf, sizeof(strbuf) - 1, fmt, ap);
444
445 if (ret > 0) {
446 panic_log_set((uint8_t *)strbuf, ret);
447 if (panic_header_buffer.log_magic != DEBUG_PANIC_LOG_MAGIC) {
448 panic_header_buffer.log_magic = DEBUG_PANIC_LOG_MAGIC;
449 panic_header_set(&panic_header_buffer);
450 }
451 }
452
453 return ret;
454 }
455
456 #endif
457
458