UINT16 Marshal()

in TPMCmd/tpm/src/support/TableDrivenMarshal.c [724:900]


UINT16 Marshal(
    UINT16               typeIndex,         // IN: the thing to marshal
    void                *source,            // IN: were the data comes from
    UINT8               **buffer,           // IN/OUT: the data source buffer
    INT32               *size               // IN/OUT: the remaining size
)
{
#define _source  ((UINT8 *)source)

    const MarshalHeader_mst     *sel;
    UINT16                       retVal;
//
    sel = GetDescriptor(typeIndex);
    switch(sel->marshalType)
    {
        case VALUES_MTYPE:
        case UINT_MTYPE:
        case TABLE_MTYPE:
        case MIN_MAX_MTYPE:
        case ATTRIBUTES_MTYPE:
        case COMPOSITE_MTYPE:
        {
#if BIG_ENDIAN_TPM
#define MM16    0
#define MM32    0
#define MM64    0
#else
// These flip the constant index values so that they count in reverse order when doing
// little-endian stuff
#define MM16    1
#define MM32    3
#define MM64    7
#endif
// Just change the name and cast the type of the input parameters for typing purposes
#define mb (*buffer)
#define _source ((UINT8 *)source)
            retVal = (1 << (sel->modifiers & SIZE_MASK));
            if(buffer != NULL)
            {
                if((size == NULL) || ((*size -= retVal) >= 0))
                {
                    if(retVal == 4)
                    {
                        mb[0 ^ MM32] = _source[0];
                        mb[1 ^ MM32] = _source[1];
                        mb[2 ^ MM32] = _source[2];
                        mb[3 ^ MM32] = _source[3];
                    }
                    else if(retVal == 2)
                    {
                        mb[0 ^ MM16] = _source[0];
                        mb[1 ^ MM16] = _source[1];
                    }
                    else if(retVal == 1)
                        mb[0] = _source[0];
                    else
                    {
                        mb[0 ^ MM64] = _source[0];
                        mb[1 ^ MM64] = _source[1];
                        mb[2 ^ MM64] = _source[2];
                        mb[3 ^ MM64] = _source[3];
                        mb[4 ^ MM64] = _source[4];
                        mb[5 ^ MM64] = _source[5];
                        mb[6 ^ MM64] = _source[6];
                        mb[7 ^ MM64] = _source[7];
                    }
                    *buffer += retVal;
                }
            }
            break;
        }
        case STRUCTURE_MTYPE:
        {
//#define _mst  ((StructMarshal_mst *)sel)
            StructMarshal_mst *mst = ((StructMarshal_mst *)sel);
            int              i;
            const UINT16  *value = mst->values;

        //
            for(retVal = 0, i = mst->elements; i > 0; value = &value[3], i--)
            {
                UINT16           des = value[0];
                marshalIndex_t   index = value[1];
                UINT8           *offset = _source + value[2];
            //
                switch(GET_ELEMENT_TYPE(des))
                {
                    case UNION_STYPE:
                    {
                        UINT32           choice;
                    //
                        choice = GetSelector(source, mst->values, des);
                        retVal += MarshalUnion(index, offset, buffer, size, choice);
                        break;
                    }
                    case ARRAY_STYPE:
                    {
                        UINT32               count;
                    //
                        count = GetSelector(source, mst->values, des);
                        retVal += ArrayMarshal(index, offset, buffer, size, count);
                        break;
                    }
                    case SIMPLE_STYPE:
                    default:
                    {
                        // This is either another structure or a simple type
                        retVal += Marshal(index, offset, buffer, size);
                        break;
                    }
                }
            }
            break;
        }
        case TPM2B_MTYPE:
        {
            // Get the number of bytes being marshaled
            INT32         val = (int32_t)*((UINT16 *)source);
        //
            retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size);

            // This is a standard 2B with a byte buffer
            retVal += MarshalBytes(((TPM2B *)_source)->buffer, buffer, size, val);
            break;
        }
        case TPM2BS_MTYPE: // A structure in a TPM2B
        {
            Tpm2bsMarshal_mst       *m2bst = (Tpm2bsMarshal_mst *)sel;
            UINT8                   *offset;
            UINT16                   amount;
            UINT8                   *marshaledSize;
        //
            // Save the address of where the size should go
            marshaledSize = *buffer;

            // marshal the size (checks the space and advanced the pointer)
            retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size);

            // This gets the 'offsetof' the structure to marshal. It was placed in the
            // modifiers byte because the offset from the start of the TPM2B to the
            // start of the structure is going to be less than 8 and the modifiers
            // byte isn't needed for anything else.
            offset = _source + (m2bst->modifiers & SIGNED_MASK);

            // Marshal the structure and get its size
            amount = Marshal(m2bst->dataIndex, offset, buffer, size);

            // put the size in the space used when the size was marshaled.
            if(buffer != NULL)
                UINT16_TO_BYTE_ARRAY(amount, marshaledSize);
            retVal += amount;
            break;
        }
        case LIST_MTYPE:
        {
            ListMarshal_mst *    mlt = ((ListMarshal_mst *)sel);
            UINT8               *offset = _source + (mlt->modifiers & SIGNED_MASK);
            retVal = Marshal(UINT32_MARSHAL_REF, source, buffer, size);
            retVal += ArrayMarshal((marshalIndex_t)(mlt->arrayRef), offset,
                                   buffer, size, *((UINT32 *)source));
            break;
        }
        case NULL_MTYPE:
            retVal = 0;
            break;
       case ERROR_MTYPE:
       default:
        {
            if(size != NULL)
               *size = -1;
            retVal = 0;
            break;
        }
    }
    return retVal;

}