AppleRAIDUserClient.cpp   [plain text]


/*
 * Copyright (c) 2001-2007 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * The contents of this file constitute Original Code as defined in and
 * are subject to the Apple Public Source License Version 1.1 (the
 * "License").  You may not use this file except in compliance with the
 * License.  Please obtain a copy of the License at
 * http://www.apple.com/publicsource and read it before using this file.
 *
 * This 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 OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * @APPLE_LICENSE_HEADER_END@
 */

#include "AppleRAID.h"

#define super IOUserClient
OSDefineMetaClassAndStructors(AppleRAIDUserClient, IOUserClient);

    
bool
AppleRAIDUserClient::initWithTask(task_t owningTask, void *security_id, UInt32 type)
{
    IOLogUC("AppleRAIDUserClient::initWithTask()\n");

    if (!super::initWithTask(owningTask, security_id, type)) return false;
    
    if (!owningTask) return false;
    ucClient = owningTask;
    ucController = NULL;
        
    return true;
}


bool 
AppleRAIDUserClient::start(IOService * provider)
{
    IOLogUC("AppleRAIDUserClient::start()\n");
    
    if (!super::start(provider)) return false;
        
    ucController = OSDynamicCast(AppleRAID, provider);
    if (!ucController) return false;
        
    return true;
}


IOReturn 
AppleRAIDUserClient::clientClose(void)
{
    IOLogUC("AppleRAIDUserClient::clientClose()\n");
    
    closeController();
    
    ucClient = NULL;
    ucController = NULL;

    terminate();
    
    // Do not call super::clientClose, which just returns notSupported
    return kIOReturnSuccess;
}


