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