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 #include <stddef.h>
11 #include <stdint.h>
12 #include <sys/types.h>
13
14
15 /**
16 * @file
17 *
18 * @defgroup coredump_apis Coredump APIs
19 * @ingroup os_services
20 * @brief Coredump APIs
21 * @{
22 */
23
24
25 /** Query ID */
26 enum coredump_query_id {
27 /**
28 * Returns error code from backend.
29 */
30 COREDUMP_QUERY_GET_ERROR,
31
32 /**
33 * Check if there is a stored coredump from backend.
34 *
35 * Returns:
36 * - 1 if there is a stored coredump, 0 if none.
37 * - -ENOTSUP if this query is not supported.
38 * - Otherwise, error code from backend.
39 */
40 COREDUMP_QUERY_HAS_STORED_DUMP,
41
42 /**
43 * Returns:
44 * - coredump raw size from backend, 0 if none.
45 * - -ENOTSUP if this query is not supported.
46 * - Otherwise, error code from backend.
47 */
48 COREDUMP_QUERY_GET_STORED_DUMP_SIZE,
49
50 /**
51 * Max value for query ID.
52 */
53 COREDUMP_QUERY_MAX
54 };
55
56 /** Command ID */
57 enum coredump_cmd_id {
58 /**
59 * Clear error code from backend.
60 *
61 * Returns 0 if successful, failed otherwise.
62 */
63 COREDUMP_CMD_CLEAR_ERROR,
64
65 /**
66 * Verify that the stored coredump is valid.
67 *
68 * Returns:
69 * - 1 if valid.
70 * - 0 if not valid or no stored coredump.
71 * - -ENOTSUP if this command is not supported.
72 * - Otherwise, error code from backend.
73 */
74 COREDUMP_CMD_VERIFY_STORED_DUMP,
75
76 /**
77 * Erase the stored coredump.
78 *
79 * Returns:
80 * - 0 if successful.
81 * - -ENOTSUP if this command is not supported.
82 * - Otherwise, error code from backend.
83 */
84 COREDUMP_CMD_ERASE_STORED_DUMP,
85
86 /**
87 * Copy the raw stored coredump.
88 *
89 * Returns:
90 * - copied size if successful
91 * - 0 if stored coredump is not found
92 * - -ENOTSUP if this command is not supported.
93 * - Otherwise, error code from backend.
94 */
95 COREDUMP_CMD_COPY_STORED_DUMP,
96
97 /**
98 * Invalidate the stored coredump. This is faster than
99 * erasing the whole partition.
100 *
101 * Returns:
102 * - 0 if successful.
103 * - -ENOTSUP if this command is not supported.
104 * - Otherwise, error code from backend.
105 */
106 COREDUMP_CMD_INVALIDATE_STORED_DUMP,
107
108 /**
109 * Max value for command ID.
110 */
111 COREDUMP_CMD_MAX
112 };
113
114 /** Coredump copy command (@ref COREDUMP_CMD_COPY_STORED_DUMP) argument definition */
115 struct coredump_cmd_copy_arg {
116 /** Copy offset */
117 off_t offset;
118
119 /** Copy destination buffer */
120 uint8_t *buffer;
121
122 /** Copy length */
123 size_t length;
124 };
125
126 #ifdef CONFIG_DEBUG_COREDUMP
127
128 #include <zephyr/toolchain.h>
129 #include <zephyr/arch/cpu.h>
130 #include <zephyr/sys/byteorder.h>
131
132 #define COREDUMP_HDR_VER 1
133
134 #define COREDUMP_ARCH_HDR_ID 'A'
135
136 #define COREDUMP_MEM_HDR_ID 'M'
137 #define COREDUMP_MEM_HDR_VER 1
138
139 /* Target code */
140 enum coredump_tgt_code {
141 COREDUMP_TGT_UNKNOWN = 0,
142 COREDUMP_TGT_X86,
143 COREDUMP_TGT_X86_64,
144 COREDUMP_TGT_ARM_CORTEX_M,
145 COREDUMP_TGT_RISC_V,
146 COREDUMP_TGT_XTENSA,
147 COREDUMP_TGT_ARM64,
148 };
149
150 /* Coredump header */
151 struct coredump_hdr_t {
152 /* 'Z', 'E' */
153 char id[2];
154
155 /* Header version */
156 uint16_t hdr_version;
157
158 /* Target code */
159 uint16_t tgt_code;
160
161 /* Pointer size in Log2 */
162 uint8_t ptr_size_bits;
163
164 uint8_t flag;
165
166 /* Coredump Reason given */
167 unsigned int reason;
168 } __packed;
169
170 /* Architecture-specific block header */
171 struct coredump_arch_hdr_t {
172 /* COREDUMP_ARCH_HDR_ID */
173 char id;
174
175 /* Header version */
176 uint16_t hdr_version;
177
178 /* Number of bytes in this block (excluding header) */
179 uint16_t num_bytes;
180 } __packed;
181
182 /* Memory block header */
183 struct coredump_mem_hdr_t {
184 /* COREDUMP_MEM_HDR_ID */
185 char id;
186
187 /* Header version */
188 uint16_t hdr_version;
189
190 /* Address of start of memory region */
191 uintptr_t start;
192
193 /* Address of end of memory region */
194 uintptr_t end;
195 } __packed;
196
197 typedef void (*coredump_backend_start_t)(void);
198 typedef void (*coredump_backend_end_t)(void);
199 typedef void (*coredump_backend_buffer_output_t)(uint8_t *buf, size_t buflen);
200 typedef int (*coredump_backend_query_t)(enum coredump_query_id query_id,
201 void *arg);
202 typedef int (*coredump_backend_cmd_t)(enum coredump_cmd_id cmd_id,
203 void *arg);
204
205 struct coredump_backend_api {
206 /* Signal to backend of the start of coredump. */
207 coredump_backend_start_t start;
208
209 /* Signal to backend of the end of coredump. */
210 coredump_backend_end_t end;
211
212 /* Raw buffer output */
213 coredump_backend_buffer_output_t buffer_output;
214
215 /* Perform query on backend */
216 coredump_backend_query_t query;
217
218 /* Perform command on backend */
219 coredump_backend_cmd_t cmd;
220 };
221
222 void coredump(unsigned int reason, const z_arch_esf_t *esf,
223 struct k_thread *thread);
224 void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr);
225 void coredump_buffer_output(uint8_t *buf, size_t buflen);
226
227 int coredump_query(enum coredump_query_id query_id, void *arg);
228 int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg);
229
230 #else
231
coredump(unsigned int reason,const z_arch_esf_t * esf,struct k_thread * thread)232 void coredump(unsigned int reason, const z_arch_esf_t *esf,
233 struct k_thread *thread)
234 {
235 ARG_UNUSED(reason);
236 ARG_UNUSED(esf);
237 ARG_UNUSED(thread);
238 }
239
coredump_memory_dump(uintptr_t start_addr,uintptr_t end_addr)240 void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr)
241 {
242 ARG_UNUSED(start_addr);
243 ARG_UNUSED(end_addr);
244 }
245
coredump_buffer_output(uint8_t * buf,size_t buflen)246 void coredump_buffer_output(uint8_t *buf, size_t buflen)
247 {
248 ARG_UNUSED(buf);
249 ARG_UNUSED(buflen);
250 }
251
coredump_query(enum coredump_query_id query_id,void * arg)252 int coredump_query(enum coredump_query_id query_id, void *arg)
253 {
254 ARG_UNUSED(query_id);
255 ARG_UNUSED(arg);
256 return -ENOTSUP;
257 }
258
coredump_cmd(enum coredump_cmd_id query_id,void * arg)259 int coredump_cmd(enum coredump_cmd_id query_id, void *arg)
260 {
261 ARG_UNUSED(query_id);
262 ARG_UNUSED(arg);
263 return -ENOTSUP;
264 }
265
266 #endif /* CONFIG_DEBUG_COREDUMP */
267
268 /**
269 * @fn void coredump(unsigned int reason, const z_arch_esf_t *esf, struct k_thread *thread);
270 * @brief Perform coredump.
271 *
272 * Normally, this is called inside z_fatal_error() to generate coredump
273 * when a fatal error is encountered. This can also be called on demand
274 * whenever a coredump is desired.
275 *
276 * @param reason Reason for the fatal error
277 * @param esf Exception context
278 * @param thread Thread information to dump
279 */
280
281 /**
282 * @fn void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr);
283 * @brief Dump memory region
284 *
285 * @param start_addr Start address of memory region to be dumped
286 * @param end_addr End address of memory region to be dumped
287 */
288
289 /**
290 * @fn int coredump_buffer_output(uint8_t *buf, size_t buflen);
291 * @brief Output the buffer via coredump
292 *
293 * This outputs the buffer of byte array to the coredump backend.
294 * For example, this can be called to output the coredump section
295 * containing registers, or a section for memory dump.
296 *
297 * @param buf Buffer to be send to coredump output
298 * @param buflen Buffer length
299 */
300
301 /**
302 * @fn int coredump_query(enum coredump_query_id query_id, void *arg);
303 * @brief Perform query on coredump subsystem.
304 *
305 * Query the coredump subsystem for information, for example, if there is
306 * an error.
307 *
308 * @param[in] query_id Query ID
309 * @param[in,out] arg Pointer to argument for exchanging information
310 * @return Depends on the query
311 */
312
313 /**
314 * @fn int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg);
315 * @brief Perform command on coredump subsystem.
316 *
317 * Perform command on coredump subsystem, for example, output the stored
318 * coredump via logging.
319 *
320 * @param[in] cmd_id Command ID
321 * @param[in,out] arg Pointer to argument for exchanging information
322 * @return Depends on the command
323 */
324
325 /**
326 * @}
327 */
328
329 #endif /* ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_ */
330