Now About Social Code
summaryrefslogtreecommitdiff
path: root/drvemu.c
blob: 5499675ee58a3bfadaeb6c6c6ed4130fcde542f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <dlfcn.h>

#include <dirent.h>

#include <sys/mman.h>
#include <sys/syscall.h>

#include <asm-generic/ioctl.h>

#include "xf86drm.h"

#define DRM_PVR_RESERVED1 (DRM_COMMAND_BASE + 0)
#define DRM_PVR_RESERVED2 (DRM_COMMAND_BASE + 1)
#define DRM_PVR_RESERVED3 (DRM_COMMAND_BASE + 2)
#define DRM_PVR_RESERVED4 (DRM_COMMAND_BASE + 3)
#define DRM_PVR_RESERVED5 (DRM_COMMAND_BASE + 4)
#define DRM_PVR_RESERVED6 (DRM_COMMAND_BASE + 5)

/* PVR includes */
#define SUPPORT_MEMINFO_IDS
#define SUPPORT_DRI_DRM_EXT
#include <config_kernel.h>
#include <sgxfeaturedefs.h>
#include <pvr_bridge.h>
#include <sgx_bridge.h>
#include <pvr_drm_shared.h>
#include <sgxconfig.h>
#include <sgx_mkif_km.h>
//#include <pvr_drm.h>

static int false_fd = 10241024;

#define PROLOG(func) \
    static typeof(func) *orig_##func = NULL; \
    if(!orig_##func) \
        orig_##func = dlsym(RTLD_NEXT, #func);

int open(const char *pathname, int flags, mode_t mode) {
    printf("Called open on %s (%d)\n", pathname, flags);
    PROLOG(open);
    return orig_open(pathname, flags, mode);
}

int open64(const char *pathname, int flags, ...) {
    printf("Called open64 on %s (%d)\n", pathname, flags);
    PROLOG(open64);
    int fd = orig_open64(pathname, flags);
    if (strcmp(pathname, "/dev/dri/renderD128") == 0) {
        printf("Spoofing FD!\n");
        return false_fd;
    }
    return fd;
}

#define DEV_NAME "pvr"
#define DEV_DATE "20110701"
#define DEV_DESC "Imagination Technologies PVR DRM"

static bool spoof_ioctl(int fd, int request, void *ptr) {
    int ioctl_nr = _IOC_NR(request);
    switch(ioctl_nr) {
        case _IOC_NR(DRM_IOCTL_VERSION): {
            printf("Spoofing device info\n");
            drmVersionPtr version = (drmVersionPtr)ptr;
            version->version_major = 1;
            version->version_minor = 13;
            version->version_patchlevel = 3341330;
            version->name_len = sizeof(DEV_NAME);
            version->date_len = sizeof(DEV_DATE);
            version->desc_len = sizeof(DEV_DESC);

            if (version->name)
                strcpy(version->name, DEV_NAME);
            if (version->date)
                strcpy(version->date, DEV_DATE);
            if (version->desc)
                strcpy(version->desc, DEV_DESC);

            break;
        }

#if 0
        case _IOC_NR(DRM_IOCTL_GET_MAGIC):
            printf(">>> ioctl(DRM_IOCTL_GET_MAGIC)\n");
            break;
        case _IOC_NR(DRM_IOCTL_GET_UNIQUE):
            printf(">>> ioctl(DRM_IOCTL_GET_UNIQUE)\n");
            break;
        case _IOC_NR(DRM_IOCTL_SET_VERSION):
            printf(">>> ioctl(DRM_IOCTL_SET_VERSION)\n");
            {
                struct drm_set_version *data = ptr;
                printf("\t%d %d %d %d\n", data->drm_di_major,
                                        data->drm_di_minor,
                                        data->drm_dd_major,
                                        data->drm_dd_minor);
            }
            break;
#endif
        case _IOC_NR(DRM_IOCTL_DROP_MASTER):
            printf(">>> ioctl(DRM_IOCTL_DROP_MASTER)\n");
            return 0;
        case PVR_DRM_SRVKM_CMD:
            printf("srv command 0x%x\n", PVR_DRM_SRVKM_CMD);
            //fwrite(ptr, 1, sizeof(PVRSRV_BRIDGE_PACKAGE), log_file);
            //PPRINT(stdout, ptr, PVRSRV_BRIDGE_PACKAGE);
            //return pvrsrv_ioctl(fd, ptr);
            break;
        case PVR_DRM_IS_MASTER_CMD:
            printf(">>> ioctl(PVR_DRM_IS_MASTER_CMD) 0x%x\n", PVR_DRM_SRVKM_CMD);
            /* From KMD source code this seems to always return 0 */
            break;
        default:
            printf("Unimplemented ioctl 0x%x\n", ioctl_nr);
            assert(false);
            break;
    }
    return 0;
}

int ioctl(int fd, int request, ...) {
    PROLOG(ioctl);
    int ioc_size = _IOC_SIZE(request);
    bool pvr = fd == false_fd;

    //printf("Size is %d\n", ioc_size);
    void *ptr = NULL;
    if(ioc_size) {
        va_list args;
        va_start(args, request);
        ptr = va_arg(args, void *);
        va_end(args);
    }

    printf("Got ioctl %d!\n", fd);

    if (pvr)
        return spoof_ioctl(fd, request, ptr);
    else
        return orig_ioctl(fd, request, ptr);
}

int openat(int dirfd, const char *pathname, int flags, ...) {
    printf("Called openat on %s (%d) (%d)\n", pathname, dirfd, flags);
    PROLOG(openat);

    return orig_openat(dirfd, pathname, flags);
}

int openat64(int fd, const char * path, int oflag, ...) {
    printf("Called openat64 %s\n", path);
    PROLOG(openat64);
    return orig_openat64(fd, path, oflag);
}

DIR *opendir(const char *dirname) {
    printf("Opening dir %s\n", dirname);
    PROLOG(opendir);
    return orig_opendir(dirname);
}

struct dirent *readdir(DIR *dirp) {
    PROLOG(readdir);
    struct dirent *out = orig_readdir(dirp);
    if (out) {
        //printf("Reading %d %d %s\n", (int)out->d_type, (int)out->d_reclen, (char*)out->d_name);
    }
    return out;
}