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);
}
Exemple #2
0
bool IORangeAllocator::serialize(OSSerialize *s) const
{
    OSArray *	array = OSArray::withCapacity( numElements * 2 );
    OSNumber *	num;
    UInt32	index;
    bool	ret;

    if( !array)
	return( false );

    LOCK();

    for( index = 0; index < numElements; index++) {
	if( (num = OSNumber::withNumber( elements[index].start,
					8 * sizeof(IORangeScalar) ))) {
	    array->setObject(num);
	    num->release();
	}
	if( (num = OSNumber::withNumber( elements[index].end,
					8 * sizeof(IORangeScalar) ))) {
	    array->setObject(num);
	    num->release();
	}
    }

    UNLOCK();

    ret = array->serialize(s);
    array->release();

    return( ret );
}
IOReturn FakeSMCDevice::setProperties(OSObject * properties)
{
    KEYSLOCK;
    
    IOReturn result = kIOReturnUnsupported;
    
    if (OSDictionary * msg = OSDynamicCast(OSDictionary, properties)) {
        if (OSString * name = OSDynamicCast(OSString, msg->getObject(kFakeSMCDeviceUpdateKeyValue))) {
            if (FakeSMCKey * key = getKey(name->getCStringNoCopy())) {
                
                OSArray *info = OSArray::withCapacity(2);
                
                info->setObject(OSString::withCString(key->getType()));
                info->setObject(OSData::withBytes(key->getValue(), key->getSize()));
                
                exposedValues->setObject(key->getKey(), info);
                
                OSDictionary *values = OSDictionary::withDictionary(exposedValues);
                
                this->setProperty(kFakeSMCDeviceValues, values);
                
                OSSafeRelease(values);
                
                result = kIOReturnSuccess;
            }
        }
        else if (OSArray* array = OSDynamicCast(OSArray, msg->getObject(kFakeSMCDevicePopulateValues))) {
            if (OSIterator* iterator = OSCollectionIterator::withCollection(array)) {
                while (OSString *keyName = OSDynamicCast(OSString, iterator->getNextObject()))
                    if (FakeSMCKey * key = getKey(keyName->getCStringNoCopy())) {
                        
                        OSArray *info = OSArray::withCapacity(2);
                        
                        info->setObject(OSString::withCString(key->getType()));
                        info->setObject(OSData::withBytes(key->getValue(), key->getSize()));
                        
                        exposedValues->setObject(key->getKey(), info);
                        
                        IOSleep(10);    //REVIEW: what is this for?
                    }
                
                OSDictionary *values = OSDictionary::withDictionary(exposedValues);
                
                this->setProperty(kFakeSMCDeviceValues, values);
                
                OSSafeRelease(values);
                OSSafeRelease(iterator);
                
                result = kIOReturnSuccess;
            }
        }
    }
    
    KEYSUNLOCK;
    
	return result;
}
void AppleUSBDiagnostics::serializePort(OSDictionary *dictionary, int port, UIMPortDiagnostics *counts, IOService *controller) const
{
#pragma unused(controller, port)
    
    UpdateNumberEntry( dictionary, counts->errorCount, "Port errors");

    if( (gUSBStackDebugFlags & kUSBEnableErrorLogMask) != 0)
    {
        UpdateNumberEntry( dictionary, counts->totalBytes, "Bytes");
        UpdateNumberEntry( dictionary, counts->totalBytes-counts->prevBytes, "Bytes (New)");
        
        counts->prevBytes = counts->totalBytes;
        
        UpdateNumberEntry( dictionary, counts->timeouts, "Timeouts");
        UpdateNumberEntry( dictionary, counts->timeouts-counts->prevTimeouts, "Timeouts (New)");
        counts->prevTimeouts = counts->timeouts;
    }
        
    UpdateNumberEntry( dictionary, counts->resets, "Resets");
    UpdateNumberEntry( dictionary, counts->resets-counts->prevResets, "Resets (New)");
    counts->prevResets = counts->resets;
    
    UpdateNumberEntry( dictionary, counts->enable, "enable");
    UpdateNumberEntry( dictionary, counts->suspend, "suspend");
    UpdateNumberEntry( dictionary, counts->resume, "resume");
    UpdateNumberEntry( dictionary, counts->warmReset, "warmReset");
    UpdateNumberEntry( dictionary, counts->power, "power");
    UpdateNumberEntry( dictionary, counts->u1Timeout, "u1Timeout");
    UpdateNumberEntry( dictionary, counts->u2Timeout, "u2Timeout");
    UpdateNumberEntry( dictionary, counts->remoteWakeMask, "remoteWakeMask");

    OSArray     * errorArray = OSArray::withCapacity(kXHCIMaxCompletionCodes);
    for(int i=0; i<kXHCIMaxCompletionCodes; i++)
    {
        OSNumber * number = OSNumber::withNumber( counts->xhciErrorCode[i], 32 );
        errorArray->setObject( i, number );
        number->release();
    }
    dictionary->setObject( "XHCI Completion Codes", errorArray );
    errorArray->release();
    
    OSArray     * linkStateArray = OSArray::withCapacity(kXHCILinkStates);
    for(int i=0; i<kXHCILinkStates; i++)
    {
        OSNumber * number = OSNumber::withNumber( counts->linkState[i], 32 );
        linkStateArray->setObject( i, number );
        number->release();
    }
    dictionary->setObject( "LinkStates", linkStateArray );
    linkStateArray->release();
    
}
OSArray * IOHIDInterface::createMatchingElements (
                                OSDictionary *              matching, 
                                IOOptionBits                options __unused)
{
    UInt32                    count        = _elementArray->getCount();
    IOHIDElementPrivate *   element        = NULL;
    OSArray *                elements    = NULL;

    if ( count )
    {
        if ( matching )
        {
            elements = OSArray::withCapacity(count);

            for ( UInt32 i = 0; i < count; i ++)
            {
                // Compare properties.
                if (( element = (IOHIDElementPrivate *)_elementArray->getObject(i) )
                        && element->matchProperties(matching))
                {
                    elements->setObject(element);
                }
            }
        }
        else
            elements = OSArray::withArray(_elementArray);
    }

    return elements;
}
Exemple #6
0
OSArray * IODeviceMemory::arrayFromList(
	InitElement		list[],
	IOItemCount		count )
{
    OSArray *		array;
    IODeviceMemory *	range;
    IOItemCount		i;

    array = OSArray::withCapacity( count );
    if( 0 == array )
	return( 0);

    for( i = 0; i < count; i++) {
	range = IODeviceMemory::withRange( list[i].start, list[i].length );
	if( range) {
	    range->setTag( list[i].tag );
	    array->setObject( range);
	    range->release();
	} else {
	    array->release();
	    array = 0;
	    break;
	}
    }

    return( array );
}
Exemple #7
0
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;
}
Exemple #8
0
/*---------------------------------------------------------------------------
 * Update all the registry properties associated with an interface
 ---------------------------------------------------------------------------*/
