summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorZane Shelley <zshelle@us.ibm.com>2015-02-10 17:18:45 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2015-02-27 23:43:21 -0600
commitb640d9b9361402f45b5c88a6bb2384ab2995accc (patch)
treee4632e8853fb82c3f5c00cc127bddb5b72b4a910 /src
parent67d0c761b1cb25b4df27b7ea794352aa2bb40e36 (diff)
downloadtalos-hostboot-b640d9b9361402f45b5c88a6bb2384ab2995accc.tar.gz
talos-hostboot-b640d9b9361402f45b5c88a6bb2384ab2995accc.zip
PRD: FIR data definition and support for OCC CS analysis
Change-Id: If2dc455e587c2cf752fcac156c7c6f206fd622fa Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15656 Tested-by: Jenkins Server Reviewed-by: Christopher T. Phan <cphan@us.ibm.com> Reviewed-by: Prem Shanker Jha <premjha2@in.ibm.com> Reviewed-by: Bilicon Patil <bilpatil@in.ibm.com> Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com> Reviewed-by: Zane Shelley <zshelle@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/usr/diag/prdf/makefile2
-rw-r--r--src/usr/diag/prdf/occ_firdata/firDataConst_common.h75
-rw-r--r--src/usr/diag/prdf/occ_firdata/homerData_common.h170
-rw-r--r--src/usr/diag/prdf/occ_firdata/pnorData_common.h152
-rw-r--r--src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.C298
-rw-r--r--src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.H83
-rw-r--r--src/usr/diag/prdf/prdf_hb_only.mk5
7 files changed, 784 insertions, 1 deletions
diff --git a/src/usr/diag/prdf/makefile b/src/usr/diag/prdf/makefile
index 1ed358a7a..088af87a0 100755
--- a/src/usr/diag/prdf/makefile
+++ b/src/usr/diag/prdf/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2014
+# Contributors Listed Below - COPYRIGHT 2012,2015
# [+] International Business Machines Corp.
#
#
diff --git a/src/usr/diag/prdf/occ_firdata/firDataConst_common.h b/src/usr/diag/prdf/occ_firdata/firDataConst_common.h
new file mode 100644
index 000000000..62fe1916c
--- /dev/null
+++ b/src/usr/diag/prdf/occ_firdata/firDataConst_common.h
@@ -0,0 +1,75 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/occ_firdata/firDataConst_common.h $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] 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 */
+
+#ifndef __firDataConst_common_h
+#define __firDataConst_common_h
+
+/** NOTE: This file is common between OCC and Hosboot. Any change to this file
+ * must be mirrored to both repositories. */
+
+#include <stdint.h>
+
+/** Target types for all supported targets. */
+typedef enum
+{
+ // NOTE: These will be used as array indexes.
+ FIRST_TRGT = 0,
+ PROC = FIRST_TRGT,
+ EX,
+ MCS,
+ MEMB,
+ MBA,
+ MAX_TRGTS,
+
+} TrgtType_t;
+
+/** Boundary/position ranges for each target type. */
+typedef enum
+{
+ MAX_PROC_PER_NODE = 8,
+ MAX_EX_PER_PROC = 16,
+ MAX_MCS_PER_PROC = 8,
+ MAX_MEMB_PER_PROC = MAX_MCS_PER_PROC,
+ MAX_MEMB_PER_NODE = MAX_MEMB_PER_PROC * MAX_PROC_PER_NODE,
+ MAX_MBA_PER_MEMB = 2,
+ MAX_MBA_PER_PROC = MAX_MEMB_PER_PROC * MAX_MBA_PER_MEMB,
+
+} TrgtPos_t;
+
+/** All register types. */
+typedef enum
+{
+ // NOTE: These will be used as array indexes.
+ FIRST_REG = 0,
+ GLBL = FIRST_REG,
+ FIR,
+ REG,
+ IDFIR,
+ IDREG,
+ MAX_REGS,
+
+} RegType_t;
+
+#endif // __firDataConst_common_h
diff --git a/src/usr/diag/prdf/occ_firdata/homerData_common.h b/src/usr/diag/prdf/occ_firdata/homerData_common.h
new file mode 100644
index 000000000..3f396c43c
--- /dev/null
+++ b/src/usr/diag/prdf/occ_firdata/homerData_common.h
@@ -0,0 +1,170 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/occ_firdata/homerData_common.h $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] 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 */
+
+#ifndef __homerData_common_h
+#define __homerData_common_h
+
+/** NOTE: This file is common between OCC and Hosboot. Any change to this file
+ * must be mirrored to both repositories. */
+
+#include <firDataConst_common.h>
+#include <string.h>
+
+/** This file is used to define the format of the register list stored in the
+ * HOMER data that the OCC will use to determine what register data to capture
+ * in the event of a system checkstop. The data will be stored in the following
+ * format:
+ *
+ * - HOMER_Data_t struct - This has all of the information characterizing what
+ * hardware is configured and how many addresses are in each register
+ * list. See the struct definition below.
+ *
+ * - Rgister address lists - These lists vary in size depending on the number
+ * of register addresses needed in each list. The list counts are
+ * stored in HOMER_Data_t::counts. All lists for each target type will
+ * be stored in the following order:
+ * - PROC lists
+ * - EX lists
+ * - MCS lists
+ * - MEMB lists
+ * - MBA lists
+ * Each target type will have a set of lists that will be stored in the
+ * following order:
+ * - Global FIRs 32-bit addresses
+ * - FIRs 32-bit addresses
+ * - Registers 32-bit addresses
+ * - Indirect-SCOM FIRs 64-bit addresses
+ * - Indirect-SCOM registers 64-bit addresses
+ *
+ * Note that FIRs and indirect-SCOM FIRs characterize a set of registers to
+ * capture. In addition to capturing the FIR (or ID FIR), the OCC will need to
+ * capture the following addresses for each type:
+ * - FIR
+ * - MASK (FIR address + 3)
+ * - ACT0 (FIR address + 6)
+ * - ACT1 (FIR address + 7)
+ * - WOF (FIR address + 8)
+ * - ID FIR
+ * - ID MASK (ID FIR address + 0x300000000ll)
+ * - ID ACT0 (ID FIR address + 0x600000000ll)
+ * - ID ACT1 (ID FIR address + 0x700000000ll)
+ * - ID WOF (ID FIR address + 0x800000000ll)
+ */
+
+typedef enum
+{
+ HOMER_FIR1 = 0x46495231, ///< FIR data version 1 ("FIR1" in ascii)
+
+} HOMER_Version_t;
+
+/** PNOR information contained within the HOMER data. */
+typedef struct
+{
+ uint32_t pnorOffset; ///< Physical offset of FIRDATA in PNOR
+ uint32_t pnorSize; ///< Maximum size of FIRDATA (includes ECC)
+ uint32_t mmioOffset; ///< Address of MMIO access
+ uint32_t norWorkarounds; ///< NOR flash vendor
+
+} HOMER_PnorInfo_t;
+
+/** HOMER data header information containing hardware configurations and
+ * register counts. */
+typedef struct
+{
+ uint32_t header; ///< Magic number to indicate valid data and version
+
+ uint16_t reserved;
+
+ uint8_t masterProc; ///< The position of the master PROC
+
+ /** Bitwise mask to indicate which PROCs are configured (max 8). The mask
+ * bit position is consistant with PROC ATTR_POSITION attribute. */
+ uint8_t procMask;
+
+ /** Bitwise masks to indicate which EXs are configured (16 per PROC). The
+ * array index is the associated PROC position. The mask bit position is
+ * consistant with the EX's ATTR_CHIP_UNIT attribute. */
+ uint16_t exMasks[MAX_PROC_PER_NODE];
+
+ /** Bitwise masks to indicate which MCSs are configured (8 per PROC). The
+ * array index is the associated PROC position. The mask bit position is
+ * consistant with the MCS's ATTR_CHIP_UNIT attribute. */
+ uint8_t mcsMasks[MAX_PROC_PER_NODE];
+
+ /** Bitwise masks to indicate which MEMBs are configured (8 per PROC). The
+ * array index is the associated PROC position. The mask bit position is
+ * consistant with the ATTR_CHIP_UNIT attribute of the connected MCS. */
+ uint8_t membMasks[MAX_PROC_PER_NODE];
+
+ /** Bitwise masks to indicate which MBAs are configured (16 per PROC). The
+ * array index is the associated PROC position. The mask bit position is
+ * calculated as:
+ * (MEMB position * MAX_MBA_PER_MEMB) + MBA's ATTR_CHIP_UNIT attribute
+ */
+ uint16_t mbaMasks[MAX_PROC_PER_NODE];
+
+ /** Contains number of registers per type for each target type. */
+ uint8_t counts[MAX_TRGTS][MAX_REGS];
+
+ /** FSI base address for each PROC chip. */
+ uint32_t procFsiBaseAddr[MAX_PROC_PER_NODE];
+
+ /** FSI base address for each MEMB chip. */
+ uint32_t membFsiBaseAddr[MAX_PROC_PER_NODE][MAX_MEMB_PER_PROC];
+
+ /** Information regarding the PNOR location and size. */
+ HOMER_PnorInfo_t pnorInfo;
+
+} HOMER_Data_t;
+
+/** @return An initialized HOMER_Data_t struct. */
+static inline HOMER_Data_t HOMER_getData()
+{
+ HOMER_PnorInfo_t p;
+ HOMER_Data_t d;
+
+ p.pnorOffset = 0;
+ p.pnorSize = 0;
+ p.mmioOffset = 0;
+ p.norWorkarounds = 0;
+
+ d.header = HOMER_FIR1;
+ d.reserved = 0;
+ d.masterProc = 0;
+ d.procMask = 0;
+ d.pnorInfo = p;
+
+ memset( d.exMasks, 0x00, sizeof(d.exMasks) );
+ memset( d.mcsMasks, 0x00, sizeof(d.mcsMasks) );
+ memset( d.membMasks, 0x00, sizeof(d.membMasks) );
+ memset( d.mbaMasks, 0x00, sizeof(d.mbaMasks) );
+ memset( d.counts, 0x00, sizeof(d.counts) );
+ memset( d.procFsiBaseAddr, 0xff, sizeof(d.procFsiBaseAddr) );
+ memset( d.membFsiBaseAddr, 0xff, sizeof(d.membFsiBaseAddr) );
+
+ return d;
+}
+
+#endif // __homerData_common_h
diff --git a/src/usr/diag/prdf/occ_firdata/pnorData_common.h b/src/usr/diag/prdf/occ_firdata/pnorData_common.h
new file mode 100644
index 000000000..85deaaaf5
--- /dev/null
+++ b/src/usr/diag/prdf/occ_firdata/pnorData_common.h
@@ -0,0 +1,152 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/occ_firdata/pnorData_common.h $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] 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 */
+
+#ifndef __pnorData_common_h
+#define __pnorData_common_h
+
+/** NOTE: This file is common between OCC and Hosboot. Any change to this file
+ * must be mirrored to both repositories. */
+
+#include <firDataConst_common.h>
+
+/** This file is used to define the format of the register data captured by the
+ * OCC and stored in PNOR. The data will be stored in the following format:
+ *
+ * - PNOR_Data_t struct - This has all of the information characterizing how
+ * many targets that have register data.
+ * - For each target with register data, the following format will be used:
+ * - PNOR_Trgt_t struct - Contains the target type, position, and how many
+ * registers are in the register list.
+ * - A list of all regular registers (PNOR_Reg_t).
+ * - A list of all indirect-SCOM registers (PNOR_IdReg_t).
+ *
+ * The PNOR has limited data space. So the following rules will apply:
+ * - Any registers with the value of zero will not be captured.
+ * - Registers with SCOM errors will not be captured, however, the number
+ * of SCOM errors detected should be stored in each PNOR_Trgt_t struct.
+ * - If the value of a FIR (or ID FIR) is zero, do not capture the
+ * associated ACT0 and ACT1 registers. Note that the associated MASK and
+ * WOF registers are still needed.
+ * - Each target type may have associated global registers. If none exist,
+ * simply capture all registers for that type. However, if they do exist
+ * and the values of ALL the global registers are zero, skip capturing
+ * the associated targets using the following rules:
+ * - For a PROC, skip this PROC and all associated EXs, and MCSs.
+ * - For an EX, skip this EX.
+ * - For an MCS, skip this MCS.
+ * - For a MEMB, skip this MEMB and all associated MBAs.
+ * - For an MBA, skip this MBA.
+ * - If for some reason we run out of space in the PNOR, do not SCOM any
+ * more registers, set the 'full' bit in the PNOR_Data_t struct, and
+ * write all data successfully captured to PNOR.
+ */
+
+typedef enum
+{
+ PNOR_FIR1 = 0x46495231, ///< FIR data version 1 ("FIR1" in ascii)
+
+} PNOR_Version_t;
+
+/** PNOR data header information. */
+typedef struct
+{
+ uint32_t header; ///< Magic number to indicate valid data and version
+
+ uint32_t trgts : 8; ///< Number of targets with register data
+ uint32_t full : 1; ///< 1 if PNOR data is full and data may be missing
+ uint32_t reserved : 23;
+
+} PNOR_Data_t;
+
+/** @return An initialized PNOR_Data_t struct. */
+static inline PNOR_Data_t PNOR_getData()
+{
+ PNOR_Data_t d;
+ d.header = PNOR_FIR1;
+ d.trgts = 0;
+ d.full = 0;
+ d.reserved = 0;
+
+ return d;
+};
+
+/** These values will match the corresponding bit fields in PNOR_Trgt_t. */
+typedef enum
+{
+ PNOR_Trgt_MAX_REGS_PER_TRGT = 511, // Currently expect 266 on the PROC
+ PNOR_Trgt_MAX_ID_REGS_PER_TRGT = 15, // Currently expect 9 on the MBA
+ PNOR_Trgt_MAX_SCOM_ERRORS = 511, // Should be plenty
+
+} PNOR_Trgt_RegLimits_t;
+
+/** Information for each target with SCOM data. */
+typedef struct
+{
+ uint32_t type : 3; ///< Target type. See enum TrgtType_t
+ uint32_t procPos : 3; ///< The processor position (0-7)
+ uint32_t unitPos : 4; ///< Unit position relative to the processor (0-15)
+ uint32_t regs : 9; ///< Number of normal registers
+ uint32_t idRegs : 4; ///< Number of indirect-SCOM registers
+ uint32_t scomErrs : 9; ///< Number of SCOM errors detected
+
+} PNOR_Trgt_t;
+
+/** @param i_type Target type. See enum TrgtType_t.
+ * @param i_procPos The processor position.
+ * @param i_procUnitPos Unit position relative to the processor.
+ * @return An initialized PNOR_Data_t struct.
+ */
+static inline PNOR_Trgt_t PNOR_getTrgt( uint32_t i_type, uint32_t i_procPos,
+ uint32_t i_procUnitPos )
+{
+ PNOR_Trgt_t t;
+ t.type = i_type;
+ t.procPos = i_procPos;
+ t.unitPos = i_procUnitPos;
+ t.regs = 0;
+ t.idRegs = 0;
+ t.scomErrs = 0;
+
+ return t;
+};
+
+/** Information for a normal register. */
+typedef struct
+{
+ uint32_t addr; ///< 32-bit address
+ uint64_t val; ///< 64-bit value
+
+} PNOR_Reg_t;
+
+/** Information for an indirect-SCOM register. */
+typedef struct
+{
+ uint64_t addr; ///< 64-bit address
+ uint32_t val; ///< 32-bit value
+
+} PNOR_IdReg_t;
+
+#endif // __pnorData_common_h
+
diff --git a/src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.C b/src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.C
new file mode 100644
index 000000000..16d71ae44
--- /dev/null
+++ b/src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.C
@@ -0,0 +1,298 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] 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 */
+
+#include <prdfReadPnorFirData.H>
+
+#include <prdfTrace.H>
+
+#include <pnor/pnorif.H>
+#include <prdfErrlUtil.H>
+
+using namespace TARGETING;
+
+namespace PRDF
+{
+
+using namespace PlatServices;
+
+class FirData
+{
+ public:
+
+ /** @brief Constructor
+ * @param i_pBuf Pointer to the PNOR data buffer
+ * @param i_maxPBufSize Maximum size of the PNOR data buffer
+ */
+ FirData( uint8_t * i_pBuf, size_t i_maxPBufSize ) :
+ iv_pBuf(i_pBuf), iv_maxPBufSize(i_maxPBufSize), iv_pBufSize(0)
+ {}
+
+ /** @brief Template function to get data from the PNOR buffer.
+ * @param o_data Data to extract from the buffer.
+ * @return True if the PNOR buffer is full, false if there was room.
+ */
+ template <typename T>
+ bool getData( T & o_data )
+ {
+ size_t sz_data = sizeof(*o_data);
+ bool full = (iv_maxPBufSize < iv_pBufSize + sz_data);
+ if ( !full )
+ {
+ o_data = reinterpret_cast<T>(&iv_pBuf[iv_pBufSize]);
+ iv_pBufSize += sz_data;
+ }
+ return full;
+ }
+
+ private:
+
+ uint8_t * iv_pBuf; ///< Pointer to the PNOR data buffer
+ uint32_t iv_maxPBufSize; ///< Maximum size of the PNOR data buffer
+ size_t iv_pBufSize; ///< Current size of the PNOR data buffer
+};
+
+//------------------------------------------------------------------------------
+
+TargetHandle_t getTargetHandle( PNOR_Trgt_t * i_pTrgt )
+{
+ TargetHandle_t o_trgt = NULL;
+
+ do
+ {
+ // Get the target type.
+ TYPE type = TYPE_LAST_IN_RANGE;
+ switch ( i_pTrgt->type )
+ {
+ case PROC: type = TYPE_PROC; break;
+ case EX: type = TYPE_EX; break;
+ case MCS: type = TYPE_MCS; break;
+ case MEMB: type = TYPE_MEMBUF; break;
+ case MBA: type = TYPE_MBA; break;
+ }
+ if ( TYPE_LAST_IN_RANGE == type ) break;
+
+ // Get the PROC target.
+ TargetHandle_t procTrgt = NULL;
+ TargetHandleList procList = getFunctionalTargetList( TYPE_PROC );
+ for ( TargetHandleList::iterator i = procList.begin();
+ i != procList.end(); ++i )
+ {
+ if ( i_pTrgt->procPos == getTargetPosition(*i) )
+ {
+ procTrgt = *i;
+ break;
+ }
+ }
+ if ( NULL == procTrgt ) break;
+
+ if ( TYPE_PROC == type )
+ {
+ o_trgt = procTrgt; // nothing more to do.
+ }
+ else if ( TYPE_EX == type || TYPE_MCS == type || TYPE_MEMBUF == type )
+ {
+ // Get the connected child
+ o_trgt = getConnectedChild( procTrgt, type, i_pTrgt->unitPos );
+ }
+ else if ( TYPE_MBA == type )
+ {
+ uint32_t membPos = i_pTrgt->unitPos / MAX_MBA_PER_MEMBUF;
+ uint32_t mbaPos = i_pTrgt->unitPos % MAX_MBA_PER_MEMBUF;
+
+ // Get the connected MEMBUF
+ TargetHandle_t membTrgt = getConnectedChild( procTrgt, TYPE_MEMBUF,
+ membPos );
+ if ( NULL != membTrgt )
+ {
+ // Get the connected MBA
+ o_trgt = getConnectedChild( membTrgt, type, mbaPos );
+ }
+ }
+
+ } while (0);
+
+ return o_trgt;
+}
+
+//------------------------------------------------------------------------------
+
+int32_t readPnorData( uint8_t * & o_pBuf, size_t & o_pBufSize )
+{
+ #define FUNC "[PRDF::readPnorData] "
+
+ int32_t rc = SUCCESS;
+
+ PNOR::SectionInfo_t info;
+ errlHndl_t errl = PNOR::getSectionInfo( PNOR::FIRDATA, info );
+ if ( NULL != errl )
+ {
+ ERRORLOG::errlCommit( errl, PRDF_COMP_ID );
+ PRDF_ERR( FUNC"getSectionInfo() failed" );
+ rc = FAIL;
+ }
+ else
+ {
+ o_pBuf = reinterpret_cast<uint8_t *>(info.vaddr);
+ o_pBufSize = info.size;
+ }
+
+ return rc;
+
+ #undef FUNC
+}
+
+//------------------------------------------------------------------------------
+
+int32_t readPnorFirData( bool & o_validData, PnorTrgtMap & o_trgtMap,
+ PnorFfdc & o_ffdc, PnorTrgtFfdcMap & o_trgtFfdc )
+{
+ #define FUNC "[PRDF::readPnorFirData] "
+
+ int32_t rc = SUCCESS;
+
+ o_validData = false;
+
+ bool full = false;
+ uint8_t * pBuf = NULL;
+ size_t sz_pBuf = 0;
+
+ do
+ {
+ // Read the PNOR data.
+ rc = readPnorData( pBuf, sz_pBuf );
+ if ( SUCCESS != rc )
+ {
+ PRDF_ERR( FUNC"readPnorData() failed" );
+ break;
+ }
+
+ FirData firData ( pBuf, sz_pBuf );
+
+ // Get the PNOR header data.
+ PNOR_Data_t * data = NULL;
+ bool full = firData.getData( data );
+ if ( full )
+ {
+ PRDF_ERR( FUNC"PNOR buffer size %d is less than PNOR header data "
+ "size %d", sz_pBuf, sizeof(*data) );
+ rc = FAIL;
+ break;
+ }
+
+ // Check the header for valid data.
+ if ( PNOR_FIR1 != data->header )
+ {
+ break; // nothing to analyze
+ }
+
+ // Gather FFDC from header data.
+ o_ffdc.trgts = data->trgts;
+ o_ffdc.full = (0 == data->full) ? false : true;
+
+ // Iterate each target and get the register data.
+ for ( uint32_t t = 0; t < data->trgts; t++ )
+ {
+ PNOR_Trgt_t * pTrgt = NULL;
+ full = firData.getData( pTrgt );
+ if ( full ) break;
+
+ TargetHandle_t trgtHndl = getTargetHandle( pTrgt );
+ if ( NULL == trgtHndl )
+ {
+ PRDF_ERR( FUNC"getTargetHandle() failed" );
+ rc = FAIL;
+ break;
+ }
+
+ // Gather FFDC from target.
+ if ( 0 != pTrgt->scomErrs )
+ {
+ o_trgtFfdc[trgtHndl].scomErrs = pTrgt->scomErrs;
+ }
+
+ // Iterate the regular registers.
+ for ( uint32_t r = 0; r < pTrgt->regs; r++ )
+ {
+ PNOR_Reg_t * reg = NULL;
+ full = firData.getData( reg );
+ if ( full ) break;
+
+ o_trgtMap[trgtHndl][(uint64_t)reg->addr] = reg->val;
+ }
+ if ( full ) break;
+
+ // Iterate the indirect-SCOM registers.
+ for ( uint32_t r = 0; r < pTrgt->idRegs; r++ )
+ {
+ PNOR_IdReg_t * reg = NULL;
+ full = firData.getData( reg );
+ if ( full ) break;
+
+ o_trgtMap[trgtHndl][reg->addr] = (uint64_t)reg->val;
+ }
+ if ( full ) break;
+
+ }
+ if ( full ) break;
+
+ o_validData = true;
+
+ } while (0);
+
+ if ( full )
+ {
+ PRDF_ERR( FUNC"Needed more data than availabe in PNOR (%d bytes)",
+ sz_pBuf );
+ rc = FAIL;
+ }
+
+ return rc;
+
+ #undef FUNC
+}
+
+//------------------------------------------------------------------------------
+
+int32_t clearPnorFirData()
+{
+ #define FUNC "[PRDF::clearPnorFirData] "
+
+ int32_t rc = SUCCESS;
+
+ errlHndl_t errl = PNOR::clearSection( PNOR::FIRDATA );
+ if ( NULL != errl )
+ {
+ ERRORLOG::errlCommit( errl, PRDF_COMP_ID );
+ PRDF_ERR( FUNC"clearSection() failed" );
+ rc = FAIL;
+ }
+
+ return rc;
+
+ #undef FUNC
+}
+
+}; // end namespace PRDF
+
diff --git a/src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.H b/src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.H
new file mode 100644
index 000000000..6e184bae6
--- /dev/null
+++ b/src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.H
@@ -0,0 +1,83 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/occ_firdata/prdfReadPnorFirData.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] 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 */
+
+#ifndef __prdfReadPnorFirData_H
+#define __prdfReadPnorFirData_H
+
+#include <map>
+
+#include <pnorData_common.h>
+#include <prdfPlatServices.H>
+
+namespace PRDF
+{
+
+typedef std::map<uint64_t, uint64_t> PnorRegMap;
+
+typedef std::map<TARGETING::TargetHandle_t, PnorRegMap> PnorTrgtMap;
+
+struct PnorFfdc
+{
+ uint8_t trgts; ///< Total number of target in the PNOR data.
+ bool full; ///< True if the PNOR data was unable to capture all regs.
+
+ PnorFfdc() : trgts(0), full(false) {}
+ PnorFfdc( uint8_t t, bool f ) : trgts(t), full(f) {}
+};
+
+struct PnorTrgtFfdc
+{
+ uint16_t scomErrs; ///< Total number of SCOM error detected on this target
+
+ PnorTrgtFfdc() : scomErrs(0) {}
+ PnorTrgtFfdc(uint16_t s) : scomErrs(s) {}
+};
+
+typedef std::map<TARGETING::TargetHandle_t, PnorTrgtFfdc> PnorTrgtFfdcMap;
+
+/** @brief Read register data captured by the OCC in the event of a system
+ * checkstop.
+ * @param o_validData True, if there the was a system checkstop and the OCC
+ * stored valid data in the PNOR. False otherwise.
+ * @param o_trgtMap If the data if valid, a map containing the register
+ * values for each target and address.
+ * @param o_ffdc PNOR FFDC data for debug.
+ * @param o_trgtFfdc PNOR target FFDC data for debug.
+ * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise.
+ */
+int32_t readPnorFirData( bool & o_validData, PnorTrgtMap & o_trgtMap,
+ PnorFfdc & o_ffdc, PnorTrgtFfdcMap & o_trgtFfdc );
+
+/** @brief Clears the OCC FIR data from the PNOR. This must be done after the
+ * checkstop analysis is complete so that analysis is not repeated on
+ * subsequent IPLs.
+ * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise.
+ */
+int32_t clearPnorFirData();
+
+}; // end namespace PRDF
+
+#endif // __prdfReadPnorFirData_H
+
diff --git a/src/usr/diag/prdf/prdf_hb_only.mk b/src/usr/diag/prdf/prdf_hb_only.mk
index c071a4a8b..31f950fea 100644
--- a/src/usr/diag/prdf/prdf_hb_only.mk
+++ b/src/usr/diag/prdf/prdf_hb_only.mk
@@ -38,6 +38,7 @@ prd_vpath += ${PRD_SRC_PATH}/framework/config
prd_vpath += ${PRD_SRC_PATH}/framework/resolution
prd_vpath += ${PRD_SRC_PATH}/framework/service
prd_vpath += ${PRD_SRC_PATH}/mnfgtools
+prd_vpath += ${PRD_SRC_PATH}/occ_firdata
prd_vpath += ${PRD_SRC_PATH}/plat
prd_vpath += ${PRD_SRC_PATH}/plat/pegasus
@@ -49,6 +50,7 @@ prd_incpath += ${PRD_SRC_PATH}/framework/config
prd_incpath += ${PRD_SRC_PATH}/framework/resolution
prd_incpath += ${PRD_SRC_PATH}/framework/service
prd_incpath += ${PRD_SRC_PATH}/mnfgtools
+prd_incpath += ${PRD_SRC_PATH}/occ_firdata
prd_incpath += ${PRD_SRC_PATH}/plat/pegasus
# External header paths
@@ -105,6 +107,9 @@ prd_obj += prdfPlatServices_ipl.o
# mnfgtools/
prd_obj += prdfMfgSync.o
+# occ_firdata/
+prd_obj += $(if $(CONFIG_ENABLE_CHECKSTOP_ANALYSIS), prdfReadPnorFirData.o)
+
# plat/pegasus/ (non-rule plugin related)
prd_obj += prdfCenMbaIplCeStats.o
prd_obj += prdfCenMbaTdCtlr_ipl.o
OpenPOWER on IntegriCloud