void BatteryTracker::stop(IOService* provider)
{
    DEBUG_LOG("BatteryTracker::stop: entering stop\n");
    
    OSSafeReleaseNULL(m_pBatteryList);
    if (NULL != m_pLock)
    {
        IORecursiveLockFree(m_pLock);
        m_pLock = NULL;
    }
    if (m_pCmdGate)
    {
        IOWorkLoop* pWorkLoop = getWorkLoop();
        if (pWorkLoop)
            pWorkLoop->removeEventSource(m_pCmdGate);
        m_pCmdGate->release();
        m_pCmdGate = NULL;
    }
    
    IOService::stop(provider);
}
void ApplePS2CypressTouchPad::stop( IOService * provider )
{
    //
    // The driver has been instructed to stop.  Note that we must break all
    // connections to other service objects now (ie. no registered actions,
    // no pointers and retains to objects, etc), if any.
    //

    assert(_device == provider);

    //
    // Disable the mouse itself, so that it may stop reporting mouse events.
    //

    setTouchPadEnable(false);

    //
    // Uninstall the interrupt handler.
    //

    if ( _interruptHandlerInstalled )  _device->uninstallInterruptAction();
    _interruptHandlerInstalled = false;

    //
    // Uninstall the power control handler.
    //

    if ( _powerControlHandlerInstalled ) _device->uninstallPowerControlAction();
    _powerControlHandlerInstalled = false;

    //
    // Release the pointer to the provider object.
    //
    
    OSSafeReleaseNULL(_device);
    
	super::stop(provider);
}
Ejemplo n.º 3
0
void FileNVRAM::stop(IOService *provider)
{
	// OSSafeReleaseNULL(mFilePath);

	if (mTimer)
	{
		mTimer->cancelTimeout();
		getWorkLoop()->removeEventSource(mTimer);
		OSSafeReleaseNULL(mTimer);
	}

	if (mCommandGate)
	{
		getWorkLoop()->removeEventSource(mCommandGate);
	}

	PMstop();
	LOG(NOTICE, "Stop called, attempting to detachFromParent\n");

	IORegistryEntry* root = IORegistryEntry::fromPath("/", gIODTPlane);
	detachFromParent(root, gIODTPlane);

	LOG(NOTICE, "Stop has passed the detach point.. move along now\n");
}
Ejemplo n.º 4
0
bool
ZFSDatasetProxy::start(IOService *provider)
{
	OSObject *property = NULL, *size = NULL;
	OSString *nameString = NULL;
	OSNumber *sizeNum = NULL;
	OSDictionary *deviceDict = NULL, *protocolDict = NULL;
	const OSSymbol *virtualSymbol = NULL, *internalSymbol = NULL;
	const char *cstr = NULL;
	char *pstring = NULL;
	int plen = 0;
	bool started = false;

	size = copyProperty(kZFSPoolSizeKey, gIOServicePlane,
	    (kIORegistryIterateRecursively|kIORegistryIterateParents));
	property = copyProperty(kZFSPoolNameKey, gIOServicePlane,
	    (kIORegistryIterateRecursively|kIORegistryIterateParents));

	if (!size || !property) {
		dprintf("couldn't get pool name or size");
		goto error;
	}

	nameString = OSDynamicCast(OSString, property);
	if (!nameString) {
		dprintf("missing pool name");
		goto error;
	}
#if 0
	/* Try hard to get the name string */
	do {
		nameString = OSDynamicCast(OSString, property);

		if (nameString) nameString->retain();

		if (!nameString) {
			OSSymbol *nameSymbol;
		       	nameSymbol = OSDynamicCast(OSSymbol, property);
			if (!nameSymbol) {
				dprintf("couldn't get name");
				goto error;
			}
			nameString = OSString::withCString(
			    nameSymbol->getCStringNoCopy());
		}
	} while (0);
#endif

	sizeNum = OSDynamicCast(OSNumber, size);
	if (!sizeNum) {
		dprintf("invalid size");
		goto error;
	}
	_pool_bcount = sizeNum->unsigned64BitValue() / DEV_BSIZE;
	sizeNum = 0;
	size->release();
	size = 0;

	cstr = nameString->getCStringNoCopy();
	if (!cstr || (plen = strlen(cstr) + 1) == 1) {
		goto error;
	}
	pstring = (char *)IOMalloc(plen);
	if (!pstring) {
		goto error;
	}
	snprintf(pstring, plen, "%s", cstr);
	productString = pstring;
	pstring = 0;

	if (IOBlockStorageDevice::start(provider) == false) {
		dprintf("BlockStorageDevice start failed");
		goto error;
	}
	started = true;

	deviceDict = OSDynamicCast(OSDictionary,
	    getProperty(kIOPropertyDeviceCharacteristicsKey));
	if (deviceDict) {
		/* Clone a new dictionary */
		deviceDict = OSDictionary::withDictionary(deviceDict);
		if (!deviceDict) {
			dprintf("dict clone failed");
			goto error;
		}
	}

	if (!deviceDict) {
		dprintf("creating new device dict");
		deviceDict = OSDictionary::withCapacity(1);
	}

	if (!deviceDict) {
		dprintf("missing device dict");
		goto error;
	}

	deviceDict->setObject(kIOPropertyProductNameKey, nameString);
	OSSafeReleaseNULL(nameString);

	if (setProperty(kIOPropertyDeviceCharacteristicsKey,
	    deviceDict) == false) {
		dprintf("device dict setProperty failed");
		goto error;
	}
	OSSafeReleaseNULL(deviceDict);

	protocolDict = OSDynamicCast(OSDictionary,
	    getProperty(kIOPropertyProtocolCharacteristicsKey));
	if (protocolDict) {
		/* Clone a new dictionary */
		protocolDict = OSDictionary::withDictionary(protocolDict);
		if (!protocolDict) {
			dprintf("dict clone failed");
			goto error;
		}
	}

	if (!protocolDict) {
		dprintf("creating new protocol dict");
		protocolDict = OSDictionary::withCapacity(1);
	}

	if (!protocolDict) {
		dprintf("missing protocol dict");
		goto error;
	}

	virtualSymbol = OSSymbol::withCString(
	    kIOPropertyPhysicalInterconnectTypeVirtual);
	internalSymbol = OSSymbol::withCString(
	    kIOPropertyInternalKey);
	if (!virtualSymbol || !internalSymbol) {
		dprintf("symbol alloc failed");
		goto error;
	}

	protocolDict->setObject(kIOPropertyPhysicalInterconnectTypeKey,
	    virtualSymbol);
	protocolDict->setObject(kIOPropertyPhysicalInterconnectLocationKey,
	    internalSymbol);

	OSSafeReleaseNULL(virtualSymbol);
	OSSafeReleaseNULL(internalSymbol);

	if (setProperty(kIOPropertyProtocolCharacteristicsKey,
	    protocolDict) == false) {
		dprintf("protocol dict setProperty failed");
		goto error;
	}
	OSSafeReleaseNULL(protocolDict);
	registerService(kIOServiceAsynchronous);

	return (true);

error:
	OSSafeReleaseNULL(size);
	OSSafeReleaseNULL(property);
	OSSafeReleaseNULL(deviceDict);
	OSSafeReleaseNULL(protocolDict);
	OSSafeReleaseNULL(nameString);
	OSSafeReleaseNULL(virtualSymbol);
	OSSafeReleaseNULL(internalSymbol);
	if (pstring) IOFree(pstring, plen);
	if (started) IOBlockStorageDevice::stop(provider);
	return (false);
}
Ejemplo n.º 5
0
bool ACPISensors::start(IOService * provider)
{
    ACPISensorsDebugLog("starting...");
    
	if (!super::start(provider))
        return false;

	if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) {
        ACPISensorsFatalLog("ACPI device not ready");
        return false;
    }

    methods = OSArray::withCapacity(0);
    
    // Try to load configuration provided by ACPI device
    OSObject *object = NULL;
        
    // Use Kelvins?
    if (kIOReturnSuccess == acpiDevice->evaluateObject("KLVN", &object) && object) {
        if (OSNumber *kelvins = OSDynamicCast(OSNumber, object)) {
            useKelvins = kelvins->unsigned8BitValue() == 1;
        }

        OSSafeReleaseNULL(object);
    }

    // Allow the device to be completely disabled depending on Platform
    OSDictionary *configuration = getConfigurationNode();
    if (configuration)
    {
        OSBoolean* disable = OSDynamicCast(OSBoolean, configuration->getObject("DisableDevice"));
        if (disable && disable->isTrue()) {
            return false;
        }
    }

    // Parse temperature table
    if (kIOReturnSuccess == acpiDevice->evaluateObject("TEMP", &object) && object) {
        addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryTemperature);
        OSSafeReleaseNULL(object);
    }
    else ACPISensorsDebugLog("temprerature description table (TEMP) not found");
    
    // Parse voltage table
    if (kIOReturnSuccess == acpiDevice->evaluateObject("VOLT", &object) && object) {
        addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryVoltage);
        OSSafeReleaseNULL(object);
    }
    else ACPISensorsDebugLog("voltage description table (VOLT) not found");
    
    // Parse amperage table
    if (kIOReturnSuccess == acpiDevice->evaluateObject("AMPR", &object) && object) {
        addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryCurrent);
        OSSafeReleaseNULL(object);
    }
    else ACPISensorsDebugLog("amperage description table (AMPR) not found");
    
    // Parse power table
    if (kIOReturnSuccess == acpiDevice->evaluateObject("POWR", &object) && object) {
        addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryPower);
        OSSafeReleaseNULL(object);
    }
    else ACPISensorsDebugLog("power description table (POWR) not found");
    
    // Parse tachometer table
    if (kIOReturnSuccess == acpiDevice->evaluateObject("TACH", &object) && object) {
        addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryFan);
        OSSafeReleaseNULL(object);
    }
    else ACPISensorsDebugLog("tachometer description table (TACH) not found");

    // If nothing was found on ACPI device try to load configuration from info.plist
    if (object == NULL && configuration)
    {
        if (OSDictionary *temperatures = OSDynamicCast(OSDictionary, configuration->getObject("Temperatures"))) {

            if (OSBoolean *kelvins = OSDynamicCast(OSBoolean, temperatures->getObject("UseKelvins"))) {
                useKelvins = kelvins->isTrue();
            }

            addSensorsFromDictionary(OSDynamicCast(OSDictionary, temperatures), kFakeSMCCategoryTemperature);
        }

        addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Voltages")), kFakeSMCCategoryVoltage);
        addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Currents")), kFakeSMCCategoryCurrent);
        addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Powers")), kFakeSMCCategoryPower);
        addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Tachometers")), kFakeSMCCategoryFan);
    }
    
    if (methods->getCount())
        ACPISensorsInfoLog("%d sensor%s added", methods->getCount(), methods->getCount() > 1 ? "s" : "");

	registerService();
    
    ACPISensorsInfoLog("started");

	return true;	
}
Ejemplo n.º 6
0
bool SuperIOPlugin::start(IOService *provider)
{	
	if (!super::start(provider)) 
        return false;
    
    OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress));
    
    if (!number || !(address = number->unsigned16BitValue())) {
        HWSensorsFatalLog("wrong address provided");
        return false;
    }
    
    number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort));
    
    if (!number || !(port = number->unsigned8BitValue())) {
        HWSensorsFatalLog("wrong port provided");
        return false;
    }
    
    number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue));
    
    if (!number || !(model = number->unsigned16BitValue())) {
        HWSensorsFatalLog("wrong model provided");
        return false;
    }
    
    OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName));
    
    if (!string || !(modelName = string->getCStringNoCopy())) {
        HWSensorsFatalLog("wrong model name provided");
        return false;
    }
    
    string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName));
    
    if (!string || !(vendorName = string->getCStringNoCopy())) {
        HWSensorsFatalLog("wrong vendor name provided");
        return false;
    }
    
    if (!initialize())
        return false;
    
    OSString *modelString = OSString::withCString(modelName);

	if (OSDictionary *configuration = getConfigurationNode(modelString))
    {
        addTemperatureSensors(configuration);
        addVoltageSensors(configuration);
        addTachometerSensors(configuration);
    }
    else HWSensorsWarningLog("no platform profile provided");
    
    OSSafeReleaseNULL(modelString);
    
    registerService();
    
    HWSensorsInfoLog("started");

	return true;
}
Ejemplo n.º 7
0
bool LPCSensors::start(IOService *provider)
{
	if (!super::start(provider))
        return false;

    OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress));

    if (!number || !(address = number->unsigned16BitValue())) {
        HWSensorsFatalLog("wrong address provided");
        return false;
    }

    number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort));

    if (!number || !(port = number->unsigned8BitValue())) {
        HWSensorsFatalLog("wrong port provided");
        return false;
    }

    number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue));

    if (!number || !(model = number->unsigned16BitValue())) {
        HWSensorsFatalLog("wrong model provided");
        return false;
    }

    OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName));

    if (!string || !(modelName = string->getCStringNoCopy())) {
        HWSensorsFatalLog("wrong model name provided");
        return false;
    }

    string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName));

    if (!string || !(vendorName = string->getCStringNoCopy())) {
        HWSensorsFatalLog("wrong vendor name provided");
        return false;
    }

    if (!initialize())
        return false;

    OSString *modelString = OSString::withCString(modelName);

	if (OSDictionary *configuration = getConfigurationNode(modelString))
    {
        addTemperatureSensors(configuration);
        addVoltageSensors(configuration);
        addTachometerSensors(configuration);
    }
    else HWSensorsWarningLog("no platform profile provided");

    OSSafeReleaseNULL(modelString);

    // woorkloop
    if (!(workloop = getWorkLoop())) {
        HWSensorsFatalLog("Failed to obtain workloop");
        return false;
    }

    if (!(timerEventSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &LPCSensors::woorkloopTimerEvent)))) {
        HWSensorsFatalLog("failed to initialize timer event source");
        return false;
    }

    if (kIOReturnSuccess != workloop->addEventSource(timerEventSource))
    {
        HWSensorsFatalLog("failed to add timer event source into workloop");
        return false;
    }

    // two power states - off and on
	static const IOPMPowerState powerStates[2] = {
        { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
    };

    // register interest in power state changes
	PMinit();
	provider->joinPMtree(this);
	registerPowerDriver(this, (IOPMPowerState *)powerStates, 2);

    registerService();

    HWSensorsInfoLog("started");

	return true;
}
Ejemplo n.º 8
0
void BrcmPatchRAM::stop(IOService* provider)
{
#ifdef DEBUG
    uint64_t stop_time, nano_secs;
    clock_get_uptime(&stop_time);
    absolutetime_to_nanoseconds(stop_time - wake_time, &nano_secs);
    uint64_t milli_secs = nano_secs / 1000000;
    AlwaysLog("Time since wake %llu.%llu seconds.\n", milli_secs / 1000, milli_secs % 1000);
#endif

    DebugLog("stop\n");

#if 0
#ifndef TARGET_ELCAPITAN
//REVIEW: so kext can be unloaded with kextunload -p
    // unload native bluetooth driver
    IOReturn result = gIOCatalogue->terminateDriversForModule(brcmBundleIdentifier, false);
    if (result != kIOReturnSuccess)
        AlwaysLog("[%04x:%04x]: failure terminating native Broadcom bluetooth (%08x)\n", mVendorId, mProductId, result);
    else
        DebugLog("[%04x:%04x]: success terminating native Broadcom bluetooth\n", mVendorId, mProductId);

    // unpublish native bluetooth personality
    removePersonality();
#endif
#endif

    mStopping = true;

    // allow firmware load already started to finish
    IOLockLock(mLoadFirmwareLock);

    OSSafeReleaseNULL(mFirmwareStore);

    IOWorkLoop* workLoop = getWorkLoop();
    if (workLoop)
    {
        if (mTimer)
        {
            mTimer->cancelTimeout();
            workLoop->removeEventSource(mTimer);
            mTimer->release();
            mTimer = NULL;
        }
        if (mWorkSource)
        {
            workLoop->removeEventSource(mWorkSource);
            mWorkSource->release();
            mWorkSource = NULL;
            mWorkPending = 0;
        }
    }

    PMstop();

    if (mCompletionLock)
    {
        IOLockFree(mCompletionLock);
        mCompletionLock = NULL;
    }
#ifndef NON_RESIDENT
    if (mWorkLock)
    {
        IOLockFree(mWorkLock);
        mWorkLock = NULL;
    }

    IOLockUnlock(mLoadFirmwareLock);
#endif // #ifndef NON_RESIDENT

    mDevice.setDevice(NULL);

    mStopping = false;

    super::stop(provider);
}
Ejemplo n.º 9
0
void
KLDBootstrap::readPrelinkedExtensions(
    kernel_section_t * prelinkInfoSect)
{
    OSArray                   * infoDictArray           = NULL;  // do not release
    OSArray                   * personalitiesArray      = NULL;  // do not release
    OSObject                  * parsedXML       = NULL;  // must release
    OSDictionary              * prelinkInfoDict         = NULL;  // do not release
    OSString                  * errorString             = NULL;  // must release
    OSKext                    * theKernel               = NULL;  // must release

#if CONFIG_KXLD
    kernel_section_t          * kernelLinkStateSection  = NULL;  // see code
#endif
    kernel_segment_command_t  * prelinkLinkStateSegment = NULL;  // see code
    kernel_segment_command_t  * prelinkTextSegment      = NULL;  // see code
    kernel_segment_command_t  * prelinkInfoSegment      = NULL;  // see code

   /* We make some copies of data, but if anything fails we're basically
    * going to fail the boot, so these won't be cleaned up on error.
    */
    void                      * prelinkData             = NULL;  // see code
    void                      * prelinkCopy             = NULL;  // see code
    vm_size_t                   prelinkLength           = 0;
#if !__LP64__ && !defined(__arm__)
    vm_map_offset_t             prelinkDataMapOffset    = 0;
#endif

    kern_return_t               mem_result              = KERN_SUCCESS;

    OSDictionary              * infoDict                = NULL;  // do not release

    IORegistryEntry           * registryRoot            = NULL;  // do not release
    OSNumber                  * prelinkCountObj         = NULL;  // must release

    u_int                       i = 0;

    OSKextLog(/* kext */ NULL,
        kOSKextLogProgressLevel |
        kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
        "Starting from prelinked kernel.");

   /*****
    * Wrap the kernel link state in-place in an OSData.
    * This is unnecessary (and the link state may not be present) if the kernel
    * does not have kxld support because this information is only used for
    * runtime linking.
    */
#if CONFIG_KXLD
    kernelLinkStateSection = getsectbyname(kPrelinkLinkStateSegment,
        kPrelinkKernelLinkStateSection);
    if (!kernelLinkStateSection) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogArchiveFlag,
            "Can't find prelinked kernel link state.");
        goto finish;
    }

    theKernel = OSKext::lookupKextWithIdentifier(kOSKextKernelIdentifier);
    if (!theKernel) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogArchiveFlag,
            "Can't find kernel kext object in prelinked kernel.");
        goto finish;
    }

    prelinkData = (void *) kernelLinkStateSection->addr;
    prelinkLength = kernelLinkStateSection->size;

    mem_result = kmem_alloc_pageable(kernel_map,
        (vm_offset_t *) &prelinkCopy, prelinkLength);
    if (mem_result != KERN_SUCCESS) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
            "Can't copy prelinked kernel link state.");
        goto finish;
    }
    memcpy(prelinkCopy, prelinkData, prelinkLength);

    theKernel->linkState = OSData::withBytesNoCopy(prelinkCopy, prelinkLength);
    if (!theKernel->linkState) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
            "Can't create prelinked kernel link state wrapper.");
        goto finish;
    }
    theKernel->linkState->setDeallocFunction(osdata_kmem_free);
