(root)/
strace-6.5/
src/
mtd.c
       1  /*
       2   * Copyright (c) 2012 Mike Frysinger <vapier@gentoo.org>
       3   * Copyright (c) 2012-2021 The strace developers.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   */
       7  
       8  #include "defs.h"
       9  
      10  #include DEF_MPERS_TYPE(struct_mtd_oob_buf)
      11  
      12  #include <linux/ioctl.h>
      13  #include <mtd/mtd-abi.h>
      14  
      15  typedef struct mtd_oob_buf struct_mtd_oob_buf;
      16  
      17  #include MPERS_DEFS
      18  
      19  #include "xlat/mtd_mode_options.h"
      20  #include "xlat/mtd_file_mode_options.h"
      21  #include "xlat/mtd_type_options.h"
      22  #include "xlat/mtd_flags_options.h"
      23  #include "xlat/mtd_otp_options.h"
      24  #include "xlat/mtd_nandecc_options.h"
      25  
      26  static void
      27  decode_erase_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
      28  {
      29  	struct erase_info_user einfo;
      30  
      31  	if (umove_or_printaddr(tcp, addr, &einfo))
      32  		return;
      33  
      34  	tprint_struct_begin();
      35  	PRINT_FIELD_X(einfo, start);
      36  	tprint_struct_next();
      37  	PRINT_FIELD_X(einfo, length);
      38  	tprint_struct_end();
      39  }
      40  
      41  static void
      42  decode_erase_info_user64(struct tcb *const tcp, const kernel_ulong_t addr)
      43  {
      44  	struct erase_info_user64 einfo64;
      45  
      46  	if (umove_or_printaddr(tcp, addr, &einfo64))
      47  		return;
      48  
      49  	tprint_struct_begin();
      50  	PRINT_FIELD_X(einfo64, start);
      51  	tprint_struct_next();
      52  	PRINT_FIELD_X(einfo64, length);
      53  	tprint_struct_end();
      54  }
      55  
      56  static void
      57  decode_mtd_oob_buf(struct tcb *const tcp, const kernel_ulong_t addr)
      58  {
      59  	struct_mtd_oob_buf mbuf;
      60  
      61  	if (umove_or_printaddr(tcp, addr, &mbuf))
      62  		return;
      63  	tprint_struct_begin();
      64  	PRINT_FIELD_X(mbuf, start);
      65  	tprint_struct_next();
      66  	PRINT_FIELD_X(mbuf, length);
      67  	tprint_struct_next();
      68  	PRINT_FIELD_PTR(mbuf, ptr);
      69  	tprint_struct_end();
      70  }
      71  
      72  static void
      73  decode_mtd_oob_buf64(struct tcb *const tcp, const kernel_ulong_t addr)
      74  {
      75  	struct mtd_oob_buf64 mbuf64;
      76  
      77  	if (umove_or_printaddr(tcp, addr, &mbuf64))
      78  		return;
      79  
      80  	tprint_struct_begin();
      81  	PRINT_FIELD_X(mbuf64, start);
      82  	tprint_struct_next();
      83  	PRINT_FIELD_X(mbuf64, length);
      84  	tprint_struct_next();
      85  	PRINT_FIELD_ADDR64(mbuf64, usr_ptr);
      86  	tprint_struct_end();
      87  }
      88  
      89  static void
      90  decode_otp_info(struct tcb *const tcp, const kernel_ulong_t addr)
      91  {
      92  	struct otp_info oinfo;
      93  
      94  	if (umove_or_printaddr(tcp, addr, &oinfo))
      95  		return;
      96  
      97  	tprint_struct_begin();
      98  	PRINT_FIELD_X(oinfo, start);
      99  	tprint_struct_next();
     100  	PRINT_FIELD_X(oinfo, length);
     101  	tprint_struct_next();
     102  	PRINT_FIELD_U(oinfo, locked);
     103  	tprint_struct_end();
     104  }
     105  
     106  static void
     107  decode_otp_select(struct tcb *const tcp, const kernel_ulong_t addr)
     108  {
     109  	unsigned int i;
     110  
     111  	if (umove_or_printaddr(tcp, addr, &i))
     112  		return;
     113  
     114  	tprint_indirect_begin();
     115  	printxval(mtd_otp_options, i, "MTD_OTP_???");
     116  	tprint_indirect_end();
     117  }
     118  
     119  static void
     120  decode_mtd_write_req(struct tcb *const tcp, const kernel_ulong_t addr)
     121  {
     122  	struct mtd_write_req mreq;
     123  
     124  	if (umove_or_printaddr(tcp, addr, &mreq))
     125  		return;
     126  
     127  	tprint_struct_begin();
     128  	PRINT_FIELD_X(mreq, start);
     129  	tprint_struct_next();
     130  	PRINT_FIELD_X(mreq, len);
     131  	tprint_struct_next();
     132  	PRINT_FIELD_X(mreq, ooblen);
     133  	tprint_struct_next();
     134  	PRINT_FIELD_ADDR64(mreq, usr_data);
     135  	tprint_struct_next();
     136  	PRINT_FIELD_ADDR64(mreq, usr_oob);
     137  	tprint_struct_next();
     138  	PRINT_FIELD_XVAL(mreq, mode, mtd_mode_options, "MTD_OPS_???");
     139  	tprint_struct_end();
     140  }
     141  
     142  static void
     143  decode_mtd_info_user(struct tcb *const tcp, const kernel_ulong_t addr)
     144  {
     145  	struct mtd_info_user minfo;
     146  
     147  	if (umove_or_printaddr(tcp, addr, &minfo))
     148  		return;
     149  
     150  	tprint_struct_begin();
     151  	PRINT_FIELD_XVAL(minfo, type, mtd_type_options, "MTD_???");
     152  	tprint_struct_next();
     153  	PRINT_FIELD_FLAGS(minfo, flags, mtd_flags_options, "MTD_???");
     154  	tprint_struct_next();
     155  	PRINT_FIELD_X(minfo, size);
     156  	tprint_struct_next();
     157  	PRINT_FIELD_X(minfo, erasesize);
     158  	tprint_struct_next();
     159  	PRINT_FIELD_X(minfo, writesize);
     160  	tprint_struct_next();
     161  	PRINT_FIELD_X(minfo, oobsize);
     162  	tprint_struct_next();
     163  	PRINT_FIELD_X(minfo, padding);
     164  	tprint_struct_end();
     165  }
     166  
     167  static bool
     168  print_xint32x2_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
     169  			    void *data)
     170  {
     171  	print_local_array_ex(tcp, elem_buf, 2, sizeof(int),
     172  			     print_xint_array_member, NULL, 0, NULL, NULL);
     173  	return true;
     174  }
     175  
     176  static void
     177  decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr)
     178  {
     179  	struct nand_oobinfo ninfo;
     180  
     181  	if (umove_or_printaddr(tcp, addr, &ninfo))
     182  		return;
     183  
     184  	tprint_struct_begin();
     185  	PRINT_FIELD_XVAL(ninfo, useecc, mtd_nandecc_options, "MTD_NANDECC_???");
     186  	tprint_struct_next();
     187  	PRINT_FIELD_X(ninfo, eccbytes);
     188  	tprint_struct_next();
     189  	PRINT_FIELD_ARRAY(ninfo, oobfree, tcp, print_xint32x2_array_member);
     190  	tprint_struct_next();
     191  	PRINT_FIELD_ARRAY(ninfo, eccpos, tcp, print_xint_array_member);
     192  	tprint_struct_end();
     193  }
     194  
     195  static bool
     196  print_nand_oobfree_array_member(struct tcb *tcp, void *elem_buf,
     197  				size_t elem_size, void *data)
     198  {
     199  	const struct nand_oobfree *p = elem_buf;
     200  	tprint_struct_begin();
     201  	PRINT_FIELD_X(*p, offset);
     202  	tprint_struct_next();
     203  	PRINT_FIELD_X(*p, length);
     204  	tprint_struct_end();
     205  	return true;
     206  }
     207  
     208  static void
     209  decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr)
     210  {
     211  	struct nand_ecclayout_user nlay;
     212  
     213  	if (umove_or_printaddr(tcp, addr, &nlay))
     214  		return;
     215  
     216  	tprint_struct_begin();
     217  	PRINT_FIELD_X(nlay, eccbytes);
     218  	tprint_struct_next();
     219  	PRINT_FIELD_ARRAY(nlay, eccpos, tcp, print_xint_array_member);
     220  	tprint_struct_next();
     221  	PRINT_FIELD_X(nlay, oobavail);
     222  	tprint_struct_next();
     223  	PRINT_FIELD_ARRAY(nlay, oobfree, tcp, print_nand_oobfree_array_member);
     224  	tprint_struct_end();
     225  }
     226  
     227  static void
     228  decode_mtd_ecc_stats(struct tcb *const tcp, const kernel_ulong_t addr)
     229  {
     230  	struct mtd_ecc_stats es;
     231  
     232  	if (umove_or_printaddr(tcp, addr, &es))
     233  		return;
     234  
     235  	tprint_struct_begin();
     236  	PRINT_FIELD_X(es, corrected);
     237  	tprint_struct_next();
     238  	PRINT_FIELD_X(es, failed);
     239  	tprint_struct_next();
     240  	PRINT_FIELD_X(es, badblocks);
     241  	tprint_struct_next();
     242  	PRINT_FIELD_X(es, bbtblocks);
     243  	tprint_struct_end();
     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  		tprint_arg_next();
     255  		decode_erase_info_user(tcp, arg);
     256  		break;
     257  
     258  	case MEMERASE64:
     259  		tprint_arg_next();
     260  		decode_erase_info_user64(tcp, arg);
     261  		break;
     262  
     263  	case MEMWRITEOOB:
     264  	case MEMREADOOB:
     265  		tprint_arg_next();
     266  		decode_mtd_oob_buf(tcp, arg);
     267  		break;
     268  
     269  	case MEMWRITEOOB64:
     270  	case MEMREADOOB64:
     271  		tprint_arg_next();
     272  		decode_mtd_oob_buf64(tcp, arg);
     273  		break;
     274  
     275  	case MEMWRITE:
     276  		tprint_arg_next();
     277  		decode_mtd_write_req(tcp, arg);
     278  		break;
     279  
     280  	case OTPGETREGIONINFO:
     281  		if (entering(tcp))
     282  			return 0;
     283  		ATTRIBUTE_FALLTHROUGH;
     284  	case OTPLOCK:
     285  		tprint_arg_next();
     286  		decode_otp_info(tcp, arg);
     287  		break;
     288  
     289  	case OTPSELECT:
     290  		tprint_arg_next();
     291  		decode_otp_select(tcp, arg);
     292  		break;
     293  
     294  	case MTDFILEMODE:
     295  		tprint_arg_next();
     296  		printxval64(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
     297  		break;
     298  
     299  	case MEMGETBADBLOCK:
     300  	case MEMSETBADBLOCK:
     301  		tprint_arg_next();
     302  		printnum_int64(tcp, arg, "%" PRIu64);
     303  		break;
     304  
     305  	case MEMGETINFO:
     306  		if (entering(tcp))
     307  			return 0;
     308  		tprint_arg_next();
     309  		decode_mtd_info_user(tcp, arg);
     310  		break;
     311  
     312  	case MEMGETOOBSEL:
     313  		if (entering(tcp))
     314  			return 0;
     315  		tprint_arg_next();
     316  		decode_nand_oobinfo(tcp, arg);
     317  		break;
     318  
     319  	case ECCGETLAYOUT:
     320  		if (entering(tcp))
     321  			return 0;
     322  		tprint_arg_next();
     323  		decode_nand_ecclayout_user(tcp, arg);
     324  		break;
     325  
     326  	case ECCGETSTATS:
     327  		if (entering(tcp))
     328  			return 0;
     329  		tprint_arg_next();
     330  		decode_mtd_ecc_stats(tcp, arg);
     331  		break;
     332  
     333  	case OTPGETREGIONCOUNT:
     334  		if (entering(tcp))
     335  			return 0;
     336  		tprint_arg_next();
     337  		printnum_int(tcp, arg, "%u");
     338  		break;
     339  
     340  	case MEMGETREGIONCOUNT:
     341  		if (entering(tcp))
     342  			return 0;
     343  		tprint_arg_next();
     344  		printnum_int(tcp, arg, "%d");
     345  		break;
     346  
     347  	case MEMGETREGIONINFO:
     348  		if (entering(tcp)) {
     349  			struct region_info_user rinfo;
     350  
     351  			tprint_arg_next();
     352  			if (umove_or_printaddr(tcp, arg, &rinfo))
     353  				break;
     354  			tprint_struct_begin();
     355  			PRINT_FIELD_X(rinfo, regionindex);
     356  			return 0;
     357  		} else {
     358  			struct region_info_user rinfo;
     359  
     360  			if (!syserror(tcp) && !umove(tcp, arg, &rinfo)) {
     361  				tprint_struct_next();
     362  				PRINT_FIELD_X(rinfo, offset);
     363  				tprint_struct_next();
     364  				PRINT_FIELD_X(rinfo, erasesize);
     365  				tprint_struct_next();
     366  				PRINT_FIELD_X(rinfo, numblocks);
     367  			}
     368  			tprint_struct_end();
     369  			break;
     370  		}
     371  
     372  	default:
     373  		return RVAL_DECODED;
     374  	}
     375  
     376  	return RVAL_IOCTL_DECODED;
     377  }