void IOPrintPlane( const IORegistryPlane * plane ) { IORegistryEntry * next; IORegistryIterator * iter; OSOrderedSet * all; char format[] = "%xxxs"; IOService * service; iter = IORegistryIterator::iterateOver( plane ); assert( iter ); all = iter->iterateAll(); if( all) { DEBG("Count %d\n", all->getCount() ); all->release(); } else DEBG("Empty\n"); iter->reset(); while( (next = iter->getNextObjectRecursive())) { snprintf(format + 1, sizeof(format) - 1, "%ds", 2 * next->getDepth( plane )); DEBG( format, ""); DEBG( "\033[33m%s", next->getName( plane )); if( (next->getLocation( plane ))) DEBG("@%s", next->getLocation( plane )); DEBG("\033[0m <class %s", next->getMetaClass()->getClassName()); if( (service = OSDynamicCast(IOService, next))) DEBG(", busy %ld", (long) service->getBusyState()); DEBG( ">\n"); // IOSleep(250); } iter->release(); }
// ====================================================================== void ListHookedDevice::Item::setDeviceIdentifier(void) { if (!device_) return; IORegistryEntry* dev = device_; while (dev) { const OSNumber* vid = nullptr; vid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDVendorIDKey)); const OSNumber* pid = nullptr; pid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDProductIDKey)); if (vid && pid) { deviceIdentifier_.setVendor(DeviceVendor(vid->unsigned32BitValue())); deviceIdentifier_.setProduct(DeviceProduct(pid->unsigned32BitValue())); goto finish; } else { // ApplePS2Keyboard does not have ProductID, // so we check for Manufacturer and Product strings const char* name = dev->getName(); if (name && strcmp(name, "ApplePS2Keyboard") == 0) { // kIOHIDManufacturerKey == "Manufacturer" // kIOHIDProductKey == "Product" const OSString* manufacturer = OSDynamicCast(OSString, dev->getProperty(kIOHIDManufacturerKey)); const OSString* product = OSDynamicCast(OSString, dev->getProperty(kIOHIDProductKey)); if (manufacturer && product) { if (manufacturer->isEqualTo("Apple") && product->isEqualTo("Keyboard")) { deviceIdentifier_.setVendor(DeviceVendor::APPLE_COMPUTER); deviceIdentifier_.setProduct(DeviceProduct::APPLE_INTERNAL_KEYBOARD_TRACKPAD_0x0218); goto finish; } } } } // check parent property. dev = dev->getParentEntry(IORegistryEntry::getPlane(kIOServicePlane)); } finish: // Set LocationID if (dev) { const OSNumber* locationid = nullptr; locationid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDLocationIDKey)); if (locationid) { deviceIdentifier_.setLocation(DeviceLocation(locationid->unsigned32BitValue())); } } IOLOG_DEBUG("HookedDevice::setVendorProductLocation device_:%p, vendor:0x%04x, product:0x%04x location:0x%04x\n", device_, deviceIdentifier_.getVendor().get(), deviceIdentifier_.getProduct().get(), deviceIdentifier_.getLocation().get()); }
void db_dumpiojunk( const IORegistryPlane * plane ) { IORegistryEntry * next; IORegistryIterator * iter; OSOrderedSet * all; char format[] = "%xxxs"; IOService * service; iter = IORegistryIterator::iterateOver( plane ); all = iter->iterateAll(); if( all) { dbugprintf("Count %d\n", all->getCount() ); all->release(); } else dbugprintf("Empty\n"); iter->reset(); while( (next = iter->getNextObjectRecursive())) { snprintf(format + 1, sizeof(format) - 1, "%ds", 2 * next->getDepth( plane )); dbugprintf( format, ""); dbugprintf( "%s", next->getName( plane )); if( (next->getLocation( plane ))) dbugprintf("@%s", next->getLocation( plane )); dbugprintf(" <class %s", next->getMetaClass()->getClassName()); if( (service = OSDynamicCast(IOService, next))) dbugprintf(", busy %ld", service->getBusyState()); dbugprintf( ">\n"); } iter->release(); }
IORegistryEntry *findEntryByPrefix(IORegistryEntry *entry, const char *prefix, const IORegistryPlane *plane, bool (*proc)(void *, IORegistryEntry *), bool brute, void *user) { bool found {false}; IORegistryEntry *res {nullptr}; size_t bruteCount {0}; do { bruteCount++; auto iterator = entry->getChildIterator(plane); if (iterator) { size_t len = strlen(prefix); while ((res = OSDynamicCast(IORegistryEntry, iterator->getNextObject())) != nullptr) { const char *resname = res->getName(); //DBGLOG("iokit @ iterating over %s", resname); if (!strncmp(prefix, resname, len)) { found = proc ? proc(user, res) : true; if (found) { if (bruteCount > 1) DBGLOG("iokit @ bruted %s value in %zu attempts", prefix, bruteCount); if (!proc) { break; } } } } iterator->release(); } else { SYSLOG("iokit @ failed to iterate over entry"); return nullptr; } } while (brute && bruteCount < bruteMax && !found); if (!found) DBGLOG("iokit @ failed to find %s", prefix); return proc ? nullptr : res; }
/* * Copyright (c) 1998-2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include <IOKit/IODeviceTreeSupport.h> #include <IOKit/IOMessage.h> #include <IOKit/storage/IOPartitionScheme.h> #define super IOStorage OSDefineMetaClassAndStructors(IOPartitionScheme, IOStorage) #ifndef __LP64__ extern IOStorageAttributes gIOStorageAttributesUnsupported; #endif /* !__LP64__ */ static SInt32 partitionComparison( const OSMetaClassBase * object1, const OSMetaClassBase * object2, void * context ) { // // Internal comparison routine for sorting partitions in an ordered set. // UInt64 base1 = ( ( IOMedia * ) object1 )->getBase( ); UInt64 base2 = ( ( IOMedia * ) object2 )->getBase( ); #if TARGET_OS_EMBEDDED OSString * uuid1 = OSDynamicCast( OSString, ( ( IOMedia * ) object1 )->getProperty( kIOMediaUUIDKey ) ); OSString * uuid2 = OSDynamicCast( OSString, ( ( IOMedia * ) object2 )->getProperty( kIOMediaUUIDKey ) ); if ( uuid1 || uuid2 ) { if ( uuid1 == 0 ) return -1; if ( uuid2 == 0 ) return 1; return strcmp( uuid2->getCStringNoCopy( ), uuid1->getCStringNoCopy( ) ); } #endif /* TARGET_OS_EMBEDDED */ if ( base1 < base2 ) return 1; if ( base1 > base2 ) return -1; return 0; } IOMedia * IOPartitionScheme::getProvider() const { // // Obtain this object's provider. We override the superclass's method // to return a more specific subclass of OSObject -- an IOMedia. This // method serves simply as a convenience to subclass developers. // return (IOMedia *) IOService::getProvider(); } bool IOPartitionScheme::init(OSDictionary * properties) { // // Initialize this object's minimal state. // if (super::init(properties) == false) return false; _openLevel = kIOStorageAccessNone; _openReaders = OSSet::withCapacity(16); _openReaderWriters = OSSet::withCapacity(16); if (_openReaders == 0 || _openReaderWriters == 0) return false; return true; } void IOPartitionScheme::free() { // // Free all of this object's outstanding resources. // if (_openReaders) _openReaders->release(); if (_openReaderWriters) _openReaderWriters->release(); super::free(); } bool IOPartitionScheme::handleOpen(IOService * client, IOOptionBits options, void * argument) { // // The handleOpen method grants or denies permission to access this object // to an interested client. The argument is an IOStorageAccess value that // specifies the level of access desired -- reader or reader-writer. // // This method can be invoked to upgrade or downgrade the access level for // an existing client as well. The previous access level will prevail for // upgrades that fail, of course. A downgrade should never fail. If the // new access level should be the same as the old for a given client, this // method will do nothing and return success. In all cases, one, singular // close-per-client is expected for all opens-per-client received. // // This implementation replaces the IOService definition of handleOpen(). // // We are guaranteed that no other opens or closes will be processed until // we make our decision, change our state, and return from this method. // IOStorageAccess access = (uintptr_t) argument; IOStorageAccess level; assert(client); assert( access == kIOStorageAccessReader || access == kIOStorageAccessReaderWriter ); // // A partition scheme multiplexes the opens it receives from several clients // and sends one open to the level below that satisfies the highest level of // access. // unsigned writers = _openReaderWriters->getCount(); if (_openReaderWriters->containsObject(client)) writers--; if (access == kIOStorageAccessReaderWriter) writers++; level = (writers) ? kIOStorageAccessReaderWriter : kIOStorageAccessReader; // // Determine whether the levels below us accept this open or not (we avoid // the open if the required access is the access we already hold). // if ( _openLevel != level ) { IOStorage * provider; provider = OSDynamicCast( IOStorage, getProvider( ) ); if ( provider ) { bool success; level = ( level | kIOStorageAccessSharedLock ); success = provider->open( this, options, level ); level = ( level & kIOStorageAccessReaderWriter ); if ( success == false ) { return false; } } } // // Process the open. // if (access == kIOStorageAccessReader) { _openReaders->setObject(client); _openReaderWriters->removeObject(client); // (for a downgrade) } else // (access == kIOStorageAccessReaderWriter) { _openReaderWriters->setObject(client); _openReaders->removeObject(client); // (for an upgrade) } _openLevel = level; return true; } bool IOPartitionScheme::handleIsOpen(const IOService * client) const { // // The handleIsOpen method determines whether the specified client, or any // client if none is specificed, presently has an open on this object. // // This implementation replaces the IOService definition of handleIsOpen(). // // We are guaranteed that no other opens or closes will be processed until // we return from this method. // if (client == 0) return (_openLevel != kIOStorageAccessNone); return ( _openReaderWriters->containsObject(client) || _openReaders->containsObject(client) ); } void IOPartitionScheme::handleClose(IOService * client, IOOptionBits options) { // // The handleClose method closes the client's access to this object. // // This implementation replaces the IOService definition of handleClose(). // // We are guaranteed that no other opens or closes will be processed until // we change our state and return from this method. // assert(client); // // Process the close. // if (_openReaderWriters->containsObject(client)) // (is it a reader-writer?) { _openReaderWriters->removeObject(client); } else if (_openReaders->containsObject(client)) // (is the client a reader?) { _openReaders->removeObject(client); } else // (is the client is an imposter?) { assert(0); return; } // // Reevaluate the open we have on the level below us. If no opens remain, // we close, or if no reader-writer remains, but readers do, we downgrade. // IOStorageAccess level; if (_openReaderWriters->getCount()) level = kIOStorageAccessReaderWriter; else if (_openReaders->getCount()) level = kIOStorageAccessReader; else level = kIOStorageAccessNone; if ( _openLevel != level ) { IOStorage * provider; provider = OSDynamicCast( IOStorage, getProvider( ) ); if ( provider ) { if ( level == kIOStorageAccessNone ) { provider->close( this, options ); } else { bool success; level = ( level | kIOStorageAccessSharedLock ); success = provider->open( this, 0, level ); level = ( level & kIOStorageAccessReaderWriter ); assert( success ); } } _openLevel = level; } } void IOPartitionScheme::read(IOService * client, UInt64 byteStart, IOMemoryDescriptor * buffer, IOStorageAttributes * attributes, IOStorageCompletion * completion) { // // Read data from the storage object at the specified byte offset into the // specified buffer, asynchronously. When the read completes, the caller // will be notified via the specified completion action. // // The buffer will be retained for the duration of the read. // // For simple partition schemes, the default behavior is to simply pass the // read through to the provider media. More complex partition schemes such // as RAID will need to do extra processing here. // #ifndef __LP64__ if ( IOStorage::_expansionData ) { if ( attributes == &gIOStorageAttributesUnsupported ) { attributes = NULL; } else { IOStorage::read( client, byteStart, buffer, attributes, completion ); return; } } #endif /* !__LP64__ */ getProvider( )->read( this, byteStart, buffer, attributes, completion ); } void IOPartitionScheme::write(IOService * client, UInt64 byteStart, IOMemoryDescriptor * buffer, IOStorageAttributes * attributes, IOStorageCompletion * completion) { // // Write data into the storage object at the specified byte offset from the // specified buffer, asynchronously. When the write completes, the caller // will be notified via the specified completion action. // // The buffer will be retained for the duration of the write. // // For simple partition schemes, the default behavior is to simply pass the // write through to the provider media. More complex partition schemes such // as RAID will need to do extra processing here. // #ifndef __LP64__ if ( IOStorage::_expansionData ) { if ( attributes == &gIOStorageAttributesUnsupported ) { attributes = NULL; } else { IOStorage::write( client, byteStart, buffer, attributes, completion ); return; } } #endif /* !__LP64__ */ getProvider( )->write( this, byteStart, buffer, attributes, completion ); } IOReturn IOPartitionScheme::synchronizeCache(IOService * client) { // // Flush the cached data in the storage object, if any, synchronously. // return getProvider()->synchronizeCache(this); } IOReturn IOPartitionScheme::unmap(IOService * client, IOStorageExtent * extents, UInt32 extentsCount, UInt32 options) { // // Delete unused data from the storage object at the specified byte offsets, // synchronously. // return getProvider( )->unmap( this, extents, extentsCount, options ); } bool IOPartitionScheme::lockPhysicalExtents(IOService * client) { // // Lock the contents of the storage object against relocation temporarily, // for the purpose of getting physical extents. // return getProvider( )->lockPhysicalExtents( this ); } IOStorage * IOPartitionScheme::copyPhysicalExtent(IOService * client, UInt64 * byteStart, UInt64 * byteCount) { // // Convert the specified byte offset into a physical byte offset, relative // to a physical storage object. This call should only be made within the // context of lockPhysicalExtents(). // return getProvider( )->copyPhysicalExtent( this, byteStart, byteCount ); } void IOPartitionScheme::unlockPhysicalExtents(IOService * client) { // // Unlock the contents of the storage object for relocation again. This // call must balance a successful call to lockPhysicalExtents(). // getProvider( )->unlockPhysicalExtents( this ); } #ifdef __LP64__ bool IOPartitionScheme::attachMediaObjectToDeviceTree(IOMedia * media) #else /* !__LP64__ */ bool IOPartitionScheme::attachMediaObjectToDeviceTree(IOMedia * media, IOOptionBits options) #endif /* !__LP64__ */ { // // Attach the given media object to the device tree plane. // IORegistryEntry * parent = this; while ( (parent = parent->getParentEntry(gIOServicePlane)) ) { if ( parent->inPlane(gIODTPlane) ) { char location[ 32 ]; const char * locationOfParent = parent->getLocation(gIODTPlane); const char * nameOfParent = parent->getName(gIODTPlane); if ( locationOfParent == 0 ) break; if ( OSDynamicCast(IOMedia, parent) == 0 ) break; parent = parent->getParentEntry(gIODTPlane); if ( parent == 0 ) break; if ( media->attachToParent(parent, gIODTPlane) == false ) break; strlcpy(location, locationOfParent, sizeof(location)); if ( strchr(location, ':') ) *(strchr(location, ':') + 1) = 0; strlcat(location, media->getLocation(), sizeof(location) - strlen(location)); media->setLocation(location, gIODTPlane); media->setName(nameOfParent, gIODTPlane); return true; } } return false; }
// ---------------------------------------------------------------------------------------------------- bool PlatformInterfaceDBDMA_Mapped::init ( IOService* device, AppleOnboardAudio* provider, UInt32 inDBDMADeviceIndex ) { bool result = FALSE; IOService* theService; IORegistryEntry *macio; IORegistryEntry *gpio; IORegistryEntry *i2s; IORegistryEntry *i2sParent; IOMemoryMap *map; debugIOLog ( 3, "+ PlatformInterfaceDBDMA_Mapped::init ( %p, %p, %d )", device, provider, inDBDMADeviceIndex ); FailIf ( NULL == provider, Exit ); FailIf ( NULL == device, Exit ); result = super::init ( device, provider, inDBDMADeviceIndex ); if ( result ) { mKeyLargoService = IOService::waitForService ( IOService::serviceMatching ( "KeyLargo" ) ); debugIOLog ( 3, " sound's name is %s", ( (IORegistryEntry*)device)->getName () ); i2s = ( ( IORegistryEntry*)device)->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2s, result = false, Exit ); debugIOLog ( 3, " parent name is '%s'", i2s->getName () ); if ( 0 == strcmp ( "i2s-a", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell0; } else if ( 0 == strcmp ( "i2s-b", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell1; } else if ( 0 == strcmp ( "i2s-c", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell2; } else if ( 0 == strcmp ( "i2s-d", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell3; } else if ( 0 == strcmp ( "i2s-e", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell4; } else if ( 0 == strcmp ( "i2s-f", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell5; } else if ( 0 == strcmp ( "i2s-g", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell6; } else if ( 0 == strcmp ( "i2s-h", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell7; } debugIOLog ( 5, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber ); i2sParent = i2s->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2sParent, result = false, Exit ); debugIOLog ( 3, " parent name of '%s' is %s", i2s->getName (), i2sParent->getName () ); macio = i2sParent->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == macio, result = false, Exit ); debugIOLog ( 3, " macio name is %s", macio->getName () ); gpio = macio->childFromPath ( kGPIODTEntry, gIODTPlane); FailWithAction ( !gpio, result = false, Exit); debugIOLog ( 3, " gpio name is %s", gpio->getName () ); theService = ( OSDynamicCast ( IOService, i2s ) ); FailWithAction ( !theService, result = false, Exit ); map = theService->mapDeviceMemoryWithIndex ( inDBDMADeviceIndex ); FailWithAction ( 0 == map, result = false, Exit ); // cache the config space mSoundConfigSpace = (UInt8 *)map->getPhysicalAddress(); // sets the clock base address figuring out which I2S cell we're on if ((((UInt32)mSoundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S0BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S0BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell0; } else if ((((UInt32)mSoundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S1BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S1BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell1; } else { debugIOLog (3, " AudioI2SControl::init ERROR: unable to setup ioBaseAddress and i2SInterfaceNumber"); } FailIf (NULL == mIOBaseAddressMemory, Exit); // [3060321] ioConfigurationBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOConfigurationBaseAddress = (void *)mIOBaseAddressMemory->map()->getVirtualAddress(); FailIf ( NULL == mIOConfigurationBaseAddress, Exit ); // // There are three sections of memory mapped I/O that are directly accessed by the Apple02Audio. These // include the GPIOs, I2S DMA Channel Registers and I2S control registers. They fall within the memory map // as follows: // ~ ~ // |______________________________| // | | // | I2S Control | // |______________________________| <- soundConfigSpace = ioBase + i2s0BaseOffset ...OR... ioBase + i2s1BaseOffset // | | // ~ ~ // ~ ~ // |______________________________| // | | // | I2S DMA Channel | // |______________________________| <- i2sDMA = ioBase + i2s0_DMA ...OR... ioBase + i2s1_DMA // | | // ~ ~ // ~ ~ // |______________________________| // | FCRs | // | GPIO | <- gpio = ioBase + gpioOffsetAddress // | ExtIntGPIO | <- fcr = ioBase + fcrOffsetAddress // |______________________________| <- ioConfigurationBaseAddress // | | // ~ ~ // // The I2S DMA Channel is mapped in by the Apple02DBDMAAudioDMAEngine. Only the I2S control registers are // mapped in by the AudioI2SControl. The Apple I/O Configuration Space (i.e. FCRs, GPIOs and ExtIntGPIOs) // are mapped in by the subclass of Apple02Audio. The FCRs must also be mapped in by the AudioI2SControl // object as the init method must enable the I2S I/O Module for which the AudioI2SControl object is // being instantiated for. // // The physical addresses for memory mapped I/O within the KeyLargo system I/O controller are as follows: // // // // ______________________________ // /| | // / | | // / |______________________________| // ______________________________ / | | // | | | I2S 1 ('i2s-b') | // | | |______________________________|....0xnnn11000 [0x80011000] // | | | | // | | | I2S 0 ('i2s-a') | // | | |______________________________|....0xnnn10000 [0x80001000] // | Device Registers | / // | | / // | | / ______________________________ // | |/ /| | // |______________________________|__/ | | // | | |______________________________| // | | | | // | | | I2S 1 Rx DMA ('i2s-b') | // | | |______________________________|....0xnnn08300 [0x80008300] // | DMA Channel Registers | | | // | | | I2S 1 Tx DMA ('i2s-b') | // | | |______________________________|....0xnnn08200 [0x80008200] // | | | | // |______________________________| | I2S 0 Rx DMA ('i2s-a') | // | |\ |______________________________|....0xnnn08100 [0x80008100] // | | \ | | // | Reserved: read "0" | \ | I2S 0 Tx DMA ('i2s-a') | // | | \|______________________________|....0xnnn08000 [0x80008000] // |______________________________| // | | // | | // | Apple I/O Configuration | // | | // |______________________________|....0xnnn00000 [0x80011000] // // Map the I2S configuration registers mIOI2SBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace), kI2S_IO_CONFIGURATION_SIZE); FailIf ( NULL == mIOI2SBaseAddressMemory, Exit ); mI2SBaseAddress = (void *)mIOI2SBaseAddressMemory->map()->getVirtualAddress(); FailIf (NULL == mI2SBaseAddress, Exit); debugIOLog (3, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber); debugIOLog (3, " mIOI2SBaseAddressMemory = %p", mIOI2SBaseAddressMemory); debugIOLog (3, " mI2SBaseAddress = %p", mI2SBaseAddress); debugIOLog (3, " mIOBaseAddressMemory = %p", mIOBaseAddressMemory); debugIOLog (3, " mIOConfigurationBaseAddress = %p", mIOConfigurationBaseAddress); } Exit: debugIOLog ( 3, "- PlatformInterfaceDBDMA_Mapped::init ( %p, %p, %d ) returns %lX", device, provider, inDBDMADeviceIndex, result ); return result; }
void FileNVRAM::copyEntryProperties(const char* prefix, IORegistryEntry* entry) { IORegistryEntry* child; OSDictionary* properties; OSCollectionIterator *iter; if (entry) { // Parse all IORegistery Children OSIterator * iterator = entry->getChildIterator(gIODTPlane); if (iterator) { while((child = OSDynamicCast(IORegistryEntry, iterator->getNextObject())) != NULL) { const char* name = child->getName(); if (prefix) { size_t size = strlen(prefix) + sizeof(NVRAM_SEPERATOR) + strlen(name); char* newPrefix = (char*)IOMalloc(size); snprintf(newPrefix, size, "%s%s%s", prefix, NVRAM_SEPERATOR, name); copyEntryProperties(newPrefix, child); IOFree(newPrefix, size); } else { copyEntryProperties(name, child); } } iterator->release(); } // Parse entry properties and add them to our self properties = entry->dictionaryWithProperties(); bool result = true; OSObject *object; const OSSymbol *key; iter = OSCollectionIterator::withCollection(properties); if (iter == 0) { return; } while (result) { key = OSDynamicCast(OSSymbol, iter->getNextObject()); if (key == 0) { break; } if (key->isEqualTo("name")) { continue; // Special property in IORegistery, ignore } object = properties->getObject(key); if (object == 0) { continue; } if (prefix) { size_t size = strlen(prefix) + sizeof(NVRAM_SEPERATOR) + strlen(key->getCStringNoCopy()); char* newKey = (char*)IOMalloc(size); snprintf(newKey, size, "%s%s%s", prefix, NVRAM_SEPERATOR, key->getCStringNoCopy()); setProperty(OSSymbol::withCString(newKey), object); IOFree(newKey, size); } else { setProperty(key, object); } } iter->release(); } }
IORegistryEntry * IODeviceTreeAlloc( void * dtTop ) { IORegistryEntry * parent; IORegistryEntry * child; IORegistryIterator * regIter; DTEntryIterator iter; DTEntry dtChild; DTEntry mapEntry; OSArray * stack; OSData * prop; OSDictionary * allInts; vm_offset_t * dtMap; unsigned int propSize; bool intMap; bool freeDT; gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane ); gIODTNameKey = OSSymbol::withCStringNoCopy( "name" ); gIODTUnitKey = OSSymbol::withCStringNoCopy( "AAPL,unit-string" ); gIODTCompatibleKey = OSSymbol::withCStringNoCopy( "compatible" ); gIODTTypeKey = OSSymbol::withCStringNoCopy( "device_type" ); gIODTModelKey = OSSymbol::withCStringNoCopy( "model" ); gIODTSizeCellKey = OSSymbol::withCStringNoCopy( "#size-cells" ); gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" ); gIODTRangeKey = OSSymbol::withCStringNoCopy( "ranges" ); gIODTPersistKey = OSSymbol::withCStringNoCopy( "IODTPersist" ); assert( gIODTPlane && gIODTCompatibleKey && gIODTTypeKey && gIODTModelKey && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey && gIODTPersistKey ); gIODTDefaultInterruptController = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController"); gIODTNWInterruptMappingKey = OSSymbol::withCStringNoCopy("IONWInterrupts"); gIODTAAPLInterruptsKey = OSSymbol::withCStringNoCopy("AAPL,interrupts"); gIODTPHandleKey = OSSymbol::withCStringNoCopy("AAPL,phandle"); gIODTInterruptParentKey = OSSymbol::withCStringNoCopy("interrupt-parent"); gIODTPHandles = OSArray::withCapacity( 1 ); gIODTPHandleMap = OSArray::withCapacity( 1 ); gIODTInterruptCellKey = OSSymbol::withCStringNoCopy("#interrupt-cells"); assert( gIODTDefaultInterruptController && gIODTNWInterruptMappingKey && gIODTAAPLInterruptsKey && gIODTPHandleKey && gIODTInterruptParentKey && gIODTPHandles && gIODTPHandleMap && gIODTInterruptCellKey ); freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry )) && (kSuccess == DTGetProperty( mapEntry, "DeviceTree", (void **) &dtMap, &propSize )) && ((2 * sizeof(uint32_t)) == propSize); parent = MakeReferenceTable( (DTEntry)dtTop, freeDT ); stack = OSArray::withObjects( (const OSObject **) &parent, 1, 10 ); DTCreateEntryIterator( (DTEntry)dtTop, &iter ); do { parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1); //parent->release(); stack->removeObject( stack->getCount() - 1); while( kSuccess == DTIterateEntries( iter, &dtChild) ) { child = MakeReferenceTable( dtChild, freeDT ); child->attachToParent( parent, gIODTPlane); AddPHandle( child ); if( kSuccess == DTEnterEntry( iter, dtChild)) { stack->setObject( parent); parent = child; } // only registry holds retain child->release(); } } while( stack->getCount() && (kSuccess == DTExitEntry( iter, &dtChild))); stack->release(); DTDisposeEntryIterator( iter); // parent is now root of the created tree // make root name first compatible entry (purely cosmetic) if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) { parent->setName( parent->getName(), gIODTPlane ); parent->setName( (const char *) prop->getBytesNoCopy() ); } // attach tree to meta root parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane); parent->release(); if( freeDT ) { // free original device tree DTInit(0); IODTFreeLoaderInfo( "DeviceTree", (void *)dtMap[0], (int) round_page(dtMap[1]) ); } // adjust tree gIODTSharedInterrupts = OSDictionary::withCapacity(4); allInts = OSDictionary::withCapacity(4); intMap = false; regIter = IORegistryIterator::iterateOver( gIODTPlane, kIORegistryIterateRecursively ); assert( regIter && allInts && gIODTSharedInterrupts ); if( regIter && allInts && gIODTSharedInterrupts ) { while( (child = regIter->getNextObject())) { IODTMapInterruptsSharing( child, allInts ); if( !intMap && child->getProperty( gIODTInterruptParentKey)) intMap = true; } regIter->release(); } #if IODTSUPPORTDEBUG parent->setProperty("allInts", allInts); parent->setProperty("sharedInts", gIODTSharedInterrupts); regIter = IORegistryIterator::iterateOver( gIODTPlane, kIORegistryIterateRecursively ); if (regIter) { while( (child = regIter->getNextObject())) { OSArray * array = OSDynamicCast(OSArray, child->getProperty( gIOInterruptSpecifiersKey )); for( UInt32 i = 0; array && (i < array->getCount()); i++) { IOOptionBits options; IOReturn ret = IODTGetInterruptOptions( child, i, &options ); if( (ret != kIOReturnSuccess) || options) IOLog("%s[%ld] %ld (%x)\n", child->getName(), i, options, ret); } } regIter->release(); } #endif allInts->release(); if( intMap) // set a key in the root to indicate we found NW interrupt mapping parent->setProperty( gIODTNWInterruptMappingKey, (OSObject *) gIODTNWInterruptMappingKey ); return( parent); }
UInt32 FakeSMCDevice::loadKeysFromNVRAM() { UInt32 count = 0; // Find driver and load keys from NVRAM // check for Chameleon NVRAM key first (because waiting for IODTNVRAM hangs) IORegistryEntry* nvram = IORegistryEntry::fromPath("/chosen/nvram", gIODTPlane); OSDictionary* matching = 0; if (!nvram) { // probably booting w/ Clover matching = serviceMatching("IODTNVRAM"); nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15)); } if (1) { //REVIEW: just to reduce diffs if (nvram) { useNVRAM = true; if ((genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", sizeof("AppleNVRAM"))))) HWSensorsInfoLog("fallback to generic NVRAM methods"); OSSerialize *s = OSSerialize::withCapacity(0); // Workaround for IODTNVRAM->getPropertyTable returns IOKitPersonalities instead of NVRAM properties dictionary if (nvram->serializeProperties(s)) { if (OSDictionary *props = OSDynamicCast(OSDictionary, OSUnserializeXML(s->text()))) { if (OSCollectionIterator *iterator = OSCollectionIterator::withCollection(props)) { size_t prefix_length = strlen(kFakeSMCKeyPropertyPrefix); char name[5]; name[4] = 0; char type[5]; type[4] = 0; while (OSString *property = OSDynamicCast(OSString, iterator->getNextObject())) { const char *buffer = static_cast<const char *>(property->getCStringNoCopy()); if (property->getLength() >= prefix_length + 1 + 4 + 1 + 0 && 0 == strncmp(buffer, kFakeSMCKeyPropertyPrefix, prefix_length)) { if (OSData *data = OSDynamicCast(OSData, props->getObject(property))) { strncpy(name, buffer + prefix_length + 1, 4); // fakesmc-key-???? -> strncpy(type, buffer + prefix_length + 1 + 4 + 1, 4); // fakesmc-key-xxxx-???? -> if (addKeyWithValue(name, type, data->getLength(), data->getBytesNoCopy())) { HWSensorsDebugLog("key %s of type %s loaded from NVRAM", name, type); count++; } } } } OSSafeRelease(iterator); } OSSafeRelease(props); } } OSSafeRelease(s); OSSafeRelease(nvram); } else { HWSensorsWarningLog("NVRAM is unavailable"); } OSSafeRelease(matching); } return count; }
IOReturn IOI2CMaxim1631::publishChildren(IOService *nub) { OSIterator *childIterator = NULL; IORegistryEntry *childEntry = NULL; IOService *childNub = NULL; childIterator = nub->getChildIterator(gIODTPlane); if( childIterator != NULL ) { // Iterate through children and create nubs while ( ( childEntry = (IORegistryEntry *)( childIterator->getNextObject() ) ) != NULL ) { // Publish child as IOService childNub = OSDynamicCast(IOService, OSMetaClass::allocClassWithName("IOService")); childNub->init(childEntry, gIODTPlane); childNub->attach(this); childNub->registerService(); DLOG("IOI2CMaxim1631::publishChildren(0x%x) published child %s\n", getI2CAddress(), childEntry->getName()); } childIterator->release(); } return kIOReturnSuccess; }