]> granicus.if.org Git - strace/blobdiff - mtd.c
travis: add build environment information to the travis log
[strace] / mtd.c
diff --git a/mtd.c b/mtd.c
index f908b9f639d791ae4c8822b0bd67e9cae835e1f6..b0468595a5167e97bf298a62a3c24ed2208ad063 100644 (file)
--- a/mtd.c
+++ b/mtd.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012 Mike Frysinger <vapier@gentoo.org>
+ * Copyright (c) 2012-2017 The strace developers.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +27,8 @@
 
 #include "defs.h"
 
+#include DEF_MPERS_TYPE(struct_mtd_oob_buf)
+
 #include <linux/ioctl.h>
 
 /* The mtd api changes quickly, so we have to keep a local copy */
 # include <mtd/mtd-abi.h>
 #endif
 
+typedef struct mtd_oob_buf struct_mtd_oob_buf;
+
+#include MPERS_DEFS
+
 #include "xlat/mtd_mode_options.h"
 #include "xlat/mtd_file_mode_options.h"
 #include "xlat/mtd_type_options.h"
 #include "xlat/mtd_otp_options.h"
 #include "xlat/mtd_nandecc_options.h"
 
-int
-mtd_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
+static void
+decode_erase_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
 {
-       if (!verbose(tcp))
-               return RVAL_DECODED;
+       struct erase_info_user einfo;
 
-       switch (code) {
-       case MEMERASE:
-       case MEMLOCK:
-       case MEMUNLOCK:
-       case MEMISLOCKED: {
-               struct erase_info_user einfo;
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &einfo))
+               return;
 
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &einfo))
-                       break;
+       tprintf("{start=%#x, length=%#x}", einfo.start, einfo.length);
+}
 
-               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 "}",
-                       einfo.start, einfo.length);
-               break;
-       }
+static void
+decode_erase_info_user64(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct erase_info_user64 einfo64;
 
-       case MEMERASE64: {
-               struct erase_info_user64 einfo64;
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &einfo64))
+               return;
 
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &einfo64))
-                       break;
+       tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
+               (uint64_t) einfo64.start, (uint64_t) einfo64.length);
+}
 
-               tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
-                       (uint64_t) einfo64.start, (uint64_t) einfo64.length);
-               break;
-       }
+static void
+decode_mtd_oob_buf(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct_mtd_oob_buf mbuf;
 
-       case MEMWRITEOOB:
-       case MEMREADOOB: {
-               struct mtd_oob_buf mbuf;
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &mbuf))
+               return;
 
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &mbuf))
-                       break;
+       tprintf("{start=%#x, length=%#x, ptr=", mbuf.start, mbuf.length);
+       printaddr(ptr_to_kulong(mbuf.ptr));
+       tprints("}");
+}
 
-               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", ptr=...}",
-                       mbuf.start, mbuf.length);
-               break;
-       }
+static void
+decode_mtd_oob_buf64(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct mtd_oob_buf64 mbuf64;
 
-       case MEMWRITEOOB64:
-       case MEMREADOOB64: {
-               struct mtd_oob_buf64 mbuf64;
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &mbuf64))
+               return;
 
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &mbuf64))
-                       break;
+       tprintf("{start=%#" PRIx64 ", length=%#x, usr_ptr=%#" PRIx64 "}",
+               (uint64_t) mbuf64.start, mbuf64.length,
+               (uint64_t) mbuf64.usr_ptr);
+}
 
-               tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 ", ptr=...}",
-                       (uint64_t) mbuf64.start, (uint64_t) mbuf64.length);
-               break;
+static void
+decode_otp_info(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct otp_info oinfo;
+
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &oinfo))
+               return;
+
+       tprintf("{start=%#x, length=%#x, locked=%u}",
+               oinfo.start, oinfo.length, oinfo.locked);
+}
+
+static void
+decode_otp_select(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       unsigned int i;
+
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &i))
+               return;
+
+       tprints("[");
+       printxval(mtd_otp_options, i, "MTD_OTP_???");
+       tprints("]");
+}
+
+static void
+decode_mtd_write_req(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct mtd_write_req mreq;
+
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &mreq))
+               return;
+
+       tprintf("{start=%#" PRIx64 ", len=%#" PRIx64
+               ", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64
+               ", usr_oob=%#" PRIx64 ", mode=",
+               (uint64_t) mreq.start, (uint64_t) mreq.len,
+               (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data,
+               (uint64_t) mreq.usr_oob);
+       printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
+       tprints("}");
+}
+
+static void
+decode_mtd_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct mtd_info_user minfo;
+
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &minfo))
+               return;
+
+       tprints("{type=");
+       printxval(mtd_type_options, minfo.type, "MTD_???");
+       tprints(", flags=");
+       printflags(mtd_flags_options, minfo.flags, "MTD_???");
+       tprintf(", size=%#x, erasesize=%#x, writesize=%#x, oobsize=%#x"
+               ", padding=%#" PRIx64 "}",
+               minfo.size, minfo.erasesize, minfo.writesize, minfo.oobsize,
+               (uint64_t) minfo.padding);
+}
+
+static void
+decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct nand_oobinfo ninfo;
+       unsigned int i, j;
+
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &ninfo))
+               return;
+
+       tprints("{useecc=");
+       printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
+       tprintf(", eccbytes=%#x", ninfo.eccbytes);
+
+       tprints(", oobfree={");
+       for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
+               if (i)
+                       tprints("}, ");
+               tprints("{");
+               for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
+                       if (j)
+                               tprints(", ");
+                       tprintf("%#x", ninfo.oobfree[i][j]);
+               }
        }
 
