Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2012 Mike Frysinger <vapier@gentoo.org>
3 : : * Copyright (c) 2012-2017 The strace developers.
4 : : *
5 : : * Redistribution and use in source and binary forms, with or without
6 : : * modification, are permitted provided that the following conditions
7 : : * are met:
8 : : * 1. Redistributions of source code must retain the above copyright
9 : : * notice, this list of conditions and the following disclaimer.
10 : : * 2. Redistributions in binary form must reproduce the above copyright
11 : : * notice, this list of conditions and the following disclaimer in the
12 : : * documentation and/or other materials provided with the distribution.
13 : : * 3. The name of the author may not be used to endorse or promote products
14 : : * derived from this software without specific prior written permission.
15 : : *
16 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : : */
27 : :
28 : : #include "defs.h"
29 : :
30 : : #include DEF_MPERS_TYPE(struct_mtd_oob_buf)
31 : :
32 : : #include <linux/ioctl.h>
33 : :
34 : : /* The mtd api changes quickly, so we have to keep a local copy */
35 : : #include <linux/version.h>
36 : : #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
37 : : # include "mtd-abi.h"
38 : : #else
39 : : # include <mtd/mtd-abi.h>
40 : : #endif
41 : :
42 : : typedef struct mtd_oob_buf struct_mtd_oob_buf;
43 : :
44 : : #include MPERS_DEFS
45 : :
46 : : #include "xlat/mtd_mode_options.h"
47 : : #include "xlat/mtd_file_mode_options.h"
48 : : #include "xlat/mtd_type_options.h"
49 : : #include "xlat/mtd_flags_options.h"
50 : : #include "xlat/mtd_otp_options.h"
51 : : #include "xlat/mtd_nandecc_options.h"
52 : :
53 : : static void
54 : 16 : decode_erase_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
55 : : {
56 : : struct erase_info_user einfo;
57 : :
58 : 16 : tprints(", ");
59 [ + + ]: 16 : if (umove_or_printaddr(tcp, addr, &einfo))
60 : 8 : return;
61 : :
62 : 8 : tprintf("{start=%#x, length=%#x}", einfo.start, einfo.length);
63 : : }
64 : :
65 : : static void
66 : 4 : decode_erase_info_user64(struct tcb *const tcp, const kernel_ulong_t addr)
67 : : {
68 : : struct erase_info_user64 einfo64;
69 : :
70 : 4 : tprints(", ");
71 [ + + ]: 4 : if (umove_or_printaddr(tcp, addr, &einfo64))
72 : 2 : return;
73 : :
74 : 2 : tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
75 : 2 : (uint64_t) einfo64.start, (uint64_t) einfo64.length);
76 : : }
77 : :
78 : : static void
79 : 8 : decode_mtd_oob_buf(struct tcb *const tcp, const kernel_ulong_t addr)
80 : : {
81 : : struct_mtd_oob_buf mbuf;
82 : :
83 : 8 : tprints(", ");
84 [ + + ]: 8 : if (umove_or_printaddr(tcp, addr, &mbuf))
85 : 4 : return;
86 : :
87 : 4 : tprintf("{start=%#x, length=%#x, ptr=", mbuf.start, mbuf.length);
88 : 4 : printaddr(ptr_to_kulong(mbuf.ptr));
89 : 4 : tprints("}");
90 : : }
91 : :
92 : : static void
93 : 8 : decode_mtd_oob_buf64(struct tcb *const tcp, const kernel_ulong_t addr)
94 : : {
95 : : struct mtd_oob_buf64 mbuf64;
96 : :
97 : 8 : tprints(", ");
98 [ + + ]: 8 : if (umove_or_printaddr(tcp, addr, &mbuf64))
99 : 4 : return;
100 : :
101 : 4 : tprintf("{start=%#" PRIx64 ", length=%#x, usr_ptr=%#" PRIx64 "}",
102 : 4 : (uint64_t) mbuf64.start, mbuf64.length,
103 : 4 : (uint64_t) mbuf64.usr_ptr);
104 : : }
105 : :
106 : : static void
107 : 6 : decode_otp_info(struct tcb *const tcp, const kernel_ulong_t addr)
108 : : {
109 : : struct otp_info oinfo;
110 : :
111 : 6 : tprints(", ");
112 [ + + ]: 6 : if (umove_or_printaddr(tcp, addr, &oinfo))
113 : 4 : return;
114 : :
115 : 2 : tprintf("{start=%#x, length=%#x, locked=%u}",
116 : : oinfo.start, oinfo.length, oinfo.locked);
117 : : }
118 : :
119 : : static void
120 : 6 : decode_otp_select(struct tcb *const tcp, const kernel_ulong_t addr)
121 : : {
122 : : unsigned int i;
123 : :
124 : 6 : tprints(", ");
125 [ + + ]: 6 : if (umove_or_printaddr(tcp, addr, &i))
126 : 2 : return;
127 : :
128 : 4 : tprints("[");
129 : 4 : printxval(mtd_otp_options, i, "MTD_OTP_???");
130 : 4 : tprints("]");
131 : : }
132 : :
133 : : static void
134 : 4 : decode_mtd_write_req(struct tcb *const tcp, const kernel_ulong_t addr)
135 : : {
136 : : struct mtd_write_req mreq;
137 : :
138 : 4 : tprints(", ");
139 [ + + ]: 4 : if (umove_or_printaddr(tcp, addr, &mreq))
140 : 2 : return;
141 : :
142 : 2 : tprintf("{start=%#" PRIx64 ", len=%#" PRIx64
143 : : ", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64
144 : : ", usr_oob=%#" PRIx64 ", mode=",
145 : 2 : (uint64_t) mreq.start, (uint64_t) mreq.len,
146 : 2 : (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data,
147 : 2 : (uint64_t) mreq.usr_oob);
148 : 2 : printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
149 : 2 : tprints("}");
150 : : }
151 : :
152 : : static void
153 : 2 : decode_mtd_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
154 : : {
155 : : struct mtd_info_user minfo;
156 : :
157 : 2 : tprints(", ");
158 [ - + ]: 2 : if (umove_or_printaddr(tcp, addr, &minfo))
159 : 2 : return;
160 : :
161 : 0 : tprints("{type=");
162 : 0 : printxval(mtd_type_options, minfo.type, "MTD_???");
163 : 0 : tprints(", flags=");
164 : 0 : printflags(mtd_flags_options, minfo.flags, "MTD_???");
165 : 0 : tprintf(", size=%#x, erasesize=%#x, writesize=%#x, oobsize=%#x"
166 : : ", padding=%#" PRIx64 "}",
167 : : minfo.size, minfo.erasesize, minfo.writesize, minfo.oobsize,
168 : 0 : (uint64_t) minfo.padding);
169 : : }
170 : :
171 : : static void
172 : 2 : decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr)
173 : : {
174 : : struct nand_oobinfo ninfo;
175 : : unsigned int i, j;
176 : :
177 : 2 : tprints(", ");
178 [ - + ]: 2 : if (umove_or_printaddr(tcp, addr, &ninfo))
179 : 2 : return;
180 : :
181 : 0 : tprints("{useecc=");
182 : 0 : printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
183 : 0 : tprintf(", eccbytes=%#x", ninfo.eccbytes);
184 : :
185 : 0 : tprints(", oobfree={");
186 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
187 [ # # ]: 0 : if (i)
188 : 0 : tprints("}, ");
189 : 0 : tprints("{");
190 [ # # ]: 0 : for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
191 [ # # ]: 0 : if (j)
192 : 0 : tprints(", ");
193 : 0 : tprintf("%#x", ninfo.oobfree[i][j]);
194 : : }
195 : : }
196 : :
197 : 0 : tprints("}}, eccpos={");
198 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
199 [ # # ]: 0 : if (i)
200 : 0 : tprints(", ");
201 : 0 : tprintf("%#x", ninfo.eccpos[i]);
202 : : }
203 : :
204 : 0 : tprints("}");
205 : : }
206 : :
207 : : static void
208 : 2 : decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr)
209 : : {
210 : : struct nand_ecclayout_user nlay;
211 : : unsigned int i;
212 : :
213 : 2 : tprints(", ");
214 [ - + ]: 2 : if (umove_or_printaddr(tcp, addr, &nlay))
215 : 2 : return;
216 : :
217 : 0 : tprintf("{eccbytes=%#x, eccpos={", nlay.eccbytes);
218 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
219 [ # # ]: 0 : if (i)
220 : 0 : tprints(", ");
221 : 0 : tprintf("%#x", nlay.eccpos[i]);
222 : : }
223 : 0 : tprintf("}, oobavail=%#x, oobfree={", nlay.oobavail);
224 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
225 [ # # ]: 0 : if (i)
226 : 0 : tprints(", ");
227 : 0 : tprintf("{offset=%#x, length=%#x}",
228 : : nlay.oobfree[i].offset, nlay.oobfree[i].length);
229 : : }
230 : 0 : tprints("}");
231 : : }
232 : :
233 : : static void
234 : 2 : decode_mtd_ecc_stats(struct tcb *const tcp, const kernel_ulong_t addr)
235 : : {
236 : : struct mtd_ecc_stats es;
237 : :
238 : 2 : tprints(", ");
239 [ - + ]: 2 : if (umove_or_printaddr(tcp, addr, &es))
240 : 2 : return;
241 : :
242 : 0 : tprintf("{corrected=%#x, failed=%#x, badblocks=%#x, bbtblocks=%#x}",
243 : : es.corrected, es.failed, es.badblocks, es.bbtblocks);
244 : : }
245 : :
246 : 94 : MPERS_PRINTER_DECL(int, mtd_ioctl, struct tcb *const tcp,
247 : : const unsigned int code, const kernel_ulong_t arg)
248 : : {
249 [ + + + + : 94 : switch (code) {
+ + + + +
+ + + + +
+ + + + ]
250 : : case MEMERASE:
251 : : case MEMLOCK:
252 : : case MEMUNLOCK:
253 : : case MEMISLOCKED:
254 : 16 : decode_erase_info_user(tcp, arg);
255 : 16 : break;
256 : :
257 : : case MEMERASE64:
258 : 4 : decode_erase_info_user64(tcp, arg);
259 : 4 : break;
260 : :
261 : : case MEMWRITEOOB:
262 : : case MEMREADOOB:
263 : 8 : decode_mtd_oob_buf(tcp, arg);
264 : 8 : break;
265 : :
266 : : case MEMWRITEOOB64:
267 : : case MEMREADOOB64:
268 : 8 : decode_mtd_oob_buf64(tcp, arg);
269 : 8 : break;
270 : :
271 : : case MEMWRITE:
272 : 4 : decode_mtd_write_req(tcp, arg);
273 : 4 : break;
274 : :
275 : : case OTPGETREGIONINFO:
276 [ + + ]: 4 : if (entering(tcp))
277 : : return 0;
278 : : /* fall through */
279 : : case OTPLOCK:
280 : 6 : decode_otp_info(tcp, arg);
281 : 6 : break;
282 : :
283 : : case OTPSELECT:
284 : 6 : decode_otp_select(tcp, arg);
285 : 6 : break;
286 : :
287 : : case MTDFILEMODE:
288 : 2 : tprints(", ");
289 : : printxval64(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
290 : : break;
291 : :
292 : : case MEMGETBADBLOCK:
293 : : case MEMSETBADBLOCK:
294 : 8 : tprints(", ");
295 : 8 : printnum_int64(tcp, arg, "%" PRIu64);
296 : 8 : break;
297 : :
298 : : case MEMGETINFO:
299 [ + + ]: 4 : if (entering(tcp))
300 : : return 0;
301 : 2 : decode_mtd_info_user(tcp, arg);
302 : 2 : break;
303 : :
304 : : case MEMGETOOBSEL:
305 [ + + ]: 4 : if (entering(tcp))
306 : : return 0;
307 : 2 : decode_nand_oobinfo(tcp, arg);
308 : 2 : break;
309 : :
310 : : case ECCGETLAYOUT:
311 [ + + ]: 4 : if (entering(tcp))
312 : : return 0;
313 : 2 : decode_nand_ecclayout_user(tcp, arg);
314 : 2 : break;
315 : :
316 : : case ECCGETSTATS:
317 [ + + ]: 4 : if (entering(tcp))
318 : : return 0;
319 : 2 : decode_mtd_ecc_stats(tcp, arg);
320 : 2 : break;
321 : :
322 : : case OTPGETREGIONCOUNT:
323 [ + + ]: 4 : if (entering(tcp))
324 : : return 0;
325 : 2 : tprints(", ");
326 : 2 : printnum_int(tcp, arg, "%u");
327 : 2 : break;
328 : :
329 : : case MEMGETREGIONCOUNT:
330 [ + + ]: 4 : if (entering(tcp))
331 : : return 0;
332 : 2 : tprints(", ");
333 : 2 : printnum_int(tcp, arg, "%d");
334 : 2 : break;
335 : :
336 : : case MEMGETREGIONINFO:
337 [ + + ]: 4 : if (entering(tcp)) {
338 : : struct region_info_user rinfo;
339 : :
340 : 2 : tprints(", ");
341 [ + - ]: 2 : if (umove_or_printaddr(tcp, arg, &rinfo))
342 : : break;
343 : 2 : tprintf("{regionindex=%#x", rinfo.regionindex);
344 : 2 : return 0;
345 : : } else {
346 : : struct region_info_user rinfo;
347 : :
348 [ - + ][ # # ]: 2 : if (!syserror(tcp) && !umove(tcp, arg, &rinfo))
349 : 0 : tprintf(", offset=%#x"
350 : : ", erasesize=%#x"
351 : : ", numblocks=%#x}",
352 : : rinfo.offset,
353 : : rinfo.erasesize,
354 : : rinfo.numblocks);
355 : 2 : tprints("}");
356 : : break;
357 : : }
358 : :
359 : : default:
360 : : return RVAL_DECODED;
361 : : }
362 : :
363 : : return RVAL_DECODED | 1;
364 : : }
|