#endif

    prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
    if (!prelinkTextSegment) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
            "Can't find prelinked kexts' text segment.");
        goto finish;
    }

    prelinkData = (void *) prelinkTextSegment->vmaddr;
    prelinkLength = prelinkTextSegment->vmsize;

#if !__LP64__
    /* To enable paging and write/execute protections on the kext
     * executables, we need to copy them out of the booter-created
     * memory, reallocate that space with VM, then prelinkCopy them back in.
     * This isn't necessary on LP64 because kexts have their own VM
     * region on that architecture model.
     */

    mem_result = kmem_alloc(kernel_map, (vm_offset_t *)&prelinkCopy,
        prelinkLength);
    if (mem_result != KERN_SUCCESS) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
            "Can't copy prelinked kexts' text for VM reassign.");
        goto finish;
    }

   /* Copy it out.
    */
    memcpy(prelinkCopy, prelinkData, prelinkLength);
    
   /* Dump the booter memory.
    */
    ml_static_mfree((vm_offset_t)prelinkData, prelinkLength);

   /* Set up the VM region.
    */
    prelinkDataMapOffset = (vm_map_offset_t)(uintptr_t)prelinkData;
    mem_result = vm_map_enter_mem_object(
        kernel_map,
        &prelinkDataMapOffset,
        prelinkLength, /* mask */ 0, 
        VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, 
        (ipc_port_t)NULL,
        (vm_object_offset_t) 0,
        /* copy */ FALSE,
        /* cur_protection */ VM_PROT_ALL,
        /* max_protection */ VM_PROT_ALL,
        /* inheritance */ VM_INHERIT_DEFAULT);
    if ((mem_result != KERN_SUCCESS) || 
        (prelinkTextSegment->vmaddr != prelinkDataMapOffset)) 
    {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
            "Can't create kexts' text VM entry at 0x%llx, length 0x%x (error 0x%x).",
            (unsigned long long) prelinkDataMapOffset, prelinkLength, mem_result);
        goto finish;
    }
    prelinkData = (void *)(uintptr_t)prelinkDataMapOffset;

   /* And copy it back.
    */
    memcpy(prelinkData, prelinkCopy, prelinkLength);

    kmem_free(kernel_map, (vm_offset_t)prelinkCopy, prelinkLength);