-       case MEMGETREGIONINFO: {
-               struct region_info_user rinfo;
+       tprints("}}, eccpos={");
+       for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
+               if (i)
+                       tprints(", ");
+               tprintf("%#x", ninfo.eccpos[i]);
+       }
 
-               if (entering(tcp)) {
+       tprints("}");
+}
+
+static void
+decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct nand_ecclayout_user nlay;
+       unsigned int i;
+
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &nlay))
+               return;
+
+       tprintf("{eccbytes=%#x, eccpos={", nlay.eccbytes);
+       for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
+               if (i)
                        tprints(", ");
-                       if (umove_or_printaddr(tcp, arg, &rinfo))
-                               break;
-                       tprintf("{regionindex=%#x", rinfo.regionindex);
-                       return 1;
-               } else {
-                       if (syserror(tcp)) {
-                               tprints("}");
-                               break;
-                       }
-                       if (umove(tcp, arg, &rinfo) < 0) {
-                               tprints(", ???}");
-                               break;
-                       }
-                       tprintf(", offset=%#x, erasesize=%#x, numblocks=%#x}",
-                               rinfo.offset, rinfo.erasesize, rinfo.numblocks);
-                       break;
-               }
+               tprintf("%#x", nlay.eccpos[i]);
        }
+       tprintf("}, oobavail=%#x, oobfree={", nlay.oobavail);
+       for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
+               if (i)
+                       tprints(", ");
+               tprintf("{offset=%#x, length=%#x}",
+                       nlay.oobfree[i].offset, nlay.oobfree[i].length);
+       }
+       tprints("}");
+}
 
-       case OTPLOCK: {
-               struct otp_info oinfo;
+static void
+decode_mtd_ecc_stats(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct mtd_ecc_stats es;
 
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &oinfo))
-                       break;
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &es))
+               return;
+
+       tprintf("{corrected=%#x, failed=%#x, badblocks=%#x, bbtblocks=%#x}",
+               es.corrected, es.failed, es.badblocks, es.bbtblocks);
+}
 
-               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
-                       oinfo.start, oinfo.length, oinfo.locked);
+MPERS_PRINTER_DECL(int, mtd_ioctl, struct tcb *const tcp,
+                  const unsigned int code, const kernel_ulong_t arg)
+{
+       switch (code) {
+       case MEMERASE:
+       case MEMLOCK:
+       case MEMUNLOCK:
+       case MEMISLOCKED:
+               decode_erase_info_user(tcp, arg);
                break;
-       }
 
-       case MEMWRITE: {
-               struct mtd_write_req mreq;
+       case MEMERASE64:
+               decode_erase_info_user64(tcp, arg);
+               break;
 
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &mreq))
-                       break;
+       case MEMWRITEOOB:
+       case MEMREADOOB:
+               decode_mtd_oob_buf(tcp, arg);
+               break;
 
-               tprintf("{start=%#" PRIx64 ", len=%#" PRIx64,
-                       (uint64_t) mreq.start, (uint64_t) mreq.len);
-               tprintf(", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64,
-                       (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data);
-               tprintf(", usr_oob=%#" PRIx64 ", mode=",
-                       (uint64_t) mreq.usr_oob);
-               printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
-               tprints(", padding=...}");
+       case MEMWRITEOOB64:
+       case MEMREADOOB64:
+               decode_mtd_oob_buf64(tcp, arg);
                break;
-       }
 
-       case OTPSELECT: {
-               unsigned int i;
+       case MEMWRITE:
+               decode_mtd_write_req(tcp, arg);
+               break;
 
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &i))
-                       break;
+       case OTPGETREGIONINFO:
+               if (entering(tcp))
+                       return 0;
+               /* fall through */
+       case OTPLOCK:
+               decode_otp_info(tcp, arg);
+               break;
 
-               tprints("[");
-               printxval(mtd_otp_options, i, "MTD_OTP_???");
-               tprints("]");
+       case OTPSELECT:
+               decode_otp_select(tcp, arg);
                break;
-       }
 
        case MTDFILEMODE:
                tprints(", ");
