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