#endif /* !__LP64__ */

   /* Unserialize the info dictionary from the prelink info section.
    */
    parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr,
        &errorString);
    if (parsedXML) {
        prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML);
    }
    if (!prelinkInfoDict) {
        const char * errorCString = "(unknown error)";
        
        if (errorString && errorString->getCStringNoCopy()) {
            errorCString = errorString->getCStringNoCopy();
        } else if (parsedXML) {
            errorCString = "not a dictionary";
        }
        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
            "Error unserializing prelink plist: %s.", errorCString);
        goto finish;
    }

    infoDictArray = OSDynamicCast(OSArray, 
        prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey));
    if (!infoDictArray) {
        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
            "The prelinked kernel has no kext info dictionaries");
        goto finish;
    }

   /* Create OSKext objects for each info dictionary.
    */
    for (i = 0; i < infoDictArray->getCount(); ++i) {
        infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i));
        if (!infoDict) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
                "Can't find info dictionary for prelinked kext #%d.", i);
            continue;
        }

       /* Create the kext for the entry, then release it, because the
        * kext system keeps them around until explicitly removed.
        * Any creation/registration failures are already logged for us.
        */
        OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict);
        OSSafeReleaseNULL(newKext);
    }
    
    /* Get all of the personalities for kexts that were not prelinked and
     * add them to the catalogue.
     */
    personalitiesArray = OSDynamicCast(OSArray,
        prelinkInfoDict->getObject(kPrelinkPersonalitiesKey));
    if (!personalitiesArray) {
        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
            "The prelinked kernel has no personalities array");
        goto finish;
    }

    if (personalitiesArray->getCount()) {
        OSKext::setPrelinkedPersonalities(personalitiesArray);
    }

   /* Store the number of prelinked kexts in the registry so we can tell
    * when the system has been started from a prelinked kernel.
    */
    registryRoot = IORegistryEntry::getRegistryRoot();
    assert(registryRoot);

    prelinkCountObj = OSNumber::withNumber(
        (unsigned long long)infoDictArray->getCount(),
        8 * sizeof(uint32_t));
    assert(prelinkCountObj);
    if (prelinkCountObj) {
        registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj);
    }

    OSSafeReleaseNULL(prelinkCountObj);
    prelinkCountObj = OSNumber::withNumber(
        (unsigned long long)personalitiesArray->getCount(),
        8 * sizeof(uint32_t));
    assert(prelinkCountObj);
    if (prelinkCountObj) {
        registryRoot->setProperty(kOSPrelinkPersonalityCountKey, prelinkCountObj);
    }

    OSKextLog(/* kext */ NULL,
        kOSKextLogProgressLevel |
        kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
        kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
        "%u prelinked kexts, and %u additional personalities.", 
        infoDictArray->getCount(), personalitiesArray->getCount());

#if __LP64__
        /* On LP64 systems, kexts are copied to their own special VM region
         * during OSKext init time, so we can free the whole segment now.
         */
        ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
