void DT__PrintFlattenedNode(DTEntry entry, int level) { char spaces[10], *cp = spaces; DTPropertyIterator propIter; char *name; void *prop; int propSize; if (level > 9) level = 9; while (level--) *cp++ = ' '; *cp = '\0'; printf("%s===Entry %p===\n", spaces, entry); if (kSuccess != DTCreatePropertyIterator(entry, &propIter)) { printf("Couldn't create property iterator\n"); return; } while( kSuccess == DTIterateProperties( propIter, &name)) { if( kSuccess != DTGetProperty( entry, name, &prop, &propSize )) continue; printf("%s Property %s = %s\n", spaces, name, prop); } DTDisposePropertyIterator(propIter); printf("%s==========\n", spaces); }
static RealDTEntry FindChild(RealDTEntry cur, char *buf) { RealDTEntry child; unsigned long index; char * str; int dummy; if (cur->nChildren == 0) { return NULL; } index = 1; child = GetFirstChild(cur); while (1) { if (DTGetProperty(child, "name", (void **)&str, &dummy) != kSuccess) { break; } if (strcmp(str, buf) == 0) { return child; } if (index >= cur->nChildren) { break; } child = GetNextChild(child); index++; } return NULL; }
RealDTEntry FindChild(RealDTEntry cur, CHAR8 *buf) { RealDTEntry child; UINT32 index; CHAR8* str; UINT32 dummy; if (cur->nChildren == 0) { return NULL; } index = 1; child = GetFirstChild(cur); while (1) { if (DTGetProperty(child, "name", (VOID **)&str, &dummy) != kSuccess) { break; } if (AsciiStrCmp((CHAR8*)str, (CHAR8*)buf) == 0) { return child; } if (index >= cur->nChildren) { break; } child = GetNextChild(child); index++; } return NULL; }
boolean_t PE_get_default( const char *property_name, void *property_ptr, unsigned int max_property) { DTEntry dte; void **property_data; unsigned int property_size; /* * Look for the property using the PE DT support. */ if (kSuccess == DTLookupEntry(NULL, "/defaults", &dte)) { /* * We have a /defaults node, look for the named property. */ if (kSuccess != DTGetProperty(dte, property_name, (void **)&property_data, &property_size)) return FALSE; /* * This would be a fine place to do smart argument size management for 32/64 * translation, but for now we'll insist that callers know how big their * default values are. */ if (property_size > max_property) return FALSE; /* * Copy back the precisely-sized result. */ memcpy(property_ptr, property_data, property_size); return TRUE; } /* * Look for the property using I/O Kit's DT support. */ return IODTGetDefault(property_name, property_ptr, max_property) ? FALSE : TRUE; }
bool AppleARMPE::start(IOService * provider) { DTEntry entry; char *dtype; unsigned int size; IOLog("AppleARMPE::start: Welcome to the NeXT generation.\n"); if (!super::start(provider)) { panic("IOPlatformExpert failed to start"); } removeProperty(kIOPlatformMapperPresentKey); assert(IOService::getPlatform() == this); registerService(); /* * Let these time out to let everything else initialize right. */ #if 0 publishResource("IONVRAM"); publishResource("IORTC"); #endif if (kSuccess == DTLookupEntry(NULL, "/", &entry)) { /* * What's the device name? */ if (kSuccess == DTGetProperty(entry, "compatible", (void **) &dtype, &size)) { populate_model_name(dtype); } else { populate_model_name("Generic ARM Device"); } } else { populate_model_name("Generic ARM Device"); } return true; }
void PE_init_iokit(void) { enum { kMaxBootVar = 128 }; typedef struct { char name[32]; unsigned long length; unsigned long value[2]; } DriversPackageProp; boolean_t bootClutInitialized = FALSE; boolean_t noroot_rle_Initialized = FALSE; DTEntry entry; unsigned int size; uint32_t *map; boot_progress_element *bootPict; norootIcon_lzss = NULL; norootClut_lzss = NULL; PE_init_kprintf(TRUE); PE_init_printf(TRUE); kprintf("Kernel boot args: '%s'\n", PE_boot_args()); /* * Fetch the CLUT and the noroot image. */ if( kSuccess == DTLookupEntry(NULL, "/chosen/memory-map", &entry)) { if( kSuccess == DTGetProperty(entry, "BootCLUT", (void **) &map, &size)) { if (sizeof(appleClut8) <= map[1]) { bcopy( (void *)ml_static_ptovirt(map[0]), appleClut8, sizeof(appleClut8) ); bootClutInitialized = TRUE; } } if( kSuccess == DTGetProperty(entry, "Pict-FailedBoot", (void **) &map, &size)) { bootPict = (boot_progress_element *) ml_static_ptovirt(map[0]); default_noroot.width = bootPict->width; default_noroot.height = bootPict->height; default_noroot.dx = 0; default_noroot.dy = bootPict->yOffset; default_noroot_data = &bootPict->data[0]; noroot_rle_Initialized = TRUE; } if( kSuccess == DTGetProperty(entry, "FailedCLUT", (void **) &map, &size)) { norootClut_lzss = (uint8_t*) ml_static_ptovirt(map[0]); } if( kSuccess == DTGetProperty(entry, "FailedImage", (void **) &map, &size)) { norootIcon_lzss = (boot_icon_element *) ml_static_ptovirt(map[0]); if (norootClut_lzss == NULL) { printf("ERROR: No FailedCLUT provided for noroot icon!\n"); } } } if (!bootClutInitialized) { bcopy( (void *) (uintptr_t) bootClut, (void *) appleClut8, sizeof(appleClut8) ); } if (!noroot_rle_Initialized) { default_noroot.width = kFailedBootWidth; default_noroot.height = kFailedBootHeight; default_noroot.dx = 0; default_noroot.dy = kFailedBootOffset; default_noroot_data = failedBootPict; } /* * Initialize the spinning wheel (progress indicator). */ vc_progress_initialize( &default_progress, default_progress_data1x, default_progress_data2x, (unsigned char *) appleClut8 ); (void) StartIOKit( PE_state.deviceTreeHead, PE_state.bootArgs, gPEEFIRuntimeServices, NULL); }
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; }
void PE_init_kprintf(__unused boolean_t vm_initialized) { unsigned int boot_arg; int32_t serial_baud = -1; unsigned int size; DTEntry options; char *str, baud[7]; if (PE_state.initialized == FALSE) panic("Platform Expert not initialized"); if (PE_parse_boot_argn("debug", &boot_arg, sizeof (boot_arg))) if(boot_arg & DB_KPRT) disable_serial_output = FALSE; if (DTLookupEntry(NULL, "/options", &options) == kSuccess) { if (DTGetProperty(options, "input-device", (void **)&str, &size) == kSuccess) { if ((size > 5) && !strncmp("scca:", str, 5)) { size -= 5; str += 5; if (size <= 6) { strncpy(baud, str, size); baud[size] = '\0'; gPESerialBaud = strtol(baud, NULL, 0); } } } if (DTGetProperty(options, "output-device", (void **)&str, &size) == kSuccess) { if ((size > 5) && !strncmp("scca:", str, 5)) { size -= 5; str += 5; if (size <= 6) { strncpy(baud, str, size); baud[size] = '\0'; gPESerialBaud = strtol(baud, NULL, 0); } } } } /* Check the boot-args for new serial baud. */ if (PE_parse_boot_argn("serialbaud", &serial_baud, sizeof (serial_baud))) if (serial_baud != -1) gPESerialBaud = serial_baud; if( (scc = PE_find_scc())) { /* See if we can find the serial port */ scc = io_map_spec(scc, 0x1000, VM_WIMG_IO); /* Map it in */ initialize_serial((void *)scc, gPESerialBaud); /* Start up the serial driver */ PE_kputc = serial_putc; simple_lock_init(&kprintf_lock, 0); } else PE_kputc = cnputc; #if 0 /* * FUTURE: eventually let the boot command determine where * the debug output will be, serial, video, etc. */ switch (PE_state.debug_video.v_display) { case kDebugTypeSerial: PE_kputc = serial_putc; break; case kDebugTypeDisplay: init_display_putc( (unsigned char*)PE_state.debug_video.v_baseAddr, PE_state.debug_video.v_rowBytes, PE_state.debug_video.v_height); PE_kputc = display_putc; break; default: PE_state.debug_video.v_baseAddr = 0; } #endif }
IORegistryEntry * IODeviceTreeAlloc( void * dtTop ) { IORegistryEntry * parent; IORegistryEntry * child; IORegistryIterator * regIter; DTEntryIterator iter; DTEntry dtChild; DTEntry mapEntry; OSArray * stack; OSData * prop; OSDictionary * allInts; vm_offset_t * dtMap; unsigned int propSize; bool intMap; bool freeDT; gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane ); gIODTNameKey = OSSymbol::withCStringNoCopy( "name" ); gIODTUnitKey = OSSymbol::withCStringNoCopy( "AAPL,unit-string" ); gIODTCompatibleKey = OSSymbol::withCStringNoCopy( "compatible" ); gIODTTypeKey = OSSymbol::withCStringNoCopy( "device_type" ); gIODTModelKey = OSSymbol::withCStringNoCopy( "model" ); gIODTSizeCellKey = OSSymbol::withCStringNoCopy( "#size-cells" ); gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" ); gIODTRangeKey = OSSymbol::withCStringNoCopy( "ranges" ); gIODTPersistKey = OSSymbol::withCStringNoCopy( "IODTPersist" ); assert( gIODTPlane && gIODTCompatibleKey && gIODTTypeKey && gIODTModelKey && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey && gIODTPersistKey ); gIODTDefaultInterruptController = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController"); gIODTNWInterruptMappingKey = OSSymbol::withCStringNoCopy("IONWInterrupts"); gIODTAAPLInterruptsKey = OSSymbol::withCStringNoCopy("AAPL,interrupts"); gIODTPHandleKey = OSSymbol::withCStringNoCopy("AAPL,phandle"); gIODTInterruptParentKey = OSSymbol::withCStringNoCopy("interrupt-parent"); gIODTPHandles = OSArray::withCapacity( 1 ); gIODTPHandleMap = OSArray::withCapacity( 1 ); gIODTInterruptCellKey = OSSymbol::withCStringNoCopy("#interrupt-cells"); assert( gIODTDefaultInterruptController && gIODTNWInterruptMappingKey && gIODTAAPLInterruptsKey && gIODTPHandleKey && gIODTInterruptParentKey && gIODTPHandles && gIODTPHandleMap && gIODTInterruptCellKey ); freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry )) && (kSuccess == DTGetProperty( mapEntry, "DeviceTree", (void **) &dtMap, &propSize )) && ((2 * sizeof(uint32_t)) == propSize); parent = MakeReferenceTable( (DTEntry)dtTop, freeDT ); stack = OSArray::withObjects( (const OSObject **) &parent, 1, 10 ); DTCreateEntryIterator( (DTEntry)dtTop, &iter ); do { parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1); //parent->release(); stack->removeObject( stack->getCount() - 1); while( kSuccess == DTIterateEntries( iter, &dtChild) ) { child = MakeReferenceTable( dtChild, freeDT ); child->attachToParent( parent, gIODTPlane); AddPHandle( child ); if( kSuccess == DTEnterEntry( iter, dtChild)) { stack->setObject( parent); parent = child; } // only registry holds retain child->release(); } } while( stack->getCount() && (kSuccess == DTExitEntry( iter, &dtChild))); stack->release(); DTDisposeEntryIterator( iter); // parent is now root of the created tree // make root name first compatible entry (purely cosmetic) if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) { parent->setName( parent->getName(), gIODTPlane ); parent->setName( (const char *) prop->getBytesNoCopy() ); } // attach tree to meta root parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane); parent->release(); if( freeDT ) { // free original device tree DTInit(0); IODTFreeLoaderInfo( "DeviceTree", (void *)dtMap[0], (int) round_page(dtMap[1]) ); } // adjust tree gIODTSharedInterrupts = OSDictionary::withCapacity(4); allInts = OSDictionary::withCapacity(4); intMap = false; regIter = IORegistryIterator::iterateOver( gIODTPlane, kIORegistryIterateRecursively ); assert( regIter && allInts && gIODTSharedInterrupts ); if( regIter && allInts && gIODTSharedInterrupts ) { while( (child = regIter->getNextObject())) { IODTMapInterruptsSharing( child, allInts ); if( !intMap && child->getProperty( gIODTInterruptParentKey)) intMap = true; } regIter->release(); } #if IODTSUPPORTDEBUG parent->setProperty("allInts", allInts); parent->setProperty("sharedInts", gIODTSharedInterrupts); regIter = IORegistryIterator::iterateOver( gIODTPlane, kIORegistryIterateRecursively ); if (regIter) { while( (child = regIter->getNextObject())) { OSArray * array = OSDynamicCast(OSArray, child->getProperty( gIOInterruptSpecifiersKey )); for( UInt32 i = 0; array && (i < array->getCount()); i++) { IOOptionBits options; IOReturn ret = IODTGetInterruptOptions( child, i, &options ); if( (ret != kIOReturnSuccess) || options) IOLog("%s[%ld] %ld (%x)\n", child->getName(), i, options, ret); } } regIter->release(); } #endif allInts->release(); if( intMap) // set a key in the root to indicate we found NW interrupt mapping parent->setProperty( gIODTNWInterruptMappingKey, (OSObject *) gIODTNWInterruptMappingKey ); return( parent); }
static IORegistryEntry * MakeReferenceTable( DTEntry dtEntry, bool copy ) { IORegistryEntry *regEntry; OSDictionary *propTable; const OSSymbol *nameKey; OSData *data; const OSSymbol *sym; DTPropertyIterator dtIter; void *prop; unsigned int propSize; char *name; char location[ 32 ]; bool noLocation = true; regEntry = new IOService; if( regEntry && (false == regEntry->init())) { regEntry->release(); regEntry = 0; } if( regEntry && (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) { propTable = regEntry->getPropertyTable(); while( kSuccess == DTIterateProperties( dtIter, &name)) { if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) continue; if( copy) { nameKey = OSSymbol::withCString(name); data = OSData::withBytes(prop, propSize); } else { nameKey = OSSymbol::withCStringNoCopy(name); data = OSData::withBytesNoCopy(prop, propSize); } assert( nameKey && data ); propTable->setObject( nameKey, data); data->release(); nameKey->release(); if( nameKey == gIODTNameKey ) { if( copy) sym = OSSymbol::withCString( (const char *) prop); else sym = OSSymbol::withCStringNoCopy( (const char *) prop); regEntry->setName( sym ); sym->release(); } else if( nameKey == gIODTUnitKey ) { // all OF strings are null terminated... except this one if( propSize >= (int) sizeof(location)) propSize = sizeof(location) - 1; strncpy( location, (const char *) prop, propSize ); location[ propSize ] = 0; regEntry->setLocation( location ); propTable->removeObject( gIODTUnitKey ); noLocation = false; } else if(noLocation && (!strncmp(name, "reg", sizeof("reg")))) { // default location - override later snprintf(location, sizeof(location), "%X", *((uint32_t *) prop)); regEntry->setLocation( location ); } } DTDisposePropertyIterator( dtIter); } return( regEntry); }
/** * PE_init_platform * * Initialize the platform expert for ARM. */ void PE_init_platform(boolean_t vm_initialized, void * _args) { boot_args *args = (boot_args *)_args; if (PE_state.initialized == FALSE) { PE_early_puts("PE_init_platform: My name is Macintosh.\n"); PE_early_puts("PE_init_platform: Initializing for the first time.\n"); PE_state.initialized = TRUE; PE_state.bootArgs = _args; PE_state.deviceTreeHead = args->deviceTreeP; PE_state.video.v_baseAddr = args->Video.v_baseAddr; PE_state.video.v_rowBytes = args->Video.v_rowBytes; PE_state.video.v_width = args->Video.v_width; PE_state.video.v_height = args->Video.v_height; PE_state.video.v_depth = args->Video.v_depth; PE_state.video.v_display = args->Video.v_display; strcpy(PE_state.video.v_pixelFormat, "PPPPPPPP"); } if (!vm_initialized) { /* Initialize the device tree crap. */ PE_early_puts("PE_init_platform: Initializing device tree\n"); DTInit(PE_state.deviceTreeHead); PE_early_puts("PE_init_platform: Calling pe_identify_machine\n"); pe_identify_machine(NULL); } else { DTEntry entry; char* fversion, map; unsigned int size; pe_initialized = 1; kprintf("PE_init_platform: It sure is great to get out of that bag.\n"); PE_init_SocSupport(); /* Reset kputc. */ PE_kputc = gPESocDispatch.uart_putc; /* XXX: Real iOS kernel does iBoot/debug-enabled init after the DTInit call. */ if( kSuccess == DTLookupEntry(NULL, "/chosen", &entry)) { /* What's the iBoot version on this bad boy? */ if( kSuccess == DTGetProperty(entry, "firmware-version", (void **) &fversion, &size)) { if(fversion && (strlen(fversion) <= 32)) { ovbcopy((void*)fversion, (void*)firmware_version, strlen(fversion)); } } /* Is the SoC debug-enabled? */ if( kSuccess == DTGetProperty(entry, "debug-enabled", (void **) &map, &size)) { debug_enabled = 1; } } pe_arm_init_interrupts(NULL); } }