Changeset 10836 in vbox for trunk/src/VBox/HostDrivers
- Timestamp:
- Jul 23, 2008 6:37:18 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 33621
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
r10805 r10836 565 565 * This is NIL_RTR0PROCESS for kernel sessions and valid for user ones. */ 566 566 RTR0PROCESS R0Process; 567 #if defined(RT_OS_DARWIN) 568 /** Pointer to the associated org_virtualbox_SupDrvClient object. */ 569 void *pvSupDrvClient; 570 /** Whether this session has been opened or not. */ 571 bool fOpened; 572 #endif 567 573 #if defined(RT_OS_OS2) 568 574 /** The system file number of this session. */ -
trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
r10714 r10836 134 134 virtual bool initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type); 135 135 virtual bool start(IOService *pProvider); 136 static void sessionClose(RTPROCESS Process); 136 137 virtual IOReturn clientClose(void); 137 138 virtual IOReturn clientDied(void); … … 341 342 342 343 /* 343 * Create a new session. 344 */ 345 rc = supdrvCreateSession(&g_DevExt, true /* fUser */, &pSession); 346 if (RT_SUCCESS(rc)) 347 { 344 * Find the session created by org_virtualbox_SupDrvClient, fail 345 * if no such session, and mark it as opened. We set the uid & gid 346 * here too, since that is more straight forward at this point. 347 */ 348 struct ucred *pCred = proc_ucred(pProcess); 349 if (pCred) 350 { 351 RTUID Uid = pCred->cr_uid; 352 RTGID Gid = pCred->cr_gid; 353 RTPROCESS Process = RTProcSelf(); 354 unsigned iHash = SESSION_HASH(Process); 348 355 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 349 unsigned iHash;350 struct ucred *pCred = proc_ucred(pProcess);351 if (pCred)352 {353 pSession->Uid = pCred->cr_uid;354 pSession->Gid = pCred->cr_gid;355 }356 357 /*358 * Insert it into the hash table.359 */360 iHash = SESSION_HASH(pSession->Process);361 356 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp); 362 pSession->pNextHash = g_apSessionHashTab[iHash]; 363 g_apSessionHashTab[iHash] = pSession; 364 ASMAtomicIncS32(&g_cSessions); 357 358 pSession = g_apSessionHashTab[iHash]; 359 if (pSession && pSession->Process != Process) 360 { 361 do pSession = pSession->pNextHash; 362 while (pSession && pSession->Process != Process); 363 } 364 if (pSession) 365 { 366 if (!pSession->fOpened) 367 { 368 pSession->fOpened = true; 369 pSession->Uid = Uid; 370 pSession->Gid = Gid; 371 } 372 else 373 rc = VERR_ALREADY_LOADED; 374 } 375 else 376 rc = VERR_GENERAL_FAILURE; 377 365 378 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp); 366 379 } 380 else 381 rc = SUPDRV_ERR_INVALID_PARAM; 367 382 368 383 #ifdef DEBUG_DARWIN_GIP … … 380 395 static int VBoxDrvDarwinClose(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) 381 396 { 382 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 383 const RTPROCESS Process = proc_pid(pProcess); 384 const unsigned iHash = SESSION_HASH(Process); 385 PSUPDRVSESSION pSession; 386 387 Log(("VBoxDrvDarwinClose: pid=%d\n", (int)Process)); 388 389 /* 390 * Remove from the hash table. 397 Log(("VBoxDrvDarwinClose: pid=%d\n", (int)RTProcSelf())); 398 Assert(proc_pid(pProcess) == (int)RTProcSelf()); 399 400 /* 401 * Hand the session closing to org_virtualbox_SupDrvClient. 402 */ 403 org_virtualbox_SupDrvClient::sessionClose(RTProcSelf()); 404 return 0; 405 } 406 407 408 /** 409 * Device I/O Control entry point. 410 * 411 * @returns Darwin for slow IOCtls and VBox status code for the fast ones. 412 * @param Dev The device number (major+minor). 413 * @param iCmd The IOCtl command. 414 * @param pData Pointer to the data (if any it's a SUPDRVIOCTLDATA (kernel copy)). 415 * @param fFlags Flag saying we're a character device (like we didn't know already). 416 * @param pProcess The process issuing this request. 417 */ 418 static int VBoxDrvDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess) 419 { 420 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 421 const RTPROCESS Process = proc_pid(pProcess); 422 const unsigned iHash = SESSION_HASH(Process); 423 PSUPDRVSESSION pSession; 424 425 /* 426 * Find the session. 391 427 */ 392 428 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp); 393 429 pSession = g_apSessionHashTab[iHash]; 430 if (pSession && pSession->Process != Process) 431 { 432 do pSession = pSession->pNextHash; 433 while (pSession && pSession->Process != Process); 434 } 435 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp); 436 if (!pSession) 437 { 438 OSDBGPRINT(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#x\n", 439 (int)Process, iCmd)); 440 return EINVAL; 441 } 442 443 /* 444 * Deal with the two high-speed IOCtl that takes it's arguments from 445 * the session and iCmd, and only returns a VBox status code. 446 */ 447 if ( iCmd == SUP_IOCTL_FAST_DO_RAW_RUN 448 || iCmd == SUP_IOCTL_FAST_DO_HWACC_RUN 449 || iCmd == SUP_IOCTL_FAST_DO_NOP) 450 return supdrvIOCtlFast(iCmd, &g_DevExt, pSession); 451 return VBoxDrvDarwinIOCtlSlow(pSession, iCmd, pData, pProcess); 452 } 453 454 455 /** 456 * Worker for VBoxDrvDarwinIOCtl that takes the slow IOCtl functions. 457 * 458 * @returns Darwin errno. 459 * 460 * @param pSession The session. 461 * @param iCmd The IOCtl command. 462 * @param pData Pointer to the kernel copy of the SUPDRVIOCTLDATA buffer. 463 * @param pProcess The calling process. 464 */ 465 static int VBoxDrvDarwinIOCtlSlow(PSUPDRVSESSION pSession, u_long iCmd, caddr_t pData, struct proc *pProcess) 466 { 467 LogFlow(("VBoxDrvDarwinIOCtlSlow: pSession=%p iCmd=%p pData=%p pProcess=%p\n", pSession, iCmd, pData, pProcess)); 468 469 470 /* 471 * Buffered or unbuffered? 472 */ 473 PSUPREQHDR pHdr; 474 user_addr_t pUser = 0; 475 void *pvPageBuf = NULL; 476 uint32_t cbReq = IOCPARM_LEN(iCmd); 477 if ((IOC_DIRMASK & iCmd) == IOC_INOUT) 478 { 479 pHdr = (PSUPREQHDR)pData; 480 if (RT_UNLIKELY(cbReq < sizeof(*pHdr))) 481 { 482 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: cbReq=%#x < %#x; iCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), iCmd)); 483 return EINVAL; 484 } 485 if (RT_UNLIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) 486 { 487 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: bad magic fFlags=%#x; iCmd=%#lx\n", pHdr->fFlags, iCmd)); 488 return EINVAL; 489 } 490 if (RT_UNLIKELY( RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq 491 || pHdr->cbIn < sizeof(*pHdr) 492 || pHdr->cbOut < sizeof(*pHdr))) 493 { 494 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: max(%#x,%#x) != %#x; iCmd=%#lx\n", pHdr->cbIn, pHdr->cbOut, cbReq, iCmd)); 495 return EINVAL; 496 } 497 } 498 else if ((IOC_DIRMASK & iCmd) == IOC_VOID && !cbReq) 499 { 500 /* 501 * Get the header and figure out how much we're gonna have to read. 502 */ 503 SUPREQHDR Hdr; 504 pUser = (user_addr_t)*(void **)pData; 505 int rc = copyin(pUser, &Hdr, sizeof(Hdr)); 506 if (RT_UNLIKELY(rc)) 507 { 508 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyin(%llx,Hdr,) -> %#x; iCmd=%#lx\n", (unsigned long long)pUser, rc, iCmd)); 509 return rc; 510 } 511 if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) 512 { 513 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: bad magic fFlags=%#x; iCmd=%#lx\n", Hdr.fFlags, iCmd)); 514 return EINVAL; 515 } 516 cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut); 517 if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr) 518 || Hdr.cbOut < sizeof(Hdr) 519 || cbReq > _1M*16)) 520 { 521 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: max(%#x,%#x); iCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, iCmd)); 522 return EINVAL; 523 } 524 525 /* 526 * Allocate buffer and copy in the data. 527 */ 528 pHdr = (PSUPREQHDR)RTMemTmpAlloc(cbReq); 529 if (!pHdr) 530 pvPageBuf = pHdr = (PSUPREQHDR)IOMallocAligned(RT_ALIGN_Z(cbReq, PAGE_SIZE), 8); 531 if (RT_UNLIKELY(!pHdr)) 532 { 533 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: failed to allocate buffer of %d bytes; iCmd=%#lx\n", cbReq, iCmd)); 534 return ENOMEM; 535 } 536 rc = copyin(pUser, pHdr, Hdr.cbIn); 537 if (RT_UNLIKELY(rc)) 538 { 539 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyin(%llx,%p,%#x) -> %#x; iCmd=%#lx\n", 540 (unsigned long long)pUser, pHdr, Hdr.cbIn, rc, iCmd)); 541 if (pvPageBuf) 542 IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); 543 else 544 RTMemTmpFree(pHdr); 545 return rc; 546 } 547 } 548 else 549 { 550 Log(("VBoxDrvDarwinIOCtlSlow: huh? cbReq=%#x iCmd=%#lx\n", cbReq, iCmd)); 551 return EINVAL; 552 } 553 554 /* 555 * Process the IOCtl. 556 */ 557 int rc = supdrvIOCtl(iCmd, &g_DevExt, pSession, pHdr); 558 if (RT_LIKELY(!rc)) 559 { 560 /* 561 * If not buffered, copy back the buffer before returning. 562 */ 563 if (pUser) 564 { 565 uint32_t cbOut = pHdr->cbOut; 566 if (cbOut > cbReq) 567 { 568 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, iCmd)); 569 cbOut = cbReq; 570 } 571 rc = copyout(pHdr, pUser, cbOut); 572 if (RT_UNLIKELY(rc)) 573 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyout(%p,%llx,%#x) -> %d; uCmd=%#lx!\n", 574 pHdr, (unsigned long long)pUser, cbOut, rc, iCmd)); 575 576 /* cleanup */ 577 if (pvPageBuf) 578 IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); 579 else 580 RTMemTmpFree(pHdr); 581 } 582 } 583 else 584 { 585 /* 586 * The request failed, just clean up. 587 */ 588 if (pUser) 589 { 590 if (pvPageBuf) 591 IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); 592 else 593 RTMemTmpFree(pHdr); 594 } 595 596 Log(("VBoxDrvDarwinIOCtlSlow: pid=%d iCmd=%lx pData=%p failed, rc=%d\n", proc_pid(pProcess), iCmd, (void *)pData, rc)); 597 rc = EINVAL; 598 } 599 600 Log2(("VBoxDrvDarwinIOCtlSlow: returns %d\n", rc)); 601 return rc; 602 } 603 604 605 /** 606 * The SUPDRV IDC entry point. 607 * 608 * @returns VBox status code, see supdrvIDC. 609 * @param iReq The request code. 610 * @param pReq The request. 611 */ 612 int VBOXCALL SUPDrvDarwinIDC(uint32_t uReq, PSUPDRVIDCREQHDR pReq) 613 { 614 PSUPDRVSESSION pSession; 615 616 /* 617 * Some quick validations. 618 */ 619 if (RT_UNLIKELY(!VALID_PTR(pReq))) 620 return VERR_INVALID_POINTER; 621 622 pSession = pReq->pSession; 623 if (pSession) 624 { 625 if (RT_UNLIKELY(!VALID_PTR(pSession))) 626 return VERR_INVALID_PARAMETER; 627 if (RT_UNLIKELY(pSession->pDevExt != &g_DevExt)) 628 return VERR_INVALID_PARAMETER; 629 } 630 else if (RT_UNLIKELY(uReq != SUPDRV_IDC_REQ_CONNECT)) 631 return VERR_INVALID_PARAMETER; 632 633 /* 634 * Do the job. 635 */ 636 return supdrvIDC(uReq, &g_DevExt, pSession, pReq); 637 } 638 639 640 /** 641 * Initializes any OS specific object creator fields. 642 */ 643 void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession) 644 { 645 NOREF(pObj); 646 NOREF(pSession); 647 } 648 649 650 /** 651 * Checks if the session can access the object. 652 * 653 * @returns true if a decision has been made. 654 * @returns false if the default access policy should be applied. 655 * 656 * @param pObj The object in question. 657 * @param pSession The session wanting to access the object. 658 * @param pszObjName The object name, can be NULL. 659 * @param prc Where to store the result when returning true. 660 */ 661 bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc) 662 { 663 NOREF(pObj); 664 NOREF(pSession); 665 NOREF(pszObjName); 666 NOREF(prc); 667 return false; 668 } 669 670 671 bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt) 672 { 673 NOREF(pDevExt); 674 return false; 675 } 676 677 678 /** 679 * Converts a supdrv error code to a darwin error code. 680 * 681 * @returns corresponding darwin error code. 682 * @param rc supdrv error code (SUPDRV_ERR_* defines). 683 */ 684 static int VBoxDrvDarwinErr2DarwinErr(int rc) 685 { 686 switch (rc) 687 { 688 case 0: return 0; 689 case SUPDRV_ERR_GENERAL_FAILURE: return EACCES; 690 case SUPDRV_ERR_INVALID_PARAM: return EINVAL; 691 case SUPDRV_ERR_INVALID_MAGIC: return EILSEQ; 692 case SUPDRV_ERR_INVALID_HANDLE: return ENXIO; 693 case SUPDRV_ERR_INVALID_POINTER: return EFAULT; 694 case SUPDRV_ERR_LOCK_FAILED: return ENOLCK; 695 case SUPDRV_ERR_ALREADY_LOADED: return EEXIST; 696 case SUPDRV_ERR_PERMISSION_DENIED: return EPERM; 697 case SUPDRV_ERR_VERSION_MISMATCH: return ENOSYS; 698 } 699 700 return EPERM; 701 } 702 703 704 /** @todo move this to assembly where a simple "jmp printf" will to the trick. */ 705 RTDECL(int) SUPR0Printf(const char *pszFormat, ...) 706 { 707 va_list args; 708 char szMsg[512]; 709 710 va_start(args, pszFormat); 711 vsnprintf(szMsg, sizeof(szMsg) - 1, pszFormat, args); 712 va_end(args); 713 714 szMsg[sizeof(szMsg) - 1] = '\0'; 715 printf("%s", szMsg); 716 return 0; 717 } 718 719 720 /* 721 * 722 * org_virtualbox_SupDrv 723 * 724 */ 725 726 727 /** 728 * Initialize the object. 729 */ 730 bool org_virtualbox_SupDrv::init(OSDictionary *pDictionary) 731 { 732 LogFlow(("org_virtualbox_SupDrv::init([%p], %p)\n", this, pDictionary)); 733 if (IOService::init(pDictionary)) 734 { 735 /* init members. */ 736 return true; 737 } 738 return false; 739 } 740 741 742 /** 743 * Free the object. 744 */ 745 void org_virtualbox_SupDrv::free(void) 746 { 747 LogFlow(("IOService::free([%p])\n", this)); 748 IOService::free(); 749 } 750 751 752 /** 753 * Check if it's ok to start this service. 754 * It's always ok by us, so it's up to IOService to decide really. 755 */ 756 IOService *org_virtualbox_SupDrv::probe(IOService *pProvider, SInt32 *pi32Score) 757 { 758 LogFlow(("org_virtualbox_SupDrv::probe([%p])\n", this)); 759 return IOService::probe(pProvider, pi32Score); 760 } 761 762 763 /** 764 * Start this service. 765 */ 766 bool org_virtualbox_SupDrv::start(IOService *pProvider) 767 { 768 LogFlow(("org_virtualbox_SupDrv::start([%p])\n", this)); 769 770 if (IOService::start(pProvider)) 771 { 772 /* register the service. */ 773 registerService(); 774 return true; 775 } 776 return false; 777 } 778 779 780 /** 781 * Stop this service. 782 */ 783 void org_virtualbox_SupDrv::stop(IOService *pProvider) 784 { 785 LogFlow(("org_virtualbox_SupDrv::stop([%p], %p)\n", this, pProvider)); 786 IOService::stop(pProvider); 787 } 788 789 790 /** 791 * Termination request. 792 * 793 * @return true if we're ok with shutting down now, false if we're not. 794 * @param fOptions Flags. 795 */ 796 bool org_virtualbox_SupDrv::terminate(IOOptionBits fOptions) 797 { 798 bool fRc; 799 LogFlow(("org_virtualbox_SupDrv::terminate: reference_count=%d g_cSessions=%d (fOptions=%#x)\n", 800 KMOD_INFO_NAME.reference_count, ASMAtomicUoReadS32(&g_cSessions), fOptions)); 801 if ( KMOD_INFO_NAME.reference_count != 0 802 || ASMAtomicUoReadS32(&g_cSessions)) 803 fRc = false; 804 else 805 fRc = IOService::terminate(fOptions); 806 LogFlow(("org_virtualbox_SupDrv::terminate: returns %d\n", fRc)); 807 return fRc; 808 } 809 810 811 /* 812 * 813 * org_virtualbox_SupDrvClient 814 * 815 */ 816 817 818 /** 819 * Initializer called when the client opens the service. 820 */ 821 bool org_virtualbox_SupDrvClient::initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type) 822 { 823 LogFlow(("org_virtualbox_SupDrvClient::initWithTask([%p], %#x, %p, %#x) (cur pid=%d proc=%p)\n", 824 this, OwningTask, pvSecurityId, u32Type, RTProcSelf(), RTR0ProcHandleSelf())); 825 AssertMsg((RTR0PROCESS)OwningTask == RTR0ProcHandleSelf(), ("%p %p\n", OwningTask, RTR0ProcHandleSelf())); 826 827 if (!OwningTask) 828 return false; 829 if (IOUserClient::initWithTask(OwningTask, pvSecurityId , u32Type)) 830 { 831 m_Task = OwningTask; 832 m_pSession = NULL; 833 m_pProvider = NULL; 834 return true; 835 } 836 return false; 837 } 838 839 840 /** 841 * Start the client service. 842 */ 843 bool org_virtualbox_SupDrvClient::start(IOService *pProvider) 844 { 845 LogFlow(("org_virtualbox_SupDrvClient::start([%p], %p) (cur pid=%d proc=%p)\n", 846 this, pProvider, RTProcSelf(), RTR0ProcHandleSelf() )); 847 AssertMsgReturn((RTR0PROCESS)m_Task == RTR0ProcHandleSelf(), 848 ("%p %p\n", m_Task, RTR0ProcHandleSelf()), 849 false); 850 851 if (IOUserClient::start(pProvider)) 852 { 853 m_pProvider = OSDynamicCast(org_virtualbox_SupDrv, pProvider); 854 if (m_pProvider) 855 { 856 Assert(!m_pSession); 857 858 /* 859 * Create a new session. 860 */ 861 int rc = supdrvCreateSession(&g_DevExt, true /* fUser */, &m_pSession); 862 if (RT_SUCCESS(rc)) 863 { 864 m_pSession->fOpened = false; 865 /* The Uid and Gid fields are set on open. */ 866 867 /* 868 * Insert it into the hash table, checking that there isn't 869 * already one for this process first. 870 */ 871 unsigned iHash = SESSION_HASH(m_pSession->Process); 872 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 873 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp); 874 875 PSUPDRVSESSION pCur = g_apSessionHashTab[iHash]; 876 if (pCur && pCur->Process != m_pSession->Process) 877 { 878 do pCur = pCur->pNextHash; 879 while (pCur && pCur->Process != m_pSession->Process); 880 } 881 if (!pCur) 882 { 883 m_pSession->pNextHash = g_apSessionHashTab[iHash]; 884 g_apSessionHashTab[iHash] = m_pSession; 885 m_pSession->pvSupDrvClient = this; 886 ASMAtomicIncS32(&g_cSessions); 887 rc = VINF_SUCCESS; 888 } 889 else 890 rc = VERR_ALREADY_LOADED; 891 892 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp); 893 if (RT_SUCCESS(rc)) 894 { 895 Log(("org_virtualbox_SupDrvClient::start: created session %p for pid %d\n", m_pSession, (int)RTProcSelf())); 896 return true; 897 } 898 899 LogFlow(("org_virtualbox_SupDrvClient::start: already got a session for this process (%p)\n", pCur)); 900 supdrvCloseSession(&g_DevExt, m_pSession); 901 } 902 903 m_pSession = NULL; 904 LogFlow(("org_virtualbox_SupDrvClient::start: rc=%Rrc from supdrvCreateSession\n", rc)); 905 } 906 else 907 LogFlow(("org_virtualbox_SupDrvClient::start: %p isn't org_virtualbox_SupDrv\n", pProvider)); 908 } 909 return false; 910 } 911 912 913 /** 914 * Common worker for clientClose and VBoxDrvDarwinClose. 915 * 916 * It will 917 */ 918 /* static */ void org_virtualbox_SupDrvClient::sessionClose(RTPROCESS Process) 919 { 920 /* 921 * Look for the session. 922 */ 923 const unsigned iHash = SESSION_HASH(Process); 924 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 925 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp); 926 PSUPDRVSESSION pSession = g_apSessionHashTab[iHash]; 394 927 if (pSession) 395 928 { … … 423 956 if (!pSession) 424 957 { 425 OSDBGPRINT(("VBoxDrvDarwinClose: WHAT?!? pSession == NULL! This must be a mistake... pid=%d (close)\n", 426 (int)Process)); 427 return EINVAL; 958 Log(("SupDrvClient::sessionClose: pSession == NULL, pid=%d; freed already?\n", (int)Process)); 959 return; 960 } 961 962 /* 963 * Remove it from the client object. 964 */ 965 org_virtualbox_SupDrvClient *pThis = (org_virtualbox_SupDrvClient *)pSession->pvSupDrvClient; 966 pSession->pvSupDrvClient = NULL; 967 if (pThis) 968 { 969 Assert(pThis->m_pSession == pSession); 970 pThis->m_pSession = NULL; 428 971 } 429 972 … … 432 975 */ 433 976 supdrvCloseSession(&g_DevExt, pSession); 434 return 0;435 }436 437 438 /**439 * Device I/O Control entry point.440 *441 * @returns Darwin for slow IOCtls and VBox status code for the fast ones.442 * @param Dev The device number (major+minor).443 * @param iCmd The IOCtl command.444 * @param pData Pointer to the data (if any it's a SUPDRVIOCTLDATA (kernel copy)).445 * @param fFlags Flag saying we're a character device (like we didn't know already).446 * @param pProcess The process issuing this request.447 */448 static int VBoxDrvDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess)449 {450 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;451 const RTPROCESS Process = proc_pid(pProcess);452 const unsigned iHash = SESSION_HASH(Process);453 PSUPDRVSESSION pSession;454 455 /*456 * Find the session.457 */458 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);459 pSession = g_apSessionHashTab[iHash];460 if (pSession && pSession->Process != Process)461 {462 do pSession = pSession->pNextHash;463 while (pSession && pSession->Process != Process);464 }465 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);466 if (!pSession)467 {468 OSDBGPRINT(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#x\n",469 (int)Process, iCmd));470 return EINVAL;471 }472 473 /*474 * Deal with the two high-speed IOCtl that takes it's arguments from475 * the session and iCmd, and only returns a VBox status code.476 */477 if ( iCmd == SUP_IOCTL_FAST_DO_RAW_RUN478 || iCmd == SUP_IOCTL_FAST_DO_HWACC_RUN479 || iCmd == SUP_IOCTL_FAST_DO_NOP)480 return supdrvIOCtlFast(iCmd, &g_DevExt, pSession);481 return VBoxDrvDarwinIOCtlSlow(pSession, iCmd, pData, pProcess);482 }483 484 485 /**486 * Worker for VBoxDrvDarwinIOCtl that takes the slow IOCtl functions.487 *488 * @returns Darwin errno.489 *490 * @param pSession The session.491 * @param iCmd The IOCtl command.492 * @param pData Pointer to the kernel copy of the SUPDRVIOCTLDATA buffer.493 * @param pProcess The calling process.494 */495 static int VBoxDrvDarwinIOCtlSlow(PSUPDRVSESSION pSession, u_long iCmd, caddr_t pData, struct proc *pProcess)496 {497 LogFlow(("VBoxDrvDarwinIOCtlSlow: pSession=%p iCmd=%p pData=%p pProcess=%p\n", pSession, iCmd, pData, pProcess));498 499 500 /*501 * Buffered or unbuffered?502 */503 PSUPREQHDR pHdr;504 user_addr_t pUser = 0;505 void *pvPageBuf = NULL;506 uint32_t cbReq = IOCPARM_LEN(iCmd);507 if ((IOC_DIRMASK & iCmd) == IOC_INOUT)508 {509 pHdr = (PSUPREQHDR)pData;510 if (RT_UNLIKELY(cbReq < sizeof(*pHdr)))511 {512 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: cbReq=%#x < %#x; iCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), iCmd));513 return EINVAL;514 }515 if (RT_UNLIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))516 {517 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: bad magic fFlags=%#x; iCmd=%#lx\n", pHdr->fFlags, iCmd));518 return EINVAL;519 }520 if (RT_UNLIKELY( RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq521 || pHdr->cbIn < sizeof(*pHdr)522 || pHdr->cbOut < sizeof(*pHdr)))523 {524 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: max(%#x,%#x) != %#x; iCmd=%#lx\n", pHdr->cbIn, pHdr->cbOut, cbReq, iCmd));525 return EINVAL;526 }527 }528 else if ((IOC_DIRMASK & iCmd) == IOC_VOID && !cbReq)529 {530 /*531 * Get the header and figure out how much we're gonna have to read.532 */533 SUPREQHDR Hdr;534 pUser = (user_addr_t)*(void **)pData;535 int rc = copyin(pUser, &Hdr, sizeof(Hdr));536 if (RT_UNLIKELY(rc))537 {538 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyin(%llx,Hdr,) -> %#x; iCmd=%#lx\n", (unsigned long long)pUser, rc, iCmd));539 return rc;540 }541 if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))542 {543 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: bad magic fFlags=%#x; iCmd=%#lx\n", Hdr.fFlags, iCmd));544 return EINVAL;545 }546 cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut);547 if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr)548 || Hdr.cbOut < sizeof(Hdr)549 || cbReq > _1M*16))550 {551 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: max(%#x,%#x); iCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, iCmd));552 return EINVAL;553 }554 555 /*556 * Allocate buffer and copy in the data.557 */558 pHdr = (PSUPREQHDR)RTMemTmpAlloc(cbReq);559 if (!pHdr)560 pvPageBuf = pHdr = (PSUPREQHDR)IOMallocAligned(RT_ALIGN_Z(cbReq, PAGE_SIZE), 8);561 if (RT_UNLIKELY(!pHdr))562 {563 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: failed to allocate buffer of %d bytes; iCmd=%#lx\n", cbReq, iCmd));564 return ENOMEM;565 }566 rc = copyin(pUser, pHdr, Hdr.cbIn);567 if (RT_UNLIKELY(rc))568 {569 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyin(%llx,%p,%#x) -> %#x; iCmd=%#lx\n",570 (unsigned long long)pUser, pHdr, Hdr.cbIn, rc, iCmd));571 if (pvPageBuf)572 IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE));573 else574 RTMemTmpFree(pHdr);575 return rc;576 }577 }578 else579 {580 Log(("VBoxDrvDarwinIOCtlSlow: huh? cbReq=%#x iCmd=%#lx\n", cbReq, iCmd));581 return EINVAL;582 }583 584 /*585 * Process the IOCtl.586 */587 int rc = supdrvIOCtl(iCmd, &g_DevExt, pSession, pHdr);588 if (RT_LIKELY(!rc))589 {590 /*591 * If not buffered, copy back the buffer before returning.592 */593 if (pUser)594 {595 uint32_t cbOut = pHdr->cbOut;596 if (cbOut > cbReq)597 {598 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, iCmd));599 cbOut = cbReq;600 }601 rc = copyout(pHdr, pUser, cbOut);602 if (RT_UNLIKELY(rc))603 OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyout(%p,%llx,%#x) -> %d; uCmd=%#lx!\n",604 pHdr, (unsigned long long)pUser, cbOut, rc, iCmd));605 606 /* cleanup */607 if (pvPageBuf)608 IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE));609 else610 RTMemTmpFree(pHdr);611 }612 }613 else614 {615 /*616 * The request failed, just clean up.617 */618 if (pUser)619 {620 if (pvPageBuf)621 IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE));622 else623 RTMemTmpFree(pHdr);624 }625 626 Log(("VBoxDrvDarwinIOCtlSlow: pid=%d iCmd=%lx pData=%p failed, rc=%d\n", proc_pid(pProcess), iCmd, (void *)pData, rc));627 rc = EINVAL;628 }629 630 Log2(("VBoxDrvDarwinIOCtlSlow: returns %d\n", rc));631 return rc;632 }633 634 635 /**636 * The SUPDRV IDC entry point.637 *638 * @returns VBox status code, see supdrvIDC.639 * @param iReq The request code.640 * @param pReq The request.641 */642 int VBOXCALL SUPDrvDarwinIDC(uint32_t uReq, PSUPDRVIDCREQHDR pReq)643 {644 PSUPDRVSESSION pSession;645 646 /*647 * Some quick validations.648 */649 if (RT_UNLIKELY(!VALID_PTR(pReq)))650 return VERR_INVALID_POINTER;651 652 pSession = pReq->pSession;653 if (pSession)654 {655 if (RT_UNLIKELY(!VALID_PTR(pSession)))656 return VERR_INVALID_PARAMETER;657 if (RT_UNLIKELY(pSession->pDevExt != &g_DevExt))658 return VERR_INVALID_PARAMETER;659 }660 else if (RT_UNLIKELY(uReq != SUPDRV_IDC_REQ_CONNECT))661 return VERR_INVALID_PARAMETER;662 663 /*664 * Do the job.665 */666 return supdrvIDC(uReq, &g_DevExt, pSession, pReq);667 }668 669 670 /**671 * Initializes any OS specific object creator fields.672 */673 void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)674 {675 NOREF(pObj);676 NOREF(pSession);677 }678 679 680 /**681 * Checks if the session can access the object.682 *683 * @returns true if a decision has been made.684 * @returns false if the default access policy should be applied.685 *686 * @param pObj The object in question.687 * @param pSession The session wanting to access the object.688 * @param pszObjName The object name, can be NULL.689 * @param prc Where to store the result when returning true.690 */691 bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)692 {693 NOREF(pObj);694 NOREF(pSession);695 NOREF(pszObjName);696 NOREF(prc);697 return false;698 }699 700 701 bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)702 {703 NOREF(pDevExt);704 return false;705 }706 707 708 /**709 * Converts a supdrv error code to a darwin error code.710 *711 * @returns corresponding darwin error code.712 * @param rc supdrv error code (SUPDRV_ERR_* defines).713 */714 static int VBoxDrvDarwinErr2DarwinErr(int rc)715 {716 switch (rc)717 {718 case 0: return 0;719 case SUPDRV_ERR_GENERAL_FAILURE: return EACCES;720 case SUPDRV_ERR_INVALID_PARAM: return EINVAL;721 case SUPDRV_ERR_INVALID_MAGIC: return EILSEQ;722 case SUPDRV_ERR_INVALID_HANDLE: return ENXIO;723 case SUPDRV_ERR_INVALID_POINTER: return EFAULT;724 case SUPDRV_ERR_LOCK_FAILED: return ENOLCK;725 case SUPDRV_ERR_ALREADY_LOADED: return EEXIST;726 case SUPDRV_ERR_PERMISSION_DENIED: return EPERM;727 case SUPDRV_ERR_VERSION_MISMATCH: return ENOSYS;728 }729 730 return EPERM;731 }732 733 734 /** @todo move this to assembly where a simple "jmp printf" will to the trick. */735 RTDECL(int) SUPR0Printf(const char *pszFormat, ...)736 {737 va_list args;738 char szMsg[512];739 740 va_start(args, pszFormat);741 vsnprintf(szMsg, sizeof(szMsg) - 1, pszFormat, args);742 va_end(args);743 744 szMsg[sizeof(szMsg) - 1] = '\0';745 printf("%s", szMsg);746 return 0;747 }748 749 750 /*751 *752 * org_virtualbox_SupDrv753 *754 */755 756 757 /**758 * Initialize the object.759 */760 bool org_virtualbox_SupDrv::init(OSDictionary *pDictionary)761 {762 LogFlow(("org_virtualbox_SupDrv::init([%p], %p)\n", this, pDictionary));763 if (IOService::init(pDictionary))764 {765 /* init members. */766 return true;767 }768 return false;769 }770 771 772 /**773 * Free the object.774 */775 void org_virtualbox_SupDrv::free(void)776 {777 LogFlow(("IOService::free([%p])\n", this));778 IOService::free();779 }780 781 782 /**783 * Check if it's ok to start this service.784 * It's always ok by us, so it's up to IOService to decide really.785 */786 IOService *org_virtualbox_SupDrv::probe(IOService *pProvider, SInt32 *pi32Score)787 {788 LogFlow(("org_virtualbox_SupDrv::probe([%p])\n", this));789 return IOService::probe(pProvider, pi32Score);790 }791 792 793 /**794 * Start this service.795 */796 bool org_virtualbox_SupDrv::start(IOService *pProvider)797 {798 LogFlow(("org_virtualbox_SupDrv::start([%p])\n", this));799 800 if (IOService::start(pProvider))801 {802 /* register the service. */803 registerService();804 return true;805 }806 return false;807 }808 809 810 /**811 * Stop this service.812 */813 void org_virtualbox_SupDrv::stop(IOService *pProvider)814 {815 LogFlow(("org_virtualbox_SupDrv::stop([%p], %p)\n", this, pProvider));816 IOService::stop(pProvider);817 }818 819 820 /**821 * Termination request.822 *823 * @return true if we're ok with shutting down now, false if we're not.824 * @param fOptions Flags.825 */826 bool org_virtualbox_SupDrv::terminate(IOOptionBits fOptions)827 {828 bool fRc;829 LogFlow(("org_virtualbox_SupDrv::terminate: reference_count=%d g_cSessions=%d (fOptions=%#x)\n",830 KMOD_INFO_NAME.reference_count, ASMAtomicUoReadS32(&g_cSessions), fOptions));831 if ( KMOD_INFO_NAME.reference_count != 0832 || ASMAtomicUoReadS32(&g_cSessions))833 fRc = false;834 else835 fRc = IOService::terminate(fOptions);836 LogFlow(("org_virtualbox_SupDrv::terminate: returns %d\n", fRc));837 return fRc;838 }839 840 841 /*842 *843 * org_virtualbox_SupDrvClient844 *845 */846 847 848 /**849 * Initializer called when the client opens the service.850 */851 bool org_virtualbox_SupDrvClient::initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type)852 {853 LogFlow(("org_virtualbox_SupDrvClient::initWithTask([%p], %#x, %p, %#x)\n", this, OwningTask, pvSecurityId, u32Type));854 855 if (!OwningTask)856 return false;857 if (IOUserClient::initWithTask(OwningTask, pvSecurityId , u32Type))858 {859 m_Task = OwningTask;860 m_pSession = NULL;861 m_pProvider = NULL;862 return true;863 }864 return false;865 }866 867 868 /**869 * Start the client service.870 */871 bool org_virtualbox_SupDrvClient::start(IOService *pProvider)872 {873 LogFlow(("org_virtualbox_SupDrvClient::start([%p], %p)\n", this, pProvider));874 if (IOUserClient::start(pProvider))875 {876 m_pProvider = OSDynamicCast(org_virtualbox_SupDrv, pProvider);877 if (m_pProvider)878 {879 /* this is where we could create the section. */880 return true;881 }882 LogFlow(("org_virtualbox_SupDrvClient::start: %p isn't org_virtualbox_SupDrv\n", pProvider));883 }884 return false;885 977 } 886 978 … … 891 983 IOReturn org_virtualbox_SupDrvClient::clientClose(void) 892 984 { 893 LogFlow(("org_virtualbox_SupDrvClient::clientClose([%p])\n", this)); 985 LogFlow(("org_virtualbox_SupDrvClient::clientClose([%p]) (cur pid=%d proc=%p)\n", this, RTProcSelf(), RTR0ProcHandleSelf())); 986 AssertMsg((RTR0PROCESS)m_Task == RTR0ProcHandleSelf(), ("%p %p\n", m_Task, RTR0ProcHandleSelf())); 987 988 /* 989 * Clean up the session if it's still around. 990 * 991 * We cannot rely 100% on close, and in the case of a dead client 992 * we'll end up hanging inside vm_map_remove() if we postpone it. 993 */ 994 if (m_pSession) 995 { 996 sessionClose(RTProcSelf()); 997 Assert(!m_pSession); 998 } 894 999 895 1000 m_pProvider = NULL; … … 901 1006 902 1007 /** 903 * The client exits abnormally / forgets to do cleanups. 1008 * The client exits abnormally / forgets to do cleanups. (logging) 904 1009 */ 905 1010 IOReturn org_virtualbox_SupDrvClient::clientDied(void) … … 908 1013 this, m_Task, RTR0ProcHandleSelf(), RTProcSelf())); 909 1014 910 /* 911 * Do early session cleanup (if there is a session) so 912 * we avoid hanging in vm_map_remove(). 913 */ 914 const RTR0PROCESS R0Process = (RTR0PROCESS)m_Task; 915 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 916 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp); 917 for (unsigned i = 0; i < RT_ELEMENTS(g_apSessionHashTab); i++) 918 { 919 for (PSUPDRVSESSION pSession = g_apSessionHashTab[i]; pSession; pSession = pSession->pNextHash) 920 { 921 Log2(("pSession=%p R0Process=%p (=? %p)\n", pSession, pSession->R0Process, R0Process)); 922 if (pSession->R0Process == R0Process) 923 { 924 /* 925 * It is safe to leave the spinlock here; the session shouldn't be able 926 * to go away while we're cleaning it up, changes to pNextHash will not 927 * harm us, and new sessions can't possibly be added for this process. 928 */ 929 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp); 930 supdrvCleanupSession(&g_DevExt, pSession); 931 RTSpinlockAcquireNoInts(g_Spinlock, &Tmp); 932 } 933 } 934 } 935 RTSpinlockReleaseNoInts(g_Spinlock, &Tmp); 936 937 /* IOUserClient::clientDied() calls close... */ 1015 /* IOUserClient::clientDied() calls clientClose, so we'll just do the work there. */ 938 1016 return IOUserClient::clientDied(); 939 1017 } … … 941 1019 942 1020 /** 943 * Terminate the service (initiate the destruction). 1021 * Terminate the service (initiate the destruction). (logging) 944 1022 */ 945 1023 bool org_virtualbox_SupDrvClient::terminate(IOOptionBits fOptions) … … 951 1029 952 1030 /** 953 * The final stage of the client service destruction. 1031 * The final stage of the client service destruction. (logging) 954 1032 */ 955 1033 bool org_virtualbox_SupDrvClient::finalize(IOOptionBits fOptions) … … 961 1039 962 1040 /** 963 * Stop the client service. 1041 * Stop the client service. (logging) 964 1042 */ 965 1043 void org_virtualbox_SupDrvClient::stop(IOService *pProvider) -
trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp
r10256 r10836 76 76 77 77 78 int suplibOsInit(size_t cbReserve) 79 { 80 /* 81 * Check if already initialized. 82 */ 83 if (g_hDevice >= 0) 84 return VINF_SUCCESS; 85 86 /* 87 * Open the IOKit client first - The first step is finding the service. 88 */ 89 mach_port_t MasterPort; 90 kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort); 91 if (kr != kIOReturnSuccess) 92 { 93 LogRel(("IOMasterPort -> %d\n", kr)); 94 return VERR_GENERAL_FAILURE; 95 } 96 97 CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_NAME); 98 if (!ClassToMatch) 99 { 100 LogRel(("IOServiceMatching(\"%s\") failed.\n", IOCLASS_NAME)); 101 return VERR_GENERAL_FAILURE; 102 } 103 104 /* Create an io_iterator_t for all instances of our drivers class that exist in the IORegistry. */ 105 io_iterator_t Iterator; 106 kr = IOServiceGetMatchingServices(g_MasterPort, ClassToMatch, &Iterator); 107 if (kr != kIOReturnSuccess) 108 { 109 LogRel(("IOServiceGetMatchingServices returned %d\n", kr)); 110 return VERR_GENERAL_FAILURE; 111 } 112 113 /* Get the first item in the iterator and release it. */ 114 io_service_t ServiceObject = IOIteratorNext(Iterator); 115 IOObjectRelease(Iterator); 116 if (!ServiceObject) 117 { 118 LogRel(("SUP: Couldn't find any matches. The kernel module is probably not loaded.\n")); 119 return VERR_VM_DRIVER_NOT_INSTALLED; 120 } 121 122 /* 123 * Open the service. 124 * This will cause the user client class in SUPDrv-darwin.cpp to be instantiated. 125 */ 126 kr = IOServiceOpen(ServiceObject, mach_task_self(), 0, &g_Connection); 127 IOObjectRelease(ServiceObject); 128 if (kr != kIOReturnSuccess) 129 { 130 LogRel(("SUP: IOServiceOpen returned %d. Driver open failed.\n", kr)); 131 return VERR_VM_DRIVER_OPEN_ERROR; 132 } 133 134 /* 135 * Now, try open the BSD device. 78 /** 79 * Opens the BSD device node. 80 * 81 * @returns VBox status code. 82 */ 83 static int suplibDarwinOpenDevice(void) 84 { 85 /* 86 * Open the BSD device. 87 * This will connect to the session created when the SupDrvClient was 88 * started, so it has to be done after opening the service (IOC v9.1+). 136 89 */ 137 90 g_hDevice = open(DEVICE_NAME, O_RDWR, 0); … … 148 101 } 149 102 LogRel(("SUP: Failed to open \"%s\", errno=%d, rc=%Vrc\n", DEVICE_NAME, errno, rc)); 150 151 kr = IOServiceClose(g_Connection);152 if (kr != kIOReturnSuccess)153 LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr));154 103 return rc; 155 104 } … … 160 109 if (fcntl(g_hDevice, F_SETFD, FD_CLOEXEC) != 0) 161 110 { 162 int rc = errno; 163 LogRel(("suplibOSInit: setting FD_CLOEXEC failed, errno=%d\n", rc)); 111 int err = errno; 112 int rc = RTErrConvertFromErrno(err); 113 LogRel(("suplibOSInit: setting FD_CLOEXEC failed, errno=%d (%Rrc)\n", err, rc)); 164 114 close(g_hDevice); 165 115 g_hDevice = -1; 166 return RTErrConvertFromErrno(rc); 167 } 168 169 /* 170 * We're done. 171 */ 116 return rc; 117 } 118 119 return VINF_SUCCESS; 120 } 121 122 123 /** 124 * Opens the IOKit service, instantiating org_virtualbox_SupDrvClient. 125 * 126 * @returns VBox status code. 127 */ 128 static int suplibDarwinOpenService(void) 129 { 130 /* 131 * Open the IOKit client first - The first step is finding the service. 132 */ 133 mach_port_t MasterPort; 134 kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort); 135 if (kr != kIOReturnSuccess) 136 { 137 LogRel(("IOMasterPort -> %d\n", kr)); 138 return VERR_GENERAL_FAILURE; 139 } 140 141 CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_NAME); 142 if (!ClassToMatch) 143 { 144 LogRel(("IOServiceMatching(\"%s\") failed.\n", IOCLASS_NAME)); 145 return VERR_GENERAL_FAILURE; 146 } 147 148 /* Create an io_iterator_t for all instances of our drivers class that exist in the IORegistry. */ 149 io_iterator_t Iterator; 150 kr = IOServiceGetMatchingServices(g_MasterPort, ClassToMatch, &Iterator); 151 if (kr != kIOReturnSuccess) 152 { 153 LogRel(("IOServiceGetMatchingServices returned %d\n", kr)); 154 return VERR_GENERAL_FAILURE; 155 } 156 157 /* Get the first item in the iterator and release it. */ 158 io_service_t ServiceObject = IOIteratorNext(Iterator); 159 IOObjectRelease(Iterator); 160 if (!ServiceObject) 161 { 162 LogRel(("SUP: Couldn't find any matches. The kernel module is probably not loaded.\n")); 163 return VERR_VM_DRIVER_NOT_INSTALLED; 164 } 165 166 /* 167 * Open the service. 168 * 169 * This will cause the user client class in SUPDrv-darwin.cpp to be 170 * instantiated and create a session for this process. 171 */ 172 kr = IOServiceOpen(ServiceObject, mach_task_self(), 0, &g_Connection); 173 IOObjectRelease(ServiceObject); 174 if (kr != kIOReturnSuccess) 175 { 176 LogRel(("SUP: IOServiceOpen returned %d. Driver open failed.\n", kr)); 177 return VERR_VM_DRIVER_OPEN_ERROR; 178 } 179 180 return VINF_SUCCESS; 181 } 182 183 int suplibOsInit(size_t cbReserve) 184 { 172 185 NOREF(cbReserve); 173 return VINF_SUCCESS; 186 187 /* 188 * Check if already initialized. 189 */ 190 if (g_hDevice >= 0) 191 return VINF_SUCCESS; 192 193 /* 194 * Do the job. 195 */ 196 int rc = suplibDarwinOpenService(); 197 if (RT_SUCCESS(rc)) 198 { 199 rc = suplibDarwinOpenDevice(); 200 if (RT_FAILURE(rc)) 201 { 202 kern_return_t kr = IOServiceClose(g_Connection); 203 if (kr != kIOReturnSuccess) 204 { 205 LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr)); 206 AssertFailed(); 207 } 208 g_Connection = NULL; 209 } 210 } 211 212 return rc; 174 213 } 175 214 … … 178 217 { 179 218 /* 180 * Check if we're initited at all. 181 */ 182 if (g_hDevice >= 0) 183 { 184 if (close(g_hDevice)) 185 AssertFailed(); 186 g_hDevice = -1; 187 } 188 189 /* 190 * Close the connection to the IOService and destroy the connection handle. 219 * Close the connection to the IOService. 220 * This will cause the SUPDRVSESSION to be closed (starting IOC 9.1). 191 221 */ 192 222 if (g_Connection) … … 201 231 } 202 232 233 /* 234 * Check if we're initited at all. 235 */ 236 if (g_hDevice >= 0) 237 { 238 if (close(g_hDevice)) 239 AssertFailed(); 240 g_hDevice = -1; 241 } 242 203 243 return VINF_SUCCESS; 204 244 }
Note:
See TracChangeset
for help on using the changeset viewer.