volatile int kmod_start(void) { libkern_init0(); OSString* one = OSString::withCString("Anal sex"); OSString* two = OSString::withCString("Cunnilingus"); OSArray* sexthings = OSArray::withCapacity(2); sexthings->setObject(one); sexthings->setObject(two); printk("Hello from IOKit!\n"); printk("Put: %p %p\n", one, two); printk("OSArray: %p\n", sexthings); printk("Get: %p %p\n", sexthings->getObject(0), sexthings->getObject(1)); OSSerialize* ser = OSSerialize::withCapacity(1024); sexthings->serialize(ser); printk("Serialized: %s \n", ser->text()); return 0; }
UInt32 ACPIBacklightPanel::queryACPICurentBrightnessLevel() { //DbgLog("%s::%s()\n", this->getName(),__FUNCTION__); if (_backlightHandler) return _backlightHandler->getBacklightLevel(); UInt32 level = minAC; const char* method = _extended ? "XBQC" : "_BQC"; if (kIOReturnSuccess == backLightDevice->evaluateInteger(method, &level)) { //DbgLog("%s: queryACPICurentBrightnessLevel %s = %d\n", this->getName(), method, level); OSBoolean * useIdx = OSDynamicCast(OSBoolean, getProperty("BQC use index")); if (useIdx && useIdx->isTrue()) { OSArray * levels = queryACPISupportedBrightnessLevels(); if (levels) { OSNumber *num = OSDynamicCast(OSNumber, levels->getObject(level)); if (num) level = num->unsigned32BitValue(); levels->release(); } } //DbgLog("%s: queryACPICurentBrightnessLevel returning %d\n", this->getName(), level); } else { IOLog("ACPIBacklight: Error in queryACPICurentBrightnessLevel %s\n", method); } //some laptops didn't return anything on startup, return then max value (first entry in _BCL): return level; }
OSString * ACPIBacklightPanel::getACPIPath(IOACPIPlatformDevice * acpiDevice) { OSString * separator = OSString::withCStringNoCopy("."); OSArray * array = OSArray::withCapacity(10); char devicePath[512]; bzero(devicePath, sizeof(devicePath)); IOACPIPlatformDevice * parent = acpiDevice; IORegistryIterator * iter = IORegistryIterator::iterateOver(acpiDevice, gIOACPIPlane, kIORegistryIterateParents | kIORegistryIterateRecursively); if (iter) { do { array->setObject(parent->copyName(gIOACPIPlane)); array->setObject(separator); parent = OSDynamicCast(IOACPIPlatformDevice, iter->getNextObject()); } while (parent); iter->release(); int offset = 0; OSString * str = OSDynamicCast(OSString, array->getLastObject()); for (int i = array->getCount()-2; ((i>=0) || ((offset + str->getLength()) > sizeof(devicePath))) ; i--) { str = OSDynamicCast(OSString, array->getObject(i)); strncpy(devicePath + offset, str->getCStringNoCopy(), str->getLength()); offset += str->getLength(); } } return OSString::withCString(devicePath); }
bool CompareDeviceUsagePairs( 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 // OSArray * pairArray; OSDictionary * pair; bool matches = true; int count; pairArray = OSDynamicCast(OSArray, matching->getObject( kIOHIDDeviceUsagePairsKey )); if (pairArray) { count = pairArray->getCount(); for (int i=0; i<count; i++) { if ( !(pair = OSDynamicCast(OSDictionary,pairArray->getObject(i))) ) continue; if ( !(matches = CompareDeviceUsage(owner, pair, score, increment)) ) continue; break; } } return matches; }
bool CompareNumberPropertyArray( IOService * owner, OSDictionary * matching, const char * arrayName, const char * key, SInt32 * score, SInt32 increment) { OSNumber *registryProperty = (OSNumber *)owner->copyProperty(key); OSArray *propertyArray = (OSArray *)matching->getObject(arrayName); CONVERT_TO_STACK_RETAIN(registryProperty); // If the property in the matching doesn't exist return true if ( OSDynamicCast(OSArray, propertyArray) ) { if ( OSDynamicCast(OSNumber, registryProperty ) ) { OSNumber *propertyFromArray; int i = 0; for ( i = 0; i < propertyArray->getCount(); i ++ ) { propertyFromArray = OSDynamicCast(OSNumber, propertyArray->getObject(i)); if ( propertyFromArray && propertyFromArray->isEqualTo(registryProperty) ) { if ( score ) *score += increment; return true; } } } } else return true; return false; }
void SuperIO::LoadConfiguration(IOService* provider) { m_Service = provider; OSBoolean* fanControl = OSDynamicCast(OSBoolean, provider->getProperty("Enable Fan Control")); m_FanControl = fanControl->getValue(); OSBoolean* alternateRegisters = OSDynamicCast(OSBoolean, provider->getProperty("Register number alternative variant")); m_AlternateRegisters = alternateRegisters->getValue(); OSArray* fanIDs = OSDynamicCast(OSArray, provider->getProperty("Fan Names")); if (fanIDs) fanIDs = OSArray::withArray(fanIDs); if (fanIDs) { UInt32 count = fanIDs->getCount(); if(count > 5) count = 5; for (UInt32 i = 0; i < count; i++) { OSString* name = OSDynamicCast(OSString, fanIDs->getObject(i)); FanName[i] = name->getCStringNoCopy(); } fanIDs->release(); } }
//==================================================================================================== // IOHIDEventOverrideDriver::dispatchKeyboardEvent //==================================================================================================== bool IOHIDEventOverrideDriver::handleStart( IOService * provider ) { OSArray * maps = NULL; if ( !super::handleStart(provider) ) return false; maps = OSDynamicCast(OSArray, getProperty("ButtonMaps")); if ( maps ) { int index; for ( index=0; index<maps->getCount(); index++ ) { OSDictionary * map; OSNumber * number; uint32_t button; uint32_t usagePage; uint32_t usage; uint32_t eventType; map = OSDynamicCast(OSDictionary, maps->getObject(index)); if ( !map ) continue; number = OSDynamicCast(OSNumber, map->getObject("ButtonNumber")); if ( !number ) continue; button = number->unsigned32BitValue(); if ( !button || button>32 ) continue; number = OSDynamicCast(OSNumber, map->getObject("EventType")); if ( !number ) continue; eventType = number->unsigned32BitValue(); number = OSDynamicCast(OSNumber, map->getObject("UsagePage")); if ( !number ) continue; usagePage = number->unsigned32BitValue(); number = OSDynamicCast(OSNumber, map->getObject("Usage")); if ( !number ) continue; usage = number->unsigned32BitValue(); _buttonMap[button-1].eventType = eventType; _buttonMap[button-1].usagePage = usagePage; _buttonMap[button-1].usage = usage; } } return true; }
void loadPStateOverride(OSArray* dict) { //return; // autodetect /* Here we load the override pstate table from the given array */ NumberOfPStates = dict->getCount(); for (int i = 0; i < NumberOfPStates; i++) { OSArray* onePstate = (OSArray*) dict->getObject(i); PStates[i].AcpiFreq = ((OSNumber*) onePstate->getObject(0))->unsigned16BitValue(); PStates[i].Frequency = MHz_to_FID(PStates[i].AcpiFreq); // this accounts for N/2 automatically PStates[i].OriginalVoltage = mV_to_VID(((OSNumber*) onePstate->getObject(1))->unsigned16BitValue()); PStates[i].Voltage = PStates[i].OriginalVoltage; PStates[i].TimesChosen = 0; info("P-State %d: %d MHz Fr: %d at %d mV\n", i, PStates[i].AcpiFreq, PStates[i].Frequency, VID_to_mV(PStates[i].OriginalVoltage)); } info("Loaded %d PStates from Info.plist\n", NumberOfPStates); }
UInt32 ACPIBacklightPanel::setupIndexedLevels() { DbgLog("%s::%s()\n", this->getName(),__FUNCTION__); OSNumber * num; OSArray * levels = queryACPISupportedBrightnessLevels(); if (levels) { BCLlevelsCount = levels->getCount(); if (BCLlevelsCount < 3) return 0; //verify the types of objects is good once for all for (int i = 0; i< BCLlevelsCount; i++) { if (!OSDynamicCast(OSNumber, levels->getObject(i))) return 0; } //TODO : manage the case when the list has no order! Linux do that //test the order of the list UInt32 min, max; num = OSDynamicCast(OSNumber, levels->getObject(2)); min = num->unsigned32BitValue(); num = OSDynamicCast(OSNumber, levels->getObject(BCLlevelsCount-1)); max = num->unsigned32BitValue(); if (max < min) //list is reverted ! { BCLlevels = new UInt32[BCLlevelsCount]; for (int i = 0; i< BCLlevelsCount; i++) { num = OSDynamicCast(OSNumber, levels->getObject(BCLlevelsCount -1 -i)); BCLlevels[i] = num->unsigned32BitValue(); } } else { BCLlevelsCount = BCLlevelsCount -2; BCLlevels = new UInt32[BCLlevelsCount]; for (int i = 0; i< BCLlevelsCount; i++) { num = OSDynamicCast(OSNumber, levels->getObject(i+2)); BCLlevels[i] = num->unsigned32BitValue(); } } //2 first items are min on ac and max on bat num = OSDynamicCast(OSNumber, levels->getObject(0)); minAC = findIndexForLevel(num->unsigned32BitValue()); setDebugProperty("BCL: Min on AC", num); num = OSDynamicCast(OSNumber, levels->getObject(1)); maxBat = findIndexForLevel(num->unsigned32BitValue()); setDebugProperty("BCL: Max on Bat", num); setDebugProperty("Brightness Control Levels", levels); levels->release(); return BCLlevelsCount-1; } return 0; }
/********************************************************************* * Remove drivers from the catalog which match the * properties in the matching dictionary. *********************************************************************/ bool IOCatalogue::removeDrivers( OSDictionary * matching, bool doNubMatching) { OSOrderedSet * set; OSCollectionIterator * iter; OSDictionary * dict; OSArray * array; const OSSymbol * key; unsigned int idx; if ( !matching ) return false; set = OSOrderedSet::withCapacity(10, IOServiceOrdering, (void *)gIOProbeScoreKey); if ( !set ) return false; iter = OSCollectionIterator::withCollection(personalities); if (!iter) { set->release(); return (false); } IORWLockWrite(lock); while ((key = (const OSSymbol *) iter->getNextObject())) { array = (OSArray *) personalities->getObject(key); if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) { /* This comparison must be done with only the keys in the * "matching" dict to enable general searches. */ if ( dict->isEqualTo(matching, matching) ) { set->setObject(dict); array->removeObject(idx); idx--; } } // Start device matching. if ( doNubMatching && (set->getCount() > 0) ) { IOService::catalogNewDrivers(set); generation++; } } IORWLockUnlock(lock); set->release(); iter->release(); return true; }
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; }
void AppleACPIPS2Nub::mergeInterruptProperties(IOService *pnpProvider, long) { /* Make sure we're called from within start() where these i-vars are valid */ if(m_interruptControllers == NULL || m_interruptSpecifiers == NULL) return; /* Get the interrupt controllers/specifiers arrays from the provider, and make sure they * exist and contain at least one entry. We assume they contain exactly one entry. */ OSArray *controllers = OSDynamicCast(OSArray,pnpProvider->getProperty(gIOInterruptControllersKey)); OSArray *specifiers = OSDynamicCast(OSArray,pnpProvider->getProperty(gIOInterruptSpecifiersKey)); if(controllers == NULL || specifiers == NULL) return; if(controllers->getCount() == 0 || specifiers->getCount() == 0) return; /* Append the first object of each array into our own respective array */ m_interruptControllers->setObject(controllers->getObject(0)); m_interruptSpecifiers->setObject(specifiers->getObject(0)); }
bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider) { IOService * aService; bool registered = false; OSArray * children; unsigned int numChildren; OSDictionary * child; // make sure someone is not already registered here if ( NULL == theTreeNode->getObject ("service") ) { if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) { // 1. CHILDREN ------------------ // we registered the node in the tree...now if the node has children // registered we must tell this service to add them. if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) { numChildren = children->getCount (); for ( unsigned int i = 0; i < numChildren; i++ ) { if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) { if ( NULL != (aService = (IOService *) child->getObject ("service")) ) theService->addPowerChild (aService); } } } // 2. PARENT -------------------- // also we must notify the parent of this node (if a registered service // exists there) of a new child. if ( theTreeParentNode ) { if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) ) if (aService != theProvider) aService->addPowerChild (theService); } registered = true; } } return registered; }
// This routine will look to see if the OSArray contains any matching keys. The OSArray has to contain a list of OSNumbers. bool IOUSBNub::USBComparePropertyInArray( OSDictionary *matching, const char * arrayName, const char * key, UInt32 * theProductIDThatMatched ) { // We return success iff we match any entry in the array with the key OSArray * propertyIDArray = NULL; OSNumber * registryProperty = NULL; OSNumber * propertyFromArrayItem = NULL; bool matches = false; unsigned int index; *theProductIDThatMatched = 0; // Get our nub's value for the key registryProperty = OSDynamicCast(OSNumber, getProperty(key)); propertyIDArray = OSDynamicCast(OSArray, matching->getObject(arrayName)); // Iterate over the array looking for the entries if (propertyIDArray && registryProperty) { USBLog(7, "%s[%p]::USBComparePropertyInArray - found array with capacity of %d", getName(), this, propertyIDArray->getCount()); for (index = 0; index < propertyIDArray->getCount(); index++) { propertyFromArrayItem = OSDynamicCast(OSNumber, propertyIDArray->getObject(index)); if (propertyFromArrayItem) { // See if this item has the same value as the one in our registry for this key matches = propertyFromArrayItem->isEqualTo( registryProperty); if (matches) { *theProductIDThatMatched = propertyFromArrayItem->unsigned32BitValue(); USBLog(7, "%s[%p]::USBComparePropertyInArray - item %d matched: id = 0x%x", getName(), this, index, (uint32_t) *theProductIDThatMatched); break; } else { USBLog(7, "%s[%p]::USBComparePropertyInArray - item %d did not match", getName(), this, index); } } } } return matches; }
// This routine will look to see if the OSArray contains any matching keys. The OSArray has to contain a list of OSNumbers. bool IOUSBNub::USBComparePropertyInArrayWithMask( OSDictionary *matching, const char * arrayName, const char * key, const char * maskKey, UInt32 * theProductIDThatMatched ) { // We return success iff we match any entry in the array with the key OSArray * propertyIDArray = NULL; OSNumber * registryProperty = NULL; OSNumber * propertyFromArrayItem = NULL; OSNumber * dictionaryMask = NULL; bool matches = false; unsigned int index; *theProductIDThatMatched = 0; // Get our nub's value for the key registryProperty = OSDynamicCast(OSNumber, getProperty(key)); propertyIDArray = OSDynamicCast(OSArray, matching->getObject(arrayName)); dictionaryMask = OSDynamicCast(OSNumber, matching->getObject(maskKey)); // Iterate over the array looking for the entries if (propertyIDArray && registryProperty && dictionaryMask) { USBLog(7, "%s[%p]::USBComparePropertyInArrayWithMask - found array with capacity of %d", getName(), this, propertyIDArray->getCount()); for (index = 0; index < propertyIDArray->getCount(); index++) { propertyFromArrayItem = OSDynamicCast(OSNumber, propertyIDArray->getObject(index)); if (propertyFromArrayItem) { UInt32 registryValue = registryProperty->unsigned32BitValue(); UInt32 arrayValue = propertyFromArrayItem->unsigned32BitValue(); UInt32 mask = dictionaryMask->unsigned32BitValue(); if ( (registryValue & mask) == (arrayValue & mask) ) { USBLog(7, "%s[%p]::USBComparePropertyInArrayWithMask - 0x%x, 0x%x, mask 0x%x matched", getName(), this, (uint32_t)arrayValue, (uint32_t)registryValue, (uint32_t)mask); *theProductIDThatMatched = registryValue; matches = true; } } } } return matches; }
/********************************************************************* * Is personality already in the catalog? *********************************************************************/ OSOrderedSet * IOCatalogue::findDrivers( OSDictionary * matching, SInt32 * generationCount) { OSCollectionIterator * iter; OSDictionary * dict; OSOrderedSet * set; OSArray * array; const OSSymbol * key; unsigned int idx; OSKext::uniquePersonalityProperties(matching); set = OSOrderedSet::withCapacity( 1, IOServiceOrdering, (void *)gIOProbeScoreKey ); if (!set) return (0); iter = OSCollectionIterator::withCollection(personalities); if (!iter) { set->release(); return (0); } IORWLockRead(lock); while ((key = (const OSSymbol *) iter->getNextObject())) { array = (OSArray *) personalities->getObject(key); if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) { /* This comparison must be done with only the keys in the * "matching" dict to enable general searches. */ if ( dict->isEqualTo(matching, matching) ) set->setObject(dict); } } *generationCount = getGenerationCount(); IORWLockUnlock(lock); iter->release(); return set; }
bool CompareNumberPropertyArrayWithMask( IOService * owner, OSDictionary * matching, const char * arrayName, const char * key, const char * maskKey, SInt32 * score, SInt32 increment) { OSNumber *registryProperty = (OSNumber *)owner->copyProperty(key); OSArray *propertyArray = (OSArray *)matching->getObject(arrayName); OSNumber *valueMask = (OSNumber *)matching->getObject(maskKey); CONVERT_TO_STACK_RETAIN(registryProperty); // If the property array or the value mask doesn't exist then return true if( OSDynamicCast(OSArray, propertyArray) && OSDynamicCast(OSNumber, valueMask) ) { if ( OSDynamicCast(OSNumber, registryProperty) ) { OSNumber *propertyFromArray; UInt32 registryValue = registryProperty->unsigned32BitValue(); UInt32 mask = valueMask->unsigned32BitValue(); int i = 0; for ( i = 0; i < propertyArray->getCount(); i ++ ) { propertyFromArray = OSDynamicCast(OSNumber, propertyArray->getObject(i)); if ( propertyFromArray ) { UInt32 propertyFromArrayValue = propertyFromArray->unsigned32BitValue(); if( (registryValue & mask) == (propertyFromArrayValue & mask ) ) { if ( score ) *score += increment; return true; } } } } } else return true; return false; }
IOReturn IOCatalogue::_removeDrivers(OSDictionary * matching) { IOReturn ret = kIOReturnSuccess; OSCollectionIterator * iter; OSDictionary * dict; OSArray * array; const OSSymbol * key; unsigned int idx; // remove configs from catalog. iter = OSCollectionIterator::withCollection(personalities); if (!iter) return (kIOReturnNoMemory); while ((key = (const OSSymbol *) iter->getNextObject())) { array = (OSArray *) personalities->getObject(key); if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) { /* 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)) { array->removeObject(idx); idx--; } } } iter->release(); return ret; }
OSOrderedSet * IOCatalogue::findDrivers( IOService * service, SInt32 * generationCount) { OSDictionary * nextTable; OSOrderedSet * set; OSArray * array; const OSMetaClass * meta; unsigned int idx; set = OSOrderedSet::withCapacity( 1, IOServiceOrdering, (void *)gIOProbeScoreKey ); if( !set ) return( 0 ); IORWLockRead(lock); meta = service->getMetaClass(); while (meta) { array = (OSArray *) personalities->getObject(meta->getClassNameSymbol()); if (array) for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++) { set->setObject(nextTable); } if (meta == &IOService::gMetaClass) break; meta = meta->getSuperClass(); } *generationCount = getGenerationCount(); IORWLockUnlock(lock); return( set ); }
void KLDBootstrap::readPrelinkedExtensions( kernel_section_t * prelinkInfoSect) { OSArray * infoDictArray = NULL; // do not release OSObject * parsedXML = NULL; // must release OSDictionary * prelinkInfoDict = NULL; // do not release OSString * errorString = NULL; // must release OSKext * theKernel = NULL; // must release kernel_segment_command_t * prelinkTextSegment = NULL; // see code kernel_segment_command_t * prelinkInfoSegment = NULL; // see code /* We make some copies of data, but if anything fails we're basically * going to fail the boot, so these won't be cleaned up on error. */ void * prelinkData = NULL; // see code vm_size_t prelinkLength = 0; OSDictionary * infoDict = NULL; // do not release IORegistryEntry * registryRoot = NULL; // do not release OSNumber * prelinkCountObj = NULL; // must release u_int i = 0; #if NO_KEXTD bool ramDiskBoot; bool developerDevice; bool dontLoad; #endif OSData * kaslrOffsets = NULL; unsigned long plk_segSizes[PLK_SEGMENTS]; vm_offset_t plk_segAddrs[PLK_SEGMENTS]; OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Starting from prelinked kernel."); prelinkTextSegment = getsegbyname(kPrelinkTextSegment); if (!prelinkTextSegment) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Can't find prelinked kexts' text segment."); goto finish; } #if KASLR_KEXT_DEBUG unsigned long scratchSize; vm_offset_t scratchAddr; IOLog("kaslr: prelinked kernel address info: \n"); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__TEXT", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__DATA", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__LINKEDIT", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__KLD", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_TEXT", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_INFO", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); #endif prelinkData = (void *) prelinkTextSegment->vmaddr; prelinkLength = prelinkTextSegment->vmsize; /* build arrays of plk info for later use */ const char ** segNamePtr; for (segNamePtr = &plk_segNames[0], i = 0; *segNamePtr && i < PLK_SEGMENTS; segNamePtr++, i++) { plk_segSizes[i] = 0; plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(&_mh_execute_header, *segNamePtr, &plk_segSizes[i]); } /* Unserialize the info dictionary from the prelink info section. */ parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr, &errorString); if (parsedXML) { prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML); } if (!prelinkInfoDict) { const char * errorCString = "(unknown error)"; if (errorString && errorString->getCStringNoCopy()) { errorCString = errorString->getCStringNoCopy(); } else if (parsedXML) { errorCString = "not a dictionary"; } OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "Error unserializing prelink plist: %s.", errorCString); goto finish; } #if NO_KEXTD /* Check if we should keep developer kexts around. * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201> */ developerDevice = true; PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice)); ramDiskBoot = IORamDiskBSDRoot(); #endif /* NO_KEXTD */ infoDictArray = OSDynamicCast(OSArray, prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey)); if (!infoDictArray) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "The prelinked kernel has no kext info dictionaries"); goto finish; } /* kaslrOffsets are available use them to slide local relocations */ kaslrOffsets = OSDynamicCast(OSData, prelinkInfoDict->getObject(kPrelinkLinkKASLROffsetsKey)); /* Create dictionary of excluded kexts */ OSKext::createExcludeListFromPrelinkInfo(infoDictArray); /* Create OSKext objects for each info dictionary. */ for (i = 0; i < infoDictArray->getCount(); ++i) { infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i)); if (!infoDict) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Can't find info dictionary for prelinked kext #%d.", i); continue; } #if NO_KEXTD dontLoad = false; /* If we're not on a developer device, skip and free developer kexts. */ if (developerDevice == false) { OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean, infoDict->getObject(kOSBundleDeveloperOnlyKey)); if (devOnlyBool == kOSBooleanTrue) { dontLoad = true; } } /* Skip and free kexts that are only needed when booted from a ram disk. */ if (ramDiskBoot == false) { OSBoolean *ramDiskOnlyBool = OSDynamicCast(OSBoolean, infoDict->getObject(kOSBundleRamDiskOnlyKey)); if (ramDiskOnlyBool == kOSBooleanTrue) { dontLoad = true; } } if (dontLoad == true) { OSString *bundleID = OSDynamicCast(OSString, infoDict->getObject(kCFBundleIdentifierKey)); if (bundleID) { OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag, "Kext %s not loading.", bundleID->getCStringNoCopy()); } OSNumber *addressNum = OSDynamicCast(OSNumber, infoDict->getObject(kPrelinkExecutableLoadKey)); OSNumber *lengthNum = OSDynamicCast(OSNumber, infoDict->getObject(kPrelinkExecutableSizeKey)); if (addressNum && lengthNum) { #error Pick the right way to free prelinked data on this arch } infoDictArray->removeObject(i--); continue; } #endif /* NO_KEXTD */ /* Create the kext for the entry, then release it, because the * kext system keeps them around until explicitly removed. * Any creation/registration failures are already logged for us. */ OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict, (kaslrOffsets ? TRUE : FALSE)); OSSafeReleaseNULL(newKext); } /* slide kxld relocations */ if (kaslrOffsets && vm_kernel_slide > 0) { int slidKextAddrCount = 0; int badSlideAddr = 0; int badSlideTarget = 0; kaslrPackedOffsets * myOffsets = NULL; myOffsets = (kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy(); for (uint32_t j = 0; j < myOffsets->count; j++) { uint64_t slideOffset = (uint64_t) myOffsets->offsetsArray[j]; uintptr_t * slideAddr = (uintptr_t *) ((uint64_t)prelinkData + slideOffset); int slideAddrSegIndex = -1; int addrToSlideSegIndex = -1; slideAddrSegIndex = __whereIsAddr( (vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS ); if (slideAddrSegIndex >= 0) { addrToSlideSegIndex = __whereIsAddr( (vm_offset_t)(*slideAddr + vm_kernel_slide), &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS ); if (addrToSlideSegIndex < 0) { badSlideTarget++; continue; } } else { badSlideAddr++; continue; } slidKextAddrCount++; *(slideAddr) += vm_kernel_slide; } // for ... /* All kexts are now slid, set VM protections for them */ OSKext::setAllVMAttributes(); } /* Store the number of prelinked kexts in the registry so we can tell * when the system has been started from a prelinked kernel. */ registryRoot = IORegistryEntry::getRegistryRoot(); assert(registryRoot); prelinkCountObj = OSNumber::withNumber( (unsigned long long)infoDictArray->getCount(), 8 * sizeof(uint32_t)); assert(prelinkCountObj); if (prelinkCountObj) { registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj); } OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "%u prelinked kexts", infoDictArray->getCount()); #if CONFIG_KEXT_BASEMENT /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own * special VM region during OSKext init time, so we can free the whole * segment now. */ ml_static_mfree((vm_offset_t) prelinkData, prelinkLength); #endif /* __x86_64__ */ /* Free the prelink info segment, we're done with it. */ prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment); if (prelinkInfoSegment) { ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr, (vm_size_t)prelinkInfoSegment->vmsize); } finish: OSSafeReleaseNULL(errorString); OSSafeReleaseNULL(parsedXML); OSSafeReleaseNULL(theKernel); OSSafeReleaseNULL(prelinkCountObj); return; }
bool ACPIMonitor::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsWarningLog("ACPI device not ready"); return false; } if (OSDictionary *config = OSDynamicCast(OSDictionary, getProperty("Keys Associations"))) { // Temperatures if ((temperatures = OSDynamicCast(OSDictionary, config->getObject("Temperatures")))) { OSCollectionIterator *iterator = OSCollectionIterator::withCollection(temperatures); iterator->reset(); while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, temperatures->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy())) { if (!addSensor(key->getCStringNoCopy(), TYPE_SP78, TYPE_SPXX_SIZE, kFakeSMCTemperatureSensor, 0)) HWSensorsWarningLog("can't add temperature sensor for method %s with key %s", method->getCStringNoCopy(), key->getCStringNoCopy()); } }; //HWSensorsInfoLog("%d temperature sensor(s) added", count); } else return false; // Voltages if ((voltages = OSDynamicCast(OSDictionary, config->getObject("Voltages")))) { OSCollectionIterator *iterator = OSCollectionIterator::withCollection(voltages); iterator->reset(); while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, voltages->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy())) { if (!addSensor(key->getCStringNoCopy(), TYPE_FP4C, TYPE_FPXX_SIZE, kFakeSMCVoltageSensor, 0)) HWSensorsWarningLog("can't add voltage sensor for method %s with key %s", method->getCStringNoCopy(), key->getCStringNoCopy()); } }; //HWSensorsInfoLog("%d voltage sensor(s) added", count); } else return false; // Tachometers if ((tachometers = OSDynamicCast(OSDictionary, config->getObject("Tachometers")))) { UInt16 count = 0; OSArray* fanNames = OSDynamicCast(OSArray, getProperty("Fan Names")); OSCollectionIterator *iterator = OSCollectionIterator::withCollection(tachometers); iterator->reset(); while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, tachometers->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy())) { OSString* name = NULL; if (fanNames) name = OSDynamicCast(OSString, fanNames->getObject(count)); if (!addTachometer(count, name ? name->getCStringNoCopy() : 0)) HWSensorsWarningLog("Failed to register tachometer sensor %d", count); count++; } }; //HWSensorsInfoLog("%d tachometer sensor(s) added", count); } else return false; } registerService(); return true; }
bool ACPIProbe::start(IOService * provider) { ACPISensorsDebugLog("starting..."); if (!super::start(provider)) return false; if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) { ACPISensorsFatalLog("ACPI device not ready"); return false; } methods = OSArray::withCapacity(0); OSNumber *interval = NULL; OSNumber *timeout = NULL; OSBoolean *logging = NULL; OSArray *list = NULL; // Try to load configuration from info.plist first if (OSDictionary *configuration = getConfigurationNode()) { OSBoolean* disable = OSDynamicCast(OSBoolean, configuration->getObject("DisableDevice")); if (disable && disable->isTrue()) return false; interval = OSDynamicCast(OSNumber, configuration->getObject("PollingInterval")); timeout = OSDynamicCast(OSNumber, configuration->getObject("PollingTimeout")); logging = OSDynamicCast(OSBoolean, configuration->getObject("LoggingEnabled")); list = OSDynamicCast(OSArray, configuration->getObject("Methods")); } // Try to load configuration provided by ACPI device else { OSObject *object = NULL; if (kIOReturnSuccess == acpiDevice->evaluateObject("INVL", &object) && object) interval = OSDynamicCast(OSNumber, object); if (kIOReturnSuccess == acpiDevice->evaluateObject("TOUT", &object) && object) timeout = OSDynamicCast(OSNumber, object); if (kIOReturnSuccess == acpiDevice->evaluateObject("LOGG", &object) && object) { if (OSNumber *number = OSDynamicCast(OSNumber, object)) { logging = OSBoolean::withBoolean(number->unsigned8BitValue() == 1); } } if (kIOReturnSuccess == acpiDevice->evaluateObject("LIST", &object) && object) list = OSDynamicCast(OSArray, object); else ACPISensorsErrorLog("polling methods table (LIST) not found"); } if (interval) { pollingInterval = (double)interval->unsigned64BitValue() / (double)1000.0; ACPISensorsInfoLog("polling interval %lld ms", interval->unsigned64BitValue()); if (pollingInterval) { if (timeout) { pollingTimeout = (double)timeout->unsigned64BitValue() / 1000.0; ACPISensorsInfoLog("polling timeout %lld ms", timeout->unsigned64BitValue()); } if (logging) { loggingEnabled = logging->isTrue(); ACPISensorsInfoLog("logging %s", loggingEnabled ? "enabled" : "disabled"); } if (list) { for (unsigned int i = 0; i < list->getCount(); i++) { if (OSString *method = OSDynamicCast(OSString, list->getObject(i))) { if (method->getLength() && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { methods->setObject(method); ACPISensorsInfoLog("method \"%s\" registered", method->getCStringNoCopy()); } else ACPISensorsErrorLog("unable to register method \"%s\"", method->getCStringNoCopy()); } } } } else ACPISensorsWarningLog("polling interval is set to zero, driver will be disabled"); } //REVIEW_REHABMAN: just bail if no methods to call... no need to stick around... if (!methods->getCount()) return false; if (methods->getCount()) { // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ACPIProbe::woorkloopTimerEvent)))) { ACPISensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { ACPISensorsFatalLog("failed to add timer event source into workloop"); return false; } timerEventSource->setTimeoutMS(100); //ACPISensorsInfoLog("%d method%s registered", methods->getCount(), methods->getCount() > 1 ? "s" : ""); } registerService(); ACPISensorsInfoLog("started"); return true; }
/********************************************************************* * 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; }
/********************************************************************* * 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; }
void KLDBootstrap::readBuiltinPersonalities(void) { OSObject * parsedXML = NULL; // must release OSArray * builtinExtensions = NULL; // do not release OSArray * allPersonalities = NULL; // must release OSString * errorString = NULL; // must release kernel_section_t * infosect = NULL; // do not free OSCollectionIterator * personalitiesIterator = NULL; // must release unsigned int count, i; OSKextLog(/* kext */ NULL, kOSKextLogStepLevel | kOSKextLogLoadFlag, "Reading built-in kernel personalities for I/O Kit drivers."); /* Look in the __BUILTIN __info segment for an array of Info.plist * entries. For each one, extract the personalities dictionary, add * it to our array, then push them all (without matching) to * the IOCatalogue. This can be used to augment the personalities * in gIOKernelConfigTables, especially when linking entire kexts into * the mach_kernel image. */ infosect = getsectbyname("__BUILTIN", "__info"); if (!infosect) { // this isn't fatal goto finish; } parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr, &errorString); if (parsedXML) { builtinExtensions = OSDynamicCast(OSArray, parsedXML); } if (!builtinExtensions) { const char * errorCString = "(unknown error)"; if (errorString && errorString->getCStringNoCopy()) { errorCString = errorString->getCStringNoCopy(); } else if (parsedXML) { errorCString = "not an array"; } OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogLoadFlag, "Error unserializing built-in personalities: %s.", errorCString); goto finish; } // estimate 3 personalities per Info.plist/kext count = builtinExtensions->getCount(); allPersonalities = OSArray::withCapacity(count * 3); for (i = 0; i < count; i++) { OSDictionary * infoDict = NULL; // do not release OSString * moduleName = NULL; // do not release OSDictionary * personalities; // do not release OSString * personalityName; // do not release OSSafeReleaseNULL(personalitiesIterator); infoDict = OSDynamicCast(OSDictionary, builtinExtensions->getObject(i)); if (!infoDict) { continue; } moduleName = OSDynamicCast(OSString, infoDict->getObject(kCFBundleIdentifierKey)); if (!moduleName) { continue; } OSKextLog(/* kext */ NULL, kOSKextLogStepLevel | kOSKextLogLoadFlag, "Adding personalities for built-in driver %s:", moduleName->getCStringNoCopy()); personalities = OSDynamicCast(OSDictionary, infoDict->getObject("IOKitPersonalities")); if (!personalities) { continue; } personalitiesIterator = OSCollectionIterator::withCollection(personalities); if (!personalitiesIterator) { continue; // xxx - well really, what can we do? should we panic? } while ((personalityName = OSDynamicCast(OSString, personalitiesIterator->getNextObject()))) { OSDictionary * personality = OSDynamicCast(OSDictionary, personalities->getObject(personalityName)); OSKextLog(/* kext */ NULL, kOSKextLogDetailLevel | kOSKextLogLoadFlag, "Adding built-in driver personality %s.", personalityName->getCStringNoCopy()); if (personality && !personality->getObject(kCFBundleIdentifierKey)) { personality->setObject(kCFBundleIdentifierKey, moduleName); } allPersonalities->setObject(personality); } } gIOCatalogue->addDrivers(allPersonalities, false); finish: OSSafeReleaseNULL(parsedXML); OSSafeReleaseNULL(allPersonalities); OSSafeReleaseNULL(errorString); OSSafeReleaseNULL(personalitiesIterator); return; }
bool ACPIMonitor::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; char key[5]; //Here is Fan in ACPI OSArray* fanNames = OSDynamicCast(OSArray, getProperty("FanNames")); for (int i=0; i<10; i++) { snprintf(key, 5, "FAN%X", i); if (kIOReturnSuccess == acpiDevice->validateObject(key)) { OSString* name = NULL; if (fanNames ) name = OSDynamicCast(OSString, fanNames->getObject(i)); if (!addTachometer(key, name ? name->getCStringNoCopy() : 0)) WarningLog("Can't add tachometer sensor, key %s", key); } else { snprintf(key, 5, "FTN%X", i); if (kIOReturnSuccess == acpiDevice->validateObject(key)) { OSString* name = NULL; if (fanNames ) name = OSDynamicCast(OSString, fanNames->getObject(i)); if (!addTachometer(key, name ? name->getCStringNoCopy() : 0)) WarningLog("Can't add tachometer sensor, key %s", key); } else break; } } //Next step - temperature keys if (kIOReturnSuccess == acpiDevice->validateObject("TCPU")) addSensor("TCPU", KEY_CPU_HEATSINK_TEMPERATURE, TYPE_SP78, 2); if (kIOReturnSuccess == acpiDevice->validateObject("TSYS")) addSensor("TSYS", KEY_NORTHBRIDGE_TEMPERATURE, TYPE_SP78, 2); if (kIOReturnSuccess == acpiDevice->validateObject("TDIM")) addSensor("TDIM", KEY_DIMM_TEMPERATURE, TYPE_SP78, 2); if (kIOReturnSuccess == acpiDevice->validateObject("TAMB")) addSensor("TAMB", KEY_AMBIENT_TEMPERATURE, TYPE_SP78, 2); if (kIOReturnSuccess == acpiDevice->validateObject("TCPP")) addSensor("TCPP", KEY_CPU_PROXIMITY_TEMPERATURE, TYPE_SP78, 2); // We should add also GPU reading stuff for those who has no supported plug in but have the value on EC registers //Voltage if (kIOReturnSuccess == acpiDevice->validateObject("VCPU")) addSensor("VSN0", KEY_CPU_VOLTAGE, TYPE_FP2E, 2); if (kIOReturnSuccess == acpiDevice->validateObject("VMEM")) addSensor("VSN0", KEY_MEMORY_VOLTAGE, TYPE_FP2E, 2); if (kIOReturnSuccess == acpiDevice->validateObject("VSN1")) addSensor("VSN1", "Vp0C", TYPE_FP2E, 2); if (kIOReturnSuccess == acpiDevice->validateObject("VSN2")) addSensor("VSN2", "Vp1C", TYPE_FP2E, 2); if (kIOReturnSuccess == acpiDevice->validateObject("VSN3")) addSensor("VSN3", "Vp2C", TYPE_FP2E, 2); //Amperage if (kIOReturnSuccess == acpiDevice->validateObject("ISN0")) addSensor("ISN0", "ICAC", TYPE_UI16, 2); if (kIOReturnSuccess == acpiDevice->validateObject("ISN1")) addSensor("ISN1", "Ip0C", TYPE_UI16, 2); if (kIOReturnSuccess == acpiDevice->validateObject("ISN2")) addSensor("ISN2", "Ip1C", TYPE_UI16, 2); if (kIOReturnSuccess == acpiDevice->validateObject("ISN3")) addSensor("ISN3", "Ip2C", TYPE_UI16, 2); //Power if (kIOReturnSuccess == acpiDevice->validateObject("PSN0")) addSensor("PSN0", "PC0C", TYPE_UI16, 2); if (kIOReturnSuccess == acpiDevice->validateObject("PSN1")) addSensor("PSN1", "PC1C", TYPE_UI16, 2); // AC Power/Battery if (kIOReturnSuccess == acpiDevice->validateObject("ACDC")) // Power Source Read AC/Battery { addSensor("ACDC", "ACEN", TYPE_UI8, 1); addSensor("ACDC", "ACFP", TYPE_FLAG, 1); addSensor("ACDC", "ACIN", TYPE_FLAG, 1); } // TODO real SMC returns ACID only when AC is plugged, if not is zeroed, so hardcoding it in plist is not OK IMHO // Same goes for ACIC, but no idea how we can get the AC current value.. // Here if ACDC returns 0 we need to set the on battery BATP flag // Battery stuff, need to implement rest of the keys once i figure those if (kIOReturnSuccess == acpiDevice->validateObject("BAK0")) // Battery 0 Current addSensor("BAK0", "B0AC", TYPE_SI16, 2); if (kIOReturnSuccess == acpiDevice->validateObject("BAK1")) // Battery 0 Voltage addSensor("BAK1", "B0AV", TYPE_UI16, 2); //Keys from info.plist OSString *tmpString = 0; OSData *tmpObj = 0; // UInt32 tmpUI32; // char tmpCString[7]; char acpiName[5]; char aKey[5]; OSIterator *iter = 0; const OSSymbol *dictKey = 0; OSDictionary *keysToAdd = 0; keysToAdd = OSDynamicCast(OSDictionary, getProperty("keysToAdd")); if (keysToAdd) { iter = OSCollectionIterator::withCollection(keysToAdd); if (iter) { while ((dictKey = (const OSSymbol *)iter->getNextObject())) { tmpObj = 0; snprintf(acpiName, 5, "%s", dictKey->getCStringNoCopy()); //WarningLog(" Found key %s", acpiName); tmpString = OSDynamicCast(OSString, keysToAdd->getObject(dictKey)); if (tmpString) { snprintf(aKey, 5, "%s", tmpString->getCStringNoCopy()); InfoLog("Custom name=%s key=%s", acpiName, aKey); if (kIOReturnSuccess == acpiDevice->validateObject(acpiName)) { if (aKey[0] == 'F') { if (!addTachometer(aKey, acpiName)) WarningLog("Can't add tachometer sensor, key %s", aKey); } else { addSensor(acpiName, aKey, TYPE_UI16, 2); } } } else { WarningLog(" no value for key %s", acpiName); } } iter->release(); } else { WarningLog(" can't interate keysToAdd"); } } else { WarningLog(" keysToAdd not found"); } registerService(0); 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); }
//============================================================================== // USB Stuff (Mainly...) //============================================================================== bool com_milvich_driver_Thrustmaster::init(OSDictionary *properties) { IOLog("%s: init\n", NAME); if(!super::init(properties)) { return false; } fIface = NULL; fPipe = NULL; fBuffer = NULL; fOutstandingIOOps = 0; fNeedToClose = false; fFinishedInit = false; for(unsigned int i = 0; i < sizeof(fControlData); i++) { fControlData[i] = 0; } OSBoolean *result; int count; // create the buffer for the reports fReport = IOBufferMemoryDescriptor::withCapacity(kReportSize, kIODirectionOutIn, true); if(!fReport) { IOLog("%s: Failed to create the MemoryDescriptor for our report\n", NAME); return false; } // I need to know this info to create the device descriptor, but I can't // dynamicly look this up until I finish initing the iMate, but that blocks... // So we be stupid and just read from a config file. fHasRudders = false; fHasThrottle = true; result = OSDynamicCast(OSBoolean, getProperty("HasRudder")); if(result) { fHasRudders = result->getValue(); } result = OSDynamicCast(OSBoolean, getProperty("HasThrottle")); if(result) { fHasThrottle = result->getValue(); } // check to see if the rocker switch should act as a modifier if(fHasThrottle) { result = OSDynamicCast(OSBoolean, getProperty("RockerIsModifier")); if(!result) { IOLog("%s: Failed to find an entry for RockerIsModifier, assuming false.\n", NAME); fRockerIsModifier = false; } else { fRockerIsModifier = result->getValue(); } } else { fRockerIsModifier = false; } // setup buttons if(fHasThrottle) { count = kNumOfButtons; } else { count = kNumOfFCSButtons; } OSArray *buttonArray = OSDynamicCast(OSArray, getProperty("Buttons")); if(fRockerIsModifier && buttonArray) { for(int i = 0; i < count; i++) { result = OSDynamicCast(OSBoolean, buttonArray->getObject(i)); if(result && result->getValue()) { for(int j = 0; j < kNumModifiers; j++) { fButtonShifts[i * kNumModifiers + j] = fNumButtons; fNumButtons++; } } else { for(int j = 0; j < kNumModifiers; j++) { fButtonShifts[i * kNumModifiers + j] = fNumButtons; } fNumButtons++; } } } else { // the buttons and hatswitchs are not shifted, so set all 3 shift values // to the same thing fNumButtons = 0; for(int i = 0; i < count; i++) { for(int j = 0; j < kNumModifiers; j++) { fButtonShifts[i * kNumModifiers + j] = fNumButtons; } fNumButtons++; } // same thing with the hat switch } result = OSDynamicCast(OSBoolean, getProperty("ModifierEffectsHat")); fHatIsModified = result && result->getValue(); if(fHatIsModified && fRockerIsModifier) { fHatSwitchShifts[0] = 0; fHatSwitchShifts[1] = 1; fHatSwitchShifts[2] = 2; } else { fHatSwitchShifts[0] = fHatSwitchShifts[1] = fHatSwitchShifts[2] = 0; fHatIsModified = false; } result = OSDynamicCast(OSBoolean, getProperty("TwistRudder")); fTwistRudder = result && result->getValue(); return true; }
bool PTIDSensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } // Update timers temperaturesLastUpdated = ptimer_read() - NSEC_PER_SEC; tachometersLastUpdated = temperaturesLastUpdated; acpiDevice->evaluateInteger("IVER", &version); if (version == 0) { OSString *name = OSDynamicCast(OSString, provider->getProperty("name")); if (name && name->isEqualTo("INT3F0D")) version = 0x30000; else return false; } setProperty("version", version, 64); // Parse sensors switch (version) { case 0x30000: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TSDL", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); HWSensorsDebugLog("Parsing temperatures..."); for (UInt32 index = 1; index < description->getCount(); index += 2) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), (index - 1) / 2); } } else HWSensorsErrorLog("failed to evaluate TSDL table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDL", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); HWSensorsDebugLog("Parsing tachometers..."); for (UInt32 index = 2; index < description->getCount(); index += 3) { parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), (index - 2) / 3); } } else HWSensorsErrorLog("failed to evaluate OSDL table"); break; } case 0x20001: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TMPV", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); for (UInt32 index = 1; index < description->getCount(); index += 3) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), index + 1); } } else HWSensorsErrorLog("failed to evaluate TMPV table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDV", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); for (UInt32 index = 2; index < description->getCount(); index += 4) { parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), index + 1); } } else HWSensorsErrorLog("failed to evaluate OSDV table"); break; } default: HWSensorsFatalLog("usupported interface version: 0x%x", (unsigned int)version); return false; } registerService(); HWSensorsInfoLog("started"); return true; }
bool createPStateTable(PState* pS, unsigned int* numStates) { checkForPenryn(); // early on, so we can display proper mV values /* If the PState table was specified manually, we dont do the rest. Otherwise autodetect */ if (NumberOfPStates != 0) { dbg("PState table was already created. No autodetection will be performed\n"); return true; } /* Find CPUs in the IODeviceTree plane */ IORegistryEntry* ioreg = IORegistryEntry::fromPath("/cpus", IORegistryEntry::getPlane("IODeviceTree")); if (ioreg == 0) { warn("Holy moly we cannot find your CPU!\n"); return false; } /* Get the first CPU - we assume all CPUs share the same P-State */ IOACPIPlatformDevice* cpu = (IOACPIPlatformDevice*) ioreg->getChildEntry(IORegistryEntry::getPlane("IODeviceTree")); if (cpu == 0) { warn("Um you don't seem to have a CPU o.O\n"); ioreg = 0; return false; } dbg("Using data from %s\n", cpu->getName()); /* Now try to find the performance state table */ OSObject* PSS; cpu->evaluateObject("_PSS", &PSS); if(PSS == 0 ) { warn("Auto-creating a PState table.\n"); int maxFID = MHz_to_FID(getCurrentFrequency()); int maxVID = mV_to_VID(getCurrentVoltage()); int minVID = mV_to_VID(800); // For now we'll use hardcoded minvolt, later use table int minFID = 6; // No LFM right now NumberOfPStates = 1 + ((maxFID - minFID) / 2); for (int i = 1; i < NumberOfPStates; i++) { PStates[i].Frequency = minFID + (2*(NumberOfPStates - i - 1)); PStates[i].AcpiFreq = FID_to_MHz(PStates[i].Frequency); PStates[i].OriginalVoltage = maxVID - (i*((maxVID - minVID) / NumberOfPStates)) ; PStates[i].Voltage = PStates[i].OriginalVoltage; PStates[i].Latency = 110; PStates[i].TimesChosen = 0; } PStates[0].Frequency = maxFID; PStates[0].AcpiFreq = FID_to_MHz(maxFID); PStates[0].OriginalVoltage = maxVID; PStates[0].Voltage = PStates[0].OriginalVoltage; PStates[0].Latency = 110; PStates[0].TimesChosen = 0; MaxLatency = PStates[0].Latency; info("Using %d PStates (auto-created, may not be optimal).\n", NumberOfPStates); ioreg = 0; cpu = 0; return true; } OSArray* PSSArray = (OSArray*) PSS; NumberOfPStates = PSSArray->getCount(); info("Found %d P-States\n", NumberOfPStates); OSArray* onestate; uint16_t ctl, acpifreq; uint32_t power, latency; int i = 0, c = 0; while (c < PSSArray->getCount()) { onestate = ( OSArray* )(PSSArray->getObject(c)); ctl = ((OSNumber*) onestate->getObject(4))->unsigned32BitValue(); acpifreq = ((OSNumber*) onestate->getObject(0))->unsigned32BitValue(); power = ((OSNumber*) onestate->getObject(1))->unsigned32BitValue(); latency = ((OSNumber*) onestate->getObject(2))->unsigned32BitValue(); c++; info("clt: 0x%x , vid: %d , fid: %d \n", ctl , VID(ctl), FID(ctl) ); if (acpifreq - (10 * (acpifreq / 10)) == 1) { // most likely spurious, so skip it warn("** Spurious P-State %d: %d MHz at %d mV, consuming %d W, latency %d usec\n", i, acpifreq, VID_to_mV(ctl), power / 1000, latency); NumberOfPStates--; continue; } if (acpifreq < 1000 && !Below1Ghz) { warn("%d MHz disabled because your processor or kernel doesn't support it.\n",acpifreq); NumberOfPStates--; continue; } PStates[i].AcpiFreq = acpifreq; // cosmetic only PStates[i].Frequency = FID(ctl); PStates[i].OriginalVoltage = VID(ctl); PStates[i].Voltage = PStates[i].OriginalVoltage *50 / 100; // initially same PStates[i].Latency = latency; PStates[i].TimesChosen = 0; if (latency > MaxLatency) MaxLatency = latency; info("Auto: P-State %d: %d MHz at %d mV VID: %d, consuming %d W, latency %d usec\n", i, PStates[i].AcpiFreq, VID_to_mV(PStates[i].Voltage),PStates[i].Voltage, power / 1000, latency); i++; } info("Using %d PStates.\n", NumberOfPStates); ioreg = 0; cpu = 0; PSS = 0; onestate = 0; return true; }