| | 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]; |
|---|
| 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 from |
|---|
| 475 | | * the session and iCmd, and only returns a VBox status code. |
|---|
| 476 | | */ |
|---|
| 477 | | if ( iCmd == SUP_IOCTL_FAST_DO_RAW_RUN |
|---|
| 478 | | || iCmd == SUP_IOCTL_FAST_DO_HWACC_RUN |
|---|
| 479 | | || 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) != cbReq |
|---|
| 521 | | || 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 | | else |
|---|
| 574 | | RTMemTmpFree(pHdr); |
|---|
| 575 | | return rc; |
|---|
| 576 | | } |
|---|
| 577 | | } |
|---|
| 578 | | else |
|---|
| 579 | | { |
|---|
| 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 | | else |
|---|
| 610 | | RTMemTmpFree(pHdr); |
|---|
| 611 | | } |
|---|
| 612 | | } |
|---|
| 613 | | else |
|---|
| 614 | | { |
|---|
| 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 | | else |
|---|
| 623 | | 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_SupDrv |
|---|
| 753 | | * |
|---|
| 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 | |
|---|