Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2012 Mike Frysinger <vapier (at) gentoo.org>
      3  * Copyright (c) 2012-2017 The strace developers.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. The name of the author may not be used to endorse or promote products
     14  *    derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "defs.h"
     29 
     30 #include DEF_MPERS_TYPE(struct_mtd_oob_buf)
     31 
     32 #include <linux/ioctl.h>
     33 
     34 /* The mtd api changes quickly, so we have to keep a local copy */
     35 #include <linux/version.h>
     36 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
     37 # include "mtd-abi.h"
     38 #else
     39 # include <mtd/mtd-abi.h>
     40 #endif
     41 
     42 typedef struct mtd_oob_buf struct_mtd_oob_buf;
     43 
     44 #include MPERS_DEFS
     45 
     46 #include "xlat/mtd_mode_options.h"
     47 #include "xlat/mtd_file_mode_options.h"
     48 #include "xlat/mtd_type_options.h"
     49 #include "xlat/mtd_flags_options.h"
     50 #include "xlat/mtd_otp_options.h"
     51 #include "xlat/mtd_nandecc_options.h"
     52 
     53 static void
     54 decode_erase_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
     55 {
     56 	struct erase_info_user einfo;
     57 
     58 	tprints(", ");
     59 	if (umove_or_printaddr(tcp, addr, &einfo))
     60 		return;
     61 
     62 	tprintf("{start=%#x, length=%#x}", einfo.start, einfo.length);
     63 }
     64 
     65 static void
     66 decode_erase_info_user64(struct tcb *const tcp, const kernel_ulong_t addr)
     67 {
     68 	struct erase_info_user64 einfo64;
     69 
     70 	tprints(", ");
     71 	if (umove_or_printaddr(tcp, addr, &einfo64))
     72 		return;
     73 
     74 	tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
     75 		(uint64_t) einfo64.start, (uint64_t) einfo64.length);
     76 }
     77 
     78 static void
     79 decode_mtd_oob_buf(struct tcb *const tcp, const kernel_ulong_t addr)
     80 {
     81 	struct_mtd_oob_buf mbuf;
     82 
     83 	tprints(", ");
     84 	if (umove_or_printaddr(tcp, addr, &mbuf))
     85 		return;
     86 
     87 	tprintf("{start=%#x, length=%#x, ptr=", mbuf.start, mbuf.length);
     88 	printaddr(ptr_to_kulong(mbuf.ptr));
     89 	tprints("}");
     90 }
     91 
     92 static void
     93 decode_mtd_oob_buf64(struct tcb *const tcp, const kernel_ulong_t addr)
     94 {
     95 	struct mtd_oob_buf64 mbuf64;
     96 
     97 	tprints(", ");
     98 	if (umove_or_printaddr(tcp, addr, &mbuf64))
     99 		return;
    100 
    101 	tprintf("{start=%#" PRIx64 ", length=%#x, usr_ptr=%#" PRIx64 "}",
    102 		(uint64_t) mbuf64.start, mbuf64.length,
    103 		(uint64_t) mbuf64.usr_ptr);
    104 }
    105 
    106 static void
    107 decode_otp_info(struct tcb *const tcp, const kernel_ulong_t addr)
    108 {
    109 	struct otp_info oinfo;
    110 
    111 	tprints(", ");
    112 	if (umove_or_printaddr(tcp, addr, &oinfo))
    113 		return;
    114 
    115 	tprintf("{start=%#x, length=%#x, locked=%u}",
    116 		oinfo.start, oinfo.length, oinfo.locked);
    117 }
    118 
    119 static void
    120 decode_otp_select(struct tcb *const tcp, const kernel_ulong_t addr)
    121 {
    122 	unsigned int i;
    123 
    124 	tprints(", ");
    125 	if (umove_or_printaddr(tcp, addr, &i))
    126 		return;
    127 
    128 	tprints("[");
    129 	printxval(mtd_otp_options, i, "MTD_OTP_???");
    130 	tprints("]");
    131 }
    132 
    133 static void
    134 decode_mtd_write_req(struct tcb *const tcp, const kernel_ulong_t addr)
    135 {
    136 	struct mtd_write_req mreq;
    137 
    138 	tprints(", ");
    139 	if (umove_or_printaddr(tcp, addr, &mreq))
    140 		return;
    141 
    142 	tprintf("{start=%#" PRIx64 ", len=%#" PRIx64
    143 		", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64
    144 		", usr_oob=%#" PRIx64 ", mode=",
    145 		(uint64_t) mreq.start, (uint64_t) mreq.len,
    146 		(uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data,
    147 		(uint64_t) mreq.usr_oob);
    148 	printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
    149 	tprints("}");
    150 }
    151 
    152 static void
    153 decode_mtd_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
    154 {
    155 	struct mtd_info_user minfo;
    156 
    157 	tprints(", ");
    158 	if (umove_or_printaddr(tcp, addr, &minfo))
    159 		return;
    160 
    161 	tprints("{type=");
    162 	printxval(mtd_type_options, minfo.type, "MTD_???");
    163 	tprints(", flags=");
    164 	printflags(mtd_flags_options, minfo.flags, "MTD_???");
    165 	tprintf(", size=%#x, erasesize=%#x, writesize=%#x, oobsize=%#x"
    166 		", padding=%#" PRIx64 "}",
    167 		minfo.size, minfo.erasesize, minfo.writesize, minfo.oobsize,
    168 		(uint64_t) minfo.padding);
    169 }
    170 
    171 static void
    172 decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr)
    173 {
    174 	struct nand_oobinfo ninfo;
    175 	unsigned int i, j;
    176 
    177 	tprints(", ");
    178 	if (umove_or_printaddr(tcp, addr, &ninfo))
    179 		return;
    180 
    181 	tprints("{useecc=");
    182 	printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
    183 	tprintf(", eccbytes=%#x", ninfo.eccbytes);
    184 
    185 	tprints(", oobfree={");
    186 	for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
    187 		if (i)
    188 			tprints("}, ");
    189 		tprints("{");
    190 		for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
    191 			if (j)
    192 				tprints(", ");
    193 			tprintf("%#x", ninfo.oobfree[i][j]);
    194 		}
    195 	}
    196 
    197 	tprints("}}, eccpos={");
    198 	for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
    199 		if (i)
    200 			tprints(", ");
    201 		tprintf("%#x", ninfo.eccpos[i]);
    202 	}
    203 
    204 	tprints("}");
    205 }
    206 
    207 static void
    208 decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr)
    209 {
    210 	struct nand_ecclayout_user nlay;
    211 	unsigned int i;
    212 
    213 	tprints(", ");
    214 	if (umove_or_printaddr(tcp, addr, &nlay))
    215 		return;
    216 
    217 	tprintf("{eccbytes=%#x, eccpos={", nlay.eccbytes);
    218 	for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
    219 		if (i)
    220 			tprints(", ");
    221 		tprintf("%#x", nlay.eccpos[i]);
    222 	}
    223 	tprintf("}, oobavail=%#x, oobfree={", nlay.oobavail);
    224 	for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
    225 		if (i)
    226 			tprints(", ");
    227 		tprintf("{offset=%#x, length=%#x}",
    228 			nlay.oobfree[i].offset, nlay.oobfree[i].length);
    229 	}
    230 	tprints("}");
    231 }
    232 
    233 static void
    234 decode_mtd_ecc_stats(struct tcb *const tcp, const kernel_ulong_t addr)
    235 {
    236 	struct mtd_ecc_stats es;
    237 
    238 	tprints(", ");
    239 	if (umove_or_printaddr(tcp, addr, &es))
    240 		return;
    241 
    242 	tprintf("{corrected=%#x, failed=%#x, badblocks=%#x, bbtblocks=%#x}",
    243 		es.corrected, es.failed, es.badblocks, es.bbtblocks);
    244 }
    245 
    246 MPERS_PRINTER_DECL(int, mtd_ioctl, struct tcb *const tcp,
    247 		   const unsigned int code, const kernel_ulong_t arg)
    248 {
    249 	switch (code) {
    250 	case MEMERASE:
    251 	case MEMLOCK:
    252 	case MEMUNLOCK:
    253 	case MEMISLOCKED:
    254 		decode_erase_info_user(tcp, arg);
    255 		break;
    256 
    257 	case MEMERASE64:
    258 		decode_erase_info_user64(tcp, arg);
    259 		break;
    260 
    261 	case MEMWRITEOOB:
    262 	case MEMREADOOB:
    263 		decode_mtd_oob_buf(tcp, arg);
    264 		break;
    265 
    266 	case MEMWRITEOOB64:
    267 	case MEMREADOOB64:
    268 		decode_mtd_oob_buf64(tcp, arg);
    269 		break;
    270 
    271 	case MEMWRITE:
    272 		decode_mtd_write_req(tcp, arg);
    273 		break;
    274 
    275 	case OTPGETREGIONINFO:
    276 		if (entering(tcp))
    277 			return 0;
    278 		/* fall through */
    279 	case OTPLOCK:
    280 		decode_otp_info(tcp, arg);
    281 		break;
    282 
    283 	case OTPSELECT:
    284 		decode_otp_select(tcp, arg);
    285 		break;
    286 
    287 	case MTDFILEMODE:
    288 		tprints(", ");
    289 		printxval64(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
    290 		break;
    291 
    292 	case MEMGETBADBLOCK:
    293 	case MEMSETBADBLOCK:
    294 		tprints(", ");
    295 		printnum_int64(tcp, arg, "%" PRIu64);
    296 		break;
    297 
    298 	case MEMGETINFO:
    299 		if (entering(tcp))
    300 			return 0;
    301 		decode_mtd_info_user(tcp, arg);
    302 		break;
    303 
    304 	case MEMGETOOBSEL:
    305 		if (entering(tcp))
    306 			return 0;
    307 		decode_nand_oobinfo(tcp, arg);
    308 		break;
    309 
    310 	case ECCGETLAYOUT:
    311 		if (entering(tcp))
    312 			return 0;
    313 		decode_nand_ecclayout_user(tcp, arg);
    314 		break;
    315 
    316 	case ECCGETSTATS:
    317 		if (entering(tcp))
    318 			return 0;
    319 		decode_mtd_ecc_stats(tcp, arg);
    320 		break;
    321 
    322 	case OTPGETREGIONCOUNT:
    323 		if (entering(tcp))
    324 			return 0;
    325 		tprints(", ");
    326 		printnum_int(tcp, arg, "%u");
    327 		break;
    328 
    329 	case MEMGETREGIONCOUNT:
    330 		if (entering(tcp))
    331 			return 0;
    332 		tprints(", ");
    333 		printnum_int(tcp, arg, "%d");
    334 		break;
    335 
    336 	case MEMGETREGIONINFO:
    337 		if (entering(tcp)) {
    338 			struct region_info_user rinfo;
    339 
    340 			tprints(", ");
    341 			if (umove_or_printaddr(tcp, arg, &rinfo))
    342 				break;
    343 			tprintf("{regionindex=%#x", rinfo.regionindex);
    344 			return 0;
    345 		} else {
    346 			struct region_info_user rinfo;
    347 
    348 			if (!syserror(tcp) && !umove(tcp, arg, &rinfo))
    349 				tprintf(", offset=%#x"
    350 					", erasesize=%#x"
    351 					", numblocks=%#x}",
    352 					rinfo.offset,
    353 					rinfo.erasesize,
    354 					rinfo.numblocks);
    355 			tprints("}");
    356 			break;
    357 		}
    358 
    359 	default:
    360 		return RVAL_DECODED;
    361 	}
    362 
    363 	return RVAL_DECODED | 1;
    364 }
    365