VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp@ 10720

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

Increased the IOC version to 7.4 with the exporting of SUPR0ComponentQueryFactory and friends. Added release logging to darwin, windows and freebsd.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.0 KB
Line 
1/* $Id: SUPDrv-os2.cpp 10662 2008-07-15 14:36:00Z vboxsync $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - OS/2 specifics.
4 */
5
6/*
7 * Copyright (c) 2007 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#define LOG_GROUP LOG_GROUP_SUP_DRV
35#define __STDC_CONSTANT_MACROS
36#define __STDC_LIMIT_MACROS
37
38#include <os2ddk/bsekee.h>
39#undef RT_MAX
40
41#include "SUPDrvInternal.h"
42#include <VBox/version.h>
43#include <iprt/initterm.h>
44#include <iprt/string.h>
45#include <iprt/spinlock.h>
46#include <iprt/process.h>
47#include <iprt/assert.h>
48#include <VBox/log.h>
49#include <iprt/param.h>
50
51
52/*******************************************************************************
53* Global Variables *
54*******************************************************************************/
55/**
56 * Device extention & session data association structure.
57 */
58static SUPDRVDEVEXT g_DevExt;
59/** Spinlock protecting g_apSessionHashTab. */
60static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
61/** Hash table */
62static PSUPDRVSESSION g_apSessionHashTab[19];
63/** Calculates the index into g_apSessionHashTab.*/
64#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
65
66__BEGIN_DECLS
67/* Defined in SUPDrvA-os2.asm */
68extern uint16_t g_offLogHead;
69extern uint16_t volatile g_offLogTail;
70extern uint16_t const g_cchLogMax;
71extern char g_szLog[];
72/* (init only:) */
73extern char g_szInitText[];
74extern uint16_t g_cchInitText;
75extern uint16_t g_cchInitTextMax;
76__END_DECLS
77
78
79/*******************************************************************************
80* Internal Functions *
81*******************************************************************************/
82
83
84
85/**
86 * 32-bit Ring-0 initialization.
87 *
88 * @returns 0 on success, non-zero on failure.
89 * @param pszArgs Pointer to the device arguments.
90 */
91DECLASM(int) VBoxDrvInit(const char *pszArgs)
92{
93 dprintf(("VBoxDrvInit: pszArgs=%s\n", pszArgs));
94
95 /*
96 * Initialize the runtime.
97 */
98 int rc = RTR0Init(0);
99 if (RT_SUCCESS(rc))
100 {
101 /*
102 * Initialize the device extension.
103 */
104 rc = supdrvInitDevExt(&g_DevExt);
105 if (RT_SUCCESS(rc))
106 {
107 /*
108 * Initialize the session hash table.
109 */
110 rc = RTSpinlockCreate(&g_Spinlock);
111 if (RT_SUCCESS(rc))
112 {
113 /*
114 * Process the commandline. Later.
115 */
116 bool fVerbose = true;
117
118 /*
119 * Success
120 */
121 if (fVerbose)
122 {
123 strcpy(&g_szInitText[0],
124 "\r\n"
125 "VirtualBox.org Support Driver for OS/2 version " VBOX_VERSION_STRING "\r\n"
126 "Copyright (C) 2007 Knut St. Osmundsen\r\n"
127 "Copyright (C) 2007 Sun Microsystems, Inc.\r\n");
128 g_cchInitText = strlen(&g_szInitText[0]);
129 }
130 return VINF_SUCCESS;
131 }
132 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTSpinlockCreate failed, rc=%Vrc\n", rc);
133 supdrvDeleteDevExt(&g_DevExt);
134 }
135 else
136 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: supdrvInitDevExt failed, rc=%Vrc\n", rc);
137 RTR0Term();
138 }
139 else
140 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTR0Init failed, rc=%Vrc\n", rc);
141 return rc;
142}
143
144
145DECLASM(int) VBoxDrvOpen(uint16_t sfn)
146{
147 int rc;
148 PSUPDRVSESSION pSession;
149
150 /*
151 * Create a new session.
152 */
153 rc = supdrvCreateSession(&g_DevExt, true /* fUser */, &pSession);
154 if (RT_SUCCESS(rc))
155 {
156 pSession->sfn = sfn;
157
158 /*
159 * Insert it into the hash table.
160 */
161 unsigned iHash = SESSION_HASH(sfn);
162 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
163 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
164 pSession->pNextHash = g_apSessionHashTab[iHash];
165 g_apSessionHashTab[iHash] = pSession;
166 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
167 }
168
169 dprintf(("VBoxDrvOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
170 return rc;
171}
172
173
174DECLASM(int) VBoxDrvClose(uint16_t sfn)
175{
176 dprintf(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
177
178 /*
179 * Remove from the hash table.
180 */
181 PSUPDRVSESSION pSession;
182 const RTPROCESS Process = RTProcSelf();
183 const unsigned iHash = SESSION_HASH(sfn);
184 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
185 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
186
187 pSession = g_apSessionHashTab[iHash];
188 if (pSession)
189 {
190 if ( pSession->sfn == sfn
191 && pSession->Process == Process)
192 {
193 g_apSessionHashTab[iHash] = pSession->pNextHash;
194 pSession->pNextHash = NULL;
195 }
196 else
197 {
198 PSUPDRVSESSION pPrev = pSession;
199 pSession = pSession->pNextHash;
200 while (pSession)
201 {
202 if ( pSession->sfn == sfn
203 && pSession->Process == Process)
204 {
205 pPrev->pNextHash = pSession->pNextHash;
206 pSession->pNextHash = NULL;
207 break;
208 }
209
210 /* next */
211 pPrev = pSession;
212 pSession = pSession->pNextHash;
213 }
214 }
215 }
216 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
217 if (!pSession)
218 {
219 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
220 return VERR_INVALID_PARAMETER;
221 }
222
223 /*
224 * Close the session.
225 */
226 supdrvCloseSession(&g_DevExt, pSession);
227 return 0;
228}
229
230
231DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction, int32_t *prc)
232{
233 /*
234 * Find the session.
235 */
236 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
237 const RTPROCESS Process = RTProcSelf();
238 const unsigned iHash = SESSION_HASH(sfn);
239 PSUPDRVSESSION pSession;
240
241 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
242 pSession = g_apSessionHashTab[iHash];
243 if (pSession && pSession->Process != Process)
244 {
245 do pSession = pSession->pNextHash;
246 while ( pSession
247 && ( pSession->sfn != sfn
248 || pSession->Process != Process));
249 }
250 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
251 if (RT_UNLIKELY(!pSession))
252 {
253 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
254 return VERR_INVALID_PARAMETER;
255 }
256
257 /*
258 * Dispatch the fast IOCtl.
259 */
260 *prc = supdrvIOCtlFast(iFunction, &g_DevExt, pSession);
261 return 0;
262}
263
264
265DECLASM(int) VBoxDrvIOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData)
266{
267 /*
268 * Find the session.
269 */
270 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
271 const RTPROCESS Process = RTProcSelf();
272 const unsigned iHash = SESSION_HASH(sfn);
273 PSUPDRVSESSION pSession;
274
275 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
276 pSession = g_apSessionHashTab[iHash];
277 if (pSession && pSession->Process != Process)
278 {
279 do pSession = pSession->pNextHash;
280 while ( pSession
281 && ( pSession->sfn != sfn
282 || pSession->Process != Process));
283 }
284 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
285 if (!pSession)
286 {
287 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
288 return VERR_INVALID_PARAMETER;
289 }
290
291 /*
292 * Verify the category and dispatch the IOCtl.
293 */
294 if (RT_LIKELY(iCat == SUP_CTL_CATEGORY))
295 {
296 dprintf(("VBoxDrvIOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
297 Assert(pvParm);
298 Assert(!pvData);
299
300 /*
301 * Lock the header.
302 */
303 PSUPREQHDR pHdr = (PSUPREQHDR)pvParm;
304 AssertReturn(*pcbParm == sizeof(*pHdr), VERR_INVALID_PARAMETER);
305 KernVMLock_t Lock;
306 int rc = KernVMLock(VMDHL_WRITE, pHdr, *pcbParm, &Lock, (KernPageList_t *)-1, NULL);
307 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, *pcbParm, &Lock, rc), VERR_LOCK_FAILED);
308
309 /*
310 * Validate the header.
311 */
312 if (RT_LIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) == SUPREQHDR_FLAGS_MAGIC))
313 {
314 uint32_t cbReq = RT_MAX(pHdr->cbIn, pHdr->cbOut);
315 if (RT_LIKELY( pHdr->cbIn >= sizeof(*pHdr)
316 && pHdr->cbOut >= sizeof(*pHdr)
317 && cbReq <= _1M*16))
318 {
319 /*
320 * Lock the rest of the buffer if necessary.
321 */
322 if (((uintptr_t)pHdr & PAGE_OFFSET_MASK) + cbReq > PAGE_SIZE)
323 {
324 rc = KernVMUnlock(&Lock);
325 AssertMsgReturn(!rc, ("KernVMUnlock(Lock) -> %#x\n", rc), VERR_LOCK_FAILED);
326
327 rc = KernVMLock(VMDHL_WRITE, pHdr, cbReq, &Lock, (KernPageList_t *)-1, NULL);
328 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, cbReq, &Lock, rc), VERR_LOCK_FAILED);
329 }
330
331 /*
332 * Process the IOCtl.
333 */
334 rc = supdrvIOCtl(iFunction, &g_DevExt, pSession, pHdr);
335 }
336 else
337 {
338 OSDBGPRINT(("VBoxDrvIOCtl: max(%#x,%#x); iCmd=%#x\n", pHdr->cbIn, pHdr->cbOut, iFunction));
339 rc = VERR_INVALID_PARAMETER;
340 }
341 }
342 else
343 {
344 OSDBGPRINT(("VBoxDrvIOCtl: bad magic fFlags=%#x; iCmd=%#x\n", pHdr->fFlags, iFunction));
345 rc = VERR_INVALID_PARAMETER;
346 }
347
348 /*
349 * Unlock and return.
350 */
351 int rc2 = KernVMUnlock(&Lock);
352 AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);
353
354 dprintf2(("VBoxDrvIOCtl: returns %d\n", rc));
355 return rc;
356 }
357 return VERR_NOT_SUPPORTED;
358}
359
360
361void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
362{
363 NOREF(pObj);
364 NOREF(pSession);
365}
366
367
368bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
369{
370 NOREF(pObj);
371 NOREF(pSession);
372 NOREF(pszObjName);
373 NOREF(prc);
374 return false;
375}
376
377/**
378 * Callback for writing to the log buffer.
379 *
380 * @returns number of bytes written.
381 * @param pvArg Unused.
382 * @param pachChars Pointer to an array of utf-8 characters.
383 * @param cbChars Number of bytes in the character array pointed to by pachChars.
384 */
385static DECLCALLBACK(size_t) VBoxDrvLogOutput(void *pvArg, const char *pachChars, size_t cbChars)
386{
387 size_t cchWritten = 0;
388 while (cbChars-- > 0)
389 {
390 const uint16_t offLogHead = g_offLogHead;
391 const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
392 if (offLogHeadNext == g_offLogTail)
393 break; /* no */
394 g_szLog[offLogHead] = *pachChars++;
395 g_offLogHead = offLogHeadNext;
396 cchWritten++;
397 }
398 return cchWritten;
399}
400
401
402SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
403{
404 va_list va;
405
406#if 0 //def DEBUG_bird
407 va_start(va, pszFormat);
408 RTLogComPrintfV(pszFormat, va);
409 va_end(va);
410#endif
411
412 va_start(va, pszFormat);
413 int cch = RTLogFormatV(VBoxDrvLogOutput, NULL, pszFormat, va);
414 va_end(va);
415
416 return cch;
417}
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