static void _PrintFlattenedTree(DTEntry entry, int level) { DTEntryIterator entryIter; PrintFlattenedNode(entry, level); if (kSuccess != DTCreateEntryIterator(entry, &entryIter)) { printf("Couldn't create entry iterator\n"); return; } level++; while (kSuccess == DTIterateEntries( entryIter, &entry )) { _PrintFlattenedTree(entry, level); } DTDisposeEntryIterator(entryIter); }
int main(int argc, char **argv) { DTEntry dtEntry; DTPropertyIterator propIter; DTEntryIterator entryIter; void *prop; int propSize; char *name; void *flatTree; uint32_t flatSize; Node *node; node = AddChild(NULL, "device-tree"); AddProperty(node, "potato", 4, "foo"); AddProperty(node, "chemistry", 4, "bar"); AddProperty(node, "physics", 4, "baz"); node = AddChild(node, "dev"); AddProperty(node, "one", 4, "one"); AddProperty(node, "two", 4, "two"); AddProperty(node, "three", 6, "three"); node = AddChild(rootNode, "foo"); AddProperty(node, "aaa", 4, "aab"); AddProperty(node, "bbb", 4, "bbc"); AddProperty(node, "cccc", 6, "ccccd"); node = FindNode("/this/is/a/test", 1); AddProperty(node, "dddd", 12, "abcdefghijk"); printf("In-memory tree:\n\n"); PrintTree(rootNode); FlattenDeviceTree(&flatTree, &flatSize); printf("Flat tree = %p, size %d\n", flatTree, flatSize); dtEntry = (DTEntry)flatTree; printf("\n\nPrinting flat tree\n\n"); DTInit(dtEntry); PrintFlattenedTree((DTEntry)flatTree); #if 0 printf("=== Entry %p ===\n", dtEntry); if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) { printf("Couldn't create property iterator\n"); return 1; } while( kSuccess == DTIterateProperties( propIter, &name)) { if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) continue; printf(" Property %s = %s\n", name, prop); } DTDisposePropertyIterator(propIter); printf("========\n"); if (kSuccess != DTCreateEntryIterator(dtEntry, &entryIter)) { printf("Couldn't create entry iterator\n"); return 1; } while (kSuccess == DTIterateEntries( entryIter, &dtEntry )) { printf("=== Entry %p ===\n", dtEntry); if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) { printf("Couldn't create property iterator\n"); return 1; } while( kSuccess == DTIterateProperties( propIter, &name)) { if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) continue; printf(" Property %s = %s\n", name, prop); } DTDisposePropertyIterator(propIter); printf("========\n"); } DTDisposeEntryIterator(entryIter); #endif return 0; }
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); }