xref: /illumos-gate/usr/src/uts/common/sys/hexdump.h (revision 80b758da23abee3ef0e550f533aada9ce3b1b01f)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2024 Oxide Computer Company
14  */
15 
16 #ifndef _HEXDUMP_H_
17 #define	_HEXDUMP_H_
18 
19 /*
20  * Header file for the generic hexdump implementation in
21  * common/hexdump/hexdump.c
22  */
23 
24 #include <sys/types.h>
25 
26 #ifndef _KERNEL
27 #include <stdio.h>
28 #endif
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 typedef enum {
35 	/*
36 	 * Include a header row showing byte positions.
37 	 */
38 	HDF_HEADER		= 1 << 0,
39 	/*
40 	 * Include the address of the first byte for each row at the left.
41 	 */
42 	HDF_ADDRESS		= 1 << 1,
43 	/*
44 	 * Include an ASCII table at the right hand side with unprintable bytes
45 	 * displayed as '.'.
46 	 */
47 	HDF_ASCII		= 1 << 2,
48 	/*
49 	 * If the data is not naturally aligned to the paragraph size, start
50 	 * the table from an aligned address and indicate where the data starts
51 	 * with a marker in the table header (if enabled). Missing data are
52 	 * shown with space characters.
53 	 */
54 	HDF_ALIGN		= 1 << 3,
55 	/*
56 	 * Suppress duplicate lines in the output, replacing them with a single
57 	 * "*".
58 	 */
59 	HDF_DEDUP		= 1 << 4,
60 	/*
61 	 * When laying out byte columns, use two spaces instead of one. This
62 	 * results in the data being more spread out and easier to read in some
63 	 * circumstances.
64 	 */
65 	HDF_DOUBLESPACE		= 1 << 5,
66 } hexdump_flag_t;
67 
68 /*
69  * Most consumers of the hexdump routines should use this default set of flags
70  * so we have consistent output across the gate.
71  */
72 #define	HDF_DEFAULT	(HDF_HEADER | HDF_ADDRESS | HDF_ASCII)
73 
74 /*
75  * Consumers of this code should treat this as an opaque type and initialise it
76  * with a call to hexdump_init(). It is defined here so that it can be placed
77  * on the stack which is particularly useful during early boot, before the kmem
78  * system is ready.
79  */
80 typedef struct {
81 	uint64_t	h_addr;		/* display address */
82 	uint8_t		h_addrwidth;	/* Minimum address width */
83 	uint8_t		h_width;	/* bytes per row */
84 	uint8_t		h_grouping;	/* display bytes in groups of.. */
85 	uint8_t		h_indent;	/* Left indent */
86 	uint8_t		h_marker;	/* marker offset */
87 	uint8_t		*h_buf;		/* optional pre-allocated buffer... */
88 	size_t		h_buflen;	/* ...and its size */
89 } hexdump_t;
90 
91 /*
92  * Initialise and finalise a hexdump_t.
93  */
94 extern void hexdump_init(hexdump_t *);
95 extern void hexdump_fini(hexdump_t *);
96 
97 /*
98  * Set the start address that corresponds to the provided data. This is used to
99  * display addresses in conjunction with the HDF_ADDRESS option.
100  */
101 extern void hexdump_set_addr(hexdump_t *, uint64_t);
102 
103 /*
104  * Set a minimum width, in characters, for the addresses shown in conjunction
105  * with the HDF_ADDRESS option. The default behaviour is to calculate the width
106  * required to show all addresses and use that for all rows.
107  */
108 extern void hexdump_set_addrwidth(hexdump_t *, uint8_t);
109 
110 /*
111  * Select the number of bytes per line. The default is 16.
112  */
113 extern void hexdump_set_width(hexdump_t *, uint8_t);
114 
115 /*
116  * Group bytes together. The default grouping is 1 which results in each byte
117  * being displayed surrounded by space. As a readability improvement an extra
118  * space is added after every 8 bytes when using a grouping of 1.
119  */
120 extern void hexdump_set_grouping(hexdump_t *, uint8_t);
121 
122 /*
123  * Set a number of spaces that should precede each row as an indent.
124  */
125 extern void hexdump_set_indent(hexdump_t *, uint8_t);
126 
127 /*
128  * Set a marker in the header for the start of interesting data. This will only
129  * be displayed if the header is enabled with the HDF_HEADER option, and if the
130  * marker value is less than the configured row width.
131  */
132 extern void hexdump_set_marker(hexdump_t *, uint8_t);
133 
134 /*
135  * Provide a scratch space working buffer. This is necessary in early boot,
136  * before kmem is ready.
137  */
138 extern void hexdump_set_buf(hexdump_t *, uint8_t *, size_t);
139 
140 /*
141  * The hexdump() function that does the work. It takes the following arguments:
142  *
143  *	const uint8_t *addr	- a pointer to the data to be dumped
144  *	size_t len		- the length of the data
145  *	hexdump_flag_t flags	- flags as per the definitions above
146  *	hexdump_cb_f callback	- fucntion called for each table row
147  *	void *callback_arg	- pointer passed to callback function
148  *
149  * More customisation can be achieved by using hexdumph() which takes an
150  * additional hexdump_t *.
151  */
152 typedef int (*hexdump_cb_f)(void *, uint64_t, const char *, size_t);
153 extern int hexdump(const uint8_t *, size_t, hexdump_flag_t,
154     hexdump_cb_f, void *);
155 
156 /*
157  * A version that takes a hexdump_t allowing for more customisation.
158  */
159 extern int hexdumph(hexdump_t *, const uint8_t *, size_t, hexdump_flag_t,
160     hexdump_cb_f, void *);
161 
162 #ifndef _KERNEL
163 /*
164  * Convenience wrappers in non-kernel context that output each table row to
165  * the provided FILE *.
166  */
167 extern int hexdump_file(const uint8_t *, size_t, hexdump_flag_t, FILE *);
168 extern int hexdump_fileh(hexdump_t *, const uint8_t *, size_t, hexdump_flag_t,
169     FILE *);
170 #endif /* _KERNEL */
171 
172 #ifdef __cplusplus
173 }
174 #endif
175 
176 #endif /* _HEXDUMP_H_ */
177