xref: /illumos-gate/usr/src/uts/common/sys/hexdump.h (revision b7fe974ee38c5da0a9b74e243e9fa36eb1908998)
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_width;	/* bytes per row */
83 	uint8_t		h_grouping;	/* display bytes in groups of.. */
84 	uint8_t		h_indent;	/* Left indent */
85 	uint8_t		h_marker;	/* marker offset */
86 	uint8_t		*h_buf;		/* optional pre-allocated buffer... */
87 	size_t		h_buflen;	/* ...and its size */
88 } hexdump_t;
89 
90 /*
91  * Initialise and finalise a hexdump_t.
92  */
93 extern void hexdump_init(hexdump_t *);
94 extern void hexdump_fini(hexdump_t *);
95 
96 /*
97  * Set the start address that corresponds to the provided data. This is used to
98  * display addresses in conjunction with the HDF_ADDRESS option.
99  */
100 extern void hexdump_set_addr(hexdump_t *, uint64_t);
101 
102 /*
103  * Select the number of bytes per line. The default is 16.
104  */
105 extern void hexdump_set_width(hexdump_t *, uint8_t);
106 
107 /*
108  * Group bytes together. The default grouping is 1 which results in each byte
109  * being displayed surrounded by space. As a readability improvement an extra
110  * space is added after every 8 bytes when using a grouping of 1.
111  */
112 extern void hexdump_set_grouping(hexdump_t *, uint8_t);
113 
114 /*
115  * Set a number of spaces that should precede each row as an indent.
116  */
117 extern void hexdump_set_indent(hexdump_t *, uint8_t);
118 
119 /*
120  * Set a marker in the header for the start of interesting data. This will only
121  * be displayed if the header is enabled with the HDF_HEADER option, and if the
122  * marker value is less than the configured row width.
123  */
124 extern void hexdump_set_marker(hexdump_t *, uint8_t);
125 
126 /*
127  * Provide a scratch space working buffer. This is necessary in early boot,
128  * before kmem is ready.
129  */
130 extern void hexdump_set_buf(hexdump_t *, uint8_t *, size_t);
131 
132 /*
133  * The hexdump() function that does the work. It takes the following arguments:
134  *
135  *	const uint8_t *addr	- a pointer to the data to be dumped
136  *	size_t len		- the length of the data
137  *	hexdump_flag_t flags	- flags as per the definitions above
138  *	hexdump_cb_f callback	- fucntion called for each table row
139  *	void *callback_arg	- pointer passed to callback function
140  *
141  * More customisation can be achieved by using hexdumph() which takes an
142  * additional hexdump_t *.
143  */
144 typedef int (*hexdump_cb_f)(void *, uint64_t, const char *, size_t);
145 extern int hexdump(const uint8_t *, size_t, hexdump_flag_t,
146     hexdump_cb_f, void *);
147 
148 /*
149  * A version that takes a hexdump_t allowing for more customisation.
150  */
151 extern int hexdumph(hexdump_t *, const uint8_t *, size_t, hexdump_flag_t,
152     hexdump_cb_f, void *);
153 
154 #ifndef _KERNEL
155 /*
156  * Convenience wrappers in non-kernel context that output each table row to
157  * the provided FILE *.
158  */
159 extern int hexdump_file(const uint8_t *, size_t, hexdump_flag_t, FILE *);
160 extern int hexdump_fileh(hexdump_t *, const uint8_t *, size_t, hexdump_flag_t,
161     FILE *);
162 #endif /* _KERNEL */
163 
164 #ifdef __cplusplus
165 }
166 #endif
167 
168 #endif /* _HEXDUMP_H_ */
169