Example #1
0
IOReturn AppleUSBCDC::setPropertiesAction(	OSObject	*owner, 
														void		*arg1, 
														void		*arg2, 
														void		*arg3, 
														void		*arg4 )
{
	IOReturn result = kIOReturnBadArgument;
	
	if ( owner != NULL )
	{
		AppleUSBCDC *me = OSDynamicCast( AppleUSBCDC, owner );
		
		if ( me != NULL )
		{
			result = me->setPropertiesWL( (OSObject *)arg1 );
		}
	}
	
	return result;
}
Example #2
0
/******************************************************************************
 * ACPIDebug::init
 ******************************************************************************/
bool ACPIDebug::init(OSDictionary *dict)
{
    DEBUG_LOG("ACPIDebug::init: Initializing\n");
    
    bool result = super::init(dict);
    m_pDevice = NULL;
    m_pWorkLoop = NULL;
    m_pTimer = NULL;
    m_pCmdGate = NULL;
    m_pLock = NULL;
    
    m_nPollingInterval = 100;
	if (OSNumber* num = OSDynamicCast(OSNumber, dict->getObject("PollingInterval")))
    {
		m_nPollingInterval = (int)num->unsigned32BitValue();
        //setProperty("PollingInterval", _wakedelay, 32);
    }
    
    return result;
}
Example #3
0
IOReturn IT87x::callPlatformFunction(const OSSymbol *functionName, bool waitForFunction, void *param1, void *param2, void *param3, void *param4 )
{
	if (functionName->isEqualTo(kFakeSMCGetValueCallback)) {
		const char* name = (const char*)param1;
		void * data = param2;
		//UInt32 size = (UInt64)param3;
		
        
		if (name && data)
			if (SuperIOSensor * sensor = getSensor(name)) {
				UInt16 value = sensor->getValue();
				
				bcopy(&value, data, 2);
				
				return kIOReturnSuccess;
			}
		
		return kIOReturnBadArgument;
	}
    
	if (functionName->isEqualTo(kFakeSMCSetValueCallback)) {
		const char* name = (const char*)param1;
		void * data = param2;
		//UInt32 size = (UInt64)param3;
		
        
		if (name && data)
			if (IT87xSensor *sensor = OSDynamicCast(IT87xSensor, getSensor(name))) {
				UInt16 value;
                bcopy(data, &value, 2);
				sensor->setValue(value);
				
				
				return kIOReturnSuccess;
			}
		
		return kIOReturnBadArgument;
	}    
    
	return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4);
}
Example #4
0
IOReturn X3100monitor::callPlatformFunction(const OSSymbol *functionName, bool waitForFunction, void *param1, void *param2, void *param3, void *param4 )
{
	UInt16 t;

	if (functionName->isEqualTo(kFakeSMCGetValueCallback)) {
		const char* name = (const char*)param1;
		void* data = param2;
		
		if (name && data) {
			if (OSNumber *number = OSDynamicCast(OSNumber, sensors->getObject(name))) {				
				UInt32 index = number->unsigned16BitValue();
				if (index != numCard) {
					return kIOReturnBadArgument;
				}
			}
			short value;
			if (mmio_base) {
				OUTVID(TIC1, 3);
				//		if ((INVID16(TSC1) & (1<<15)) && !(INVID16(TSC1) & (1<<8)))//enabled and ready
				for (int i=0; i<1000; i++) {  //attempts to ready
					
					if (INVID16(TSS1) & (1<<10))   //valid?
						break;
					IOSleep(10);
				}				
				value = INVID8(TR1);
			}				
			
			t = 140 - value;
			bcopy(&t, data, 2);
			
			return kIOReturnSuccess;
		}
		
		//DebugLog("bad argument key name or data");
		
		return kIOReturnBadArgument;
	}
	
	return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4);
}
bool NullEthernet::start(IOService *provider)
{
    DebugLog("start() ===>\n");

    if (!super::start(provider))
    {
        AlwaysLog("NullEthernet: IOEthernetController::start failed.\n");
        return false;
    }

    // retain provider...
    m_pProvider = OSDynamicCast(IOService, provider);
    if (!m_pProvider)
    {
        AlwaysLog("NullEthernet: No provider.\n");
        return false;
    }
    m_pProvider->retain();

    // initialize MAC address: priority is from DSDT, then provider, last is default
    if (!initMACfromACPI() && !initMACfromProvider())
    {
        AlwaysLog("Using default MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", m_rgMacAddr[0], m_rgMacAddr[1], m_rgMacAddr[2], m_rgMacAddr[3], m_rgMacAddr[4], m_rgMacAddr[5]);
    }
    
    if (!attachInterface(reinterpret_cast<IONetworkInterface**>(&m_netif)))
    {
        AlwaysLog("NullEthernet: attachInterface() failed.\n");
        goto error1;
    }

    AlwaysLog("NullEthernet: NullEthernet v1.0.0 starting.\n");

done:
    DebugLog("start() <===\n");
    return true;

error1:
    OSSafeReleaseNULL(m_pProvider);
    return false;
}
Example #6
0
bool CLASS::init( IOService *       provider,
                  OSDictionary *    properties,
                  IORegistryEntry * dtEntry )
{
    if ( dtEntry )
    {
        if ( super::init( dtEntry, gIODTPlane ) == false ||
             mergeProperties( properties ) == false )
             return false;
    }
    else
    {
        if ( super::init( properties ) == false )
             return false;
    }

    fProvider = OSDynamicCast(AppleOnboardPCATARoot, provider);
    if (fProvider == 0)
        return false;

    // Call platform to register the interrupt assigned to each ATA
    // channel. For PCI interrupts (native mode), each channel will
    // share the same interrupt vector assigned to the PCI device.
    // Legacy mode channels will attempt to register IRQ 14 and 15.

    UInt32 vector = getInterruptVector();
    if (provider->callPlatformFunction( "SetDeviceInterrupts",
                   /* waitForFunction */ false,
                   /* nub             */ this,
                   /* vectors         */ (void *) &vector,
                   /* vectorCount     */ (void *) 1,
                   /* exclusive       */ (void *) false )
                                         != kIOReturnSuccess)
    {
        return false;
    }

    setLocation( getChannelNumber() ? "1" : "0" );

    return true;
}
  bool
  ListHookedKeyboard::Item::restoreEventAction(void)
  {
    if (! device_) return false;

    IOHIKeyboard* kbd = OSDynamicCast(IOHIKeyboard, device_);
    if (! kbd) return false;

    bool result = false;

    // ----------------------------------------
    {
      KeyboardEventCallback callback = reinterpret_cast<KeyboardEventCallback>(kbd->_keyboardEventAction);
      if (callback == EventInputQueue::push_KeyboardEventCallback) {
        IOLOG_DEBUG("HookedKeyboard::restoreEventAction (KeyboardEventCallback) device_:%p (%p -> %p)\n",
                    device_, callback, orig_keyboardEventAction_);

        kbd->_keyboardEventAction = reinterpret_cast<KeyboardEventAction>(orig_keyboardEventAction_);

        result = true;
      }
    }
    {
      UpdateEventFlagsCallback callback = reinterpret_cast<UpdateEventFlagsCallback>(kbd->_updateEventFlagsAction);
      if (callback == EventInputQueue::push_UpdateEventFlagsCallback) {
        IOLOG_DEBUG("HookedKeyboard::restoreEventAction (UpdateEventFlagsCallback) device_:%p (%p -> %p)\n",
                    device_, callback, orig_updateEventFlagsAction_);

        kbd->_updateEventFlagsAction = reinterpret_cast<UpdateEventFlagsAction>(orig_updateEventFlagsAction_);

        result = true;
      }
    }

    orig_keyboardEventAction_ = NULL;
    orig_keyboardEventTarget_ = NULL;
    orig_updateEventFlagsAction_ = NULL;
    orig_updateEventFlagsTarget_ = NULL;

    return result;
  }
