[PATCH v2 3/3] hdio: improve HDIO support

Srikavin Ramkumar srikavinramkumar at gmail.com
Wed Sep 8 15:36:54 UTC 2021


Add decoders for HDIO_DRIVE_RESET, HDIO_GET_32BIT, HDIO_GET_ACOUSTIC,
HDIO_GET_ADDRESS, HDIO_GET_BUSSTATE, HDIO_GET_DMA, HDIO_GET_IDENTITY,
HDIO_GET_KEEPSETTINGS, HDIO_GET_MULTCOUNT, HDIO_GET_NICE, HDIO_GET_NOWERR,
HDIO_GET_UNMASKINTR, HDIO_GET_WCACHE, HDIO_OBSOLETE_IDENTITY, HDIO_SCAN_HWIF,
HDIO_SET_32BIT, HDIO_SET_ACOUSTIC, HDIO_SET_ADDRESS, HDIO_SET_BUSSTATE,
HDIO_SET_DMA, HDIO_SET_KEEPSETTINGS, HDIO_SET_MULTCOUNT, HDIO_SET_NICE,
HDIO_SET_NOWERR, HDIO_SET_PIO_MODE, HDIO_SET_UNMASKINTR, HDIO_SET_WCACHE,
and HDIO_UNREGISTER_HWIF.

* maint/gen/defs/common.def: Add decoder for uint32_t arrays.
* maint/gen/defs/hdio.def: New file.
* NEWS: Mention this change.
* src/Makefile.am (libstrace_a_SOURCES): Add gen/generated.h and gen/gen_hdio.c.
* src/gen/gen_hdio.c: Add generated file.
* src/gen/generated.h: New file.
* src/hdio.c: Add call to generated file for unimplemented commands.
* src/xlat/hdio_busstates.in: New file.
* src/xlat/hdio_ide_nice.in: Likewise.
* tests/ioctl_hdio.c: Add tests for newly implemented commands.
---

Changes since V1:
    * maint/gen/defs/common.def: Changed ptr[in, array[uint32_t, length]] decoder
                                 to use print_xint32_array_member.
    * maint/gen/defs/hdio.def: Added decoders for SET_32BIT, SET_NOWERR, SET_DMA,
                               SET_WCACHE, SET_ACOUSTIC, SET_ADDRESS, UNREGISTER_HWIF,
                               SET_PIO_MODE, SCAN_HWIF (and updated commit message).
    * src/Makefile.am: Fixed indentation.
    * src/gen/gen_hdio.c: Regenerated from hdio.def.
    * src/xlat/hdio_busstates.in: Use #unconditional and #value_indexed instead of #enum.
    * tests/ioctl_hdio.c: Added tests for new decoders and check that hexadecimal values 
                          are printed for the HDIO_DRIVE_RESET command.
    * NEWS: Added entry listing new HDIO command decoders.

    The following HDIO commands are still unimplemented:
        (undocumented): HDIO_GET_QDMA, HDIO_SET_XFER, HDIO_SET_QDMA, HDIO_TRISTATE_HWIF
        (complex): HDIO_DRIVE_TASKFILE, HDIO_DRIVE_TASK

 NEWS                       |   1 +
 maint/gen/defs/common.def  |   2 +-
 maint/gen/defs/hdio.def    |  51 +++++
 src/Makefile.am            |   2 +
 src/gen/gen_hdio.c         | 441 +++++++++++++++++++++++++++++++++++++
 src/gen/generated.h        |   4 +
 src/hdio.c                 |   4 +-
 src/xlat/hdio_busstates.in |   5 +
 src/xlat/hdio_ide_nice.in  |   5 +
 tests/ioctl_hdio.c         | 215 +++++++++++++++---
 10 files changed, 698 insertions(+), 32 deletions(-)
 create mode 100644 maint/gen/defs/hdio.def
 create mode 100644 src/gen/gen_hdio.c
 create mode 100644 src/gen/generated.h
 create mode 100644 src/xlat/hdio_busstates.in
 create mode 100644 src/xlat/hdio_ide_nice.in