#endif /* __LP64__ */

   /* Free the link state segment, kexts have copied out what they need.
    */
    prelinkLinkStateSegment = getsegbyname(kPrelinkLinkStateSegment);
    if (prelinkLinkStateSegment) {
        ml_static_mfree((vm_offset_t)prelinkLinkStateSegment->vmaddr,
            (vm_size_t)prelinkLinkStateSegment->vmsize);
    }

   /* Free the prelink info segment, we're done with it.
    */
    prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
    if (prelinkInfoSegment) {
        ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
            (vm_size_t)prelinkInfoSegment->vmsize);
    }

finish:
    OSSafeRelease(errorString);
    OSSafeRelease(parsedXML);
    OSSafeRelease(theKernel);
    OSSafeRelease(prelinkCountObj);
    return;
}
void ApplePS2Mouse::stop(IOService * provider)
{
  //
  // The driver has been instructed to stop.  Note that we must break all
  // connections to other service objects now (ie. no registered actions,
  // no pointers and retains to objects, etc), if any.
  //

  assert(_device == provider);

  //
  // Disable the mouse itself, so that it may stop reporting mouse events.
  //

  setMouseEnable(false);

  // free up the command gate
  IOWorkLoop* pWorkLoop = getWorkLoop();
  if (pWorkLoop)
  {
    if (_cmdGate)
    {
      pWorkLoop->removeEventSource(_cmdGate);
      _cmdGate->release();
      _cmdGate = 0;
    }
    if (_buttonTimer)
    {
      pWorkLoop->removeEventSource(_buttonTimer);
      _buttonTimer->release();
      _buttonTimer = 0;
    }
  }
    
  //
  // Uninstall the interrupt handler.
  //

  if ( _interruptHandlerInstalled )  _device->uninstallInterruptAction();
  _interruptHandlerInstalled = false;

  //
  // Uninstall the power control handler.
  //

  if ( _powerControlHandlerInstalled ) _device->uninstallPowerControlAction();
  _powerControlHandlerInstalled = false;

  //
  // Uinstall message handler.
  //
  if (_messageHandlerInstalled)
  {
    _device->uninstallMessageAction();
    _messageHandlerInstalled = false;
  }
    
  //
  // Release the pointer to the provider object.
  //

  OSSafeReleaseNULL(_device);;

  super::stop(provider);
}
Ejemplo n.º 11
0
void
KLDBootstrap::loadKernelExternalComponents(void)
{
    OSDictionary         * extensionsDict = NULL;  // must release
    OSCollectionIterator * keyIterator    = NULL;  // must release
    OSString             * bundleID       = NULL;  // don't release
    OSKext               * theKext        = NULL;  // don't release
    OSBoolean            * isKernelExternalComponent = NULL;  // don't release

    OSKextLog(/* kext */ NULL,
        kOSKextLogStepLevel |
        kOSKextLogLoadFlag,
        "Loading Kernel External Components.");

    extensionsDict = OSKext::copyKexts();
    if (!extensionsDict) {
        return;
    }

    keyIterator = OSCollectionIterator::withCollection(extensionsDict);
    if (!keyIterator) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag,
            "Failed to allocate iterator for Kernel External Components.");
        goto finish;
    }

    while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {

        const char * bundle_id = bundleID->getCStringNoCopy();
        
       /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
        */
        if (!bundle_id ||
            (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) {

            continue;
        }

        theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
        if (!theKext) {
            continue;
        }

        isKernelExternalComponent = OSDynamicCast(OSBoolean,
            theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey));
        if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogStepLevel |
                kOSKextLogLoadFlag,
                "Loading kernel external component %s.", bundleID->getCStringNoCopy());
            OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
                /* allowDefer */ false);
        }
    }

finish:
    OSSafeReleaseNULL(keyIterator);
    OSSafeReleaseNULL(extensionsDict);

    return;
}
Ejemplo n.º 12
0
void
KLDBootstrap::readBooterExtensions(void)
{
    IORegistryEntry           * booterMemoryMap         = NULL;  // must release
    OSDictionary              * propertyDict            = NULL;  // must release
    OSCollectionIterator      * keyIterator             = NULL;  // must release
    OSString                  * deviceTreeName          = NULL;  // do not release
    
    const _DeviceTreeBuffer   * deviceTreeBuffer        = NULL;  // do not free
    char                      * booterDataPtr           = NULL;  // do not free
    OSData                    * booterData              = NULL;  // must release

    OSKext                    * aKext                   = NULL;  // must release

    OSKextLog(/* kext */ NULL,
        kOSKextLogProgressLevel |
        kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
        "Reading startup extensions from booter memory.");
    
    booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);

    if (!booterMemoryMap) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag,
            "Can't read booter memory map.");
        goto finish;
    }

    propertyDict = booterMemoryMap->dictionaryWithProperties();
    if (!propertyDict) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogDirectoryScanFlag,
            "Can't get property dictionary from memory map.");
        goto finish;
    }

    keyIterator = OSCollectionIterator::withCollection(propertyDict);
    if (!keyIterator) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag,
            "Can't allocate iterator for driver images.");
        goto finish;
    }

    /* Create dictionary of excluded kexts
     */
    OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
    keyIterator->reset();

    while ( ( deviceTreeName =
        OSDynamicCast(OSString, keyIterator->getNextObject() ))) {

        const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
        OSData * deviceTreeEntry = OSDynamicCast(OSData,
            propertyDict->getObject(deviceTreeName));

       /* Clear out the booterData from the prior iteration.
        */
        OSSafeReleaseNULL(booterData);

        /* If there is no entry for the name, we can't do much with it. */
        if (!deviceTreeEntry) {
            continue;
        }

        /* Make sure it is a kext */
        if (strncmp(devTreeNameCString,
                    BOOTER_KEXT_PREFIX,
                    CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
            continue;
        }

        deviceTreeBuffer = (const _DeviceTreeBuffer *)
            deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
        if (!deviceTreeBuffer) {
           /* We can't get to the data, so we can't do anything,
            * not even free it from physical memory (if it's there).
            */
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogDirectoryScanFlag,
                "Device tree entry %s has NULL pointer.",
                devTreeNameCString);
            goto finish;  // xxx - continue, panic?
        }

        booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
        if (!booterDataPtr) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogDirectoryScanFlag,
                "Can't get virtual address for device tree entry %s.",
                devTreeNameCString);
            goto finish;
        }

       /* Wrap the booter data buffer in an OSData and set a dealloc function
        * so it will take care of the physical memory when freed. Kexts will
        * retain the booterData for as long as they need it. Remove the entry
        * from the booter memory map after this is done.
        */
        booterData = OSData::withBytesNoCopy(booterDataPtr,
            deviceTreeBuffer->length);
        if (!booterData) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogGeneralFlag,
                "Error - Can't allocate OSData wrapper for device tree entry %s.",
                devTreeNameCString);
            goto finish;
        }
        booterData->setDeallocFunction(osdata_phys_free);

        /* Create the kext for the entry, then release it, because the
         * kext system keeps them around until explicitly removed.
         * Any creation/registration failures are already logged for us.
         */
        OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData);
        OSSafeReleaseNULL(newKext);

        booterMemoryMap->removeProperty(deviceTreeName);

    } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */

finish:

    OSSafeReleaseNULL(booterMemoryMap);
    OSSafeReleaseNULL(propertyDict);
    OSSafeReleaseNULL(keyIterator);
    OSSafeReleaseNULL(booterData);
    OSSafeReleaseNULL(aKext);
    return;
}
Ejemplo n.º 13
0
void
KLDBootstrap::readPrelinkedExtensions(
    kernel_section_t * prelinkInfoSect)
{
    OSArray                   * infoDictArray           = NULL;  // do not release
    OSObject                  * parsedXML       = NULL;  // must release
    OSDictionary              * prelinkInfoDict         = NULL;  // do not release
    OSString                  * errorString             = NULL;  // must release
    OSKext                    * theKernel               = NULL;  // must release

    kernel_segment_command_t  * prelinkTextSegment      = NULL;  // see code
    kernel_segment_command_t  * prelinkInfoSegment      = NULL;  // see code

   /* We make some copies of data, but if anything fails we're basically
    * going to fail the boot, so these won't be cleaned up on error.
    */
    void                      * prelinkData             = NULL;  // see code
    vm_size_t                   prelinkLength           = 0;


    OSDictionary              * infoDict                = NULL;  // do not release

    IORegistryEntry           * registryRoot            = NULL;  // do not release
    OSNumber                  * prelinkCountObj         = NULL;  // must release

    u_int                       i = 0;
#if NO_KEXTD
    bool                        ramDiskBoot;
    bool                        developerDevice;
    bool                        dontLoad;
#endif
    OSData                     * kaslrOffsets = NULL;
    unsigned long               plk_segSizes[PLK_SEGMENTS];
    vm_offset_t                 plk_segAddrs[PLK_SEGMENTS];

    OSKextLog(/* kext */ NULL,
        kOSKextLogProgressLevel |
        kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
        "Starting from prelinked kernel.");

    prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
    if (!prelinkTextSegment) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
            "Can't find prelinked kexts' text segment.");
        goto finish;
    }

