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