VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp@ 10836

Last change on this file since 10836 was 10836, checked in by vboxsync, 17 years ago

supdrv: Fixed missing session clean on the mac when more than one client was active.

File size: 8.0 KB
Line 
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 Sun Microsystems, Inc.
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 (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * The contents of this file may alternatively be used under the terms
19 * of the Common Development and Distribution License Version 1.0
20 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
21 * VirtualBox OSE distribution, in which case the provisions of the
22 * CDDL are applicable instead of those of the GPL.
23 *
24 * You may elect to license modified versions of this file under the
25 * terms and conditions of either the GPL or the CDDL or both.
26 *
27 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
28 * Clara, CA 95054 USA or visit http://www.sun.com if you need
29 * additional information or have any questions.
30 */
31
32
33/*******************************************************************************
34* Header Files *
35*******************************************************************************/
36#define LOG_GROUP LOG_GROUP_SUP
37#include <VBox/types.h>
38#include <VBox/sup.h>
39#include <VBox/param.h>
40#include <VBox/err.h>
41#include <VBox/log.h>
42#include <iprt/path.h>
43#include <iprt/assert.h>
44#include <iprt/err.h>
45#include <iprt/string.h>
46#include "../SUPLibInternal.h"
47#include "../SUPDrvIOC.h"
48
49#include <sys/fcntl.h>
50#include <sys/ioctl.h>
51#include <errno.h>
52#include <unistd.h>
53#include <stdlib.h>
54#include <mach/mach_port.h>
55#include <IOKit/IOKitLib.h>
56
57
58/*******************************************************************************
59* Defined Constants And Macros *
60*******************************************************************************/
61/** BSD Device name. */
62#define DEVICE_NAME "/dev/vboxdrv"
63/** The IOClass key of the service (see SUPDrv-darwin.cpp / Info.plist). */
64#define IOCLASS_NAME "org_virtualbox_SupDrv"
65
66
67/*******************************************************************************
68* Global Variables *
69*******************************************************************************/
70/** Handle to the open device. */
71static int g_hDevice = -1;
72/** The IOMasterPort. */
73static mach_port_t g_MasterPort = 0;
74/** The current service connection. */
75static io_connect_t g_Connection = NULL;
76
77
78/**
79 * Opens the BSD device node.
80 *
81 * @returns VBox status code.
82 */
83static int suplibDarwinOpenDevice(void)
84{
85 /*
86 * Open the BSD device.
87 * This will connect to the session created when the SupDrvClient was
88 * started, so it has to be done after opening the service (IOC v9.1+).
89 */
90 g_hDevice = open(DEVICE_NAME, O_RDWR, 0);
91 if (g_hDevice < 0)
92 {
93 int rc;
94 switch (errno)
95 {
96 case ENODEV: rc = VERR_VM_DRIVER_LOAD_ERROR; break;
97 case EPERM:
98 case EACCES: rc = VERR_VM_DRIVER_NOT_ACCESSIBLE; break;
99 case ENOENT: rc = VERR_VM_DRIVER_NOT_INSTALLED; break;
100 default: rc = VERR_VM_DRIVER_OPEN_ERROR; break;
101 }
102 LogRel(("SUP: Failed to open \"%s\", errno=%d, rc=%Vrc\n", DEVICE_NAME, errno, rc));
103 return rc;
104 }
105
106 /*
107 * Mark the file handle close on exec.
108 */
109 if (fcntl(g_hDevice, F_SETFD, FD_CLOEXEC) != 0)
110 {
111 int err = errno;
112 int rc = RTErrConvertFromErrno(err);
113 LogRel(("suplibOSInit: setting FD_CLOEXEC failed, errno=%d (%Rrc)\n", err, rc));
114 close(g_hDevice);
115 g_hDevice = -1;
116 return rc;
117 }
118
119 return VINF_SUCCESS;
120}
121
122
123/**
124 * Opens the IOKit service, instantiating org_virtualbox_SupDrvClient.
125 *
126 * @returns VBox status code.
127 */
128static int suplibDarwinOpenService(void)
129{
130 /*
131 * Open the IOKit client first - The first step is finding the service.
132 */
133 mach_port_t MasterPort;
134 kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort);
135 if (kr != kIOReturnSuccess)
136 {
137 LogRel(("IOMasterPort -> %d\n", kr));
138 return VERR_GENERAL_FAILURE;
139 }
140
141 CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_NAME);
142 if (!ClassToMatch)
143 {
144 LogRel(("IOServiceMatching(\"%s\") failed.\n", IOCLASS_NAME));
145 return VERR_GENERAL_FAILURE;
146 }
147
148 /* Create an io_iterator_t for all instances of our drivers class that exist in the IORegistry. */
149 io_iterator_t Iterator;
150 kr = IOServiceGetMatchingServices(g_MasterPort, ClassToMatch, &Iterator);
151 if (kr != kIOReturnSuccess)
152 {
153 LogRel(("IOServiceGetMatchingServices returned %d\n", kr));
154 return VERR_GENERAL_FAILURE;
155 }
156
157 /* Get the first item in the iterator and release it. */
158 io_service_t ServiceObject = IOIteratorNext(Iterator);
159 IOObjectRelease(Iterator);
160 if (!ServiceObject)
161 {
162 LogRel(("SUP: Couldn't find any matches. The kernel module is probably not loaded.\n"));
163 return VERR_VM_DRIVER_NOT_INSTALLED;
164 }
165
166 /*
167 * Open the service.
168 *
169 * This will cause the user client class in SUPDrv-darwin.cpp to be
170 * instantiated and create a session for this process.
171 */
172 kr = IOServiceOpen(ServiceObject, mach_task_self(), 0, &g_Connection);
173 IOObjectRelease(ServiceObject);
174 if (kr != kIOReturnSuccess)
175 {
176 LogRel(("SUP: IOServiceOpen returned %d. Driver open failed.\n", kr));
177 return VERR_VM_DRIVER_OPEN_ERROR;
178 }
179
180 return VINF_SUCCESS;
181}
182
183int suplibOsInit(size_t cbReserve)
184{
185 NOREF(cbReserve);
186
187 /*
188 * Check if already initialized.
189 */
190 if (g_hDevice >= 0)
191 return VINF_SUCCESS;
192
193 /*
194 * Do the job.
195 */
196 int rc = suplibDarwinOpenService();
197 if (RT_SUCCESS(rc))
198 {
199 rc = suplibDarwinOpenDevice();
200 if (RT_FAILURE(rc))
201 {
202 kern_return_t kr = IOServiceClose(g_Connection);
203 if (kr != kIOReturnSuccess)
204 {
205 LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr));
206 AssertFailed();
207 }
208 g_Connection = NULL;
209 }
210 }
211
212 return rc;
213}
214
215
216int suplibOsTerm(void)
217{
218 /*
219 * Close the connection to the IOService.
220 * This will cause the SUPDRVSESSION to be closed (starting IOC 9.1).
221 */
222 if (g_Connection)
223 {
224 kern_return_t kr = IOServiceClose(g_Connection);
225 if (kr != kIOReturnSuccess)
226 {
227 LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr));
228 AssertFailed();
229 }
230 g_Connection = NULL;
231 }
232
233 /*
234 * Check if we're initited at all.
235 */
236 if (g_hDevice >= 0)
237 {
238 if (close(g_hDevice))
239 AssertFailed();
240 g_hDevice = -1;
241 }
242
243 return VINF_SUCCESS;
244}
245
246
247int suplibOsInstall(void)
248{
249 return VERR_NOT_IMPLEMENTED;
250}
251
252
253int suplibOsUninstall(void)
254{
255 return VERR_NOT_IMPLEMENTED;
256}
257
258
259int suplibOsIOCtl(uintptr_t uFunction, void *pvReq, size_t cbReq)
260{
261 AssertMsg(g_hDevice != -1, ("SUPLIB not initiated successfully!\n"));
262
263 if (RT_LIKELY(ioctl(g_hDevice, uFunction, pvReq) >= 0))
264 return VINF_SUCCESS;
265 return RTErrConvertFromErrno(errno);
266}
267
268
269int suplibOsIOCtlFast(uintptr_t uFunction)
270{
271 int rc = ioctl(g_hDevice, uFunction, NULL);
272 if (rc == -1)
273 rc = errno;
274 return rc;
275}
276
277
278int suplibOsPageAlloc(size_t cPages, void **ppvPages)
279{
280 *ppvPages = valloc(cPages << PAGE_SHIFT);
281 if (*ppvPages)
282 {
283 memset(*ppvPages, 0, cPages << PAGE_SHIFT);
284 return VINF_SUCCESS;
285 }
286 return RTErrConvertFromErrno(errno);
287}
288
289
290int suplibOsPageFree(void *pvPages, size_t /* cPages */)
291{
292 free(pvPages);
293 return VINF_SUCCESS;
294}
295
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette