1
2
3
4
5
6#include <linux/types.h>
7#include <linux/ctype.h>
8#include <linux/errno.h>
9#include <linux/kernel.h>
10#include <linux/minmax.h>
11#include <linux/export.h>
12#include <asm/unaligned.h>
13
14const char hex_asc[] = "0123456789abcdef";
15EXPORT_SYMBOL(hex_asc);
16const char hex_asc_upper[] = "0123456789ABCDEF";
17EXPORT_SYMBOL(hex_asc_upper);
18
19
20
21
22
23
24
25
26int hex_to_bin(char ch)
27{
28 if ((ch >= '0') && (ch <= '9'))
29 return ch - '0';
30 ch = tolower(ch);
31 if ((ch >= 'a') && (ch <= 'f'))
32 return ch - 'a' + 10;
33 return -1;
34}
35EXPORT_SYMBOL(hex_to_bin);
36
37
38
39
40
41
42
43
44
45int hex2bin(u8 *dst, const char *src, size_t count)
46{
47 while (count--) {
48 int hi = hex_to_bin(*src++);
49 int lo = hex_to_bin(*src++);
50
51 if ((hi < 0) || (lo < 0))
52 return -EINVAL;
53
54 *dst++ = (hi << 4) | lo;
55 }
56 return 0;
57}
58EXPORT_SYMBOL(hex2bin);
59
60
61
62
63
64
65
66char *bin2hex(char *dst, const void *src, size_t count)
67{
68 const unsigned char *_src = src;
69
70 while (count--)
71 dst = hex_byte_pack(dst, *_src++);
72 return dst;
73}
74EXPORT_SYMBOL(bin2hex);
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
107 char *linebuf, size_t linebuflen, bool ascii)
108{
109 const u8 *ptr = buf;
110 int ngroups;
111 u8 ch;
112 int j, lx = 0;
113 int ascii_column;
114 int ret;
115
116 if (rowsize != 16 && rowsize != 32)
117 rowsize = 16;
118
119 if (len > rowsize)
120 len = rowsize;
121 if (!is_power_of_2(groupsize) || groupsize > 8)
122 groupsize = 1;
123 if ((len % groupsize) != 0)
124 groupsize = 1;
125
126 ngroups = len / groupsize;
127 ascii_column = rowsize * 2 + rowsize / groupsize + 1;
128
129 if (!linebuflen)
130 goto overflow1;
131
132 if (!len)
133 goto nil;
134
135 if (groupsize == 8) {
136 const u64 *ptr8 = buf;
137
138 for (j = 0; j < ngroups; j++) {
139 ret = snprintf(linebuf + lx, linebuflen - lx,
140 "%s%16.16llx", j ? " " : "",
141 get_unaligned(ptr8 + j));
142 if (ret >= linebuflen - lx)
143 goto overflow1;
144 lx += ret;
145 }
146 } else if (groupsize == 4) {
147 const u32 *ptr4 = buf;
148
149 for (j = 0; j < ngroups; j++) {
150 ret = snprintf(linebuf + lx, linebuflen - lx,
151 "%s%8.8x", j ? " " : "",
152 get_unaligned(ptr4 + j));
153 if (ret >= linebuflen - lx)
154 goto overflow1;
155 lx += ret;
156 }
157 } else if (groupsize == 2) {
158 const u16 *ptr2 = buf;
159
160 for (j = 0; j < ngroups; j++) {
161 ret = snprintf(linebuf + lx, linebuflen - lx,
162 "%s%4.4x", j ? " " : "",
163 get_unaligned(ptr2 + j));
164 if (ret >= linebuflen - lx)
165 goto overflow1;
166 lx += ret;
167 }
168 } else {
169 for (j = 0; j < len; j++) {
170 if (linebuflen < lx + 2)
171 goto overflow2;
172 ch = ptr[j];
173 linebuf[lx++] = hex_asc_hi(ch);
174 if (linebuflen < lx + 2)
175 goto overflow2;
176 linebuf[lx++] = hex_asc_lo(ch);
177 if (linebuflen < lx + 2)
178 goto overflow2;
179 linebuf[lx++] = ' ';
180 }
181 if (j)
182 lx--;
183 }
184 if (!ascii)
185 goto nil;
186
187 while (lx < ascii_column) {
188 if (linebuflen < lx + 2)
189 goto overflow2;
190 linebuf[lx++] = ' ';
191 }
192 for (j = 0; j < len; j++) {
193 if (linebuflen < lx + 2)
194 goto overflow2;
195 ch = ptr[j];
196 linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
197 }
198nil:
199 linebuf[lx] = '\0';
200 return lx;
201overflow2:
202 linebuf[lx++] = '\0';
203overflow1:
204 return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
205}
206EXPORT_SYMBOL(hex_dump_to_buffer);
207
208#ifdef CONFIG_PRINTK
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
241 int rowsize, int groupsize,
242 const void *buf, size_t len, bool ascii)
243{
244 const u8 *ptr = buf;
245 int i, linelen, remaining = len;
246 unsigned char linebuf[32 * 3 + 2 + 32 + 1];
247
248 if (rowsize != 16 && rowsize != 32)
249 rowsize = 16;
250
251 for (i = 0; i < len; i += rowsize) {
252 linelen = min(remaining, rowsize);
253 remaining -= rowsize;
254
255 hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
256 linebuf, sizeof(linebuf), ascii);
257
258 switch (prefix_type) {
259 case DUMP_PREFIX_ADDRESS:
260 printk("%s%s%p: %s\n",
261 level, prefix_str, ptr + i, linebuf);
262 break;
263 case DUMP_PREFIX_OFFSET:
264 printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
265 break;
266 default:
267 printk("%s%s%s\n", level, prefix_str, linebuf);
268 break;
269 }
270 }
271}
272EXPORT_SYMBOL(print_hex_dump);
273
274#endif
275