Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mtd.c 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. * Copyright (c) 2012 Mike Frysinger <vapier@gentoo.org>
  3. * Copyright (c) 2012-2018 The strace developers.
  4. *
  5. * SPDX-License-Identifier: LGPL-2.1-or-later
  6. */
  7. #include "defs.h"
  8. #ifdef HAVE_STRUCT_MTD_WRITE_REQ
  9. # include DEF_MPERS_TYPE(struct_mtd_oob_buf)
  10. # include <linux/ioctl.h>
  11. # include <mtd/mtd-abi.h>
  12. typedef struct mtd_oob_buf struct_mtd_oob_buf;
  13. #endif /* HAVE_STRUCT_MTD_WRITE_REQ */
  14. #include MPERS_DEFS
  15. #ifdef HAVE_STRUCT_MTD_WRITE_REQ
  16. # include "xlat/mtd_mode_options.h"
  17. # include "xlat/mtd_file_mode_options.h"
  18. # include "xlat/mtd_type_options.h"
  19. # include "xlat/mtd_flags_options.h"
  20. # include "xlat/mtd_otp_options.h"
  21. # include "xlat/mtd_nandecc_options.h"
  22. static void
  23. decode_erase_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
  24. {
  25. struct erase_info_user einfo;
  26. tprints(", ");
  27. if (umove_or_printaddr(tcp, addr, &einfo))
  28. return;
  29. tprintf("{start=%#x, length=%#x}", einfo.start, einfo.length);
  30. }
  31. static void
  32. decode_erase_info_user64(struct tcb *const tcp, const kernel_ulong_t addr)
  33. {
  34. struct erase_info_user64 einfo64;
  35. tprints(", ");
  36. if (umove_or_printaddr(tcp, addr, &einfo64))
  37. return;
  38. tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
  39. (uint64_t) einfo64.start, (uint64_t) einfo64.length);
  40. }
  41. static void
  42. decode_mtd_oob_buf(struct tcb *const tcp, const kernel_ulong_t addr)
  43. {
  44. struct_mtd_oob_buf mbuf;
  45. tprints(", ");
  46. if (umove_or_printaddr(tcp, addr, &mbuf))
  47. return;
  48. tprintf("{start=%#x, length=%#x, ptr=", mbuf.start, mbuf.length);
  49. printaddr(ptr_to_kulong(mbuf.ptr));
  50. tprints("}");
  51. }
  52. static void
  53. decode_mtd_oob_buf64(struct tcb *const tcp, const kernel_ulong_t addr)
  54. {
  55. struct mtd_oob_buf64 mbuf64;
  56. tprints(", ");
  57. if (umove_or_printaddr(tcp, addr, &mbuf64))
  58. return;
  59. tprintf("{start=%#" PRIx64 ", length=%#x, usr_ptr=%#" PRIx64 "}",
  60. (uint64_t) mbuf64.start, mbuf64.length,
  61. (uint64_t) mbuf64.usr_ptr);
  62. }
  63. static void
  64. decode_otp_info(struct tcb *const tcp, const kernel_ulong_t addr)
  65. {
  66. struct otp_info oinfo;
  67. tprints(", ");
  68. if (umove_or_printaddr(tcp, addr, &oinfo))
  69. return;
  70. tprintf("{start=%#x, length=%#x, locked=%u}",
  71. oinfo.start, oinfo.length, oinfo.locked);
  72. }
  73. static void
  74. decode_otp_select(struct tcb *const tcp, const kernel_ulong_t addr)
  75. {
  76. unsigned int i;
  77. tprints(", ");
  78. if (umove_or_printaddr(tcp, addr, &i))
  79. return;
  80. tprints("[");
  81. printxval(mtd_otp_options, i, "MTD_OTP_???");
  82. tprints("]");
  83. }
  84. static void
  85. decode_mtd_write_req(struct tcb *const tcp, const kernel_ulong_t addr)
  86. {
  87. struct mtd_write_req mreq;
  88. tprints(", ");
  89. if (umove_or_printaddr(tcp, addr, &mreq))
  90. return;
  91. tprintf("{start=%#" PRIx64 ", len=%#" PRIx64
  92. ", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64
  93. ", usr_oob=%#" PRIx64 ", mode=",
  94. (uint64_t) mreq.start, (uint64_t) mreq.len,
  95. (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data,
  96. (uint64_t) mreq.usr_oob);
  97. printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
  98. tprints("}");
  99. }
  100. static void
  101. decode_mtd_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
  102. {
  103. struct mtd_info_user minfo;
  104. tprints(", ");
  105. if (umove_or_printaddr(tcp, addr, &minfo))
  106. return;
  107. tprints("{type=");
  108. printxval(mtd_type_options, minfo.type, "MTD_???");
  109. tprints(", flags=");
  110. printflags(mtd_flags_options, minfo.flags, "MTD_???");
  111. tprintf(", size=%#x, erasesize=%#x, writesize=%#x, oobsize=%#x"
  112. ", padding=%#" PRIx64 "}",
  113. minfo.size, minfo.erasesize, minfo.writesize, minfo.oobsize,
  114. (uint64_t) minfo.padding);
  115. }
  116. static void
  117. decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr)
  118. {
  119. struct nand_oobinfo ninfo;
  120. unsigned int i, j;
  121. tprints(", ");
  122. if (umove_or_printaddr(tcp, addr, &ninfo))
  123. return;
  124. tprints("{useecc=");
  125. printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
  126. tprintf(", eccbytes=%#x", ninfo.eccbytes);
  127. tprints(", oobfree={");
  128. for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
  129. if (i)
  130. tprints("}, ");
  131. tprints("{");
  132. for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) {
  133. if (j)
  134. tprints(", ");
  135. tprintf("%#x", ninfo.oobfree[i][j]);
  136. }
  137. }
  138. tprints("}}, eccpos={");
  139. for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) {
  140. if (i)
  141. tprints(", ");
  142. tprintf("%#x", ninfo.eccpos[i]);
  143. }
  144. tprints("}");
  145. }
  146. static void
  147. decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr)
  148. {
  149. struct nand_ecclayout_user nlay;
  150. unsigned int i;
  151. tprints(", ");
  152. if (umove_or_printaddr(tcp, addr, &nlay))
  153. return;
  154. tprintf("{eccbytes=%#x, eccpos={", nlay.eccbytes);
  155. for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
  156. if (i)
  157. tprints(", ");
  158. tprintf("%#x", nlay.eccpos[i]);
  159. }
  160. tprintf("}, oobavail=%#x, oobfree={", nlay.oobavail);
  161. for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) {
  162. if (i)
  163. tprints(", ");
  164. tprintf("{offset=%#x, length=%#x}",
  165. nlay.oobfree[i].offset, nlay.oobfree[i].length);
  166. }
  167. tprints("}");
  168. }
  169. static void
  170. decode_mtd_ecc_stats(struct tcb *const tcp, const kernel_ulong_t addr)
  171. {
  172. struct mtd_ecc_stats es;
  173. tprints(", ");
  174. if (umove_or_printaddr(tcp, addr, &es))
  175. return;
  176. tprintf("{corrected=%#x, failed=%#x, badblocks=%#x, bbtblocks=%#x}",
  177. es.corrected, es.failed, es.badblocks, es.bbtblocks);
  178. }
  179. MPERS_PRINTER_DECL(int, mtd_ioctl, struct tcb *const tcp,
  180. const unsigned int code, const kernel_ulong_t arg)
  181. {
  182. switch (code) {
  183. case MEMERASE:
  184. case MEMLOCK:
  185. case MEMUNLOCK:
  186. case MEMISLOCKED:
  187. decode_erase_info_user(tcp, arg);
  188. break;
  189. case MEMERASE64:
  190. decode_erase_info_user64(tcp, arg);
  191. break;
  192. case MEMWRITEOOB:
  193. case MEMREADOOB:
  194. decode_mtd_oob_buf(tcp, arg);
  195. break;
  196. case MEMWRITEOOB64:
  197. case MEMREADOOB64:
  198. decode_mtd_oob_buf64(tcp, arg);
  199. break;
  200. case MEMWRITE:
  201. decode_mtd_write_req(tcp, arg);
  202. break;
  203. case OTPGETREGIONINFO:
  204. if (entering(tcp))
  205. return 0;
  206. ATTRIBUTE_FALLTHROUGH;
  207. case OTPLOCK:
  208. decode_otp_info(tcp, arg);
  209. break;
  210. case OTPSELECT:
  211. decode_otp_select(tcp, arg);
  212. break;
  213. case MTDFILEMODE:
  214. tprints(", ");
  215. printxval64(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
  216. break;
  217. case MEMGETBADBLOCK:
  218. case MEMSETBADBLOCK:
  219. tprints(", ");
  220. printnum_int64(tcp, arg, "%" PRIu64);
  221. break;
  222. case MEMGETINFO:
  223. if (entering(tcp))
  224. return 0;
  225. decode_mtd_info_user(tcp, arg);
  226. break;
  227. case MEMGETOOBSEL:
  228. if (entering(tcp))
  229. return 0;
  230. decode_nand_oobinfo(tcp, arg);
  231. break;
  232. case ECCGETLAYOUT:
  233. if (entering(tcp))
  234. return 0;
  235. decode_nand_ecclayout_user(tcp, arg);
  236. break;
  237. case ECCGETSTATS:
  238. if (entering(tcp))
  239. return 0;
  240. decode_mtd_ecc_stats(tcp, arg);
  241. break;
  242. case OTPGETREGIONCOUNT:
  243. if (entering(tcp))
  244. return 0;
  245. tprints(", ");
  246. printnum_int(tcp, arg, "%u");
  247. break;
  248. case MEMGETREGIONCOUNT:
  249. if (entering(tcp))
  250. return 0;
  251. tprints(", ");
  252. printnum_int(tcp, arg, "%d");
  253. break;
  254. case MEMGETREGIONINFO:
  255. if (entering(tcp)) {
  256. struct region_info_user rinfo;
  257. tprints(", ");
  258. if (umove_or_printaddr(tcp, arg, &rinfo))
  259. break;
  260. tprintf("{regionindex=%#x", rinfo.regionindex);
  261. return 0;
  262. } else {
  263. struct region_info_user rinfo;
  264. if (!syserror(tcp) && !umove(tcp, arg, &rinfo))
  265. tprintf(", offset=%#x"
  266. ", erasesize=%#x"
  267. ", numblocks=%#x}",
  268. rinfo.offset,
  269. rinfo.erasesize,
  270. rinfo.numblocks);
  271. tprints("}");
  272. break;
  273. }
  274. default:
  275. return RVAL_DECODED;
  276. }
  277. return RVAL_IOCTL_DECODED;
  278. }
  279. #endif /* HAVE_STRUCT_MTD_WRITE_REQ */