void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller) { OSData * data; IORegistryEntry * entry; OSString * string = 0; uuid_string_t uuid; entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane ); if ( entry ) { data = OSDynamicCast( OSData, entry->getProperty( "system-id" ) ); if ( data && data->getLength( ) == 16 ) { SHA1_CTX context; uint8_t digest[ SHA_DIGEST_LENGTH ]; const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC }; SHA1Init( &context ); SHA1Update( &context, space, sizeof( space ) ); SHA1Update( &context, data->getBytesNoCopy( ), data->getLength( ) ); SHA1Final( digest, &context ); digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50; digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80; uuid_unparse( digest, uuid ); string = OSString::withCString( uuid ); } entry->release( ); } if ( string == 0 ) { entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); if ( entry ) { data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ) ); if ( data && data->getLength( ) == sizeof( uuid_t ) ) { uuid_unparse( ( uint8_t * ) data->getBytesNoCopy( ), uuid ); string = OSString::withCString( uuid ); } entry->release( ); } } if ( string ) { getProvider( )->setProperty( kIOPlatformUUIDKey, string ); publishResource( kIOPlatformUUIDKey, string ); string->release( ); } publishResource("IONVRAM"); }
OSReturn NoSleepExtension::writeNVRAM(UInt8 value) { #ifdef DEBUG IOLog("%s: writing nvram, value: 0x%02x\n", getName(), value); #endif bool ret; IORegistryEntry *entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); if ( entry ) { OSData *dataToSave = OSData::withBytes(&value, 1); ret = entry->setProperty(IORegistrySleepSuppressionMode, dataToSave); dataToSave->release(); entry->release(); #ifdef DEBUG IOLog("%s: writing nvram, result: %s\n", getName(), ret?"true":"false"); #endif } else { return kOSReturnError; } return ret?kOSReturnSuccess:kOSReturnError; }
/****************************************************************************** * CodecCommander::parseCodecPowerState - get codec power state from IOReg ******************************************************************************/ void CodecCommander::parseCodecPowerState() { // monitor power state of hda audio codec IORegistryEntry *hdaDriverEntry = IORegistryEntry::fromPath(hdaDriverPath); if (hdaDriverEntry != NULL) { OSNumber *powerState = OSDynamicCast(OSNumber, hdaDriverEntry->getProperty("IOAudioPowerState")); if (powerState != NULL) { hdaCurrentPowerState = powerState->unsigned8BitValue(); // if hda codec changed power state if (hdaCurrentPowerState != hdaPrevPowerState) { // store current power state as previous state for next workloop cycle hdaPrevPowerState = hdaCurrentPowerState; // notify about codec power loss state if (hdaCurrentPowerState == 0x0) { DEBUG_LOG("CodecCommander: cc: --> hda codec lost power\n"); eapdPoweredDown = true; coldBoot = false; //codec entered fugue state or sleep - no longer a cold boot updateCount = 0; } } } else { DEBUG_LOG("CodecCommander: IOAudioPowerState unknown\n"); return; } } else { DEBUG_LOG("CodecCommander: %s is unreachable\n", hdaDriverPath); return; } hdaDriverEntry->release(); }
void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) { #if 1 NOREF(pDevExt); NOREF(pImage); #else /* * Try store the image load address in NVRAM so we can retrived it on panic. * Note! This only works if you're root! - Acutally, it doesn't work at all at the moment. FIXME! */ IORegistryEntry *pEntry = IORegistryEntry::fromPath("/options", gIODTPlane); if (pEntry) { char szVar[80]; RTStrPrintf(szVar, sizeof(szVar), "vboximage"/*-%s*/, pImage->szName); char szValue[48]; RTStrPrintf(szValue, sizeof(szValue), "%#llx,%#llx", (uint64_t)(uintptr_t)pImage->pvImage, (uint64_t)(uintptr_t)pImage->pvImage + pImage->cbImageBits - 1); bool fRc = pEntry->setProperty(szVar, szValue); NOREF(fRc); pEntry->release(); SUPR0Printf("fRc=%d '%s'='%s'\n", fRc, szVar, szValue); } /*else SUPR0Printf("failed to find /options in gIODTPlane\n");*/ #endif }
/****************************************************************************** * CodecCommander::parseAudioEngineState - repeats the action when timer fires ******************************************************************************/ void CodecCommander::parseAudioEngineState() { IORegistryEntry *hdaEngineOutputEntry = IORegistryEntry::fromPath(engineOutputPath); if (hdaEngineOutputEntry != NULL) { OSNumber *state = OSDynamicCast(OSNumber, hdaEngineOutputEntry->getProperty("IOAudioEngineState")); if (state != NULL) { hdaEngineState = state->unsigned8BitValue(); //DEBUG_LOG("CodecCommander: EngineOutput power state %d\n", hdaEngineState); if (hdaEngineState == 0x1) DEBUG_LOG("CodecCommander: cc: --> audio stream active\n"); //else //DEBUG_LOG("CodecCommander: cc: --> audio stream inactive\n"); // will produce spam in console } else { DEBUG_LOG("CodecCommander: IOAudioEngineState unknown\n"); return; } } else { DEBUG_LOG("CodecCommander: %s is unreachable\n", engineOutputPath); return; } hdaEngineOutputEntry->release(); }
inline static int init_gIOOptionsEntry(void) { IORegistryEntry *entry; void *nvram_entry; volatile void **options; int ret = -1; if (gIOOptionsEntry) return 0; entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); if (!entry) return -1; nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry); if (!nvram_entry) goto release; options = (volatile void **) &gIOOptionsEntry; if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) { ret = 0; goto release; } return 0; release: entry->release(); return ret; }
bool IOPlatformExpert::start( IOService * provider ) { IORangeAllocator * physicalRanges; OSData * busFrequency; if (!super::start(provider)) return false; // Register the presence or lack thereof a system // PCI address mapper with the IOMapper class #if 1 IORegistryEntry * regEntry = IORegistryEntry::fromPath("/u3/dart", gIODTPlane); if (!regEntry) regEntry = IORegistryEntry::fromPath("/dart", gIODTPlane); if (regEntry) { int debugFlags; if (!PE_parse_boot_arg("dart", &debugFlags) || debugFlags) setProperty(kIOPlatformMapperPresentKey, kOSBooleanTrue); regEntry->release(); } #endif IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey)); gIOInterruptControllers = OSDictionary::withCapacity(1); gIOInterruptControllersLock = IOLockAlloc(); // Correct the bus frequency in the device tree. busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4); provider->setProperty("clock-frequency", busFrequency); busFrequency->release(); gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController"); physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16, IORangeAllocator::kLocking); assert(physicalRanges); setProperty("Platform Memory Ranges", physicalRanges); setPlatform( this ); gIOPlatform = this; PMInstantiatePowerDomains(); // Parse the serial-number data and publish a user-readable string OSData* mydata = (OSData*) (provider->getProperty("serial-number")); if (mydata != NULL) { OSString *serNoString = createSystemSerialNumberString(mydata); if (serNoString != NULL) { provider->setProperty(kIOPlatformSerialNumberKey, serNoString); serNoString->release(); } } return( configure(provider) ); }
void IORecordProgressBackbuffer(void * buffer, size_t size, uint32_t theme) { IORegistryEntry * chosen; if ((chosen = IORegistryEntry::fromPath(kIODeviceTreePlane ":/chosen"))) { chosen->setProperty(kIOProgressBackbufferKey, buffer, size); chosen->setProperty(kIOProgressColorThemeKey, theme, 32); chosen->release(); } }
IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties ) { OSDictionary * dictionary; OSObject * object; IOReturn status; status = super::setProperties( properties ); if ( status != kIOReturnUnsupported ) return status; status = IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator ); if ( status != kIOReturnSuccess ) return status; dictionary = OSDynamicCast( OSDictionary, properties ); if ( dictionary == 0 ) return kIOReturnBadArgument; object = dictionary->getObject( kIOPlatformUUIDKey ); if ( object ) { IORegistryEntry * entry; OSString * string; uuid_t uuid; string = ( OSString * ) getProperty( kIOPlatformUUIDKey ); if ( string ) return kIOReturnNotPermitted; string = OSDynamicCast( OSString, object ); if ( string == 0 ) return kIOReturnBadArgument; status = uuid_parse( string->getCStringNoCopy( ), uuid ); if ( status != 0 ) return kIOReturnBadArgument; entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); if ( entry ) { entry->setProperty( "platform-uuid", uuid, sizeof( uuid_t ) ); entry->release( ); } setProperty( kIOPlatformUUIDKey, string ); publishResource( kIOPlatformUUIDKey, string ); return kIOReturnSuccess; } return kIOReturnUnsupported; }
UInt32 ACPIBacklightPanel::loadFromNVRAM(void) { DbgLog("%s::%s()\n", this->getName(),__FUNCTION__); IORegistryEntry* nvram = IORegistryEntry::fromPath("/chosen/nvram", gIODTPlane); if (!nvram) { DbgLog("%s: no /chosen/nvram, trying IODTNVRAM\n", this->getName()); // probably booting w/ Clover if (OSDictionary* matching = serviceMatching("IODTNVRAM")) { nvram = waitForMatchingService(matching, 1000000000ULL * 15); matching->release(); } } else DbgLog("%s: have nvram from /chosen/nvram\n", this->getName()); UInt32 val = -1; if (nvram) { // need to serialize as getProperty on nvram does not work if (OSSerialize* serial = OSSerialize::withCapacity(0)) { nvram->serializeProperties(serial); if (OSDictionary* props = OSDynamicCast(OSDictionary, OSUnserializeXML(serial->text()))) { if (OSData* number = OSDynamicCast(OSData, props->getObject(kACPIBacklightLevel))) { val = 0; unsigned l = number->getLength(); if (l <= sizeof(val)) memcpy(&val, number->getBytesNoCopy(), l); DbgLog("%s: read level from nvram = %d\n", this->getName(), val); //number->release(); } else DbgLog("%s: no acpi-backlight-level in nvram\n", this->getName()); props->release(); } serial->release(); } nvram->release(); } return val; }
OSReturn NoSleepExtension::readNVRAM(UInt8 *value) { #ifdef DEBUG IOLog("%s[%p]::%s(%p)\n", getName(), this, __FUNCTION__, value); #endif OSReturn ret = kOSReturnError; IORegistryEntry *entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); if ( entry ) { OSObject *rawValue = entry->getProperty(IORegistrySleepSuppressionMode); if(rawValue != NULL) { #ifdef DEBUG IOLog("%s: rawValueClassName: %s\n", getName(), rawValue->getMetaClass()->getClassName()); #endif OSData *data = OSDynamicCast(OSData, rawValue); if(data->getLength() == 1) { *value = ((UInt8 *)data->getBytesNoCopy())[0]; ret = kOSReturnSuccess; #ifdef DEBUG IOLog("%s: reading nvram, value: 0x%02x\n", getName(), (*value)); #endif } #ifdef DEBUG else { IOLog("%s: read error: data->Len %s 1\n", getName(), (data->getLength() == 1)?"==":"!="); } #endif } entry->release(); } return ret; }
/****************************************************************************** * CodecCommander::parseCodecPowerState - get codec power state from IOReg ******************************************************************************/ void CodecCommander::parseCodecPowerState() { // monitor power state of hda audio codec IORegistryEntry *hdaDriverEntry = IORegistryEntry::fromPath(mConfiguration->getHDADriverPath()); if (hdaDriverEntry != NULL) { OSNumber *powerState = OSDynamicCast(OSNumber, hdaDriverEntry->getProperty("IOAudioPowerState")); if (powerState != NULL) { hdaCurrentPowerState = powerState->unsigned8BitValue(); // if hda codec changed power state if (hdaCurrentPowerState != hdaPrevPowerState) { DEBUG_LOG("CodecCommander: cc - power state transition from %d to %d recorded\n", hdaPrevPowerState, hdaCurrentPowerState); // store current power state as previous state for next workloop cycle hdaPrevPowerState = hdaCurrentPowerState; // notify about codec power loss state if (hdaCurrentPowerState == 0x0) { DEBUG_LOG("CodecCommander: HDA codec lost power\n"); handleStateChange(kStateSleep); // power down EAPDs properly eapdPoweredDown = true; coldBoot = false; //codec entered fugue state or sleep - no longer a cold boot } } } else DEBUG_LOG("CodecCommander: IOAudioPowerState unknown\n"); hdaDriverEntry->release(); } else DEBUG_LOG("CodecCommander: %s is unreachable\n", mConfiguration->getHDADriverPath()); }
/****************************************************************************** * CodecCommander::start - start kernel extension and init PM ******************************************************************************/ bool CodecCommander::start(IOService *provider) { DEBUG_LOG("CodecCommander: cc: commander version 2.1.1 starting\n"); if(!provider || !super::start( provider )) { DEBUG_LOG("CodecCommander: cc: error loading kext\n"); return false; } // notify about extra feature requests if (generatePop && checkInfinite) { DEBUG_LOG("CodecCommander: cc: stream requested, will *pop* upon wake or fugue-wake\n"); } if (checkInfinite) { DEBUG_LOG("CodecCommander: cc: infinite workloop requested, will start now!\n"); } if (generatePop && !checkInfinite) { DEBUG_LOG("CodecCommander: cc: stream requested, will *pop* upon wake\n"); } // start virtual keyboard device _keyboardDevice = new CCHIDKeyboardDevice; if ( !_keyboardDevice || !_keyboardDevice->init() || !_keyboardDevice->attach(this) ) { _keyboardDevice->release(); DEBUG_LOG("CodecCommander: hi: unable to create keyboard device\n"); } else { DEBUG_LOG("CodecCommander: hi: keyboard device created\n"); _keyboardDevice->registerService(); } // determine HDEF ACPI device path in IORegistry IORegistryEntry *hdaDeviceEntry = IORegistryEntry::fromPath(hdaDevicePath); if (hdaDeviceEntry != NULL) { IOService *service = OSDynamicCast(IOService, hdaDeviceEntry); // get address field from IODeviceMemory if (service != NULL && service->getDeviceMemoryCount() != 0) { ioregEntry = service->getDeviceMemoryWithIndex(0); } hdaDeviceEntry->release(); } else { DEBUG_LOG("CodecCommander: %s is unreachable\n",hdaDevicePath); return false; } // init power state management & set state as PowerOn PMinit(); registerPowerDriver(this, powerStateArray, kPowerStateCount); provider->joinPMtree(this); // setup workloop and timer fWorkLoop = IOWorkLoop::workLoop(); fTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &CodecCommander::onTimerAction)); if (!fWorkLoop || !fTimer) stop(provider);; if (fWorkLoop->addEventSource(fTimer) != kIOReturnSuccess) stop(provider); this->registerService(0); return true; }
OSSet * AppleNForceATARoot::createATAChannels( void ) { OSSet * nubSet; OSDictionary * channelInfo; IORegistryEntry * dtEntry; char* debugInfo; do { nubSet = OSSet::withCapacity(2); if (nubSet == 0) break; if (fProvider->open(this) != true) break; for ( UInt32 channelID = 0; channelID < 2; channelID++ ) { // Create a dictionary for the channel info. Use native mode // settings if possible, else default to legacy mode. debugInfo = "native"; channelInfo = createNativeModeChannelInfo( channelID ); if (channelInfo == 0) { debugInfo = "legacy"; channelInfo = createLegacyModeChannelInfo( channelID ); } if (channelInfo == 0) continue; DEBUG_LOG( "%s::%s() [this=%p] created channel %d in %s mode.\n", getName(), __FUNCTION__, this, (int)channelID, debugInfo ); // Create a nub for each ATA channel. AppleNForceATAChannel * nub = new AppleNForceATAChannel; if ( nub ) { dtEntry = getDTChannelEntry( channelID ); // Invoke special init method in channel nub. if (nub->init( this, channelInfo, dtEntry ) && nub->attach( this )) { nubSet->setObject( nub ); } if ( dtEntry ) { dtEntry->release(); } else { // Platform did not create a device tree entry for // this ATA channel. Do it here. char channelName[5] = {'C','H','N','_','\0'}; channelName[3] = '0' + channelID; nub->setName( channelName ); if (fProvider->inPlane(gIODTPlane)) { nub->attachToParent( fProvider, gIODTPlane ); } } nub->release(); } channelInfo->release(); } fProvider->close( this ); } while ( false ); // Release and invalidate an empty set. if (nubSet && (nubSet->getCount() == 0)) { nubSet->release(); nubSet = 0; } return nubSet; }
OSSet * AppleIntelPIIXATARoot::createATAChannelNubs( void ) { OSSet * nubSet; OSDictionary * channelInfo; IORegistryEntry * dtEntry; UInt32 priChannelMode; UInt32 secChannelMode; UInt8 mapValue = 0; do { nubSet = OSSet::withCapacity(2); if ( nubSet == 0 ) break; if ( _provider->open( this ) != true ) break; priChannelMode = kChannelModePATA; secChannelMode = kChannelModePATA; // Determine SATA channel mode based on Port Mapping Register. if ( getProperty( kSerialATAKey ) == kOSBooleanTrue ) { OSString * hwName; hwName = OSDynamicCast(OSString, getProperty(kControllerNameKey)); mapValue = _provider->configRead8(kPIIX_PCI_MAP); setProperty( kPortMappingKey, mapValue, 8 ); priChannelMode = kChannelModeDisabled; secChannelMode = kChannelModeDisabled; if (hwName) { if (hwName->isEqualTo("ICH7-M SATA")) { mapValue &= 0x3; priChannelMode = gICH7MChannelModeMap[mapValue][0]; secChannelMode = gICH7MChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH6 SATA") || hwName->isEqualTo("ESB2 SATA")) { mapValue &= 0x3; priChannelMode = gICH6ChannelModeMap[mapValue][0]; secChannelMode = gICH6ChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH6-M SATA")) { mapValue &= 0x3; priChannelMode = gICH6MChannelModeMap[mapValue][0]; secChannelMode = gICH6MChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH5 SATA")) { mapValue &= 0x7; priChannelMode = gICH5ChannelModeMap[mapValue][0]; secChannelMode = gICH5ChannelModeMap[mapValue][1]; } else /* if (hwName->isEqualTo("ICH7 SATA")) */ { mapValue &= 0x3; priChannelMode = gICH7ChannelModeMap[mapValue][0]; secChannelMode = gICH7ChannelModeMap[mapValue][1]; } } } if ( priChannelMode == kChannelModeDisabled && secChannelMode == kChannelModeDisabled ) { IOLog("%s: bad value (%x) in Port Mapping register", getName(), mapValue); _provider->close( this ); break; } for ( UInt32 channelID = 0; channelID < 2; channelID++ ) { UInt32 channelMode = (channelID ? secChannelMode : priChannelMode); // Create a dictionary for the channel info. Use native mode // settings if possible, else default to legacy mode. channelInfo = createNativeModeChannelInfo( channelID, channelMode ); if (channelInfo == 0) channelInfo = createLegacyModeChannelInfo( channelID, channelMode ); if (channelInfo == 0) continue; // Create a nub for each ATA channel. AppleIntelPIIXATAChannel * nub = new AppleIntelPIIXATAChannel; if ( nub ) { dtEntry = getDTChannelEntry( channelID ); if ( nub->init( this, channelInfo, dtEntry ) && nub->attach( this ) ) { nubSet->setObject( nub ); } if ( dtEntry ) { dtEntry->release(); } else { // Platform did not create a device tree entry for // this ATA channel. Do it here. char channelName[5] = {'C','H','N','_','\0'}; channelName[3] = '0' + channelID; nub->setName( channelName ); if ( _provider->inPlane(gIODTPlane) ) { nub->attachToParent( _provider, gIODTPlane ); } } nub->release(); } channelInfo->release(); } _provider->close( this ); } while ( false ); // Release and invalidate an empty set. if ( nubSet && (nubSet->getCount() == 0) ) { nubSet->release(); nubSet = 0; } return nubSet; }
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(); } }
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); }
static IORegistryEntry * MakeReferenceTable( DTEntry dtEntry, bool copy ) { IORegistryEntry *regEntry; OSDictionary *propTable; const OSSymbol *nameKey; OSData *data; const OSSymbol *sym; DTPropertyIterator dtIter; void *prop; unsigned int propSize; char *name; char location[ 32 ]; bool noLocation = true; regEntry = new IOService; if( regEntry && (false == regEntry->init())) { regEntry->release(); regEntry = 0; } if( regEntry && (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) { propTable = regEntry->getPropertyTable(); while( kSuccess == DTIterateProperties( dtIter, &name)) { if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) continue; if( copy) { nameKey = OSSymbol::withCString(name); data = OSData::withBytes(prop, propSize); } else { nameKey = OSSymbol::withCStringNoCopy(name); data = OSData::withBytesNoCopy(prop, propSize); } assert( nameKey && data ); propTable->setObject( nameKey, data); data->release(); nameKey->release(); if( nameKey == gIODTNameKey ) { if( copy) sym = OSSymbol::withCString( (const char *) prop); else sym = OSSymbol::withCStringNoCopy( (const char *) prop); regEntry->setName( sym ); sym->release(); } else if( nameKey == gIODTUnitKey ) { // all OF strings are null terminated... except this one if( propSize >= (int) sizeof(location)) propSize = sizeof(location) - 1; strncpy( location, (const char *) prop, propSize ); location[ propSize ] = 0; regEntry->setLocation( location ); propTable->removeObject( gIODTUnitKey ); noLocation = false; } else if(noLocation && (!strncmp(name, "reg", sizeof("reg")))) { // default location - override later snprintf(location, sizeof(location), "%X", *((uint32_t *) prop)); regEntry->setLocation( location ); } } DTDisposePropertyIterator( dtIter); } return( regEntry); }
bool SMBIOSResolver::start(IOService * provider) { if( super::start(provider) != true ) return false; // Oh no if( IOService::getResourceService()->getProperty("SMBIOS-Resolver") ) return false; // We should exist only once if( !IOService::getResourceService()->getProperty("SMBIOS") ) return false; // AppleSMBIOS.kext didn´t start we bail out IOService * iosRoot = getServiceRoot(); if( !iosRoot ) return false; // Unable to get IOServiceRoot int doVerbose = 0; // PE_parse_boot_arg("smbios", &doVerbose); // bootarg SMBIOS=1 will give a verbose output to log (when I find something verbose worth outputting) // Dictionary from plist OSDictionary * hwDict = OSDynamicCast( OSDictionary, getProperty("Override")); // /rom/version IORegistryEntry * dtROMNode = fromPath("/rom", gIODTPlane); if( dtROMNode ) { OSString * romVersion = OSDynamicCast( OSString, hwDict->getObject("rom-version")); if(romVersion->getLength() > 0) dtROMNode->setProperty("version", OSData::withBytes(romVersion->getCStringNoCopy(), romVersion->getLength() + 1) ); dtROMNode->release(); } else { return false; // No /rom node in IODeviceTree plane } // root entries OSObject * dictString = 0; dictString = hwDict->getObject("manufacturer"); if(dictString) { OSString * rootManufacturer = OSDynamicCast( OSString, dictString); if(rootManufacturer->getLength() > 1) iosRoot->setProperty("manufacturer", OSData::withBytes(rootManufacturer->getCStringNoCopy(), rootManufacturer->getLength() + 1) ); } dictString = hwDict->getObject("system-type"); if(dictString) { OSData * systemType = OSDynamicCast( OSData, dictString); if(systemType) iosRoot->setProperty("system-type", systemType ); } dictString = hwDict->getObject("compatible"); if(dictString) { OSString * rootCompatible = OSDynamicCast( OSString, dictString); if(rootCompatible->getLength() > 1) iosRoot->setProperty("compatible", OSData::withBytes(rootCompatible->getCStringNoCopy(), rootCompatible->getLength() + 1) ); } dictString = hwDict->getObject("product-name"); if(dictString) { OSString * rootProductName = OSDynamicCast( OSString, dictString); if(rootProductName->getLength() > 1) iosRoot->setProperty("product-name", OSData::withBytes(rootProductName->getCStringNoCopy(), rootProductName->getLength() + 1) ); } dictString = hwDict->getObject("model"); if(dictString) { OSString * rootModel = OSDynamicCast( OSString, dictString); if(rootModel->getLength() > 1) { iosRoot->setProperty("model", OSData::withBytes(rootModel->getCStringNoCopy(), rootModel->getLength() + 1) ); iosRoot->setName(rootModel->getCStringNoCopy()); } } dictString = hwDict->getObject("version"); if(dictString) { OSString * rootVersion = OSDynamicCast( OSString, dictString); if(rootVersion->getLength() > 1) iosRoot->setProperty("version", OSData::withBytes(rootVersion->getCStringNoCopy(), rootVersion->getLength() + 1) ); } dictString = hwDict->getObject("board-id"); if(dictString) { OSString * rootBoardId = OSDynamicCast( OSString, dictString); if(rootBoardId->getLength() > 1) iosRoot->setProperty("board-id", OSData::withBytes(rootBoardId->getCStringNoCopy(), rootBoardId->getLength() + 1) ); } dictString = hwDict->getObject("serial-number"); if(dictString) { OSString * rootSerial = OSDynamicCast( OSString, dictString); if(rootSerial->getLength() > 1) { UInt8 length = rootSerial->getLength(); const char *serialNumberString = rootSerial->getCStringNoCopy(); // The serial-number property in the IORegistry is a 43-byte data object. // Bytes 0 through 2 are the last three bytes of the serial number string. // Bytes 11 through 20, inclusive, are the serial number string itself. // All other bytes are '\0'. OSData * data = OSData::withCapacity(43); if (data) { data->appendBytes(serialNumberString + (length - 3), 3); data->appendBytes(NULL, 10); data->appendBytes(serialNumberString, length); data->appendBytes(NULL, 43 - length - 10 - 3); iosRoot->setProperty("serial-number", data); data->release(); } iosRoot->setProperty(kIOPlatformSerialNumberKey, rootSerial); } } dictString = hwDict->getObject("UUID-key"); if(dictString) { OSString * rootUUIDKey = OSDynamicCast( OSString, hwDict->getObject("UUID-key")); iosRoot->setProperty(kIOPlatformUUIDKey, rootUUIDKey); publishResource(kIOPlatformUUIDKey, rootUUIDKey); } bool useEfiBus = false; UInt64 fsbFrequency = 0; UInt64 msr; dictString = hwDict->getObject("use-efi-bus"); if (dictString) useEfiBus = (OSDynamicCast(OSBoolean, dictString))->getValue(); IORegistryEntry * efiPlatform = fromPath("/efi/platform", gIODTPlane); if (efiPlatform && useEfiBus) { OSData * efiFSBFreq = OSDynamicCast(OSData, efiPlatform->getProperty("FSBFrequency")); bcopy(efiFSBFreq->getBytesNoCopy(), &fsbFrequency, efiFSBFreq->getLength()); efiPlatform->release(); } else { // No /efi/platform found fsbFrequency = gPEClockFrequencyInfo.bus_frequency_hz; // Value previously set by AppleSMBIOS if (!strncmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL, sizeof(CPUID_VID_INTEL)) && (cpuid_info()->cpuid_features & CPUID_FEATURE_SSE2)) fsbFrequency /= 4; } dictString = hwDict->getObject("hardcode-bus"); if(dictString) { fsbFrequency = (OSDynamicCast(OSNumber, dictString))->unsigned64BitValue(); if (fsbFrequency) { if (fsbFrequency <= 10000) fsbFrequency *= 1000000; } else { if (!strncmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL, sizeof(CPUID_VID_INTEL))) { if ((cpuid_info()->cpuid_family == 0x0f) && (cpuid_info()->cpuid_model >= 2)) { msr = rdmsr64(0x0000002C); switch ((msr >> 16) & 0x7) { case 0: if (cpuid_info()->cpuid_model == 2) fsbFrequency = 100 * 1000000; else { fsbFrequency = (800 * 1000000) / 3; // 266 fsbFrequency++; } break; case 1: fsbFrequency = (400 * 1000000) / 3; // 133 break; case 2: fsbFrequency = (600 * 1000000) / 3; // 200 break; case 3: fsbFrequency = (500 * 1000000) / 3; // 166 fsbFrequency++; break; case 4: fsbFrequency = (1000 * 1000000) / 3; // 333 break; default: break; } } else { fsbFrequency = 100 * 1000000; } if (cpuid_info()->cpuid_family == 0x06) { msr = rdmsr64(0x000000CD); switch (msr & 0x7) { case 0: fsbFrequency = (800 * 1000000) / 3; // 266 fsbFrequency++; break; case 1: fsbFrequency = (400 * 1000000) / 3; // 133 break; case 2: fsbFrequency = (600 * 1000000) / 3; // 200 break; case 3: fsbFrequency = (500 * 1000000) / 3; // 166 fsbFrequency++; break; case 4: fsbFrequency = (1000 * 1000000) / 3;// 333 break; case 5: fsbFrequency = (300 * 1000000) / 3; // 100 break; case 6: fsbFrequency = (1200 * 1000000) / 3;// 400 break; case 7: // should check fsbFrequency = (1400 * 1000000) / 3;// 466 fsbFrequency++; break; default: break; } } } }