-               printxval_long(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
+               printxval64(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
                break;
 
        case MEMGETBADBLOCK:
@@ -181,133 +295,33 @@ mtd_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                printnum_int64(tcp, arg, "%" PRIu64);
                break;
 
-       case MEMGETINFO: {
-               struct mtd_info_user minfo;
-
+       case MEMGETINFO:
                if (entering(tcp))
                        return 0;
-
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &minfo))
-                       break;
-
-               tprints("{type=");
-               printxval(mtd_type_options, minfo.type, "MTD_???");
-               tprints(", flags=");
-               printflags(mtd_flags_options, minfo.flags, "MTD_???");
-               tprintf(", size=%#" PRIx32 ", erasesize=%#" PRIx32,
-                       minfo.size, minfo.erasesize);
-               tprintf(", writesize=%#" PRIx32 ", oobsize=%#" PRIx32,
-                       minfo.writesize, minfo.oobsize);
-               tprintf(", padding=%#" PRIx64 "}",
-                       (uint64_t) minfo.padding);
+               decode_mtd_info_user(tcp, arg);
                break;
-       }
-
-       case MEMGETOOBSEL: {
-               struct nand_oobinfo ninfo;
-               unsigned int i;
 
+       case MEMGETOOBSEL:
                if (entering(tcp))
                        return 0;
-
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &ninfo))
-                       break;
-
-               tprints("{useecc=");
-               printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
-               tprintf(", eccbytes=%#" PRIx32, ninfo.eccbytes);
-
-               tprints(", oobfree={");
-               for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
-                       unsigned int j;
-
-                       if (i)
-                               tprints("}, ");
-                       tprints("{");
-                       for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
-                               if (j)
-                                       tprints(", ");
-                               tprintf("%#" PRIx32, ninfo.oobfree[i][j]);
-                       }
-               }
-
-               tprints("}}, eccpos={");
-               for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
-                       if (i)
-                               tprints(", ");
-                       tprintf("%#" PRIx32, ninfo.eccpos[i]);
-               }
-
-               tprints("}");
+               decode_nand_oobinfo(tcp, arg);
                break;
-       }
-
-       case OTPGETREGIONINFO: {
-               struct otp_info oinfo;
 
+       case ECCGETLAYOUT:
                if (entering(tcp))
                        return 0;
-
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &oinfo))
-                       break;
-
-               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
-                       oinfo.start, oinfo.length, oinfo.locked);
+               decode_nand_ecclayout_user(tcp, arg);
                break;
-       }
-
-       case ECCGETLAYOUT: {
-               struct nand_ecclayout_user nlay;
-               unsigned int i;
 
+       case ECCGETSTATS:
                if (entering(tcp))
                        return 0;
-
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &nlay))
-                       break;
-
-               tprintf("{eccbytes=%#" PRIx32 ", eccpos={", nlay.eccbytes);
-               for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
-                       if (i)
-                               tprints(", ");
-                       tprintf("%#" PRIx32, nlay.eccpos[i]);
-               }
-               tprintf("}, oobavail=%#" PRIx32 ", oobfree={", nlay.oobavail);
-               for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
-                       if (i)
-                               tprints(", ");
-                       tprintf("{offset=%#" PRIx32 ", length=%#" PRIx32 "}",
-                               nlay.oobfree[i].offset, nlay.oobfree[i].length);
-               }
-               tprints("}");
+               decode_mtd_ecc_stats(tcp, arg);
                break;
-       }
-
-       case ECCGETSTATS: {
-               struct mtd_ecc_stats estat;
-
-               if (entering(tcp))
-                       return 0;
-
-               tprints(", ");
-               if (umove_or_printaddr(tcp, arg, &estat))
-                       break;
-
-               tprintf("{corrected=%#" PRIx32 ", failed=%#" PRIx32,
-                       estat.corrected, estat.failed);
-               tprintf(", badblocks=%#" PRIx32 ", bbtblocks=%#" PRIx32 "}",
-                       estat.badblocks, estat.bbtblocks);
-               break;
-       }
 
        case OTPGETREGIONCOUNT:
                if (entering(tcp))
                        return 0;
-
                tprints(", ");
                printnum_int(tcp, arg, "%u");
                break;
@@ -315,11 +329,33 @@ mtd_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
        case MEMGETREGIONCOUNT:
                if (entering(tcp))
                        return 0;
-
                tprints(", ");
                printnum_int(tcp, arg, "%d");
                break;
 
+       case MEMGETREGIONINFO:
+               if (entering(tcp)) {
+                       struct region_info_user rinfo;
+
+                       tprints(", ");
+                       if (umove_or_printaddr(tcp, arg, &rinfo))
+                               break;
+                       tprintf("{regionindex=%#x", rinfo.regionindex);
+                       return 0;
+               } else {
+                       struct region_info_user rinfo;
+
+                       if (!syserror(tcp) && !umove(tcp, arg, &rinfo))
+                               tprintf(", offset=%#x"
+                                       ", erasesize=%#x"
+                                       ", numblocks=%#x}",
+                                       rinfo.offset,
+                                       rinfo.erasesize,
+                                       rinfo.numblocks);
+                       tprints("}");
+                       break;
+               }
+
        default:
                return RVAL_DECODED;
        }