File:  [Apple XNU] / XNU / iokit / Families / IOFireWire / IOFWUtils.cpp
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:44:57 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: v68_4-1_1, HEAD
xnu-68.4-1.1

/*
 * Copyright (c) 1998-2000 Apple Computer, 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@
 */
/*
 * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved.
 *
 * HISTORY
 * 3 June 99 wgulland created.
 *
 * Useful stuff called from several different FireWire objects.
 */
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/firewire/IOFWRegs.h>
#include <IOKit/firewire/IOFireWirePriv.h>

////////////////////////////////////////////////////////////////////////////////
//
// FWComputeCRC16
//
//   This proc computes a CRC 16 check.
//

UInt16	FWComputeCRC16(UInt32 *pQuads, UInt32 numQuads)
{
    SInt32	shift;
    UInt32	sum;
    UInt32	crc16;
    UInt32	quadNum;
    UInt32	quad;

    // Compute CRC 16 over all quads.
    crc16 = 0;
    for (quadNum = 0; quadNum < numQuads; quadNum++) {
        quad = *pQuads++;
        for (shift = 28; shift >= 0; shift -= 4) {
            sum = ((crc16 >> 12) ^ (quad >> shift)) & 0x0F;
            crc16 = (crc16 << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
        }
    }

    return (crc16 & 0xFFFF);
}


////////////////////////////////////////////////////////////////////////////////
//
// FWCSRROMInvalidateEntryIDType
//
//   Invalidate a CSR ROM entry ID.  This will deallocate any memory allocated
// for the ID excluding the ID data record itself.
//
// Probably only thing needed is to release reference to the ROM.
//

void  FWCSRROMInvalidateEntryIDType(CSRROMEntryID csrROMEntryID)
{
    CSRROMEntryIDDataPtr		pCSRROMEntryIDData;

    if (csrROMEntryID != kInvalidCSRROMEntryID)
    {
        pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;

        switch (pCSRROMEntryIDData->entryType)
        {
                case kLocalCSRROMEntryIDType :
                        break;

                case kRemoteCSRROMEntryIDType :

                        break;

                default :
                        break;
        }

        // Entry is now invalid.
        pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType;
    }
}

////////////////////////////////////////////////////////////////////////////////
//
// FWCSRROMCreateEntryID
//
//   Allocate memory for a CSR ROM entry ID.
//zzz could be a little more efficient computing allocation size.
//

CSRROMEntryID	FWCSRROMCreateEntryID(void)
{
    CSRROMEntryID		csrROMEntryID = kInvalidCSRROMEntryID;
    CSRROMEntryIDDataPtr	pCSRROMEntryIDData;
    UInt32			maxSize;

    // Determine maximum size of all entry types.
    // Need enough for local ID type.
    maxSize = sizeof (CSRROMLocalIDData);
    if (sizeof (CSRROMRemoteIDData) > maxSize)
        maxSize = sizeof (CSRROMRemoteIDData);

    // Allocate the data.
    pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) IOMalloc (maxSize);
    if (pCSRROMEntryIDData != NULL) {
        pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType;
        csrROMEntryID = (CSRROMEntryID) pCSRROMEntryIDData;
    }
    return (csrROMEntryID);
}

////////////////////////////////////////////////////////////////////////////////
//
// FWCSRROMDisposeEntryID
//
//   Deallocate memory for a CSR ROM entry ID.
//

void  FWCSRROMDisposeEntryID(CSRROMEntryID csrROMEntryID)
{
    CSRROMEntryIDDataPtr pCSRROMEntryIDData;

    if (csrROMEntryID != kInvalidCSRROMEntryID) {
        UInt32 maxSize;

        // Determine maximum size of all entry types.
        // Need enough for local ID type.
        maxSize = sizeof (CSRROMLocalIDData);
        if (sizeof (CSRROMRemoteIDData) > maxSize)
            maxSize = sizeof (CSRROMRemoteIDData);
        pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;

        // Invalidate entry.
        FWCSRROMInvalidateEntryIDType (csrROMEntryID);

        // Deallocate entry.
        IOFree(pCSRROMEntryIDData, maxSize);
    }
}

////////////////////////////////////////////////////////////////////////////////
//
// FWCSRROMCreateRemoteEntryID
//
//   Create a remote CSR ROM entry ID.
//