bool IOHIDDeviceShim::handleStart( IOService * provider )
{
    IOService *device = 0;
    
    if (!super::handleStart(provider))
        return false;

    if ((_hiDevice = OSDynamicCast(IOHIDevice, provider)))
    {
        if (_hiDevice->getProperty(kIOHIDVirtualHIDevice) == kOSBooleanTrue)
            return false;
            
        device = _hiDevice;
        do {
			if ((_device = (IOService *)device->metaCast("IOHIDDevice")))
			{
				break;
			}
			
            if ((_device = (IOService *)device->metaCast("IOUSBDevice")) || (_device = (IOService *)device->metaCast("IOUSBInterface")))
            {
                _transport = kIOHIDTransportUSB;
                break;
            }
                
			if (_device = (IOService *)device->metaCast("IOADBDevice"))
            {
                _transport = kIOHIDTransportADB;
                break;
            }
            
			if (_device = (IOService *)device->metaCast("ApplePS2Controller"))
            {
                _transport = kIOHIDTransportPS2;
                break;
            }
        } while (device = device->getProvider());
    }
                
    return true;
}
  bool
  ListHookedPointing::Item::restoreEventAction(void)
  {
    if (! device_) return false;

    IOHIPointing* pointing = OSDynamicCast(IOHIPointing, device_);
    if (! pointing) return false;

    bool result = false;

    // ----------------------------------------
    {
      RelativePointerEventCallback callback = reinterpret_cast<RelativePointerEventCallback>(pointing->_relativePointerEventAction);

      if (callback == EventInputQueue::push_RelativePointerEventCallback) {
        IOLOG_DEBUG("HookedPointing::restoreEventAction (RelativePointerEventCallback) device_:%p\n", device_);

        pointing->_relativePointerEventAction = reinterpret_cast<RelativePointerEventAction>(orig_relativePointerEventAction_);

        result = true;
      }
    }
    {
      ScrollWheelEventCallback callback = reinterpret_cast<ScrollWheelEventCallback>(pointing->_scrollWheelEventAction);

      if (callback == EventInputQueue::push_ScrollWheelEventCallback) {
        IOLOG_DEBUG("HookedPointing::restoreEventAction (ScrollWheelEventCallback) device_:%p\n", device_);

        pointing->_scrollWheelEventAction = reinterpret_cast<ScrollWheelEventAction>(orig_scrollWheelEventAction_);

        result = true;
      }
    }

    orig_relativePointerEventAction_ = NULL;
    orig_scrollWheelEventAction_ = NULL;
    orig_relativePointerEventTarget_ = NULL;
    orig_scrollWheelEventTarget_ = NULL;

    return result;
  }
  bool
  ListHookedConsumer::Item::replaceEventAction(void)
  {
    if (! device_) return false;

    IOHIKeyboard* kbd = OSDynamicCast(IOHIKeyboard, device_);
    if (! kbd) return false;

    KeyboardSpecialEventCallback callback = reinterpret_cast<KeyboardSpecialEventCallback>(kbd->_keyboardSpecialEventAction);
    if (callback == EventInputQueue::push_KeyboardSpecialEventCallback) return false;

    // ------------------------------------------------------------
    IOLOG_DEBUG("HookedConsumer::replaceEventAction device_:%p\n", device_);

    orig_keyboardSpecialEventAction_ = callback;
    orig_keyboardSpecialEventTarget_ = kbd->_keyboardSpecialEventTarget;

    kbd->_keyboardSpecialEventAction = reinterpret_cast<KeyboardSpecialEventAction>(EventInputQueue::push_KeyboardSpecialEventCallback);

    return true;
  }
  void
  EventInputQueue::push_UpdateEventFlagsCallback(OSObject* target,
                                                 unsigned flags,
                                                 OSObject* sender,
                                                 void* refcon)
  {
    GlobalLock::ScopedLock lk;
    if (! lk) return;

    Params_UpdateEventFlagsCallback::log(true, Flags(flags));

    // ------------------------------------------------------------
    // update device priority by calling ListHookedKeyboard::instance().get(kbd).
    IOHIKeyboard* device = OSDynamicCast(IOHIKeyboard, sender);
    if (! device) return;

    ListHookedKeyboard::Item* item = static_cast<ListHookedKeyboard::Item*>(ListHookedKeyboard::instance().get(device));
    if (! item) return;

    // Don't push_back for UpdateEventFlagsCallback.
  }
