[PATCH v3 3/5] drm: Add dispatcher and driver identification for DRM

Patrik Jakobsson
2015-07-01T12:52:46Z

* Makefile.am: Add compilation of drm.c
* defs.h: Declarations of drm functions
* drm.c: Utility functions for drm driver detection
* io.c: Dispatch drm ioctls
* ioctl.c: Distpatch generic and driver specific ioctls

Signed-off-by: Patrik Jakobsson <patrik.jakobsson-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
Makefile.am | 1 +
defs.h | 4 ++-
drm.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
io.c | 2 +-
ioctl.c | 6 +++-
5 files changed, 118 insertions(+), 3 deletions(-)
create mode 100644 drm.c

diff --git a/Makefile.am b/Makefile.am
index e2a0f74..99382bd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ strace_SOURCES = \
count.c \
desc.c \
dirent.c \
+ drm.c \
evdev.c \
execve.c \
exit.c \
diff --git a/defs.h b/defs.h
index 5b0670e..63e4585 100644
--- a/defs.h
+++ b/defs.h
@@ -573,8 +573,10 @@ extern const struct_ioctlent *ioctl_lookup(const unsigned int);
extern const struct_ioctlent *ioctl_next_match(const struct_ioctlent *);
extern void ioctl_print_code(const unsigned int);
extern int ioctl_decode(struct tcb *, const unsigned int, long);
-extern int ioctl_decode_command_number(const unsigned int);
+extern int ioctl_decode_command_number(struct tcb *, const unsigned int);
extern int block_ioctl(struct tcb *, const unsigned int, long);
+extern int drm_decode_number(struct tcb *tcp, unsigned int arg);
+extern int drm_ioctl(struct tcb *, const unsigned int, long);
extern int evdev_ioctl(struct tcb *, const unsigned int, long);
extern int loop_ioctl(struct tcb *, const unsigned int, long);
extern int mtd_ioctl(struct tcb *, const unsigned int, long);
diff --git a/drm.c b/drm.c
new file mode 100644
index 0000000..61df09f
--- /dev/null
+++ b/drm.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015 Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ * Patrik Jakobsson <patrik.jakobsson-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
+ */
+
+#include "defs.h"
+
+#include <drm.h>
+#include <linux/limits.h>
+
+#define DRM_MAX_NAME_LEN 128
+
+struct drm_ioctl_priv {
+ char name[DRM_MAX_NAME_LEN];
+};
+
+inline int drm_is_priv(const unsigned int num)
+{
+ return (_IOC_NR(num) >= DRM_COMMAND_BASE &&
+ _IOC_NR(num) < DRM_COMMAND_END);
+}
+
+static int drm_get_driver_name(struct tcb *tcp, char *name, size_t bufsize)
+{
+ char path[PATH_MAX];
+ char link[PATH_MAX];
+ int ret;
+
+ ret = getfdpath(tcp, tcp->u_arg[0], path, PATH_MAX - 1);
+ if (ret < 0)
+ return ret;
+
+ snprintf(link, PATH_MAX, "/sys/class/drm/%s/device/driver",
+ basename(path));
+
+ ret = readlink(link, path, PATH_MAX - 1);
+ if (ret < 0)
+ return ret;
+
+ path[ret] = '\0';
+ strncpy(name, basename(path), bufsize);
+
+ return 0;
+}
+
+int drm_is_driver(struct tcb *tcp, const char *name)
+{
+ struct drm_ioctl_priv *priv;
+ int ret;
+
+ /*
+ * If no private data is allocated we are detecting the driver name for
+ * the first time and must resolve it.
+ */
+ if (tcp->priv_data == NULL) {
+ tcp->priv_data = xcalloc(1, sizeof(struct drm_ioctl_priv));
+ priv = tcp->priv_data;
+
+ ret = drm_get_driver_name(tcp, priv->name, DRM_MAX_NAME_LEN);
+ if (ret)
+ return 0;
+ }
+
+ priv = tcp->priv_data;
+
+ return strncmp(name, priv->name, DRM_MAX_NAME_LEN) == 0;
+}
+
+int drm_decode_number(struct tcb *tcp, unsigned int arg)
+{
+ return 0;
+}
+
+int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+{
+ /* Free any allocated private data */
+ if (exiting(tcp) && tcp->priv_data != NULL) {
+ free(tcp->priv_data);
+ tcp->priv_data = NULL;
+ }
+
+ return 0;
+}
diff --git a/io.c b/io.c
index 30ed578..6810a45 100644
--- a/io.c
+++ b/io.c
@@ -391,7 +391,7 @@ SYS_FUNC(ioctl)
if (entering(tcp)) {
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
- if (!ioctl_decode_command_number(tcp->u_arg[1])) {
+ if (!ioctl_decode_command_number(tcp, tcp->u_arg[1])) {
iop = ioctl_lookup(tcp->u_arg[1]);
if (iop) {
tprints(iop->symbol);
diff --git a/ioctl.c b/ioctl.c
index c67d048..0b3dd3f 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -182,7 +182,7 @@ hiddev_decode_number(unsigned int arg)
}

int
-ioctl_decode_command_number(unsigned int arg)
+ioctl_decode_command_number(struct tcb *tcp, unsigned int arg)
{
switch (_IOC_TYPE(arg)) {
case 'E':
@@ -204,6 +204,8 @@ ioctl_decode_command_number(unsigned int arg)
return 1;
}
return 0;
+ case 'd':
+ return drm_decode_number(tcp, arg);
case 'j':
if (_IOC_DIR(arg) == _IOC_READ && _IOC_NR(arg) == 0x13) {
tprintf("JSIOCGNAME(%u)", _IOC_SIZE(arg));
@@ -243,6 +245,8 @@ ioctl_decode(struct tcb *tcp, unsigned int code, long arg)
case 0x22:
return scsi_ioctl(tcp, code, arg);
#endif
+ case 'd':
+ return drm_ioctl(tcp, code, arg);
case 'L':
return loop_ioctl(tcp, code, arg);
case 'M':
--
2.1.4

------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.