(root)/
strace-6.5/
tests-m32/
ioctl_hdio.c
       1  /*
       2   * Check HDIO_* ioctl decoding.
       3   *
       4   * Copyright (c) 2020-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  
      12  #include <errno.h>
      13  #include <stdio.h>
      14  #include <stdlib.h>
      15  #include <linux/hdreg.h>
      16  #include <sys/ioctl.h>
      17  #include "xlat.h"
      18  
      19  #include "xlat/hdio_busstates.h"
      20  #include "xlat/hdio_ide_nice.h"
      21  
      22  static const char *errstr;
      23  
      24  static long
      25  do_ioctl(kernel_ulong_t cmd, kernel_ulong_t arg)
      26  {
      27  	long rc = ioctl(-1, cmd, arg);
      28  
      29  	errstr = sprintrc(rc);
      30  
      31  #ifdef INJECT_RETVAL
      32  	if (rc != INJECT_RETVAL)
      33  		error_msg_and_fail("Got a return value of %ld != %ld",
      34  				   rc, (long) INJECT_RETVAL);
      35  
      36  	static char inj_errstr[4096];
      37  
      38  	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
      39  	errstr = inj_errstr;
      40  #endif
      41  
      42  	return rc;
      43  }
      44  
      45  static long
      46  do_ioctl_ptr(kernel_ulong_t cmd, const void *arg)
      47  {
      48  	return do_ioctl(cmd, (uintptr_t) arg);
      49  }
      50  
      51  int
      52  main(int argc, char *argv[])
      53  {
      54  #ifdef INJECT_RETVAL
      55  	unsigned long num_skip;
      56  	bool locked = false;
      57  
      58  	if (argc < 2)
      59  		error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]);
      60  
      61  	num_skip = strtoul(argv[1], NULL, 0);
      62  
      63  	for (size_t i = 0; i < num_skip; i++) {
      64  		long ret = ioctl(-1, HDIO_GET_QDMA, 0);
      65  
      66  		printf("ioctl(-1, %s, 0) = %s%s\n",
      67  		       XLAT_STR(HDIO_GET_QDMA), sprintrc(ret),
      68  		       ret == INJECT_RETVAL ? " (INJECTED)" : "");
      69  
      70  		if (ret != INJECT_RETVAL)
      71  			continue;
      72  
      73  		locked = true;
      74  		break;
      75  	}
      76  
      77  	if (!locked)
      78  		error_msg_and_fail("Hasn't locked on ioctl(-1"
      79  				   ", HDIO_GET_QDMA, 0) returning %d",
      80  				   INJECT_RETVAL);
      81  #endif
      82  
      83  	long rc;
      84  
      85  	/* Decoding is not supported */
      86  	static const struct {
      87  		uint32_t cmd;
      88  		const char *str;
      89  	} unsupp_cmds[] = {
      90  		{ ARG_STR(HDIO_GET_QDMA) },
      91  		{ ARG_STR(HDIO_SET_XFER) },
      92  		{ ARG_STR(HDIO_TRISTATE_HWIF) },
      93  		{ ARG_STR(HDIO_DRIVE_TASKFILE) },
      94  		{ ARG_STR(HDIO_DRIVE_TASK) },
      95  		{ ARG_STR(HDIO_SET_QDMA) },
      96  #ifdef MPERS_IS_m32
      97  		{ ARG_STR(HDIO_GET_UNMASKINTR) },
      98  		{ ARG_STR(HDIO_GET_MULTCOUNT) },
      99  		{ ARG_STR(HDIO_OBSOLETE_IDENTITY) },
     100  		{ ARG_STR(HDIO_GET_KEEPSETTINGS) },
     101  		{ ARG_STR(HDIO_GET_32BIT) },
     102  		{ ARG_STR(HDIO_GET_NOWERR) },
     103  		{ ARG_STR(HDIO_GET_DMA) },
     104  		{ ARG_STR(HDIO_GET_NICE) },
     105  		{ ARG_STR(HDIO_GET_IDENTITY) },
     106  		{ ARG_STR(HDIO_GET_WCACHE) },
     107  		{ ARG_STR(HDIO_GET_ACOUSTIC) },
     108  		{ ARG_STR(HDIO_GET_ADDRESS) },
     109  		{ ARG_STR(HDIO_GET_BUSSTATE) },
     110  		{ ARG_STR(HDIO_DRIVE_RESET) },
     111  		{ ARG_STR(HDIO_SET_MULTCOUNT) },
     112  		{ ARG_STR(HDIO_SET_UNMASKINTR) },
     113  		{ ARG_STR(HDIO_SET_KEEPSETTINGS) },
     114  		{ ARG_STR(HDIO_SET_32BIT) },
     115  		{ ARG_STR(HDIO_SET_NOWERR) },
     116  		{ ARG_STR(HDIO_SET_DMA) },
     117  		{ ARG_STR(HDIO_SET_PIO_MODE) },
     118  		{ ARG_STR(HDIO_SCAN_HWIF) },
     119  		{ ARG_STR(HDIO_UNREGISTER_HWIF) },
     120  		{ ARG_STR(HDIO_SET_NICE) },
     121  		{ ARG_STR(HDIO_SET_WCACHE) },
     122  		{ ARG_STR(HDIO_SET_ACOUSTIC) },
     123  		{ ARG_STR(HDIO_SET_BUSSTATE) },
     124  		{ ARG_STR(HDIO_SET_ADDRESS) },
     125  #endif /* MPERS_IS_m32 */
     126  	};
     127  
     128  	for (size_t i = 0; i < ARRAY_SIZE(unsupp_cmds); i++) {
     129  		do_ioctl(unsupp_cmds[i].cmd, 0);
     130  		printf("ioctl(-1, " XLAT_FMT ", 0) = %s\n",
     131  		       XLAT_SEL(unsupp_cmds[i].cmd, unsupp_cmds[i].str),
     132  		       errstr);
     133  
     134  		do_ioctl(unsupp_cmds[i].cmd,
     135  			 (unsigned long) 0xbadc0deddeadc0deULL);
     136  		printf("ioctl(-1, " XLAT_FMT ", %#lx) = %s\n",
     137  		       XLAT_SEL(unsupp_cmds[i].cmd, unsupp_cmds[i].str),
     138  		       (unsigned long) 0xbadc0deddeadc0deULL, errstr);
     139  	}
     140  
     141  
     142  	/* HDIO_GETGEO */
     143  	do_ioctl(HDIO_GETGEO, 0);
     144  	printf("ioctl(-1, %s, NULL) = %s\n",
     145  	       XLAT_STR(HDIO_GETGEO), errstr);
     146  
     147  	TAIL_ALLOC_OBJECT_CONST_PTR(struct hd_geometry, p_hd_geom);
     148  
     149  	p_hd_geom->heads = 0xca;
     150  	p_hd_geom->sectors = 0xfe;
     151  	p_hd_geom->cylinders = 0xbabe;
     152  	p_hd_geom->start = (unsigned long) 0xbadc0deddeadfaceULL;
     153  
     154  	do_ioctl_ptr(HDIO_GETGEO, (char *) p_hd_geom + 1);
     155  	printf("ioctl(-1, %s, %p) = %s\n",
     156  	       XLAT_STR(HDIO_GETGEO), (char *) p_hd_geom + 1, errstr);
     157  
     158  	rc = do_ioctl_ptr(HDIO_GETGEO, p_hd_geom);
     159  	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_GETGEO));
     160  	if (rc >= 0) {
     161  		printf("{heads=202, sectors=254, cylinders=47806, start=%lu}",
     162  		       (unsigned long) 0xbadc0deddeadfaceULL);
     163  	} else {
     164  		printf("%p", p_hd_geom);
     165  	}
     166  	printf(") = %s\n", errstr);
     167  
     168  	/* HDIO_DRIVE_CMD */
     169  	do_ioctl(HDIO_DRIVE_CMD, 0);
     170  	printf("ioctl(-1, %s, NULL) = %s\n",
     171  	       XLAT_STR(HDIO_DRIVE_CMD), errstr);
     172  
     173  	TAIL_ALLOC_OBJECT_CONST_PTR(struct hd_drive_cmd_hdr, p_hd_drive_cmd);
     174  	struct hd_drive_cmd_hdr *p_hd_drive_cmd2 =
     175  		tail_alloc(sizeof(*p_hd_drive_cmd2) + 16);
     176  	struct hd_drive_cmd_hdr *p_hd_drive_cmd3 =
     177  		tail_alloc(sizeof(*p_hd_drive_cmd3) + DEFAULT_STRLEN + 1);
     178  
     179  	fill_memory(p_hd_drive_cmd2, sizeof(*p_hd_drive_cmd2) + 16);
     180  	fill_memory(p_hd_drive_cmd3,
     181  		    sizeof(*p_hd_drive_cmd3) + DEFAULT_STRLEN + 1);
     182  
     183  	p_hd_drive_cmd->command = 0xca;
     184  	p_hd_drive_cmd->sector_number = 0xff;
     185  	p_hd_drive_cmd->feature = 0xee;
     186  	p_hd_drive_cmd->sector_count = 0;
     187  
     188  	do_ioctl_ptr(HDIO_DRIVE_CMD, (char *) p_hd_drive_cmd + 1);
     189  	printf("ioctl(-1, %s, %p) = %s\n",
     190  	       XLAT_STR(HDIO_DRIVE_CMD), (char *) p_hd_drive_cmd + 1, errstr);
     191  
     192  	for (size_t i = 0; i < 2; i++) {
     193  		p_hd_drive_cmd->sector_count = i;
     194  
     195  		rc = do_ioctl_ptr(HDIO_DRIVE_CMD, p_hd_drive_cmd);
     196  		printf("ioctl(-1, %s, {command=" XLAT_FMT ", sector_number=255"
     197  		       ", feature=238, sector_count=%zu",
     198  		       XLAT_STR(HDIO_DRIVE_CMD),
     199  		       XLAT_SEL(0xca, "ATA_CMD_WRITE"), i);
     200  		if (rc >= 0) {
     201  			printf("} => {status=0xca, error=255, nsector=238");
     202  			if (i)
     203  				printf(", buf=%p", p_hd_drive_cmd + 1);
     204  		}
     205  		printf("}) = %s\n", errstr);
     206  	}
     207  
     208  	rc = do_ioctl_ptr(HDIO_DRIVE_CMD, p_hd_drive_cmd2);
     209  	printf("ioctl(-1, %s, {command=0x80" NRAW(" /* ATA_CMD_??? */")
     210  	       ", sector_number=129, feature=130, sector_count=131",
     211  	       XLAT_STR(HDIO_DRIVE_CMD));
     212  	if (rc >= 0) {
     213  		printf("} => {status=0x80, error=129, nsector=130, buf=%p",
     214  		       p_hd_drive_cmd2 + 1);
     215  	}
     216  	printf("}) = %s\n", errstr);
     217  
     218  	rc = do_ioctl_ptr(HDIO_DRIVE_CMD, p_hd_drive_cmd3);
     219  	printf("ioctl(-1, %s, {command=0x80" NRAW(" /* ATA_CMD_??? */")
     220  	       ", sector_number=129, feature=130, sector_count=131",
     221  	       XLAT_STR(HDIO_DRIVE_CMD));
     222  	if (rc >= 0) {
     223  		printf("} => {status=0x80, error=129, nsector=130, buf=");
     224  		print_quoted_hex(p_hd_drive_cmd3 + 1, DEFAULT_STRLEN);
     225  		printf("...");
     226  	}
     227  	printf("}) = %s\n", errstr);
     228  
     229  /* HDIO compat has never been supported by the kernel.  */
     230  #ifndef MPERS_IS_m32
     231  
     232  	void *const efault = tail_alloc(1) + 1;
     233  
     234  	/* HDIO_DRIVE_RESET */
     235  	printf("ioctl(-1, %s, NULL) = %s\n",
     236  	       XLAT_STR(HDIO_DRIVE_RESET), errstr);
     237  	do_ioctl_ptr(HDIO_DRIVE_RESET, 0);
     238  
     239  	printf("ioctl(-1, %s, %p) = %s\n",
     240  	       XLAT_STR(HDIO_DRIVE_RESET), efault, errstr);
     241  	do_ioctl(HDIO_DRIVE_RESET, (uintptr_t) efault);
     242  
     243  	printf("ioctl(-1, %s, [%#x, %#x, %#x]) = %s\n",
     244  	       XLAT_STR(HDIO_DRIVE_RESET),
     245  	       (unsigned int) 0xdeadbeef,
     246  	       (unsigned int) 0xAAAAAAAA,
     247  	       (unsigned int) 0xbeefbeef,
     248  	       errstr);
     249  	int drive_reset_args[3] = {0xdeadbeef, 0xAAAAAAAA, 0xbeefbeef};
     250  	do_ioctl_ptr(HDIO_DRIVE_RESET, &drive_reset_args);
     251  
     252  	/* HDIO_SCAN_HWIF */
     253  	printf("ioctl(-1, %s, NULL) = %s\n", XLAT_STR(HDIO_SCAN_HWIF), errstr);
     254  	do_ioctl_ptr(HDIO_SCAN_HWIF, 0);
     255  
     256  	printf("ioctl(-1, %s, %p) = %s\n",
     257  	       XLAT_STR(HDIO_SCAN_HWIF), efault, errstr);
     258  	do_ioctl(HDIO_SCAN_HWIF, (uintptr_t) efault);
     259  
     260  	printf("ioctl(-1, %s, [%#x, %#x, %#x]) = %s\n",
     261  	       XLAT_STR(HDIO_SCAN_HWIF),
     262  	       (unsigned int) 0xdeadbeef,
     263  	       (unsigned int) 0xAAAAAAAA,
     264  	       (unsigned int) 0xbeefbeef,
     265  	       errstr);
     266  	int scan_hwif_args[3] = {0xdeadbeef, 0xAAAAAAAA, 0xbeefbeef};
     267  	do_ioctl_ptr(HDIO_SCAN_HWIF, &scan_hwif_args);
     268  
     269  	/* Getters of the form ioctl(..., ..., &val) */
     270  	static const struct {
     271  		uint32_t cmd;
     272  		const char *str;
     273  	} getter_cmds[] = {
     274  		{ ARG_STR(HDIO_GET_32BIT) },
     275  		{ ARG_STR(HDIO_GET_ACOUSTIC) },
     276  		{ ARG_STR(HDIO_GET_ADDRESS) },
     277  		{ ARG_STR(HDIO_GET_DMA) },
     278  		{ ARG_STR(HDIO_GET_KEEPSETTINGS) },
     279  		{ ARG_STR(HDIO_GET_MULTCOUNT) },
     280  		{ ARG_STR(HDIO_GET_NOWERR) },
     281  		{ ARG_STR(HDIO_GET_UNMASKINTR) },
     282  		{ ARG_STR(HDIO_GET_WCACHE) },
     283  	};
     284  
     285  	for (size_t i = 0; i < ARRAY_SIZE(getter_cmds); i++) {
     286  		kernel_ulong_t val = (kernel_ulong_t) 0xfacefeeddeadbeefULL;
     287  
     288  		rc = do_ioctl_ptr(getter_cmds[i].cmd, &val);
     289  		printf("ioctl(-1, " XLAT_FMT ", ",
     290  		       XLAT_SEL(getter_cmds[i].cmd, getter_cmds[i].str));
     291  		if (rc >= 0) {
     292  			printf("[%llu]", (unsigned long long) val);
     293  		} else {
     294  			printf("%p", &val);
     295  		}
     296  		printf(") = %s\n", errstr);
     297  	}
     298  
     299  	/* Setters of the form ioctl(..., ..., val) */
     300  	static const struct {
     301  		uint32_t cmd;
     302  		const char *str;
     303  	} setter_cmds[] = {
     304  			{ ARG_STR(HDIO_SET_32BIT) },
     305  			{ ARG_STR(HDIO_SET_ACOUSTIC) },
     306  			{ ARG_STR(HDIO_SET_ADDRESS) },
     307  			{ ARG_STR(HDIO_SET_DMA) },
     308  			{ ARG_STR(HDIO_SET_KEEPSETTINGS) },
     309  			{ ARG_STR(HDIO_SET_MULTCOUNT) },
     310  			{ ARG_STR(HDIO_SET_NOWERR) },
     311  			{ ARG_STR(HDIO_SET_PIO_MODE) },
     312  			{ ARG_STR(HDIO_SET_UNMASKINTR) },
     313  			{ ARG_STR(HDIO_SET_WCACHE) },
     314  			{ ARG_STR(HDIO_UNREGISTER_HWIF) },
     315  	};
     316  
     317  	for (size_t i = 0; i < ARRAY_SIZE(setter_cmds); i++) {
     318  		unsigned long val = (unsigned long) 0xfacefeeddeadbeefULL;
     319  
     320  		rc = do_ioctl(setter_cmds[i].cmd, val);
     321  		printf("ioctl(-1, " XLAT_FMT ", %llu) = %s\n",
     322  		       XLAT_SEL(setter_cmds[i].cmd, setter_cmds[i].str),
     323  		       (unsigned long long) val, errstr);
     324  	}
     325  
     326  	/* HDIO_OBSOLETE_IDENTITY */
     327  	do_ioctl_ptr(HDIO_OBSOLETE_IDENTITY, NULL);
     328  	printf("ioctl(-1, %s, NULL) = %s\n",
     329  	       XLAT_STR(HDIO_OBSOLETE_IDENTITY), errstr);
     330  
     331  	char obsolete_identity[142];
     332  	rc = do_ioctl_ptr(HDIO_OBSOLETE_IDENTITY, obsolete_identity);
     333  
     334  	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_OBSOLETE_IDENTITY));
     335  
     336  	if (rc >= 0) {
     337  		print_quoted_memory(obsolete_identity, DEFAULT_STRLEN);
     338  		printf("...");
     339  	} else {
     340  		printf("%p", obsolete_identity);
     341  	}
     342  	printf(") = %s\n", errstr);
     343  
     344  	/* HDIO_GET_IDENTITY */
     345  	do_ioctl_ptr(HDIO_GET_IDENTITY, NULL);
     346  	printf("ioctl(-1, %s, NULL) = %s\n",
     347  	       XLAT_STR(HDIO_GET_IDENTITY), errstr);
     348  
     349  	char identity[512];
     350  	rc = do_ioctl_ptr(HDIO_GET_IDENTITY, identity);
     351  
     352  	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_GET_IDENTITY));
     353  
     354  	if (rc >= 0) {
     355  		print_quoted_memory(identity, DEFAULT_STRLEN);
     356  		printf("...");
     357  	} else {
     358  		printf("%p", identity);
     359  	}
     360  	printf(") = %s\n", errstr);
     361  
     362  	/* HDIO_GET_NICE */
     363  	kernel_ulong_t nice_val = (kernel_ulong_t) 0xfacefeedded1ffffULL;
     364  
     365  	rc = do_ioctl_ptr(HDIO_GET_NICE, &nice_val);
     366  	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_GET_NICE));
     367  	if (rc >= 0) {
     368  		printf("[");
     369  # if XLAT_RAW
     370  		printf("%#llx", (unsigned long long) nice_val);
     371  # else
     372  #  if XLAT_VERBOSE
     373  			printf("%#llx /* ", (unsigned long long) nice_val);
     374  #  endif
     375  		printflags(hdio_ide_nice, nice_val, "IDE_NICE_???");
     376  #  if XLAT_VERBOSE
     377  			printf(" */");
     378  #  endif
     379  # endif
     380  		printf("]");
     381  	} else {
     382  		printf("%p", &nice_val);
     383  	}
     384  	printf(") = %s\n", errstr);
     385  
     386  	/* HDIO_SET_NICE */
     387  	nice_val = (unsigned long) 0xfacefeedded2ffffULL;
     388  	do_ioctl(HDIO_SET_NICE, nice_val);
     389  	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_SET_NICE));
     390  # if XLAT_RAW
     391  	printf("%#llx", (unsigned long long) nice_val);
     392  # else
     393  #  if XLAT_VERBOSE
     394  	printf("%#llx /* ", (unsigned long long) nice_val);
     395  #  endif
     396  	printflags(hdio_ide_nice, nice_val, "IDE_NICE_???");
     397  #  if XLAT_VERBOSE
     398  	printf(" */");
     399  #  endif
     400  # endif
     401  	printf(") = %s\n", errstr);
     402  
     403  	/* HDIO_GET_BUSSTATE */
     404  	kernel_ulong_t busstate_value = (kernel_ulong_t) 0xfacefeedded3ffffULL;
     405  
     406  	rc = do_ioctl_ptr(HDIO_GET_BUSSTATE, &busstate_value);
     407  	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_GET_BUSSTATE));
     408  	if (rc >= 0) {
     409  		printf("[");
     410  		printxval(hdio_busstates, busstate_value, "BUSSTATE_???");
     411  		printf("]");
     412  	} else {
     413  		printf("%p", &busstate_value);
     414  	}
     415  	printf(") = %s\n", errstr);
     416  
     417  
     418  	/* HDIO_SET_BUSSTATE */
     419  	busstate_value = (unsigned long) 0xfacefeedded4ffffULL;
     420  
     421  	do_ioctl(HDIO_SET_BUSSTATE, busstate_value);
     422  	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_SET_BUSSTATE));
     423  	printxval(hdio_busstates, busstate_value, "BUSSTATE_???");
     424  	printf(") = %s\n", errstr);
     425  
     426  #endif /* !MPERS_IS_m32 */
     427  
     428  	puts("+++ exited with 0 +++");
     429  	return 0;
     430  }