Exemple #1
0
bool IOCatalogue::removePersonalities(OSArray * personalitiesToRemove)
{
    bool                   result           = true;
    OSArray              * arrayCopy        = NULL;  // do not release
    OSCollectionIterator * iterator         = NULL;  // must release
    OSDictionary         * personality      = NULL;  // do not release
    OSDictionary         * checkPersonality = NULL;  // do not release
    unsigned int           count, i;

    // remove configs from catalog.

    arrayCopy = OSArray::withArray(array);
    if (!arrayCopy) {
        result = false;
        goto finish;
    }

    iterator = OSCollectionIterator::withCollection(arrayCopy);
    arrayCopy->release();
    if (!iterator) {
        result = false;
        goto finish;
    }

    array->flushCollection();

    count = personalitiesToRemove->getCount();

    /* Go through the old catalog's list of personalities and add back any that
     * are *not* found in 'personalitiesToRemove'.
     */
    while ((personality = (OSDictionary *)iterator->getNextObject())) {
        bool found = false;

        for (i = 0; i < count; i++) {
            checkPersonality = OSDynamicCast(OSDictionary,
                                             personalitiesToRemove->getObject(i));

            /* Do isEqualTo() with the single-arg version to make an exact
             * comparison (unlike _removeDrivers() above).
             */
            if (personality->isEqualTo(checkPersonality)) {
                found = true;
                break;
            }
        }

        if (!found) {
            array->setObject(personality);
        }
    }

finish:

    OSSafeRelease(iterator);
    return result;
}
// <rdar://8202424>
IOReturn IOAudioSelectorControl::addAvailableSelection(SInt32 selectionValue, OSString *selectionDescription, const char* tagName, OSObject* tag)
{
	OSArray *newSelections;
	OSArray *oldAvailableSelections;
    IOReturn result = kIOReturnSuccess;
    
	oldAvailableSelections = availableSelections;
	newSelections = OSArray::withArray(availableSelections);
	if (!newSelections)
		return kIOReturnNoMemory;

    if (selectionDescription == NULL) {
        result = kIOReturnBadArgument;
    } else {
        if (valueExists(selectionValue)) {
            result = kIOReturnError;
        } else {
            OSDictionary *newSelection;
            
            newSelection = OSDictionary::withCapacity(2);
            
            if (newSelection) {
                OSNumber *number;
				
                number = OSNumber::withNumber(selectionValue, sizeof(SInt32)*8);
                
                if (number) {
                    newSelection->setObject(kIOAudioSelectorControlSelectionValueKey, number);
                    newSelection->setObject(kIOAudioSelectorControlSelectionDescriptionKey, selectionDescription);
                    newSelections->setObject(newSelection);
					
                    number->release();
                } else {
                    result = kIOReturnError;
                }
				
				if ( tagName && tag ) {
					newSelection->setObject(tagName, tag);
				}
				
				availableSelections = newSelections;
				setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections);
				oldAvailableSelections->release();
                
                newSelection->release();
            } else {
                result = kIOReturnError;
            }
        }
    }
    
	if (kIOReturnSuccess == result) {
		sendChangeNotification(kIOAudioControlRangeChangeNotification);
	}
	
    return result;
}
bool CompareDeviceUsage( IOService * owner, OSDictionary * matching, SInt32 * score, SInt32 increment)
{
    // We return success if we match the key in the dictionary with the key in
    // the property table, or if the prop isn't present
    //
    OSObject * 		usage;
    OSObject *		usagePage;
    OSArray *		functions;
    OSDictionary * 	pair;
    bool		matches = true;
    int			count;
    
    usage = matching->getObject( kIOHIDDeviceUsageKey );
    usagePage = matching->getObject( kIOHIDDeviceUsagePageKey );
    functions = OSDynamicCast(OSArray, owner->copyProperty( kIOHIDDeviceUsagePairsKey ));
    
    if ( functions )
    {
        if ( usagePage || usage )
        {
            count = functions->getCount();
            
            for (int i=0; i<count; i++)
            {
                if ( !(pair = (OSDictionary *)functions->getObject(i)) )
                    continue;
            
                if ( !usagePage || 
                    !(matches = usagePage->isEqualTo(pair->getObject(kIOHIDDeviceUsagePageKey))) )
                    continue;

                if ( score && !usage ) 
                {
                    *score += increment / 2;
                    break;
                }
                    
                if ( !usage || 
                    !(matches = usage->isEqualTo(pair->getObject(kIOHIDDeviceUsageKey))) )            
                    continue;
        
                if ( score ) 
                    *score += increment;
                
                break;
            }
        }
        
        functions->release();
    } else {
		matches = false;
	}
    
    return matches;
}
Exemple #4
0
OSArray *OSArray::withCapacity(unsigned int capacity)
{
    OSArray *me = new OSArray;

    if (me && !me->initWithCapacity(capacity)) {
        me->release();
        return 0;
    }

    return me;
}
Exemple #5
0
OSArray *OSArray::withArray(const OSArray *array,
                            unsigned int capacity)
{
    OSArray *me = new OSArray;

    if (me && !me->initWithArray(array, capacity)) {
        me->release();
        return 0;
    }

    return me;
}
Exemple #6
0
OSCollection * OSArray::copyCollection(OSDictionary *cycleDict)
{
    bool allocDict = !cycleDict;
    OSCollection *ret = 0;
    OSArray *newArray = 0;

    if (allocDict) {
	cycleDict = OSDictionary::withCapacity(16);
	if (!cycleDict)
	    return 0;
    }

    do {
	// Check for a cycle
	ret = super::copyCollection(cycleDict);
	if (ret)
	    continue;
	
	newArray = OSArray::withArray(this);
	if (!newArray)
	    continue;

	// Insert object into cycle Dictionary
	cycleDict->setObject((const OSSymbol *) this, newArray);

	for (unsigned int i = 0; i < count; i++) {
	    OSCollection *coll =
		OSDynamicCast(OSCollection, EXT_CAST(newArray->array[i]));

	    if (coll) {
		OSCollection *newColl = coll->copyCollection(cycleDict);
		if (!newColl)
		    goto abortCopy;

		newArray->replaceObject(i, newColl);
		newColl->release();
	    };
	};

	ret = newArray;
	newArray = 0;

    } while (false);

abortCopy:
    if (newArray)
	newArray->release();

    if (allocDict)
	cycleDict->release();

    return ret;
}
Exemple #7
0
OSArray *OSArray::withObjects(const OSObject *objects[],
                              unsigned int count,
                              unsigned int capacity)
{
    OSArray *me = new OSArray;

    if (me && !me->initWithObjects(objects, count, capacity)) {
        me->release();
        return 0;
    }

    return me;
}
Exemple #8
0
void IOCatalogue::addPersonality(OSDictionary * dict)
{
    const OSSymbol * sym;
    OSArray * arr;

    sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
    if (!sym) return;
    arr = (OSArray *) personalities->getObject(sym);
    if (arr) arr->setObject(dict);
    else
    {
        arr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
        personalities->setObject(sym, arr);
        arr->release();
    }
}
IOReturn IOAudioSelectorControl::replaceAvailableSelection(SInt32 selectionValue, OSString *selectionDescription)
{
    OSCollectionIterator *iterator;
	OSArray *newSelections;
	OSArray *oldAvailableSelections;
    IOReturn result = kIOReturnSuccess;
    
    assert(availableSelections);

	oldAvailableSelections = availableSelections;
	newSelections = OSArray::withArray(availableSelections);
	if (!newSelections)
		return kIOReturnNoMemory;

    iterator = OSCollectionIterator::withCollection(newSelections);
    if (iterator) {
        OSDictionary *	selection;
		UInt32			index;

		index = 0;
        while ( (selection = (OSDictionary *)iterator->getNextObject() )) {
            OSNumber *	sValue;

            sValue = (OSNumber *)selection->getObject(kIOAudioSelectorControlSelectionValueKey);

            if (sValue && ((SInt32)sValue->unsigned32BitValue() == selectionValue)) {
				// Replace the selected dictionary in the array
				newSelections->replaceObject(index, selectionDescription);
				result = kIOReturnSuccess;
                break;
            }
			index++;
        }
		availableSelections = newSelections;
        setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections);
		oldAvailableSelections->release();

        iterator->release();
    }

	if (kIOReturnSuccess == result) {
		sendChangeNotification(kIOAudioControlRangeChangeNotification);
	}

    return result;
}
Exemple #10
0
OSArray * OSDictionary::copyKeys(void)
{
    OSArray * array;

	array = OSArray::withCapacity(count);
	if (!array) return (0);

	for (unsigned int i = 0; i < count; i++)
	{
	    if (!array->setObject(i, dictionary[i].key))
	    {
            array->release();
            array = 0;
            break;
        }
	}
    return (array);
}
Exemple #11
0
static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
{
    OSCollectionIterator * tables;
    OSDictionary         * dict;
    OSArray              * arrayCopy;
    IOReturn               ret = kIOReturnSuccess;

    // remove configs from catalog.

    arrayCopy = OSArray::withCapacity(100);
    if ( !arrayCopy )
        return kIOReturnNoMemory;

    tables = OSCollectionIterator::withCollection(arrayCopy);
    arrayCopy->release();
    if ( !tables )
        return kIOReturnNoMemory;

    arrayCopy->merge(array);
    array->flushCollection();
    tables->reset();
    while ( (dict = (OSDictionary *)tables->getNextObject()) ) {

        /* Remove from the catalogue's array any personalities
         * that match the matching dictionary.
         * This comparison must be done with only the keys in the
         * "matching" dict to enable general matching.
         */
        if ( dict->isEqualTo(matching, matching) )
            continue;

        array->setObject(dict);
    }

    tables->release();

    return ret;
}
Exemple #12
0
/*********************************************************************
* This is the function that IOCatalogue calls in order to load a kmod.
* It first checks whether the kmod is already loaded. If the kmod
* isn't loaded, this function builds a dependency list and calls
* load_kmod() repeatedly to guarantee that each dependency is in fact
* loaded.
*********************************************************************/
__private_extern__
kern_return_t load_kernel_extension(char * kmod_name) {
    kern_return_t result = KERN_SUCCESS;
    kmod_info_t * kmod_info = 0;  // must free
    OSArray * dependencyList = NULL;     // must release
    OSArray * curDependencyList = NULL;  // must release

   /* See if the kmod is already loaded.
    */
    kmod_info = kmod_lookupbyname_locked(kmod_name);
    if (kmod_info) {  // NOT checked
        result = KERN_SUCCESS;
        goto finish;
    }

   /* It isn't loaded; build a dependency list and
    * load those.
    */
    unsigned int count;
    unsigned int i;
    dependencyList = getDependencyListForKmod(kmod_name);
    if (!dependencyList) {
        IOLog("load_kernel_extension(): "
            "Can't get dependencies for kernel extension \"%s\".\n",
            kmod_name);
        LOG_DELAY();
        result = KERN_FAILURE;
        goto finish;
    }

    count = dependencyList->getCount();
    for (i = 0; i < count; i++) {
        kern_return_t load_result;
        OSString * curKmodName;  // don't release
        const char * cur_kmod_name;

        curKmodName = OSDynamicCast(OSString,
            dependencyList->getObject(i));
        cur_kmod_name = curKmodName->getCStringNoCopy();
        curDependencyList = getDependencyListForKmod(cur_kmod_name);
        if (!curDependencyList) {
            IOLog("load_kernel_extension(): "
                "Can't get dependencies for kernel extension \"%s\".\n",
                cur_kmod_name);
            LOG_DELAY();
            result = KERN_FAILURE;
            goto finish;
        } else {
            load_result = load_kmod(curDependencyList);
            if (load_result != KERN_SUCCESS) {
                IOLog("load_kernel_extension(): "
                    "load_kmod() failed for kmod \"%s\".\n",
                    cur_kmod_name);
                LOG_DELAY();
                result = load_result;
                goto finish;
            }
            curDependencyList->release();
            curDependencyList = NULL;
        }
    }


finish:

    if (kmod_info) {
        kfree((unsigned int)kmod_info, sizeof(kmod_info_t));
    }

    if (dependencyList) {
        dependencyList->release();
        dependencyList = NULL;
    }
    if (curDependencyList) {
        curDependencyList->release();
        curDependencyList = NULL;
    }

    return result;
}
Exemple #13
0
void testSet()
{
    bool res = true;
    void *spaceCheck, *spaceCheck2 , *spaceCheck3;
    int i, count, count2;
    OSObject *cache[numStrCache], *str, *sym;
    OSSet *set1, *set2;
    OSArray *array;

    // Do first test without memory leak tests to initialise the metaclass
    set1 = OSSet::withCapacity(1);
    TEST_ASSERT('S', "0a", set1);
    if (set1)
        set1->release();

    // Grow the symbol pool to maximum
    for (i = 0; i < numStrCache; i++)
        cache[i] = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
    for (i = 0; i < numStrCache; i++)
        cache[i]->release();

    // Create and destroy an set
    spaceCheck = checkPointSpace();
    set1 = OSSet::withCapacity(1);
    TEST_ASSERT('S', "1a", set1);
    if (set1) {
        TEST_ASSERT('S', "1b", !set1->getCount());
        TEST_ASSERT('S', "1c", 1 == set1->getCapacity());
        TEST_ASSERT('S', "1d", 1 == set1->getCapacityIncrement());
        TEST_ASSERT('S', "1e", 4 == set1->setCapacityIncrement(4));
        TEST_ASSERT('S', "1f", 4 == set1->getCapacityIncrement());
        TEST_ASSERT('S', "1g", 8 == set1->ensureCapacity(5));

        spaceCheck2 = checkPointSpace();
        cache[0] = IOString::withCStringNoCopy(strCache[0]);

        spaceCheck3 = checkPointSpace();
        TEST_ASSERT('S', "1h", set1->setObject(cache[0]));
        TEST_ASSERT('S', "1i", set1->containsObject(cache[0]));
        TEST_ASSERT('S', "1j", cache[0] == set1->getAnyObject());
        cache[0]->release();
        res = res && checkSpace("(S)1k", spaceCheck3, 0);

        TEST_ASSERT('S', "1l", 1 == set1->getCount());
        set1->flushCollection();
        TEST_ASSERT('S', "1m", !set1->getCount());
        res = res && checkSpace("(S)1n", spaceCheck2, 0);

        set1->release();
    }
    res = res && checkSpace("(S)1", spaceCheck, 0);

    // Check the creation of a sizable OSSet from an set of IOObjects
    // Also check member test of set.
    spaceCheck = checkPointSpace();
    for (i = 0; i < numStrCache; i++)
        cache[i] = OSString::withCStringNoCopy(strCache[i]);
    set1 = OSSet::withObjects(cache, numStrCache, numStrCache);
    TEST_ASSERT('S', "2a", set1);
    for (i = 0; i < numStrCache; i++)
        cache[i]->release();
    if (set1) {
        TEST_ASSERT('S', "2b", numStrCache == (int) set1->getCount());
        TEST_ASSERT('S', "2c", numStrCache == (int) set1->getCapacity());
        TEST_ASSERT('S', "2d",
                    numStrCache == (int) set1->getCapacityIncrement());

        count = 0;
        for (i = set1->getCount(); --i >= 0; )
            count += set1->member(cache[i]);

        TEST_ASSERT('S', "2e", numStrCache == count);
        set1->release();
    }
    res = res && checkSpace("(S)2", spaceCheck, 0);

    // Test set creation from another set by both the setObject method
    // and the withArray factory.  And test __takeObject code first
    // with tail removal then with head removal
    spaceCheck = checkPointSpace();
    for (i = 0; i < numStrCache; i++)
        cache[i] = OSString::withCStringNoCopy(strCache[i]);
    set1 = OSSet::withObjects(cache, numStrCache, numStrCache);
    TEST_ASSERT('S', "3a", set1);
    for (i = 0; i < numStrCache; i++)
        cache[i]->release();
    set2 = 0;
    if (set1) {
        set2 = OSSet::withCapacity(set1->getCount());
        TEST_ASSERT('S', "3b", set2);
        TEST_ASSERT('S', "3c", !set2->getCount());
        TEST_ASSERT('S', "3d", set2->setObject(set1));
        TEST_ASSERT('S', "3e", set1->getCount() == set2->getCount());
    }
    if (set2) {
        TEST_ASSERT('S', "3f", numStrCache == (int) set2->getCount());
        count = count2 = 0;
        while ( (str = set2->getAnyObject()) ) {
            count  += set2->__takeObject(str);
            count2 += set1->member(str);
            str->release();
        }
        TEST_ASSERT('S', "3g", !set2->getCount());
        TEST_ASSERT('S', "3h", numStrCache == count);
        TEST_ASSERT('S', "3i", numStrCache == count2);

        spaceCheck2 = checkPointSpace();
        set2->flushCollection();
        res = res && checkSpace("(S)3j", spaceCheck2, 0);

        set2->release();
        set2 = 0;
    }
    if (set1) {
        set2 = OSSet::withSet(set1, numStrCache - 1);
        TEST_ASSERT('S', "3k", !set2);
        set2 = OSSet::withSet(set1, set1->getCount());
        TEST_ASSERT('S', "3l", set2);
        set1->release();
    }
    if (set2) {
        TEST_ASSERT('S', "3m", numStrCache == (int) set2->getCount());
        i = count = count2 = 0;
        while ( (str = set2->getAnyObject()) ) {
            count  += set2->__takeObject(str);
            count2 += (cache[i++] == str);
            str->release();
        }
        TEST_ASSERT('S', "3n", !set2->getCount());
        TEST_ASSERT('S', "3o", numStrCache == count);
        TEST_ASSERT('S', "3p", numStrCache == count2);

        set2->release();
        set2 = 0;
    }
    res = res && checkSpace("(S)3", spaceCheck, 0);

    // Test duplicate removal
    spaceCheck = checkPointSpace();
    set2 = 0;
    set1 = OSSet::withCapacity(numStrCache);
    TEST_ASSERT('S', "4a", set1);
    if (set1) {
        count = 0;
        for (i = 0; i < numStrCache; i++) {
            sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
            count += set1->setObject(sym);
            sym->release();
        }
        TEST_ASSERT('S', "4b", numStrCache != (int) set1->getCount());
        TEST_ASSERT('S', "4c", count == (int) set1->getCount());

        count = count2 = 0;
        for (i = 0; i < numStrCache; i++) {
            sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
            count += set1->member(sym);
            count2 += sym->getRetainCount();
            sym->release();
        }
        TEST_ASSERT('S', "4d", count  == numStrCache);
        TEST_ASSERT('S', "4e", count2 == numStrCache * 2);

        set2 = OSSet::withSet(set1, 2 * set1->getCount());
    }
    TEST_ASSERT('S', "4f", set2);
    if (set2) {
        set2->setObject(set1);
        TEST_ASSERT('S', "4g", set1->getCount() == set2->getCount());
        set1->release();
        set2->release();
    }
    res = res && checkSpace("(S)4", spaceCheck, 0);

    // Test array duplicate removal
    spaceCheck = checkPointSpace();
    array = OSArray::withCapacity(numStrCache);
    for (i = 0; i < numStrCache; i++) {
        sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
        count += array->setObject(sym);
        sym->release();
    }
    set1 = OSSet::withArray(array, numStrCache);
    TEST_ASSERT('S', "5a", set1);
    if (set1) {
        TEST_ASSERT('S', "5b", array->getCount() != set1->getCount());
        array->release();

        count = count2 = set1->getCount();
        while ( (sym = set1->getAnyObject()) ) {
            count  -= set1->__takeObject(sym);
            count2 -= sym->getRetainCount();
            sym->release();
        }
        TEST_ASSERT('S', "5c", !count);
        TEST_ASSERT('S', "5d", !count2);
        set1->release();
    }
    res = res && checkSpace("(S)5", spaceCheck, 0);

    if (res)
        verPrintf(("testSet: All OSSet Tests passed\n"));
    else
        logPrintf(("testSet: Some OSSet Tests failed\n"));
}
bool ACPIBacklightPanel::findDevices(IOService * provider)
{
    DbgLog("%s::%s()\n", this->getName(),__FUNCTION__);
    
    if (!gpuDevice || !backLightDevice)
    {
        IOACPIPlatformDevice * dev = OSDynamicCast(IOACPIPlatformDevice, provider);
        if (hasBacklightMethods(dev))
        {
            DbgLog("%s: PNLF has backlight Methods\n", this->getName());
            backLightDevice = dev;
            gpuDevice = dev;
            gpuDevice->retain();
            backLightDevice->retain();
        }
        else
        {            
            gpuDevice = getGPU();
            
            if (NULL == gpuDevice)
                return false;
            
            gpuDevice->retain();
            
            if (hasBacklightMethods(gpuDevice))
            {
                backLightDevice = gpuDevice;
            }
            else
            {
                backLightDevice = getChildWithBacklightMethods(gpuDevice);
            }
            
            if (backLightDevice == NULL)
                return false;
            
            backLightDevice->retain();
        }

#ifdef DEBUG
        if (gpuDevice != backLightDevice)
        {
            OSArray * devicePaths = OSArray::withCapacity(2);
            OSString* path = getACPIPath(gpuDevice);
            IOLog("ACPIBacklight: ACPI Method _DOS found. Device path: %s\n", path->getCStringNoCopy());
            devicePaths->setObject(path);
            path->release();
            path = getACPIPath(backLightDevice);
            IOLog("ACPIBacklight: ACPI Methods _BCL _BCM _BQC found. Device path: %s\n", path->getCStringNoCopy());
            devicePaths->setObject(path);
            path->release();
            setProperty("ACPI Devices Paths", devicePaths);
            devicePaths->release();
        }
        else
        {
            OSString* path = getACPIPath(backLightDevice);
            IOLog("ACPIBacklight: ACPI Methods _DOS _BCL _BCM _BQC found. Device path: %s\n", path->getCStringNoCopy());
            setProperty("ACPI Device Path", path);
            path->release();
        }
#endif
    }
    return true;
}
Exemple #15
0
bool IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching)
{
    bool                   result              = false;
    OSArray              * newPersonalities    = NULL;  // do not release
    OSCollectionIterator * newPIterator        = NULL;  // must release
    OSOrderedSet         * matchSet            = NULL;  // must release
    OSArray              * oldPersonalities    = NULL;  // must release
    OSArray              * kernelPersonalities = NULL;  // must release
    OSString             * errorString         = NULL;  // must release
    OSObject             * object              = NULL;  // do not release
    OSDictionary         * thisNewPersonality  = NULL;  // do not release
    signed int             count, i;

    extern const char    * gIOKernelConfigTables;

    if (drivers) {
        newPersonalities = OSDynamicCast(OSArray, drivers);
        if (!newPersonalities) {
            goto finish;
        }

        newPIterator = OSCollectionIterator::withCollection(newPersonalities);
        if (!newPIterator) {
            goto finish;
        }
        
        matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering,
            (void *)gIOProbeScoreKey);
        if (!matchSet) {
            goto finish;
        }
    }

   /* Read personalities for the built-in kernel driver classes.
    * We don't have many any more.
    */
    kernelPersonalities = OSDynamicCast(OSArray,
        OSUnserialize(gIOKernelConfigTables, &errorString));
    if (!kernelPersonalities && errorString) {
        IOLog("KernelConfigTables syntax error: %s\n",
            errorString->getCStringNoCopy());
        goto finish;
    }
    
   /* Now copy the current array of personalities so we can reuse them
    * if the new list contains any duplicates. This saves on memory
    * consumption.
    */
    oldPersonalities = OSDynamicCast(OSArray, array->copyCollection());
    if (!oldPersonalities) {
        goto finish;
    }

    result = true;

    IOLog("Resetting IOCatalogue.\n");
    
   /* No goto finish from here to unlock.
    */
    IOLockLock(lock);
    
    array->flushCollection();

   /* Add back the kernel personalities and remove them from the old
    * array so we don't try to match on them again. Go forward through
    * the arrays as this causes the least iteration since kernel personalities
    * should always be first.
    */
    count = kernelPersonalities->getCount();
    for (i = 0; i < count; i++) {
    
       /* Static cast here, as the data is coming from within the kernel image.
        */
        OSDictionary * thisNewPersonality = (OSDictionary *)
            kernelPersonalities->getObject(i);
        array->setObject(thisNewPersonality);

        signed int oldPCount = oldPersonalities->getCount();
        for (signed int oldPIndex = 0; oldPIndex < oldPCount; oldPIndex++) {
            if (thisNewPersonality->isEqualTo(oldPersonalities->getObject(oldPIndex))) {
                oldPersonalities->removeObject(oldPIndex);
                break;
            }
        }
    }

   /* Now add the new set of personalities passed in, using existing
    * copies if we had them in kernel memory already.
    */
    if (newPIterator) {
        OSDictionary * thisOldPersonality = NULL;  // do not release
        
        while ( (object = newPIterator->getNextObject()) ) {

            thisNewPersonality = OSDynamicCast(OSDictionary, object);
            if (!thisNewPersonality) {
                IOLog("IOCatalogue::resetAndAddDrivers() encountered non-dictionary; bailing.\n");
            result = false;
            break;
            }

           /* Convert common OSString property values to OSSymbols.
            */
            OSKext::uniquePersonalityProperties(thisNewPersonality);
            
           /* Add driver personality to catalogue, but if we had a copy already
            * use that instead so we don't have multiple copies from OSKext instances.
            */
            count = oldPersonalities->getCount();
            thisOldPersonality = NULL;
            while (count--) {
                
                thisOldPersonality = (OSDictionary *)oldPersonalities->getObject(count);
                
               /* Unlike in other functions, this comparison must be exact!
                * The catalogue must be able to contain personalities that
                * are proper supersets of others.
                * Do not compare just the properties present in one driver
                * pesonality or the other.
                */
                if (thisNewPersonality->isEqualTo(thisOldPersonality)) {
                    break;
                }
            }

           /* If we found a dup, add the *original* back to the catalogue,
            * remove it from our bookkeeping list, and continue.
            * Don't worry about matching on personalities we already had.
            */
            if (count >= 0) {
                array->setObject(thisOldPersonality);
                oldPersonalities->removeObject(count);
                continue;
            }

           /* Otherwise add the new personality and mark it for matching.
            */
            array->setObject(thisNewPersonality);
            AddNewImports(matchSet, thisNewPersonality);                
        }

       /*****
        * Now, go through remaining old personalities, which have effectively
        * been removed, and add them to the match set as necessary.
        */
        count = oldPersonalities->getCount();
        while (count--) {
        
           /* Static cast here is ok as these dictionaries were already in the catalogue.
            */
            thisOldPersonality = (OSDictionary *)oldPersonalities->getObject(count);
            AddNewImports(matchSet, thisOldPersonality);
        }

       /* Finally, start device matching on all new & removed personalities.
        */
        if (result && doNubMatching && (matchSet->getCount() > 0)) {
            IOService::catalogNewDrivers(matchSet);
            generation++;
        }
    }

    IOLockUnlock(lock);

