~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 *
 
3
 * VBox host drivers - Ring-0 support drivers - Darwin host:
 
4
 * Darwin implementations for support library
 
5
 */
 
6
 
 
7
/*
 
8
 * Copyright (C) 2006-2007 innotek GmbH
 
9
 *
 
10
 * This file is part of VirtualBox Open Source Edition (OSE), as
 
11
 * available from http://www.virtualbox.org. This file is free software;
 
12
 * you can redistribute it and/or modify it under the terms of the GNU
 
13
 * General Public License as published by the Free Software Foundation,
 
14
 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
 
15
 * distribution. VirtualBox OSE is distributed in the hope that it will
 
16
 * be useful, but WITHOUT ANY WARRANTY of any kind.
 
17
 */
 
18
 
 
19
 
 
20
/*******************************************************************************
 
21
*   Header Files                                                               *
 
22
*******************************************************************************/
 
23
#define LOG_GROUP LOG_GROUP_SUP
 
24
#include <VBox/types.h>
 
25
#include <VBox/sup.h>
 
26
#include <VBox/param.h>
 
27
#include <VBox/err.h>
 
28
#include <VBox/log.h>
 
29
#include <iprt/path.h>
 
30
#include <iprt/assert.h>
 
31
#include <iprt/err.h>
 
32
#include <iprt/string.h>
 
33
#include "SUPLibInternal.h"
 
34
#include "SUPDRVIOC.h"
 
35
 
 
36
#include <sys/fcntl.h>
 
37
#include <sys/ioctl.h>
 
38
#include <errno.h>
 
39
#include <unistd.h>
 
40
#include <stdlib.h>
 
41
#include <mach/mach_port.h>
 
42
#include <IOKit/IOKitLib.h>
 
43
 
 
44
 
 
45
/*******************************************************************************
 
46
*   Defined Constants And Macros                                               *
 
47
*******************************************************************************/
 
48
/** BSD Device name. */
 
49
#define DEVICE_NAME     "/dev/vboxdrv"
 
50
/** The IOClass key of the service (see SUPDrv-darwin.cpp / Info.plist). */
 
51
#define IOCLASS_NAME    "org_virtualbox_SupDrv"
 
52
 
 
53
 
 
54
/*******************************************************************************
 
55
*   Global Variables                                                           *
 
56
*******************************************************************************/
 
57
/** Handle to the open device. */
 
58
static int              g_hDevice = -1;
 
59
/** The IOMasterPort. */
 
60
static mach_port_t      g_MasterPort = 0;
 
61
/** The current service connection. */
 
62
static io_connect_t     g_Connection = NULL;
 
63
 
 
64
 
 
65
int suplibOsInit(size_t cbReserve)
 
66
{
 
67
    /*
 
68
     * Check if already initialized.
 
69
     */
 
70
    if (g_hDevice >= 0)
 
71
        return VINF_SUCCESS;
 
72
 
 
73
    /*
 
74
     * Open the IOKit client first - The first step is finding the service.
 
75
     */
 
76
    mach_port_t MasterPort;
 
77
    kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort);
 
78
    if (kr != kIOReturnSuccess)
 
79
    {
 
80
        LogRel(("IOMasterPort -> %d\n", kr));
 
81
        return VERR_GENERAL_FAILURE;
 
82
    }
 
83
 
 
84
    CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_NAME);
 
85
    if (!ClassToMatch)
 
86
    {
 
87
        LogRel(("IOServiceMatching(\"%s\") failed.\n", IOCLASS_NAME));
 
88
        return VERR_GENERAL_FAILURE;
 
89
    }
 
90
 
 
91
    /* Create an io_iterator_t for all instances of our drivers class that exist in the IORegistry. */
 
92
    io_iterator_t Iterator;
 
93
    kr = IOServiceGetMatchingServices(g_MasterPort, ClassToMatch, &Iterator);
 
94
    if (kr != kIOReturnSuccess)
 
95
    {
 
96
        LogRel(("IOServiceGetMatchingServices returned %d\n", kr));
 
97
        return VERR_GENERAL_FAILURE;
 
98
    }
 
99
 
 
100
    /* Get the first item in the iterator and release it. */
 
101
    io_service_t ServiceObject = IOIteratorNext(Iterator);
 
102
    IOObjectRelease(Iterator);
 
103
    if (!ServiceObject)
 
104
    {
 
105
        LogRel(("Couldn't find any matches.\n"));
 
106
        return VERR_GENERAL_FAILURE;
 
107
    }
 
108
 
 
109
    /*
 
110
     * Open the service.
 
111
     * This will cause the user client class in SUPDrv-darwin.cpp to be instantiated.
 
112
     */
 
113
    kr = IOServiceOpen(ServiceObject, mach_task_self(), 0, &g_Connection);
 
114
    IOObjectRelease(ServiceObject);
 
115
    if (kr != kIOReturnSuccess)
 
116
    {
 
117
        LogRel(("IOServiceOpen returned %d\n", kr));
 
118
        return VERR_GENERAL_FAILURE;
 
119
    }
 
120
 
 
121
    /*
 
122
     * Now, try open the BSD device.
 
123
     */
 
124
    g_hDevice = open(DEVICE_NAME, O_RDWR, 0);
 
125
    if (g_hDevice < 0)
 
126
    {
 
127
        int rc = errno;
 
128
        LogRel(("Failed to open \"%s\", errno=%d\n", rc));
 
129
        kr = IOServiceClose(g_Connection);
 
130
        if (kr != kIOReturnSuccess)
 
131
            LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr));
 