static IOReturn	FWCSRROMCreateRemoteEntryID(
	CSRROMEntryID			*pCSRROMEntryID,
	const UInt32 *			data,
	UInt32				*physicalPath,
	UInt32				pathSize)
{
    CSRROMEntryID			csrROMEntryID = *pCSRROMEntryID;
    CSRROMEntryIDDataPtr		pCSRROMEntryIDData;
    CSRROMRemoteIDDataPtr		pCSRROMRemoteIDData;

    // Allocate an entry ID if given entry ID is invalid.
    if (csrROMEntryID == kInvalidCSRROMEntryID) {
        csrROMEntryID = FWCSRROMCreateEntryID ();
        // If entry ID is still invalid, there must have been a memory error.
        if (csrROMEntryID == kInvalidCSRROMEntryID)
            return kIOReturnNoMemory;
   }


    // Get data from ID.
    pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
    pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData;

    // If entry is not a remote type, invalidate its type.
    if ((pCSRROMEntryIDData->entryType != kRemoteCSRROMEntryIDType) &&
        (pCSRROMEntryIDData->entryType != kInvalidCSRROMEntryIDType)) {
        FWCSRROMInvalidateEntryIDType (csrROMEntryID);
    }

    // Make entry a remote type.
    pCSRROMEntryIDData->entryType = kRemoteCSRROMEntryIDType;


    // Copy directory paths and data pointer
    pCSRROMRemoteIDData->data = data;
    bcopy (physicalPath, pCSRROMRemoteIDData->physicalPath, pathSize * sizeof (UInt32));
    pCSRROMRemoteIDData->pathSize = pathSize;

    // Return entry ID.
    *pCSRROMEntryID = csrROMEntryID;

    return (kIOReturnSuccess);
}

////////////////////////////////////////////////////////////////////////////////
//
// FWCSRROMDisposeIterator
//
//   Dispose of storage allocated for iterator.
//

void FWCSRROMDisposeIterator(CSRROMEntryIterator csrROMIterator)
{
    CSRROMEntryIteratorRecPtr	pIteratorRec;

    // Deallocate if iterator is valid.
    if (csrROMIterator != kInvalidCSRROMIterator) {
        // Get iterator record.
        pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;

        // Deallocate iterator record.
        IOFree (pIteratorRec, sizeof (CSRROMEntryIteratorRec));
    }
}


////////////////////////////////////////////////////////////////////////////////
//
// FWCSRROMSetIterator
//
//   Set current path and relationship of iterator.
//zzz should support all entry ID types.
//zzz should support kIterateRoot
//

IOReturn FWCSRROMSetIterator(
	CSRROMEntryIterator			csrROMIterator,
	CSRROMEntryID				csrROMEntryID,
	CSRROMIterationOp			relationship)
{
    CSRROMEntryIteratorRecPtr	pIteratorRec;
    CSRROMEntryIDDataPtr		pCSRROMEntryIDData;
    CSRROMRemoteIDDataPtr		pCSRROMRemoteIDData;

    // Get CSR ROM search iterator record.
    pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;

    // Set to given entry.
    if (csrROMEntryID != kInvalidCSRROMEntryID) {
        // Get entry data from ID.
        pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;

        if (pCSRROMEntryIDData->entryType == kRemoteCSRROMEntryIDType) {
            // Recast entry data.
            pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData;

            // Copy physical path.
            bcopy (pCSRROMRemoteIDData->physicalPath,
                                            pIteratorRec->physicalPath,
                                            pCSRROMRemoteIDData->pathSize * sizeof (UInt32));

            // Copy data pointer and path depth
            pIteratorRec->data = pCSRROMRemoteIDData->data;
            pIteratorRec->pathSize = pCSRROMRemoteIDData->pathSize;
        }
    }

    // Set to given relationship.
    if (relationship != kIterateContinue)
            pIteratorRec->relationship = relationship;

    return (kIOReturnSuccess);
}


////////////////////////////////////////////////////////////////////////////////
//
// FWCSRROMEntrySearch
//
//   Search for the next ROM entry that matches the search criteria.
//zzz need to check the search type in the criteria record and the relationship
//zzz could be more efficient.  should make and use more defs.
//zzz need to return information on what exactly was found
//zzz fill in entry value better
//zzz should break this up
//zzz should support all entry ID types.
//

