1
2
3
4
5
6
7
8
9
10#include <linux/types.h>
11#include <linux/ctype.h>
12#include <linux/kernel.h>
13#include <linux/export.h>
14#include <asm/unaligned.h>
15
16const char hex_asc[] = "0123456789abcdef";
17EXPORT_SYMBOL(hex_asc);
18const char hex_asc_upper[] = "0123456789ABCDEF";
19EXPORT_SYMBOL(hex_asc_upper);
20
21
22
23
24
25
26
27
28int hex_to_bin(char ch)
29{
30 if ((ch >= '0') && (ch <= '9'))
31 return ch - '0';
32 ch = tolower(ch);
33 if ((ch >= 'a') && (ch <= 'f'))
34 return ch - 'a' + 10;
35 return -1;
36}
37EXPORT_SYMBOL(hex_to_bin);
38
39
40
41
42
43
44
45
46
47int hex2bin(u8 *dst, const char *src, size_t count)
48{
49 while (count--) {
50 int hi = hex_to_bin(*src++);
51 int lo = hex_to_bin(*src++);
52
53 if ((hi < 0) || (lo < 0))
54 return -1;
55
56 *dst++ = (hi << 4) | lo;
57 }
58 return 0;
59}
60EXPORT_SYMBOL(hex2bin);
61
62
63
64
65
66
67
68char *bin2hex(char *dst, const void *src, size_t count)
69{
70 const unsigned char *_src = src;
71
72 while (count--)
73 dst = hex_byte_pack(dst, *_src++);
74 return dst;
75}
76EXPORT_SYMBOL(bin2hex);
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
106
107
108int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
109 char *linebuf, size_t linebuflen, bool ascii)
110{
111 const u8 *ptr = buf;
112 int ngroups;
113 u8 ch;
114 int j, lx = 0;
115 int ascii_column;
116 int ret;
117
118 if (rowsize != 16 && rowsize != 32)
119 rowsize = 16;
120
121 if (len > rowsize)
122 len = rowsize;
123 if (!is_power_of_2(groupsize) || groupsize > 8)
124 groupsize = 1;
125 if ((len % groupsize) != 0)
126 groupsize = 1;
127
128 ngroups = len / groupsize;
129 ascii_column = rowsize * 2 + rowsize / groupsize + 1;
130
131 if (!linebuflen)
132 goto overflow1;
133
134 if (!len)
135 goto nil;
136
137 if (groupsize == 8) {
138 const u64 *ptr8 = buf;
139
140 for (j = 0; j < ngroups; j++) {
141 ret = snprintf(linebuf + lx, linebuflen - lx,
142 "%s%16.16llx", j ? " " : "",
143 get_unaligned(ptr8 + j));
144 if (ret >= linebuflen - lx)
145 goto overflow1;
146 lx += ret;
147 }
148 } else if (groupsize == 4) {
149 const u32 *ptr4 = buf;
150
151 for (j = 0; j < ngroups; j++) {
152 ret = snprintf(linebuf + lx, linebuflen - lx,
153 "%s%8.8x", j ? " " : "",
154 get_unaligned(ptr4 + j));
155 if (ret >= linebuflen - lx)
156 goto overflow1;
157 lx += ret;
158 }
159 } else if (groupsize == 2) {
160 const u16 *ptr2 = buf;
161
162 for (j = 0; j < ngroups; j++) {
163 ret = snprintf(linebuf + lx, linebuflen - lx,
164 "%s%4.4x", j ? " " : "",
165 get_unaligned(ptr2 + j));
166 if (ret >= linebuflen - lx)
167 goto overflow1;
168 lx += ret;
169 }
170 } else {
171 for (j = 0; j < len; j++) {
172 if (linebuflen < lx + 2)
173 goto overflow2;
174 ch = ptr[j];
175 linebuf[lx++] = hex_asc_hi(ch);
176 if (linebuflen < lx + 2)
177 goto overflow2;
178 linebuf[lx++] = hex_asc_lo(ch);
179 if (linebuflen < lx + 2)
180 goto overflow2;
181 linebuf[lx++] = ' ';
182 }
183 if (j)
184 lx--;
185 }
186 if (!ascii)
187 goto nil;
188
189 while (lx < ascii_column) {
190 if (linebuflen < lx + 2)
191 goto overflow2;
192 linebuf[lx++] = ' ';
193 }
194 for (j = 0; j < len; j++) {
195 if (linebuflen < lx + 2)
196 goto overflow2;
197 ch = ptr[j];
198 linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
199 }
200nil:
201 linebuf[lx] = '\0';
202 return lx;
203overflow2:
204 linebuf[lx++] = '\0';
205overflow1:
206 return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
207}
208EXPORT_SYMBOL(hex_dump_to_buffer);
209
210#ifdef CONFIG_PRINTK
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
240
241
242void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
243 int rowsize, int groupsize,
244 const void *buf, size_t len, bool ascii)
245{
246 const u8 *ptr = buf;
247 int i, linelen, remaining = len;
248 unsigned char linebuf[32 * 3 + 2 + 32 + 1];
249
250 if (rowsize != 16 && rowsize != 32)
251 rowsize = 16;
252
253 for (i = 0; i < len; i += rowsize) {
254 linelen = min(remaining, rowsize);
255 remaining -= rowsize;
256
257 hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
258 linebuf, sizeof(linebuf), ascii);
259
260 switch (prefix_type) {
261 case DUMP_PREFIX_ADDRESS:
262 printk("%s%s%p: %s\n",
263 level, prefix_str, ptr + i, linebuf);
264 break;
265 case DUMP_PREFIX_OFFSET:
266 printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
267 break;
268 default:
269 printk("%s%s%s\n", level, prefix_str, linebuf);
270 break;
271 }
272 }
273}
274EXPORT_SYMBOL(print_hex_dump);
275
276#if !defined(CONFIG_DYNAMIC_DEBUG)
277
278
279
280
281
282
283
284
285
286
287
288
289void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
290 const void *buf, size_t len)
291{
292 print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
293 buf, len, true);
294}
295EXPORT_SYMBOL(print_hex_dump_bytes);
296#endif
297#endif
298