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