#if KASLR_KEXT_DEBUG
    unsigned long   scratchSize;
    vm_offset_t     scratchAddr;
    
    IOLog("kaslr: prelinked kernel address info: \n");
    
    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__TEXT", &scratchSize);
    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n", 
          (unsigned long)scratchAddr, 
          (unsigned long)(scratchAddr + scratchSize),
          scratchSize);
    
    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__DATA", &scratchSize);
    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n", 
          (unsigned long)scratchAddr, 
          (unsigned long)(scratchAddr + scratchSize),
          scratchSize);
    
    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__LINKEDIT", &scratchSize);
    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n", 
          (unsigned long)scratchAddr, 
          (unsigned long)(scratchAddr + scratchSize),
          scratchSize);
    
    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__KLD", &scratchSize);
    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n", 
          (unsigned long)scratchAddr, 
          (unsigned long)(scratchAddr + scratchSize),
          scratchSize);
    
    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_TEXT", &scratchSize);
    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n", 
          (unsigned long)scratchAddr, 
          (unsigned long)(scratchAddr + scratchSize),
          scratchSize);
    
    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_INFO", &scratchSize);
    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n", 
          (unsigned long)scratchAddr, 
          (unsigned long)(scratchAddr + scratchSize),
          scratchSize);
#endif

    prelinkData = (void *) prelinkTextSegment->vmaddr;
    prelinkLength = prelinkTextSegment->vmsize;

    /* build arrays of plk info for later use */
    const char ** segNamePtr;

    for (segNamePtr = &plk_segNames[0], i = 0; *segNamePtr && i < PLK_SEGMENTS; segNamePtr++, i++) {
        plk_segSizes[i] = 0;
        plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(&_mh_execute_header, *segNamePtr, &plk_segSizes[i]);
    }


   /* Unserialize the info dictionary from the prelink info section.
    */
    parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr,
        &errorString);
    if (parsedXML) {
        prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML);
    }
    if (!prelinkInfoDict) {
        const char * errorCString = "(unknown error)";
        
        if (errorString && errorString->getCStringNoCopy()) {
            errorCString = errorString->getCStringNoCopy();
        } else if (parsedXML) {
            errorCString = "not a dictionary";
        }
        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
            "Error unserializing prelink plist: %s.", errorCString);
        goto finish;
    }

#if NO_KEXTD
    /* Check if we should keep developer kexts around.
     * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
     */
    developerDevice = true;
    PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice));

    ramDiskBoot = IORamDiskBSDRoot();
#endif /* NO_KEXTD */


    infoDictArray = OSDynamicCast(OSArray, 
        prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey));
    if (!infoDictArray) {
        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
            "The prelinked kernel has no kext info dictionaries");
        goto finish;
    }
    
    /* kaslrOffsets are available use them to slide local relocations */
    kaslrOffsets = OSDynamicCast(OSData,
                                 prelinkInfoDict->getObject(kPrelinkLinkKASLROffsetsKey));
        
    /* Create dictionary of excluded kexts
     */
    OSKext::createExcludeListFromPrelinkInfo(infoDictArray);
    /* Create OSKext objects for each info dictionary. 
     */
    for (i = 0; i < infoDictArray->getCount(); ++i) {
        infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i));
        if (!infoDict) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
                "Can't find info dictionary for prelinked kext #%d.", i);
            continue;
        }

#if NO_KEXTD
        dontLoad = false;

        /* If we're not on a developer device, skip and free developer kexts.
         */
        if (developerDevice == false) {
            OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean,
                infoDict->getObject(kOSBundleDeveloperOnlyKey));
            if (devOnlyBool == kOSBooleanTrue) {
                dontLoad = true;
            }
        }

        /* Skip and free kexts that are only needed when booted from a ram disk.
         */
        if (ramDiskBoot == false) {
            OSBoolean *ramDiskOnlyBool = OSDynamicCast(OSBoolean,
                infoDict->getObject(kOSBundleRamDiskOnlyKey));
            if (ramDiskOnlyBool == kOSBooleanTrue) {
                dontLoad = true;
            }
        }

        if (dontLoad == true) {
            OSString *bundleID = OSDynamicCast(OSString,
                infoDict->getObject(kCFBundleIdentifierKey));
            if (bundleID) {
                OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag,
                    "Kext %s not loading.", bundleID->getCStringNoCopy());
            }
            
            OSNumber *addressNum = OSDynamicCast(OSNumber,
                infoDict->getObject(kPrelinkExecutableLoadKey));
            OSNumber *lengthNum = OSDynamicCast(OSNumber,
                infoDict->getObject(kPrelinkExecutableSizeKey));
            if (addressNum && lengthNum) {
#error Pick the right way to free prelinked data on this arch
            }

            infoDictArray->removeObject(i--);
            continue;
        }
#endif /* NO_KEXTD */

       /* Create the kext for the entry, then release it, because the
        * kext system keeps them around until explicitly removed.
        * Any creation/registration failures are already logged for us.
        */
        OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict, (kaslrOffsets ? TRUE : FALSE));
        OSSafeReleaseNULL(newKext);
    }

    /* slide kxld relocations */
    if (kaslrOffsets && vm_kernel_slide > 0) {
	    int slidKextAddrCount = 0;
	    int badSlideAddr = 0;
	    int badSlideTarget = 0;

        kaslrPackedOffsets * myOffsets = NULL;
	    myOffsets = (kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy();

	    for (uint32_t j = 0; j < myOffsets->count; j++) {

		    uint64_t        slideOffset = (uint64_t) myOffsets->offsetsArray[j];
		    uintptr_t *     slideAddr = (uintptr_t *) ((uint64_t)prelinkData + slideOffset);
		    int             slideAddrSegIndex = -1;
		    int             addrToSlideSegIndex = -1;

		    slideAddrSegIndex = __whereIsAddr( (vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS );
		    if (slideAddrSegIndex >= 0) {
			    addrToSlideSegIndex = __whereIsAddr( (vm_offset_t)(*slideAddr + vm_kernel_slide), &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS );
			    if (addrToSlideSegIndex < 0) {
				    badSlideTarget++;
				    continue;
			    }
		    }
		    else {
			    badSlideAddr++;
			    continue;
		    }

		    slidKextAddrCount++;
		    *(slideAddr) += vm_kernel_slide;
	    } // for ...

	    /* All kexts are now slid, set VM protections for them */
	    OSKext::setAllVMAttributes();
    }

   /* Store the number of prelinked kexts in the registry so we can tell
    * when the system has been started from a prelinked kernel.
    */
    registryRoot = IORegistryEntry::getRegistryRoot();
    assert(registryRoot);

    prelinkCountObj = OSNumber::withNumber(
        (unsigned long long)infoDictArray->getCount(),
        8 * sizeof(uint32_t));
    assert(prelinkCountObj);
    if (prelinkCountObj) {
        registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj);
    }
    
    OSKextLog(/* kext */ NULL,
        kOSKextLogProgressLevel |
        kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
        kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
        "%u prelinked kexts", 
        infoDictArray->getCount());

#if CONFIG_KEXT_BASEMENT
        /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own 
         * special VM region during OSKext init time, so we can free the whole 
         * segment now.
         */
        ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
#endif /* __x86_64__ */

   /* Free the prelink info segment, we're done with it.
    */
    prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
    if (prelinkInfoSegment) {
        ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
            (vm_size_t)prelinkInfoSegment->vmsize);
    }

