summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/pnor/pnor_reasoncodes.H3
-rw-r--r--src/include/usr/pnor/pnorif.H8
-rw-r--r--src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C36
-rw-r--r--src/usr/pnor/HBconfig3
-rw-r--r--src/usr/pnor/makefile5
-rw-r--r--src/usr/pnor/pnordd.C202
-rw-r--r--src/usr/pnor/pnordd.H44
-rw-r--r--src/usr/pnor/pnorrp.H40
-rw-r--r--src/usr/pnor/pnorvalid.C410
-rw-r--r--src/usr/pnor/test/pnorddtest.H20
10 files changed, 641 insertions, 130 deletions
diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H
index 52721f834..6760efd40 100644
--- a/src/include/usr/pnor/pnor_reasoncodes.H
+++ b/src/include/usr/pnor/pnor_reasoncodes.H
@@ -56,6 +56,9 @@ namespace PNOR
MOD_PNORDD_CHECKFOROPBERRORS = 0x1E, /**< pnordd.C : PnorDD::checkForErrors */
MOD_PNORDD_HANDLEECCBERROR = 0x1F, /**< pnordd.C : PnorDD::handleEccbError */
MOD_PNORDD_RESETPNOR = 0x20, /**< pnordd.C : PnorDD::resetPnor */
+ MOD_PNORVALID_MAIN = 0x21, /**< pnorvalid.C : Main Function */
+ MOD_PNORVALID_MAGIC = 0x22, /**< pnorvalid.C : Magic Function */
+
};
enum PNORReasonCode
diff --git a/src/include/usr/pnor/pnorif.H b/src/include/usr/pnor/pnorif.H
index 94a9632b6..7db87e56c 100644
--- a/src/include/usr/pnor/pnorif.H
+++ b/src/include/usr/pnor/pnorif.H
@@ -101,6 +101,14 @@ errlHndl_t getSectionInfo( SectionId i_section,
*/
bool usingL3Cache();
+/**
+ * @brief Validate the Alternative Master Processor's LPC
+ * Connection to PNOR
+ *
+ * @return errlHndl_t Error log if validation failed
+ */
+errlHndl_t validateAltMaster( void );
+
}
diff --git a/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C b/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C
index 0d430d867..90752042d 100644
--- a/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C
+++ b/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C
@@ -48,6 +48,7 @@
#include <hwpisteperror.H>
#include <sbe/sbeif.H>
+#include <pnor/pnorif.H>
// targeting support
#include <targeting/common/commontargeting.H>
@@ -338,9 +339,36 @@ void* call_proc_build_smp( void *io_pArgs )
void * call_host_slave_sbe_update( void * io_pArgs )
{
errlHndl_t l_errl = NULL;
+ IStepError l_StepError;
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"call_host_slave_sbe_update entry" );
+ do
+ {
+
+ // Call to check state of Processor SBE SEEPROMs and
+ // make any necessary updates
+ l_errl = SBE::updateProcessorSbeSeeproms();
+
+ if (l_errl)
+ {
+ // Create IStep error log and cross reference error that occurred
+ l_StepError.addErrorDetails( l_errl);
+ // Commit error
+ errlCommit( l_errl, HWPF_COMP_ID );
+ break;
+ }
+
+ // Call to Validate any Alternative Master's connection to PNOR
+ // Any error returned should not fail istep
+ l_errl = PNOR::validateAltMaster();
+ if (l_errl)
+ {
+ // Commit error
+ errlCommit( l_errl, HWPF_COMP_ID );
+ break;
+ }
+
#ifdef CONFIG_PCIE_HOTPLUG_CONTROLLER
// Loop through all the procs in the system
@@ -398,14 +426,14 @@ void * call_host_slave_sbe_update( void * io_pArgs )
#endif
- // Call to check state of Processor SBE SEEPROMs and
- // make any necessary updates
- l_errl = SBE::updateProcessorSbeSeeproms();
+ } while (0);
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"call_host_slave_sbe_update exit" );
- return l_errl;
+ // end task, returning any errorlogs to IStepDisp
+ return l_StepError.getErrorHandle();
+
}
}; // end namespace
diff --git a/src/usr/pnor/HBconfig b/src/usr/pnor/HBconfig
index 05640191b..e25089cef 100644
--- a/src/usr/pnor/HBconfig
+++ b/src/usr/pnor/HBconfig
@@ -16,5 +16,6 @@ config BMC_DOES_SFC_INIT
default y
help
The BMC is completely responsible for initializing and configuring the
- SFC before Hostboot is started.
+ SFC before Hostboot is started. The BMC is also responsible for doing
+ any repairs or recovery for the SFC.
diff --git a/src/usr/pnor/makefile b/src/usr/pnor/makefile
index 7a81aef19..c9a37cc3e 100644
--- a/src/usr/pnor/makefile
+++ b/src/usr/pnor/makefile
@@ -5,7 +5,9 @@
#
# OpenPOWER HostBoot Project
#
-# COPYRIGHT International Business Machines Corp. 2011,2014
+# Contributors Listed Below - COPYRIGHT 2011,2014
+# [+] 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.
@@ -25,6 +27,7 @@ MODULE = pnor
OBJS += pnorrp.o
OBJS += pnordd.o
+OBJS += pnorvalid.o
OBJS += ecc.o
SUBDIRS += test.d
diff --git a/src/usr/pnor/pnordd.C b/src/usr/pnor/pnordd.C
index 326f14de0..52ebe997b 100644
--- a/src/usr/pnor/pnordd.C
+++ b/src/usr/pnor/pnordd.C
@@ -106,6 +106,11 @@ errlHndl_t ddRead(DeviceFW::OperationType i_opType,
assert( reinterpret_cast<uint64_t>(io_buffer) % 4 == 0 );
assert( io_buflen % 4 == 0 );
+ // The PNOR device driver interface is initialized with the
+ // MASTER_PROCESSOR_CHIP_TARGET_SENTINEL. Other target
+ // access requires a separate PnorDD class created
+ assert( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL );
+
// Read the flash
l_err = Singleton<PnorDD>::instance().readFlash(io_buffer,
io_buflen,
@@ -157,13 +162,18 @@ errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
assert( reinterpret_cast<uint64_t>(io_buffer) % 4 == 0 );
assert( io_buflen % 4 == 0 );
+ // The PNOR device driver interface is initialized with the
+ // MASTER_PROCESSOR_CHIP_TARGET_SENTINEL. Other target
+ // access requires a separate PnorDD class created
+ assert( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL );
+
// Write the flash
l_err = Singleton<PnorDD>::instance().writeFlash(io_buffer,
io_buflen,
l_addr);
if(l_err)
{
- break;
+ break;
}
}while(0);
@@ -226,9 +236,9 @@ errlHndl_t PnorDD::readFlash(void* o_buffer,
}
//If we get here we're doing either MODEL_LPC_MEM, MODEL_REAL_CMD, or MODEL_REAL_MMIO
- mutex_lock(&cv_mutex);
+ mutex_lock(iv_mutex_ptr);
l_err = bufferedSfcRead(i_address, io_buflen, o_buffer);
- mutex_unlock(&cv_mutex);
+ mutex_unlock(iv_mutex_ptr);
if(l_err) { break;}
@@ -266,11 +276,11 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
//If we're in VPO, just do the write directly (no erases)
if(0 != iv_vpoMode)
{
- mutex_lock(&cv_mutex);
+ mutex_lock(iv_mutex_ptr);
l_err = bufferedSfcWrite(static_cast<uint32_t>(l_address),
8,
i_buffer);
- mutex_unlock(&cv_mutex);
+ mutex_unlock(iv_mutex_ptr);
break;
}
@@ -323,7 +333,7 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
//note that writestart < blkstart can never happen
// write a single block of data out to flash efficiently
- mutex_lock(&cv_mutex);
+ mutex_lock(iv_mutex_ptr);
l_err = compareAndWriteBlock(
cur_blkStart_addr,
cur_writeStart_addr,
@@ -331,7 +341,7 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
(void*)((uint64_t)i_buffer +
((uint64_t)cur_writeStart_addr-l_address)));
- mutex_unlock(&cv_mutex);
+ mutex_unlock(iv_mutex_ptr);
if( l_err ) { break; }
@@ -362,7 +372,6 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
Private/Protected Methods
********************/
mutex_t PnorDD::cv_mutex = MUTEX_INITIALIZER;
-uint64_t PnorDD::iv_vpoMode = 0;
//
// @note fake pnor no longer needs to allow from for SLW
@@ -377,8 +386,13 @@ uint64_t PnorDD::iv_vpoMode = 0;
*/
PnorDD::PnorDD( PnorMode_t i_mode,
uint64_t i_fakeStart,
- uint64_t i_fakeSize )
+ uint64_t i_fakeSize,
+ TARGETING::Target* i_target )
: iv_mode(i_mode)
+, iv_vpoMode(0)
+, iv_nor_chipid(0)
+, iv_hw_workaround(0)
+, iv_sfcInitDone(false)
, iv_ffdc_active(false)
, iv_error_handled_count(0x0)
, iv_error_recovery_failed(false)
@@ -389,6 +403,40 @@ PnorDD::PnorDD( PnorMode_t i_mode,
//Zero out erase counter
memset(iv_erases, 0xff, sizeof(iv_erases));
+
+ // Use i_target if all of these apply
+ // 1) not NULL
+ // 2) not MASTER_PROCESSOR_CHIP_TARGET_SENTINEL
+ // 3) i_target does not correspond to Master processor (ie the
+ // same processor as MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ // otherwise, use MASTER_PROCESSOR_CHIP_TARGET_SENTINEL
+ // NOTE: i_target can only be used when targetting is loaded
+ if ( ( i_target != NULL ) &&
+ ( i_target != TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL ) )
+ {
+
+ iv_target = i_target;
+
+ // Check if processor is MASTER
+ TARGETING::ATTR_PROC_MASTER_TYPE_type type_enum =
+ iv_target->getAttr<TARGETING::ATTR_PROC_MASTER_TYPE>();
+
+ // Master target could collide and cause deadlocks with PnorDD singleton
+ // used for ddRead/ddWrite with MASTER_PROCESSOR_CHIP_TARGET_SENTINEL
+ assert( type_enum != TARGETING::PROC_MASTER_TYPE_ACTING_MASTER );
+
+ // Initialize and use class-specific mutex
+ iv_mutex_ptr = &iv_mutex;
+ mutex_init(iv_mutex_ptr);
+ TRACFCOMP(g_trac_pnor, "PnorDD::PnorDD()> Using i_target=0x%X (non-master) and iv_mutex_ptr", TARGETING::get_huid(i_target));
+
+ }
+ else
+ {
+ iv_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ iv_mutex_ptr = &(cv_mutex);
+ }
+
//Use real PNOR for everything except VPO
if(0 == iv_vpoMode)
{
@@ -431,6 +479,8 @@ PnorDD::PnorDD( PnorMode_t i_mode,
if( (MODEL_REAL_CMD == iv_mode) ||
(MODEL_REAL_MMIO == iv_mode) )
{
+
+ // @todo RTC 97493 - make sure sfcInit only gets called once per target
sfcInit( );
}
@@ -445,9 +495,6 @@ PnorDD::~PnorDD()
}
-bool PnorDD::cv_sfcInitDone = false; //Static flag to ensure we only init the SFC one time.
-uint32_t PnorDD::cv_nor_chipid = 0; //Detected NOR Flash Type
-uint32_t PnorDD::cv_hw_workaround = 0; //Hardware Workaround flags
/**
* STATIC
@@ -458,7 +505,7 @@ void PnorDD::sfcInit( )
TRACFCOMP(g_trac_pnor, "PnorDD::sfcInit> iv_mode=0x%.8x", iv_mode );
errlHndl_t l_err = NULL;
- mutex_lock(&cv_mutex);
+ mutex_lock(iv_mutex_ptr);
do {
#ifdef CONFIG_SFC_IS_AST2400
@@ -467,20 +514,16 @@ void PnorDD::sfcInit( )
//@todo RTC:106881 - Fix up to support erase/write later
#endif //CONFIG_SFC_IS_AST2400
- if(!cv_sfcInitDone)
+ if(!iv_sfcInitDone)
{
#ifdef CONFIG_BMC_DOES_SFC_INIT
// Set OPB LPCM FIR Mask - hostboot will monitor these FIR bits
- //@todo (RTC:36950) - add non-master support
- TARGETING::Target* scom_target =
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
size_t scom_size = sizeof(uint64_t);
uint64_t fir_mask_data = OPB_LPCM_FIR_ERROR_MASK;
- // Read FIR Register
l_err = deviceOp( DeviceFW::WRITE,
- scom_target,
+ iv_target,
&(fir_mask_data),
scom_size,
DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_MASK_WO_OR_REG));
@@ -488,11 +531,11 @@ void PnorDD::sfcInit( )
//Determine NOR Flash type - triggers vendor specific workarounds
//We also use the chipID in some FFDC situations.
- l_err = getNORChipId(cv_nor_chipid);
+ l_err = getNORChipId(iv_nor_chipid);
if(l_err) { break; }
TRACFCOMP(g_trac_pnor,
- "PnorDD::sfcInit: cv_nor_chipid=0x%.8x> ",
- cv_nor_chipid );
+ "PnorDD::sfcInit: iv_nor_chipid=0x%.8x> ",
+ iv_nor_chipid );
// Re-initialize internal erase size cached value.
l_err = readRegSfc(SFC_CMD_SPACE,
@@ -509,12 +552,12 @@ void PnorDD::sfcInit( )
#endif //CONFIG_BMC_DOES_SFC_INIT
- cv_sfcInitDone = true;
+ iv_sfcInitDone = true;
}
}while(0);
- mutex_unlock(&cv_mutex);
+ mutex_unlock(iv_mutex_ptr);
if( l_err )
{
@@ -708,13 +751,13 @@ errlHndl_t PnorDD::pollSfcOpComplete(uint64_t i_pollTime)
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_PNORDD_POLLSFCOPCOMPLETE,
PNOR::RC_LPC_ERROR,
- TWO_UINT32_TO_UINT64(cv_nor_chipid,
+ TWO_UINT32_TO_UINT64(iv_nor_chipid,
poll_time),
TWO_UINT32_TO_UINT64(sfc_stat.data32,0));
// Limited in callout: no PNOR target, so calling out processor
l_err->addHwCallout(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ iv_target,
HWAS::SRCI_PRIORITY_HIGH,
HWAS::NO_DECONFIG,
HWAS::GARD_NULL );
@@ -743,7 +786,7 @@ errlHndl_t PnorDD::pollSfcOpComplete(uint64_t i_pollTime)
// Commit reset error as informational since we have
// original error l_err
TRACFCOMP(g_trac_pnor, "PnorDD::pollSfcOpComplete> Error from resetPnor() after previous error eid=0x%X. Committing resetPnor() error log eid=0x%X.",
- l_err->eid(), tmp_err->eid());
+ l_err->eid(), tmp_err->eid());
tmp_err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL);
tmp_err->collectTrace(PNOR_COMP_NAME);
tmp_err->plid(l_err->plid());
@@ -939,7 +982,7 @@ errlHndl_t PnorDD::checkForSfcErrors( ResetLevels &o_pnorResetLevel )
// Limited in callout: no PNOR target, so calling out processor
l_err->addHwCallout(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ iv_target,
HWAS::SRCI_PRIORITY_HIGH,
HWAS::NO_DECONFIG,
HWAS::GARD_NULL );
@@ -972,20 +1015,14 @@ errlHndl_t PnorDD::checkForOpbErrors( ResetLevels &o_pnorResetLevel )
size_t scom_size = sizeof(uint64_t);
do {
-
- //@todo (RTC:36950) - add non-master support
- TARGETING::Target* scom_target =
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
-
// Read FIR Register
l_err = deviceOp( DeviceFW::READ,
- scom_target,
+ iv_target,
&(fir_data),
scom_size,
DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_REG) );
if( l_err ) { break; }
-
// Mask data to just the FIR bits we care about
fir_reg.data64 = fir_data & OPB_LPCM_FIR_ERROR_MASK;
@@ -1082,14 +1119,14 @@ errlHndl_t PnorDD::checkForOpbErrors( ResetLevels &o_pnorResetLevel )
* and/or LPCHC Status Register
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORDD_CHECKFORSFCERRORS,
+ PNOR::MOD_PNORDD_CHECKFOROPBERRORS,
PNOR::RC_ERROR_IN_STATUS_REG,
fir_reg.data64,
o_pnorResetLevel );
// Limited in callout: no PNOR target, so calling out processor
l_err->addHwCallout(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ iv_target,
HWAS::SRCI_PRIORITY_HIGH,
HWAS::NO_DECONFIG,
HWAS::GARD_NULL );
@@ -1097,7 +1134,7 @@ errlHndl_t PnorDD::checkForOpbErrors( ResetLevels &o_pnorResetLevel )
// Log FIR Register Data
ERRORLOG::ErrlUserDetailsLogRegister
- l_eud(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+ l_eud(iv_target);
l_eud.addDataBuffer(&fir_data, scom_size,
DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_REG));
@@ -1136,16 +1173,12 @@ void PnorDD::addFFDCRegisters(errlHndl_t & io_errl)
io_errl->eid(), io_errl->plid() );
ERRORLOG::ErrlUserDetailsLogRegister
- l_eud(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+ l_eud(iv_target);
do {
- // Add ECCB Status Register
- TARGETING::Target* scom_target =
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
-
tmp_err = deviceOp( DeviceFW::READ,
- scom_target,
+ iv_target,
&(data64),
size64,
DEVICE_SCOM_ADDRESS(ECCB_STAT_REG) );
@@ -1163,7 +1196,7 @@ void PnorDD::addFFDCRegisters(errlHndl_t & io_errl)
// Add OPB Fir Register
tmp_err = deviceOp( DeviceFW::READ,
- scom_target,
+ iv_target,
&(data64),
size64,
DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_REG) );
@@ -1382,13 +1415,13 @@ errlHndl_t PnorDD::micronFlagStatus(uint64_t i_pollTime)
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_PNORDD_MICRONFLAGSTATUS,
PNOR::RC_MICRON_INCOMPLETE,
- TWO_UINT32_TO_UINT64(cv_nor_chipid,
+ TWO_UINT32_TO_UINT64(iv_nor_chipid,
poll_time),
TWO_UINT32_TO_UINT64(opStatus,0));
// Limited in callout: no PNOR target, so calling out processor
l_err->addHwCallout(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ iv_target,
HWAS::SRCI_PRIORITY_HIGH,
HWAS::NO_DECONFIG,
HWAS::GARD_NULL );
@@ -1514,7 +1547,7 @@ errlHndl_t PnorDD::getNORChipId(uint32_t& o_chipId,
if( o_chipId == MICRON_NOR_ID )
{
// Assume all Micron chips have this bug
- cv_hw_workaround |= HWWK_MICRON_EXT_READ;
+ iv_hw_workaround |= HWWK_MICRON_EXT_READ;
uint32_t outdata[4];
@@ -1538,7 +1571,7 @@ errlHndl_t PnorDD::getNORChipId(uint32_t& o_chipId,
{
TRACFCOMP( g_trac_pnor,"PnorDD::getNORChipId> Setting Micron workaround flag");
//Set Micron workaround flag
- cv_hw_workaround |= HWWK_MICRON_WRT_ERASE;
+ iv_hw_workaround |= HWWK_MICRON_WRT_ERASE;
}
@@ -1644,7 +1677,7 @@ errlHndl_t PnorDD::flushSfcBuf(uint32_t i_addr,
if(l_err) { break; }
//check for special Micron Flag Status reg
- if(cv_hw_workaround & HWWK_MICRON_WRT_ERASE)
+ if(iv_hw_workaround & HWWK_MICRON_WRT_ERASE)
{
l_err = micronFlagStatus();
if(l_err) { break; }
@@ -1901,10 +1934,6 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
do {
- //@todo (RTC:36950) - add non-master support
- TARGETING::Target* scom_target =
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
-
// always read/write 64 bits to SCOM
size_t scom_size = sizeof(uint64_t);
@@ -1913,7 +1942,7 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
eccb_cmd.read_op = 1;
eccb_cmd.address = i_addr;
l_err = deviceOp( DeviceFW::WRITE,
- scom_target,
+ iv_target,
&(eccb_cmd.data64),
scom_size,
DEVICE_SCOM_ADDRESS(ECCB_CTL_REG) );
@@ -1927,7 +1956,7 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
while( poll_time < ECCB_POLL_TIME_NS )
{
l_err = deviceOp( DeviceFW::READ,
- scom_target,
+ iv_target,
&(eccb_stat.data64),
scom_size,
DEVICE_SCOM_ADDRESS(ECCB_STAT_REG) );
@@ -1938,6 +1967,7 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
break;
}
+
// want to start out incrementing by small numbers then get bigger
// to avoid a really tight loop in an error case so we'll increase
// the wait each time through
@@ -1972,7 +2002,7 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
// Limited in callout: no PNOR target, so calling out processor
l_err->addHwCallout(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ iv_target,
HWAS::SRCI_PRIORITY_HIGH,
HWAS::NO_DECONFIG,
HWAS::GARD_NULL );
@@ -2008,7 +2038,7 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
{
// Commit reset error since we have original error l_err
TRACFCOMP(g_trac_pnor, "PnorDD::readLPC Error from resetPnor() after previous error eid=0x%X. Committing resetPnor() error log eid=0x%X.",
- l_err->eid(), tmp_err->eid());
+ l_err->eid(), tmp_err->eid());
tmp_err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL);
tmp_err->collectTrace(PNOR_COMP_NAME);
@@ -2035,10 +2065,6 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
do {
- //@todo (RTC:36950) - add non-master support
- TARGETING::Target* scom_target =
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
-
// always read/write 64 bits to SCOM
size_t scom_size = sizeof(uint64_t);
@@ -2048,7 +2074,7 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
uint64_t eccb_data = static_cast<uint64_t>(i_data);
eccb_data = eccb_data << 32; //left-justify my data
l_err = deviceOp( DeviceFW::WRITE,
- scom_target,
+ iv_target,
&eccb_data,
scom_size,
DEVICE_SCOM_ADDRESS(ECCB_DATA_REG) );
@@ -2060,7 +2086,7 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
eccb_cmd.address = i_addr;
TRACDCOMP(g_trac_pnor, "writeLPC> Write ECCB command register, cmd=0x%.16x", eccb_cmd.data64 );
l_err = deviceOp( DeviceFW::WRITE,
- scom_target,
+ iv_target,
&(eccb_cmd.data64),
scom_size,
DEVICE_SCOM_ADDRESS(ECCB_CTL_REG) );
@@ -2074,7 +2100,7 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
while( poll_time < ECCB_POLL_TIME_NS )
{
l_err = deviceOp( DeviceFW::READ,
- scom_target,
+ iv_target,
&(eccb_stat.data64),
scom_size,
DEVICE_SCOM_ADDRESS(ECCB_STAT_REG) );
@@ -2119,7 +2145,7 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
eccb_stat.data64);
// Limited in callout: no PNOR target, so calling out processor
l_err->addHwCallout(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ iv_target,
HWAS::SRCI_PRIORITY_HIGH,
HWAS::NO_DECONFIG,
HWAS::GARD_NULL );
@@ -2151,7 +2177,7 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
{
// Commit reset error since we have original error l_err
TRACFCOMP(g_trac_pnor, "PnorDD::writeLPC Error from resetPnor() after previous error eid=0x%X. Committing resetPnor() error log eid=0x%X.",
- l_err->eid(), tmp_err->eid());
+ l_err->eid(), tmp_err->eid());
tmp_err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL);
tmp_err->collectTrace(PNOR_COMP_NAME);
@@ -2366,7 +2392,6 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
// reset class variable since we're starting a new operation
iv_error_recovery_failed = false;
-
// This do-while loop supports retries
do {
@@ -2404,13 +2429,13 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
break; //all done
}
- else if(cv_nor_chipid != 0)
+ else if(iv_nor_chipid != 0)
{
// group this block together with do-while
do{
- TRACDCOMP(g_trac_pnor, "PnorDD::eraseFlash> Erasing flash for cv_nor_chipid=0x%.8x, iv_mode=0x%.8x",
- cv_nor_chipid, iv_mode);
+ TRACDCOMP(g_trac_pnor, "PnorDD::eraseFlash> Erasing flash for iv_nor_chipid=0x%.8x, iv_mode=0x%.8x",
+ iv_nor_chipid, iv_mode);
//Write erase address to ADR reg
l_err = writeRegSfc(SFC_CMD_SPACE,
@@ -2434,7 +2459,7 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
if(l_err) { break; }
//check for special Micron Flag Status reg
- if(cv_hw_workaround & HWWK_MICRON_WRT_ERASE)
+ if(iv_hw_workaround & HWWK_MICRON_WRT_ERASE)
{
l_err = micronFlagStatus();
if(l_err) { break; }
@@ -2445,8 +2470,8 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
}
else
{
- TRACFCOMP(g_trac_pnor,"PnorDD::eraseFlash> Erase not supported for cv_nor_chipid=%d",
- cv_nor_chipid );
+ TRACFCOMP(g_trac_pnor,"PnorDD::eraseFlash> Erase not supported for iv_nor_chipid=%d",
+ iv_nor_chipid );
/*@
* @errortype
@@ -2460,7 +2485,7 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_PNORDD_ERASEFLASH,
PNOR::RC_UNSUPPORTED_OPERATION,
- static_cast<uint64_t>(cv_nor_chipid),
+ static_cast<uint64_t>(iv_nor_chipid),
i_address,
true /*Add HB SW Callout*/ );
l_err->collectTrace(PNOR_COMP_NAME);
@@ -2493,7 +2518,7 @@ errlHndl_t PnorDD::readRegFlash( SfcCustomReg_t i_cmd,
{
//Do a read of flash address zero to workaround
// a micron bug with extended reads
- if( (HWWK_MICRON_EXT_READ & cv_hw_workaround)
+ if( (HWWK_MICRON_EXT_READ & iv_hw_workaround)
&& (i_cmd.length > 4) )
{
l_err = loadSfcBuf( 0, 1 );
@@ -2628,11 +2653,6 @@ errlHndl_t PnorDD::resetPnor( ResetLevels i_pnorResetLevel )
do {
- // Setup common scom target
- //@todo (RTC:36950) - add non-master support
- TARGETING::Target* scom_target =
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
-
// always read/write 64 bits to SCOM
uint64_t scom_data_64 = 0x0;
size_t scom_size = sizeof(uint64_t);
@@ -2665,7 +2685,7 @@ errlHndl_t PnorDD::resetPnor( ResetLevels i_pnorResetLevel )
TRACFCOMP(g_trac_pnor, "PnorDD::resetPnor> Writing ECCB_RESET_REG to reset ECCB FW Logic");
scom_data_64 = 0x0;
l_err = deviceOp( DeviceFW::WRITE,
- scom_target,
+ iv_target,
&(scom_data_64),
scom_size,
DEVICE_SCOM_ADDRESS(ECCB_RESET_REG) );
@@ -2705,7 +2725,7 @@ errlHndl_t PnorDD::resetPnor( ResetLevels i_pnorResetLevel )
scom_data_64 = ~(OPB_LPCM_FIR_ERROR_MASK);
l_err = deviceOp(
DeviceFW::WRITE,
- scom_target,
+ iv_target,
&(scom_data_64),
scom_size,
DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_WOX_AND_REG) );
@@ -2730,8 +2750,8 @@ errlHndl_t PnorDD::resetPnor( ResetLevels i_pnorResetLevel )
scom_data_64 = ~(OPB_LPCM_FIR_ERROR_MASK);
l_err = deviceOp(
DeviceFW::WRITE,
- scom_target,
- &(scom_data_64),
+ iv_target,
+ &(scom_data_64),
scom_size,
DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_WOX_AND_REG) );
@@ -2878,7 +2898,7 @@ errlHndl_t PnorDD::reinitializeSfc( void )
do {
-#ifdef PNORDD_FSPATTACHED
+#ifdef CONFIG_BMC_DOES_SFC_INIT
TRACFCOMP( g_trac_pnor, ERR_MRK"PnorDD::reinitializeSfc> Need to Re-Initialize SFC. Calling doShutdown(PNOR::RC_REINITIALIZE_SFC)");
@@ -2892,7 +2912,7 @@ errlHndl_t PnorDD::reinitializeSfc( void )
// Clear member variable in case we don't successfully
// reinitialize PNOR
- cv_sfcInitDone = false;
+ iv_sfcInitDone = false;
l_err = writeRegSfc(SFC_CMD_SPACE,
SFC_REG_OADRNB,
@@ -2922,12 +2942,12 @@ errlHndl_t PnorDD::reinitializeSfc( void )
//Determine NOR Flash type - triggers vendor specific workarounds
//We also use the chipID in some FFDC situations.
- l_err = getNORChipId(cv_nor_chipid);
+ l_err = getNORChipId(iv_nor_chipid);
if(l_err) { break; }
TRACFCOMP(g_trac_pnor,
- "PnorDD::reinitializeSfc> cv_nor_chipid=0x%.8x> ",
- cv_nor_chipid );
+ "PnorDD::reinitializeSfc> iv_nor_chipid=0x%.8x> ",
+ iv_nor_chipid );
l_err = readRegSfc(SFC_CMD_SPACE,
SFC_REG_ERASMS,
@@ -2935,7 +2955,7 @@ errlHndl_t PnorDD::reinitializeSfc( void )
if(l_err) { break; }
// Good path if you made it here: reset class variable
- cv_sfcInitDone = true;
+ iv_sfcInitDone = true;
#endif
diff --git a/src/usr/pnor/pnordd.H b/src/usr/pnor/pnordd.H
index 93d03d117..25915b294 100644
--- a/src/usr/pnor/pnordd.H
+++ b/src/usr/pnor/pnordd.H
@@ -99,10 +99,17 @@ class PnorDD
/**
* @brief Constructor
+ *
+ * @parm i_mode o_buffer Buffer to read data into
+ * @parm i_fakeStart Input: Number of bytes to read,
+ * @parm i_fakeSize Output: Number of bytes actually read
+ * @parm i_target Processor Target connected to PNOR
+ * NOTE: i_target can only be used when targetting is loaded
*/
PnorDD( PnorMode_t i_mode = MODEL_UNKNOWN,
uint64_t i_fakeStart = 0,
- uint64_t i_fakeSize = 0);
+ uint64_t i_fakeSize = 0,
+ TARGETING::Target* i_target = NULL );
/**
@@ -335,7 +342,6 @@ class PnorDD
SfcStatReg_t() : data32(0) {};
};
-
/**
* @brief LPC Slave Registers
* These are offsets within the LPC Slave Register Space
@@ -659,6 +665,7 @@ class PnorDD
errlHndl_t writeLPC(uint32_t i_addr,
uint32_t i_data);
+
/**
* @brief Erase a block of flash
*
@@ -903,11 +910,24 @@ class PnorDD
// NOTE: The layout of the variables in this class must be maintained
// along with the offsets in the debug framework.
+ /**
+ * @brief Global Mutex to prevent concurrent PNOR accesses to Master Proc
+ * This needs to be static so we can mutex across multiple
+ * instances of PnorDD
+ */
+ static mutex_t cv_mutex;
+
/**
- * @brief Mutex to prevent concurrent PNOR accesses
- * This needs to be static so we can mutex across multiple instances of PnorDD
+ * @brief Class Mutex used to prevent concurrent PNOR accesses
*/
- static mutex_t cv_mutex;
+ mutex_t iv_mutex;
+
+ /**
+ * @brief Mutex pointer to either class-specific or global mutex to prevent
+ * concurrent PNOR accesses.
+ * Each class uses a mutex; some share the static cv_mutex
+ */
+ mutex_t* iv_mutex_ptr;
/**
* @brief Track PNOR erases for wear monitoring
@@ -924,7 +944,7 @@ class PnorDD
/**
* @brief Flag to drive special behavior in VPO.
*/
- static uint64_t iv_vpoMode;
+ uint64_t iv_vpoMode;
/**
* @brief describes the erase block size, set based on NOR chip type
@@ -936,19 +956,19 @@ class PnorDD
* @brief CHIP ID or the NOR chip attached to SFC.
*
*/
- static uint32_t cv_nor_chipid;
+ uint32_t iv_nor_chipid;
/**
* @brief Hardware workarounds
*
*/
- static uint32_t cv_hw_workaround;
+ uint32_t iv_hw_workaround;
/**
* @brief indicates if SFC initialization has been performed.
*
*/
- static bool cv_sfcInitDone;
+ bool iv_sfcInitDone;
/**
* @brief Start of Fake PNOR address range..
@@ -986,6 +1006,12 @@ class PnorDD
*/
bool iv_reset_active;
+ /**
+ * @brief Processor Target used to access PNOR device
+ *
+ */
+ TARGETING::Target* iv_target;
+
// Needed for testcases
friend class PnorDdTest;
diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H
index 6c8c5b416..38043f875 100644
--- a/src/usr/pnor/pnorrp.H
+++ b/src/usr/pnor/pnorrp.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2014 */
+/* [+] 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. */
@@ -31,6 +33,25 @@
#include <vmmconst.h>
#include <map>
+namespace PNOR
+{
+
+ /**
+ * @brief Creates a 4-byte Cyclic Redundancy Check (CRC) on the data
+ * provided. The last iteration of the for-loop includes the ffs
+ * checksum itself. Therefore if the 4-byte CRC created matches
+ * the ffs checksum, the resulting CRC will be 0
+ *
+ * @param[in] ptr Pointer to the data
+ *
+ * @param[in] size Size of the data
+ *
+ * @return uint32_t return 4-byte CRC, 0 if checksums match
+ */
+ uint32_t pnor_ffs_checksum(void* data, size_t size);
+
+}; //namespace PNOR
+
/**
* PNOR Resource Provider
*/
@@ -55,20 +76,6 @@ class PnorRP
errlHndl_t getSectionInfo( PNOR::SectionId i_section,
PNOR::SectionInfo_t& o_info );
- /**
- * @brief Creates a 4-byte Cyclic Redundancy Check (CRC) on the data
- * provided. The last iteration of the for-loop includes the ffs
- * checksum itself. Therefore if the 4-byte CRC created matches
- * the ffs checksum, the resulting CRC will be 0
- *
- * @param[in] ptr Pointer to the data
- *
- * @param[in] size Size of the data
- *
- * @return uint32_t return 4-byte CRC, 0 if checksums match
- */
- uint32_t pnor_ffs_checksum(void* data, size_t size);
-
protected:
/**
* @brief Constructor
@@ -254,6 +261,9 @@ class PnorRP
friend class PnorRpTest;
friend class PnorDdTest;
+ // allow this function to use constant(s)
+ friend errlHndl_t PNOR::validateAltMaster( void );
+
/**
* @brief Static instance function for testcase only
*/
diff --git a/src/usr/pnor/pnorvalid.C b/src/usr/pnor/pnorvalid.C
new file mode 100644
index 000000000..22232729d
--- /dev/null
+++ b/src/usr/pnor/pnorvalid.C
@@ -0,0 +1,410 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnorvalid.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014 */
+/* [+] 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 pnorvalid.C
+ *
+ * @brief Implements PNOR::validateAltMaster(), which Validates
+ * the Alternative Master Processor's connection to PNOR
+ */
+
+/*****************************************************************************/
+// I n c l u d e s
+/*****************************************************************************/
+#include <trace/interface.H>
+#include <devicefw/driverif.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <errl/errludlogregister.H>
+#include <targeting/common/targetservice.H>
+#include <targeting/common/utilFilter.H>
+#include <attributeenums.H>
+#include "ffs.h"
+#include "common/ffs_hb.H"
+#include "pnorrp.H"
+#include "pnordd.H"
+#include <pnor/pnorif.H>
+#include <pnor/pnor_reasoncodes.H>
+
+
+// Used for creating an Invalid TOC ("PNOR")
+#define PNORVALID_FAKE_MAGIC 0x504E4F52
+
+extern trace_desc_t* g_trac_pnor;
+
+namespace PNOR
+{
+
+/**
+ * @brief Validate the MAGIC field in the TOC
+ *
+ * @parm i_pnordd PNOR Device Driver Object of Alt Master
+ * @parm i_ffs_hdr FFS Header to check
+ * @parm i_toc0_offset Offset Address of TOC
+ * @parm i_attempt_write If invalid MAGIC, rewrite TOC if true
+ * (createEmptyTOC gets called)
+ *
+ * @return errlHndl_t Error log if validation failed
+ */
+errlHndl_t validateMagic(PnorDD* i_pnordd,
+ ffs_hdr* i_ffs_hdr,
+ uint64_t i_toc0_offset,
+ bool i_attempt_write);
+
+/**
+ * @brief Create an Invalid TOC on Alt Master's PNOR
+ *
+ * @parm i_pnordd PNOR Device Driver Object of Alt Master
+ * @parm i_ffs_hdr FFS Header to check
+ * @parm i_toc0_offset Offset Address of TOC
+ *
+ * @return errlHndl_t Error log if validation failed
+ */
+errlHndl_t createInvalidTOC(PnorDD* i_pnordd,
+ ffs_hdr* i_ffs_hdr,
+ uint64_t i_toc0_offset);
+
+/**
+ * @brief Validate the Alternative Master Processor's LPC connection to PNOR
+ *
+ * @return errlHndl_t Error log if validation failed
+ */
+
+errlHndl_t validateAltMaster( void )
+{
+ errlHndl_t l_err = NULL;
+
+ PnorDD* pnordd = NULL;
+
+ // When reading PNOR TOC assume a single page and no ECC
+ uint8_t* tocBuffer = new uint8_t[PAGESIZE];
+ size_t read_size = PAGESIZE;
+ const uint64_t toc0_offset = PnorRP::TOC_0_OFFSET;
+
+ do{
+
+ // Get list of all processors
+ TARGETING::TargetHandleList procList;
+ TARGETING::getAllChips(procList,
+ TARGETING::TYPE_PROC,
+ true); // true: return functional targets
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_pnor, INFO_MRK"PNOR::validateAltMaster()> No functional processors Found! Validation skipped" );
+ break;
+ }
+
+ // Loop through all processors
+ for(uint32_t i=0; i<procList.size(); i++)
+ {
+ // Check if processor is MASTER_CANDIDATE
+ TARGETING::ATTR_PROC_MASTER_TYPE_type type_enum =
+ procList[i]->getAttr<TARGETING::ATTR_PROC_MASTER_TYPE>();
+
+ if ( type_enum != TARGETING::PROC_MASTER_TYPE_MASTER_CANDIDATE )
+ {
+ TRACDCOMP( g_trac_pnor, INFO_MRK"PNOR::validateAltMaster> Skipping Processor 0x%X (PROC_MASTER_TYPE=%d)",
+ TARGETING::get_huid(procList[i]), type_enum);
+ continue;
+ }
+
+ TRACFCOMP( g_trac_pnor, INFO_MRK"PNOR::validateAltMaster> Validating Processor 0x%X (PROC_MASTER_TYPE=%d)",
+ TARGETING::get_huid(procList[i]), type_enum);
+
+ // Create and initialize custom PNOR DD class for this target
+ if ( pnordd )
+ {
+ delete pnordd;
+ pnordd = NULL;
+ }
+ pnordd = new PnorDD(PnorDD::MODEL_REAL_MMIO, 0, 0, procList[i]);
+
+ // Read Flash
+ l_err = pnordd->readFlash(tocBuffer, read_size,
+ PnorRP::TOC_0_OFFSET);
+ if ( l_err )
+ {
+ // Commit Error Log, but continue the test
+ TRACFCOMP( g_trac_pnor, INFO_MRK"PNOR::validateAltMaster> readFlash fail for 0x%X. eid=0x%X, rc=0x%X. Committing log and Continuing",
+ TARGETING::get_huid(procList[i]), l_err->eid(),
+ l_err->reasonCode());
+
+ l_err->collectTrace(PNOR_COMP_NAME);
+
+ // if there was an error, commit here and then proceed to
+ // the next processor
+ errlCommit(l_err,PNOR_COMP_ID);
+ continue;
+ }
+
+ // Set the header pointer
+ ffs_hdr* l_ffs_hdr = (ffs_hdr*) tocBuffer;
+
+ // Recursive function to check FFS/TOC Magic and possibly write
+ // new TOC if necessary
+ l_err = validateMagic(pnordd,
+ l_ffs_hdr,
+ toc0_offset,
+ true); // true->write TOC if necessary
+
+ if ( l_err )
+ {
+ // Commit Error Log, but continue the test
+ TRACFCOMP( g_trac_pnor, INFO_MRK"PNOR::validateAltMaster> validateMagic fail for 0x%X. eid=0x%X, rc=0x%X. Committing log and Continuing",
+ TARGETING::get_huid(procList[i]), l_err->eid(),
+ l_err->reasonCode());
+
+ // Limited in callout: no PNOR target, so calling out processor
+ l_err->addHwCallout(
+ procList[i],
+ HWAS::SRCI_PRIORITY_HIGH,
+ HWAS::NO_DECONFIG,
+ HWAS::GARD_NULL );
+
+
+ l_err->collectTrace(PNOR_COMP_NAME);
+
+ // if there was an error, commit here and then proceed to
+ // the next processor
+ errlCommit(l_err,PNOR_COMP_ID);
+ continue;
+ }
+
+
+ // Now check ffs entry checksum (0 if checksums match)
+ if( pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE) != 0)
+ {
+ //@TODO - RTC:90780 - May need to handle this differently in
+ // SP-less config
+ TRACFCOMP(g_trac_pnor, "PNOR::validateAltMaster> pnor_ffs_checksum header checksums do not match on target 0x%X. Create and commit error log then continue the test",
+ TARGETING::get_huid(procList[i]));
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORVALID_MAIN
+ * @reasoncode PNOR::RC_PARTITION_TABLE_INVALID
+ * @userdata1 Master Candidate Processor Target
+ * @userdata2 <unused>
+ * @devdesc PNOR::validateAltMaster> Fail verifying FFS
+ * Header on Master Candidate PNOR TOC0
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORVALID_MAIN,
+ PNOR::RC_PARTITION_TABLE_INVALID,
+ TARGETING::get_huid(procList[i]),
+ 0);
+
+ // Limited in callout: no PNOR target, so calling out processor
+ l_err->addHwCallout(
+ procList[i],
+ HWAS::SRCI_PRIORITY_HIGH,
+ HWAS::NO_DECONFIG,
+ HWAS::GARD_NULL );
+
+
+ TRACFBIN(g_trac_pnor, "tocBuffer", tocBuffer, 0x20);
+
+ l_err->collectTrace(PNOR_COMP_NAME);
+ errlCommit(l_err,PNOR_COMP_ID);
+ continue;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::validateAltMaster> Successful validation of Alt-Master 0x%X",
+ TARGETING::get_huid(procList[i]));
+ }
+
+ } // end of processor 'for' loop
+
+
+ }while(0);
+
+ // Delete PNOR DD class and memory buffer
+ if ( pnordd )
+ {
+ delete pnordd;
+ pnordd = NULL;
+ }
+
+ if(tocBuffer != NULL)
+ {
+ delete[] tocBuffer;
+ tocBuffer = NULL;
+ }
+
+ return l_err;
+}
+
+
+
+/**
+ * @brief Validate the MAGIC field in the TOC
+ */
+errlHndl_t validateMagic(PnorDD* i_pnordd,
+ ffs_hdr* i_ffs_hdr,
+ uint64_t i_toc0_offset,
+ bool i_attempt_write)
+{
+ errlHndl_t l_err = NULL;
+
+ do{
+
+ /* Checking FFS Header MAGIC to make sure it looks valid */
+ if ( ( i_ffs_hdr->magic != FFS_MAGIC ) &&
+ ( i_ffs_hdr->magic != PNORVALID_FAKE_MAGIC ) )
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::validateMagic> Invalid magic number in FFS header: 0x%.4X",
+ i_ffs_hdr->magic);
+
+ TRACFBIN(g_trac_pnor, "PNOR::validateMagic> i_ffs_hdr",
+ i_ffs_hdr, FFS_HDR_SIZE);
+
+ // Check if we should attempt to write empty TOC
+ if ( i_attempt_write == true )
+ {
+ // Write Invalid TOC with a specific 'MAGIC' marker
+ l_err = createInvalidTOC(i_pnordd, i_ffs_hdr, i_toc0_offset);
+ if ( l_err )
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::validateMagic> createInvalidTOC returned error: eid=0x%X, rc=0x%X",
+ l_err->eid(), l_err->reasonCode());
+ break;
+ }
+ else
+ {
+ // Writing TOC successful, so recursively call this function
+ l_err = validateMagic(i_pnordd,
+ i_ffs_hdr,
+ i_toc0_offset,
+ false); // false->don't write TOC
+ if ( l_err )
+ {
+
+ TRACFCOMP(g_trac_pnor, "PNOR::validateMagic> After successful createEmptyTOC, validateMagic returned error: eid=0x%X, rc=0x%X",
+ l_err->eid(), l_err->reasonCode());
+ break;
+ }
+ }
+ }
+ else
+ {
+
+ //@TODO - RTC:90780 - May need to handle this differently in
+ // SP-less config
+ TRACFCOMP(g_trac_pnor, "PNOR::validateMagic> MAGIC number header still incorrect after writing empty TOC");
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORVALID_MAGIC
+ * @reasoncode PNOR::RC_PARTITION_TABLE_INVALID
+ * @userdata1 Magic Number read
+ * @userdata2 <unused>
+ * @devdesc PNOR::validateMagic> Fail verifying FFS Magic
+ * Number in Header on Master
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORVALID_MAGIC,
+ PNOR::RC_PARTITION_TABLE_INVALID,
+ i_ffs_hdr->magic,
+ 0);
+
+ TRACFBIN(g_trac_pnor, "i_ffs_hdr", i_ffs_hdr, FFS_HDR_SIZE);
+
+ // HW Callout handled by caller
+ break;
+ }
+ }
+
+ }while(0);
+
+
+ return l_err;
+}
+
+/**
+ * @brief Create an Invalid TOC on Alt Master's PNOR
+ */
+errlHndl_t createInvalidTOC(PnorDD* i_pnordd,
+ ffs_hdr* i_ffs_hdr,
+ uint64_t i_toc0_offset)
+{
+ errlHndl_t l_err = NULL;
+
+ // When reading PNOR TOC assume a single page and no ECC
+ size_t toc_size = PAGESIZE;
+
+ do{
+ // Create FFS Header of Empty TOC with Invalid MAGIC field
+ ffs_hdr l_hdr;
+
+ // Clear the struct and only set (invalid) MAGIC and checksum fields
+ // - Thus HWSV will recognize this TOC needs to be updated
+ memset(&(l_hdr), 0, FFS_HDR_SIZE);
+ l_hdr.magic = PNORVALID_FAKE_MAGIC;
+ l_hdr.checksum = pnor_ffs_checksum(&(l_hdr), FFS_HDR_SIZE_CSUM);
+
+ // Re-use previously defined io_ffs_hdr memory space
+ memset(i_ffs_hdr, 0, toc_size);
+ memcpy(i_ffs_hdr, &(l_hdr), FFS_HDR_SIZE);
+
+ TRACFBIN(g_trac_pnor, "PNOR::createInvalidTOC> New FFS Header",
+ i_ffs_hdr, FFS_HDR_SIZE);
+
+
+ // Write TOC to PNOR
+ l_err = i_pnordd->writeFlash(i_ffs_hdr, toc_size,
+ i_toc0_offset);
+ if ( l_err )
+ {
+ TRACFCOMP( g_trac_pnor, INFO_MRK"PNOR::createInvalidTOC> writeFlash fail: eid=0x%X, rc=0x%X",
+ l_err->eid(), l_err->reasonCode());
+
+ TRACFBIN(g_trac_pnor, "EMPTY TOC", i_ffs_hdr, 0x20);
+ break;
+ }
+
+ // Read Back TOC from PNOR (reset toc_size and i_ffs_hdr to be safe)
+ toc_size = PAGESIZE;
+ memset(i_ffs_hdr, 0, toc_size);
+ l_err = i_pnordd->readFlash(i_ffs_hdr, toc_size,
+ i_toc0_offset);
+ if ( l_err )
+ {
+ TRACFCOMP( g_trac_pnor, INFO_MRK"PNOR::createInvalidTOC> readFlash fail: eid=0x%X, rc=0x%X",
+ l_err->eid(), l_err->reasonCode());
+
+ }
+
+
+ }while(0);
+
+ return l_err;
+}
+
+}; //namespace PNOR
+
diff --git a/src/usr/pnor/test/pnorddtest.H b/src/usr/pnor/test/pnorddtest.H
index 652ed0597..d762875b0 100644
--- a/src/usr/pnor/test/pnorddtest.H
+++ b/src/usr/pnor/test/pnorddtest.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2014 */
+/* [+] 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. */
@@ -996,7 +998,7 @@ class PnorDdTest : public CxxTest::TestSuite
sfc_cmd.opcode = PnorDD::SFC_OP_INVALID;
sfc_cmd.length = 0;
- mutex_lock(&(pnordd->cv_mutex));
+ mutex_lock(pnordd->iv_mutex_ptr);
l_err = pnordd->writeRegSfc(PnorDD::SFC_CMD_SPACE,
PnorDD::SFC_REG_CMD,
sfc_cmd.data32);
@@ -1007,16 +1009,16 @@ class PnorDdTest : public CxxTest::TestSuite
fails++;
// Unlock mutex for Error Log to be commited
- mutex_unlock(&(pnordd->cv_mutex));
+ mutex_unlock(pnordd->iv_mutex_ptr);
errlCommit(l_err,PNOR_COMP_ID);
// Lock mutex for next operation
- mutex_lock(&(pnordd->cv_mutex));
+ mutex_lock(pnordd->iv_mutex_ptr);
}
// Poll for complete status without waiting
l_err = pnordd->pollSfcOpComplete();
- mutex_unlock(&(pnordd->cv_mutex));
+ mutex_unlock(pnordd->iv_mutex_ptr);
total++;
if ( l_err == NULL )
@@ -1037,7 +1039,7 @@ class PnorDdTest : public CxxTest::TestSuite
sfc_cmd.opcode = PnorDD::SFC_OP_CHIPID;
sfc_cmd.length = 0;
- mutex_lock(&(pnordd->cv_mutex));
+ mutex_lock(pnordd->iv_mutex_ptr);
l_err = pnordd->writeRegSfc(PnorDD::SFC_CMD_SPACE,
PnorDD::SFC_REG_CMD,
sfc_cmd.data32);
@@ -1049,11 +1051,11 @@ class PnorDdTest : public CxxTest::TestSuite
fails++;
// Unlock mutex for Error Log to be commited
- mutex_unlock(&(pnordd->cv_mutex));
+ mutex_unlock(pnordd->iv_mutex_ptr);
errlCommit(l_err,PNOR_COMP_ID);
// Lock mutex for next operation
- mutex_lock(&(pnordd->cv_mutex));
+ mutex_lock(pnordd->iv_mutex_ptr);
}
// Poll for complete status without waiting
@@ -1076,7 +1078,7 @@ class PnorDdTest : public CxxTest::TestSuite
/* before continuing */
/*******************************************************/
l_err = pnordd->pollSfcOpComplete();
- mutex_unlock(&(pnordd->cv_mutex));
+ mutex_unlock(pnordd->iv_mutex_ptr);
total++;
if (l_err)
OpenPOWER on IntegriCloud