void EInterfaces::update_interface_property(void)
{
	int n;
	
	debug("update_interface_property - m_nInterfacesInUse=%d\n", m_nInterfacesInUse);

	if ( m_pProvider )
	{
		m_pProvider->removeProperty(ENABLED_INTERFACES_PROPERTY);
		
		if ( m_nInterfacesInUse )
		{
			OSArray* pInterfaces = OSArray::withCapacity(m_nInterfacesInUse);
			if ( pInterfaces )
			{
				for(n=0; n<numberof(m_aInterfaces); n++)
					if ( m_aInterfaces[n].m_fEnabled )
					{
						OSNumber* pNumber = OSNumber::withNumber(n, 32);
						if ( pNumber )
						{
							pInterfaces->setObject(pNumber);
							pNumber->release();
						}
					}
				
				m_pProvider->setProperty(ENABLED_INTERFACES_PROPERTY, (OSObject* )pInterfaces);
				pInterfaces->release();
			}
		}
	}
}
Exemple #9
0
OSCollection * OSSet::copyCollection(OSDictionary *cycleDict)
{
    bool allocDict = !cycleDict;
    OSCollection *ret = 0;
    OSSet *newSet = 0;

    if (allocDict) {
	cycleDict = OSDictionary::withCapacity(16);
	if (!cycleDict)
	    return 0;
    }

    do {
	// Check for a cycle
	ret = super::copyCollection(cycleDict);
	if (ret)
	    continue;	// Found it

	newSet = OSSet::withCapacity(members->capacity);
	if (!newSet)
	    continue;	// Couldn't create new set abort

	// Insert object into cycle Dictionary
	cycleDict->setObject((const OSSymbol *) this, newSet);

	OSArray *newMembers = newSet->members;
	newMembers->capacityIncrement = members->capacityIncrement;

	// Now copy over the contents into the new duplicate
	for (unsigned int i = 0; i < members->count; i++) {
	    OSObject *obj = EXT_CAST(members->array[i]);
	    OSCollection *coll = OSDynamicCast(OSCollection, obj);
	    if (coll) {
		OSCollection *newColl = coll->copyCollection(cycleDict);
		if (newColl) {
		    obj = newColl;	// Rely on cycleDict ref for a bit
		    newColl->release();
		}
		else
		    goto abortCopy;
	    };
	    newMembers->setObject(obj);
	};

	ret = newSet;
	newSet = 0;

    } while(false);

abortCopy:
    if (newSet)
	newSet->release();

    if (allocDict)
	cycleDict->release();

    return ret;
}
// <rdar://8202424>
IOReturn IOAudioSelectorControl::addAvailableSelection(SInt32 selectionValue, OSString *selectionDescription, const char* tagName, OSObject* tag)
{
	OSArray *newSelections;
	OSArray *oldAvailableSelections;
    IOReturn result = kIOReturnSuccess;
    
	oldAvailableSelections = availableSelections;
	newSelections = OSArray::withArray(availableSelections);
	if (!newSelections)
		return kIOReturnNoMemory;

    if (selectionDescription == NULL) {
        result = kIOReturnBadArgument;
    } else {
        if (valueExists(selectionValue)) {
            result = kIOReturnError;
        } else {
            OSDictionary *newSelection;
            
            newSelection = OSDictionary::withCapacity(2);
            
            if (newSelection) {
                OSNumber *number;
				
                number = OSNumber::withNumber(selectionValue, sizeof(SInt32)*8);
                
                if (number) {
                    newSelection->setObject(kIOAudioSelectorControlSelectionValueKey, number);
                    newSelection->setObject(kIOAudioSelectorControlSelectionDescriptionKey, selectionDescription);
                    newSelections->setObject(newSelection);
					
                    number->release();
                } else {
                    result = kIOReturnError;
                }
				
				if ( tagName && tag ) {
					newSelection->setObject(tagName, tag);
				}
				
				availableSelections = newSelections;
				setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections);
				oldAvailableSelections->release();
                
                newSelection->release();
            } else {
                result = kIOReturnError;
            }
        }
    }
    
	if (kIOReturnSuccess == result) {
		sendChangeNotification(kIOAudioControlRangeChangeNotification);
	}
	
    return result;
}
Exemple #11
0
void IOCatalogue::addPersonality(OSDictionary * dict)
{
    const OSSymbol * sym;
    OSArray * arr;

    sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
    if (!sym) return;
    arr = (OSArray *) personalities->getObject(sym);
    if (arr) arr->setObject(dict);
    else
    {
        arr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
        personalities->setObject(sym, arr);
        arr->release();
    }
}
Exemple #12
0
OSArray * OSDictionary::copyKeys(void)
{
    OSArray * array;

	array = OSArray::withCapacity(count);
	if (!array) return (0);

	for (unsigned int i = 0; i < count; i++)
	{
	    if (!array->setObject(i, dictionary[i].key))
	    {
            array->release();
            array = 0;
            break;
        }
	}
    return (array);
}
Exemple #13
0
bool FakeSMCDevice::initAndStart(IOService *platform, IOService *provider)
{
	if (!provider || !super::init(platform, 0, 0))
		return false;
    
    OSDictionary *properties = OSDynamicCast(OSDictionary, provider->getProperty("Configuration"));
    
    if (!properties)
        return false;
    
	status = (ApleSMCStatus *) IOMalloc(sizeof(struct AppleSMCStatus));
	bzero((void*)status, sizeof(struct AppleSMCStatus));
	interrupt_handler = 0;
    
	keys = OSArray::withCapacity(1);
    types = OSDictionary::withCapacity(0);
    exposedValues = OSDictionary::withCapacity(0);
    
    // Add fist key - counter key
    keyCounterKey = FakeSMCKey::withValue(KEY_COUNTER, TYPE_UI32, TYPE_UI32_SIZE, "\0\0\0\1");
	keys->setObject(keyCounterKey);
    
    fanCounterKey = FakeSMCKey::withValue(KEY_FAN_NUMBER, TYPE_UI8, TYPE_UI8_SIZE, "\0");
    keys->setObject(fanCounterKey);
    
    if (!gKeysLock)
        gKeysLock = IORecursiveLockAlloc();
    
    // Load preconfigured keys
    FakeSMCDebugLog("loading keys...");
    
    if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Keys"))) {
		if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) {
			while (const OSSymbol *key = (const OSSymbol *)iterator->getNextObject()) {
				if (OSArray *array = OSDynamicCast(OSArray, dictionary->getObject(key))) {
					if (OSIterator *aiterator = OSCollectionIterator::withCollection(array)) {
                        
						OSString *type = OSDynamicCast(OSString, aiterator->getNextObject());
						OSData *value = OSDynamicCast(OSData, aiterator->getNextObject());
                        
						if (type && value)
							addKeyWithValue(key->getCStringNoCopy(), type->getCStringNoCopy(), value->getLength(), value->getBytesNoCopy());
                        
                        OSSafeRelease(aiterator);
					}
				}
				key = 0;
			}
            
			OSSafeRelease(iterator);
		}
        
		HWSensorsInfoLog("%d preconfigured key%s added", keys->getCount(), keys->getCount() == 1 ? "" : "s");
	}
	else {
		HWSensorsWarningLog("no preconfigured keys found");
	}
    
    // Load wellknown type names
    FakeSMCDebugLog("loading types...");
    
    if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Types"))) {
        if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) {
			while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) {
                if (OSString *value = OSDynamicCast(OSString, dictionary->getObject(key))) {
                    types->setObject(key, value);
                }
            }
            OSSafeRelease(iterator);
        }
    }
    
    // Set Clover platform keys
    if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Clover"))) {
        UInt32 count = 0;
        if (IORegistryEntry* cloverPlatformNode = fromPath("/efi/platform", gIODTPlane)) {
            if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) {
                while (OSString *name = OSDynamicCast(OSString, iterator->getNextObject())) {
                    if (OSData *data = OSDynamicCast(OSData, cloverPlatformNode->getProperty(name))) {
                        if (OSArray *items = OSDynamicCast(OSArray, dictionary->getObject(name))) {
                            OSString *key = OSDynamicCast(OSString, items->getObject(0));
                            OSString *type = OSDynamicCast(OSString, items->getObject(1));
                            
                            if (addKeyWithValue(key->getCStringNoCopy(), type->getCStringNoCopy(), data->getLength(), data->getBytesNoCopy()))
                                count++;
                        }
                    }
                }
                OSSafeRelease(iterator);
            }
        }
        
        if (count)
            HWSensorsInfoLog("%d key%s exported by Clover EFI", count, count == 1 ? "" : "s");
    }
    
    // Start SMC device
    
    if (!super::start(platform))
        return false;
    
	this->setName("SMC");
    
    FakeSMCSetProperty("name", "APP0001");
    
	if (OSString *compatibleKey = OSDynamicCast(OSString, properties->getObject("smc-compatible")))
		FakeSMCSetProperty("compatible", (const char *)compatibleKey->getCStringNoCopy());
	else
		FakeSMCSetProperty("compatible", "smc-napa");
    
	if (!this->setProperty("_STA", (unsigned long long)0x0000000b, 32)) {
        HWSensorsErrorLog("failed to set '_STA' property");
        return false;
    }
    
	if (OSBoolean *debugKey = OSDynamicCast(OSBoolean, properties->getObject("debug")))
		debug = debugKey->getValue();
    else
        debug = false;
    
    if (OSBoolean *traceKey = OSDynamicCast(OSBoolean, properties->getObject("trace")))
		trace = traceKey->getValue();
    else
        trace = false;
    
	IODeviceMemory::InitElement	rangeList[1];
    
	rangeList[0].start = 0x300;
	rangeList[0].length = 0x20;