finish:
    if (newPIterator) newPIterator->release();
    if (matchSet) matchSet->release();
    if (oldPersonalities) oldPersonalities->release();
    if (kernelPersonalities) kernelPersonalities->release();
    if (errorString) errorString->release();

    return result;
}
// Class start
bool
VoodooPState::start(IOService * provider)
{
	if (!IOService::start(provider)) return false;

	// Printout banner
	InfoLog("%s %s (%s) %s %s [%s]",
			KextProductName,
			KextVersion,
			KextConfig,
			KextBuildDate,
			KextBuildTime,
			KextOSX);
	InfoLog("based on VoodooPower 1.2.3.");
	
	
	
	// Setup workloop and timer
	IOWorkLoop* WorkLoop = getWorkLoop();
	if (!WorkLoop) return false;
	TimerEventSource = 
	IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action,
																	this,
																	&VoodooPState::LoopTimerEvent));
	if (!TimerEventSource) return false;
	
	if (kIOReturnSuccess != WorkLoop->addEventSource(TimerEventSource)) {
		return false;
	}
	
	// Get a SimpleLock
	SimpleLock = IOSimpleLockAlloc();
	if (!SimpleLock) return false;
	
	// Publish the static characteristics
	OSDictionary * dictionary = OSDictionary::withCapacity(13);
	if (!dictionary) return false;
	OSArray * array = OSArray::withCapacity(PStateCount);
	if (!array) return false;
	setDictionaryNumber(keyCpuCoreTech, CpuCoreTech, dictionary);
	setDictionaryNumber(keyFrontSideBus, CpuFSB, dictionary);
	for (int i = 0; i < PStateCount; i++) {
		OSDictionary * pdictionary = OSDictionary::withCapacity(3);
		if (!pdictionary) return false;
		setDictionaryNumber(keyCurrentFrequency, PState[i].frequency, pdictionary);
		setDictionaryNumber(keyCurrentVoltage, PState[i].voltage, pdictionary);
		setDictionaryNumber(keyFid, PState[i].fid, pdictionary);
		setDictionaryNumber(keyDid, PState[i].did, pdictionary);
		setDictionaryNumber(keyVid, PState[i].vid, pdictionary);
		array->setObject(i, pdictionary);
		pdictionary->release();
	}
	setDictionaryArray(keyPStates, array, dictionary);
	setDictionaryString(keyProductName, KextProductName, dictionary);
	setDictionaryString(keyProductVersion, KextVersion, dictionary);
	setDictionaryString(keyBuildConfig, KextConfig, dictionary);
	setDictionaryString(keyBuildDate, KextBuildDate, dictionary);
	setDictionaryString(keyBuildTime, KextBuildTime, dictionary);
	setDictionaryNumber(keyTimerInterval, TimerInterval, dictionary);
	setProperty(keyCharacteristics, dictionary);

	array->release();
	dictionary->release();

	// set initial pstate
	Request = ColdStart ? (PStateCount-1) : 0;	// hot/cold start

	gPEClockFrequencyInfo.cpu_frequency_max_hz = VoodooFrequencyProc(this,&PState[0]) * Mega;
	gPEClockFrequencyInfo.cpu_frequency_min_hz = VoodooFrequencyProc(this,&PState[PStateCount-1]) * Mega;

	LoopTimerEvent();
	
	// Finalize and kick off the loop
	this->registerService(0);
	Ready = true;

	return true;
}
Exemple #17
0
/*********************************************************************
* Remove drivers from the catalog which match the
* properties in the matching dictionary.
*********************************************************************/
bool
IOCatalogue::removeDrivers(
    OSDictionary * matching,
    bool doNubMatching)
{
    OSCollectionIterator * tables;
    OSDictionary         * dict;
    OSOrderedSet         * set;
    OSArray              * arrayCopy;

    if ( !matching )
        return false;

    set = OSOrderedSet::withCapacity(10,
                                     IOServiceOrdering,
                                     (void *)gIOProbeScoreKey);
    if ( !set )
        return false;

    arrayCopy = OSArray::withCapacity(100);
    if ( !arrayCopy ) {
        set->release();
        return false;
    }

    tables = OSCollectionIterator::withCollection(arrayCopy);
    arrayCopy->release();
    if ( !tables ) {
        set->release();
        return false;
    }

    UniqueProperties( matching );

    IOLockLock(lock);
    kernelTables->reset();
    arrayCopy->merge(array);
    array->flushCollection();
    tables->reset();
    while ( (dict = (OSDictionary *)tables->getNextObject()) ) {

        /* This comparison must be done with only the keys in the
         * "matching" dict to enable general searches.
         */
        if ( dict->isEqualTo(matching, matching) ) {
            AddNewImports( set, dict );
            continue;
        }

        array->setObject(dict);
    }
    // Start device matching.
    if ( doNubMatching && (set->getCount() > 0) ) {
        IOService::catalogNewDrivers(set);
        generation++;
    }
    IOLockUnlock(lock);

    set->release();
    tables->release();

    return true;
}
IORegistryEntry *
IODeviceTreeAlloc( void * dtTop )
{
    IORegistryEntry *		parent;
    IORegistryEntry *		child;
    IORegistryIterator *	regIter;
    DTEntryIterator		iter;
    DTEntry			dtChild;
    DTEntry			mapEntry;
    OSArray *			stack;
    OSData *			prop;
    OSDictionary *		allInts;
    vm_offset_t *		dtMap;
    unsigned int		propSize;
    bool			intMap;
    bool			freeDT;

    gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane );

    gIODTNameKey 		= OSSymbol::withCStringNoCopy( "name" );
    gIODTUnitKey 		= OSSymbol::withCStringNoCopy( "AAPL,unit-string" );
    gIODTCompatibleKey 	= OSSymbol::withCStringNoCopy( "compatible" );
    gIODTTypeKey 		= OSSymbol::withCStringNoCopy( "device_type" );
    gIODTModelKey 		= OSSymbol::withCStringNoCopy( "model" );
    gIODTSizeCellKey 	= OSSymbol::withCStringNoCopy( "#size-cells" );
    gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" );
    gIODTRangeKey 		= OSSymbol::withCStringNoCopy( "ranges" );
    gIODTPersistKey		= OSSymbol::withCStringNoCopy( "IODTPersist" );

    assert(    gIODTPlane && gIODTCompatibleKey
            && gIODTTypeKey && gIODTModelKey
            && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey
            && gIODTPersistKey );

    gIODTDefaultInterruptController
		= OSSymbol::withCStringNoCopy("IOPrimaryInterruptController");
    gIODTNWInterruptMappingKey
		= OSSymbol::withCStringNoCopy("IONWInterrupts");

    gIODTAAPLInterruptsKey
		= OSSymbol::withCStringNoCopy("AAPL,interrupts");
    gIODTPHandleKey
		= OSSymbol::withCStringNoCopy("AAPL,phandle");

    gIODTInterruptParentKey
		= OSSymbol::withCStringNoCopy("interrupt-parent");

    gIODTPHandles	= OSArray::withCapacity( 1 );
    gIODTPHandleMap	= OSArray::withCapacity( 1 );

    gIODTInterruptCellKey
		= OSSymbol::withCStringNoCopy("#interrupt-cells");

    assert(    gIODTDefaultInterruptController && gIODTNWInterruptMappingKey 
	    && gIODTAAPLInterruptsKey
	    && gIODTPHandleKey && gIODTInterruptParentKey
	    && gIODTPHandles && gIODTPHandleMap
            && gIODTInterruptCellKey
	 );

    freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry ))
	  && (kSuccess == DTGetProperty( mapEntry,
                "DeviceTree", (void **) &dtMap, &propSize ))
	  && ((2 * sizeof(uint32_t)) == propSize);

    parent = MakeReferenceTable( (DTEntry)dtTop, freeDT );

    stack = OSArray::withObjects( (const OSObject **) &parent, 1, 10 );
    DTCreateEntryIterator( (DTEntry)dtTop, &iter );

    do {
        parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1);
        //parent->release();
        stack->removeObject( stack->getCount() - 1);

        while( kSuccess == DTIterateEntries( iter, &dtChild) ) {

            child = MakeReferenceTable( dtChild, freeDT );
            child->attachToParent( parent, gIODTPlane);

            AddPHandle( child );

            if( kSuccess == DTEnterEntry( iter, dtChild)) {
                stack->setObject( parent);
                parent = child;
            }
            // only registry holds retain
            child->release();
        }

    } while( stack->getCount()
		&& (kSuccess == DTExitEntry( iter, &dtChild)));

    stack->release();
    DTDisposeEntryIterator( iter);

    // parent is now root of the created tree

    // make root name first compatible entry (purely cosmetic)
    if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) {
        parent->setName( parent->getName(), gIODTPlane );
        parent->setName( (const char *) prop->getBytesNoCopy() );
    }

    // attach tree to meta root
    parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane);
    parent->release();

    if( freeDT ) {
        // free original device tree
        DTInit(0);
        IODTFreeLoaderInfo( "DeviceTree",
			    (void *)dtMap[0], (int) round_page(dtMap[1]) );
    }

    // adjust tree

    gIODTSharedInterrupts = OSDictionary::withCapacity(4);
    allInts = OSDictionary::withCapacity(4);
    intMap = false;
    regIter = IORegistryIterator::iterateOver( gIODTPlane,
						kIORegistryIterateRecursively );
    assert( regIter && allInts && gIODTSharedInterrupts );
    if( regIter && allInts && gIODTSharedInterrupts ) {
        while( (child = regIter->getNextObject())) {
            IODTMapInterruptsSharing( child, allInts );
            if( !intMap && child->getProperty( gIODTInterruptParentKey))
                intMap = true;

        }
        regIter->release();
    }

