/* 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) )
    {
        HEI_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  =nullptr;
        l_chipHuid =  ntohl(l_chipHuid);
        l_pchipHandle = PlatServices::getTarget(l_chipHuid );
        if(nullptr ==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(nullptr)
{
    if(d.dataPtr != nullptr)
    {
        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 != nullptr)
    {
        delete[]dataPtr;
        dataPtr = nullptr;
    }
    if(d.dataPtr != nullptr)
    {
        dataPtr = new uint8_t[dataByteLength];
        memcpy(dataPtr, d.dataPtr, dataByteLength);
    }

    return *this;
}

} // end of namespace PRDF
