(root)/
strace-6.5/
src/
hdio.c
       1  /*
       2   * Copyright (c) 2009, 2010 Jeff Mahoney <jeffm@suse.com>
       3   * Copyright (c) 2011-2016 Dmitry V. Levin <ldv@strace.io>
       4   * Copyright (c) 2016-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   */
       9  
      10  #include "defs.h"
      11  
      12  #include DEF_MPERS_TYPE(struct_hd_geometry)
      13  
      14  #include <linux/hdreg.h>
      15  
      16  typedef struct hd_geometry struct_hd_geometry;
      17  
      18  #include MPERS_DEFS
      19  
      20  #include "xlat/hdio_drive_cmds.h"
      21  
      22  #include "gen/generated.h"
      23  
      24  static int
      25  print_hdio_getgeo(struct tcb *const tcp, const kernel_ulong_t arg)
      26  {
      27  	if (entering(tcp)) {
      28  		tprint_arg_next();
      29  
      30  		return 0;
      31  	}
      32  
      33  	/* exiting */
      34  	struct_hd_geometry geo;
      35  
      36  	if (umove_or_printaddr(tcp, arg, &geo))
      37  		return RVAL_IOCTL_DECODED;
      38  
      39  	tprint_struct_begin();
      40  	PRINT_FIELD_U(geo, heads);
      41  	tprint_struct_next();
      42  	PRINT_FIELD_U(geo, sectors);
      43  	tprint_struct_next();
      44  	PRINT_FIELD_U(geo, cylinders);
      45  	tprint_struct_next();
      46  	PRINT_FIELD_U(geo, start);
      47  	tprint_struct_end();
      48  
      49  	return RVAL_IOCTL_DECODED;
      50  }
      51  
      52  static int
      53  print_hdio_drive_cmd(struct tcb *const tcp, const kernel_ulong_t arg)
      54  {
      55  	enum { SECTOR_SIZE = 512 };
      56  
      57  	if (entering(tcp)) {
      58  		tprint_arg_next();
      59  
      60  		struct hd_drive_cmd_hdr c;
      61  		if (umove_or_printaddr(tcp, arg, &c))
      62  			return RVAL_IOCTL_DECODED;
      63  
      64  		tprint_struct_begin();
      65  		PRINT_FIELD_XVAL(c, command, hdio_drive_cmds,
      66  				 "ATA_CMD_???");
      67  		tprint_struct_next();
      68  		PRINT_FIELD_U(c, sector_number);
      69  		tprint_struct_next();
      70  		PRINT_FIELD_U(c, feature);
      71  		tprint_struct_next();
      72  		PRINT_FIELD_U(c, sector_count);
      73  		tprint_struct_end();
      74  
      75  		return 0;
      76  	}
      77  
      78  	/* exiting */
      79  	struct {
      80  		uint8_t status;
      81  		uint8_t error;
      82  		uint8_t nsector;
      83  		uint8_t sector_count;
      84  	} c;
      85  
      86  	if ((syserror(tcp) && tcp->u_error != EIO) || umove(tcp, arg, &c))
      87  		return RVAL_IOCTL_DECODED;
      88  
      89  	tprint_value_changed();
      90  	tprint_struct_begin();
      91  	PRINT_FIELD_X(c, status);
      92  	tprint_struct_next();
      93  	PRINT_FIELD_U(c, error);
      94  	tprint_struct_next();
      95  	PRINT_FIELD_U(c, nsector);
      96  
      97  	if (c.sector_count) {
      98  		tprint_struct_next();
      99  		tprints_field_name("buf");
     100  		printstr_ex(tcp, arg + 4, c.sector_count * SECTOR_SIZE,
     101  			    QUOTE_FORCE_HEX);
     102  	}
     103  
     104  	tprint_struct_end();
     105  
     106  	return RVAL_IOCTL_DECODED;
     107  }
     108  
     109  MPERS_PRINTER_DECL(int, hdio_ioctl, struct tcb *const tcp,
     110  		   const unsigned int code, const kernel_ulong_t arg)
     111  {
     112  	switch (code) {
     113  	case HDIO_GETGEO:
     114  		return print_hdio_getgeo(tcp, arg);
     115  	case HDIO_DRIVE_CMD:
     116  		return print_hdio_drive_cmd(tcp, arg);
     117  	default:
     118  		if (current_klongsize == sizeof(kernel_ulong_t)) {
     119  			return var_ioctl_HDIO(tcp, code, arg);
     120  		} else {
     121  			/*
     122  			 * HDIO compat has never been supported by the kernel.
     123  			 */
     124  			return RVAL_DECODED;
     125  		}
     126  	}
     127  
     128  	return RVAL_IOCTL_DECODED;
     129  }