#if IODTSUPPORTDEBUG
    parent->setProperty("allInts", allInts);
    parent->setProperty("sharedInts", gIODTSharedInterrupts);

    regIter = IORegistryIterator::iterateOver( gIODTPlane,
						kIORegistryIterateRecursively );
    if (regIter) {
        while( (child = regIter->getNextObject())) {
	    OSArray *
	    array = OSDynamicCast(OSArray, child->getProperty( gIOInterruptSpecifiersKey ));
	    for( UInt32 i = 0; array && (i < array->getCount()); i++)
	    {
		IOOptionBits options;
		IOReturn ret = IODTGetInterruptOptions( child, i, &options );
		if( (ret != kIOReturnSuccess) || options)
		    IOLog("%s[%ld] %ld (%x)\n", child->getName(), i, options, ret);
	    }
	}
        regIter->release();
    }
#endif

    allInts->release();

    if( intMap)
        // set a key in the root to indicate we found NW interrupt mapping
        parent->setProperty( gIODTNWInterruptMappingKey,
                (OSObject *) gIODTNWInterruptMappingKey );

    return( parent);
}
Exemple #19
0
/*********************************************************************
* This function builds a uniqued, in-order list of modules that need
* to be loaded in order for kmod_name to be successfully loaded. This
* list ends with kmod_name itself.
*********************************************************************/
static
OSArray * getDependencyListForKmod(const char * kmod_name) {

    int error = 0;

    OSDictionary * extensionsDict; // don't release
    OSDictionary * extDict;        // don't release
    OSDictionary * extPlist;       // don't release
    OSString     * extName;        // don't release
    OSArray      * dependencyList = NULL; // return value, caller releases
    unsigned int   i;

   /* These are used to remove duplicates from the dependency list.
    */
    OSArray      * originalList = NULL;     // must be released
    OSDictionary * encounteredNames = NULL; // must be release


   /* Get the dictionary of startup extensions.
    * This is keyed by module name.
    */
    extensionsDict = getStartupExtensions();
    if (!extensionsDict) {
        IOLog("getDependencyListForKmod(): No extensions dictionary.\n");
        LOG_DELAY();
        error = 1;
        goto finish;
    }
    

   /* Get the requested extension's dictionary entry and its property
    * list, containing module dependencies.
    */
    extDict = OSDynamicCast(OSDictionary,
        extensionsDict->getObject(kmod_name));

    if (!extDict) {
        IOLog("getDependencyListForKmod(): "
           "Extension \"%s\" cannot be found.\n",
           kmod_name);
        LOG_DELAY();
        error = 1;
        goto finish;
    }

    extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
    if (!extPlist) {
        IOLog("getDependencyListForKmod(): "
            "Extension \"%s\" has no property list.\n",
            kmod_name);
        LOG_DELAY();
        error = 1;
        goto finish;
    }


   /* Verify that the retrieved entry's "CFBundleIdentifier" property exists.
    * This will be added to the dependency list.
    */
    extName = OSDynamicCast(OSString,
        extPlist->getObject("CFBundleIdentifier"));
    if (!extName) {
        IOLog("getDependencyListForKmod(): "
            "Extension \"%s\" has no \"CFBundleIdentifier\" property.\n",
            kmod_name);
        LOG_DELAY();
        error = 1;
        goto finish;
    }

    dependencyList = OSArray::withCapacity(10);
    if (!dependencyList) {
        IOLog("getDependencyListForKmod(): "
            "Couldn't allocate dependency array for extension \"%s\".\n",
            kmod_name);
        LOG_DELAY();
        error = 1;
        goto finish;
    }


   /* Okay, let's get started.
    */
    dependencyList->setObject(extName);


   /* Here's a slightly tricky bit. This loop iterates through
    * the dependency list until it runs off the end. Each time
    * through, however, any number of dependencies can be added
    * to the end of the list. Eventually some extensions won't
    * have any more dependencies, no more names will be added
    * to the list, and this loop will terminate.
    */
    for (i = 0; i < dependencyList->getCount(); i++) {

        // None of these needs to be released, as they're all from plists.
        OSString     * curName;
        OSDictionary * curExtDict;
        OSDictionary * curExtDepDict;
        OSDictionary * curExtPlist;
        OSString     * curDepName;


       /* An arbitrary limit to prevent infinite loops.
        */
        if (i > 255) {
            IOLog("getDependencyListForKmod(): "
                "max dependency list length exceeded for "
                "extension \"%s\".\n",
                kmod_name);
            LOG_DELAY();
            error = 1;
            goto finish;
        }

        curName = OSDynamicCast(OSString, dependencyList->getObject(i));

        curExtDict = OSDynamicCast(OSDictionary,
            extensionsDict->getObject(curName));
        if (!curExtDict) {
            IOLog("getDependencyListForKmod(): "
                "Extension \"%s\", required for extension \"%s\", "
                "is not available.\n",
                curName->getCStringNoCopy(), kmod_name);
            LOG_DELAY();
            error = 1;
            goto finish;
        }

        curExtPlist = OSDynamicCast(OSDictionary,
            curExtDict->getObject("plist"));
        if (!curExtPlist) {
            IOLog("getDependencyListForKmod(): "
                "Extension \"%s\", required for extension \"%s\", "
                "has no property list.\n",
                curName->getCStringNoCopy(), kmod_name);
            LOG_DELAY();
            error = 1;
            goto finish;
        }

        curExtDepDict = OSDynamicCast(OSDictionary,
              curExtPlist->getObject("OSBundleLibraries"));
        if (curExtDepDict) {
            OSCollectionIterator * keyIterator =
                OSCollectionIterator::withCollection(curExtDepDict);

            if (!keyIterator) {
                IOLog("getDependencyListForKmod(): "
                    "Couldn't allocate iterator for extension "
                    "\"%s\".\n", kmod_name);
                LOG_DELAY();
                error = 1;
                goto finish;
            }
            while ( (curDepName =
                     OSDynamicCast(OSString,
                         keyIterator->getNextObject())) ) {

                OSString * requiredVersion = OSDynamicCast(OSString,
                    curExtDepDict->getObject(curDepName));

                if (!verifyCompatibility(curDepName, requiredVersion)) {
                    IOLog("getDependencyListForKmod(): "
                        "Dependency %s of %s is not compatible or is unavailable.\n",
                        curDepName->getCStringNoCopy(),
                        curName->getCStringNoCopy());
                    LOG_DELAY();
                    error = 1;
                    goto finish;
                }

                dependencyList->setObject(curDepName);
            }

            keyIterator->release();
        }
    }


   /*****
    * The dependency list now exists in the reverse order of required loads,
    * and may have duplicates. Now we turn the list around and remove
    * duplicates.
    */
    originalList = dependencyList;
    dependencyList = OSArray::withCapacity(originalList->getCount());
    if (!dependencyList) {
        IOLog("getDependenciesForKmod(): "
              "Couldn't allocate reversal dependency list for extension "
              "\"%s\".\n", kmod_name);
        LOG_DELAY();
        error = 1;
        goto finish;
    }
    encounteredNames = OSDictionary::withCapacity(originalList->getCount());
    if (!encounteredNames) {
        IOLog("getDependenciesForKmod(): "
              "Couldn't allocate list of encountered names for extension "
              "\"%s\".\n", kmod_name);
        LOG_DELAY();
        error = 1;
        goto finish;
    }


   /* Go backward through the original list, using the encounteredNames
    * dictionary to check for duplicates. We put originalList in as the
    * value because we need some non-NULL value. Here we also drop any
    * extensions that aren't proper dependencies (that is, any that are
    * nonkernel kexts without code).
    */
    i = originalList->getCount();

    if (i > 0) {
        do {
            i--;

            OSString * item = OSDynamicCast(OSString,
                originalList->getObject(i));

            if ( (!encounteredNames->getObject(item)) &&
                 kextIsADependency(item)) {

                encounteredNames->setObject(item, originalList);
                dependencyList->setObject(item);
            }
        } while (i > 0);
    }


finish:

    if (originalList) {
        originalList->release();
    }
    if (encounteredNames) {
        encounteredNames->release();
    }
    if (error) {
        if (dependencyList) {
            dependencyList->release();
            dependencyList = NULL;
        }
    }

    return dependencyList;
}
// Should only be done during init time - this is not thread safe
IOReturn IOAudioLevelControl::addRange(SInt32 minRangeValue, 
                                        SInt32 maxRangeValue, 
                                        IOFixed minRangeDB, 
                                        IOFixed maxRangeDB)
{
    IOReturn result = kIOReturnSuccess;
    
    // We should verify the new range doesn't overlap any others here
    
    if (ranges == NULL) {
        ranges = OSArray::withCapacity(1);
        if (ranges) {
            setProperty(kIOAudioLevelControlRangesKey, ranges);
        }
    }
    
    if (ranges) {
        OSDictionary *newRange;
		OSArray *newRanges;
		OSArray *oldRanges;
        
		oldRanges = ranges;
        newRanges = OSArray::withArray(ranges);
		if (!newRanges)
			return kIOReturnNoMemory;
		
        newRange = OSDictionary::withCapacity(4);
        if (newRange) {
            OSNumber *number;
            
            number = OSNumber::withNumber(minRangeValue, sizeof(SInt32)*8);
            newRange->setObject(kIOAudioLevelControlMinValueKey, number);
            number->release();
            
            number = OSNumber::withNumber(maxRangeValue, sizeof(SInt32)*8);
            newRange->setObject(kIOAudioLevelControlMaxValueKey, number);
            number->release();
            
            number = OSNumber::withNumber(minRangeDB, sizeof(IOFixed)*8);
            newRange->setObject(kIOAudioLevelControlMinDBKey, number);
            number->release();
            
            number = OSNumber::withNumber(maxRangeDB, sizeof(IOFixed)*8);
            newRange->setObject(kIOAudioLevelControlMaxDBKey, number);
            number->release();
            
            newRanges->setObject(newRange);
            setProperty(kIOAudioLevelControlRangesKey, newRanges);
			ranges = newRanges;
			oldRanges->release();
            
            newRange->release();
        } else {
            result = kIOReturnError;
        }
    } else {
        result = kIOReturnError;
    }
    
    return result;
}
Exemple #21
0
bool MacRISC2CPU::start(IOService *provider)
{
    kern_return_t        result;
    IORegistryEntry      *cpusRegEntry, *uniNRegEntry, *mpicRegEntry, *devicetreeRegEntry;
    OSIterator           *cpusIterator;
    OSData               *tmpData;
    IOService            *service;
    const OSSymbol       *interruptControllerName;
    OSData               *interruptData;
    OSArray              *tmpArray;
    UInt32               maxCPUs, uniNVersion, physCPU;
    ml_processor_info_t  processor_info;
    
#if enableUserClientInterface    
	DFScontMode = 0;
    fWorkLoop = 0;
    DFS_Status = false;
    GPU_Status = kGPUHigh;
	vStepped = false;
#endif

    // callPlatformFunction symbols
    mpic_getProvider = OSSymbol::withCString("mpic_getProvider");
    mpic_getIPIVector= OSSymbol::withCString("mpic_getIPIVector");
    mpic_setCurrentTaskPriority = OSSymbol::withCString("mpic_setCurrentTaskPriority");
    mpic_setUpForSleep = OSSymbol::withCString("mpic_setUpForSleep");
    mpic_dispatchIPI = OSSymbol::withCString("mpic_dispatchIPI");
    keyLargo_restoreRegisterState = OSSymbol::withCString("keyLargo_restoreRegisterState");
    keyLargo_syncTimeBase = OSSymbol::withCString("keyLargo_syncTimeBase");
    keyLargo_saveRegisterState = OSSymbol::withCString("keyLargo_saveRegisterState");
    keyLargo_turnOffIO = OSSymbol::withCString("keyLargo_turnOffIO");
    keyLargo_writeRegUInt8 = OSSymbol::withCString("keyLargo_writeRegUInt8");
    keyLargo_getHostKeyLargo = OSSymbol::withCString("keyLargo_getHostKeyLargo");
    keyLargo_setPowerSupply = OSSymbol::withCString("setPowerSupply");
    uniN_setPowerState = OSSymbol::withCString(kUniNSetPowerState);
    uniN_setAACKDelay = OSSymbol::withCString(kUniNSetAACKDelay);
	pmu_cpuReset = OSSymbol::withCString("cpuReset");
	ati_prepareDMATransaction = OSSymbol::withCString(kIOFBPrepareDMAValueKey);
    ati_performDMATransaction = OSSymbol::withCString(kIOFBPerformDMAValueKey);
    
    macRISC2PE = OSDynamicCast(MacRISC2PE, getPlatform());
    if (macRISC2PE == 0) return false;
  
    if (!super::start(provider)) return false;

    // Get the Uni-N Version.
    uniNRegEntry = fromPath("/uni-n", gIODTPlane);
    if (uniNRegEntry == 0) return false;
    tmpData = OSDynamicCast(OSData, uniNRegEntry->getProperty("device-rev"));
    if (tmpData == 0) return false;
    uniNVersion = *(long *)tmpData->getBytesNoCopy();
  
    // Find out if this is the boot CPU.
    bootCPU = false;
    tmpData = OSDynamicCast(OSData, provider->getProperty("state"));
    if (tmpData == 0) return false;
    if (!strcmp((char *)tmpData->getBytesNoCopy(), "running")) bootCPU = true;

    // Count the CPUs.
    numCPUs = 0;
    cpusRegEntry = fromPath("/cpus", gIODTPlane);
    if (cpusRegEntry == 0) return false;
    cpusIterator = cpusRegEntry->getChildIterator(gIODTPlane);
    while (cpusIterator->getNextObject()) numCPUs++;
    cpusIterator->release();
  
	// [3830950] - The bootCPU driver inits globals for all instances (like gCPUIC) so if we're not the
	// boot CPU driver we wait here for that driver to finish its initialization
	if ((numCPUs > 1) && !bootCPU)
		// Wait for bootCPU driver to say it's up and running
		(void) waitForService (resourceMatching ("BootCPU"));
		
    // Limit the number of CPUs to one if uniNVersion is 1.0.7 or less.
    if (uniNVersion < kUniNVersion107) numCPUs = 1;
  
    // Limit the number of CPUs by the cpu=# boot arg.
    if (PE_parse_boot_arg("cpus", &maxCPUs))
    {
        if (numCPUs > maxCPUs) numCPUs = maxCPUs;
    }
	
	ignoreSpeedChange = false;
	doSleep = false;
	topLevelPCIBridgeCount = 0;
  
    // Get the "flush-on-lock" property from the first cpu node.
    flushOnLock = false;
    cpusRegEntry = fromPath("/cpus/@0", gIODTPlane);
    if (cpusRegEntry == 0) return false;
    if (cpusRegEntry->getProperty("flush-on-lock") != 0) flushOnLock = true;
  
    // Set flushOnLock when numCPUs is not one.
    if (numCPUs != 1) flushOnLock = true;
  
    // If system is PowerMac3,5 (TowerG4), then set flushOnLock to disable nap
    devicetreeRegEntry = fromPath("/", gIODTPlane);
    tmpData = OSDynamicCast(OSData, devicetreeRegEntry->getProperty("model"));
    if (tmpData == 0) return false;
#if 0
    if(!strcmp((char *)tmpData->getBytesNoCopy(), "PowerMac3,5"))
        flushOnLock = true;
#endif

    // Get the physical CPU number from the "reg" property.
    tmpData = OSDynamicCast(OSData, provider->getProperty("reg"));
    if (tmpData == 0) return false;
    physCPU = *(long *)tmpData->getBytesNoCopy();
    setCPUNumber(physCPU);

    // Get the gpio offset for soft reset from the "soft-reset" property.
    tmpData = OSDynamicCast(OSData, provider->getProperty("soft-reset"));
    if (tmpData == 0) 
    {
        if (physCPU == 0)
            soft_reset_offset = 0x5B;
        else
            soft_reset_offset = 0x5C;
    }
    else
        soft_reset_offset = *(long *)tmpData->getBytesNoCopy();
   
    // Get the gpio offset for timebase enable from the "timebase-enable" property.
    tmpData = OSDynamicCast(OSData, provider->getProperty("timebase-enable"));
    if (tmpData == 0) 
        timebase_enable_offset = 0x73;
    else
        timebase_enable_offset = *(long *)tmpData->getBytesNoCopy();
  
	// See if reset is needed on wake
	resetOnWake = (provider->getProperty ("reset-on-wake") != NULL);
	
	if (resetOnWake) {
		vm_address_t reserveMem;
		

		reserveMem = (vm_address_t)IOMallocAligned (PAGE_SIZE, PAGE_SIZE);	// Get one page (which we keep forever)
		if (reserveMem) {			
			// map it
			reserveMemDesc = IOMemoryDescriptor::withAddress (reserveMem, PAGE_SIZE, kIODirectionNone, NULL);
			if (reserveMemDesc) {
				// get the physical address
				reserveMemPhys = reserveMemDesc->getPhysicalAddress();
			} 
		} 
	}

    // On machines with a 'vmin' property in the CPU Node we need to make sure to tell the kernel to 
    // ml_set_processor_voltage on needed processors.
    needVSetting = (provider->getProperty( "vmin" ) != 0);

    // While techincally the Apollo7PM machines do need AACK delay, it is already set in the bootROM
    // since we boot slow.  We don't want the machine to switch AACKdelay off when we run DFS high so
    // setting this to false will take care of the issue.
        
    needAACKDelay = false;
 
 	if (bootCPU)
    {
        gCPUIC = new IOCPUInterruptController;
        if (gCPUIC == 0) return false;
        if (gCPUIC->initCPUInterruptController(numCPUs) != kIOReturnSuccess)
            return false;
        gCPUIC->attach(this);
        gCPUIC->registerCPUInterruptController();
    }
  
    // Get the l2cr value from the property list.
    tmpData = OSDynamicCast(OSData, provider->getProperty("l2cr"));
    if (tmpData != 0)
    {
        l2crValue = *(long *)tmpData->getBytesNoCopy() & 0x7FFFFFFF;
    }
    else
    {
        l2crValue = mfl2cr() & 0x7FFFFFFF;
    }
  
    // Wait for KeyLargo to show up.
    keyLargo = waitForService(serviceMatching("KeyLargo"));
    if (keyLargo == 0) return false;
  
    keyLargo->callPlatformFunction (keyLargo_getHostKeyLargo, false, &keyLargo, 0, 0, 0);
    if (keyLargo == 0)
    {
        kprintf ("MacRISC2CPU::start - getHostKeyLargo returned nil\n");
        return false;
    }

    // Wait for MPIC to show up.
    mpic = waitForService(serviceMatching("AppleMPICInterruptController"));
    if (mpic == 0) return false;
  
    // Set the Interrupt Properties for this cpu.
    mpic->callPlatformFunction(mpic_getProvider, false, (void *)&mpicRegEntry, 0, 0, 0);
    interruptControllerName = IODTInterruptControllerName(mpicRegEntry);
    mpic->callPlatformFunction(mpic_getIPIVector, false, (void *)&physCPU, (void *)&interruptData, 0, 0);
    if ((interruptControllerName == 0) || (interruptData == 0)) return false;
  
    tmpArray = OSArray::withCapacity(1);
    tmpArray->setObject(interruptControllerName);
    cpuNub->setProperty(gIOInterruptControllersKey, tmpArray);
    tmpArray->release();
  
    tmpArray = OSArray::withCapacity(1);
    tmpArray->setObject(interruptData);
    cpuNub->setProperty(gIOInterruptSpecifiersKey, tmpArray);
    tmpArray->release();
  
    setCPUState(kIOCPUStateUninitalized);
  
	// necessary bootCPU initialization is done, so release other CPU drivers to do their thing
	// other drivers need to be unblocked *before* we call processor_start otherwise we deadlock
	if (bootCPU)
		publishResource ("BootCPU", this);
		
    if (physCPU < numCPUs)
    {
        processor_info.cpu_id           = (cpu_id_t)this;
        processor_info.boot_cpu         = bootCPU;
        processor_info.start_paddr      = 0x0100;
        processor_info.l2cr_value       = l2crValue;
        processor_info.supports_nap     = !flushOnLock;
        processor_info.time_base_enable =
        OSMemberFunctionCast(time_base_enable_t, this, &MacRISC2CPU::enableCPUTimeBase);	// [4091924]
    
        // Register this CPU with mach.
        result = ml_processor_register(&processor_info, &machProcessor,	&ipi_handler);
        if (result == KERN_FAILURE) return false;
    
        processor_start(machProcessor);
    }

    // Before to go to sleep we wish to disable the napping mode so that the PMU
    // will not shutdown the system while going to sleep:
    service = waitForService(serviceMatching("IOPMrootDomain"));
    pmRootDomain = OSDynamicCast(IOPMrootDomain, service);
    if (pmRootDomain != 0)
    {
        kprintf("Register MacRISC2CPU %ld to acknowledge power changes\n", getCPUNumber());
        pmRootDomain->registerInterestedDriver(this);
        
        // Join the Power Management Tree to receive setAggressiveness calls.
        PMinit();
        provider->joinPMtree(this);
    }

    // Finds PMU and UniN so in quiesce we can put the machine to sleep.
    // I can not put these calls there because quiesce runs in interrupt
    // context and waitForService may block.
    pmu = waitForService(serviceMatching("ApplePMU"));
	uniN = waitForService(serviceMatching("AppleUniN"));
    if ((pmu == 0) || (uniN == 0)) return false;
	

    if (macRISC2PE->hasPMon) {
            // Find the platform monitor, if present
            service = waitForService(resourceMatching("IOPlatformMonitor"));
            ioPMon = OSDynamicCast (IOPlatformMonitor, service->getProperty("IOPlatformMonitor"));
            if (!ioPMon) 
                    return false;
            
            ioPMonDict = OSDictionary::withCapacity(2);
            if (!ioPMonDict) {
                    ioPMon = NULL;
            } else {
                    ioPMonDict->setObject (kIOPMonTypeKey, OSSymbol::withCString (kIOPMonTypeCPUCon));
                    ioPMonDict->setObject (kIOPMonCPUIDKey, OSNumber::withNumber ((long long)getCPUNumber(), 32));

                    if (messageClient (kIOPMonMessageRegister, ioPMon, (void *)ioPMonDict) != kIOReturnSuccess) {
                            // IOPMon doesn't need to know about us, so don't bother with it
                            IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformMonitor\n");
                            ioPMonDict->release();
                            ioPMon = NULL;
                    }
            }
    }

    if (macRISC2PE->hasPPlugin) {
		IOService		*ioPPlugin;
		OSDictionary	*ioPPluginDict;
		
		// Find the platform plugin, if present
		service = waitForService(resourceMatching("IOPlatformPlugin"));
		ioPPlugin = OSDynamicCast (IOService, service->getProperty("IOPlatformPlugin"));
		if (!ioPPlugin) 
			return false;
		
		ioPPluginDict = OSDictionary::withCapacity(2);
		if (ioPPluginDict) {
			ioPPluginDict->setObject ("cpu-id", OSNumber::withNumber ((long long)getCPUNumber(), 32));

			// Register with the plugin - same API as for platform monitor
			if (messageClient (kIOPMonMessageRegister, ioPPlugin, (void *)ioPPluginDict) != kIOReturnSuccess) {
				// ioPPlugin doesn't need to know about us, so don't bother with it
				IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformPlugin\n");
			}
			ioPPluginDict->release();	// Not needed any more
		}
    }

#if enableUserClientInterface    
//   
// UserClient stuff...
//  
    fWorkLoop = getWorkLoop();
    if(!fWorkLoop)
    {
            IOLog("MacRISC2CPU::start ERROR: failed to find a fWorkLoop\n");
    }
    if(!initTimers()) 
    {
            IOLog("MacRISC2CPU::start ERROR: failed to init the timers\n");
    }
    
#endif

    registerService();
  
    return true;
}
static void createNubs(IOService *provider) {
	const char nameID[2][8] = {"@0,name", "@1,name"};
	const char name[11] = "Aty,Radeon";
	const char typeID[2][15] = {"@0,device_type", "@1,device_type"};
	const char type[] = "display";
	OSObject *tempObj;
	
	int i;
	
	if (provider->getProperty(kIONDRVIgnoreKey)) return;
	provider->setProperty(kIONDRVIgnoreKey, kOSBooleanTrue);	//prevent IONDRVFramebuffer from match
	
	LOG("createNubs\n");
	
	if (!provider->getProperty("@0,name") && !provider->getProperty("@1,name")) {
		for (i = 0;i < 2;i++) {	// Debug
			tempObj = OSData::withBytes(name, 11);
			provider->setProperty(nameID[i], tempObj);
			tempObj->release();
			tempObj = OSData::withBytes(type, 8);
			provider->setProperty(typeID[i], tempObj);
			tempObj->release();
		}
	}
	// have to move below part from IONDRVFramebuffer to make it work
	IORegistryIterator * iter;
	IORegistryEntry *    next;
	IOService *          newNub;
	OSArray *            toDo = 0;
	bool                 firstLevel;
    OSData *            data;
	
	if (provider->getProperty("@0,name"))
	{
		OSDictionary *         dict;
		OSCollectionIterator * keys;
		const OSSymbol *       key;
		char                   buffer[80];
		const char *           keyChrs;
		size_t                 len;
		char                   c;
		
		dict = provider->dictionaryWithProperties();
		keys = OSCollectionIterator::withCollection(dict);
		if (dict)
			dict->release();
		if (keys)
		{
			while ((key = OSDynamicCast(OSSymbol, keys->getNextObject())))
			{
				keyChrs = key->getCStringNoCopy();
				if ('@' != keyChrs[0])
					continue;
				
				len = 0;
				do
				{
					c = keyChrs[len];
					if (!c || (c == ','))
						break;
					buffer[len] = c;
					len++;
				}
				while (len < (sizeof(buffer) - 1));
				if (!c)
					continue;
				
				buffer[len] = 0;
				keyChrs += len + 1;
				
				next = provider->childFromPath(buffer, gIODTPlane);
				if (!next)
				{
					next = new IOService;
					if (next && !next->init())
					{
						next->release();
						next = 0;
					}
					if (!next)
						continue;
					next->setLocation(&buffer[1]);
					if (!next->attachToParent(provider, gIODTPlane))
						continue;
				}
				
				OSObject * obj = dict->getObject(key);
				next->setProperty(keyChrs, dict->getObject(key));
				if (!strcmp(keyChrs, "name"))
				{
					OSData * data = OSDynamicCast(OSData, obj);
					if (data)
						next->setName((const char *) data->getBytesNoCopy());
				}
				next->release();
				provider->removeProperty(key);
			}
			keys->release();
		}
	}
	
	iter = IORegistryIterator::iterateOver( provider, gIODTPlane, 0 );
	toDo = OSArray::withCapacity(2);
	
	if (iter && toDo)
	{
		bool haveDoneLibInit = false;
		UInt32 index = 0;
		do
		{
			while ((next = (IORegistryEntry *) iter->getNextObject()))
			{
				firstLevel = (provider == next->getParentEntry(gIODTPlane));
				if (firstLevel)
				{
					data = OSDynamicCast( OSData, next->getProperty("device_type"));
					if (!data || (0 != strcmp("display", (char *) data->getBytesNoCopy())))
						continue;
					
					if (!haveDoneLibInit)
					{
						haveDoneLibInit = (kIOReturnSuccess == _IONDRVLibrariesInitialize(provider));
						if (!haveDoneLibInit)
							continue;
					}
					next->setProperty( kIOFBDependentIDKey, (uintptr_t) provider, 64 );
					next->setProperty( kIOFBDependentIndexKey, index, 32 );
					next->setProperty( kIONDRVIgnoreKey, kOSBooleanTrue );
					index++;
				}
				
				toDo->setObject( next );
				iter->enterEntry();
			}
		}
		while (iter->exitEntry());
	}
	if (iter)
		iter->release();
	
	if (toDo)
	{
		OSObject * obj;
		OSArray  * deviceMemory;
		obj = provider->copyProperty(gIODeviceMemoryKey);
		deviceMemory = OSDynamicCast(OSArray, obj);
		
		for (unsigned int i = 0;
			 (next = (IORegistryEntry *) toDo->getObject(i));
			 i++)
		{
			newNub = new IONDRVDevice;
			if (!newNub)
				continue;
			if (!newNub->init(next, gIODTPlane))
			{
				newNub->free();
				newNub = 0;
				continue;
			}
			if (deviceMemory)
				newNub->setDeviceMemory(deviceMemory);
			newNub->attach(provider);
			newNub->registerService(kIOServiceSynchronous);
		}
		if (obj)
			obj->release();
		toDo->release();
	}
}