Example #12
0
void
IOI2CDevice::performFunctionsWithFlags(
	UInt32				flags)
{
	UInt32				count, i;
	IOPlatformFunction	*func;

	if (0 == fPlatformFuncArray)
		return;

	// Execute any functions flagged as "on sleep"
	count = fPlatformFuncArray->getCount();
	for (i = 0; i < count; i++)
	{
		if (func = OSDynamicCast(IOPlatformFunction, fPlatformFuncArray->getObject(i)))
		{
			if (func->getCommandFlags() & flags)
				performFunction(func);
		}
	}
}
Example #13
0
void ListHookedKeyboard::Item::apply(const Params_UpdateEventFlagsCallback& params) {
  // ------------------------------------------------------------
  UpdateEventFlagsCallback callback = orig_updateEventFlagsAction_;
  if (!callback) return;

  OSObject* target = orig_updateEventFlagsTarget_;
  if (!target) return;

  OSObject* sender = OSDynamicCast(OSObject, device_);
  if (!sender) return;

  OSObject* refcon = nullptr;

  Params_UpdateEventFlagsCallback::log(false, params.flags);
  {
    // We need to unlock the global lock while we are calling the callback function.
    // For more information, See ListHookedKeyboard::Item::apply(const Params_KeyboardEventCallBack& params)
    GlobalLock::ScopedUnlock lk;
    callback(target, params.flags.get(), sender, refcon);
  }
}
  bool
  HookedKeyboard::restoreEventAction(void)
  {
    if (! device_) return false;

    IOHIKeyboard* kbd = OSDynamicCast(IOHIKeyboard, device_);
    if (! kbd) return false;

    KeyboardEventCallback callback = reinterpret_cast<KeyboardEventCallback>(kbd->_keyboardEventAction);
    if (callback != hook_KeyboardEventCallback) return false;

    // ----------------------------------------
    IOLog("KeyRemap4MacBook HookedKeyboard::restoreEventAction (device_ = 0x%p)\n", device_);

    kbd->_keyboardEventAction = reinterpret_cast<KeyboardEventAction>(orig_keyboardEventAction_);

    orig_keyboardEventAction_ = NULL;
    orig_keyboardEventTarget_ = NULL;

    return true;
  }
