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;
}
void
OWCDumpIORegistry::dumpIORegistry (void *argument)
{
	IOSleep (DUMP_DELAY_SECONDS * 1000);
		
	IORegistryIterator *iter = IORegistryIterator::iterateOver (gIOServicePlane, kIORegistryIterateRecursively);
	if (iter == NULL) return;
	
	int maxBufferSize = 2048;
	char *buffer = (char *) IOMalloc (maxBufferSize);
	if (buffer == NULL) return;
	
	OSSerialize *s = OSSerialize::withCapacity (maxBufferSize);
	if (s == NULL) return;
	
	IORegistryEntry *object = iter->getCurrentEntry ();
	while (object) {
		s->clearText ();
		
		int busyState = 0;
		IOService *ios = OSDynamicCast (IOService, object);
		if (ios) busyState = ios->getBusyState ();
					
		int pathSize = maxBufferSize;
		object->getPath (buffer, &pathSize, gIOServicePlane);
		kprintf ("\n--> %s <%s> (%d, %d)\n", buffer, object->getMetaClass ()->getClassName (), object->getRetainCount (), busyState);
		
		if (object->serializeProperties (s)) {
			kprintf ("%s\n", s->text ());
		} else {
			kprintf ("serializeProperties failed\n");
		}
		
		object = iter->getNextObject ();
	} 
	
	IOFree (buffer, maxBufferSize);
	s->release ();
	iter->release ();
}
UInt32 FakeSMCDevice::loadKeysFromNVRAM()
{
    UInt32 count = 0;
    
    // Find driver and load keys from NVRAM
    // check for Chameleon NVRAM key first (because waiting for IODTNVRAM hangs)
    IORegistryEntry* nvram = IORegistryEntry::fromPath("/chosen/nvram", gIODTPlane);
    OSDictionary* matching = 0;
    if (!nvram) {
        // probably booting w/ Clover
        matching = serviceMatching("IODTNVRAM");
        nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15));
    }
    if (1) { //REVIEW: just to reduce diffs
        if (nvram) {
            
            useNVRAM = true;
            
            if ((genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", sizeof("AppleNVRAM")))))
                HWSensorsInfoLog("fallback to generic NVRAM methods");
            
            OSSerialize *s = OSSerialize::withCapacity(0); // Workaround for IODTNVRAM->getPropertyTable returns IOKitPersonalities instead of NVRAM properties dictionary
            
            if (nvram->serializeProperties(s)) {
                if (OSDictionary *props = OSDynamicCast(OSDictionary, OSUnserializeXML(s->text()))) {
                    if (OSCollectionIterator *iterator = OSCollectionIterator::withCollection(props)) {
                        
                        size_t prefix_length = strlen(kFakeSMCKeyPropertyPrefix);
                        
                        char name[5]; name[4] = 0;
                        char type[5]; type[4] = 0;
                        
                        while (OSString *property = OSDynamicCast(OSString, iterator->getNextObject())) {
                            const char *buffer = static_cast<const char *>(property->getCStringNoCopy());
                            
                            if (property->getLength() >= prefix_length + 1 + 4 + 1 + 0 && 0 == strncmp(buffer, kFakeSMCKeyPropertyPrefix, prefix_length)) {
                                if (OSData *data = OSDynamicCast(OSData, props->getObject(property))) {
                                    strncpy(name, buffer + prefix_length + 1, 4); // fakesmc-key-???? ->
                                    strncpy(type, buffer + prefix_length + 1 + 4 + 1, 4); // fakesmc-key-xxxx-???? ->
                                    
                                    if (addKeyWithValue(name, type, data->getLength(), data->getBytesNoCopy())) {
                                        HWSensorsDebugLog("key %s of type %s loaded from NVRAM", name, type);
                                        count++;
                                    }
                                }
                            }
                        }
                        
                        OSSafeRelease(iterator);
                    }
                    
                    OSSafeRelease(props);
                }
            }
            
            OSSafeRelease(s);
            OSSafeRelease(nvram);
        }
        else {
            HWSensorsWarningLog("NVRAM is unavailable");
        }
        
        OSSafeRelease(matching);
    }
    
    return count;
}