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 <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 #ifdef UBI_IOCVOLCRBLK
    483 	case UBI_IOCVOLCRBLK:
    484 #endif
    485 #ifdef UBI_IOCVOLRMBLK
    486 	case UBI_IOCVOLRMBLK:
    487 #endif
    488 		/* no arguments */
    489 		break;
    490 
    491 	default:
    492 		return RVAL_DECODED;
    493 	}
    494 
    495 	return RVAL_DECODED | 1;
    496 }
    497