bool com_ximeta_driver_NDASPhysicalUnitDevice::sendNDASFamilyIOMessage(UInt32 type, void * argument, vm_size_t argSize) 
{
	if (!fDevice) {
		return false;
	}
	
	com_ximeta_driver_NDASBusEnumerator	*bus;
	
	bus = OSDynamicCast(com_ximeta_driver_NDASBusEnumerator, 
						fDevice->getParentEntry(gIOServicePlane));
	
	if (NULL == bus) {
		DbgIOLog(DEBUG_MASK_NDAS_INFO, ("sendNDASFamilyIIOMessage: Can't Find bus.\n"));
		
		return false;
	} else {
		bus->messageClients(type, argument, argSize);
		
		return true;
	}
}	
bool com_ximeta_driver_NDASPhysicalUnitDevice::processSRBCommand(com_ximeta_driver_NDASCommand *command)
{
	com_ximeta_driver_NDASDeviceController *deviceController;
	
	// Send Command.
	deviceController = OSDynamicCast(com_ximeta_driver_NDASDeviceController, 
									 getParentEntry(gIOServicePlane));
	if (NULL == deviceController) {
		DbgIOLog(DEBUG_MASK_NDAS_ERROR, ("readSectorsOnce: Can't Find controller.\n"));
		
		return false;		
	}
	
	// Set Target Number.
	command->scsiCommand()->targetNo = unitNumber();
	command->scsiCommand()->device = this;
	
	deviceController->enqueueCommand(command);
	
	return true;
}
Example #17
0
void AppleGPIO::publishStrings(OSCollection *strings)
{
	OSCollectionIterator	*strIter;
	OSSymbol				*key;

	if (!strings) return;

	strIter = OSCollectionIterator::withCollection(strings);

	if (strIter)
	{
		while ((key = OSDynamicCast(OSSymbol, strIter->getNextObject())) != 0)
		{
			//DLOG("AppleGPIO::publishStrings 0x%x %s\n",
			//	fGPIOID, key->getCStringNoCopy());
			publishResource(key, this);
		}

		strIter->release();
	}
}
IOReturn IOAudioSelectorControl::validateValue(OSObject *newValue)
{
    IOReturn result = kIOReturnBadArgument;
    OSNumber *number;
    
    number = OSDynamicCast(OSNumber, newValue);

    if (number) {
        result = super::validateValue(newValue);
        
        if (result == kIOReturnSuccess) {
            if (valueExists((SInt32)number->unsigned32BitValue())) {
                result = kIOReturnSuccess;
            } else {
                result = kIOReturnNotFound;
            }
        }
    }
    
    return result;
}
static IORegistryEntry * IODTFindInterruptParent( IORegistryEntry * regEntry, IOItemCount index )
{
    IORegistryEntry *	parent;
    UInt32		phandle;
    OSData	    *	data;
    unsigned int	len;

    if( (data = OSDynamicCast( OSData, regEntry->getProperty( gIODTInterruptParentKey )))
      && (sizeof(UInt32) <= (len = data->getLength()))) {
	if (((index + 1) * sizeof(UInt32)) > len)
	    index = 0;
	phandle = ((UInt32 *) data->getBytesNoCopy())[index];
	parent = FindPHandle( phandle );

    } else if( 0 == regEntry->getProperty( "interrupt-controller"))
        parent = regEntry->getParentEntry( gIODTPlane);
    else
        parent = 0;

    return( parent );
}
Example #20
0
void FakeSMCDevice::saveKeyToNVRAM(FakeSMCKey *key)
{
    if (!useNVRAM)
        return;
    
    if (IORegistryEntry *nvram = OSDynamicCast(IORegistryEntry, fromPath("/options", gIODTPlane))) {
        char name[32];
        
        snprintf(name, 32, "%s-%s-%s", kFakeSMCKeyPropertyPrefix, key->getKey(), key->getType());
    
        const OSSymbol *tempName = OSSymbol::withCString(name);
    
        if (genericNVRAM)
            nvram->IORegistryEntry::setProperty(tempName, OSData::withBytes(key->getValue(), key->getSize()));
        else
            nvram->setProperty(tempName, OSData::withBytes(key->getValue(), key->getSize()));
        
        OSSafeRelease(tempName);
        OSSafeRelease(nvram);
    }
}
// ======================================================================
void ListHookedPointing::Item::apply(const Params_RelativePointerEventCallback& params) {
  RelativePointerEventCallback callback = orig_relativePointerEventAction_;
  if (!callback) return;

  OSObject* target = orig_relativePointerEventTarget_;
  if (!target) return;

  OSObject* sender = OSDynamicCast(OSObject, device_);
  if (!sender) return;

  const AbsoluteTime& ts = CommonData::getcurrent_ts();
  OSObject* refcon = nullptr;

  Params_RelativePointerEventCallback::log(false, params.buttons, params.dx, params.dy);
  {
    // We need to unlock the global lock while we are calling the callback function.
    // For more information, See ListHookedKeyboard::Item::apply(const Params_KeyboardEventCallBack& params)
    GlobalLock::ScopedUnlock lk;
    callback(target, params.buttons.get(), params.dx, params.dy, ts, sender, refcon);
  }
}
IOReturn
IOATABlockStorageDriver::reportMaxWriteTransfer ( UInt64 blocksize, UInt64 * max )
{
	
	OSNumber *		size;

	STATUS_LOG ( ( "IOATABlockStorageDriver::reportMaxWriteTransfer called.\n" ) );	
	
	*max = blocksize * kIOATAMaximumBlockCount8Bit;
	
	size = OSDynamicCast ( OSNumber, getProperty ( kIOMaximumBlockCountWriteKey ) );
	if ( size != NULL )
	{
		
		*max = size->unsigned64BitValue ( ) * blocksize;
		
	}
	
	return kIOReturnSuccess;
	
}
//====================================================================================================
// IOHIDEventService::registerEventSource
//====================================================================================================
void IOHIDEventSystem::registerEventSource(IOHIDEventService * service)
{
    EventServiceInfoRef tempEventServiceInfoRef;
    OSData *            tempData = NULL;
    UInt32              index;

    IOLog("IOHIDEventSystem::registerEventSource\n");

    for ( index = 0; index<_eventServiceInfoArray->getCount(); index++ )
    {
        if ( (tempData = OSDynamicCast(OSData, _eventServiceInfoArray->getObject(index)))
            && (tempEventServiceInfoRef = (EventServiceInfoRef)tempData->getBytesNoCopy())
            && (tempEventServiceInfoRef->service == service) )
            break;
        
        tempData = NULL;
    }

    service->open(this, 0, tempData, 
                OSMemberFunctionCast(IOHIDEventService::HIDEventCallback, this, &IOHIDEventSystem::handleHIDEvent));
}
Example #24
0
bool darwin_iwi3945::init(OSDictionary *dict)
{

	//priv=(struct iwl_priv*)IOMalloc(sizeof(struct iwl_priv));

/* module parameters */
param_disable_hw_scan = 0;
//need to define param_debug better
param_debug =  0xffffffff;
param_debug &= ~(IWL_DL_IO | IWL_DL_ISR | IWL_DL_TEMP|IWL_DL_POWER);
param_debug |=IWL_DL_INFO;
param_disable = 0;      /* def: enable radio */
param_antenna = 0;      /* def: 0 = both antennas (use diversity) */
param_hwcrypto = 0;     /* def: using software encryption */
param_qos_enable = 0;
 
param_disable=OSDynamicCast(OSNumber,dict->getObject("param_disable"))->unsigned32BitValue();
 //IOLog("debug_level %x sw_disable %d\n",param_debug, param_disable);

 return super::init(dict);
}
Example #25
0
void
PAEngine::removeVirtualDeviceWithRefcon(void *refCon)
{
	OSCollectionIterator *iter = OSCollectionIterator::withCollection(virtualDeviceArray);
	PAVirtualDevice *dev;

	while ((dev = OSDynamicCast(PAVirtualDevice, iter->getNextObject()))) {
		UInt index = virtualDeviceArray->getNextIndexOfObject((OSMetaClassBase *) dev, 0);

		if (dev->refCon == refCon) {
			if (state == kIOAudioEngineRunning)
				dev->sendNotification(kPAVirtualDeviceUserClientNotificationEngineStopped, 0);
			dev->detachFromParent(this, gIOServicePlane);
			dev->stop(this);
			dev->terminate(0);
			virtualDeviceArray->removeObject(index);
		}
	}

	iter->release();
}
void
OWCDumpIORegistry::dumpIORegistry (void *argument)
{
	IOSleep (DUMP_DELAY_SECONDS * 1000);
		
	IORegistryIterator *iter = IORegistryIterator::iterateOver (gIOServicePlane, kIORegistryIterateRecursively);
	if (iter == NULL) return;
	
	int maxBufferSize = 2048;
	char *buffer = (char *) IOMalloc (maxBufferSize);
	if (buffer == NULL) return;
	
	OSSerialize *s = OSSerialize::withCapacity (maxBufferSize);
	if (s == NULL) return;
	
	IORegistryEntry *object = iter->getCurrentEntry ();
	while (object) {
		s->clearText ();
		
		int busyState = 0;
		IOService *ios = OSDynamicCast (IOService, object);
		if (ios) busyState = ios->getBusyState ();
					
		int pathSize = maxBufferSize;
		object->getPath (buffer, &pathSize, gIOServicePlane);
		kprintf ("\n--> %s <%s> (%d, %d)\n", buffer, object->getMetaClass ()->getClassName (), object->getRetainCount (), busyState);
		
		if (object->serializeProperties (s)) {
			kprintf ("%s\n", s->text ());
		} else {
			kprintf ("serializeProperties failed\n");
		}
		
		object = iter->getNextObject ();
	} 
	
	IOFree (buffer, maxBufferSize);
	s->release ();
	iter->release ();
}
/*
 * 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;
}
IOReturn
AppleUSBUHCI::GetRootHubDescriptor(IOUSBHubDescriptor *desc)
{
    IOUSBHubDescriptor	hubDesc;
	UInt32				appleCaptive = 0;
	OSNumber *			appleCaptiveProperty = NULL;
   
    if (!desc) 
        return(kIOReturnNoMemory); 
    
    hubDesc.length = sizeof(IOUSBHubDescriptor); 
    hubDesc.hubType = kUSBHubDescriptorType; 
    hubDesc.numPorts = kUHCI_NUM_PORTS;							// UHCI all have 2 ports - how convenient
	_rootHubNumPorts = kUHCI_NUM_PORTS;

    hubDesc.powerOnToGood = 50; /* 100ms */
    hubDesc.hubCurrent = 0;
    // XXX for now do not support overcurrent, although PIIX chips do support it
    hubDesc.characteristics = HostToUSBWord(kNoPowerSwitchingBit | kNoOverCurrentBit);
    
    assert(kUHCI_NUM_PORTS < 8);

	// Set removable port flags -- we might have an AAPL property that tells us which ports
	// are captive.  If we don't then we'll assume that all ports are removable
	appleCaptiveProperty = OSDynamicCast(OSNumber, _device->getProperty(kAppleInternalUSBDevice));
	if (appleCaptiveProperty)
		appleCaptive = appleCaptiveProperty->unsigned32BitValue();
	
    hubDesc.removablePortFlags[0] = (UInt8) appleCaptive;
    hubDesc.removablePortFlags[1] = 0xFF;

    // Adjust descriptor length to account for unused bytes
    // in removable flags and power control flags arrays.
    hubDesc.length -= (sizeof(hubDesc.removablePortFlags) - 1 +
                       sizeof(hubDesc.pwrCtlPortFlags) - 1);
    
    bcopy(&hubDesc, desc, hubDesc.length);
    
    return kIOReturnSuccess; 
}
	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;
	}
