Esempio n. 1
0
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();
}
Esempio n. 4
0
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();
}
Esempio n. 6
0
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) );
}
Esempio n. 8
0
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();
    }
}
Esempio n. 9
0
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;
}
Esempio n. 15
0
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;
					}
				}
				 
			}
		}