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; }
OSArray *OSArray::withCapacity(unsigned int capacity) { OSArray *me = new OSArray; if (me && !me->initWithCapacity(capacity)) { me->release(); return 0; } return me; }
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; }
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; }
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; }
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; }
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); }
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; }
/********************************************************************* * 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; }
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; }
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; }
/********************************************************************* * 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); }
/********************************************************************* * 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; }
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(); } }