3 * VBoxGuestLibR0 - Library initialization.
7 * Copyright (C) 2006-2016 Oracle Corporation
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
28 /*********************************************************************************************************************************
30 *********************************************************************************************************************************/
31 #define VBGL_DECL_DATA
32 #include "VBGLInternal.h"
34 #include <iprt/string.h>
35 #include <iprt/assert.h>
36 #include <iprt/semaphore.h>
39 /*********************************************************************************************************************************
41 *********************************************************************************************************************************/
42 /** The global VBGL instance data. */
46 * Used by vbglQueryDriverInfo and VbglInit to try get the host feature mask and
47 * version information (g_vbgldata::hostVersion).
49 * This was first implemented by the host in 3.1 and we quietly ignore failures
52 static void vbglR0QueryHostVersion (void)
54 VMMDevReqHostVersion
*pReq
;
56 int rc
= VbglGRAlloc ((VMMDevRequestHeader
**) &pReq
, sizeof (*pReq
), VMMDevReq_GetHostVersion
);
60 rc
= VbglGRPerform (&pReq
->header
);
64 g_vbgldata
.hostVersion
= *pReq
;
65 Log (("vbglR0QueryHostVersion: %u.%u.%ur%u %#x\n",
66 pReq
->major
, pReq
->minor
, pReq
->build
, pReq
->revision
, pReq
->features
));
69 VbglGRFree (&pReq
->header
);
73 #ifndef VBGL_VBOXGUEST
75 * The guest library uses lazy initialization for VMMDev port and memory,
76 * because these values are provided by the VBoxGuest driver and it might
77 * be loaded later than other drivers.
79 * The VbglEnter checks the current library status, tries to retrieve these
80 * values and fails if they are unavailable.
83 static void vbglQueryDriverInfo (void)
85 int rc
= VINF_SUCCESS
;
87 rc
= RTSemMutexRequest(g_vbgldata
.mutexDriverInit
, RT_INDEFINITE_WAIT
);
92 if (g_vbgldata
.status
== VbglStatusReady
)
94 RTSemMutexRelease(g_vbgldata
.mutexDriverInit
);
98 rc
= vbglDriverOpen(&g_vbgldata
.driver
);
103 * Try query the port info.
105 VBoxGuestPortInfo port
;
107 rc
= vbglDriverIOCtl (&g_vbgldata
.driver
,
108 VBOXGUEST_IOCTL_GETVMMDEVPORT
, &port
,
113 dprintf (("port = 0x%04X, mem = %p\n", port
.portAddress
, port
.pVMMDevMemory
));
115 g_vbgldata
.portVMMDev
= (RTIOPORT
)port
.portAddress
;
116 g_vbgldata
.pVMMDevMemory
= port
.pVMMDevMemory
;
118 g_vbgldata
.status
= VbglStatusReady
;
120 vbglR0QueryHostVersion();
123 RTSemMutexRelease(g_vbgldata
.mutexDriverInit
);
124 dprintf (("vbglQueryDriverInfo rc = %d\n", rc
));
126 #endif /* !VBGL_VBOXGUEST */
129 * Checks if VBGL has been initialized.
131 * The client library, this will lazily complete the initialization.
133 * @return VINF_SUCCESS or VERR_VBGL_NOT_INITIALIZED.
135 int vbglR0Enter (void)
139 #ifndef VBGL_VBOXGUEST
140 if (g_vbgldata
.status
== VbglStatusInitializing
)
142 vbglQueryDriverInfo ();
146 rc
= g_vbgldata
.status
== VbglStatusReady
? VINF_SUCCESS
: VERR_VBGL_NOT_INITIALIZED
;
148 // dprintf(("VbglEnter: rc = %d\n", rc));
153 int vbglInitCommon (void)
155 int rc
= VINF_SUCCESS
;
159 g_vbgldata
.status
= VbglStatusInitializing
;
161 rc
= VbglPhysHeapInit ();
165 /* other subsystems, none yet */
170 LogRel(("vbglInitCommon: VbglPhysHeapInit failed. rc=%Rrc\n", rc
));
171 g_vbgldata
.status
= VbglStatusNotInitialized
;
174 dprintf(("vbglInitCommon: rc = %d\n", rc
));
179 DECLVBGL(void) vbglTerminateCommon (void)
181 VbglPhysHeapTerminate ();
182 g_vbgldata
.status
= VbglStatusNotInitialized
;
187 #ifdef VBGL_VBOXGUEST
189 DECLVBGL(int) VbglInitPrimary(RTIOPORT portVMMDev
, VMMDevMemory
*pVMMDevMemory
)
191 int rc
= VINF_SUCCESS
;
193 # ifdef RT_OS_WINDOWS /** @todo r=bird: this doesn't make sense. Is there something special going on on windows? */
194 dprintf(("vbglInit: starts g_vbgldata.status %d\n", g_vbgldata
.status
));
196 if ( g_vbgldata
.status
== VbglStatusInitializing
197 || g_vbgldata
.status
== VbglStatusReady
)
199 /* Initialization is already in process. */
203 dprintf(("vbglInit: starts\n"));
206 rc
= vbglInitCommon ();
210 g_vbgldata
.portVMMDev
= portVMMDev
;
211 g_vbgldata
.pVMMDevMemory
= pVMMDevMemory
;
213 g_vbgldata
.status
= VbglStatusReady
;
215 vbglR0QueryHostVersion();
219 g_vbgldata
.status
= VbglStatusNotInitialized
;
225 DECLVBGL(void) VbglTerminate (void)
227 vbglTerminateCommon ();
233 #else /* !VBGL_VBOXGUEST */
235 DECLVBGL(int) VbglInitClient(void)
237 int rc
= VINF_SUCCESS
;
239 if ( g_vbgldata
.status
== VbglStatusInitializing
240 || g_vbgldata
.status
== VbglStatusReady
)
242 /* Initialization is already in process. */
246 rc
= vbglInitCommon ();
250 rc
= RTSemMutexCreate(&g_vbgldata
.mutexDriverInit
);
253 /* Try to obtain VMMDev port via IOCTL to VBoxGuest main driver. */
254 vbglQueryDriverInfo ();
256 # ifdef VBOX_WITH_HGCM
257 rc
= vbglR0HGCMInit ();
258 # endif /* VBOX_WITH_HGCM */
262 RTSemMutexDestroy(g_vbgldata
.mutexDriverInit
);
263 g_vbgldata
.mutexDriverInit
= NIL_RTSEMMUTEX
;
269 vbglTerminateCommon ();
277 DECLVBGL(void) VbglTerminate (void)
279 # ifdef VBOX_WITH_HGCM
280 vbglR0HGCMTerminate ();
283 /* driver open could fail, which does not prevent VbglInit from succeeding,
284 * close the driver only if it is opened */
285 if (vbglDriverIsOpened(&g_vbgldata
.driver
))
286 vbglDriverClose(&g_vbgldata
.driver
);
287 RTSemMutexDestroy(g_vbgldata
.mutexDriverInit
);
288 g_vbgldata
.mutexDriverInit
= NIL_RTSEMMUTEX
;
290 /* note: do vbglTerminateCommon as a last step since it zeroez up the g_vbgldata
291 * conceptually, doing vbglTerminateCommon last is correct
292 * since this is the reverse order to how init is done */
293 vbglTerminateCommon ();
298 int vbglGetDriver(VBGLDRIVER
**ppDriver
)
300 if (g_vbgldata
.status
!= VbglStatusReady
)
302 vbglQueryDriverInfo();
303 if (g_vbgldata
.status
!= VbglStatusReady
)
304 return VERR_TRY_AGAIN
;
306 *ppDriver
= &g_vbgldata
.driver
;
310 #endif /* !VBGL_VBOXGUEST */