Example #30
0
void net_habitue_device_SC101::deblock(OSData *addr, IOMemoryDescriptor *buffer, UInt32 block, UInt32 nblks, IOStorageCompletion completion)
{
  bool isWrite = (buffer->getDirection() == kIODirectionOut);
  const OSSymbol *ioMaxKey = (isWrite ? gSC101DeviceIOMaxWriteSizeKey : gSC101DeviceIOMaxReadSizeKey);
  UInt64 ioMaxSize = OSDynamicCast(OSNumber, getProperty(ioMaxKey))->unsigned64BitValue();
  UInt64 ioSize = (nblks * SECTOR_SIZE);
  
  deblock_master_state *master = IONewZero(deblock_master_state, 1);
  master->addr = addr;
  master->buffer = buffer;
  master->block = block;
  master->nblks = nblks;
  master->completion = completion;
  master->status = kIOReturnSuccess;
    
  master->addr->retain();
  
  for (UInt64 used = 0, use = min(LSB(ioSize), ioMaxSize);
       used < ioSize;
       used += use, use = min(LSB(ioSize - used), ioMaxSize))
  {
    deblock_state *state = IONewZero(deblock_state, 1);
    state->master = master;
    state->buffer = IOMemoryDescriptor::withSubRange(master->buffer, used, use, master->buffer->getDirection());
    if (!state->buffer)
      panic("alloc failed"); // TODO(iwade) handle

    IOStorageCompletion new_completion;
    new_completion.target = this;
    new_completion.action = deblockCompletion;
    new_completion.parameter = state;
    
    master->pending++;
    
    KDEBUG("deblock %s used=%llu, use=%llu", (isWrite ? "write" : "read"), used, use);
    
    prepareAndDoAsyncReadWrite(master->addr, state->buffer, master->block + used / SECTOR_SIZE, use / SECTOR_SIZE, new_completion);
  }
}