]> granicus.if.org Git - strace/blob - mtd.c
execve.c: make use of RVAL_DECODED
[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 <linux/ioctl.h>
30
31 /* The mtd api changes quickly, so we have to keep a local copy */
32 #include <linux/version.h>
33 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
34 # include "mtd-abi.h"
35 #else
36 # include <mtd/mtd-abi.h>
37 #endif
38 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
39 # include "ubi-user.h"
40 #else
41 # include <mtd/ubi-user.h>
42 #endif
43
44 #include "xlat/mtd_mode_options.h"
45 #include "xlat/mtd_file_mode_options.h"
46 #include "xlat/mtd_type_options.h"
47 #include "xlat/mtd_flags_options.h"
48 #include "xlat/mtd_otp_options.h"
49 #include "xlat/mtd_nandecc_options.h"
50
51 int
52 mtd_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
53 {
54         if (!verbose(tcp))
55                 return RVAL_DECODED;
56
57         switch (code) {
58         case MEMERASE:
59         case MEMLOCK:
60         case MEMUNLOCK:
61         case MEMISLOCKED: {
62                 struct erase_info_user einfo;
63
64                 tprints(", ");
65                 if (umove_or_printaddr(tcp, arg, &einfo))
66                         break;
67
68                 tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 "}",
69                         einfo.start, einfo.length);
70                 break;
71         }
72
73         case MEMERASE64: {
74                 struct erase_info_user64 einfo64;
75
76                 tprints(", ");
77                 if (umove_or_printaddr(tcp, arg, &einfo64))
78                         break;
79
80                 tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
81                         (uint64_t) einfo64.start, (uint64_t) einfo64.length);
82                 break;
83         }
84
85         case MEMWRITEOOB:
86         case MEMREADOOB: {
87                 struct mtd_oob_buf mbuf;
88
89                 tprints(", ");
90                 if (umove_or_printaddr(tcp, arg, &mbuf))
91                         break;
92
93                 tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", ptr=...}",
94                         mbuf.start, mbuf.length);
95                 break;
96         }
97
98         case MEMWRITEOOB64:
99         case MEMREADOOB64: {
100                 struct mtd_oob_buf64 mbuf64;
101
102                 tprints(", ");
103                 if (umove_or_printaddr(tcp, arg, &mbuf64))
104                         break;
105
106                 tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 ", ptr=...}",
107                         (uint64_t) mbuf64.start, (uint64_t) mbuf64.length);
108                 break;
109         }
110
111         case MEMGETREGIONINFO: {
112                 struct region_info_user rinfo;
113
114                 if (entering(tcp)) {
115                         tprints(", ");
116                         if (umove_or_printaddr(tcp, arg, &rinfo))
117                                 break;
118                         tprintf("{regionindex=%#x", rinfo.regionindex);
119                         return 1;
120                 } else {
121                         if (syserror(tcp)) {
122                                 tprints("}");
123                                 break;
124                         }
125                         if (umove(tcp, arg, &rinfo) < 0) {
126                                 tprints(", ???}");
127                                 break;
128                         }
129                         tprintf(", offset=%#x, erasesize=%#x, numblocks=%#x}",
130                                 rinfo.offset, rinfo.erasesize, rinfo.numblocks);
131                         break;
132                 }
133         }
134
135         case OTPLOCK: {
136                 struct otp_info oinfo;
137
138                 tprints(", ");
139                 if (umove_or_printaddr(tcp, arg, &oinfo))
140                         break;
141
142                 tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
143                         oinfo.start, oinfo.length, oinfo.locked);
144                 break;
145         }
146
147         case MEMWRITE: {
148                 struct mtd_write_req mreq;
149
150                 tprints(", ");
151                 if (umove_or_printaddr(tcp, arg, &mreq))
152                         break;
153
154                 tprintf("{start=%#" PRIx64 ", len=%#" PRIx64,
155                         (uint64_t) mreq.start, (uint64_t) mreq.len);
156                 tprintf(", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64,
157                         (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data);
158                 tprintf(", usr_oob=%#" PRIx64 ", mode=",
159                         (uint64_t) mreq.usr_oob);
160                 printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
161                 tprints(", padding=...}");
162                 break;
163         }
164
165         case OTPSELECT: {
166                 unsigned int i;
167
168                 tprints(", ");
169                 if (umove_or_printaddr(tcp, arg, &i))
170                         break;
171
172                 tprints("[");
173                 printxval(mtd_otp_options, i, "MTD_OTP_???");
174                 tprints("]");
175                 break;
176         }
177
178         case MTDFILEMODE:
179                 tprints(", ");
180                 printxval(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
181                 break;
182
183         case MEMGETBADBLOCK:
184         case MEMSETBADBLOCK:
185                 tprints(", ");
186                 printnum_int64(tcp, arg, "%" PRIu64);
187                 break;
188
189         case MEMGETINFO: {
190                 struct mtd_info_user minfo;
191
192                 if (entering(tcp))
193                         return 0;
194
195                 tprints(", ");
196                 if (umove_or_printaddr(tcp, arg, &minfo))
197                         break;
198
199                 tprints("{type=");
200                 printxval(mtd_type_options, minfo.type, "MTD_???");
201                 tprints(", flags=");
202                 printflags(mtd_flags_options, minfo.flags, "MTD_???");
203                 tprintf(", size=%#" PRIx32 ", erasesize=%#" PRIx32,
204                         minfo.size, minfo.erasesize);
205                 tprintf(", writesize=%#" PRIx32 ", oobsize=%#" PRIx32,
206                         minfo.writesize, minfo.oobsize);
207                 tprintf(", padding=%#" PRIx64 "}",
208                         (uint64_t) minfo.padding);
209                 break;
210         }
211
212         case MEMGETOOBSEL: {
213                 struct nand_oobinfo ninfo;
214                 unsigned int i;
215
216                 if (entering(tcp))
217                         return 0;
218
219                 tprints(", ");
220                 if (umove_or_printaddr(tcp, arg, &ninfo))
221                         break;
222
223                 tprints("{useecc=");
224                 printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
225                 tprintf(", eccbytes=%#" PRIx32, ninfo.eccbytes);
226
227                 tprints(", oobfree={");
228                 for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
229                         unsigned int j;
230
231                         if (i)
232                                 tprints("}, ");
233                         tprints("{");
234                         for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
235                                 if (j)
236                                         tprints(", ");
237                                 tprintf("%#" PRIx32, ninfo.oobfree[i][j]);
238                         }
239                 }
240
241                 tprints("}}, eccpos={");
242                 for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
243                         if (i)
244                                 tprints(", ");
245                         tprintf("%#" PRIx32, ninfo.eccpos[i]);
246                 }
247
248                 tprints("}");
249                 break;
250         }
251
252         case OTPGETREGIONINFO: {
253                 struct otp_info oinfo;
254
255                 if (entering(tcp))
256                         return 0;
257
258                 tprints(", ");
259                 if (umove_or_printaddr(tcp, arg, &oinfo))
260                         break;
261
262                 tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
263                         oinfo.start, oinfo.length, oinfo.locked);
264                 break;
265         }
266
267         case ECCGETLAYOUT: {
268                 struct nand_ecclayout_user nlay;
269                 unsigned int i;
270
271                 if (entering(tcp))
272                         return 0;
273
274                 tprints(", ");
275                 if (umove_or_printaddr(tcp, arg, &nlay))
276                         break;
277
278                 tprintf("{eccbytes=%#" PRIx32 ", eccpos={", nlay.eccbytes);
279                 for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
280                         if (i)
281                                 tprints(", ");
282                         tprintf("%#" PRIx32, nlay.eccpos[i]);
283                 }
284                 tprintf("}, oobavail=%#" PRIx32 ", oobfree={", nlay.oobavail);
285                 for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
286                         if (i)
287                                 tprints(", ");
288                         tprintf("{offset=%#" PRIx32 ", length=%#" PRIx32 "}",
289                                 nlay.oobfree[i].offset, nlay.oobfree[i].length);
290                 }
291                 tprints("}");
292                 break;
293         }
294
295         case ECCGETSTATS: {
296                 struct mtd_ecc_stats estat;
297
298                 if (entering(tcp))
299                         return 0;
300
301                 tprints(", ");
302                 if (umove_or_printaddr(tcp, arg, &estat))
303                         break;
304
305                 tprintf("{corrected=%#" PRIx32 ", failed=%#" PRIx32,
306                         estat.corrected, estat.failed);
307                 tprintf(", badblocks=%#" PRIx32 ", bbtblocks=%#" PRIx32 "}",
308                         estat.badblocks, estat.bbtblocks);
309                 break;
310         }
311
312         case OTPGETREGIONCOUNT:
313                 if (entering(tcp))
314                         return 0;
315
316                 tprints(", ");
317                 printnum_int(tcp, arg, "%u");
318                 break;
319
320         case MEMGETREGIONCOUNT:
321                 if (entering(tcp))
322                         return 0;
323
324                 tprints(", ");
325                 printnum_int(tcp, arg, "%d");
326                 break;
327
328         default:
329                 return RVAL_DECODED;
330         }
331
332         return RVAL_DECODED | 1;
333 }
334
335 #include "xlat/ubi_volume_types.h"
336 #include "xlat/ubi_volume_props.h"
337
338 int
339 ubi_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
340 {
341         if (!verbose(tcp))
342                 return RVAL_DECODED;
343
344         switch (code) {
345         case UBI_IOCMKVOL:
346                 if (entering(tcp)) {
347                         struct ubi_mkvol_req mkvol;
348
349                         tprints(", ");
350                         if (umove_or_printaddr(tcp, arg, &mkvol))
351                                 break;
352
353                         tprintf("{vol_id=%" PRIi32 ", alignment=%" PRIi32
354                                 ", bytes=%" PRIi64 ", vol_type=", mkvol.vol_id,
355                                 mkvol.alignment, (int64_t)mkvol.bytes);
356                         printxval(ubi_volume_types, mkvol.vol_type, "UBI_???_VOLUME");
357                         tprintf(", name_len=%" PRIi16 ", name=", mkvol.name_len);
358                         if (print_quoted_string(mkvol.name,
359                                         CLAMP(mkvol.name_len, 0, UBI_MAX_VOLUME_NAME),
360                                         QUOTE_0_TERMINATED) > 0) {
361                                 tprints("...");
362                         }
363                         tprints("}");
364                         return 1;
365                 }
366                 if (!syserror(tcp)) {
367                         tprints(" => ");
368                         printnum_int(tcp, arg, "%d");
369                 }
370                 break;
371
372         case UBI_IOCRSVOL: {
373                 struct ubi_rsvol_req rsvol;
374
375                 tprints(", ");
376                 if (umove_or_printaddr(tcp, arg, &rsvol))
377                         break;
378
379                 tprintf("{vol_id=%" PRIi32 ", bytes=%" PRIi64 "}",
380                         rsvol.vol_id, (int64_t)rsvol.bytes);
381                 break;
382         }
383
384         case UBI_IOCRNVOL: {
385                 struct ubi_rnvol_req rnvol;
386                 int c;
387
388                 tprints(", ");
389                 if (umove_or_printaddr(tcp, arg, &rnvol))
390                         break;
391
392                 tprintf("{count=%" PRIi32 ", ents=[", rnvol.count);
393                 for (c = 0; c < CLAMP(rnvol.count, 0, UBI_MAX_RNVOL); ++c) {
394                         if (c)
395                                 tprints(", ");
396                         tprintf("{vol_id=%" PRIi32 ", name_len=%" PRIi16
397                                 ", name=", rnvol.ents[c].vol_id,
398                                 rnvol.ents[c].name_len);
399                         if (print_quoted_string(rnvol.ents[c].name,
400                                         CLAMP(rnvol.ents[c].name_len, 0, UBI_MAX_VOLUME_NAME),
401                                         QUOTE_0_TERMINATED) > 0) {
402                                 tprints("...");
403                         }
404                         tprints("}");
405                 }
406                 tprints("]}");
407                 break;
408         }
409
410         case UBI_IOCEBCH: {
411                 struct ubi_leb_change_req leb;
412
413                 tprints(", ");
414                 if (umove_or_printaddr(tcp, arg, &leb))
415                         break;
416
417                 tprintf("{lnum=%d, bytes=%d}", leb.lnum, leb.bytes);
418                 break;
419         }
420
421         case UBI_IOCATT:
422                 if (entering(tcp)) {
423                         struct ubi_attach_req attach;
424
425                         tprints(", ");
426                         if (umove_or_printaddr(tcp, arg, &attach))
427                                 break;
428
429                         tprintf("{ubi_num=%" PRIi32 ", mtd_num=%" PRIi32
430                                 ", vid_hdr_offset=%" PRIi32
431                                 ", max_beb_per1024=%" PRIi16 "}",
432                                 attach.ubi_num, attach.mtd_num,
433                                 attach.vid_hdr_offset, attach.max_beb_per1024);
434                         return 1;
435                 }
436                 if (!syserror(tcp)) {
437                         tprints(" => ");
438                         printnum_int(tcp, arg, "%d");
439                 }
440                 break;
441
442         case UBI_IOCEBMAP: {
443                 struct ubi_map_req map;
444
445                 tprints(", ");
446                 if (umove_or_printaddr(tcp, arg, &map))
447                         break;
448
449                 tprintf("{lnum=%" PRIi32 ", dtype=%" PRIi8 "}",
450                         map.lnum, map.dtype);
451                 break;
452         }
453
454         case UBI_IOCSETVOLPROP: {
455                 struct ubi_set_vol_prop_req prop;
456
457                 tprints(", ");
458                 if (umove_or_printaddr(tcp, arg, &prop))
459                         break;
460
461                 tprints("{property=");
462                 printxval(ubi_volume_props, prop.property, "UBI_VOL_PROP_???");
463                 tprintf(", value=%#" PRIx64 "}", (uint64_t)prop.value);
464                 break;
465         }
466
467
468         case UBI_IOCVOLUP:
469                 tprints(", ");
470                 printnum_int64(tcp, arg, "%" PRIi64);
471                 break;
472
473         case UBI_IOCDET:
474         case UBI_IOCEBER:
475         case UBI_IOCEBISMAP:
476         case UBI_IOCEBUNMAP:
477         case UBI_IOCRMVOL:
478                 tprints(", ");
479                 printnum_int(tcp, arg, "%d");
480                 break;
481
482         case UBI_IOCVOLCRBLK:
483         case UBI_IOCVOLRMBLK:
484                 /* no arguments */
485                 break;
486
487         default:
488                 return RVAL_DECODED;
489         }
490
491         return RVAL_DECODED | 1;
492 }