//    rangeList[1].start = 0xfef00000;
//	rangeList[1].length = 0x10000;
    
	if(OSArray *array = IODeviceMemory::arrayFromList(rangeList, 1)) {
		this->setDeviceMemory(array);
		OSSafeRelease(array);
	}
	else
	{
		HWSensorsFatalLog("failed to create Device memory array");
		return false;
	}
    
	OSArray *controllers = OSArray::withCapacity(1);
    
    if(!controllers) {
		HWSensorsFatalLog("failed to create controllers array");
        return false;
    }
    
    controllers->setObject((OSSymbol *)OSSymbol::withCStringNoCopy("io-apic-0"));
    
	OSArray *specifiers  = OSArray::withCapacity(1);
    
    if(!specifiers) {
		HWSensorsFatalLog("failed to create specifiers array");
        return false;
    }
    
	UInt64 line = 0x06;
    
    OSData *tmpData = OSData::withBytes(&line, sizeof(line));
    
    if (!tmpData) {
		HWSensorsFatalLog("failed to create specifiers data");
        return false;
    }
    
    specifiers->setObject(tmpData);
    
	this->setProperty(gIOInterruptControllersKey, controllers) && this->setProperty(gIOInterruptSpecifiersKey, specifiers);
	this->attachToParent(platform, gIOServicePlane);
    
    registerService();
    
	HWSensorsInfoLog("successfully initialized");
    
	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);
}
Exemple #15
0
/*********************************************************************
* 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;
}
Exemple #16
0
bool MacRISC2CPU::start(IOService *provider)
{
    kern_return_t        result;
    IORegistryEntry      *cpusRegEntry, *uniNRegEntry, *mpicRegEntry, *devicetreeRegEntry;
    OSIterator           *cpusIterator;
    OSData               *tmpData;
    IOService            *service;
    const OSSymbol       *interruptControllerName;
    OSData               *interruptData;
    OSArray              *tmpArray;
    UInt32               maxCPUs, uniNVersion, physCPU;
    ml_processor_info_t  processor_info;
    
#if enableUserClientInterface    
	DFScontMode = 0;
    fWorkLoop = 0;
    DFS_Status = false;
    GPU_Status = kGPUHigh;
	vStepped = false;
#endif

    // callPlatformFunction symbols
    mpic_getProvider = OSSymbol::withCString("mpic_getProvider");
    mpic_getIPIVector= OSSymbol::withCString("mpic_getIPIVector");
    mpic_setCurrentTaskPriority = OSSymbol::withCString("mpic_setCurrentTaskPriority");
    mpic_setUpForSleep = OSSymbol::withCString("mpic_setUpForSleep");
    mpic_dispatchIPI = OSSymbol::withCString("mpic_dispatchIPI");
    keyLargo_restoreRegisterState = OSSymbol::withCString("keyLargo_restoreRegisterState");
    keyLargo_syncTimeBase = OSSymbol::withCString("keyLargo_syncTimeBase");
    keyLargo_saveRegisterState = OSSymbol::withCString("keyLargo_saveRegisterState");
    keyLargo_turnOffIO = OSSymbol::withCString("keyLargo_turnOffIO");
    keyLargo_writeRegUInt8 = OSSymbol::withCString("keyLargo_writeRegUInt8");
    keyLargo_getHostKeyLargo = OSSymbol::withCString("keyLargo_getHostKeyLargo");
    keyLargo_setPowerSupply = OSSymbol::withCString("setPowerSupply");
    uniN_setPowerState = OSSymbol::withCString(kUniNSetPowerState);
    uniN_setAACKDelay = OSSymbol::withCString(kUniNSetAACKDelay);
	pmu_cpuReset = OSSymbol::withCString("cpuReset");
	ati_prepareDMATransaction = OSSymbol::withCString(kIOFBPrepareDMAValueKey);
    ati_performDMATransaction = OSSymbol::withCString(kIOFBPerformDMAValueKey);
    
    macRISC2PE = OSDynamicCast(MacRISC2PE, getPlatform());
    if (macRISC2PE == 0) return false;
  
    if (!super::start(provider)) return false;

    // Get the Uni-N Version.
    uniNRegEntry = fromPath("/uni-n", gIODTPlane);
    if (uniNRegEntry == 0) return false;
    tmpData = OSDynamicCast(OSData, uniNRegEntry->getProperty("device-rev"));
    if (tmpData == 0) return false;
    uniNVersion = *(long *)tmpData->getBytesNoCopy();
  
    // Find out if this is the boot CPU.
    bootCPU = false;
    tmpData = OSDynamicCast(OSData, provider->getProperty("state"));
    if (tmpData == 0) return false;
    if (!strcmp((char *)tmpData->getBytesNoCopy(), "running")) bootCPU = true;

    // Count the CPUs.
    numCPUs = 0;
    cpusRegEntry = fromPath("/cpus", gIODTPlane);
    if (cpusRegEntry == 0) return false;
    cpusIterator = cpusRegEntry->getChildIterator(gIODTPlane);
    while (cpusIterator->getNextObject()) numCPUs++;
    cpusIterator->release();
  
	// [3830950] - The bootCPU driver inits globals for all instances (like gCPUIC) so if we're not the
	// boot CPU driver we wait here for that driver to finish its initialization
	if ((numCPUs > 1) && !bootCPU)
		// Wait for bootCPU driver to say it's up and running
		(void) waitForService (resourceMatching ("BootCPU"));
		
    // Limit the number of CPUs to one if uniNVersion is 1.0.7 or less.
    if (uniNVersion < kUniNVersion107) numCPUs = 1;
  
    // Limit the number of CPUs by the cpu=# boot arg.
    if (PE_parse_boot_arg("cpus", &maxCPUs))
    {
        if (numCPUs > maxCPUs) numCPUs = maxCPUs;
    }
	
	ignoreSpeedChange = false;
	doSleep = false;
	topLevelPCIBridgeCount = 0;
  
    // Get the "flush-on-lock" property from the first cpu node.
    flushOnLock = false;
    cpusRegEntry = fromPath("/cpus/@0", gIODTPlane);
    if (cpusRegEntry == 0) return false;
    if (cpusRegEntry->getProperty("flush-on-lock") != 0) flushOnLock = true;
  
    // Set flushOnLock when numCPUs is not one.
    if (numCPUs != 1) flushOnLock = true;
  
    // If system is PowerMac3,5 (TowerG4), then set flushOnLock to disable nap
    devicetreeRegEntry = fromPath("/", gIODTPlane);
    tmpData = OSDynamicCast(OSData, devicetreeRegEntry->getProperty("model"));
    if (tmpData == 0) return false;
#if 0
    if(!strcmp((char *)tmpData->getBytesNoCopy(), "PowerMac3,5"))
        flushOnLock = true;
#endif

    // Get the physical CPU number from the "reg" property.
    tmpData = OSDynamicCast(OSData, provider->getProperty("reg"));
    if (tmpData == 0) return false;
    physCPU = *(long *)tmpData->getBytesNoCopy();
    setCPUNumber(physCPU);

    // Get the gpio offset for soft reset from the "soft-reset" property.
    tmpData = OSDynamicCast(OSData, provider->getProperty("soft-reset"));
    if (tmpData == 0) 
    {
        if (physCPU == 0)
            soft_reset_offset = 0x5B;
        else
            soft_reset_offset = 0x5C;
    }
    else
        soft_reset_offset = *(long *)tmpData->getBytesNoCopy();
   
    // Get the gpio offset for timebase enable from the "timebase-enable" property.
    tmpData = OSDynamicCast(OSData, provider->getProperty("timebase-enable"));
    if (tmpData == 0) 
        timebase_enable_offset = 0x73;
    else
        timebase_enable_offset = *(long *)tmpData->getBytesNoCopy();
  
	// See if reset is needed on wake
	resetOnWake = (provider->getProperty ("reset-on-wake") != NULL);
	
	if (resetOnWake) {
		vm_address_t reserveMem;
		

		reserveMem = (vm_address_t)IOMallocAligned (PAGE_SIZE, PAGE_SIZE);	// Get one page (which we keep forever)
		if (reserveMem) {			
			// map it
			reserveMemDesc = IOMemoryDescriptor::withAddress (reserveMem, PAGE_SIZE, kIODirectionNone, NULL);
			if (reserveMemDesc) {
				// get the physical address
				reserveMemPhys = reserveMemDesc->getPhysicalAddress();
			} 
		} 
	}

    // On machines with a 'vmin' property in the CPU Node we need to make sure to tell the kernel to 
    // ml_set_processor_voltage on needed processors.
    needVSetting = (provider->getProperty( "vmin" ) != 0);

    // While techincally the Apollo7PM machines do need AACK delay, it is already set in the bootROM
    // since we boot slow.  We don't want the machine to switch AACKdelay off when we run DFS high so
    // setting this to false will take care of the issue.
        
    needAACKDelay = false;
 
 	if (bootCPU)
    {
        gCPUIC = new IOCPUInterruptController;
        if (gCPUIC == 0) return false;
        if (gCPUIC->initCPUInterruptController(numCPUs) != kIOReturnSuccess)
            return false;
        gCPUIC->attach(this);
        gCPUIC->registerCPUInterruptController();
    }
  
    // Get the l2cr value from the property list.
    tmpData = OSDynamicCast(OSData, provider->getProperty("l2cr"));
    if (tmpData != 0)
    {
        l2crValue = *(long *)tmpData->getBytesNoCopy() & 0x7FFFFFFF;
    }
    else
    {
        l2crValue = mfl2cr() & 0x7FFFFFFF;
    }
  
    // Wait for KeyLargo to show up.
    keyLargo = waitForService(serviceMatching("KeyLargo"));
    if (keyLargo == 0) return false;
  
    keyLargo->callPlatformFunction (keyLargo_getHostKeyLargo, false, &keyLargo, 0, 0, 0);
    if (keyLargo == 0)
    {
        kprintf ("MacRISC2CPU::start - getHostKeyLargo returned nil\n");
        return false;
    }

    // Wait for MPIC to show up.
    mpic = waitForService(serviceMatching("AppleMPICInterruptController"));
    if (mpic == 0) return false;
  
    // Set the Interrupt Properties for this cpu.
    mpic->callPlatformFunction(mpic_getProvider, false, (void *)&mpicRegEntry, 0, 0, 0);
    interruptControllerName = IODTInterruptControllerName(mpicRegEntry);
    mpic->callPlatformFunction(mpic_getIPIVector, false, (void *)&physCPU, (void *)&interruptData, 0, 0);
    if ((interruptControllerName == 0) || (interruptData == 0)) return false;
  
    tmpArray = OSArray::withCapacity(1);
    tmpArray->setObject(interruptControllerName);
    cpuNub->setProperty(gIOInterruptControllersKey, tmpArray);
    tmpArray->release();
  
    tmpArray = OSArray::withCapacity(1);
    tmpArray->setObject(interruptData);
    cpuNub->setProperty(gIOInterruptSpecifiersKey, tmpArray);
    tmpArray->release();
  
    setCPUState(kIOCPUStateUninitalized);
  
	// necessary bootCPU initialization is done, so release other CPU drivers to do their thing
	// other drivers need to be unblocked *before* we call processor_start otherwise we deadlock
	if (bootCPU)
		publishResource ("BootCPU", this);
		
    if (physCPU < numCPUs)
    {
        processor_info.cpu_id           = (cpu_id_t)this;
        processor_info.boot_cpu         = bootCPU;
        processor_info.start_paddr      = 0x0100;
        processor_info.l2cr_value       = l2crValue;
        processor_info.supports_nap     = !flushOnLock;
        processor_info.time_base_enable =
        OSMemberFunctionCast(time_base_enable_t, this, &MacRISC2CPU::enableCPUTimeBase);	// [4091924]
    
        // Register this CPU with mach.
        result = ml_processor_register(&processor_info, &machProcessor,	&ipi_handler);
        if (result == KERN_FAILURE) return false;
    
        processor_start(machProcessor);
    }

    // Before to go to sleep we wish to disable the napping mode so that the PMU
    // will not shutdown the system while going to sleep:
    service = waitForService(serviceMatching("IOPMrootDomain"));
    pmRootDomain = OSDynamicCast(IOPMrootDomain, service);
    if (pmRootDomain != 0)
    {
        kprintf("Register MacRISC2CPU %ld to acknowledge power changes\n", getCPUNumber());
        pmRootDomain->registerInterestedDriver(this);
        
        // Join the Power Management Tree to receive setAggressiveness calls.
        PMinit();
        provider->joinPMtree(this);
    }

    // Finds PMU and UniN so in quiesce we can put the machine to sleep.
    // I can not put these calls there because quiesce runs in interrupt
    // context and waitForService may block.
    pmu = waitForService(serviceMatching("ApplePMU"));
	uniN = waitForService(serviceMatching("AppleUniN"));
    if ((pmu == 0) || (uniN == 0)) return false;
	

    if (macRISC2PE->hasPMon) {
            // Find the platform monitor, if present
            service = waitForService(resourceMatching("IOPlatformMonitor"));
            ioPMon = OSDynamicCast (IOPlatformMonitor, service->getProperty("IOPlatformMonitor"));
            if (!ioPMon) 
                    return false;
            
            ioPMonDict = OSDictionary::withCapacity(2);
            if (!ioPMonDict) {
                    ioPMon = NULL;
            } else {
                    ioPMonDict->setObject (kIOPMonTypeKey, OSSymbol::withCString (kIOPMonTypeCPUCon));
                    ioPMonDict->setObject (kIOPMonCPUIDKey, OSNumber::withNumber ((long long)getCPUNumber(), 32));

                    if (messageClient (kIOPMonMessageRegister, ioPMon, (void *)ioPMonDict) != kIOReturnSuccess) {
                            // IOPMon doesn't need to know about us, so don't bother with it
                            IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformMonitor\n");
                            ioPMonDict->release();
                            ioPMon = NULL;
                    }
            }
    }

    if (macRISC2PE->hasPPlugin) {
		IOService		*ioPPlugin;
		OSDictionary	*ioPPluginDict;
		
		// Find the platform plugin, if present
		service = waitForService(resourceMatching("IOPlatformPlugin"));
		ioPPlugin = OSDynamicCast (IOService, service->getProperty("IOPlatformPlugin"));
		if (!ioPPlugin) 
			return false;
		
		ioPPluginDict = OSDictionary::withCapacity(2);
		if (ioPPluginDict) {
			ioPPluginDict->setObject ("cpu-id", OSNumber::withNumber ((long long)getCPUNumber(), 32));

			// Register with the plugin - same API as for platform monitor
			if (messageClient (kIOPMonMessageRegister, ioPPlugin, (void *)ioPPluginDict) != kIOReturnSuccess) {
				// ioPPlugin doesn't need to know about us, so don't bother with it
				IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformPlugin\n");
			}
			ioPPluginDict->release();	// Not needed any more
		}
    }

#if enableUserClientInterface    
//   
// UserClient stuff...
//  
    fWorkLoop = getWorkLoop();
    if(!fWorkLoop)
    {
            IOLog("MacRISC2CPU::start ERROR: failed to find a fWorkLoop\n");
    }
    if(!initTimers()) 
    {
            IOLog("MacRISC2CPU::start ERROR: failed to init the timers\n");
    }
    
#endif

    registerService();
  
    return true;
}
Exemple #17
0
void testSet()
{
    bool res = true;
    void *spaceCheck, *spaceCheck2 , *spaceCheck3;
    int i, count, count2;
    OSObject *cache[numStrCache], *str, *sym;
    OSSet *set1, *set2;
    OSArray *array;

    // Do first test without memory leak tests to initialise the metaclass
    set1 = OSSet::withCapacity(1);
    TEST_ASSERT('S', "0a", set1);
    if (set1)
        set1->release();

    // Grow the symbol pool to maximum
    for (i = 0; i < numStrCache; i++)
        cache[i] = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
    for (i = 0; i < numStrCache; i++)
        cache[i]->release();

    // Create and destroy an set
    spaceCheck = checkPointSpace();
    set1 = OSSet::withCapacity(1);
    TEST_ASSERT('S', "1a", set1);
    if (set1) {
        TEST_ASSERT('S', "1b", !set1->getCount());
        TEST_ASSERT('S', "1c", 1 == set1->getCapacity());
        TEST_ASSERT('S', "1d", 1 == set1->getCapacityIncrement());
        TEST_ASSERT('S', "1e", 4 == set1->setCapacityIncrement(4));
        TEST_ASSERT('S', "1f", 4 == set1->getCapacityIncrement());
        TEST_ASSERT('S', "1g", 8 == set1->ensureCapacity(5));

        spaceCheck2 = checkPointSpace();
        cache[0] = IOString::withCStringNoCopy(strCache[0]);

        spaceCheck3 = checkPointSpace();
        TEST_ASSERT('S', "1h", set1->setObject(cache[0]));
        TEST_ASSERT('S', "1i", set1->containsObject(cache[0]));
        TEST_ASSERT('S', "1j", cache[0] == set1->getAnyObject());
        cache[0]->release();
        res = res && checkSpace("(S)1k", spaceCheck3, 0);

        TEST_ASSERT('S', "1l", 1 == set1->getCount());
        set1->flushCollection();
        TEST_ASSERT('S', "1m", !set1->getCount());
        res = res && checkSpace("(S)1n", spaceCheck2, 0);

        set1->release();
    }
    res = res && checkSpace("(S)1", spaceCheck, 0);

    // Check the creation of a sizable OSSet from an set of IOObjects
    // Also check member test of set.
    spaceCheck = checkPointSpace();
    for (i = 0; i < numStrCache; i++)
        cache[i] = OSString::withCStringNoCopy(strCache[i]);
    set1 = OSSet::withObjects(cache, numStrCache, numStrCache);
    TEST_ASSERT('S', "2a", set1);
    for (i = 0; i < numStrCache; i++)
        cache[i]->release();
    if (set1) {
        TEST_ASSERT('S', "2b", numStrCache == (int) set1->getCount());
        TEST_ASSERT('S', "2c", numStrCache == (int) set1->getCapacity());
        TEST_ASSERT('S', "2d",
                    numStrCache == (int) set1->getCapacityIncrement());

        count = 0;
        for (i = set1->getCount(); --i >= 0; )
            count += set1->member(cache[i]);

        TEST_ASSERT('S', "2e", numStrCache == count);
        set1->release();
    }
    res = res && checkSpace("(S)2", spaceCheck, 0);

    // Test set creation from another set by both the setObject method
    // and the withArray factory.  And test __takeObject code first
    // with tail removal then with head removal
    spaceCheck = checkPointSpace();
    for (i = 0; i < numStrCache; i++)
        cache[i] = OSString::withCStringNoCopy(strCache[i]);
    set1 = OSSet::withObjects(cache, numStrCache, numStrCache);
    TEST_ASSERT('S', "3a", set1);
    for (i = 0; i < numStrCache; i++)
        cache[i]->release();
    set2 = 0;
    if (set1) {
        set2 = OSSet::withCapacity(set1->getCount());
        TEST_ASSERT('S', "3b", set2);
        TEST_ASSERT('S', "3c", !set2->getCount());
        TEST_ASSERT('S', "3d", set2->setObject(set1));
        TEST_ASSERT('S', "3e", set1->getCount() == set2->getCount());
    }
    if (set2) {
        TEST_ASSERT('S', "3f", numStrCache == (int) set2->getCount());
        count = count2 = 0;
        while ( (str = set2->getAnyObject()) ) {
            count  += set2->__takeObject(str);
            count2 += set1->member(str);
            str->release();
        }
        TEST_ASSERT('S', "3g", !set2->getCount());
        TEST_ASSERT('S', "3h", numStrCache == count);
        TEST_ASSERT('S', "3i", numStrCache == count2);

        spaceCheck2 = checkPointSpace();
        set2->flushCollection();
        res = res && checkSpace("(S)3j", spaceCheck2, 0);

        set2->release();
        set2 = 0;
    }
    if (set1) {
        set2 = OSSet::withSet(set1, numStrCache - 1);
        TEST_ASSERT('S', "3k", !set2);
        set2 = OSSet::withSet(set1, set1->getCount());
        TEST_ASSERT('S', "3l", set2);
        set1->release();
    }
    if (set2) {
        TEST_ASSERT('S', "3m", numStrCache == (int) set2->getCount());
        i = count = count2 = 0;
        while ( (str = set2->getAnyObject()) ) {
            count  += set2->__takeObject(str);
            count2 += (cache[i++] == str);
            str->release();
        }
        TEST_ASSERT('S', "3n", !set2->getCount());
        TEST_ASSERT('S', "3o", numStrCache == count);
        TEST_ASSERT('S', "3p", numStrCache == count2);

        set2->release();
        set2 = 0;
    }
    res = res && checkSpace("(S)3", spaceCheck, 0);

    // Test duplicate removal
    spaceCheck = checkPointSpace();
    set2 = 0;
    set1 = OSSet::withCapacity(numStrCache);
    TEST_ASSERT('S', "4a", set1);
    if (set1) {
        count = 0;
        for (i = 0; i < numStrCache; i++) {
            sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
            count += set1->setObject(sym);
            sym->release();
        }
        TEST_ASSERT('S', "4b", numStrCache != (int) set1->getCount());
        TEST_ASSERT('S', "4c", count == (int) set1->getCount());

        count = count2 = 0;
        for (i = 0; i < numStrCache; i++) {
            sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
            count += set1->member(sym);
            count2 += sym->getRetainCount();
            sym->release();
        }
        TEST_ASSERT('S', "4d", count  == numStrCache);
        TEST_ASSERT('S', "4e", count2 == numStrCache * 2);

        set2 = OSSet::withSet(set1, 2 * set1->getCount());
    }
    TEST_ASSERT('S', "4f", set2);
    if (set2) {
        set2->setObject(set1);
        TEST_ASSERT('S', "4g", set1->getCount() == set2->getCount());
        set1->release();
        set2->release();
    }
    res = res && checkSpace("(S)4", spaceCheck, 0);

    // Test array duplicate removal
    spaceCheck = checkPointSpace();
    array = OSArray::withCapacity(numStrCache);
    for (i = 0; i < numStrCache; i++) {
        sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
        count += array->setObject(sym);
        sym->release();
    }
    set1 = OSSet::withArray(array, numStrCache);
    TEST_ASSERT('S', "5a", set1);
    if (set1) {
        TEST_ASSERT('S', "5b", array->getCount() != set1->getCount());
        array->release();

        count = count2 = set1->getCount();
        while ( (sym = set1->getAnyObject()) ) {
            count  -= set1->__takeObject(sym);
            count2 -= sym->getRetainCount();
            sym->release();
        }
        TEST_ASSERT('S', "5c", !count);
        TEST_ASSERT('S', "5d", !count2);
        set1->release();
    }
    res = res && checkSpace("(S)5", spaceCheck, 0);

    if (res)
        verPrintf(("testSet: All OSSet Tests passed\n"));
    else
        logPrintf(("testSet: Some OSSet Tests failed\n"));
}
Exemple #18
0
bool IOCatalogue::addDrivers(
    OSArray * drivers,
    bool doNubMatching)
{
    bool                   result = false;
    OSCollectionIterator * iter = NULL;       // must release
    OSOrderedSet         * set = NULL;        // must release
    OSObject             * object = NULL;       // do not release
    OSArray              * persons = NULL;    // do not release
    
    persons = OSDynamicCast(OSArray, drivers);
    if (!persons) {
        goto finish;
    }
    
    set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
        (void *)gIOProbeScoreKey );
    if (!set) {
        goto finish;
    }

    iter = OSCollectionIterator::withCollection(persons);
    if (!iter) {
        goto finish;
    }

   /* Start with success; clear it on an error.
    */
    result = true;

    IORWLockWrite(lock);
    while ( (object = iter->getNextObject()) ) {
    
        // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL

        OSDictionary * personality = OSDynamicCast(OSDictionary, object);

        SInt count;

        if (!personality) {
            IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
            result = false;
            break;
        }

        OSKext::uniquePersonalityProperties(personality);

        // Add driver personality to catalogue.

	OSArray * array = arrayForPersonality(personality);
	if (!array) addPersonality(personality);
	else
	{       
	    count = array->getCount();
	    while (count--) {
		OSDictionary * driver;
		
		// Be sure not to double up on personalities.
		driver = (OSDictionary *)array->getObject(count);
		
	       /* Unlike in other functions, this comparison must be exact!
		* The catalogue must be able to contain personalities that
		* are proper supersets of others.
		* Do not compare just the properties present in one driver
		* pesonality or the other.
		*/
		if (personality->isEqualTo(driver)) {
		    break;
		}
	    }
	    if (count >= 0) {
		// its a dup
		continue;
	    }
	    result = array->setObject(personality);
	    if (!result) {
		break;
	    }
        }

	set->setObject(personality);        
    }
    // Start device matching.
    if (result && doNubMatching && (set->getCount() > 0)) {
        IOService::catalogNewDrivers(set);
        generation++;
    }
    IORWLockUnlock(lock);