finish:
    OSSafeReleaseNULL(errorString);
    OSSafeReleaseNULL(parsedXML);
    OSSafeReleaseNULL(theKernel);
    OSSafeReleaseNULL(prelinkCountObj);
    return;
}
Ejemplo n.º 14
0
// We are the best match, setup driver
bool ODINXHostDevice::start(IOService *provider) {
    LOG(V_DEBUG, "ODINXHostDevice::start called");

    this->usbDevice = OSDynamicCast(IOUSBHostDevice, provider);
    if (!this->usbDevice) {
        
        LOG(V_ERROR, "Provider is not an IOUSBHostDevice, this is impossible!");
        // Tell the kernel to try the next highest score driver
        return false;
    }
    
    const StandardUSB::ConfigurationDescriptor *activeConfiguration = nullptr;
    IOReturn returnCode = NULL;
    
    if (!this->usbDevice->isOpen()) {
        returnCode = this->usbDevice->open(this);
        if (returnCode != kIOReturnSuccess && returnCode != kIOReturnExclusiveAccess) {
            /*
             * Only error if return code is neither kIOReturnSuccess or kIOReturnExclusiveAccess.
             * If we got kIOReturnExclusiveAccess that means we do (not?) have exclusivity and that open has already been called.
             */
            LOG(V_ERROR, "Error opening the USB device! Code: %04X", returnCode);
            return false;
        }
        LOG(V_DEBUG, "Device is not open and we failed to open it!");
    }
    
    // DEBUG
    {
        LOG(V_NOTE, "      Manufacturer: \"%s\"\n", ODINXHostDevice::stringDescriptorToCString(this->usbDevice->getStringDescriptor(this->usbDevice->getDeviceDescriptor()->iManufacturer)));
        LOG(V_NOTE, "           Product: \"%s\"\n", ODINXHostDevice::stringDescriptorToCString(this->usbDevice->getStringDescriptor(this->usbDevice->getDeviceDescriptor()->iProduct)));
        LOG(V_NOTE, "         Serial No: \"%s\"\n", ODINXHostDevice::stringDescriptorToCString(this->usbDevice->getStringDescriptor(this->usbDevice->getDeviceDescriptor()->iSerialNumber)));
        
        LOG(V_NOTE, "            length: %d\n", this->usbDevice->getDeviceDescriptor()->bLength);
        LOG(V_NOTE, "      device class: %d\n", this->usbDevice->getDeviceDescriptor()->bDeviceClass);
        LOG(V_NOTE, "               S/N: %d\n", this->usbDevice->getDeviceDescriptor()->iSerialNumber);
        LOG(V_NOTE, "           VID:PID: %04X:%04X\n", this->usbDevice->getDeviceDescriptor()->idVendor, this->usbDevice->getDeviceDescriptor()->idProduct);
        LOG(V_NOTE, "         bcdDevice: %04X\n", this->usbDevice->getDeviceDescriptor()->bcdDevice);
        LOG(V_NOTE, "   iMan:iProd:iSer: %d:%d:%d\n", this->usbDevice->getDeviceDescriptor()->iManufacturer, this->usbDevice->getDeviceDescriptor()->iProduct, this->usbDevice->getDeviceDescriptor()->iSerialNumber);
        LOG(V_NOTE, "          nb confs: %d\n", this->usbDevice->getDeviceDescriptor()->bNumConfigurations);
    }
    
    if (this->usbDevice->getDeviceDescriptor()->bNumConfigurations > 0 && returnCode != kIOReturnExclusiveAccess) {
        for (int configIndex = 0; configIndex < this->usbDevice->getDeviceDescriptor()->bNumConfigurations; configIndex++) {
            // Set the configuration active, the second param disables IOKit from automaticly trying to find drivers for the new interfaces since we do it ourselves.
            activeConfiguration = this->usbDevice->getConfigurationDescriptor(configIndex);
            returnCode = this->usbDevice->setConfiguration(activeConfiguration->bConfigurationValue, false);
            if (returnCode != kIOReturnSuccess) {
                LOG(V_ERROR, "Error setting the device to the configuration at index zero!");
            }
            
            // Find the interfaces
            OSIterator *deviceInterfaceIterator = this->usbDevice->getChildIterator(gIOServicePlane);
            if (!deviceInterfaceIterator) {
                LOG(V_ERROR, "USB Device has no interfaces?!?!");
                return false;
            }
            
            OSObject *entry = nullptr;
            
            while ((entry = deviceInterfaceIterator->getNextObject()) != nullptr) {
                IOUSBHostInterface *usbInterface = OSDynamicCast(IOUSBHostInterface, entry);
                if (!usbInterface) {
                    LOG(V_DEBUG, "Object in interface iterator that isn't a IOUSBHostInterface!");
                    continue;
                }
                
                uint8_t interfaceClass = usbInterface->getInterfaceDescriptor()->bInterfaceClass;
                if (interfaceClass != USB_INTERFACE_CLASS_CDC_DATA) {
                    LOG(V_DEBUG, "Interface isn't of the CDC Data class. Interface class: 0x%02X!", interfaceClass);
                    continue;
                }

                {
                    LOG(V_NOTE, "config[%d].interface[%d]: num endpoints = %d", configIndex, usbInterface->getInterfaceDescriptor()->bInterfaceNumber, usbInterface->getInterfaceDescriptor()->bNumEndpoints);
                    LOG(V_NOTE, "   Class.SubClass.Protocol: %02X.%02X.%02X", usbInterface->getInterfaceDescriptor()->bInterfaceClass, usbInterface->getInterfaceDescriptor()->bInterfaceSubClass, usbInterface->getInterfaceDescriptor()->bInterfaceProtocol);
                }
                
                const StandardUSB::EndpointDescriptor *endpoint = nullptr;
                while ((endpoint = StandardUSB::getNextEndpointDescriptor(activeConfiguration, usbInterface->getInterfaceDescriptor(), endpoint)) != nullptr) {
                    {
                        LOG(V_NOTE, "       endpoint address: %02X\n", endpoint->bEndpointAddress);
                        LOG(V_NOTE, "           max packet size: %04X\n", endpoint->wMaxPacketSize);
                        LOG(V_NOTE, "          polling interval: %02X\n", endpoint->bInterval);
                    }
                    
                    if (!inPipe || !outPipe) {
                        if (StandardUSB::getEndpointDirection(endpoint)) {
                            if (inPipe) {
                                OSSafeReleaseNULL(inPipe);
                            }
                            this->inPipe = usbInterface->copyPipe(endpoint->bEndpointAddress);
                            LOG(V_DEBUG, "Found an input endpoint: 0x%02X!", endpoint->bEndpointAddress);
                        } else {
                            if (outPipe) {
                                OSSafeReleaseNULL(outPipe);
                            }
                            this->outPipe = usbInterface->copyPipe(endpoint->bEndpointAddress);
                            LOG(V_DEBUG, "Found an output endpoint: 0x%02X!", endpoint->bEndpointAddress);
                        }
                    }
                }
            }
            OSSafeReleaseNULL(deviceInterfaceIterator);
        }
        
        if (!inPipe || !outPipe) {
            LOG(V_ERROR, "Error opening I/O pipes!");
            OSSafeReleaseNULL(inPipe);
            OSSafeReleaseNULL(outPipe);
            return false;
        }
    } else if (returnCode != kIOReturnExclusiveAccess) {
        LOG(V_ERROR, "The USB device somehow has no valid configurations?!?!");
        return false;
    }
    
    // Retain the device
    usbDevice->retain();
    
    // Kick off input
    inPipe->io(inbuf.mdp, PAGE_SIZE, &inbuf.comp);
    this->handshake();
    
    LOG(V_NOTE, "ODIN Mode device successfully started!");
    return true;
}
Ejemplo n.º 15
0
void ODINXHostDevice::free() {
    OSSafeReleaseNULL(inbuf.mdp);
    OSSafeReleaseNULL(outbuf.mdp);
    IOUSBHostDevice::free();
}
Ejemplo n.º 16
0
bool setOemProperties(IOService *provider)
{
    SMBEntryPoint* eps = 0;
	IOMemoryDescriptor* dmiMemory = 0;
	IOItemCount dmiStructureCount = 0;
    
  	UInt8* biosAddress = NULL;	
    
    IOMemoryDescriptor * biosMemory = 0;
    IOMemoryMap * biosMap = 0;
    
    biosMemory = IOMemoryDescriptor::withPhysicalAddress( 0xf0000,0xfffff-0xf0000+1,kIODirectionOutIn);
    
    if(biosMemory)
    {
        biosMap = biosMemory->map();
        
        if(biosMap)
        {
            biosAddress = (UInt8 *) biosMap->getVirtualAddress();
        }
    }
    
    
	// Search 0x0f0000 - 0x0fffff for SMBIOS Ptr
	if(biosAddress)
        for (UInt32 Address = 0; Address < biosMap->getLength(); Address += 0x10) {
            if (*(UInt32 *)(biosAddress + Address) == SMBIOS_PTR) {
                eps = (SMBEntryPoint *)(biosAddress + Address);
                continue;
            }
        }
    
    if(eps)
        if (memcmp(eps->anchor, "_SM_", 4) == 0)
        {
            UInt8 csum;
            
            csum = checksum8(eps, sizeof(SMBEntryPoint));
            
            /*HWSensorsDebugLog("DMI checksum       = 0x%x", csum);
             HWSensorsDebugLog("DMI tableLength    = %d",
             eps->dmi.tableLength);
             HWSensorsDebugLog("DMI tableAddress   = 0x%x",
             (uint32_t) eps->dmi.tableAddress);
             HWSensorsDebugLog("DMI structureCount = %d",
             eps->dmi.structureCount);
             HWSensorsDebugLog("DMI bcdRevision    = %x",
             eps->dmi.bcdRevision);*/
            
            if (csum == 0 && eps->dmi.tableLength &&
                eps->dmi.structureCount)
            {
                dmiStructureCount = eps->dmi.structureCount;
                dmiMemory = IOMemoryDescriptor::withPhysicalAddress(
                                                                    eps->dmi.tableAddress, eps->dmi.tableLength,
                                                                    kIODirectionOutIn );
            }
            /*else
             {
             HWSensorsDebugLog("no DMI structure found");
             }*/
        }
    
    if (biosMap)
        OSSafeReleaseNULL(biosMap);
    
    if(biosMemory)
        OSSafeReleaseNULL(biosMemory);
    
    if ( dmiMemory )
    {
        if (IOMemoryMap *fDMIMemoryMap = dmiMemory->map())        {
            decodeSMBIOSTable(provider, (void *) fDMIMemoryMap->getVirtualAddress(), fDMIMemoryMap->getLength(), dmiStructureCount );
        
            OSSafeReleaseNULL(fDMIMemoryMap);
        }
        
        OSSafeReleaseNULL(dmiMemory);
    }
    
    return true;
}
bool IOHIDInterface::start( IOService * provider )
{
    OSNumber * number;
    
    if ( !super::start(provider) )
        return false;
		
	_owner = OSDynamicCast( IOHIDDevice, provider );
	
	if ( !_owner )
		return false;
            
    
    _transportString    = (OSString*)copyProperty(kIOHIDTransportKey);
    _manufacturerString = (OSString*)copyProperty(kIOHIDManufacturerKey);
    _productString      = (OSString*)copyProperty(kIOHIDProductKey);
    _serialNumberString = (OSString*)copyProperty(kIOHIDSerialNumberKey);
    if (_transportString && !OSDynamicCast(OSString, _transportString))
        OSSafeReleaseNULL(_transportString);
    if (_manufacturerString && !OSDynamicCast(OSString, _manufacturerString))
        OSSafeReleaseNULL(_manufacturerString);
    if (_productString && !OSDynamicCast(OSString, _productString))
        OSSafeReleaseNULL(_productString);
    if (_serialNumberString && !OSDynamicCast(OSString, _serialNumberString))
        OSSafeReleaseNULL(_serialNumberString);
    
    number = (OSNumber*)copyProperty(kIOHIDLocationIDKey);
    if ( OSDynamicCast(OSNumber, number) ) _locationID = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);
    
    number = (OSNumber*)copyProperty(kIOHIDVendorIDKey);
    if ( OSDynamicCast(OSNumber, number) ) _vendorID = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);

    number = (OSNumber*)copyProperty(kIOHIDVendorIDSourceKey);
    if ( OSDynamicCast(OSNumber, number) ) _vendorIDSource = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);

    number = (OSNumber*)copyProperty(kIOHIDProductIDKey);
    if ( OSDynamicCast(OSNumber, number) ) _productID = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);

    number = (OSNumber*)copyProperty(kIOHIDVersionNumberKey);
    if ( OSDynamicCast(OSNumber, number) ) _version = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);

    number = (OSNumber*)copyProperty(kIOHIDCountryCodeKey);
    if ( number ) _countryCode = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);

    number = (OSNumber*)_owner->copyProperty(kIOHIDMaxInputReportSizeKey);
    if ( OSDynamicCast(OSNumber, number) ) _maxReportSize[kIOHIDReportTypeInput] = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);

    number = (OSNumber*)_owner->copyProperty(kIOHIDMaxOutputReportSizeKey);
    if ( OSDynamicCast(OSNumber, number) ) _maxReportSize[kIOHIDReportTypeOutput] = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);

    number = (OSNumber*)_owner->copyProperty(kIOHIDMaxFeatureReportSizeKey);
    if ( OSDynamicCast(OSNumber, number) ) _maxReportSize[kIOHIDReportTypeFeature] = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);
    
    number = (OSNumber*)_owner->copyProperty(kIOHIDReportIntervalKey);
    if ( OSDynamicCast(OSNumber, number) ) _reportInterval = number->unsigned32BitValue();
    OSSafeReleaseNULL(number);
    
    registerService(kIOServiceAsynchronous);
    
    return true;
}
Ejemplo n.º 18
0
void FileNVRAM::timeoutOccurred(OSObject *target, IOTimerEventSource* timer)
{
	static int retryCount;

	if (target)
	{
		FileNVRAM* self = OSDynamicCast(FileNVRAM, target);

		if (self)
		{
			uint64_t timeout = 20000; // 20ms
			// Check to see if BSD has been published, if so sync();

			OSDictionary *  dict = 0;
			IOService *     match = 0;
			boolean_t		found = false;

			do
			{
				dict = IOService::resourceMatching("IOBSD");

				if (dict)
				{
					if (IOService::waitForMatchingService(dict, timeout))
					{
						found = true;
					}
				}
			} while (false);

			OSSafeReleaseNULL(dict);
			OSSafeReleaseNULL(match);

			if (found)
			{
				UInt8 mLoggingLevel = self->mLoggingLevel;
				LOG(NOTICE, "BSD found, syncing\n");

				// TODO: Read /Extra/NVRAM/nvram.plist and populate the device tree.
				char* buffer;
				uint64_t len;

				if (self->read_buffer(&buffer, &len, self->mCtx))
				{
					retryCount++;
					LOG(ERROR, "Unable to read in nvram data at %s\n", self->mFilePath->getCStringNoCopy());
					// TODO: Check if / is mounted, and if not, try again until it is.
					if (retryCount < 100)
					{
						timer->setTimeoutMS(100);
					}
					else
					{
						self->mSafeToSync = true;
						self->registerNVRAM();
					}
				}
				else
				{
					self->mSafeToSync = false;

					timer->cancelTimeout();
					self->getWorkLoop()->removeEventSource(timer);
					timer->release();
					self->mTimer = NULL;

					if (len > strlen(NVRAM_FILE_HEADER) + strlen(NVRAM_FILE_FOOTER) + 1)
					{
						char* xml = buffer + strlen(NVRAM_FILE_HEADER);
						size_t xmllen = (size_t)len - strlen(NVRAM_FILE_HEADER) - strlen(NVRAM_FILE_FOOTER);
						xml[xmllen-1] = 0;
						OSString *errmsg = 0;
						OSObject* nvram = OSUnserializeXML(xml, &errmsg);

						if (nvram)
						{
							OSDictionary* data = OSDynamicCast(OSDictionary, nvram);
							//if(data) self->setPropertyTable(data);

							if (data)
							{
								self->copyUnserialzedData(NULL, data);
							}

							nvram->release();
						}
					}

					IOFree(buffer, (size_t)len);


					self->mSafeToSync = true;
					self->registerNVRAM();
					//self->sync();
				}
			}
			else
			{
				timer->setTimeoutMS(50);
			}
		}
		else
		{
			//printf("Self is not of type FileNVRAM.\n");
		}
	}
}
Ejemplo n.º 19
0
/*
 * Common KeyMap initialization
 */
