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