IOReturn
AppleRAIDUserClient::externalMethod(uint32_t                    selector, 
				    IOExternalMethodArguments * arguments,
				    IOExternalMethodDispatch *  dispatch, 
				    OSObject *                  target, 
				    void *                      reference)
{
    IOLogUC("AppleRAIDUserClient::externalMethod(selector = %d)\n", (int)selector);
    
    static const IOExternalMethodDispatch sMethods[kAppleRAIDUserClientMethodsCount] = 
    {
        {   // 0 - kAppleRAIDClientOpen
            (IOExternalMethodAction) &AppleRAIDUserClient::openShim,
            0, 0,							// scalar in count, struct in size
	    0, 0							// scalar out count, struct out size 
        },
        {   // 1 - kAppleRAIDClientClose 
            (IOExternalMethodAction) &AppleRAIDUserClient::closeShim,
            0, 0,							// scalar in count, struct in size
	    0, 0							// scalar out count, struct out size
        },
        {   // 2 - kAppleRAIDGetListOfSets 
            (IOExternalMethodAction) &AppleRAIDUserClient::getListOfSetsShim,
            0, sizeof(UInt32),						// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size 
        },
	{   // 3 - kAppleRAIDGetSetProperties
            (IOExternalMethodAction) &AppleRAIDUserClient::getSetPropertiesShim,
            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        },
        {   // 4 - kAppleRAIDGetMemberProperties
            (IOExternalMethodAction) &AppleRAIDUserClient::getMemberPropertiesShim,
            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        },
        {   // 5 - kAppleRAIDUpdateSet
            (IOExternalMethodAction) &AppleRAIDUserClient::updateSetShim,
            0, 0xffffffff,						// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        },
        {   // 6 - kAppleLVMGetVolumesForGroup
            (IOExternalMethodAction) &AppleRAIDUserClient::getVolumesForGroupShim,
            0, kAppleRAIDMaxUUIDStringSize * 2,				// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        },
        {   // 7 - kAppleLVMGetVolumeProperties
            (IOExternalMethodAction) &AppleRAIDUserClient::getVolumePropertiesShim,
            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        },
        {   // 8 - kAppleLVMGetVolumeExtents
            (IOExternalMethodAction) &AppleRAIDUserClient::getVolumeExtentsShim,
            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        },
        {   // 9 - kAppleLVMUpdateLogicalVolume
            (IOExternalMethodAction) &AppleRAIDUserClient::updateLogicalVolumeShim,
            0, 0xffffffff,						// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        },
        {   // 10 - kAppleLVMDestroyLogicalVolume
            (IOExternalMethodAction) &AppleRAIDUserClient::destroyLogicalVolumeShim,
            0, 0xffffffff,						// scalar in count, struct in size
	    0, 0xffffffff						// scalar out count, struct out size
        }
    };

    // Make sure that the index of the function we're calling actually exists in the function table.
    if (selector < (uint32_t)kAppleRAIDUserClientMethodsCount) 
    {
	dispatch = (IOExternalMethodDispatch *) &sMethods[selector];
	target = this;	   
	return super::externalMethod(selector, arguments, dispatch, target, reference);
    }

    return kIOReturnBadArgument;
}


// ***********************************************************************************************************
// ***********************************************************************************************************
// ***********************************************************************************************************

IOReturn 
AppleRAIDUserClient::openController(void)
{
    IOLogUC("AppleRAIDUserClient::openController()\n");
    
    if (!ucController) return kIOReturnNotAttached;
        
    if (!ucController->open(this)) return kIOReturnExclusiveAccess;
        
    return kIOReturnSuccess;
}


IOReturn 
AppleRAIDUserClient::closeController(void)
{
    IOLogUC("AppleRAIDUserClient::closeController()\n");
            
    if (!ucController) return kIOReturnNotAttached;
        
    if (ucController->isOpen(this)) {
	ucController->close(this);
    }
        
    return kIOReturnSuccess;
}

#if 0
// XXX will need to support larger ool arguments someday

IOReturn
AppleRAIDUserClient::mapArguments(IOExternalMethodArguments * arguments, void ** in, uint32_t * inCount, void ** out, uint32_t * outCount)
{
    if (arguments->structureInputDescriptor) {

        IOMemoryDescriptor * mem = arguments->structureInputDescriptor;
        IOReturn ret = mem->map();  ///////////
        if (ret != kIOReturnSuccess) return ret;
	
	*in = mem->virtual;  ////////////
	*inCount = mem->getLength();
    } else {
        *in = arguments->structureInput;
	*inCount = arguments->structureInputSize;
    }
    if (arguments->structureOutputDescriptor) {

        IOMemoryDescriptor * mem = arguments->structureOutputDescriptor;
        IOReturn ret = mem->map();  ///////////
        if (ret != kIOReturnSuccess) return ret;

	*out = 0;  ////////
	*outCount = arguments->structureOutputSize;
    } else {
        *out = arguments->structureOutput;
	*outCount = arguments->structureOutputSize;
    }

    return IOReturnSuccess;
}

IOReturn
AppleRAIDUserClient::unmapArguments(IOExternalMethodArguments * arguments, void * out, uint32_t outCount)
{
}
#endif

IOReturn 
AppleRAIDUserClient::getListOfSets(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::getListOfSets()\n");

    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    UInt32 flags = *((UInt32 *)arguments->structureInput);
			       
    return ucController->getListOfSets(flags, (char *)arguments->structureOutput, &arguments->structureOutputSize);
}


IOReturn 
AppleRAIDUserClient::getSetProperties(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::getSetProperties()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    return ucController->getSetProperties((char *)arguments->structureInput, arguments->structureInputSize,
					  (char *)arguments->structureOutput, &arguments->structureOutputSize);
}


IOReturn 
AppleRAIDUserClient::getMemberProperties(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::getMemberProperties()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    return ucController->getMemberProperties((char *)arguments->structureInput, arguments->structureInputSize,
					     (char *)arguments->structureOutput, &arguments->structureOutputSize);
}


IOReturn 
AppleRAIDUserClient::updateSet(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::updateSet()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    if (clientHasPrivilege(ucClient, kIOClientPrivilegeAdministrator)) return kIOReturnNotPrivileged;

    return ucController->updateSet((char *)arguments->structureInput, arguments->structureInputSize,
				   (char *)arguments->structureOutput, &arguments->structureOutputSize);
}

IOReturn 
AppleRAIDUserClient::getVolumesForGroup(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::getVolumesForGroup()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    return ucController->getVolumesForGroup((char *)arguments->structureInput, arguments->structureInputSize,
					    (char *)arguments->structureOutput, &arguments->structureOutputSize);
}

IOReturn 
AppleRAIDUserClient::getVolumeProperties(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::getVolumeProperties()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    return ucController->getVolumeProperties((char *)arguments->structureInput, arguments->structureInputSize,
					     (char *)arguments->structureOutput, &arguments->structureOutputSize);
}

IOReturn 
AppleRAIDUserClient::getVolumeExtents(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::getVolumeExtentss()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    return ucController->getVolumeExtents((char *)arguments->structureInput, arguments->structureInputSize,
					  (char *)arguments->structureOutput, &arguments->structureOutputSize);
}

IOReturn 
AppleRAIDUserClient::updateLogicalVolume(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::updateLogicalVolume()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    if (clientHasPrivilege(ucClient, kIOClientPrivilegeAdministrator)) return kIOReturnNotPrivileged;

    return ucController->updateLogicalVolume((char *)arguments->structureInput, arguments->structureInputSize,
					     (char *)arguments->structureOutput, &arguments->structureOutputSize);
    return 0;
}


IOReturn 
AppleRAIDUserClient::destroyLogicalVolume(IOExternalMethodArguments * arguments)
{
    IOLogUC("AppleRAIDUserClient::destroyLogicalVolume()\n");
    
    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
             
    if (!ucController || isInactive()) return kIOReturnNotAttached;

    if (clientHasPrivilege(ucClient, kIOClientPrivilegeAdministrator)) return kIOReturnNotPrivileged;

    return ucController->destroyLogicalVolume((char *)arguments->structureInput, arguments->structureInputSize,
					      (char *)arguments->structureOutput, &arguments->structureOutputSize);
    return 0;
}