Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2012 Mike Frysinger <vapier (at) 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 <sys/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_type_options.h"
     46 #include "xlat/mtd_flags_options.h"
     47 #include "xlat/mtd_otp_options.h"
     48 #include "xlat/mtd_nandecc_options.h"
     49 
     50 int mtd_ioctl(struct tcb *tcp, long code, long arg)
     51 {
     52 	struct mtd_info_user minfo;
     53 	struct erase_info_user einfo;
     54 	struct erase_info_user64 einfo64;
     55 	struct mtd_oob_buf mbuf;
     56 	struct mtd_oob_buf64 mbuf64;
     57 	struct region_info_user rinfo;
     58 	struct otp_info oinfo;
     59 	struct mtd_ecc_stats estat;
     60 	struct mtd_write_req mreq;
     61 	struct nand_oobinfo ninfo;
     62 	struct nand_ecclayout_user nlay;
     63 	int i, j;
     64 
     65 	if (entering(tcp))
     66 		return 0;
     67 
     68 	switch (code) {
     69 
     70 	case MEMGETINFO:
     71 		if (!verbose(tcp) || umove(tcp, arg, &minfo) < 0)
     72 			return 0;
     73 
     74 		tprints(", {type=");
     75 		printxval(mtd_type_options, minfo.type, "MTD_???");
     76 		tprints(", flags=");
     77 		printflags(mtd_flags_options, minfo.flags, "MTD_???");
     78 		tprintf(", size=%#" PRIx32 ", erasesize=%#" PRIx32,
     79 			minfo.size, minfo.erasesize);
     80 		tprintf(", writesize=%#" PRIx32 ", oobsize=%#" PRIx32,
     81 			minfo.writesize, minfo.oobsize);
     82 		tprintf(", padding=%#" PRIx64 "}",
     83 			(uint64_t) minfo.padding);
     84 		return 1;
     85 
     86 	case MEMERASE:
     87 	case MEMLOCK:
     88 	case MEMUNLOCK:
     89 	case MEMISLOCKED:
     90 		if (!verbose(tcp) || umove(tcp, arg, &einfo) < 0)
     91 			return 0;
     92 
     93 		tprintf(", {start=%#" PRIx32 ", length=%#" PRIx32 "}",
     94 			einfo.start, einfo.length);
     95 		return 1;
     96 
     97 	case MEMERASE64:
     98 		if (!verbose(tcp) || umove(tcp, arg, &einfo64) < 0)
     99 			return 0;
    100 
    101 		tprintf(", {start=%#" PRIx64 ", length=%#" PRIx64 "}",
    102 			(uint64_t) einfo64.start, (uint64_t) einfo64.length);
    103 		return 1;
    104 
    105 	case MEMWRITEOOB:
    106 	case MEMREADOOB:
    107 		if (!verbose(tcp) || umove(tcp, arg, &mbuf) < 0)
    108 			return 0;
    109 
    110 		tprintf(", {start=%#" PRIx32 ", length=%#" PRIx32 ", ptr=...}",
    111 			mbuf.start, mbuf.length);
    112 		return 1;
    113 
    114 	case MEMWRITEOOB64:
    115 	case MEMREADOOB64:
    116 		if (!verbose(tcp) || umove(tcp, arg, &mbuf64) < 0)
    117 			return 0;
    118 
    119 		tprintf(", {start=%#" PRIx64 ", length=%#" PRIx64 ", ptr=...}",
    120 			(uint64_t) mbuf64.start, (uint64_t) mbuf64.length);
    121 		return 1;
    122 
    123 	case MEMGETREGIONINFO:
    124 		if (!verbose(tcp) || umove(tcp, arg, &rinfo) < 0)
    125 			return 0;
    126 
    127 		tprintf(", {offset=%#" PRIx32 ", erasesize=%#" PRIx32,
    128 			rinfo.offset, rinfo.erasesize);
    129 		tprintf(", numblocks=%#" PRIx32 ", regionindex=%#" PRIx32 "}",
    130 			rinfo.numblocks, rinfo.regionindex);
    131 		return 1;
    132 
    133 	case MEMGETOOBSEL:
    134 		if (!verbose(tcp) || umove(tcp, arg, &ninfo) < 0)
    135 			return 0;
    136 
    137 		tprints(", {useecc=");
    138 		printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
    139 		tprintf(", eccbytes=%#" PRIx32, ninfo.eccbytes);
    140 
    141 		tprints(", oobfree={");
    142 		for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
    143 			if (i)
    144 				tprints("}, ");
    145 			tprints("{");
    146 			for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
    147 				if (j)
    148 					tprints(", ");
    149 				tprintf("%#" PRIx32, ninfo.oobfree[i][j]);
    150 			}
    151 		}
    152 
    153 		tprints("}}, eccpos={");
    154 		for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
    155 			if (i)
    156 				tprints(", ");
    157 			tprintf("%#" PRIx32, ninfo.eccpos[i]);
    158 		}
    159 
    160 		tprints("}");
    161 		return 1;
    162 
    163 	case OTPGETREGIONINFO:
    164 	case OTPLOCK:
    165 		if (!verbose(tcp) || umove(tcp, arg, &oinfo) < 0)
    166 			return 0;
    167 
    168 		tprintf(", {start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
    169 			oinfo.start, oinfo.length, oinfo.locked);
    170 		return 1;
    171 
    172 	case ECCGETLAYOUT:
    173 		if (!verbose(tcp) || umove(tcp, arg, &nlay) < 0)
    174 			return 0;
    175 
    176 		tprintf(", {eccbytes=%#" PRIx32 ", eccpos={", nlay.eccbytes);
    177 		for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
    178 			if (i)
    179 				tprints(", ");
    180 			tprintf("%#" PRIx32, nlay.eccpos[i]);
    181 		}
    182 		tprintf("}, oobavail=%#" PRIx32 ", oobfree={", nlay.oobavail);
    183 		for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
    184 			if (i)
    185 				tprints(", ");
    186 			tprintf("{offset=%#" PRIx32 ", length=%#" PRIx32 "}",
    187 				nlay.oobfree[i].offset, nlay.oobfree[i].length);
    188 		}
    189 		tprints("}");
    190 		return 1;
    191 
    192 	case ECCGETSTATS:
    193 		if (!verbose(tcp) || umove(tcp, arg, &estat) < 0)
    194 			return 0;
    195 
    196 		tprintf(", {corrected=%#" PRIx32 ", failed=%#" PRIx32,
    197 			estat.corrected, estat.failed);
    198 		tprintf(", badblocks=%#" PRIx32 ", bbtblocks=%#" PRIx32 "}",
    199 			estat.badblocks, estat.bbtblocks);
    200 		return 1;
    201 
    202 	case MEMWRITE:
    203 		if (!verbose(tcp) || umove(tcp, arg, &mreq) < 0)
    204 			return 0;
    205 
    206 		tprintf(", {start=%#" PRIx64 ", len=%#" PRIx64,
    207 			(uint64_t) mreq.start, (uint64_t) mreq.len);
    208 		tprintf(", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64,
    209 			(uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data);
    210 		tprintf(", usr_oob=%#" PRIx64 ", mode=",
    211 			(uint64_t) mreq.usr_oob);
    212 		printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
    213 		tprints(", padding=...}");
    214 		return 1;
    215 
    216 	case OTPSELECT:
    217 		if (!verbose(tcp) || umove(tcp, arg, &i) < 0)
    218 			return 0;
    219 
    220 		tprints(", [");
    221 		printxval(mtd_otp_options, i, "MTD_OTP_???");
    222 		tprints("]");
    223 		return 1;
    224 
    225 	case MEMGETBADBLOCK:
    226 	case MEMSETBADBLOCK:
    227 		if (!verbose(tcp))
    228 			return 0;
    229 
    230 		tprints(", ");
    231 		print_loff_t(tcp, arg);
    232 		return 1;
    233 
    234 	case OTPGETREGIONCOUNT:
    235 		if (!verbose(tcp) || umove(tcp, arg, &i) < 0)
    236 			return 0;
    237 
    238 		tprintf(", [%d]", i);
    239 		return 1;
    240 
    241 	case MTDFILEMODE:
    242 		/* XXX: process return value as enum mtd_file_modes */
    243 
    244 	case MEMGETREGIONCOUNT:
    245 		/* These ones take simple args, so let default printer handle it */
    246 
    247 	default:
    248 		return 0;
    249 	}
    250 }
    251 
    252 #include "xlat/ubi_volume_types.h"
    253 #include "xlat/ubi_volume_props.h"
    254 
    255 int ubi_ioctl(struct tcb *tcp, long code, long arg)
    256 {
    257 	struct ubi_mkvol_req mkvol;
    258 	struct ubi_rsvol_req rsvol;
    259 	struct ubi_rnvol_req rnvol;
    260 	struct ubi_attach_req attach;
    261 	struct ubi_map_req map;
    262 	struct ubi_set_vol_prop_req prop;
    263 	/* 4*(n-1) + 3 for quotes and NUL */
    264 	char vol_name[(UBI_MAX_VOLUME_NAME + 1) * 4];
    265 	int ret;
    266 
    267 	if (entering(tcp))
    268 		return 0;
    269 
    270 	switch (code) {
    271 	case UBI_IOCMKVOL:
    272 		if (!verbose(tcp) || umove(tcp, arg, &mkvol) < 0)
    273 			return 0;
    274 
    275 		tprintf(", {vol_id=%" PRIi32 ", alignment=%" PRIi32
    276 			", bytes=%" PRIi64 ", vol_type=", mkvol.vol_id,
    277 			mkvol.alignment, (int64_t)mkvol.bytes);
    278 		printxval(ubi_volume_types, mkvol.vol_type, "UBI_???_VOLUME");
    279 		ret = string_quote(mkvol.name, vol_name, -1,
    280 			CLAMP(mkvol.name_len, 0, UBI_MAX_VOLUME_NAME));
    281 		tprintf(", name_len=%" PRIi16 ", name=%s%s",
    282 			mkvol.name_len, vol_name, ret ? "..." : "");
    283 		tprints("}");
    284 		return 1;
    285 
    286 	case UBI_IOCRSVOL:
    287 		if (!verbose(tcp) || umove(tcp, arg, &rsvol) < 0)
    288 			return 0;
    289 
    290 		tprintf(", {vol_id=%" PRIi32 ", bytes=%" PRIi64 "}",
    291 			rsvol.vol_id, (int64_t)rsvol.bytes);
    292 		return 1;
    293 
    294 	case UBI_IOCRNVOL: {
    295 		__s32 c;
    296 
    297 		if (!verbose(tcp) || umove(tcp, arg, &rnvol) < 0)
    298 			return 0;
    299 
    300 		tprintf(", {count=%" PRIi32 ", ents=[", rnvol.count);
    301 		for (c = 0; c < CLAMP(rnvol.count, 0, UBI_MAX_RNVOL); ++c) {
    302 			if (c)
    303 				tprints(", ");
    304 			ret = string_quote(rnvol.ents[c].name, vol_name, -1,
    305 				CLAMP(rnvol.ents[c].name_len, 0, UBI_MAX_VOLUME_NAME));
    306 			tprintf("{vol_id=%" PRIi32 ", name_len=%" PRIi16
    307 				", name=%s%s}", rnvol.ents[c].vol_id,
    308 				rnvol.ents[c].name_len, vol_name, ret ? "..." : "");
    309 		}
    310 		tprints("]}");
    311 		return 1;
    312 	}
    313 
    314 	case UBI_IOCVOLUP: {
    315 		__s64 bytes;
    316 
    317 		if (!verbose(tcp) || umove(tcp, arg, &bytes) < 0)
    318 			return 0;
    319 
    320 		tprintf(", %" PRIi64, (int64_t)bytes);
    321 		return 1;
    322 	}
    323 
    324 	case UBI_IOCATT:
    325 		if (!verbose(tcp) || umove(tcp, arg, &attach) < 0)
    326 			return 0;
    327 
    328 		tprintf(", {ubi_num=%" PRIi32 ", mtd_num=%" PRIi32
    329 			", vid_hdr_offset=%" PRIi32
    330 			", max_beb_per1024=%" PRIi16 "}",
    331 			attach.ubi_num, attach.mtd_num,
    332 			attach.vid_hdr_offset, attach.max_beb_per1024);
    333 		return 1;
    334 
    335 	case UBI_IOCEBMAP:
    336 		if (!verbose(tcp) || umove(tcp, arg, &map) < 0)
    337 			return 0;
    338 
    339 		tprintf(", {lnum=%" PRIi32 ", dtype=%" PRIi8 "}",
    340 			map.lnum, map.dtype);
    341 		return 1;
    342 
    343 	case UBI_IOCSETVOLPROP:
    344 		if (!verbose(tcp) || umove(tcp, arg, &prop) < 0)
    345 			return 0;
    346 
    347 		tprints(", {property=");
    348 		printxval(ubi_volume_props, prop.property, "UBI_VOL_PROP_???");
    349 		tprintf(", value=%#" PRIx64 "}", (uint64_t)prop.value);
    350 		return 1;
    351 
    352 	case UBI_IOCRMVOL:
    353 	case UBI_IOCDET:
    354 	case UBI_IOCEBER:
    355 	case UBI_IOCEBCH:
    356 	case UBI_IOCEBUNMAP:
    357 	case UBI_IOCEBISMAP:
    358 		/* These ones take simple args, so let default printer handle it */
    359 
    360 	default:
    361 		return 0;
    362 	}
    363 }
    364