1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_
8 #define ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_
9 
10 /* Query ID */
11 enum coredump_query_id {
12 	/*
13 	 * Returns error code from backend.
14 	 */
15 	COREDUMP_QUERY_GET_ERROR,
16 
17 	/*
18 	 * Check if there is a stored coredump from backend.
19 	 *
20 	 * Returns 1 if there is a stored coredump.
21 	 *         0 if none.
22 	 *         -ENOTSUP if this query is not supported.
23 	 *	   Otherwise, error code from backend.
24 	 */
25 	COREDUMP_QUERY_HAS_STORED_DUMP,
26 
27 	COREDUMP_QUERY_MAX
28 };
29 
30 /* Command ID */
31 enum coredump_cmd_id {
32 	/*
33 	 * Clear error code from backend.
34 	 *
35 	 * Returns 0 if successful, failed otherwise.
36 	 */
37 	COREDUMP_CMD_CLEAR_ERROR,
38 
39 	/*
40 	 * Verify that the stored coredump is valid.
41 	 *
42 	 * Returns 1 if valid.
43 	 *         0 if not valid or no stored coredump.
44 	 *         -ENOTSUP if this command is not supported.
45 	 *	   Otherwise, error code from backend.
46 	 */
47 	COREDUMP_CMD_VERIFY_STORED_DUMP,
48 
49 	/*
50 	 * Erase the stored coredump.
51 	 *
52 	 * Returns 0 if successful.
53 	 *         -ENOTSUP if this command is not supported.
54 	 *	   Otherwise, error code from backend.
55 	 */
56 	COREDUMP_CMD_ERASE_STORED_DUMP,
57 
58 	COREDUMP_CMD_MAX
59 };
60 
61 #ifdef CONFIG_DEBUG_COREDUMP
62 
63 #include <toolchain.h>
64 #include <arch/cpu.h>
65 #include <sys/byteorder.h>
66 
67 #define COREDUMP_HDR_VER		1
68 
69 #define	COREDUMP_ARCH_HDR_ID		'A'
70 
71 #define	COREDUMP_MEM_HDR_ID		'M'
72 #define COREDUMP_MEM_HDR_VER		1
73 
74 /* Target code */
75 enum coredump_tgt_code {
76 	COREDUMP_TGT_UNKNOWN = 0,
77 	COREDUMP_TGT_X86,
78 	COREDUMP_TGT_X86_64,
79 	COREDUMP_TGT_ARM_CORTEX_M,
80 };
81 
82 /* Coredump header */
83 struct coredump_hdr_t {
84 	/* 'Z', 'E' */
85 	char		id[2];
86 
87 	/* Header version */
88 	uint16_t	hdr_version;
89 
90 	/* Target code */
91 	uint16_t	tgt_code;
92 
93 	/* Pointer size in Log2 */
94 	uint8_t		ptr_size_bits;
95 
96 	uint8_t		flag;
97 
98 	/* Coredump Reason given */
99 	unsigned int	reason;
100 } __packed;
101 
102 /* Architecture-specific block header */
103 struct coredump_arch_hdr_t {
104 	/* COREDUMP_ARCH_HDR_ID */
105 	char		id;
106 
107 	/* Header version */
108 	uint16_t	hdr_version;
109 
110 	/* Number of bytes in this block (excluding header) */
111 	uint16_t	num_bytes;
112 } __packed;
113 
114 /* Memory block header */
115 struct coredump_mem_hdr_t {
116 	/* COREDUMP_MEM_HDR_ID */
117 	char		id;
118 
119 	/* Header version */
120 	uint16_t	hdr_version;
121 
122 	/* Address of start of memory region */
123 	uintptr_t	start;
124 
125 	/* Address of end of memory region */
126 	uintptr_t	end;
127 } __packed;
128 
129 typedef void (*coredump_backend_start_t)(void);
130 typedef void (*coredump_backend_end_t)(void);
131 typedef void (*coredump_backend_buffer_output_t)(uint8_t *buf, size_t buflen);
132 typedef int (*coredump_backend_query_t)(enum coredump_query_id query_id,
133 					void *arg);
134 typedef int (*coredump_backend_cmd_t)(enum coredump_cmd_id cmd_id,
135 				      void *arg);
136 
137 struct coredump_backend_api {
138 	/* Signal to backend of the start of coredump. */
139 	coredump_backend_start_t		start;
140 
141 	/* Signal to backend of the end of coredump. */
142 	coredump_backend_end_t		end;
143 
144 	/* Raw buffer output */
145 	coredump_backend_buffer_output_t	buffer_output;
146 
147 	/* Perform query on backend */
148 	coredump_backend_query_t		query;
149 
150 	/* Perform command on backend */
151 	coredump_backend_cmd_t			cmd;
152 };
153 
154 void coredump(unsigned int reason, const z_arch_esf_t *esf,
155 	      struct k_thread *thread);
156 void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr);
157 void coredump_buffer_output(uint8_t *buf, size_t buflen);
158 
159 int coredump_query(enum coredump_query_id query_id, void *arg);
160 int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg);
161 
162 #else
163 
coredump(unsigned int reason,const z_arch_esf_t * esf,struct k_thread * thread)164 void coredump(unsigned int reason, const z_arch_esf_t *esf,
165 	      struct k_thread *thread)
166 {
167 }
168 
coredump_memory_dump(uintptr_t start_addr,uintptr_t end_addr)169 void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr)
170 {
171 }
172 
coredump_buffer_output(uint8_t * buf,size_t buflen)173 void coredump_buffer_output(uint8_t *buf, size_t buflen)
174 {
175 }
176 
coredump_query(enum coredump_query_id query_id,void * arg)177 int coredump_query(enum coredump_query_id query_id, void *arg)
178 {
179 	return -ENOTSUP;
180 }
181 
coredump_cmd(enum coredump_cmd_id query_id,void * arg)182 int coredump_cmd(enum coredump_cmd_id query_id, void *arg)
183 {
184 	return -ENOTSUP;
185 }
186 
187 #endif /* CONFIG_DEBUG_COREDUMP */
188 
189 /**
190  * @defgroup coredump_apis Coredump APIs
191  * @brief Coredump APIs
192  * @{
193  */
194 
195 /**
196  * @fn void coredump(unsigned int reason, const z_arch_esf_t *esf, struct k_thread *thread);
197  * @brief Perform coredump.
198  *
199  * Normally, this is called inside z_fatal_error() to generate coredump
200  * when a fatal error is encountered. This can also be called on demand
201  * whenever a coredump is desired.
202  *
203  * @param reason Reason for the fatal error
204  * @param esf Exception context
205  * @param thread Thread information to dump
206  */
207 
208 /**
209  * @fn void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr);
210  * @brief Dump memory region
211  *
212  * @param start_addr Start address of memory region to be dumped
213  * @param end_addr End address of memory region to be dumped
214  */
215 
216 /**
217  * @fn int coredump_buffer_output(uint8_t *buf, size_t buflen);
218  * @brief Output the buffer via coredump
219  *
220  * This outputs the buffer of byte array to the coredump backend.
221  * For example, this can be called to output the coredump section
222  * containing registers, or a section for memory dump.
223  *
224  * @param buf Buffer to be send to coredump output
225  * @param buflen Buffer length
226  */
227 
228 /**
229  * @fn int coredump_query(enum coredump_query_id query_id, void *arg);
230  * @brief Perform query on coredump subsystem.
231  *
232  * Query the coredump subsystem for information, for example, if there is
233  * an error.
234  *
235  * @param[in] query_id Query ID
236  * @param[in,out] arg Pointer to argument for exchanging information
237  * @return Depends on the query
238  */
239 
240 /**
241  * @fn int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg);
242  * @brief Perform command on coredump subsystem.
243  *
244  * Perform certain on coredump subsystem, for example, output the stored
245  * coredump via logging.
246  *
247  * @param[in] cmd_id Command ID
248  * @param[in,out] arg Pointer to argument for exchanging information
249  * @return Depends on the command
250  */
251 
252 /**
253  * @}
254  */
255 
256 #endif /* ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_ */
257