diff --git a/NEWS b/NEWS
index df032f85c..d7805d9f2 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,7 @@ Noteworthy changes in release 5.14 (2021-09-02)
   * Updated lists of BPF_*, IORING_*, MADV_*, MOUNT_ATTR_*, SCTP_*,
     and UFFD_* constants.
   * Updated lists of ioctl commands from Linux 5.14.
+  * Enhanced decoding of HDIO_* commands.
 
 * Bug fixes
   * Fixed build using bionic libc.
diff --git a/maint/gen/defs/common.def b/maint/gen/defs/common.def
index 24322e9c1..0d8fa096a 100644
--- a/maint/gen/defs/common.def
+++ b/maint/gen/defs/common.def
@@ -36,7 +36,7 @@
 :ptr[in, array[uint32_t, $1]] %{
 	{
 		uint32_t int_buffer;
-		print_array(tcp, $$, $1, &int_buffer, sizeof(int_buffer), tfetch_mem, print_uint32_array_member, 0);
+		print_array(tcp, $$, $1, &int_buffer, sizeof(int_buffer), tfetch_mem, print_xint32_array_member, 0);
 	}
 %}
 
diff --git a/maint/gen/defs/hdio.def b/maint/gen/defs/hdio.def
new file mode 100644
index 000000000..751978f09
--- /dev/null
+++ b/maint/gen/defs/hdio.def
@@ -0,0 +1,51 @@
+#import "defs/common.def"
+
+include <linux/hdreg.h>
+
+include "xlat/hdio_ide_nice.h"
+include "xlat/hdio_busstates.h"
+
+ioctl$HDIO(fd fd, code kernel_ulong_t, arg3 kernel_ulong_t)
+
+ioctl$HDIO$GET_UNMASKINTR(fd fd, code const[HDIO_GET_UNMASKINTR], unmaskintr ptr[out, ulong])
+ioctl$HDIO$SET_UNMASKINTR(fd fd, code const[HDIO_SET_UNMASKINTR], unmaskintr kernel_ulong_t)
+
+ioctl$HDIO$GET_MULTCOUNT(fd fd, code const[HDIO_GET_MULTCOUNT], multcount ptr[out, ulong])
+ioctl$HDIO$SET_MULTCOUNT(fd fd, code const[HDIO_SET_MULTCOUNT], multcount kernel_ulong_t)
+
+ioctl$HDIO$OBSOLETE_IDENTITY(fd fd, code const[HDIO_OBSOLETE_IDENTITY], identity ptr[out, stringnoz[142]])
+ioctl$HDIO$GET_IDENTITY(fd fd, code const[HDIO_GET_IDENTITY], identity ptr[out, stringnoz[512]])
+
+ioctl$HDIO$GET_KEEPSETTINGS(fd fd, code const[HDIO_GET_KEEPSETTINGS], keep_settings ptr[out, ulong])
+ioctl$HDIO$SET_KEEPSETTINGS(fd fd, code const[HDIO_SET_KEEPSETTINGS], keep_settings kernel_ulong_t)
+
+ioctl$HDIO$GET_32BIT(fd fd, code const[HDIO_GET_32BIT], arg ptr[out, ulong])
+ioctl$HDIO$SET_32BIT(fd fd, code const[HDIO_SET_32BIT], arg kernel_ulong_t)
+
+ioctl$HDIO$GET_NOWERR(fd fd, code const[HDIO_GET_NOWERR], arg ptr[out, ulong])
+ioctl$HDIO$SET_NOWERR(fd fd, code const[HDIO_SET_NOWERR], arg kernel_ulong_t)
+
+ioctl$HDIO$GET_DMA(fd fd, code const[HDIO_GET_DMA], arg ptr[out, ulong])
+ioctl$HDIO$SET_DMA(fd fd, code const[HDIO_SET_DMA], arg kernel_ulong_t)
+
+ioctl$HDIO$GET_NICE(fd fd, code const[HDIO_GET_NICE], arg ptr[out, or_flags[hdio_ide_nice, IDE_NICE_???, ulong]])
+ioctl$HDIO$SET_NICE(fd fd, code const[HDIO_SET_NICE], arg or_flags[hdio_ide_nice, IDE_NICE_???, kernel_ulong_t])
+
+ioctl$HDIO$GET_WCACHE(fd fd, code const[HDIO_GET_WCACHE], arg ptr[out, ulong])
+ioctl$HDIO$SET_WCACHE(fd fd, code const[HDIO_SET_WCACHE], arg kernel_ulong_t)
+
+ioctl$HDIO$GET_ACOUSTIC(fd fd, code const[HDIO_GET_ACOUSTIC], arg ptr[out, ulong])
+ioctl$HDIO$SET_ACOUSTIC(fd fd, code const[HDIO_SET_ACOUSTIC], arg kernel_ulong_t)
+
+ioctl$HDIO$GET_ADDRESS(fd fd, code const[HDIO_GET_ADDRESS], arg ptr[out, ulong])
+ioctl$HDIO$SET_ADDRESS(fd fd, code const[HDIO_SET_ADDRESS], arg kernel_ulong_t)
+
+ioctl$HDIO$GET_BUSSTATE(fd fd, code const[HDIO_GET_BUSSTATE], arg ptr[out, xor_flags[hdio_busstates, BUSSTATE_???, ulong]])
+ioctl$HDIO$SET_BUSSTATE(fd fd, code const[HDIO_SET_BUSSTATE], arg xor_flags[hdio_busstates, BUSSTATE_???, kernel_ulong_t])
+
+ioctl$HDIO$SET_PIO_MODE(fd fd, code const[HDIO_SET_PIO_MODE], arg kernel_ulong_t)
+
+ioctl$HDIO$UNREGISTER_HWIF(fd fd, code const[HDIO_UNREGISTER_HWIF], arg kernel_ulong_t)
+
+ioctl$HDIO$DRIVE_RESET(fd fd, code const[HDIO_DRIVE_RESET], arg ptr[in, array[uint32_t, 3]])
+ioctl$HDIO$SCAN_HWIF(fd fd, code const[HDIO_SCAN_HWIF], arg ptr[in, array[uint32_t, 3]])
diff --git a/src/Makefile.am b/src/Makefile.am
index b7e74a76e..aae7f86f1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -132,6 +132,8 @@ libstrace_a_SOURCES =	\
 	fstatfs64.c \
 	futex.c		\
 	gcc_compat.h	\
