]> granicus.if.org Git - strace/blob - mtd.c
tests: add ioctl_evdev-success* test binaries to .gitignore
[strace] / mtd.c
1 /*
2  * Copyright (c) 2012 Mike Frysinger <vapier@gentoo.org>
3  * Copyright (c) 2012-2018 The strace developers.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  */
7
8 #include "defs.h"
9
10 #ifdef HAVE_STRUCT_MTD_WRITE_REQ
11
12 # include DEF_MPERS_TYPE(struct_mtd_oob_buf)
13
14 # include <linux/ioctl.h>
15 # include <mtd/mtd-abi.h>
16
17 typedef struct mtd_oob_buf struct_mtd_oob_buf;
18
19 #endif /* HAVE_STRUCT_MTD_WRITE_REQ */
20
21 #include MPERS_DEFS
22
23 #ifdef HAVE_STRUCT_MTD_WRITE_REQ
24
25 # include "xlat/mtd_mode_options.h"
26 # include "xlat/mtd_file_mode_options.h"
27 # include "xlat/mtd_type_options.h"
28 # include "xlat/mtd_flags_options.h"
29 # include "xlat/mtd_otp_options.h"
30 # include "xlat/mtd_nandecc_options.h"
31
32 static void
33 decode_erase_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
34 {
35         struct erase_info_user einfo;
36
37         tprints(", ");
38         if (umove_or_printaddr(tcp, addr, &einfo))
39                 return;
40
41         tprintf("{start=%#x, length=%#x}", einfo.start, einfo.length);
42 }
43
44 static void
45 decode_erase_info_user64(struct tcb *const tcp, const kernel_ulong_t addr)
46 {
47         struct erase_info_user64 einfo64;
48
49         tprints(", ");
50         if (umove_or_printaddr(tcp, addr, &einfo64))
51                 return;
52
53         tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
54                 (uint64_t) einfo64.start, (uint64_t) einfo64.length);
55 }
56
57 static void
58 decode_mtd_oob_buf(struct tcb *const tcp, const kernel_ulong_t addr)
59 {
60         struct_mtd_oob_buf mbuf;
61
62         tprints(", ");
63         if (umove_or_printaddr(tcp, addr, &mbuf))
64                 return;
65
66         tprintf("{start=%#x, length=%#x, ptr=", mbuf.start, mbuf.length);
67         printaddr(ptr_to_kulong(mbuf.ptr));
68         tprints("}");
69 }
70
71 static void
72 decode_mtd_oob_buf64(struct tcb *const tcp, const kernel_ulong_t addr)
73 {
74         struct mtd_oob_buf64 mbuf64;
75
76         tprints(", ");
77         if (umove_or_printaddr(tcp, addr, &mbuf64))
78                 return;
79
80         tprintf("{start=%#" PRIx64 ", length=%#x, usr_ptr=%#" PRIx64 "}",
81                 (uint64_t) mbuf64.start, mbuf64.length,
82                 (uint64_t) mbuf64.usr_ptr);
83 }
84
85 static void
86 decode_otp_info(struct tcb *const tcp, const kernel_ulong_t addr)
87 {
88         struct otp_info oinfo;
89
90         tprints(", ");
91         if (umove_or_printaddr(tcp, addr, &oinfo))
92                 return;
93
94         tprintf("{start=%#x, length=%#x, locked=%u}",
95                 oinfo.start, oinfo.length, oinfo.locked);
96 }
97
98 static void
99 decode_otp_select(struct tcb *const tcp, const kernel_ulong_t addr)
100 {
101         unsigned int i;
102
103         tprints(", ");
104         if (umove_or_printaddr(tcp, addr, &i))
105                 return;
106
107         tprints("[");
108         printxval(mtd_otp_options, i, "MTD_OTP_???");
109         tprints("]");
110 }
111
112 static void
113 decode_mtd_write_req(struct tcb *const tcp, const kernel_ulong_t addr)
114 {
115         struct mtd_write_req mreq;
116
117         tprints(", ");
118         if (umove_or_printaddr(tcp, addr, &mreq))
119                 return;
120
121         tprintf("{start=%#" PRIx64 ", len=%#" PRIx64
122                 ", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64
123                 ", usr_oob=%#" PRIx64 ", mode=",
124                 (uint64_t) mreq.start, (uint64_t) mreq.len,
125                 (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data,
126                 (uint64_t) mreq.usr_oob);
127         printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
128         tprints("}");
129 }
130
131 static void
132 decode_mtd_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
133 {
134         struct mtd_info_user minfo;
135
136         tprints(", ");
137         if (umove_or_printaddr(tcp, addr, &minfo))
138                 return;
139
140         tprints("{type=");
141         printxval(mtd_type_options, minfo.type, "MTD_???");
142         tprints(", flags=");
143         printflags(mtd_flags_options, minfo.flags, "MTD_???");
144         tprintf(", size=%#x, erasesize=%#x, writesize=%#x, oobsize=%#x"
145                 ", padding=%#" PRIx64 "}",
146                 minfo.size, minfo.erasesize, minfo.writesize, minfo.oobsize,
147                 (uint64_t) minfo.padding);
148 }
149
150 static void
151 decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr)
152 {
153         struct nand_oobinfo ninfo;
154         unsigned int i, j;
155
156         tprints(", ");
157         if (umove_or_printaddr(tcp, addr, &ninfo))
158                 return;
159
160         tprints("{useecc=");
161         printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
162         tprintf(", eccbytes=%#x", ninfo.eccbytes);
163
164         tprints(", oobfree={");
165         for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
166                 if (i)
167                         tprints("}, ");
168                 tprints("{");
169                 for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
170                         if (j)
171                                 tprints(", ");
172                         tprintf("%#x", ninfo.oobfree[i][j]);
173                 }
174         }
175
176         tprints("}}, eccpos={");
177         for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
178                 if (i)
179                         tprints(", ");
180                 tprintf("%#x", ninfo.eccpos[i]);
181         }
182
183         tprints("}");
184 }
185
186 static void
187 decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr)
188 {
189         struct nand_ecclayout_user nlay;
190         unsigned int i;
191
192         tprints(", ");
193         if (umove_or_printaddr(tcp, addr, &nlay))
194                 return;
195
196         tprintf("{eccbytes=%#x, eccpos={", nlay.eccbytes);
197         for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
198                 if (i)
199                         tprints(", ");
200                 tprintf("%#x", nlay.eccpos[i]);
201         }
202         tprintf("}, oobavail=%#x, oobfree={", nlay.oobavail);
203         for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
204                 if (i)
205                         tprints(", ");
206                 tprintf("{offset=%#x, length=%#x}",
207                         nlay.oobfree[i].offset, nlay.oobfree[i].length);
208         }
209         tprints("}");
210 }
211
212 static void
213 decode_mtd_ecc_stats(struct tcb *const tcp, const kernel_ulong_t addr)
214 {
215         struct mtd_ecc_stats es;
216
217         tprints(", ");
218         if (umove_or_printaddr(tcp, addr, &es))
219                 return;
220
221         tprintf("{corrected=%#x, failed=%#x, badblocks=%#x, bbtblocks=%#x}",
222                 es.corrected, es.failed, es.badblocks, es.bbtblocks);
223 }
224
225 MPERS_PRINTER_DECL(int, mtd_ioctl, struct tcb *const tcp,
226                    const unsigned int code, const kernel_ulong_t arg)
227 {
228         switch (code) {
229         case MEMERASE:
230         case MEMLOCK:
231         case MEMUNLOCK:
232         case MEMISLOCKED:
233                 decode_erase_info_user(tcp, arg);
234                 break;
235
236         case MEMERASE64:
237                 decode_erase_info_user64(tcp, arg);
238                 break;
239
240         case MEMWRITEOOB:
241         case MEMREADOOB:
242                 decode_mtd_oob_buf(tcp, arg);
243                 break;
244
245         case MEMWRITEOOB64:
246         case MEMREADOOB64:
247                 decode_mtd_oob_buf64(tcp, arg);
248                 break;
249
250         case MEMWRITE:
251                 decode_mtd_write_req(tcp, arg);
252                 break;
253
254         case OTPGETREGIONINFO:
255                 if (entering(tcp))
256                         return 0;
257                 ATTRIBUTE_FALLTHROUGH;
258         case OTPLOCK:
259                 decode_otp_info(tcp, arg);
260                 break;
261
262         case OTPSELECT:
263                 decode_otp_select(tcp, arg);
264                 break;
265
266         case MTDFILEMODE:
267                 tprints(", ");
268                 printxval64(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
269                 break;
270
271         case MEMGETBADBLOCK:
272         case MEMSETBADBLOCK:
273                 tprints(", ");
274                 printnum_int64(tcp, arg, "%" PRIu64);
275                 break;
276
277         case MEMGETINFO:
278                 if (entering(tcp))
279                         return 0;
280                 decode_mtd_info_user(tcp, arg);
281                 break;
282
283         case MEMGETOOBSEL:
284                 if (entering(tcp))
285                         return 0;
286                 decode_nand_oobinfo(tcp, arg);
287                 break;
288
289         case ECCGETLAYOUT:
290                 if (entering(tcp))
291                         return 0;
292                 decode_nand_ecclayout_user(tcp, arg);
293                 break;
294
295         case ECCGETSTATS:
296                 if (entering(tcp))
297                         return 0;
298                 decode_mtd_ecc_stats(tcp, arg);
299                 break;
300
301         case OTPGETREGIONCOUNT:
302                 if (entering(tcp))
303                         return 0;
304                 tprints(", ");
305                 printnum_int(tcp, arg, "%u");
306                 break;
307
308         case MEMGETREGIONCOUNT:
309                 if (entering(tcp))
310                         return 0;
311                 tprints(", ");
312                 printnum_int(tcp, arg, "%d");
313                 break;
314
315         case MEMGETREGIONINFO:
316                 if (entering(tcp)) {
317                         struct region_info_user rinfo;
318
319                         tprints(", ");
320                         if (umove_or_printaddr(tcp, arg, &rinfo))
321                                 break;
322                         tprintf("{regionindex=%#x", rinfo.regionindex);
323                         return 0;
324                 } else {
325                         struct region_info_user rinfo;
326
327                         if (!syserror(tcp) && !umove(tcp, arg, &rinfo))
328                                 tprintf(", offset=%#x"
329                                         ", erasesize=%#x"
330                                         ", numblocks=%#x}",
331                                         rinfo.offset,
332                                         rinfo.erasesize,
333                                         rinfo.numblocks);
334                         tprints("}");
335                         break;
336                 }
337
338         default:
339                 return RVAL_DECODED;
340         }
341
342         return RVAL_IOCTL_DECODED;
343 }
344
345 #endif /* HAVE_STRUCT_MTD_WRITE_REQ */