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