/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/common/framework/register/prdfCaptureData.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/**
  @file prdfCaptureData.C
  @brief Squadrons implementation of capture data
*/
//----------------------------------------------------------------------
//  Includes
//----------------------------------------------------------------------

#include <register/hei_hardware_register.hpp>
#include <util/hei_bit_string.hpp>

#include <prdfHomRegisterAccess.H>  // dg06a
#include <iipchip.h>
#include <iipCaptureData.h>
#include <string.h>
#include <algorithm>    // @jl04 a Add this for the Drop function.

using namespace TARGETING;

namespace PRDF
{

//---------------------------------------------------------------------
// Member Function Specifications
//---------------------------------------------------------------------

CaptureData::CaptureData(void):data()
{
//  data.reserve(INITIAL_DATA_COUNT);
}

// dg05d CaptureData::~CaptureData(void)
// dg05d {
// dg05d   if(!data.empty())
// dg05d   {
// dg05d     Clear();
// dg05d   }
// dg05d }

void CaptureData::Clear(void)
{

  if(!data.empty())
  {
// dg05d   for(DataContainerType::iterator i  = data.begin();i != data.end();i++)
// dg05d   {
// dg05d     delete [] (*i).dataPtr;
// dg05d   }

    data.erase(data.begin(), data.end());

  }                             /* if not empty */
}

//------------------------------------------------------------------------------

void CaptureData::AddDataElement( TargetHandle_t i_trgt, int i_scomId,
                                  const BitString * i_bs,
                                  Place i_place, RegType i_type )
{
    // Initial values of the bit string buffer if i_bs has a zero value.
    uint8_t * buf = nullptr;
    size_t sz_buf = 0;

    // Add buffer only if the value is non-zero.
    if ( !i_bs->isZero() )
    {
        // Get the size of i_bs and ensure byte alignment.
        sz_buf = (i_bs->getBitLen() + 8-1) / 8;

        // Since we are using a BitString below, which does everything on a
        // CPU_WORD boundary, we must make sure the buffer is CPU_WORD aligned.
        const size_t sz_word = sizeof(CPU_WORD);
        sz_buf = ((sz_buf + sz_word-1) / sz_word) * sz_word;

        // Allocate memory for the buffer.
        buf = new uint8_t[sz_buf];
        memset( buf, 0x00, sz_buf );

        // Use a BitString to copy i_bs to the buffer.
        BitString bs ( i_bs->getBitLen(), (CPU_WORD *)buf );
        bs.setString( *i_bs );

        // Create the new data element.
        Data element( i_trgt, i_scomId, sz_buf, buf );
        element.registerType = i_type;

        // Add the new element to the data.
        if ( FRONT == i_place )
            data.insert( data.begin(), element );
        else
            data.push_back( element );
    }
}

//------------------------------------------------------------------------------

void CaptureData::Add( TargetHandle_t i_trgt, int32_t i_scomId,
                       Register & io_scr,
                       Place i_place, RegType i_type )
{
    if ( SUCCESS == io_scr.Read() )
    {
        AddDataElement( i_trgt, i_scomId, io_scr.GetBitString(),
                        i_place, i_type );
    }
}

//------------------------------------------------------------------------------

void CaptureData::Add( TargetHandle_t i_trgt, int i_scomId,
                       const BitString & i_bs, Place i_place )
{
    AddDataElement( i_trgt, i_scomId, &i_bs, i_place );
}

//------------------------------------------------------------------------------

// start jl04a
void CaptureData::Drop(RegType i_type)
{
  //  Function below requires a predicate function above to Drop
  //  a data element from the capture data if it is
  //    defined as secondary data instead of primary data in the rule files.
  //  This predicate has to exist within the CaptureData Class because the
  //  class "Data" is defined within CaptureData class.
  data.erase( std::remove_if(data.begin(),data.end(),
              prdfCompareCaptureDataType(i_type)), data.end() );
}
// end jl04a

//------------------------------------------------------------------------------

template <class T>
void __bufferAdd( uint8_t* & i_idx, T i_val )
{
    memcpy( i_idx, &i_val, sizeof(i_val) );
    i_idx += sizeof(i_val);
}

bool __bufferFull( uint8_t * i_buf, size_t i_bufSize,
                   uint8_t * i_idx, size_t i_idxSize )
{
    if ( (i_buf + i_bufSize) < (i_idx + i_idxSize) )
    {
        PRDF_ERR( "[CaptureData::Copy] Buffer is full. Some data may have "
                  "been lost" );
        return true;
    }

    return false;
}

/* CaptureData Format:
 *        capture data -> ( <chip header> <registers> )*
 *        chip header -> ( <chip id:32> <# registers:32> )
 *        registers -> ( <reg id:16> <reg byte len:16> <bytes>+ )
 */
uint32_t CaptureData::Copy( uint8_t * i_buffer, uint32_t i_bufferSize ) const
{
    TargetHandle_t curTrgt = nullptr;

    uint32_t * regCntPtr = nullptr;

    uint8_t * curIdx = i_buffer;

    for ( auto & entry : data )
    {
        // We only need the target data when the target for this entry does not
        // match the previous entry.
        if ( entry.chipHandle != curTrgt )
        {
            // Ensure we have enough space for the entry header.
            if ( __bufferFull( i_buffer, i_bufferSize, curIdx,
                               (sizeof(HUID) + sizeof(uint32_t)) ) )
            {
                break;
            }

            // Update current target.
            curTrgt = entry.chipHandle;

            // Add HUID to buffer.
            __bufferAdd( curIdx, htonl(PlatServices::getHuid(curTrgt)) );

            // Update the current count pointer.
            regCntPtr = (uint32_t *)curIdx;

            // Zero out the register count.
            __bufferAdd( curIdx, htonl(0) );
        }

        // Go to next entry if the data byte length is 0.
        if ( 0 == entry.dataByteLength )
            continue;

        // Ensure we have enough space for the entry header.
        if ( __bufferFull( i_buffer, i_bufferSize, curIdx,
                           (2 * sizeof(uint16_t) + entry.dataByteLength) ) )
        {
            break;
        }

        // Write register ID.
        __bufferAdd( curIdx, htons(entry.address) );

        // Write data length.
        __bufferAdd( curIdx, htons(entry.dataByteLength) );

        // Write the data.
        // >>> TODO: RTC 199045 The data should already be in network format.
        //           However, that is not the case. Instead, the data is
        //           converted here, which would be is fine if we were only
        //           adding registers, but we have additional capture data,
        //           especially in the memory subsytem, that are actually stored
        //           in the network format, but swizzled before adding to the
        //           capture data. Which means we are doing too much.
        //           Unfortunately, it currently works and will take some time
        //           to actually do it right. Therefore, we will leave this
        //           as-is and try to make the appropriate fix later.
        uint32_t l_dataWritten = 0;
        while ((l_dataWritten + 4) <= entry.dataByteLength)
        {
            uint32_t l_temp32;
            memcpy(&l_temp32, &entry.dataPtr[l_dataWritten], sizeof(l_temp32));
            l_temp32 = htonl(l_temp32);
            memcpy(curIdx, &l_temp32, 4);
            l_dataWritten += 4; curIdx += 4;
        }
        if (l_dataWritten != entry.dataByteLength)
        {
            // TODO: RTC 199045 This is actually pretty bad because it will read
            //       four bytes of memory, sizzle the four bytes, then write
            //       less than four bytes to the buffer. This could cause a
            //       buffer overrun exception if we were at the end of memory.
            //       Also, how can we trust the right most bytes to be correct
            //       since they technically should not be part of the entry
            //       data? Again, we don't seem to be hitting this bug and it
            //       will take time to fix it (see note above). Therefore, we
            //       will leave it for now and fix it when we have time.
            uint32_t l_temp32;
            memcpy(&l_temp32, &entry.dataPtr[l_dataWritten], sizeof(l_temp32));
            l_temp32 = htonl(l_temp32);
            memcpy(curIdx, &l_temp32, entry.dataByteLength - l_dataWritten);
            curIdx += entry.dataByteLength - l_dataWritten;
        }
        // <<< TODO: RTC 199045

        // Update entry count. It is important to update the buffer just in
        // case we happen to run out of room in the buffer and need to exit
        // early.
        *regCntPtr = htonl( ntohl(*regCntPtr) + 1 );
    }

    return curIdx - i_buffer;
}

// dg08a -->
CaptureData & CaptureData::operator=(const uint8_t *i_flatdata)
{
    uint32_t l_tmp32 = 0;
    uint16_t l_tmp16 = 0;

    HUID  l_chipHuid = INVALID_HUID;
    const size_t l_huidSize = sizeof(l_chipHuid);

    // Read size.
    memcpy(&l_tmp32, i_flatdata, sizeof(uint32_t));
    uint32_t size = ntohl(l_tmp32);
    i_flatdata += sizeof(uint32_t);

    Clear();

    // Calculate end of buffer.
    const uint8_t *eptr = i_flatdata + size;

    while(i_flatdata < eptr)
    {
        // Read chip Handle.
        memcpy(&l_chipHuid , i_flatdata,l_huidSize );
        i_flatdata += l_huidSize ;
        TargetHandle_t l_pchipHandle  =NULL;
        l_chipHuid =  ntohl(l_chipHuid);
        l_pchipHandle = PlatServices::getTarget(l_chipHuid );
        if(NULL ==l_pchipHandle)
        {
            continue;
        }

        // Read # of entries.
        memcpy(&l_tmp32, i_flatdata, sizeof(uint32_t));
        i_flatdata += sizeof(l_tmp32);
        uint32_t entries = ntohl(l_tmp32);

        // Input each entry.
        for(uint32_t i = 0; i < entries; ++i)
        {
            // Read register id.
            memcpy(&l_tmp16, i_flatdata, sizeof(uint16_t));
            i_flatdata += sizeof(uint16_t);
            int regid = ntohs(l_tmp16);

            // Read byte count.
            memcpy(&l_tmp16, i_flatdata, sizeof(uint16_t));
            i_flatdata += sizeof(uint16_t);
            uint32_t bytecount = ntohs(l_tmp16);

            // Read data for register.
            BitStringBuffer bs(bytecount * 8);
            for(uint32_t bc = 0; bc < bytecount; ++bc)
            {
                bs.setFieldJustify(bc*8,8,(CPU_WORD)(*(i_flatdata+bc))); //mp01a
            }
            i_flatdata += bytecount;

            // Add to capture data.
            Add(l_pchipHandle, regid, bs);
        }
    }

    return *this;
}

// <-- dg08a

void CaptureData::mergeData(CaptureData & i_cd)
{
    DataContainerType l_data = *(i_cd.getData());

    if( !l_data.empty() )
    {
        // Remove duplicate entries from secondary capture data
        for (ConstDataIterator i = data.begin(); i != data.end(); i++)
        {
            l_data.remove_if(prdfCompareCaptureDataEntry(i->chipHandle,
                                                         i->address) );
        }

        // Add secondary capture data to primary one
        data.insert( data.end(),
                     l_data.begin(),
                     l_data.end() );
    }
}


// copy ctor for Data class
CaptureData::Data::Data(const Data & d):
chipHandle(d.chipHandle), address(d.address),
dataByteLength(d.dataByteLength), dataPtr(NULL)
{
    if(d.dataPtr != NULL)
    {
        dataPtr = new uint8_t[dataByteLength];

        memcpy(dataPtr, d.dataPtr, dataByteLength);
    }
}

CaptureData::Data & CaptureData::Data::operator=(const Data & d)
{
    chipHandle = d.chipHandle;
    address = d.address;
    dataByteLength = d.dataByteLength;
    if(dataPtr != NULL)
    {
        delete[]dataPtr;
        dataPtr = NULL;
    }
    if(d.dataPtr != NULL)
    {
        dataPtr = new uint8_t[dataByteLength];
        memcpy(dataPtr, d.dataPtr, dataByteLength);
    }

    return *this;
}

} // end of namespace PRDF
