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