132
        return RTErrConvertFromErrno(rc);
 
133
    }
 
134
 
 
135
    /*
 
136
     * We're done.
 
137
     */
 
138
    NOREF(cbReserve);
 
139
    return VINF_SUCCESS;
 
140
}
 
141
 
 
142
 
 
143
int suplibOsTerm(void)
 
144
{
 
145
    /*
 
146
     * Check if we're initited at all.
 
147
     */
 
148
    if (g_hDevice >= 0)
 
149
    {
 
150
        if (close(g_hDevice))
 
151
            AssertFailed();
 
152
        g_hDevice = -1;
 
153
    }
 
154
 
 
155
    /*
 
156
     * Close the connection to the IOService and destroy the connection handle.
 
157
     */
 
158
    if (g_Connection)
 
159
    {
 
160
        kern_return_t kr = IOServiceClose(g_Connection);
 
161
        if (kr != kIOReturnSuccess)
 
162
        {
 
163
            LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr));
 
164
            AssertFailed();
 
165
        }
 
166
        g_Connection = NULL;
 
167
    }
 
168
 
 
169
    return VINF_SUCCESS;
 
170
}
 
171
 
 
172
 
 
173
/**
 
174
 * Installs anything required by the support library.
 
175
 *
 
176
 * @returns 0 on success.
 
177
 * @returns error code on failure.
 
178
 */
 
179
int suplibOsInstall(void)
 
180
{
 
181
//    int rc = mknod(DEVICE_NAME, S_IFCHR, );
 
182
 
 
183
    return VERR_NOT_IMPLEMENTED;
 
184
}
 
185
 
 
186
 
 
187
/**
 
188
 * Installs anything required by the support library.
 
189
 *
 
190
 * @returns 0 on success.
 
191
 * @returns error code on failure.
 
192
 */
 
193
int suplibOsUninstall(void)
 
194
{
 
195
//    int rc = unlink(DEVICE_NAME);
 
196
 
 
197
    return VERR_NOT_IMPLEMENTED;
 
198
}
 
199
 
 
200
 
 
201
/**
 
202
 * Send a I/O Control request to the device.
 
203
 *
 
204
 * @returns 0 on success.
 
205
 * @returns VBOX error code on failure.
 
206
 * @param   uFunction   IO Control function.
 
207
 * @param   pvIn        Input data buffer.
 
208
 * @param   cbIn        Size of input data.
 
209
 * @param   pvOut       Output data buffer.
 
210
 * @param   cbOut       Size of output data.
 
211
 */
 
212
int suplibOsIOCtl(unsigned uFunction, void *pvIn, size_t cbIn, void *pvOut, size_t cbOut)
 
213
{
 
214
    AssertMsg(g_hDevice != -1, ("SUPLIB not initiated successfully!\n"));
 
215
    /*
 
216
     * Issue device iocontrol.
 
217
     */
 
218
    SUPDRVIOCTLDATA Args;
 
219
    Args.pvIn = pvIn;
 
220
    Args.cbIn = cbIn;
 
221
    Args.pvOut = pvOut;
 
222
    Args.cbOut = cbOut;
 
223
 
 
224
    if (ioctl(g_hDevice, uFunction, &Args) >= 0)
 
225
        return 0;
 
226
    /* This is the reverse operation of the one found in SUPDrv-linux.c */
 
227
    switch (errno)
 
228
    {
 
229
        case EACCES: return VERR_GENERAL_FAILURE;
 
230
        case EINVAL: return VERR_INVALID_PARAMETER;
 
231
        case ENOSYS: return VERR_INVALID_MAGIC;
 
232
        case ENXIO:  return VERR_INVALID_HANDLE;
 
233
        case EFAULT: return VERR_INVALID_POINTER;
 
234
        case ENOLCK: return VERR_LOCK_FAILED;
 
235
        case EEXIST: return VERR_ALREADY_LOADED;
 
236
    }
 
237
 
 
238
    return RTErrConvertFromErrno(errno);
 
239
}
 
240
 
 
241
#ifdef VBOX_WITHOUT_IDT_PATCHING
 
242
int suplibOSIOCtlFast(unsigned uFunction)
 
243
{
 
244
    int rc = ioctl(g_hDevice, uFunction, NULL);
 
245
    if (rc == -1)
 
246
        rc = errno;
 
247
    return rc;
 
248
}
 
249
#endif
 
250
 
 
251
 
 
252
/**
 
253
 * Allocate a number of zero-filled pages in user space.
 
254
 *
 
255
 * @returns VBox status code.
 
256
 * @param   cPages      Number of pages to allocate.
 
257
 * @param   ppvPages    Where to return the base pointer.
 
258
 */
 
259
int suplibOsPageAlloc(size_t cPages, void **ppvPages)
 
260
{
 
261
    *ppvPages = valloc(cPages << PAGE_SHIFT);
 
262
    if (*ppvPages)
 
263
    {
 
264
        memset(*ppvPages, 0, cPages << PAGE_SHIFT);
 
265
        return VINF_SUCCESS;
 
266
    }
 
267
    return RTErrConvertFromErrno(errno);
 
268
}
 
269
 
 
270
 
 
271
/**
 
272
 * Frees pages allocated by suplibOsPageAlloc().
 
273
 *
 
274
 * @returns VBox status code.
 
275
 * @param   pvPages     Pointer to pages.
 
276
 */
 
277
int suplibOsPageFree(void *pvPages, size_t /* cPages */)
 
278
{
 
279
    free(pvPages);
 
280
    return VINF_SUCCESS;
 
281
}
 
282