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