Copied PRD register access code from Hostboot project

This is just a straight copy from the Hostboot project. No modifications
have been made. Those will come in later commits.

Change-Id: Id9985f5542944ba88498b348b24b711fe2c30704
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/src/register/prdfCaptureData.C b/src/register/prdfCaptureData.C
new file mode 100755
index 0000000..3911350
--- /dev/null
+++ b/src/register/prdfCaptureData.C
@@ -0,0 +1,403 @@
+/* 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 <iipbits.h>
+#include <prdfHomRegisterAccess.H>  // dg06a
+#include <prdfScomRegister.H>
+#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,
+                       SCAN_COMM_REGISTER_CLASS & 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