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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
43 int groupsize, char *linebuf, size_t linebuflen,
44 bool ascii)
45{
46 const u8 *ptr = buf;
47 u8 ch;
48 int j, lx = 0;
49 int ascii_column;
50
51 if (rowsize != 16 && rowsize != 32)
52 rowsize = 16;
53
54 if (!len)
55 goto nil;
56 if (len > rowsize)
57 len = rowsize;
58 if ((len % groupsize) != 0)
59 groupsize = 1;
60
61 switch (groupsize) {
62 case 8: {
63 const u64 *ptr8 = buf;
64 int ngroups = len / groupsize;
65
66 for (j = 0; j < ngroups; j++)
67 lx += scnprintf(linebuf + lx, linebuflen - lx,
68 "%s%16.16llx", j ? " " : "",
69 (unsigned long long)*(ptr8 + j));
70 ascii_column = 17 * ngroups + 2;
71 break;
72 }
73
74 case 4: {
75 const u32 *ptr4 = buf;
76 int ngroups = len / groupsize;
77
78 for (j = 0; j < ngroups; j++)
79 lx += scnprintf(linebuf + lx, linebuflen - lx,
80 "%s%8.8x", j ? " " : "", *(ptr4 + j));
81 ascii_column = 9 * ngroups + 2;
82 break;
83 }
84
85 case 2: {
86 const u16 *ptr2 = buf;
87 int ngroups = len / groupsize;
88
89 for (j = 0; j < ngroups; j++)
90 lx += scnprintf(linebuf + lx, linebuflen - lx,
91 "%s%4.4x", j ? " " : "", *(ptr2 + j));
92 ascii_column = 5 * ngroups + 2;
93 break;
94 }
95
96 default:
97 for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) {
98 ch = ptr[j];
99 linebuf[lx++] = hex_asc_hi(ch);
100 linebuf[lx++] = hex_asc_lo(ch);
101 linebuf[lx++] = ' ';
102 }
103 if (j)
104 lx--;
105
106 ascii_column = 3 * rowsize + 2;
107 break;
108 }
109 if (!ascii)
110 goto nil;
111
112 while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
113 linebuf[lx++] = ' ';
114 for (j = 0; (j < len) && (lx + 2) < linebuflen; j++)
115 linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j]
116 : '.';
117nil:
118 linebuf[lx++] = '\0';
119}
120EXPORT_SYMBOL(hex_dump_to_buffer);
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
154 int rowsize, int groupsize,
155 const void *buf, size_t len, bool ascii)
156{
157 const u8 *ptr = buf;
158 int i, linelen, remaining = len;
159 unsigned char linebuf[200];
160
161 if (rowsize != 16 && rowsize != 32)
162 rowsize = 16;
163
164 for (i = 0; i < len; i += rowsize) {
165 linelen = min(remaining, rowsize);
166 remaining -= rowsize;
167 hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
168 linebuf, sizeof(linebuf), ascii);
169
170 switch (prefix_type) {
171 case DUMP_PREFIX_ADDRESS:
172 printk("%s%s%*p: %s\n", level, prefix_str,
173 (int)(2 * sizeof(void *)), ptr + i, linebuf);
174 break;
175 case DUMP_PREFIX_OFFSET:
176 printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
177 break;
178 default:
179 printk("%s%s%s\n", level, prefix_str, linebuf);
180 break;
181 }
182 }
183}
184EXPORT_SYMBOL(print_hex_dump);
185
186
187
188
189
190
191
192
193
194
195
196
197
198void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
199 const void *buf, size_t len)
200{
201 print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
202 buf, len, 1);
203}
204EXPORT_SYMBOL(print_hex_dump_bytes);
205