1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <zephyr/sys/util.h>
9 
10 #include <zephyr/debug/coredump.h>
11 #include "coredump_internal.h"
12 
13 #include <zephyr/logging/log.h>
14 #include <zephyr/logging/log_ctrl.h>
15 
16 LOG_MODULE_REGISTER(coredump, CONFIG_DEBUG_COREDUMP_LOG_LEVEL);
17 
18 /* Length of buffer of printable size */
19 #define LOG_BUF_SZ		64
20 
21 /* Length of buffer of printable size plus null character */
22 #define LOG_BUF_SZ_RAW		(LOG_BUF_SZ + 1)
23 
24 /* Log Buffer */
25 static char log_buf[LOG_BUF_SZ_RAW];
26 
27 static int error;
28 
coredump_logging_backend_start(void)29 static void coredump_logging_backend_start(void)
30 {
31 	/* Reset error */
32 	error = 0;
33 
34 	while (LOG_PROCESS()) {
35 		;
36 	}
37 
38 	LOG_PANIC();
39 	LOG_ERR(COREDUMP_PREFIX_STR COREDUMP_BEGIN_STR);
40 }
41 
coredump_logging_backend_end(void)42 static void coredump_logging_backend_end(void)
43 {
44 	if (error != 0) {
45 		LOG_ERR(COREDUMP_PREFIX_STR COREDUMP_ERROR_STR);
46 	}
47 
48 	LOG_ERR(COREDUMP_PREFIX_STR COREDUMP_END_STR);
49 }
50 
coredump_logging_backend_buffer_output(uint8_t * buf,size_t buflen)51 static void coredump_logging_backend_buffer_output(uint8_t *buf, size_t buflen)
52 {
53 	uint8_t log_ptr = 0;
54 	size_t remaining = buflen;
55 	size_t i = 0;
56 
57 	if ((buf == NULL) || (buflen == 0)) {
58 		error = -EINVAL;
59 		remaining = 0;
60 	}
61 
62 	while (remaining > 0) {
63 		if (hex2char(buf[i] >> 4, &log_buf[log_ptr]) < 0) {
64 			error = -EINVAL;
65 			break;
66 		}
67 		log_ptr++;
68 
69 		if (hex2char(buf[i] & 0xf, &log_buf[log_ptr]) < 0) {
70 			error = -EINVAL;
71 			break;
72 		}
73 		log_ptr++;
74 
75 		i++;
76 		remaining--;
77 
78 		if ((log_ptr >= LOG_BUF_SZ) || (remaining == 0)) {
79 			log_buf[log_ptr] = '\0';
80 			LOG_ERR(COREDUMP_PREFIX_STR "%s", log_buf);
81 			log_ptr = 0;
82 		}
83 	}
84 }
85 
coredump_logging_backend_query(enum coredump_query_id query_id,void * arg)86 static int coredump_logging_backend_query(enum coredump_query_id query_id,
87 					  void *arg)
88 {
89 	int ret;
90 
91 	switch (query_id) {
92 	case COREDUMP_QUERY_GET_ERROR:
93 		ret = error;
94 		break;
95 	default:
96 		ret = -ENOTSUP;
97 		break;
98 	}
99 
100 	return ret;
101 }
102 
coredump_logging_backend_cmd(enum coredump_cmd_id cmd_id,void * arg)103 static int coredump_logging_backend_cmd(enum coredump_cmd_id cmd_id,
104 					void *arg)
105 {
106 	int ret;
107 
108 	switch (cmd_id) {
109 	case COREDUMP_CMD_CLEAR_ERROR:
110 		ret = 0;
111 		error = 0;
112 		break;
113 	default:
114 		ret = -ENOTSUP;
115 		break;
116 	}
117 
118 	return ret;
119 }
120 
121 
122 struct coredump_backend_api coredump_backend_logging = {
123 	.start = coredump_logging_backend_start,
124 	.end = coredump_logging_backend_end,
125 	.buffer_output = coredump_logging_backend_buffer_output,
126 	.query = coredump_logging_backend_query,
127 	.cmd = coredump_logging_backend_cmd,
128 };
129