2 * Copyright (c) 2012 Mike Frysinger <vapier@gentoo.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include <sys/ioctl.h>
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)
36 # include <mtd/mtd-abi.h>
39 static const struct xlat mtd_mode_options[] = {
40 { MTD_OPS_PLACE_OOB, "MTD_OPS_PLACE_OOB" },
41 { MTD_OPS_AUTO_OOB, "MTD_OPS_AUTO_OOB" },
42 { MTD_OPS_RAW, "MTD_OPS_RAW" },
46 static const struct xlat mtd_type_options[] = {
47 { MTD_ABSENT, "MTD_ABSENT" },
48 { MTD_RAM, "MTD_RAM" },
49 { MTD_ROM, "MTD_ROM" },
50 { MTD_NORFLASH, "MTD_NORFLASH" },
51 { MTD_NANDFLASH, "MTD_NANDFLASH" },
52 { MTD_DATAFLASH, "MTD_DATAFLASH" },
53 { MTD_UBIVOLUME, "MTD_UBIVOLUME" },
54 { MTD_MLCNANDFLASH, "MTD_MLCNANDFLASH" },
58 static const struct xlat mtd_flags_options[] = {
59 { MTD_WRITEABLE, "MTD_WRITEABLE" },
60 { MTD_BIT_WRITEABLE, "MTD_BIT_WRITEABLE" },
61 { MTD_NO_ERASE, "MTD_NO_ERASE" },
62 { MTD_POWERUP_LOCK, "MTD_POWERUP_LOCK" },
66 static const struct xlat mtd_otp_options[] = {
67 { MTD_OTP_OFF, "MTD_OTP_OFF" },
68 { MTD_OTP_FACTORY, "MTD_OTP_FACTORY" },
69 { MTD_OTP_USER, "MTD_OTP_USER" },
73 static const struct xlat mtd_nandecc_options[] = {
74 { MTD_NANDECC_OFF, "MTD_NANDECC_OFF" },
75 { MTD_NANDECC_PLACE, "MTD_NANDECC_PLACE" },
76 { MTD_NANDECC_AUTOPLACE, "MTD_NANDECC_AUTOPLACE" },
77 { MTD_NANDECC_PLACEONLY, "MTD_NANDECC_PLACEONLY" },
78 { MTD_NANDECC_AUTOPL_USR, "MTD_NANDECC_AUTOPL_USR" },
82 int mtd_ioctl(struct tcb *tcp, long code, long arg)
84 struct mtd_info_user minfo;
85 struct erase_info_user einfo;
86 struct erase_info_user64 einfo64;
87 struct mtd_oob_buf mbuf;
88 struct mtd_oob_buf64 mbuf64;
89 struct region_info_user rinfo;
90 struct otp_info oinfo;
91 struct mtd_ecc_stats estat;
92 struct mtd_write_req mreq;
93 struct nand_oobinfo ninfo;
94 struct nand_ecclayout_user nlay;
103 if (!verbose(tcp) || umove(tcp, arg, &minfo) < 0)
107 printxval(mtd_type_options, minfo.type, "MTD_???");
109 printflags(mtd_flags_options, minfo.flags, "MTD_???");
110 tprintf(", size=%#" PRIx32 ", erasesize=%#" PRIx32,
111 minfo.size, minfo.erasesize);
112 tprintf(", writesize=%#" PRIx32 ", oobsize=%#" PRIx32,
113 minfo.writesize, minfo.oobsize);
114 tprintf(", padding=%#" PRIx64 "}",
115 (uint64_t) minfo.padding);
122 if (!verbose(tcp) || umove(tcp, arg, &einfo) < 0)
125 tprintf(", {start=%#" PRIx32 ", length=%#" PRIx32 "}",
126 einfo.start, einfo.length);
130 if (!verbose(tcp) || umove(tcp, arg, &einfo64) < 0)
133 tprintf(", {start=%#" PRIx64 ", length=%#" PRIx64 "}",
134 (uint64_t) einfo64.start, (uint64_t) einfo64.length);
139 if (!verbose(tcp) || umove(tcp, arg, &mbuf) < 0)
142 tprintf(", {start=%#" PRIx32 ", length=%#" PRIx32 ", ptr=...}",
143 mbuf.start, mbuf.length);
148 if (!verbose(tcp) || umove(tcp, arg, &mbuf64) < 0)
151 tprintf(", {start=%#" PRIx64 ", length=%#" PRIx64 ", ptr=...}",
152 (uint64_t) mbuf64.start, (uint64_t) mbuf64.length);
155 case MEMGETREGIONINFO:
156 if (!verbose(tcp) || umove(tcp, arg, &rinfo) < 0)
159 tprintf(", {offset=%#" PRIx32 ", erasesize=%#" PRIx32,
160 rinfo.offset, rinfo.erasesize);
161 tprintf(", numblocks=%#" PRIx32 ", regionindex=%#" PRIx32 "}",
162 rinfo.numblocks, rinfo.regionindex);
166 if (!verbose(tcp) || umove(tcp, arg, &ninfo) < 0)
169 tprints(", {useecc=");
170 printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
171 tprintf(", eccbytes=%#" PRIx32, ninfo.eccbytes);
173 tprints(", oobfree={");
174 for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
178 for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
181 tprintf("%#" PRIx32, ninfo.oobfree[i][j]);
185 tprints("}}, eccpos={");
186 for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
189 tprintf("%#" PRIx32, ninfo.eccpos[i]);
195 case OTPGETREGIONINFO:
197 if (!verbose(tcp) || umove(tcp, arg, &oinfo) < 0)
200 tprintf(", {start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
201 oinfo.start, oinfo.length, oinfo.locked);
205 if (!verbose(tcp) || umove(tcp, arg, &nlay) < 0)
208 tprintf(", {eccbytes=%#" PRIx32 ", eccpos={", nlay.eccbytes);
209 for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
212 tprintf("%#" PRIx32, nlay.eccpos[i]);
214 tprintf("}, oobavail=%#" PRIx32 ", oobfree={", nlay.oobavail);
215 for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
218 tprintf("{offset=%#" PRIx32 ", length=%#" PRIx32 "}",
219 nlay.oobfree[i].offset, nlay.oobfree[i].length);
225 if (!verbose(tcp) || umove(tcp, arg, &estat) < 0)
228 tprintf(", {corrected=%#" PRIx32 ", failed=%#" PRIx32,
229 estat.corrected, estat.failed);
230 tprintf(", badblocks=%#" PRIx32 ", bbtblocks=%#" PRIx32 "}",
231 estat.badblocks, estat.bbtblocks);
235 if (!verbose(tcp) || umove(tcp, arg, &mreq) < 0)
238 tprintf(", {start=%#" PRIx64 ", len=%#" PRIx64,
239 (uint64_t) mreq.start, (uint64_t) mreq.len);
240 tprintf(", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64,
241 (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data);
242 tprintf(", usr_oob=%#" PRIx64 ", mode=",
243 (uint64_t) mreq.usr_oob);
244 printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
245 tprints(", padding=...}");
249 if (!verbose(tcp) || umove(tcp, arg, &i) < 0)
253 printxval(mtd_otp_options, i, "MTD_OTP_???");
263 print_loff_t(tcp, arg);
266 case OTPGETREGIONCOUNT:
267 if (!verbose(tcp) || umove(tcp, arg, &i) < 0)
270 tprintf(", [%i]", i);
274 /* XXX: process return value as enum mtd_file_modes */
276 case MEMGETREGIONCOUNT:
277 /* These ones take simple args, so let default printer handle it */