finish:
    if (set)  set->release();
    if (iter) iter->release();

    return result;
}
// Class start
bool
VoodooPState::start(IOService * provider)
{
	if (!IOService::start(provider)) return false;

	// Printout banner
	InfoLog("%s %s (%s) %s %s [%s]",
			KextProductName,
			KextVersion,
			KextConfig,
			KextBuildDate,
			KextBuildTime,
			KextOSX);
	InfoLog("based on VoodooPower 1.2.3.");
	
	
	
	// Setup workloop and timer
	IOWorkLoop* WorkLoop = getWorkLoop();
	if (!WorkLoop) return false;
	TimerEventSource = 
	IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action,
																	this,
																	&VoodooPState::LoopTimerEvent));
	if (!TimerEventSource) return false;
	
	if (kIOReturnSuccess != WorkLoop->addEventSource(TimerEventSource)) {
		return false;
	}
	
	// Get a SimpleLock
	SimpleLock = IOSimpleLockAlloc();
	if (!SimpleLock) return false;
	
	// Publish the static characteristics
	OSDictionary * dictionary = OSDictionary::withCapacity(13);
	if (!dictionary) return false;
	OSArray * array = OSArray::withCapacity(PStateCount);
	if (!array) return false;
	setDictionaryNumber(keyCpuCoreTech, CpuCoreTech, dictionary);
	setDictionaryNumber(keyFrontSideBus, CpuFSB, dictionary);
	for (int i = 0; i < PStateCount; i++) {
		OSDictionary * pdictionary = OSDictionary::withCapacity(3);
		if (!pdictionary) return false;
		setDictionaryNumber(keyCurrentFrequency, PState[i].frequency, pdictionary);
		setDictionaryNumber(keyCurrentVoltage, PState[i].voltage, pdictionary);
		setDictionaryNumber(keyFid, PState[i].fid, pdictionary);
		setDictionaryNumber(keyDid, PState[i].did, pdictionary);
		setDictionaryNumber(keyVid, PState[i].vid, pdictionary);
		array->setObject(i, pdictionary);
		pdictionary->release();
	}
	setDictionaryArray(keyPStates, array, dictionary);
	setDictionaryString(keyProductName, KextProductName, dictionary);
	setDictionaryString(keyProductVersion, KextVersion, dictionary);
	setDictionaryString(keyBuildConfig, KextConfig, dictionary);
	setDictionaryString(keyBuildDate, KextBuildDate, dictionary);
	setDictionaryString(keyBuildTime, KextBuildTime, dictionary);
	setDictionaryNumber(keyTimerInterval, TimerInterval, dictionary);
	setProperty(keyCharacteristics, dictionary);

	array->release();
	dictionary->release();

	// set initial pstate
	Request = ColdStart ? (PStateCount-1) : 0;	// hot/cold start

	gPEClockFrequencyInfo.cpu_frequency_max_hz = VoodooFrequencyProc(this,&PState[0]) * Mega;
	gPEClockFrequencyInfo.cpu_frequency_min_hz = VoodooFrequencyProc(this,&PState[PStateCount-1]) * Mega;

	LoopTimerEvent();
	
	// Finalize and kick off the loop
	this->registerService(0);
	Ready = true;

	return true;
}
bool ACPIBacklightPanel::findDevices(IOService * provider)
{
    DbgLog("%s::%s()\n", this->getName(),__FUNCTION__);
    
    if (!gpuDevice || !backLightDevice)
    {
        IOACPIPlatformDevice * dev = OSDynamicCast(IOACPIPlatformDevice, provider);
        if (hasBacklightMethods(dev))
        {
            DbgLog("%s: PNLF has backlight Methods\n", this->getName());
            backLightDevice = dev;
            gpuDevice = dev;
            gpuDevice->retain();
            backLightDevice->retain();
        }
        else
        {            
            gpuDevice = getGPU();
            
            if (NULL == gpuDevice)
                return false;
            
            gpuDevice->retain();
            
            if (hasBacklightMethods(gpuDevice))
            {
                backLightDevice = gpuDevice;
            }
            else
            {
                backLightDevice = getChildWithBacklightMethods(gpuDevice);
            }
            
            if (backLightDevice == NULL)
                return false;
            
            backLightDevice->retain();
        }

#ifdef DEBUG
        if (gpuDevice != backLightDevice)
        {
            OSArray * devicePaths = OSArray::withCapacity(2);
            OSString* path = getACPIPath(gpuDevice);
            IOLog("ACPIBacklight: ACPI Method _DOS found. Device path: %s\n", path->getCStringNoCopy());
            devicePaths->setObject(path);
            path->release();
            path = getACPIPath(backLightDevice);
            IOLog("ACPIBacklight: ACPI Methods _BCL _BCM _BQC found. Device path: %s\n", path->getCStringNoCopy());
            devicePaths->setObject(path);
            path->release();
            setProperty("ACPI Devices Paths", devicePaths);
            devicePaths->release();
        }
        else
        {
            OSString* path = getACPIPath(backLightDevice);
            IOLog("ACPIBacklight: ACPI Methods _DOS _BCL _BCM _BQC found. Device path: %s\n", path->getCStringNoCopy());
            setProperty("ACPI Device Path", path);
            path->release();
        }
#endif
    }
    return true;
}
// Should only be done during init time - this is not thread safe
IOReturn IOAudioLevelControl::addRange(SInt32 minRangeValue, 
                                        SInt32 maxRangeValue, 
                                        IOFixed minRangeDB, 
                                        IOFixed maxRangeDB)
{
    IOReturn result = kIOReturnSuccess;
    
    // We should verify the new range doesn't overlap any others here
    
    if (ranges == NULL) {
        ranges = OSArray::withCapacity(1);
        if (ranges) {
            setProperty(kIOAudioLevelControlRangesKey, ranges);
        }
    }
    
    if (ranges) {
        OSDictionary *newRange;
		OSArray *newRanges;
		OSArray *oldRanges;
        
		oldRanges = ranges;
        newRanges = OSArray::withArray(ranges);
		if (!newRanges)
			return kIOReturnNoMemory;
		
        newRange = OSDictionary::withCapacity(4);
        if (newRange) {
            OSNumber *number;
            
            number = OSNumber::withNumber(minRangeValue, sizeof(SInt32)*8);
            newRange->setObject(kIOAudioLevelControlMinValueKey, number);
            number->release();
            
            number = OSNumber::withNumber(maxRangeValue, sizeof(SInt32)*8);
            newRange->setObject(kIOAudioLevelControlMaxValueKey, number);
            number->release();
            
            number = OSNumber::withNumber(minRangeDB, sizeof(IOFixed)*8);
            newRange->setObject(kIOAudioLevelControlMinDBKey, number);
            number->release();
            
            number = OSNumber::withNumber(maxRangeDB, sizeof(IOFixed)*8);
            newRange->setObject(kIOAudioLevelControlMaxDBKey, number);
            number->release();
            
            newRanges->setObject(newRange);
            setProperty(kIOAudioLevelControlRangesKey, newRanges);
			ranges = newRanges;
			oldRanges->release();
            
            newRange->release();
        } else {
            result = kIOReturnError;
        }
    } else {
        result = kIOReturnError;
    }
    
    return result;
}
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();
	}
}
Exemple #23
0
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;
}
Exemple #24
0
OSObject *
OSUnserializeBinary(const char *buffer, size_t bufferSize, OSString **errorString)
{
	OSObject ** objsArray;
	uint32_t    objsCapacity;
	enum      { objsCapacityMax = 16*1024*1024 };
	uint32_t    objsIdx;

	OSObject ** stackArray;
	uint32_t    stackCapacity;
	enum      { stackCapacityMax = 64 };
	uint32_t    stackIdx;

    OSObject     * result;
    OSObject     * parent;
    OSDictionary * dict;
    OSArray      * array;
    OSSet        * set;
    OSDictionary * newDict;
    OSArray      * newArray;
    OSSet        * newSet;
    OSObject     * o;
    OSSymbol     * sym;
    OSString     * str;

    size_t           bufferPos;
    const uint32_t * next;
    uint32_t         key, len, wordLen;
    bool             end, newCollect, isRef;
    unsigned long long value;
    bool ok;

	if (errorString) *errorString = 0;
	if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (NULL);
	if (0 != strcmp(kOSSerializeBinarySignature, buffer)) return (NULL);
	if (3 & ((uintptr_t) buffer)) return (NULL);
	bufferPos = sizeof(kOSSerializeBinarySignature);
	next = (typeof(next)) (((uintptr_t) buffer) + bufferPos);

	DEBG("---------OSUnserializeBinary(%p)\n", buffer);

	objsArray = stackArray    = NULL;
	objsIdx   = objsCapacity  = 0;
	stackIdx  = stackCapacity = 0;

    result   = 0;
    parent   = 0;
	dict     = 0;
	array    = 0;
	set      = 0;
	sym      = 0;

	ok = true;
	while (ok)
	{
		bufferPos += sizeof(*next);
		if (!(ok = (bufferPos <= bufferSize))) break;
		key = *next++;

        len = (key & kOSSerializeDataMask);
        wordLen = (len + 3) >> 2;
		end = (0 != (kOSSerializeEndCollecton & key));
        DEBG("key 0x%08x: 0x%04x, %d\n", key, len, end);

        newCollect = isRef = false;
		o = 0; newDict = 0; newArray = 0; newSet = 0;
		
		switch (kOSSerializeTypeMask & key)
		{
		    case kOSSerializeDictionary:
				o = newDict = OSDictionary::withCapacity(len);
				newCollect = (len != 0);
		        break;
		    case kOSSerializeArray:
				o = newArray = OSArray::withCapacity(len);
				newCollect = (len != 0);
		        break;
		    case kOSSerializeSet:
				o = newSet = OSSet::withCapacity(len);
				newCollect = (len != 0);
		        break;

		    case kOSSerializeObject:
				if (len >= objsIdx) break;
				o = objsArray[len];
				isRef = true;
				break;

		    case kOSSerializeNumber:
				bufferPos += sizeof(long long);
				if (bufferPos > bufferSize) break;
		        if ((len != 32) && (len != 64) && (len != 16) && (len != 8)) break;
		    	value = next[1];
		    	value <<= 32;
		    	value |= next[0];
		    	o = OSNumber::withNumber(value, len);
		    	next += 2;
		        break;

		    case kOSSerializeSymbol:
				bufferPos += (wordLen * sizeof(uint32_t));
				if (bufferPos > bufferSize)           break;
				if (len < 2)                          break;
				if (0 != ((const char *)next)[len-1]) break;
		        o = (OSObject *) OSSymbol::withCString((const char *) next);
		        next += wordLen;
		        break;

		    case kOSSerializeString:
				bufferPos += (wordLen * sizeof(uint32_t));
				if (bufferPos > bufferSize) break;
		        o = OSString::withStringOfLength((const char *) next, len);
		        next += wordLen;
		        break;

    	    case kOSSerializeData:
				bufferPos += (wordLen * sizeof(uint32_t));
				if (bufferPos > bufferSize) break;
		        o = OSData::withBytes(next, len);
		        next += wordLen;
		        break;

    	    case kOSSerializeBoolean:
				o = (len ? kOSBooleanTrue : kOSBooleanFalse);
		        break;

		    default:
		        break;
		}

		if (!(ok = (o != 0))) break;

		if (!isRef)
		{
			setAtIndex(objs, objsIdx, o);
			if (!ok)
			{
			    o->release();
                break;
            }
			objsIdx++;
		}

		if (dict)
		{
			if (!sym) sym = (OSSymbol *) o;
			else
			{
                str = sym;
				sym = OSDynamicCast(OSSymbol, sym);
				if (!sym && (str = OSDynamicCast(OSString, str)))
				{
				    sym = const_cast<OSSymbol *>(OSSymbol::withString(str));
                    ok = (sym != 0);
                    if (!ok) break;
				}
				DEBG("%s = %s\n", sym->getCStringNoCopy(), o->getMetaClass()->getClassName());
				if (o != dict) ok = dict->setObject(sym, o);
                if (sym && (sym != str)) sym->release();
				sym = 0;
			}
		}
		else if (array)  ok = array->setObject(o);
		else if (set)    ok = set->setObject(o);
		else if (result) ok = false;
		else
		{
		    assert(!parent);
		    result = o;
		}

		if (!ok) break;

        if (end) parent = 0;
		if (newCollect)
		{
            stackIdx++;
            setAtIndex(stack, stackIdx, parent);
            if (!ok) break;
			DEBG("++stack[%d] %p\n", stackIdx, parent);
			parent = o;
			dict   = newDict;
			array  = newArray;
			set    = newSet;
			end    = false;
		}

		if (end)
		{
            while (stackIdx)
            {
                parent = stackArray[stackIdx];
                DEBG("--stack[%d] %p\n", stackIdx, parent);
                stackIdx--;
                if (parent) break;
            }
            if (!parent) break;
			set   = 0;
			dict  = 0; 
			array = 0;
			if (!(dict = OSDynamicCast(OSDictionary, parent)))
			{
				if (!(array = OSDynamicCast(OSArray, parent))) ok = (0 != (set = OSDynamicCast(OSSet, parent)));
			}
		}
	}
	DEBG("ret %p\n", result);

	if (!ok) result = 0;

	if (objsCapacity)
	{
        for (len = (result != 0); len < objsIdx; len++) objsArray[len]->release();
	    kfree(objsArray,  objsCapacity  * sizeof(*objsArray));
    }
	if (stackCapacity) kfree(stackArray, stackCapacity * sizeof(*stackArray));

	return (result);
}
Exemple #25
0
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;
    }

    profiles = OSDictionary::withCapacity(0);
    profileList = OSArray::withCapacity(0);

    OSObject *object = NULL;


    // Try to load configuration provided by ACPI device

        if (kIOReturnSuccess == acpiDevice->evaluateObject("LIST", &object) && object) {
            if (OSArray *list = OSDynamicCast(OSArray, object)) {
                for (unsigned int i = 0; i < list->getCount(); i++) {
                    if (OSString *method = OSDynamicCast(OSString, list->getObject(i))) {
                        if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) {
                            if (OSArray *config = OSDynamicCast(OSArray, object)) {
                                if (config->getCount() > 4) {
                                    OSString *pName = OSDynamicCast(OSString, config->getObject(0));
                                    OSNumber *pInterval = OSDynamicCast(OSNumber, config->getObject(1));
                                    OSNumber *pTimeout = OSDynamicCast(OSNumber, config->getObject(2));
                                    OSNumber *pVerbose = OSDynamicCast(OSNumber, config->getObject(3));

                                    OSArray *pMethods = OSArray::withCapacity(config->getCount() - 4);

                                    for (unsigned int offset = 4; offset < config->getCount(); offset++) {
                                        if (OSString *methodName = OSDynamicCast(OSString, config->getObject(offset))) {
                                            pMethods->setObject(methodName);
                                        }
                                    }

                                    addProfile(pName, pMethods, pInterval, pTimeout, pVerbose);
                                }
                            }

                            OSSafeRelease(object);
                        }
                    }
                }

                OSSafeRelease(list);
            }

        }
        else {
            ACPISensorsErrorLog("profile definition table (LIST) not found");
        }

    // Try to load configuration from info.plist
    if (profiles->getCount() == 0) {
        if (OSDictionary *configuration = getConfigurationNode())
        {
            OSString *pName = OSDynamicCast(OSString, configuration->getObject("ProfileName"));
            OSNumber *pInterval = OSDynamicCast(OSNumber, configuration->getObject("PollingInterval"));
            OSNumber *pTimeout = OSDynamicCast(OSNumber, configuration->getObject("PollingTimeout"));
            OSBoolean *pVerboseBool = OSDynamicCast(OSBoolean, configuration->getObject("VerboseLog"));
            OSNumber *pVerbose = OSNumber::withNumber(pVerboseBool->getValue() ? 1 : 0, 8);
            OSArray *pMethods = OSDynamicCast(OSArray, configuration->getObject("MethodsToPoll"));

            addProfile(pName, pMethods, pInterval, pTimeout, pVerbose);
        }
    }

    if (this->profiles->getCount()) {

        // Parse active profile
        if (kIOReturnSuccess == acpiDevice->evaluateObject("ACTV", &object) && object) {
            if (OSString *method = OSDynamicCast(OSString, object)) {
                if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) {
                    if (OSArray *config = OSDynamicCast(OSArray, object)) {
                        if (config->getCount() > 4) {
                            if (OSString *profile = OSDynamicCast(OSString, config->getObject(0))) {
                                if (!(activeProfile = (ACPIProbeProfile *)profiles->getObject(profile))) {
                                    activeProfile = (ACPIProbeProfile *)profileList->getObject(0);
                                }
                            }
                        }
                    }

                    OSSafeRelease(object);
                }

                OSSafeRelease(method);
            }
        }

        // 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" : "");
    }

    // two power states - off and on
	static const IOPMPowerState powerStates[2] = {
        { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
    };

    // register interest in power state changes
	PMinit();
	provider->joinPMtree(this);
	registerPowerDriver(this, (IOPMPowerState *)powerStates, 2);
    
	registerService();
    
    ACPISensorsInfoLog("started");
    
	return true;
}