bool IOHIKeyboardMapper::init(	IOHIKeyboard *delegate,
								const UInt8 *map,
								UInt32 mappingLen,
								bool mappingShouldBeFreed )
{
	_mappingShouldBeFreed		= mappingShouldBeFreed;
	_parsedMapping.mapping		= map;
	_parsedMapping.mappingLen	= mappingLen;

	if (!super::init())	 return false;

	_delegate				  = delegate;

	if (!parseKeyMapping(map, mappingLen, &_parsedMapping))	return false;

//	_hidSystem					= NULL;
//	_stateDirty					= false;

	_reserved = IONew(ExpansionData, 1);
    bzero(_reserved, sizeof(ExpansionData));

//	_ejectTimerEventSource		= 0;
//
//	_f12Eject_State			= 0;
//
//	_eject_Delay_MS			= kEjectF12DelayMS;
//
//	_slowKeys_State			= 0;
//
//	_slowKeys_Delay_MS		= 0;
//
//	_slowKeysTimerEventSource	= 0;

	_specialKeyModifierFlags	= 0;

//	_supportsF12Eject		= 0;

//	_cached_KeyBits			= 0;

	_cachedAlphaLockModDefs = 0;

	// If there are right hand modifiers defined, set a property
	if (_delegate && (_parsedMapping.maxMod > 0))
	{

		if ( _delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) )
		{
			_delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanTrue);
			_cachedAlphaLockModDefs = _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK];
		}
		else
		{
			_delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanFalse);
		}

		UInt32 supportedModifiers = 0;
		OSNumber * number = 0;

		number = (OSNumber *)_delegate->copyProperty(kIOHIDKeyboardSupportedModifiersKey);

		if (number) supportedModifiers = number->unsigned32BitValue();
		OSSafeReleaseNULL(number);

		_delegate->setProperty( kIOHIDKeyboardSupportedModifiersKey, supportedModifiers, 32 );

		if ( (supportedModifiers & NX_DEVICERSHIFTKEYMASK) ||
			 (supportedModifiers & NX_DEVICERCTLKEYMASK) ||
			 (supportedModifiers & NX_DEVICERALTKEYMASK) ||
			 (supportedModifiers & NX_DEVICERCMDKEYMASK) )
		{
			_delegate->setProperty("HIDKeyboardRightModifierSupport", kOSBooleanTrue);
		}
	}

	if (_parsedMapping.numDefs && _delegate)
	{
		_delegate->setProperty("HIDKeyboardKeysDefined", kOSBooleanTrue);

	}

	if ( !_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) )
	{
		UInt32 myFlags = _delegate->deviceFlags();

		if ( _delegate->alphaLock() )
		{
			_specialKeyModifierFlags	|= NX_ALPHASHIFTMASK;
			myFlags						|= NX_ALPHASHIFTMASK;

			_delegate->IOHIKeyboard::setDeviceFlags(myFlags);
		}
		else
		{
			_specialKeyModifierFlags	&= ~NX_ALPHASHIFTMASK;
			myFlags						&= ~NX_ALPHASHIFTMASK;

			_delegate->IOHIKeyboard::setDeviceFlags(myFlags);
		}
	}

    return true;
}
Ejemplo n.º 20
0
void
KLDBootstrap::readBuiltinPersonalities(void)
{
    OSObject              * parsedXML             = NULL;  // must release
    OSArray               * builtinExtensions     = NULL;  // do not release
    OSArray               * allPersonalities      = NULL;  // must release
    OSString              * errorString           = NULL;  // must release
    kernel_section_t      * infosect              = NULL;  // do not free
    OSCollectionIterator  * personalitiesIterator = NULL;  // must release
    unsigned int            count, i;
    
    OSKextLog(/* kext */ NULL,
        kOSKextLogStepLevel |
        kOSKextLogLoadFlag,
        "Reading built-in kernel personalities for I/O Kit drivers.");

   /* Look in the __BUILTIN __info segment for an array of Info.plist
    * entries. For each one, extract the personalities dictionary, add
    * it to our array, then push them all (without matching) to
    * the IOCatalogue. This can be used to augment the personalities
    * in gIOKernelConfigTables, especially when linking entire kexts into
    * the mach_kernel image.
    */
    infosect   = getsectbyname("__BUILTIN", "__info");
    if (!infosect) {
        // this isn't fatal
        goto finish;
    }
        
    parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
        &errorString);
    if (parsedXML) {
        builtinExtensions = OSDynamicCast(OSArray, parsedXML);
    }
    if (!builtinExtensions) {
        const char * errorCString = "(unknown error)";
        
        if (errorString && errorString->getCStringNoCopy()) {
            errorCString = errorString->getCStringNoCopy();
        } else if (parsedXML) {
            errorCString = "not an array";
        }
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogLoadFlag,
            "Error unserializing built-in personalities: %s.", errorCString);
        goto finish;
    }
            
    // estimate 3 personalities per Info.plist/kext
    count = builtinExtensions->getCount();
    allPersonalities = OSArray::withCapacity(count * 3);
            
    for (i = 0; i < count; i++) {
        OSDictionary            * infoDict = NULL;      // do not release
        OSString                * moduleName = NULL;    // do not release
        OSDictionary            * personalities;        // do not release
        OSString                * personalityName;      // do not release    
        
        OSSafeReleaseNULL(personalitiesIterator);

        infoDict = OSDynamicCast(OSDictionary,
            builtinExtensions->getObject(i));
        if (!infoDict) {
            continue;
        }
        
        moduleName = OSDynamicCast(OSString,
            infoDict->getObject(kCFBundleIdentifierKey));
        if (!moduleName) {
            continue;
        }
        
        OSKextLog(/* kext */ NULL,
            kOSKextLogStepLevel |
            kOSKextLogLoadFlag,
            "Adding personalities for built-in driver %s:",
            moduleName->getCStringNoCopy());
        
        personalities = OSDynamicCast(OSDictionary,
            infoDict->getObject("IOKitPersonalities"));
        if (!personalities) {
            continue;
        }
        
        personalitiesIterator = OSCollectionIterator::withCollection(personalities);
        if (!personalitiesIterator) {
            continue;  // xxx - well really, what can we do? should we panic?
        }
        
        while ((personalityName = OSDynamicCast(OSString,
            personalitiesIterator->getNextObject()))) {
            
            OSDictionary * personality = OSDynamicCast(OSDictionary,
                personalities->getObject(personalityName));

            OSKextLog(/* kext */ NULL,
                kOSKextLogDetailLevel |
                kOSKextLogLoadFlag,
                "Adding built-in driver personality %s.",
                personalityName->getCStringNoCopy());
        
			if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
				personality->setObject(kCFBundleIdentifierKey, moduleName);
			}
            allPersonalities->setObject(personality);
        }
    }
    
    gIOCatalogue->addDrivers(allPersonalities, false);

