VirtualBox

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

Last change on this file since 41530 was 41067, checked in by vboxsync, 13 years ago

supdrvOSLdrNotifyOpened so we can record the load address in NVRAM if we choose to.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.7 KB
Line 
1/* $Id: SUPDrv-os2.cpp 41067 2012-04-26 11:36:57Z 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
66RT_C_DECLS_BEGIN
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;
76RT_C_DECLS_END
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 /*
94 * Initialize the runtime.
95 */
96 int rc = RTR0Init(0);
97 if (RT_SUCCESS(rc))
98 {
99 Log(("VBoxDrvInit: pszArgs=%s\n", pszArgs));
100
101 /*
102 * Initialize the device extension.
103 */
104 rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION));
105 if (RT_SUCCESS(rc))
106 {
107 /*
108 * Initialize the session hash table.
109 */
110 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvOS2");
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 Oracle Corporation\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=%Rrc\n", rc);
133 supdrvDeleteDevExt(&g_DevExt);
134 }
135 else
136 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: supdrvInitDevExt failed, rc=%Rrc\n", rc);
137 RTR0Term();
138 }
139 else
140 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTR0Init failed, rc=%Rrc\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 RTSpinlockAcquire(g_Spinlock);
163 pSession->pNextHash = g_apSessionHashTab[iHash];
164 g_apSessionHashTab[iHash] = pSession;
165 RTSpinlockReleaseNoInts(g_Spinlock);
166 }
167
168 Log(("VBoxDrvOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
169 return rc;
170}
171
172
173DECLASM(int) VBoxDrvClose(uint16_t sfn)
174{
175 Log(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
176
177 /*
178 * Remove from the hash table.
179 */
180 PSUPDRVSESSION pSession;
181 const RTPROCESS Process = RTProcSelf();
182 const unsigned iHash = SESSION_HASH(sfn);
183 RTSpinlockAcquire(g_Spinlock);
184
185 pSession = g_apSessionHashTab[iHash];
186 if (pSession)
187 {
188 if ( pSession->sfn == sfn
189 && pSession->Process == Process)
190 {
191 g_apSessionHashTab[iHash] = pSession->pNextHash;
192 pSession->pNextHash = NULL;
193 }
194 else
195 {
196 PSUPDRVSESSION pPrev = pSession;
197 pSession = pSession->pNextHash;
198 while (pSession)
199 {
200 if ( pSession->sfn == sfn
201 && pSession->Process == Process)
202 {
203 pPrev->pNextHash = pSession->pNextHash;
204 pSession->pNextHash = NULL;
205 break;
206 }
207
208 /* next */
209 pPrev = pSession;
210 pSession = pSession->pNextHash;
211 }
212 }
213 }
214 RTSpinlockReleaseNoInts(g_Spinlock);
215 if (!pSession)
216 {
217 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
218 return VERR_INVALID_PARAMETER;
219 }
220
221 /*
222 * Close the session.
223 */
224 supdrvCloseSession(&g_DevExt, pSession);
225 return 0;
226}
227
228
229DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction)
230{
231 /*
232 * Find the session.
233 */
234 const RTPROCESS Process = RTProcSelf();
235 const unsigned iHash = SESSION_HASH(sfn);
236 PSUPDRVSESSION pSession;
237
238 RTSpinlockAcquire(g_Spinlock);
239 pSession = g_apSessionHashTab[iHash];
240 if (pSession && pSession->Process != Process)
241 {
242 do pSession = pSession->pNextHash;
243 while ( pSession
244 && ( pSession->sfn != sfn
245 || pSession->Process != Process));
246 }
247 RTSpinlockReleaseNoInts(g_Spinlock);
248 if (RT_UNLIKELY(!pSession))
249 {
250 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
251 return VERR_INVALID_PARAMETER;
252 }
253
254 /*
255 * Dispatch the fast IOCtl.
256 */
257 supdrvIOCtlFast(iFunction, 0, &g_DevExt, pSession);
258 return 0;
259}
260
261
262DECLASM(int) VBoxDrvIOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData)
263{
264 /*
265 * Find the session.
266 */
267 const RTPROCESS Process = RTProcSelf();
268 const unsigned iHash = SESSION_HASH(sfn);
269 PSUPDRVSESSION pSession;
270
271 RTSpinlockAcquire(g_Spinlock);
272 pSession = g_apSessionHashTab[iHash];
273 if (pSession && pSession->Process != Process)
274 {
275 do pSession = pSession->pNextHash;
276 while ( pSession
277 && ( pSession->sfn != sfn
278 || pSession->Process != Process));
279 }
280 RTSpinlockReleaseNoInts(g_Spinlock);
281 if (!pSession)
282 {
283 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
284 return VERR_INVALID_PARAMETER;
285 }
286
287 /*
288 * Verify the category and dispatch the IOCtl.
289 */
290 if (RT_LIKELY(iCat == SUP_CTL_CATEGORY))
291 {
292 Log(("VBoxDrvIOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
293 Assert(pvParm);
294 Assert(!pvData);
295
296 /*
297 * Lock the header.
298 */
299 PSUPREQHDR pHdr = (PSUPREQHDR)pvParm;
300 AssertReturn(*pcbParm == sizeof(*pHdr), VERR_INVALID_PARAMETER);
301 KernVMLock_t Lock;
302 int rc = KernVMLock(VMDHL_WRITE, pHdr, *pcbParm, &Lock, (KernPageList_t *)-1, NULL);
303 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, *pcbParm, &Lock, rc), VERR_LOCK_FAILED);
304
305 /*
306 * Validate the header.
307 */
308 if (RT_LIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) == SUPREQHDR_FLAGS_MAGIC))
309 {
310 uint32_t cbReq = RT_MAX(pHdr->cbIn, pHdr->cbOut);
311 if (RT_LIKELY( pHdr->cbIn >= sizeof(*pHdr)
312 && pHdr->cbOut >= sizeof(*pHdr)
313 && cbReq <= _1M*16))
314 {
315 /*
316 * Lock the rest of the buffer if necessary.
317 */
318 if (((uintptr_t)pHdr & PAGE_OFFSET_MASK) + cbReq > PAGE_SIZE)
319 {
320 rc = KernVMUnlock(&Lock);
321 AssertMsgReturn(!rc, ("KernVMUnlock(Lock) -> %#x\n", rc), VERR_LOCK_FAILED);
322
323 rc = KernVMLock(VMDHL_WRITE, pHdr, cbReq, &Lock, (KernPageList_t *)-1, NULL);
324 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, cbReq, &Lock, rc), VERR_LOCK_FAILED);
325 }
326
327 /*
328 * Process the IOCtl.
329 */
330 rc = supdrvIOCtl(iFunction, &g_DevExt, pSession, pHdr);
331 }
332 else
333 {
334 OSDBGPRINT(("VBoxDrvIOCtl: max(%#x,%#x); iCmd=%#x\n", pHdr->cbIn, pHdr->cbOut, iFunction));
335 rc = VERR_INVALID_PARAMETER;
336 }
337 }
338 else
339 {
340 OSDBGPRINT(("VBoxDrvIOCtl: bad magic fFlags=%#x; iCmd=%#x\n", pHdr->fFlags, iFunction));
341 rc = VERR_INVALID_PARAMETER;
342 }
343
344 /*
345 * Unlock and return.
346 */
347 int rc2 = KernVMUnlock(&Lock);
348 AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);
349
350 Log2(("VBoxDrvIOCtl: returns %d\n", rc));
351 return rc;
352 }
353 return VERR_NOT_SUPPORTED;
354}
355
356
357void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
358{
359 NOREF(pObj);
360 NOREF(pSession);
361}
362
363
364bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
365{
366 NOREF(pObj);
367 NOREF(pSession);
368 NOREF(pszObjName);
369 NOREF(prc);
370 return false;
371}
372
373
374bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)
375{
376 NOREF(pDevExt);
377 return false;
378}
379
380
381int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
382{
383 NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
384 return VERR_NOT_SUPPORTED;
385}
386
387
388void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
389{
390 NOREF(pDevExt); NOREF(pImage);
391}
392
393
394int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
395{
396 NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits);
397 return VERR_NOT_SUPPORTED;
398}
399
400
401int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
402{
403 NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq);
404 return VERR_NOT_SUPPORTED;
405}
406
407
408void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
409{
410 NOREF(pDevExt); NOREF(pImage);
411}
412
413
414/**
415 * Callback for writing to the log buffer.
416 *
417 * @returns number of bytes written.
418 * @param pvArg Unused.
419 * @param pachChars Pointer to an array of utf-8 characters.
420 * @param cbChars Number of bytes in the character array pointed to by pachChars.
421 */
422static DECLCALLBACK(size_t) VBoxDrvLogOutput(void *pvArg, const char *pachChars, size_t cbChars)
423{
424 size_t cchWritten = 0;
425 while (cbChars-- > 0)
426 {
427 const uint16_t offLogHead = g_offLogHead;
428 const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
429 if (offLogHeadNext == g_offLogTail)
430 break; /* no */
431 g_szLog[offLogHead] = *pachChars++;
432 g_offLogHead = offLogHeadNext;
433 cchWritten++;
434 }
435 return cchWritten;
436}
437
438
439SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
440{
441 va_list va;
442
443#if 0 //def DEBUG_bird
444 va_start(va, pszFormat);
445 RTLogComPrintfV(pszFormat, va);
446 va_end(va);
447#endif
448
449 va_start(va, pszFormat);
450 int cch = RTLogFormatV(VBoxDrvLogOutput, NULL, pszFormat, va);
451 va_end(va);
452
453 return cch;
454}
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