+	gen/gen_hdio.c	\
+	gen/generated.h	\
 	get_personality.c \
 	get_personality.h \
 	get_robust_list.c \
diff --git a/src/gen/gen_hdio.c b/src/gen/gen_hdio.c
new file mode 100644
index 000000000..563f14939
--- /dev/null
+++ b/src/gen/gen_hdio.c
@@ -0,0 +1,441 @@
+/* Generated by ./maint/gen/generate.sh from ./maint/gen/defs/hdio.def; do not edit. */
+
+#include <stddef.h>
+#include "generated.h"
+
+typedef kernel_ulong_t kernel_size_t;
+
+#include <linux/hdreg.h>
+#include "xlat/hdio_ide_nice.h"
+#include "xlat/hdio_busstates.h"
+static int
+var_leaf_ioctl_HDIO_DRIVE_RESET(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (array *) */
+	/* using decoder from defs/common.def:36:1 */
+
+	{
+		uint32_t int_buffer;
+		print_array(tcp, (arg), (3), &int_buffer, sizeof(int_buffer), tfetch_mem, print_xint32_array_member, 0);
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_32BIT(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_ACOUSTIC(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_ADDRESS(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_BUSSTATE(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	unsigned long tmpvar_arg;
+	if (!umove_or_printaddr(tcp, arg, &tmpvar_arg)) {
+		tprint_indirect_begin();
+		printxval(hdio_busstates, tmpvar_arg, "BUSSTATE_???");
+		tprint_indirect_end();
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_DMA(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_IDENTITY(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: identity (stringnoz *) */
+	/* using decoder from defs/common.def:5:1 */
+
+	if (entering(tcp)) {
+		printstrn(tcp, (arg), (512));
+	} else if (syserror(tcp)) {
+		printaddr((arg));
+	} else {
+		printstrn(tcp, (arg), (512));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_KEEPSETTINGS(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: keep_settings (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_MULTCOUNT(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: multcount (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_NICE(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	unsigned long tmpvar_arg;
+	if (!umove_or_printaddr(tcp, arg, &tmpvar_arg)) {
+		tprint_indirect_begin();
+		printflags(hdio_ide_nice, tmpvar_arg, "IDE_NICE_???");
+		tprint_indirect_end();
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_NOWERR(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_UNMASKINTR(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: unmaskintr (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_GET_WCACHE(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: arg (unsigned long *) */
+	/* using decoder from defs/common.def:43:1 */
+
+	if (exiting(tcp)) {
+		printnum_ulong(tcp, (arg));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_OBSOLETE_IDENTITY(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if (entering(tcp)) {
+		tprint_arg_next();
+		return 0;
+	}
+	/* arg: identity (stringnoz *) */
+	/* using decoder from defs/common.def:5:1 */
+
+	if (entering(tcp)) {
+		printstrn(tcp, (arg), (142));
+	} else if (syserror(tcp)) {
+		printaddr((arg));
+	} else {
+		printstrn(tcp, (arg), (142));
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SCAN_HWIF(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (array *) */
+	/* using decoder from defs/common.def:36:1 */
+
+	{
+		uint32_t int_buffer;
+		print_array(tcp, (arg), (3), &int_buffer, sizeof(int_buffer), tfetch_mem, print_xint32_array_member, 0);
+	}
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_32BIT(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_ACOUSTIC(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_ADDRESS(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_BUSSTATE(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	printxval(hdio_busstates, arg, "BUSSTATE_???");
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_DMA(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_KEEPSETTINGS(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: keep_settings (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_MULTCOUNT(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: multcount (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_NICE(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	printflags(hdio_ide_nice, arg, "IDE_NICE_???");
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_NOWERR(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_PIO_MODE(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_UNMASKINTR(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: unmaskintr (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_SET_WCACHE(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO_UNREGISTER_HWIF(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	tprint_arg_next();
+	/* arg: arg (kernel_ulong_t) */
+	PRINT_VAL_U((kernel_ulong_t) arg);
+
+	return RVAL_IOCTL_DECODED;
+}
+static int
+var_leaf_ioctl_HDIO(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	return RVAL_DECODED;
+}
+int
+var_ioctl_HDIO(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+	if ((code) == (HDIO_DRIVE_RESET)) {
+		return var_leaf_ioctl_HDIO_DRIVE_RESET(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_32BIT)) {
+		return var_leaf_ioctl_HDIO_GET_32BIT(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_ACOUSTIC)) {
+		return var_leaf_ioctl_HDIO_GET_ACOUSTIC(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_ADDRESS)) {
+		return var_leaf_ioctl_HDIO_GET_ADDRESS(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_BUSSTATE)) {
+		return var_leaf_ioctl_HDIO_GET_BUSSTATE(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_DMA)) {
+		return var_leaf_ioctl_HDIO_GET_DMA(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_IDENTITY)) {
+		return var_leaf_ioctl_HDIO_GET_IDENTITY(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_KEEPSETTINGS)) {
+		return var_leaf_ioctl_HDIO_GET_KEEPSETTINGS(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_MULTCOUNT)) {
+		return var_leaf_ioctl_HDIO_GET_MULTCOUNT(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_NICE)) {
+		return var_leaf_ioctl_HDIO_GET_NICE(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_NOWERR)) {
+		return var_leaf_ioctl_HDIO_GET_NOWERR(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_UNMASKINTR)) {
+		return var_leaf_ioctl_HDIO_GET_UNMASKINTR(tcp, code, arg);
+	} else if ((code) == (HDIO_GET_WCACHE)) {
+		return var_leaf_ioctl_HDIO_GET_WCACHE(tcp, code, arg);
+	} else if ((code) == (HDIO_OBSOLETE_IDENTITY)) {
+		return var_leaf_ioctl_HDIO_OBSOLETE_IDENTITY(tcp, code, arg);
+	} else if ((code) == (HDIO_SCAN_HWIF)) {
+		return var_leaf_ioctl_HDIO_SCAN_HWIF(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_32BIT)) {
+		return var_leaf_ioctl_HDIO_SET_32BIT(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_ACOUSTIC)) {
+		return var_leaf_ioctl_HDIO_SET_ACOUSTIC(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_ADDRESS)) {
+		return var_leaf_ioctl_HDIO_SET_ADDRESS(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_BUSSTATE)) {
+		return var_leaf_ioctl_HDIO_SET_BUSSTATE(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_DMA)) {
+		return var_leaf_ioctl_HDIO_SET_DMA(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_KEEPSETTINGS)) {
+		return var_leaf_ioctl_HDIO_SET_KEEPSETTINGS(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_MULTCOUNT)) {
+		return var_leaf_ioctl_HDIO_SET_MULTCOUNT(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_NICE)) {
+		return var_leaf_ioctl_HDIO_SET_NICE(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_NOWERR)) {
+		return var_leaf_ioctl_HDIO_SET_NOWERR(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_PIO_MODE)) {
+		return var_leaf_ioctl_HDIO_SET_PIO_MODE(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_UNMASKINTR)) {
+		return var_leaf_ioctl_HDIO_SET_UNMASKINTR(tcp, code, arg);
+	} else if ((code) == (HDIO_SET_WCACHE)) {
+		return var_leaf_ioctl_HDIO_SET_WCACHE(tcp, code, arg);
+	} else if ((code) == (HDIO_UNREGISTER_HWIF)) {
+		return var_leaf_ioctl_HDIO_UNREGISTER_HWIF(tcp, code, arg);
+	} else {
+		return var_leaf_ioctl_HDIO(tcp, code, arg);
+	}
+}
diff --git a/src/gen/generated.h b/src/gen/generated.h
new file mode 100644
index 000000000..ab8a7bab2
--- /dev/null
+++ b/src/gen/generated.h
@@ -0,0 +1,4 @@
+#include "defs.h"
+
+int
+var_ioctl_HDIO(struct tcb *tcp, unsigned int code, kernel_ulong_t arg);
diff --git a/src/hdio.c b/src/hdio.c
index 9a260a423..b681dc6fa 100644
--- a/src/hdio.c
+++ b/src/hdio.c
@@ -19,6 +19,8 @@ typedef struct hd_geometry struct_hd_geometry;
 
 #include "xlat/hdio_drive_cmds.h"
 
+#include "gen/generated.h"
+
 static int
 print_hdio_getgeo(struct tcb *const tcp, const kernel_ulong_t arg)
 {
@@ -113,7 +115,7 @@ MPERS_PRINTER_DECL(int, hdio_ioctl, struct tcb *const tcp,
 	case HDIO_DRIVE_CMD:
 		return print_hdio_drive_cmd(tcp, arg);
 	default:
-		return RVAL_DECODED;
+		return var_ioctl_HDIO(tcp, code, arg);
 	}
 
 	return RVAL_IOCTL_DECODED;
diff --git a/src/xlat/hdio_busstates.in b/src/xlat/hdio_busstates.in
new file mode 100644
index 000000000..9224700a7
--- /dev/null
+++ b/src/xlat/hdio_busstates.in
@@ -0,0 +1,5 @@
+#unconditional
+#value_indexed
+BUSSTATE_OFF
+BUSSTATE_ON
+BUSSTATE_TRISTATE
diff --git a/src/xlat/hdio_ide_nice.in b/src/xlat/hdio_ide_nice.in
new file mode 100644
index 000000000..6dd3bb0fd
--- /dev/null
+++ b/src/xlat/hdio_ide_nice.in
@@ -0,0 +1,5 @@
+1 << IDE_NICE_DSC_OVERLAP
+1 << IDE_NICE_ATAPI_OVERLAP
+1 << IDE_NICE_1
+1 << IDE_NICE_0
+1 << IDE_NICE_2
diff --git a/tests/ioctl_hdio.c b/tests/ioctl_hdio.c
index 96cd4696e..2d246c5fe 100644
--- a/tests/ioctl_hdio.c
+++ b/tests/ioctl_hdio.c
@@ -14,6 +14,10 @@
 #include <stdlib.h>
 #include <linux/hdreg.h>
 #include <sys/ioctl.h>
+#include "xlat.h"
+
+#include "xlat/hdio_busstates.h"
+#include "xlat/hdio_ide_nice.h"
 
 static const char *errstr;
 
@@ -59,7 +63,7 @@ main(int argc, char *argv[])
 	for (size_t i = 0; i < num_skip; i++) {
 		long ret = ioctl(-1, HDIO_GET_UNMASKINTR, 0);
 
-		printf("ioctl(-1, %s, 0) = %s%s\n",
+		printf("ioctl(-1, %s, NULL) = %s%s\n",
 		       XLAT_STR(HDIO_GET_UNMASKINTR), sprintrc(ret),
 		       ret == INJECT_RETVAL ? " (INJECTED)" : "");
 
@@ -72,7 +76,7 @@ main(int argc, char *argv[])
 
 	if (!locked)
 		error_msg_and_fail("Hasn't locked on ioctl(-1"
-				   ", HDIO_GET_UNMASKINTR, 0) returning %d",
+				   ", HDIO_GET_UNMASKINTR, NULL) returning %d",
 				   INJECT_RETVAL);
 #endif
 
@@ -83,40 +87,12 @@ main(int argc, char *argv[])
 		uint32_t cmd;
 		const char *str;
 	} unsupp_cmds[] = {
-		{ ARG_STR(HDIO_GET_UNMASKINTR) },
-		{ ARG_STR(HDIO_GET_MULTCOUNT) },
 		{ ARG_STR(HDIO_GET_QDMA) },
 		{ ARG_STR(HDIO_SET_XFER) },
-		{ ARG_STR(HDIO_OBSOLETE_IDENTITY) },
-		{ ARG_STR(HDIO_GET_KEEPSETTINGS) },
-		{ ARG_STR(HDIO_GET_32BIT) },
-		{ ARG_STR(HDIO_GET_NOWERR) },
-		{ ARG_STR(HDIO_GET_DMA) },
-		{ ARG_STR(HDIO_GET_NICE) },
-		{ ARG_STR(HDIO_GET_IDENTITY) },
-		{ ARG_STR(HDIO_GET_WCACHE) },
-		{ ARG_STR(HDIO_GET_ACOUSTIC) },
-		{ ARG_STR(HDIO_GET_ADDRESS) },
-		{ ARG_STR(HDIO_GET_BUSSTATE) },
 		{ ARG_STR(HDIO_TRISTATE_HWIF) },
-		{ ARG_STR(HDIO_DRIVE_RESET) },
 		{ ARG_STR(HDIO_DRIVE_TASKFILE) },
 		{ ARG_STR(HDIO_DRIVE_TASK) },
-		{ ARG_STR(HDIO_SET_MULTCOUNT) },
-		{ ARG_STR(HDIO_SET_UNMASKINTR) },
-		{ ARG_STR(HDIO_SET_KEEPSETTINGS) },
-		{ ARG_STR(HDIO_SET_32BIT) },
-		{ ARG_STR(HDIO_SET_NOWERR) },
-		{ ARG_STR(HDIO_SET_DMA) },
-		{ ARG_STR(HDIO_SET_PIO_MODE) },
-		{ ARG_STR(HDIO_SCAN_HWIF) },
-		{ ARG_STR(HDIO_UNREGISTER_HWIF) },
-		{ ARG_STR(HDIO_SET_NICE) },
-		{ ARG_STR(HDIO_SET_WCACHE) },
-		{ ARG_STR(HDIO_SET_ACOUSTIC) },
-		{ ARG_STR(HDIO_SET_BUSSTATE) },
 		{ ARG_STR(HDIO_SET_QDMA) },
-		{ ARG_STR(HDIO_SET_ADDRESS) },
 	};
 
 	for (size_t i = 0; i < ARRAY_SIZE(unsupp_cmds); i++) {
@@ -220,6 +196,185 @@ main(int argc, char *argv[])
 	}
 	printf("}) = %s\n", errstr);
 
+	/* HDIO_DRIVE_RESET */
+	printf("ioctl(-1, %s, NULL) = %s\n", XLAT_STR(HDIO_DRIVE_RESET), errstr);
+	do_ioctl_ptr(HDIO_DRIVE_RESET, 0);
+
+	printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(HDIO_DRIVE_RESET),
+		   (void *) 0xdeadbeef, errstr);
+	do_ioctl(HDIO_DRIVE_RESET, 0xdeadbeef);
+
+	printf("ioctl(-1, %s, [%#x, %#x, %#x]) = %s\n", XLAT_STR(HDIO_DRIVE_RESET),
+		   (unsigned) 0xdeadbeef, (unsigned) 0xAAAAAAAA, (unsigned) 0xbeefbeef, errstr);
+	int drive_reset_args[3] = {0xdeadbeef, 0xAAAAAAAA, 0xbeefbeef};
+	do_ioctl_ptr(HDIO_DRIVE_RESET, &drive_reset_args);
+
+	/* HDIO_SCAN_HWIF */
+	printf("ioctl(-1, %s, NULL) = %s\n", XLAT_STR(HDIO_SCAN_HWIF), errstr);
+	do_ioctl_ptr(HDIO_SCAN_HWIF, 0);
+
+	printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(HDIO_SCAN_HWIF),
+		   (void *) 0xdeadbeef, errstr);
+	do_ioctl(HDIO_SCAN_HWIF, 0xdeadbeef);
+
+	printf("ioctl(-1, %s, [%#x, %#x, %#x]) = %s\n", XLAT_STR(HDIO_SCAN_HWIF),
+		   (unsigned) 0xdeadbeef, (unsigned) 0xAAAAAAAA, (unsigned) 0xbeefbeef, errstr);
+	int scan_hwif_args[3] = {0xdeadbeef, 0xAAAAAAAA, 0xbeefbeef};
+	do_ioctl_ptr(HDIO_SCAN_HWIF, &scan_hwif_args);
+
+	/* Getters of the form ioctl(..., ..., &val) */
+	static const struct {
+		uint32_t cmd;
+		const char *str;
+	} getter_cmds[] = {
+		{ ARG_STR(HDIO_GET_32BIT) },
+		{ ARG_STR(HDIO_GET_ACOUSTIC) },
+		{ ARG_STR(HDIO_GET_ADDRESS) },
+		{ ARG_STR(HDIO_GET_DMA) },
+		{ ARG_STR(HDIO_GET_KEEPSETTINGS) },
+		{ ARG_STR(HDIO_GET_MULTCOUNT) },
+		{ ARG_STR(HDIO_GET_NOWERR) },
+		{ ARG_STR(HDIO_GET_UNMASKINTR) },
+		{ ARG_STR(HDIO_GET_WCACHE) },
+	};
+
+	for (size_t i = 0; i < ARRAY_SIZE(getter_cmds); i++) {
+		unsigned long val = 0xdeadbeef;
+
+		rc = do_ioctl_ptr(getter_cmds[i].cmd, &val);
+		printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(getter_cmds[i].cmd, getter_cmds[i].str));
+		if (rc >= 0) {
+			printf("[%lu]", val);
+		} else {
+			printf("%p", &val);
+		}
+		printf(") = %s\n", errstr);
+	}
+
+	/* Setters of the form ioctl(..., ..., val) */
+	static const struct {
+		uint32_t cmd;
+		const char *str;
+	} setter_cmds[] = {
+			{ ARG_STR(HDIO_SET_32BIT) },
+			{ ARG_STR(HDIO_SET_ACOUSTIC) },
+			{ ARG_STR(HDIO_SET_ADDRESS) },
+			{ ARG_STR(HDIO_SET_DMA) },
+			{ ARG_STR(HDIO_SET_KEEPSETTINGS) },
+			{ ARG_STR(HDIO_SET_MULTCOUNT) },
+			{ ARG_STR(HDIO_SET_NOWERR) },
+			{ ARG_STR(HDIO_SET_PIO_MODE) },
+			{ ARG_STR(HDIO_SET_UNMASKINTR) },
+			{ ARG_STR(HDIO_SET_WCACHE) },
+			{ ARG_STR(HDIO_UNREGISTER_HWIF) },
+	};
+
+	for (size_t i = 0; i < ARRAY_SIZE(setter_cmds); i++) {
+		unsigned long val = 0xdeadbeef;
+
+		rc = do_ioctl(setter_cmds[i].cmd, val);
+		printf("ioctl(-1, " XLAT_FMT ", %lu) = %s\n", XLAT_SEL(setter_cmds[i].cmd, setter_cmds[i].str),
+			   val, errstr);
+	}
+
+	/* HDIO_OBSOLETE_IDENTITY */
+	do_ioctl_ptr(HDIO_OBSOLETE_IDENTITY, NULL);
+	printf("ioctl(-1, %s, NULL) = %s\n", XLAT_STR(HDIO_OBSOLETE_IDENTITY), errstr);
+
+	char obsolete_identity[142];
+	rc = do_ioctl_ptr(HDIO_OBSOLETE_IDENTITY, obsolete_identity);
+
+	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_OBSOLETE_IDENTITY));
+
+	if (rc >= 0) {
+		print_quoted_memory(obsolete_identity, DEFAULT_STRLEN);
+		printf("...");
+	} else {
+		printf("%p", obsolete_identity);
+	}
+	printf(") = %s\n", errstr);
+
+	/* HDIO_GET_IDENTITY */
+	do_ioctl_ptr(HDIO_GET_IDENTITY, NULL);
+	printf("ioctl(-1, %s, NULL) = %s\n", XLAT_STR(HDIO_GET_IDENTITY), errstr);
+
+	char identity[512];
+	rc = do_ioctl_ptr(HDIO_GET_IDENTITY, identity);
+
+	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_GET_IDENTITY));
+
+	if (rc >= 0) {
+		print_quoted_memory(identity, DEFAULT_STRLEN);
+		printf("...");
+	} else {
+		printf("%p", identity);
+	}
+	printf(") = %s\n", errstr);
+
+	/* HDIO_GET_NICE */
+	unsigned long nice_val = 0xdeadffff;
+
+	rc = do_ioctl_ptr(HDIO_GET_NICE, &nice_val);
+	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_GET_NICE));
+	if (rc >= 0) {
+		printf("[");
+#if XLAT_RAW
+		printf("%#lx", nice_val);
+#else
+#if XLAT_VERBOSE
+			printf("%#lx /* ", nice_val);
+#endif
+		printflags(hdio_ide_nice, nice_val, "IDE_NICE_???");
+#if XLAT_VERBOSE
+			printf(" */");
+#endif
+#endif
+		printf("]");
+	} else {
+		printf("%p", &nice_val);
+	}
+	printf(") = %s\n", errstr);
+
+	/* HDIO_SET_NICE */
+	nice_val = 0xc0dec0de;
+	do_ioctl(HDIO_SET_NICE, nice_val);
+	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_SET_NICE));
+#if XLAT_RAW
+	printf("%#lx", nice_val);
+#else
+#if XLAT_VERBOSE
+	printf("%#lx /* ", nice_val);
+#endif
+	printflags(hdio_ide_nice, nice_val, "IDE_NICE_???");
+#if XLAT_VERBOSE
+	printf(" */");
+#endif
+#endif
+	printf(") = %s\n", errstr);
+
+	/* HDIO_GET_BUSSTATE */
+	unsigned long busstate_value = 0xdeadffff;
+
+	rc = do_ioctl_ptr(HDIO_GET_BUSSTATE, &busstate_value);
+	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_GET_BUSSTATE));
+	if (rc >= 0) {
+		printf("[");
+		printxval(hdio_busstates, busstate_value, "BUSSTATE_???");
+		printf("]");
+	} else {
+		printf("%p", &busstate_value);
+	}
+	printf(") = %s\n", errstr);
+
+
+	/* HDIO_SET_BUSSTATE */
+	busstate_value = 0xc0dec0de;
+
+	do_ioctl(HDIO_SET_BUSSTATE, busstate_value);
+	printf("ioctl(-1, %s, ", XLAT_STR(HDIO_SET_BUSSTATE));
+	printxval(hdio_busstates, busstate_value, "BUSSTATE_???");
+	printf(") = %s\n", errstr);
+
 	puts("+++ exited with 0 +++");
 	return 0;
 }
-- 
2.25.1



More information about the Strace-devel mailing list