xref: /illumos-gate/usr/src/uts/common/sys/hexdump.h (revision 80b758da23abee3ef0e550f533aada9ce3b1b01f)
143379a28SAndy Fiddaman /*
243379a28SAndy Fiddaman  * This file and its contents are supplied under the terms of the
343379a28SAndy Fiddaman  * Common Development and Distribution License ("CDDL"), version 1.0.
443379a28SAndy Fiddaman  * You may only use this file in accordance with the terms of version
543379a28SAndy Fiddaman  * 1.0 of the CDDL.
643379a28SAndy Fiddaman  *
743379a28SAndy Fiddaman  * A full copy of the text of the CDDL should have accompanied this
843379a28SAndy Fiddaman  * source.  A copy of the CDDL is also available via the Internet at
943379a28SAndy Fiddaman  * http://www.illumos.org/license/CDDL.
1043379a28SAndy Fiddaman  */
1143379a28SAndy Fiddaman 
1243379a28SAndy Fiddaman /*
1343379a28SAndy Fiddaman  * Copyright 2024 Oxide Computer Company
1443379a28SAndy Fiddaman  */
1543379a28SAndy Fiddaman 
1643379a28SAndy Fiddaman #ifndef _HEXDUMP_H_
1743379a28SAndy Fiddaman #define	_HEXDUMP_H_
1843379a28SAndy Fiddaman 
1943379a28SAndy Fiddaman /*
2043379a28SAndy Fiddaman  * Header file for the generic hexdump implementation in
2143379a28SAndy Fiddaman  * common/hexdump/hexdump.c
2243379a28SAndy Fiddaman  */
2343379a28SAndy Fiddaman 
2443379a28SAndy Fiddaman #include <sys/types.h>
2543379a28SAndy Fiddaman 
2643379a28SAndy Fiddaman #ifndef _KERNEL
2743379a28SAndy Fiddaman #include <stdio.h>
2843379a28SAndy Fiddaman #endif
2943379a28SAndy Fiddaman 
3043379a28SAndy Fiddaman #ifdef __cplusplus
3143379a28SAndy Fiddaman extern "C" {
3243379a28SAndy Fiddaman #endif
3343379a28SAndy Fiddaman 
3443379a28SAndy Fiddaman typedef enum {
3543379a28SAndy Fiddaman 	/*
3643379a28SAndy Fiddaman 	 * Include a header row showing byte positions.
3743379a28SAndy Fiddaman 	 */
3843379a28SAndy Fiddaman 	HDF_HEADER		= 1 << 0,
3943379a28SAndy Fiddaman 	/*
4043379a28SAndy Fiddaman 	 * Include the address of the first byte for each row at the left.
4143379a28SAndy Fiddaman 	 */
4243379a28SAndy Fiddaman 	HDF_ADDRESS		= 1 << 1,
4343379a28SAndy Fiddaman 	/*
4443379a28SAndy Fiddaman 	 * Include an ASCII table at the right hand side with unprintable bytes
4543379a28SAndy Fiddaman 	 * displayed as '.'.
4643379a28SAndy Fiddaman 	 */
4743379a28SAndy Fiddaman 	HDF_ASCII		= 1 << 2,
4843379a28SAndy Fiddaman 	/*
4943379a28SAndy Fiddaman 	 * If the data is not naturally aligned to the paragraph size, start
5043379a28SAndy Fiddaman 	 * the table from an aligned address and indicate where the data starts
5143379a28SAndy Fiddaman 	 * with a marker in the table header (if enabled). Missing data are
5243379a28SAndy Fiddaman 	 * shown with space characters.
5343379a28SAndy Fiddaman 	 */
5443379a28SAndy Fiddaman 	HDF_ALIGN		= 1 << 3,
5543379a28SAndy Fiddaman 	/*
5643379a28SAndy Fiddaman 	 * Suppress duplicate lines in the output, replacing them with a single
5743379a28SAndy Fiddaman 	 * "*".
5843379a28SAndy Fiddaman 	 */
5943379a28SAndy Fiddaman 	HDF_DEDUP		= 1 << 4,
6043379a28SAndy Fiddaman 	/*
6143379a28SAndy Fiddaman 	 * When laying out byte columns, use two spaces instead of one. This
6243379a28SAndy Fiddaman 	 * results in the data being more spread out and easier to read in some
6343379a28SAndy Fiddaman 	 * circumstances.
6443379a28SAndy Fiddaman 	 */
6543379a28SAndy Fiddaman 	HDF_DOUBLESPACE		= 1 << 5,
6643379a28SAndy Fiddaman } hexdump_flag_t;
6743379a28SAndy Fiddaman 
6843379a28SAndy Fiddaman /*
6943379a28SAndy Fiddaman  * Most consumers of the hexdump routines should use this default set of flags
7043379a28SAndy Fiddaman  * so we have consistent output across the gate.
7143379a28SAndy Fiddaman  */
7243379a28SAndy Fiddaman #define	HDF_DEFAULT	(HDF_HEADER | HDF_ADDRESS | HDF_ASCII)
7343379a28SAndy Fiddaman 
7443379a28SAndy Fiddaman /*
7543379a28SAndy Fiddaman  * Consumers of this code should treat this as an opaque type and initialise it
7643379a28SAndy Fiddaman  * with a call to hexdump_init(). It is defined here so that it can be placed
7743379a28SAndy Fiddaman  * on the stack which is particularly useful during early boot, before the kmem
7843379a28SAndy Fiddaman  * system is ready.
7943379a28SAndy Fiddaman  */
8043379a28SAndy Fiddaman typedef struct {
8143379a28SAndy Fiddaman 	uint64_t	h_addr;		/* display address */
82*80b758daSAndy Fiddaman 	uint8_t		h_addrwidth;	/* Minimum address width */
8343379a28SAndy Fiddaman 	uint8_t		h_width;	/* bytes per row */
8443379a28SAndy Fiddaman 	uint8_t		h_grouping;	/* display bytes in groups of.. */
8543379a28SAndy Fiddaman 	uint8_t		h_indent;	/* Left indent */
8643379a28SAndy Fiddaman 	uint8_t		h_marker;	/* marker offset */
8743379a28SAndy Fiddaman 	uint8_t		*h_buf;		/* optional pre-allocated buffer... */
8843379a28SAndy Fiddaman 	size_t		h_buflen;	/* ...and its size */
8943379a28SAndy Fiddaman } hexdump_t;
9043379a28SAndy Fiddaman 
9143379a28SAndy Fiddaman /*
9243379a28SAndy Fiddaman  * Initialise and finalise a hexdump_t.
9343379a28SAndy Fiddaman  */
9443379a28SAndy Fiddaman extern void hexdump_init(hexdump_t *);
9543379a28SAndy Fiddaman extern void hexdump_fini(hexdump_t *);
9643379a28SAndy Fiddaman 
9743379a28SAndy Fiddaman /*
9843379a28SAndy Fiddaman  * Set the start address that corresponds to the provided data. This is used to
9943379a28SAndy Fiddaman  * display addresses in conjunction with the HDF_ADDRESS option.
10043379a28SAndy Fiddaman  */
10143379a28SAndy Fiddaman extern void hexdump_set_addr(hexdump_t *, uint64_t);
10243379a28SAndy Fiddaman 
10343379a28SAndy Fiddaman /*
104*80b758daSAndy Fiddaman  * Set a minimum width, in characters, for the addresses shown in conjunction
105*80b758daSAndy Fiddaman  * with the HDF_ADDRESS option. The default behaviour is to calculate the width
106*80b758daSAndy Fiddaman  * required to show all addresses and use that for all rows.
107*80b758daSAndy Fiddaman  */
108*80b758daSAndy Fiddaman extern void hexdump_set_addrwidth(hexdump_t *, uint8_t);
109*80b758daSAndy Fiddaman 
110*80b758daSAndy Fiddaman /*
11143379a28SAndy Fiddaman  * Select the number of bytes per line. The default is 16.
11243379a28SAndy Fiddaman  */
11343379a28SAndy Fiddaman extern void hexdump_set_width(hexdump_t *, uint8_t);
11443379a28SAndy Fiddaman 
11543379a28SAndy Fiddaman /*
11643379a28SAndy Fiddaman  * Group bytes together. The default grouping is 1 which results in each byte
11743379a28SAndy Fiddaman  * being displayed surrounded by space. As a readability improvement an extra
11843379a28SAndy Fiddaman  * space is added after every 8 bytes when using a grouping of 1.
11943379a28SAndy Fiddaman  */
12043379a28SAndy Fiddaman extern void hexdump_set_grouping(hexdump_t *, uint8_t);
12143379a28SAndy Fiddaman 
12243379a28SAndy Fiddaman /*
12343379a28SAndy Fiddaman  * Set a number of spaces that should precede each row as an indent.
12443379a28SAndy Fiddaman  */
12543379a28SAndy Fiddaman extern void hexdump_set_indent(hexdump_t *, uint8_t);
12643379a28SAndy Fiddaman 
12743379a28SAndy Fiddaman /*
12843379a28SAndy Fiddaman  * Set a marker in the header for the start of interesting data. This will only
12943379a28SAndy Fiddaman  * be displayed if the header is enabled with the HDF_HEADER option, and if the
13043379a28SAndy Fiddaman  * marker value is less than the configured row width.
13143379a28SAndy Fiddaman  */
13243379a28SAndy Fiddaman extern void hexdump_set_marker(hexdump_t *, uint8_t);
13343379a28SAndy Fiddaman 
13443379a28SAndy Fiddaman /*
13543379a28SAndy Fiddaman  * Provide a scratch space working buffer. This is necessary in early boot,
13643379a28SAndy Fiddaman  * before kmem is ready.
13743379a28SAndy Fiddaman  */
13843379a28SAndy Fiddaman extern void hexdump_set_buf(hexdump_t *, uint8_t *, size_t);
13943379a28SAndy Fiddaman 
14043379a28SAndy Fiddaman /*
14143379a28SAndy Fiddaman  * The hexdump() function that does the work. It takes the following arguments:
14243379a28SAndy Fiddaman  *
14343379a28SAndy Fiddaman  *	const uint8_t *addr	- a pointer to the data to be dumped
14443379a28SAndy Fiddaman  *	size_t len		- the length of the data
14543379a28SAndy Fiddaman  *	hexdump_flag_t flags	- flags as per the definitions above
14643379a28SAndy Fiddaman  *	hexdump_cb_f callback	- fucntion called for each table row
14743379a28SAndy Fiddaman  *	void *callback_arg	- pointer passed to callback function
14843379a28SAndy Fiddaman  *
14943379a28SAndy Fiddaman  * More customisation can be achieved by using hexdumph() which takes an
15043379a28SAndy Fiddaman  * additional hexdump_t *.
15143379a28SAndy Fiddaman  */
15243379a28SAndy Fiddaman typedef int (*hexdump_cb_f)(void *, uint64_t, const char *, size_t);
15343379a28SAndy Fiddaman extern int hexdump(const uint8_t *, size_t, hexdump_flag_t,
15443379a28SAndy Fiddaman     hexdump_cb_f, void *);
15543379a28SAndy Fiddaman 
15643379a28SAndy Fiddaman /*
15743379a28SAndy Fiddaman  * A version that takes a hexdump_t allowing for more customisation.
15843379a28SAndy Fiddaman  */
15943379a28SAndy Fiddaman extern int hexdumph(hexdump_t *, const uint8_t *, size_t, hexdump_flag_t,
16043379a28SAndy Fiddaman     hexdump_cb_f, void *);
16143379a28SAndy Fiddaman 
16243379a28SAndy Fiddaman #ifndef _KERNEL
16343379a28SAndy Fiddaman /*
16443379a28SAndy Fiddaman  * Convenience wrappers in non-kernel context that output each table row to
16543379a28SAndy Fiddaman  * the provided FILE *.
16643379a28SAndy Fiddaman  */
16743379a28SAndy Fiddaman extern int hexdump_file(const uint8_t *, size_t, hexdump_flag_t, FILE *);
16843379a28SAndy Fiddaman extern int hexdump_fileh(hexdump_t *, const uint8_t *, size_t, hexdump_flag_t,
16943379a28SAndy Fiddaman     FILE *);
17043379a28SAndy Fiddaman #endif /* _KERNEL */
17143379a28SAndy Fiddaman 
17243379a28SAndy Fiddaman #ifdef __cplusplus
17343379a28SAndy Fiddaman }
17443379a28SAndy Fiddaman #endif
17543379a28SAndy Fiddaman 
17643379a28SAndy Fiddaman #endif /* _HEXDUMP_H_ */
177