finish:
    OSSafeReleaseNULL(parsedXML);
    OSSafeReleaseNULL(allPersonalities);
    OSSafeReleaseNULL(errorString);
    OSSafeReleaseNULL(personalitiesIterator);
    return;
}
bool IOHIDLibUserClient::start(IOService *provider)
{
    OSDictionary *matching = NULL;
    if (!super::start(provider))
        return false;

    fNub = OSDynamicCast(IOHIDDevice, provider);
    if (!fNub)
        return false;

    fWL = getWorkLoop();
    if (!fWL)
        return false;

    fWL->retain();

    OSNumber *primaryUsage = (OSNumber*)fNub->copyProperty(kIOHIDPrimaryUsageKey);
    OSNumber *primaryUsagePage = (OSNumber*)fNub->copyProperty(kIOHIDPrimaryUsagePageKey);

    if ((OSDynamicCast(OSNumber, primaryUsagePage) && (primaryUsagePage->unsigned32BitValue() == kHIDPage_GenericDesktop)) &&
        (OSDynamicCast(OSNumber, primaryUsage) && ((primaryUsage->unsigned32BitValue() == kHIDUsage_GD_Keyboard) || (primaryUsage->unsigned32BitValue() == kHIDUsage_GD_Keypad))))
    {
        fNubIsKeyboard = true;
    }
    
    OSSafeReleaseNULL(primaryUsage);
    OSSafeReleaseNULL(primaryUsagePage);
            
    IOCommandGate * cmdGate = IOCommandGate::commandGate(this);
    if (!cmdGate)
        goto ABORT_START;
    
    fWL->addEventSource(cmdGate);
    
    fGate = cmdGate;

    fResourceES = IOInterruptEventSource::interruptEventSource
        (this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &IOHIDLibUserClient::resourceNotificationGated));
        
    if ( !fResourceES )
        goto ABORT_START;

    fWL->addEventSource(fResourceES);

    // Get notified everytime Root properties change
    matching = serviceMatching("IOResources");
    fResourceNotification = addMatchingNotification(
        gIOPublishNotification,
        matching,
        OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &IOHIDLibUserClient::resourceNotification),
        this);
    matching->release();
    matching = NULL;

    if ( !fResourceNotification )
        goto ABORT_START;
        
    return true;

ABORT_START:
    if (fResourceES) {
        fWL->removeEventSource(fResourceES);
        fResourceES->release();
        fResourceES = 0;
    }
    if (fGate) {
        fWL->removeEventSource(fGate);
        fGate->release();
        fGate = 0;
    }
    fWL->release();
    fWL = 0;

    return false;
}