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