Branch data Line data Source code
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 : 40 : decode_erase_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
54 : : {
55 : : struct erase_info_user einfo;
56 : :
57 : 40 : tprints(", ");
58 [ + + ]: 40 : if (umove_or_printaddr(tcp, addr, &einfo))
59 : 20 : return;
60 : :
61 : 20 : tprintf("{start=%#x, length=%#x}", einfo.start, einfo.length);
62 : : }
63 : :
64 : : static void
65 : 10 : decode_erase_info_user64(struct tcb *const tcp, const kernel_ulong_t addr)
66 : : {
67 : : struct erase_info_user64 einfo64;
68 : :
69 : 10 : tprints(", ");
70 [ + + ]: 10 : if (umove_or_printaddr(tcp, addr, &einfo64))
71 : 5 : return;
72 : :
73 : 5 : tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
74 : 5 : (uint64_t) einfo64.start, (uint64_t) einfo64.length);
75 : : }
76 : :
77 : : static void
78 : 20 : decode_mtd_oob_buf(struct tcb *const tcp, const kernel_ulong_t addr)
79 : : {
80 : : struct_mtd_oob_buf mbuf;
81 : :
82 : 20 : tprints(", ");
83 [ + + ]: 20 : if (umove_or_printaddr(tcp, addr, &mbuf))
84 : 10 : return;
85 : :
86 : 10 : tprintf("{start=%#x, length=%#x, ptr=", mbuf.start, mbuf.length);
87 : 10 : printaddr(ptr_to_kulong(mbuf.ptr));
88 : 10 : tprints("}");
89 : : }
90 : :
91 : : static void
92 : 20 : decode_mtd_oob_buf64(struct tcb *const tcp, const kernel_ulong_t addr)
93 : : {
94 : : struct mtd_oob_buf64 mbuf64;
95 : :
96 : 20 : tprints(", ");
97 [ + + ]: 20 : if (umove_or_printaddr(tcp, addr, &mbuf64))
98 : 10 : return;
99 : :
100 : 10 : tprintf("{start=%#" PRIx64 ", length=%#x, usr_ptr=%#" PRIx64 "}",
101 : 10 : (uint64_t) mbuf64.start, mbuf64.length,
102 : 10 : (uint64_t) mbuf64.usr_ptr);
103 : : }
104 : :
105 : : static void
106 : 15 : decode_otp_info(struct tcb *const tcp, const kernel_ulong_t addr)
107 : : {
108 : : struct otp_info oinfo;
109 : :
110 : 15 : tprints(", ");
111 [ + + ]: 15 : if (umove_or_printaddr(tcp, addr, &oinfo))
112 : 10 : return;
113 : :
114 : 5 : tprintf("{start=%#x, length=%#x, locked=%u}",
115 : : oinfo.start, oinfo.length, oinfo.locked);
116 : : }
117 : :
118 : : static void
119 : 15 : decode_otp_select(struct tcb *const tcp, const kernel_ulong_t addr)
120 : : {
121 : : unsigned int i;
122 : :
123 : 15 : tprints(", ");
124 [ + + ]: 15 : if (umove_or_printaddr(tcp, addr, &i))
125 : 5 : return;
126 : :
127 : 10 : tprints("[");
128 : 10 : printxval(mtd_otp_options, i, "MTD_OTP_???");
129 : 10 : tprints("]");
130 : : }
131 : :
132 : : static void
133 : 10 : decode_mtd_write_req(struct tcb *const tcp, const kernel_ulong_t addr)
134 : : {
135 : : struct mtd_write_req mreq;
136 : :
137 : 10 : tprints(", ");
138 [ + + ]: 10 : if (umove_or_printaddr(tcp, addr, &mreq))
139 : 5 : return;
140 : :
141 : 5 : tprintf("{start=%#" PRIx64 ", len=%#" PRIx64
142 : : ", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64
143 : : ", usr_oob=%#" PRIx64 ", mode=",
144 : 5 : (uint64_t) mreq.start, (uint64_t) mreq.len,
145 : 5 : (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data,
146 : 5 : (uint64_t) mreq.usr_oob);
147 : 5 : printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
148 : 5 : tprints("}");
149 : : }
150 : :
151 : : static void
152 : 5 : decode_mtd_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
153 : : {
154 : : struct mtd_info_user minfo;
155 : :
156 : 5 : tprints(", ");
157 [ + - ]: 5 : if (umove_or_printaddr(tcp, addr, &minfo))
158 : 5 : return;
159 : :
160 : 0 : tprints("{type=");
161 : 0 : printxval(mtd_type_options, minfo.type, "MTD_???");
162 : 0 : tprints(", flags=");
163 : 0 : printflags(mtd_flags_options, minfo.flags, "MTD_???");
164 : 0 : tprintf(", size=%#x, erasesize=%#x, writesize=%#x, oobsize=%#x"
165 : : ", padding=%#" PRIx64 "}",
166 : : minfo.size, minfo.erasesize, minfo.writesize, minfo.oobsize,
167 : 0 : (uint64_t) minfo.padding);
168 : : }
169 : :
170 : : static void
171 : 5 : decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr)
172 : : {
173 : : struct nand_oobinfo ninfo;
174 : : unsigned int i, j;
175 : :
176 : 5 : tprints(", ");
177 [ + - ]: 5 : if (umove_or_printaddr(tcp, addr, &ninfo))
178 : 5 : return;
179 : :
180 : 0 : tprints("{useecc=");
181 : 0 : printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
182 : 0 : tprintf(", eccbytes=%#x", ninfo.eccbytes);
183 : :
184 : 0 : tprints(", oobfree={");
185 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
186 [ # # ]: 0 : if (i)
187 : 0 : tprints("}, ");
188 : 0 : tprints("{");
189 [ # # ]: 0 : for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
190 [ # # ]: 0 : if (j)
191 : 0 : tprints(", ");
192 : 0 : tprintf("%#x", ninfo.oobfree[i][j]);
193 : : }
194 : : }
195 : :
196 : 0 : tprints("}}, eccpos={");
197 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
198 [ # # ]: 0 : if (i)
199 : 0 : tprints(", ");
200 : 0 : tprintf("%#x", ninfo.eccpos[i]);
201 : : }
202 : :
203 : 0 : tprints("}");
204 : : }
205 : :
206 : : static void
207 : 5 : decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr)
208 : : {
209 : : struct nand_ecclayout_user nlay;
210 : : unsigned int i;
211 : :
212 : 5 : tprints(", ");
213 [ + - ]: 5 : if (umove_or_printaddr(tcp, addr, &nlay))
214 : 5 : return;
215 : :
216 : 0 : tprintf("{eccbytes=%#x, eccpos={", nlay.eccbytes);
217 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
218 [ # # ]: 0 : if (i)
219 : 0 : tprints(", ");
220 : 0 : tprintf("%#x", nlay.eccpos[i]);
221 : : }
222 : 0 : tprintf("}, oobavail=%#x, oobfree={", nlay.oobavail);
223 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
224 [ # # ]: 0 : if (i)
225 : 0 : tprints(", ");
226 : 0 : tprintf("{offset=%#x, length=%#x}",
227 : : nlay.oobfree[i].offset, nlay.oobfree[i].length);
228 : : }
229 : 0 : tprints("}");
230 : : }
231 : :
232 : : static void
233 : 5 : decode_mtd_ecc_stats(struct tcb *const tcp, const kernel_ulong_t addr)
234 : : {
235 : : struct mtd_ecc_stats es;
236 : :
237 : 5 : tprints(", ");
238 [ + - ]: 5 : if (umove_or_printaddr(tcp, addr, &es))
239 : 5 : return;
240 : :
241 : 0 : tprintf("{corrected=%#x, failed=%#x, badblocks=%#x, bbtblocks=%#x}",
242 : : es.corrected, es.failed, es.badblocks, es.bbtblocks);
243 : : }
244 : :
245 : 235 : MPERS_PRINTER_DECL(int, mtd_ioctl, struct tcb *const tcp,
246 : : const unsigned int code, const kernel_ulong_t arg)
247 : : {
248 [ + + + + : 235 : switch (code) {
+ + + + +
+ + + + +
+ + + + ]
249 : : case MEMERASE:
250 : : case MEMLOCK:
251 : : case MEMUNLOCK:
252 : : case MEMISLOCKED:
253 : 40 : decode_erase_info_user(tcp, arg);
254 : 40 : break;
255 : :
256 : : case MEMERASE64:
257 : 10 : decode_erase_info_user64(tcp, arg);
258 : 10 : break;
259 : :
260 : : case MEMWRITEOOB:
261 : : case MEMREADOOB:
262 : 20 : decode_mtd_oob_buf(tcp, arg);
263 : 20 : break;
264 : :
265 : : case MEMWRITEOOB64:
266 : : case MEMREADOOB64:
267 : 20 : decode_mtd_oob_buf64(tcp, arg);
268 : 20 : break;
269 : :
270 : : case MEMWRITE:
271 : 10 : decode_mtd_write_req(tcp, arg);
272 : 10 : break;
273 : :
274 : : case OTPGETREGIONINFO:
275 [ + + ]: 10 : if (entering(tcp))
276 : 5 : return 0;
277 : : /* fall through */
278 : : case OTPLOCK:
279 : 15 : decode_otp_info(tcp, arg);
280 : 15 : break;
281 : :
282 : : case OTPSELECT:
283 : 15 : decode_otp_select(tcp, arg);
284 : 15 : break;
285 : :
286 : : case MTDFILEMODE:
287 : 5 : tprints(", ");
288 : 5 : printxval64(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
289 : 5 : break;
290 : :
291 : : case MEMGETBADBLOCK:
292 : : case MEMSETBADBLOCK:
293 : 20 : tprints(", ");
294 : 20 : printnum_int64(tcp, arg, "%" PRIu64);
295 : 20 : break;
296 : :
297 : : case MEMGETINFO:
298 [ + + ]: 10 : if (entering(tcp))
299 : 5 : return 0;
300 : 5 : decode_mtd_info_user(tcp, arg);
301 : 5 : break;
302 : :
303 : : case MEMGETOOBSEL:
304 [ + + ]: 10 : if (entering(tcp))
305 : 5 : return 0;
306 : 5 : decode_nand_oobinfo(tcp, arg);
307 : 5 : break;
308 : :
309 : : case ECCGETLAYOUT:
310 [ + + ]: 10 : if (entering(tcp))
311 : 5 : return 0;
312 : 5 : decode_nand_ecclayout_user(tcp, arg);
313 : 5 : break;
314 : :
315 : : case ECCGETSTATS:
316 [ + + ]: 10 : if (entering(tcp))
317 : 5 : return 0;
318 : 5 : decode_mtd_ecc_stats(tcp, arg);
319 : 5 : break;
320 : :
321 : : case OTPGETREGIONCOUNT:
322 [ + + ]: 10 : if (entering(tcp))
323 : 5 : return 0;
324 : 5 : tprints(", ");
325 : 5 : printnum_int(tcp, arg, "%u");
326 : 5 : break;
327 : :
328 : : case MEMGETREGIONCOUNT:
329 [ + + ]: 10 : if (entering(tcp))
330 : 5 : return 0;
331 : 5 : tprints(", ");
332 : 5 : printnum_int(tcp, arg, "%d");
333 : 5 : break;
334 : :
335 : : case MEMGETREGIONINFO:
336 [ + + ]: 10 : if (entering(tcp)) {
337 : : struct region_info_user rinfo;
338 : :
339 : 5 : tprints(", ");
340 [ - + ]: 5 : if (umove_or_printaddr(tcp, arg, &rinfo))
341 : 0 : break;
342 : 5 : tprintf("{regionindex=%#x", rinfo.regionindex);
343 : 5 : return 0;
344 : : } else {
345 : : struct region_info_user rinfo;
346 : :
347 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &rinfo))
348 : 0 : tprintf(", offset=%#x"
349 : : ", erasesize=%#x"
350 : : ", numblocks=%#x}",
351 : : rinfo.offset,
352 : : rinfo.erasesize,
353 : : rinfo.numblocks);
354 : 5 : tprints("}");
355 : 5 : break;
356 : : }
357 : :
358 : : default:
359 : 5 : return RVAL_DECODED;
360 : : }
361 : :
362 : 190 : return RVAL_DECODED | 1;
363 : : }
|