VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c@ 4859

Last change on this file since 4859 was 4851, checked in by vboxsync, 18 years ago

Difference approach to instance data, hope this fixes some of the issues...

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 23.1 KB
Line 
1/** @file
2 * VBox host drivers - Ring-0 support drivers - Solaris host:
3 * Solaris driver C code
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <sys/types.h>
23#include <sys/param.h>
24#include <sys/errno.h>
25#include <sys/uio.h>
26#include <sys/buf.h>
27#include <sys/modctl.h>
28#include <sys/open.h>
29#include <sys/conf.h>
30#include <sys/cmn_err.h>
31#include <sys/stat.h>
32#include <sys/ddi.h>
33#include <sys/sunddi.h>
34#include <sys/file.h>
35#undef u /* /usr/include/sys/user.h:249:1 is where this is defined to (curproc->p_user). very cool. */
36
37#include "SUPDRV.h"
38#include <iprt/spinlock.h>
39#include <iprt/process.h>
40#include <iprt/initterm.h>
41#include <iprt/alloc.h>
42#include <iprt/string.h>
43
44
45/*******************************************************************************
46* Defined Constants And Macros *
47*******************************************************************************/
48/** The module name. */
49#define DEVICE_NAME "vboxdrv"
50/** The module description as seen in 'modinfo'. */
51#define DEVICE_DESC "VirtualBox Driver"
52/** Maximum number of driver instances. */
53#define DEVICE_MAXINSTANCES 16
54
55
56/*******************************************************************************
57* Internal Functions *
58*******************************************************************************/
59static int VBoxDrvSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred);
60static int VBoxDrvSolarisClose(dev_t Dev, int fFlag, int fType, cred_t *pCred);
61static int VBoxDrvSolarisRead(dev_t Dev, struct uio *pUio, cred_t *pCred);
62static int VBoxDrvSolarisWrite(dev_t Dev, struct uio *pUio, cred_t *pCred);
63static int VBoxDrvSolarisIOCtl (dev_t Dev, int Cmd, intptr_t pArgs, int mode, cred_t *pCred, int *pVal);
64
65static int VBoxDrvSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t Cmd);
66static int VBoxDrvSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t Cmd);
67
68static int VBoxSupDrvErr2SolarisErr(int rc);
69static int VBoxDrvSolarisIOCtlSlow(PSUPDRVSESSION pSession, int Cmd, int Mode, intptr_t pArgs);
70
71
72/*******************************************************************************
73* Global Variables *
74*******************************************************************************/
75/**
76 * cb_ops: for drivers that support char/block entry points
77 */
78static struct cb_ops g_VBoxDrvSolarisCbOps =
79{
80 VBoxDrvSolarisOpen,
81 VBoxDrvSolarisClose,
82 nodev, /* b strategy */
83 nodev, /* b dump */
84 nodev, /* b print */
85 VBoxDrvSolarisRead,
86 VBoxDrvSolarisWrite,
87 VBoxDrvSolarisIOCtl,
88 nodev, /* c devmap */
89 nodev, /* c mmap */
90 nodev, /* c segmap */
91 nochpoll, /* c poll */
92 ddi_prop_op, /* property ops */
93 NULL, /* streamtab */
94 D_NEW | D_MP, /* compat. flag */
95 CB_REV /* revision */
96};
97
98/**
99 * dev_ops: for driver device operations
100 */
101static struct dev_ops g_VBoxDrvSolarisDevOps =
102{
103 DEVO_REV, /* driver build revision */
104 0, /* ref count */
105 nulldev, /* get info */
106 nulldev, /* identify */
107 nulldev, /* probe */
108 VBoxDrvSolarisAttach,
109 VBoxDrvSolarisDetach,
110 nodev, /* reset */
111 &g_VBoxDrvSolarisCbOps,
112 (struct bus_ops *)0,
113 nodev /* power */
114};
115
116/**
117 * modldrv: export driver specifics to the kernel
118 */
119static struct modldrv g_VBoxDrvSolarisModule =
120{
121 &mod_driverops, /* extern from kernel */
122 DEVICE_DESC,
123 &g_VBoxDrvSolarisDevOps
124};
125
126/**
127 * modlinkage: export install/remove/info to the kernel
128 */
129static struct modlinkage g_VBoxDrvSolarisModLinkage =
130{
131 MODREV_1, /* loadable module system revision */
132 &g_VBoxDrvSolarisModule,
133 NULL /* terminate array of linkage structures */
134};
135
136#ifndef USE_SESSION_HASH
137/**
138 * State info for each open file handle.
139 */
140typedef struct
141{
142 /**< Pointer to the session data. */
143 PSUPDRVSESSION pSession;
144} vbox_devstate_t;
145#else
146/** State info. for each driver instance. */
147typedef struct
148{
149 dev_info_t *pDip; /* Device handle */
150} vbox_devstate_t;
151#endif
152
153/** Opaque pointer to state */
154static void *g_pVBoxDrvSolarisState;
155
156/** Device extention & session data association structure */
157static SUPDRVDEVEXT g_DevExt;
158
159/* GCC C++ hack. */
160unsigned __gxx_personality_v0 = 0xcccccccc;
161
162/** Hash table */
163static PSUPDRVSESSION g_apSessionHashTab[19];
164/** Spinlock protecting g_apSessionHashTab. */
165static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
166/** Calculates bucket index into g_apSessionHashTab.*/
167#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
168
169/**
170 * Kernel entry points
171 */
172int _init(void)
173{
174 cmn_err(CE_CONT, "VBoxDrvSolaris _init");
175
176 int rc = ddi_soft_state_init(&g_pVBoxDrvSolarisState, sizeof(vbox_devstate_t), 8);
177 if (!rc)
178 {
179 rc = mod_install(&g_VBoxDrvSolarisModLinkage);
180 if (!rc)
181 return 0; /* success */
182
183 ddi_soft_state_fini(&g_pVBoxDrvSolarisState);
184 }
185
186 cmn_err(CE_CONT, "VBoxDrvSolaris _init failed with rc=%d", rc);
187 return rc;
188}
189
190
191int _fini(void)
192{
193 cmn_err(CE_CONT, "VBoxDrvSolaris _fini");
194
195 int e = mod_remove(&g_VBoxDrvSolarisModLinkage);
196 if (e != 0)
197 return e;
198
199 ddi_soft_state_fini(&g_pVBoxDrvSolarisState);
200 return e;
201}
202
203
204int _info(struct modinfo *pModInfo)
205{
206 cmn_err(CE_CONT, "VBoxDrvSolaris _info");
207 int e = mod_info(&g_VBoxDrvSolarisModLinkage, pModInfo);
208 cmn_err(CE_CONT, "VBoxDrvSolaris _info returns %d", e);
209 return e;
210}
211
212/**
213 * User context entry points
214 */
215static int VBoxDrvSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred)
216{
217 int rc;
218 PSUPDRVSESSION pSession;
219 dprintf(("VBoxDrvSolarisOpen: pDev=%p:%#x\n", pDev, *pDev));
220
221#ifndef USE_SESSION_HASH
222 /*
223 * Locate a new device open instance.
224 *
225 * For each open call we'll allocate an item in the soft state of the device.
226 * The item index is stored in the dev_t. I hope this is ok...
227 */
228 vbox_devstate_t *pState = NULL;
229 unsigned iOpenInstance;
230 for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
231 {
232 if ( !ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance) /* faster */
233 && ddi_soft_state_zalloc(g_pVBoxDrvSolarisState, iOpenInstance) == DDI_SUCCESS)
234 {
235 pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance);
236 break;
237 }
238 }
239 if (!pState)
240 {
241 cmn_err(CE_NOTE,"VBoxDrvSolarisOpen: too many open instances.");
242 return ENXIO;
243 }
244
245 /*
246 * Create a new session.
247 */
248 rc = supdrvCreateSession(&g_DevExt, &pSession);
249 if (RT_SUCCESS(rc))
250 {
251 pState->pSession = pSession;
252 *pDev = makedevice(getmajor(*pDev), iOpenInstance);
253 dprintf(("VBoxDrvSolarisOpen: returns pDev=%#x pSession=%p pState=%p\n", *pDev, pSession, pState));
254 return 0;
255 }
256
257 /* failed - clean up */
258 ddi_soft_state_free(g_pVBoxDrvSolarisState, iOpenInstance);
259
260#else
261 /*
262 * Create a new session.
263 * Sessions in Solaris driver are mostly useless. It's however needed
264 * in VBoxDrvSolarisIOCtlSlow() while calling supdrvIOCtl()
265 */
266 rc = supdrvCreateSession(&g_DevExt, &pSession);
267 if (RT_SUCCESS(rc))
268 {
269 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
270 unsigned iHash;
271
272 pSession->Uid = crgetuid(pCred);
273 pSession->Gid = crgetgid(pCred);
274 pSession->Process = RTProcSelf();
275 pSession->R0Process = RTR0ProcHandleSelf();
276
277 /*
278 * Insert it into the hash table.
279 */
280 iHash = SESSION_HASH(pSession->Process);
281 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
282 pSession->pNextHash = g_apSessionHashTab[iHash];
283 g_apSessionHashTab[iHash] = pSession;
284 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
285 cmn_err(CE_NOTE,"VBoxDrvSolarisOpen success");
286 }
287
288 int instance;
289 for (instance = 0; instance < DEVICE_MAXINSTANCES; instance++)
290 {
291 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
292 if (pState)
293 break;
294 }
295
296 if (instance >= DEVICE_MAXINSTANCES)
297 {
298 cmn_err(CE_NOTE, "VBoxDrvSolarisOpen: All instances exhausted\n");
299 return ENXIO;
300 }
301
302 *pDev = makedevice(getmajor(*pDev), instance);
303
304 return VBoxSupDrvErr2SolarisErr(rc);
305#endif
306}
307
308
309static int VBoxDrvSolarisClose(dev_t Dev, int flag, int otyp, cred_t *cred)
310{
311 dprintf(("VBoxDrvSolarisClose: Dev=%#x\n", Dev));
312#ifndef USE_SESSION_HASH
313 /*
314 * Get the session and free the soft state item.
315 */
316 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev));
317 if (!pState)
318 {
319 OSDBGPRINT(("VBoxDrvSolarisClose: no state data for %#x (%d)\n", Dev, getminor(Dev)));
320 return DDI_SUCCESS;
321 }
322
323 PSUPDRVSESSION pSession = pState->pSession;
324 pState->pSession = NULL;
325 ddi_soft_state_free(g_pVBoxDrvSolarisState, getminor(Dev));
326
327 if (!pSession)
328 {
329 OSDBGPRINT(("VBoxDrvSolarisClose: no session in state data for %#x (%d)\n", Dev, getminor(Dev)));
330 return DDI_SUCCESS;
331 }
332
333#else
334 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
335 const RTPROCESS Process = RTProcSelf();
336 const unsigned iHash = SESSION_HASH(Process);
337 PSUPDRVSESSION pSession;
338
339 /*
340 * Remove from the hash table.
341 */
342 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
343 pSession = g_apSessionHashTab[iHash];
344 if (pSession)
345 {
346 if (pSession->Process == Process)
347 {
348 g_apSessionHashTab[iHash] = pSession->pNextHash;
349 pSession->pNextHash = NULL;
350 }
351 else
352 {
353 PSUPDRVSESSION pPrev = pSession;
354 pSession = pSession->pNextHash;
355 while (pSession)
356 {
357 if (pSession->Process == Process)
358 {
359 pPrev->pNextHash = pSession->pNextHash;
360 pSession->pNextHash = NULL;
361 break;
362 }
363
364 /* next */
365 pPrev = pSession;
366 pSession = pSession->pNextHash;
367 }
368 }
369 }
370 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
371 if (!pSession)
372 {
373 OSDBGPRINT(("VBoxDrvSolarisClose: WHAT?!? pSession == NULL! This must be a mistake... pid=%d (close)\n",
374 (int)Process));
375 return DDI_FAILURE;
376 }
377#endif
378
379 /*
380 * Close the session.
381 */
382 supdrvCloseSession(&g_DevExt, pSession);
383 return DDI_SUCCESS;
384}
385
386
387static int VBoxDrvSolarisRead(dev_t Dev, struct uio *pUio, cred_t *pCred)
388{
389 cmn_err(CE_CONT, "VBoxDrvSolarisRead");
390 return DDI_SUCCESS;
391}
392
393
394static int VBoxDrvSolarisWrite(dev_t Dev, struct uio *pUio, cred_t *pCred)
395{
396 cmn_err(CE_CONT, "VBoxDrvSolarisWrite");
397 return DDI_SUCCESS;
398}
399
400/**
401 * Attach entry point, to attach a device to the system or resume it.
402 *
403 * @param pDip The module structure instance.
404 * @param enmCmd Attach type (ddi_attach_cmd_t)
405 *
406 * @return corresponding solaris error code.
407 */
408static int VBoxDrvSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
409{
410 cmn_err(CE_CONT, "VBoxDrvSolarisAttach");
411
412 switch (enmCmd)
413 {
414 case DDI_ATTACH:
415 {
416 int rc;
417 int instance = ddi_get_instance(pDip);
418#ifdef USE_SESSION_HASH
419 vbox_devstate_t *pState;
420
421 if (ddi_soft_state_zalloc(g_pVBoxDrvSolarisState, instance) != DDI_SUCCESS)
422 {
423 cmn_err(CE_NOTE, "VBoxDrvSolarisAttach: state alloc failed");
424 return DDI_FAILURE;
425 }
426
427 pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
428#endif
429
430 /*
431 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
432 */
433 rc = RTR0Init(0);
434 if (RT_SUCCESS(rc))
435 {
436 /*
437 * Initialize the device extension
438 */
439 rc = supdrvInitDevExt(&g_DevExt);
440 if (RT_SUCCESS(rc))
441 {
442 /*
443 * Initialize the session hash table.
444 */
445 memset(g_apSessionHashTab, 0, sizeof(g_apSessionHashTab));
446 rc = RTSpinlockCreate(&g_Spinlock);
447 if (RT_SUCCESS(rc))
448 {
449 /*
450 * Register ourselves as a character device, pseudo-driver
451 */
452 if (ddi_create_minor_node(pDip, "0", S_IFCHR, instance, DDI_PSEUDO, 0) == DDI_SUCCESS)
453 {
454#ifdef USE_SESSION_HASH
455 pState->pDip = pDip;
456#endif
457 ddi_report_dev(pDip);
458 return DDI_SUCCESS;
459 }
460
461 /* Is this really necessary? */
462 ddi_remove_minor_node(pDip, NULL);
463 cmn_err(CE_NOTE,"VBoxDrvSolarisAttach: ddi_create_minor_node failed.");
464
465 RTSpinlockDestroy(g_Spinlock);
466 g_Spinlock = NIL_RTSPINLOCK;
467 }
468 else
469 cmn_err(CE_NOTE, "VBoxDrvSolarisAttach: RTSpinlockCreate failed");
470 supdrvDeleteDevExt(&g_DevExt);
471 }
472 else
473 cmn_err(CE_NOTE, "VBoxDrvSolarisAttach: supdrvInitDevExt failed");
474 RTR0Term ();
475 }
476 else
477 cmn_err(CE_NOTE, "VBoxDrvSolarisAttach: failed to init R0Drv");
478 memset(&g_DevExt, 0, sizeof(g_DevExt));
479 break;
480 }
481
482 default:
483 return DDI_FAILURE;
484 }
485
486 return DDI_FAILURE;
487}
488
489/**
490 * Detach entry point, to detach a device to the system or suspend it.
491 *
492 * @param pDip The module structure instance.
493 * @param enmCmd Attach type (ddi_attach_cmd_t)
494 *
495 * @return corresponding solaris error code.
496 */
497static int VBoxDrvSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
498{
499 int rc = VINF_SUCCESS;
500
501
502 cmn_err(CE_CONT, "VBoxDrvSolarisDetach");
503 switch (enmCmd)
504 {
505 case DDI_DETACH:
506 {
507 int instance = ddi_get_instance(pDip);
508#ifndef USE_SESSION_HASH
509 ddi_remove_minor_node(pDip, NULL);
510#else
511 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
512 ddi_remove_minor_node(pDip, NULL);
513 ddi_soft_state_free(g_pVBoxDrvSolarisState, instance);
514#endif
515
516 supdrvDeleteDevExt(&g_DevExt);
517
518 rc = RTSpinlockDestroy(g_Spinlock);
519 AssertRC(rc);
520 g_Spinlock = NIL_RTSPINLOCK;
521
522 RTR0Term();
523
524 memset(&g_DevExt, 0, sizeof(g_DevExt));
525 cmn_err(CE_CONT, "VBoxDrvSolarisDetach: Clean Up Done.");
526 return DDI_SUCCESS;
527 }
528
529 default:
530 return DDI_FAILURE;
531 }
532}
533
534/**
535 * Driver ioctl, an alternate entry point for this character driver.
536 *
537 * @param Dev Device number
538 * @param Cmd Operation identifier
539 * @param pArg Arguments from user to driver
540 * @param Mode Information bitfield (read/write, address space etc.)
541 * @param pCred User credentials
542 * @param pVal Return value for calling process.
543 *
544 * @return corresponding solaris error code.
545 */
546static int VBoxDrvSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArgs, int Mode, cred_t *pCred, int *pVal)
547{
548#ifndef USE_SESSION_HASH
549 /*
550 * Get the session from the soft state item.
551 */
552 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev));
553 if (!pState)
554 {
555 OSDBGPRINT(("VBoxDrvSolarisIOCtl: no state data for %#x (%d)\n", Dev, getminor(Dev)));
556 return EINVAL;
557 }
558
559 PSUPDRVSESSION pSession = pState->pSession;
560 if (!pSession)
561 {
562 OSDBGPRINT(("VBoxDrvSolarisIOCtl: no session in state data for %#x (%d)\n", Dev, getminor(Dev)));
563 return DDI_SUCCESS;
564 }
565#else
566 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
567 const RTPROCESS Process = RTProcSelf();
568 const unsigned iHash = SESSION_HASH(Process);
569 PSUPDRVSESSION pSession;
570
571 /*
572 * Find the session.
573 */
574 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
575 pSession = g_apSessionHashTab[iHash];
576 if (pSession && pSession->Process != Process)
577 {
578 do pSession = pSession->pNextHash;
579 while (pSession && pSession->Process != Process);
580 }
581 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
582 if (!pSession)
583 {
584 OSDBGPRINT(("VBoxSupDrvIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#x\n",
585 (int)Process, Cmd));
586 return EINVAL;
587 }
588#endif
589
590 /*
591 * Deal with the two high-speed IOCtl that takes it's arguments from
592 * the session and iCmd, and only returns a VBox status code.
593 */
594 if ( Cmd == SUP_IOCTL_FAST_DO_RAW_RUN
595 || Cmd == SUP_IOCTL_FAST_DO_HWACC_RUN
596 || Cmd == SUP_IOCTL_FAST_DO_NOP)
597 {
598 *pVal = supdrvIOCtlFast(Cmd, &g_DevExt, pSession);
599 return 0;
600 }
601
602 return VBoxDrvSolarisIOCtlSlow(pSession, Cmd, Mode, pArgs);
603}
604
605
606/** @def IOCPARM_LEN
607 * Gets the length from the ioctl number.
608 * This is normally defined by sys/ioccom.h on BSD systems...
609 */
610#ifndef IOCPARM_LEN
611# define IOCPARM_LEN(x) ( ((x) >> 16) & IOCPARM_MASK )
612#endif
613
614
615/**
616 * Worker for VBoxSupDrvIOCtl that takes the slow IOCtl functions.
617 *
618 * @returns Solaris errno.
619 *
620 * @param pSession The session.
621 * @param Cmd The IOCtl command.
622 * @param Mode Information bitfield (for specifying ownership of data)
623 * @param iArg User space address of the request buffer.
624 */
625static int VBoxDrvSolarisIOCtlSlow(PSUPDRVSESSION pSession, int iCmd, int Mode, intptr_t iArg)
626{
627 int rc;
628 uint32_t cbBuf = 0;
629 SUPREQHDR Hdr;
630 PSUPREQHDR pHdr;
631
632
633 /*
634 * Read the header.
635 */
636 if (RT_UNLIKELY(IOCPARM_LEN(iCmd) != sizeof(Hdr)))
637 {
638 OSDBGPRINT(("VBoxDrvSolarisIOCtlSlow: iCmd=%#x len %d expected %d\n", iCmd, IOCPARM_LEN(iCmd), sizeof(Hdr)));
639 return EINVAL;
640 }
641 rc = ddi_copyin((void *)iArg, &Hdr, sizeof(Hdr), Mode);
642 if (RT_UNLIKELY(rc))
643 {
644 OSDBGPRINT(("VBoxDrvSolarisIOCtlSlow: ddi_copyin(,%#lx,) failed; iCmd=%#x. rc=%d\n", iArg, iCmd, rc));
645 return EFAULT;
646 }
647 if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))
648 {
649 OSDBGPRINT(("VBoxDrvSolarisIOCtlSlow: bad header magic %#x; iCmd=%#x\n", Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK, iCmd));
650 return EINVAL;
651 }
652 cbBuf = RT_MAX(Hdr.cbIn, Hdr.cbOut);
653 if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr)
654 || Hdr.cbOut < sizeof(Hdr)
655 || cbBuf > _1M*16))
656 {
657 OSDBGPRINT(("VBoxDrvSolarisIOCtlSlow: max(%#x,%#x); iCmd=%#x\n", Hdr.cbIn, Hdr.cbOut, iCmd));
658 return EINVAL;
659 }
660
661 /*
662 * Buffer the request.
663 */
664 pHdr = RTMemTmpAlloc(cbBuf);
665 if (RT_UNLIKELY(!pHdr))
666 {
667 OSDBGPRINT(("VBoxDrvSolarisIOCtlSlow: failed to allocate buffer of %d bytes for iCmd=%#x.\n", cbBuf, iCmd));
668 return ENOMEM;
669 }
670 rc = ddi_copyin((void *)iArg, pHdr, cbBuf, Mode);
671 if (RT_UNLIKELY(rc))
672 {
673 dprintf(("VBoxDrvSolarisIOCtlSlow: copy_from_user(,%#lx, %#x) failed; iCmd=%#x. rc=%d\n", iArg, Hdr.cbIn, iCmd, rc));
674 RTMemFree(pHdr);
675 return EFAULT;
676 }
677
678 /*
679 * Process the IOCtl.
680 */
681 rc = supdrvIOCtl(iCmd, &g_DevExt, pSession, pHdr);
682
683 /*
684 * Copy ioctl data and output buffer back to user space.
685 */
686 if (RT_LIKELY(!rc))
687 {
688 uint32_t cbOut = pHdr->cbOut;
689 if (RT_UNLIKELY(cbOut > cbBuf))
690 {
691 OSDBGPRINT(("VBoxDrvSolarisIOCtlSlow: too much output! %#x > %#x; iCmd=%#x!\n", cbOut, cbBuf, iCmd));
692 cbOut = cbBuf;
693 }
694 rc = ddi_copyout(pHdr, (void *)iArg, cbOut, Mode);
695 if (RT_UNLIKELY(rc != 0))
696 {
697 /* this is really bad */
698 OSDBGPRINT(("VBoxDrvSolarisIOCtlSlow: ddi_copyout(,%p,%d) failed. rc=%d\n", (void *)iArg, cbBuf, rc));
699 rc = EFAULT;
700 }
701 }
702 else
703 rc = EINVAL;
704
705 RTMemTmpFree(pHdr);
706 return rc;
707}
708
709
710/**
711 * Converts an supdrv error code to a solaris error code.
712 *
713 * @returns corresponding solaris error code.
714 * @param rc supdrv error code (SUPDRV_ERR_* defines).
715 */
716static int VBoxSupDrvErr2SolarisErr(int rc)
717{
718 switch (rc)
719 {
720 case 0: return 0;
721 case SUPDRV_ERR_GENERAL_FAILURE: return EACCES;
722 case SUPDRV_ERR_INVALID_PARAM: return EINVAL;
723 case SUPDRV_ERR_INVALID_MAGIC: return EILSEQ;
724 case SUPDRV_ERR_INVALID_HANDLE: return ENXIO;
725 case SUPDRV_ERR_INVALID_POINTER: return EFAULT;
726 case SUPDRV_ERR_LOCK_FAILED: return ENOLCK;
727 case SUPDRV_ERR_ALREADY_LOADED: return EEXIST;
728 case SUPDRV_ERR_PERMISSION_DENIED: return EPERM;
729 case SUPDRV_ERR_VERSION_MISMATCH: return ENOSYS;
730 }
731
732 return EPERM;
733}
734
735/**
736 * Initializes any OS specific object creator fields.
737 */
738void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
739{
740 NOREF(pObj);
741 NOREF(pSession);
742}
743
744
745/**
746 * Checks if the session can access the object.
747 *
748 * @returns true if a decision has been made.
749 * @returns false if the default access policy should be applied.
750 *
751 * @param pObj The object in question.
752 * @param pSession The session wanting to access the object.
753 * @param pszObjName The object name, can be NULL.
754 * @param prc Where to store the result when returning true.
755 */
756bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
757{
758 NOREF(pObj);
759 NOREF(pSession);
760 NOREF(pszObjName);
761 NOREF(prc);
762 return false;
763}
764
765
766RTDECL(int) SUPR0Printf(const char *pszFormat, ...)
767{
768 va_list args;
769 char szMsg[512];
770
771 va_start(args, pszFormat);
772 RTStrPrintfV(szMsg, sizeof(szMsg) - 1, pszFormat, args);
773 va_end(args);
774
775 szMsg[sizeof(szMsg) - 1] = '\0';
776 uprintf("SUPR0Printf: %s", szMsg);
777// cmn_err(CE_CONT, "VBoxDrv: %s", szMsg);
778
779 return 0;
780}
781
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