// zzz
// Made a quick fix here so that if we are searching for Unit Directories (key d1)
// we will ignore any Instance Directories (key d8) because they contain redundant
// pointers to Unit Directories.  This is almost surely not the best soltution.

IOReturn FWCSRROMEntrySearch(
    CSRROMEntryIterator		csrROMIterator,
    CSRROMIterationOp		relationship,
    CSRROMEntryID		*pCSRROMEntryID,
    int			*pDone,
    CSRROMSearchCriteriaPtr	pSearchCriteria,
    UInt8 *			pEntryValue,
    UInt32			*pEntrySize)
{
    CSRROMEntryIteratorRecPtr	pIteratorRec;
    UInt32				currentAddress, entryValueAddress;
    UInt32				pathSize;
    UInt32				directoryEnd;
    UInt32				address;
    UInt32				directoryHeader, directoryEntry;
    UInt32				leafEntry;
    UInt32				keyType, keyValue;
    UInt32				keyTypeBit, keyValueBitHi, keyValueBitLo;
    UInt32				returnedEntrySize;
    bool				found, done;
    IOReturn			status = kIOReturnSuccess;

//zzz Part of the Instance Directory hack
    bool				unitDirSearch;
    bool				ignoreInstanceDir;

    // If we are searching for Unit Directories (in FWExpertLoader.c/FWUpdateDevice)
    // then just don't go down any Instance Directories (key d8), because we'll find a
    // redundant pointer to the Unit Directory in there.

    unitDirSearch = (pSearchCriteria->csrROMSearchType == kCSRROMSearchForKey) &&
            (pSearchCriteria->keyType == kCSRDirectoryKeyTypeBit) &&
            (pSearchCriteria->keyHi == kCSRUnitDirectoryKeyHiBit) &&
            (pSearchCriteria->keyLo == kCSRUnitDirectoryKeyLoBit);

    // Get CSR ROM search iterator record.
    pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;

    // Read the current directory length.  First, get base address of current
    // directory by going up one node in the directory path.  Special case
    // when we're in the root directory.  Second, read the directory length
    // at the base address.
    pathSize = pIteratorRec->pathSize;
    if (pathSize > 2) {
        address = pIteratorRec->physicalPath[pathSize - 2];
        directoryEntry = pIteratorRec->data[address];
        address += (directoryEntry & 0x00FFFFFF);
    }
    else {
        address = pIteratorRec->physicalPath[0];
    }
    directoryHeader = pIteratorRec->data[address];
    directoryEnd = address + ((directoryHeader >> 16) + 1);

    // Loop until we've found what we're looking for, or we've searched
    // everything.
    found = false;
    done = false;
    while ((!found) && (!done)) {
        // Read our current location.
        pathSize = pIteratorRec->pathSize;
        currentAddress = pIteratorRec->physicalPath[pathSize - 1];

        // Check if search was reset.
        if (pIteratorRec->reset) {
            pIteratorRec->reset = false;
        }
        else {
            // Read directory entry at current address.
            //zzz should have some address defs.
            directoryEntry = pIteratorRec->data[currentAddress];
            // If the current directory entry is a directory, add it to
            // the path.  Otherwise, go to next directory entry.
            keyType = (directoryEntry & 0xC0000000) >> 30;
//zzz
//The Instance Directory hack
            ignoreInstanceDir = (directoryEntry >> 24) == 0xd8;
//zzz
            if ((keyType == kCSRDirectoryKeyType) && !ignoreInstanceDir) {
                // Go to and read directory header.
                //zzz should do this the right way if offset > 1024.
                currentAddress += (directoryEntry & 0x00FFFFFF);
                directoryHeader = pIteratorRec->data[currentAddress];
                // Add directory to path and set location to first
                // entry in directory.
                pathSize++;

                directoryEnd =
                        currentAddress + ((directoryHeader >> 16) + 1);

                currentAddress += 1;
            }
            else {
                currentAddress += 1;
            }
        }

        // If we're past the end of the current directory, take it out
        // of path.
        while ((currentAddress >= directoryEnd) && (!done)) {
            pathSize--;
            currentAddress = pIteratorRec->physicalPath[pathSize - 1] + 1;

            // Read the current directory length.
            if (pathSize > 2) {
                address = pIteratorRec->physicalPath[pathSize - 2];
                directoryEntry = pIteratorRec->data[address];
                address += (directoryEntry & 0x00FFFFFF);
            }
            else {
                address = pIteratorRec->physicalPath[0];
            }
            directoryHeader = pIteratorRec->data[address];
            directoryEnd = address + ((directoryHeader >> 16) + 1);
            if (pathSize < 2) {
                done = true;
            }
        }
        // If we're not done searching, check the current directory entry
        // against the search criteria.
        if (!done) {
            directoryEntry = pIteratorRec->data[currentAddress];
            // Read key type and value.
            keyType = (directoryEntry & 0xC0000000) >> 30;
            keyValue = (directoryEntry & 0x3F000000) >> 24;

            // Convert to bit flag.
            keyTypeBit = 1 << keyType;
            if (keyValue > 31) {
                keyValueBitHi = 1 << (keyValue - 32);
                keyValueBitLo = 0;
            }
            else {
                keyValueBitHi = 0;
                keyValueBitLo = 1 << keyValue;
            }

            // Compare bit flags against search criteria.

            if ((keyTypeBit & pSearchCriteria->keyType) &&
                    ((keyValueBitHi & pSearchCriteria->keyHi) ||
                                (keyValueBitLo & pSearchCriteria->keyLo))) {
                switch (keyType) {
                    case kCSRImmediateKeyType :
                        if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
                                // Determine size of data.
                                if (*pEntrySize < 4)
                                        returnedEntrySize = *pEntrySize;
                                else
                                        returnedEntrySize = 4;

                                // Copy data.//zzz not right.
                                //zzz need def here.
                                *((UInt32 *) pEntryValue) =
                                        directoryEntry & 0x00FFFFFF;

                                // Return size.
                                *pEntrySize = returnedEntrySize;
                        }
                        break;

                    case kCSROffsetKeyType :
                        if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
                                // Determine size of data.
                                if (*pEntrySize < 4)
                                        returnedEntrySize = *pEntrySize;
                                else
                                        returnedEntrySize = 4;

                                // Copy data.//zzz not right.
                                //zzz need def here.
                                *((UInt32 *) pEntryValue) =
                                        directoryEntry & kCSREntryValue;

                                // Return size.
                                *pEntrySize = returnedEntrySize;
                        }
                        break;

                    case kCSRLeafKeyType :
                        if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
                            // Get address of leaf.
                            //zzz need to do indirect stuff right.
                            entryValueAddress = currentAddress + (directoryEntry & kCSREntryValue);

                            // Get size of leaf.
                            leafEntry = pIteratorRec->data[entryValueAddress];
                            returnedEntrySize = (leafEntry >> 16) * sizeof (UInt32);
                            entryValueAddress += 1;
                            // Determine size of data.
                            if (returnedEntrySize > *pEntrySize)
                                returnedEntrySize = *pEntrySize;
                            // Copy data.
                            bcopy(&pIteratorRec->data[entryValueAddress], pEntryValue, returnedEntrySize);
                            // Return size.
                            *pEntrySize = returnedEntrySize;
                        }

                        break;

                    case kCSRDirectoryKeyType ://zzz
                        break;

                    default : //zzz
                        break;
                }

                found = true;
            }
        }

        // Update current address.
        pIteratorRec->physicalPath[pathSize - 1] = currentAddress;
        pIteratorRec->pathSize = pathSize;
    }

    // Return CSR ROM entry ID.
    if (pCSRROMEntryID != NULL) {
        if (!done) {
            status = FWCSRROMCreateRemoteEntryID
                                    (pCSRROMEntryID,
                                                pIteratorRec->data,
                                                pIteratorRec->physicalPath,
                                                pIteratorRec->pathSize);
        }
        else {
            if (*pCSRROMEntryID != kInvalidCSRROMEntryID)
                    FWCSRROMDisposeEntryID (*pCSRROMEntryID);
            *pCSRROMEntryID = kInvalidCSRROMEntryID;
        }
    }

    *pDone = done;
    return (status);
}



unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.