VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuestLib/Init.cpp@ 68550

Last change on this file since 68550 was 68550, checked in by vboxsync, 7 years ago

merging vbglioc r117689: Initial VBoxGuest I/O control changes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/* $Id: Init.cpp 68550 2017-08-31 12:09:41Z vboxsync $ */
2/** @file
3 * VBoxGuestLibR0 - Library initialization.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
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.
16 *
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.
22 *
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.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define VBGL_DECL_DATA
32#include "VBGLInternal.h"
33
34#include <iprt/string.h>
35#include <iprt/assert.h>
36#include <iprt/semaphore.h>
37
38
39/*********************************************************************************************************************************
40* Global Variables *
41*********************************************************************************************************************************/
42/** The global VBGL instance data. */
43VBGLDATA g_vbgldata;
44
45
46/**
47 * Used by vbglQueryDriverInfo and VbglInit to try get the host feature mask and
48 * version information (g_vbgldata::hostVersion).
49 *
50 * This was first implemented by the host in 3.1 and we quietly ignore failures
51 * for that reason.
52 */
53static void vbglR0QueryHostVersion(void)
54{
55 VMMDevReqHostVersion *pReq;
56 int rc = VbglGRAlloc((VMMDevRequestHeader **) &pReq, sizeof (*pReq), VMMDevReq_GetHostVersion);
57 if (RT_SUCCESS(rc))
58 {
59 rc = VbglGRPerform(&pReq->header);
60 if (RT_SUCCESS(rc))
61 {
62 g_vbgldata.hostVersion = *pReq;
63 Log(("vbglR0QueryHostVersion: %u.%u.%ur%u %#x\n",
64 pReq->major, pReq->minor, pReq->build, pReq->revision, pReq->features));
65 }
66
67 VbglGRFree(&pReq->header);
68 }
69}
70
71
72#ifndef VBGL_VBOXGUEST
73/**
74 * The guest library uses lazy initialization for VMMDev port and memory,
75 * because these values are provided by the VBoxGuest driver and it might
76 * be loaded later than other drivers.
77 *
78 * The VbglEnter checks the current library status, tries to retrieve these
79 * values and fails if they are unavailable.
80 */
81static void vbglQueryDriverInfo(void)
82{
83 int rc = RTSemMutexRequest(g_vbgldata.hMtxIdcSetup, RT_INDEFINITE_WAIT);
84 if (RT_SUCCESS(rc))
85 {
86 if (g_vbgldata.status == VbglStatusReady)
87 { /* likely */ }
88 else
89 {
90 rc = VbglR0IdcOpen(&g_vbgldata.IdcHandle,
91 VBGL_IOC_VERSION /*uReqVersion*/,
92 VBGL_IOC_VERSION & UINT32_C(0xffff0000) /*uMinVersion*/,
93 NULL /*puSessionVersion*/, NULL /*puDriverVersion*/, NULL /*puDriverRevision*/);
94 if (RT_SUCCESS(rc))
95 {
96 /*
97 * Try query the port info.
98 */
99 VBGLIOCGETVMMDEVIOINFO PortInfo;
100 RT_ZERO(PortInfo);
101 VBGLREQHDR_INIT(&PortInfo.Hdr, GET_VMMDEV_IO_INFO);
102 rc = VbglR0IdcCall(&g_vbgldata.IdcHandle, VBGL_IOCTL_GET_VMMDEV_IO_INFO, &PortInfo.Hdr, sizeof(PortInfo));
103 if (RT_SUCCESS(rc))
104 {
105 dprintf(("Port I/O = 0x%04x, MMIO = %p\n", PortInfo.u.Out.IoPort, PortInfo.u.Out.pvVmmDevMapping));
106
107 g_vbgldata.portVMMDev = PortInfo.u.Out.IoPort;
108 g_vbgldata.pVMMDevMemory = (VMMDevMemory *)PortInfo.u.Out.pvVmmDevMapping;
109 g_vbgldata.status = VbglStatusReady;
110
111 vbglR0QueryHostVersion();
112 }
113 }
114
115 dprintf(("vbglQueryDriverInfo rc = %Rrc\n", rc));
116 }
117
118 RTSemMutexRelease(g_vbgldata.hMtxIdcSetup);
119 }
120}
121#endif /* !VBGL_VBOXGUEST */
122
123/**
124 * Checks if VBGL has been initialized.
125 *
126 * The client library, this will lazily complete the initialization.
127 *
128 * @return VINF_SUCCESS or VERR_VBGL_NOT_INITIALIZED.
129 */
130int vbglR0Enter(void)
131{
132 if (g_vbgldata.status == VbglStatusReady)
133 return VINF_SUCCESS;
134
135#ifndef VBGL_VBOXGUEST
136 if (g_vbgldata.status == VbglStatusInitializing)
137 {
138 vbglQueryDriverInfo();
139 if (g_vbgldata.status == VbglStatusReady)
140 return VINF_SUCCESS;
141 }
142#endif
143 return VERR_VBGL_NOT_INITIALIZED;
144}
145
146
147static int vbglInitCommon(void)
148{
149 int rc;
150
151 RT_ZERO(g_vbgldata);
152 g_vbgldata.status = VbglStatusInitializing;
153
154 rc = VbglPhysHeapInit();
155 if (RT_SUCCESS(rc))
156 {
157 dprintf(("vbglInitCommon: returns rc = %d\n", rc));
158 return rc;
159 }
160
161 LogRel(("vbglInitCommon: VbglPhysHeapInit failed: rc=%Rrc\n", rc));
162 g_vbgldata.status = VbglStatusNotInitialized;
163 return rc;
164}
165
166
167static void vbglTerminateCommon(void)
168{
169 VbglPhysHeapTerminate();
170 g_vbgldata.status = VbglStatusNotInitialized;
171}
172
173#ifdef VBGL_VBOXGUEST
174
175DECLVBGL(int) VbglInitPrimary(RTIOPORT portVMMDev, VMMDevMemory *pVMMDevMemory)
176{
177 int rc;
178
179# ifdef RT_OS_WINDOWS /** @todo r=bird: this doesn't make sense. Is there something special going on on windows? */
180 dprintf(("vbglInit: starts g_vbgldata.status %d\n", g_vbgldata.status));
181
182 if ( g_vbgldata.status == VbglStatusInitializing
183 || g_vbgldata.status == VbglStatusReady)
184 {
185 /* Initialization is already in process. */
186 return VINF_SUCCESS;
187 }
188# else
189 dprintf(("vbglInit: starts\n"));
190# endif
191
192 rc = vbglInitCommon();
193 if (RT_SUCCESS(rc))
194 {
195 g_vbgldata.portVMMDev = portVMMDev;
196 g_vbgldata.pVMMDevMemory = pVMMDevMemory;
197 g_vbgldata.status = VbglStatusReady;
198
199 vbglR0QueryHostVersion();
200 return VINF_SUCCESS;
201 }
202
203 g_vbgldata.status = VbglStatusNotInitialized;
204 return rc;
205}
206
207DECLVBGL(void) VbglR0TerminatePrimary(void)
208{
209 vbglTerminateCommon();
210}
211
212
213#else /* !VBGL_VBOXGUEST */
214
215DECLVBGL(int) VbglR0InitClient(void)
216{
217 int rc;
218
219 /** @todo r=bird: explain why we need to be doing this, please... */
220 if ( g_vbgldata.status == VbglStatusInitializing
221 || g_vbgldata.status == VbglStatusReady)
222 {
223 /* Initialization is already in process. */
224 return VINF_SUCCESS;
225 }
226
227 rc = vbglInitCommon();
228 if (RT_SUCCESS(rc))
229 {
230 rc = RTSemMutexCreate(&g_vbgldata.hMtxIdcSetup);
231 if (RT_SUCCESS(rc))
232 {
233 /* Try to obtain VMMDev port via IOCTL to VBoxGuest main driver. */
234 vbglQueryDriverInfo();
235
236# ifdef VBOX_WITH_HGCM
237 rc = VbglR0HGCMInit();
238# endif
239 if (RT_SUCCESS(rc))
240 return VINF_SUCCESS;
241
242 RTSemMutexDestroy(g_vbgldata.hMtxIdcSetup);
243 g_vbgldata.hMtxIdcSetup = NIL_RTSEMMUTEX;
244 }
245 vbglTerminateCommon();
246 }
247
248 return rc;
249}
250
251DECLVBGL(void) VbglR0TerminateClient(void)
252{
253# ifdef VBOX_WITH_HGCM
254 VbglR0HGCMTerminate();
255# endif
256
257 /* driver open could fail, which does not prevent VbglInit from succeeding,
258 * close the driver only if it is opened */
259 VbglR0IdcClose(&g_vbgldata.IdcHandle);
260 RTSemMutexDestroy(g_vbgldata.hMtxIdcSetup);
261 g_vbgldata.hMtxIdcSetup = NIL_RTSEMMUTEX;
262
263 /* note: do vbglTerminateCommon as a last step since it zeroez up the g_vbgldata
264 * conceptually, doing vbglTerminateCommon last is correct
265 * since this is the reverse order to how init is done */
266 vbglTerminateCommon();
267}
268
269
270int VBOXCALL vbglR0QueryIdcHandle(PVBGLIDCHANDLE *ppIdcHandle)
271{
272 if (g_vbgldata.status == VbglStatusReady)
273 { /* likely */ }
274 else
275 {
276 vbglQueryDriverInfo();
277 if (g_vbgldata.status != VbglStatusReady)
278 {
279 *ppIdcHandle = NULL;
280 return VERR_TRY_AGAIN;
281 }
282 }
283
284 *ppIdcHandle = &g_vbgldata.IdcHandle;
285 return VINF_SUCCESS;
286}
287
288#endif /* !VBGL_VBOXGUEST */
Note: See TracBrowser for help on using the repository browser.

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