// ====================================================================== 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 ListHookedDevice::Item::setVendorProduct(void) { if (! device_) return; IORegistryEntry* dev = device_; while (dev) { const OSNumber* vid = NULL; vid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDVendorIDKey)); const OSNumber* pid = NULL; pid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDProductIDKey)); if (vid && pid) { vendor_ = vid->unsigned32BitValue(); product_ = pid->unsigned32BitValue(); goto finish; } // check parent property. dev = dev->getParentEntry(IORegistryEntry::getPlane(kIOServicePlane)); } finish: IOLOG_DEBUG("HookedDevice::setVendorProduct device_:%p, vendor_:0x%04x, product_:0x%04x\n", device_, vendor_.get(), product_.get()); }
/* * 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; }
IOService * IOPMPagingPlexus::findProvider ( IOService * mediaObject ) { IORegistryEntry * node = mediaObject; if ( mediaObject == NULL ) { return NULL; } while ( node ) { if ( node->inPlane(gIOPowerPlane) ) { return (IOService *)node; } node = node->getParentEntry(gIOServicePlane); } return NULL; }
IOReturn IOPolledFilePollersClose(IOPolledFileIOVars * filevars, uint32_t state) { IOPolledFilePollers * vars = filevars->pollers; IOPolledInterface * poller; IORegistryEntry * next; IOReturn err; int32_t idx; (void) IOPolledFilePollersIODone(vars, false); if (kIOPolledPostflightState == state) { vars->openCount--; if (vars->openCount) { // 21207427 IOPolledFilePollersOpen(filevars, vars->openState, vars->abortable); return (kIOReturnSuccess); } } for (idx = 0, err = kIOReturnSuccess; (poller = (IOPolledInterface *) vars->pollers->getObject(idx)); idx++) { err = poller->close(state); if (err) HIBLOG("IOPolledInterface::close[%d] 0x%x\n", idx, err); } if (kIOPolledPostflightState == state) { next = vars->media; while (next) { next->removeProperty(kIOPolledInterfaceActiveKey); next = next->getParentEntry(gIOServicePlane); } if (vars->ioBuffer) { vars->ioBuffer->release(); vars->ioBuffer = 0; } } return (err); }
void IOPMPagingPlexus::processSiblings ( IOService * aNode ) { OSIterator * parentIterator; IORegistryEntry * nextNub; IORegistryEntry * nextParent; OSIterator * siblingIterator; IORegistryEntry * nextSibling; parentIterator = aNode->getParentIterator(gIOPowerPlane); // iterate parents of this node if ( parentIterator ) { while ( true ) { if ( ! (nextNub = (IORegistryEntry *)(parentIterator->getNextObject())) ) { parentIterator->release(); break; } if ( OSDynamicCast(IOPowerConnection,nextNub) ) { nextParent = nextNub->getParentEntry(gIOPowerPlane); if ( nextParent == getPMRootDomain() ) { continue; // plexus already has root's children } if ( nextParent == this ) { parentIterator->release(); removePowerChild((IOPowerConnection *)nextNub); break; } siblingIterator = nextParent->getChildIterator(gIOPowerPlane); // iterate children of this parent if ( siblingIterator ) { while ( (nextSibling = (IORegistryEntry *)(siblingIterator->getNextObject())) ) { if ( OSDynamicCast(IOPowerConnection,nextSibling) ) { nextSibling = nextSibling->getChildEntry(gIOPowerPlane); if ( nextSibling != aNode ) { // non-ancestor of driver gets addPowerChild((IOService *)nextSibling); // plexus as parent } } } siblingIterator->release(); } processSiblings((IOService *)nextParent); // do the same thing to this parent } } } }
// ---------------------------------------------------------------------- bool org_pqrs_driver_Seil::isTargetDevice(IOHIKeyboard* kbd) { if (!kbd) return false; // ------------------------------------------------------------ uint32_t vendorID = 0; uint32_t productID = 0; IORegistryEntry* dev = kbd; 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) { vendorID = vid->unsigned32BitValue(); productID = pid->unsigned32BitValue(); goto finish; } // check parent property. dev = dev->getParentEntry(IORegistryEntry::getPlane(kIOServicePlane)); } finish: enum { VENDOR_LOGITECH = 0x046d, PRODUCT_LOGITECH_G700_LASER_MOUSE = 0xc06b, }; if (vendorID == VENDOR_LOGITECH && productID == PRODUCT_LOGITECH_G700_LASER_MOUSE) { IOLOG_INFO("vendorID:0x%04x, productID:0x%04x (skipped)\n", vendorID, productID); return false; } return true; }
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(); } }
IOPolledFilePollers * IOPolledFilePollers::copyPollers(IOService * media) { IOPolledFilePollers * vars; IOReturn err; IOService * service; OSObject * obj; IORegistryEntry * next; IORegistryEntry * child; if ((obj = media->copyProperty(kIOPolledInterfaceStackKey))) { return (OSDynamicCast(IOPolledFilePollers, obj)); } do { vars = OSTypeAlloc(IOPolledFilePollers); vars->init(); vars->pollers = OSArray::withCapacity(4); if (!vars->pollers) { err = kIOReturnNoMemory; break; } next = vars->media = media; do { IOPolledInterface * poller; OSObject * obj; obj = next->getProperty(kIOPolledInterfaceSupportKey); if (kOSBooleanFalse == obj) { vars->pollers->flushCollection(); break; } else if ((poller = OSDynamicCast(IOPolledInterface, obj))) vars->pollers->setObject(poller); if ((service = OSDynamicCast(IOService, next)) && service->getDeviceMemory() && !vars->pollers->getCount()) break; child = next; } while ((next = child->getParentEntry(gIOServicePlane)) && child->isParent(next, gIOServicePlane, true)); if (!vars->pollers->getCount()) { err = kIOReturnUnsupported; break; } } while (false); media->setProperty(kIOPolledInterfaceStackKey, vars); return (vars); }