summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/fsi/fsipres.C91
-rw-r--r--src/usr/hwpf/hwp/mc_config/mc_config.C71
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types_hb.xml27
-rw-r--r--src/usr/targeting/common/xmltohb/target_types_hb.xml7
-rw-r--r--src/usr/vpd/HBconfig8
-rw-r--r--src/usr/vpd/cvpd.C2
-rwxr-xr-xsrc/usr/vpd/dimmPres.C34
-rw-r--r--src/usr/vpd/ipvpd.C586
-rw-r--r--src/usr/vpd/ipvpd.H114
-rw-r--r--src/usr/vpd/mvpd.C3
-rw-r--r--src/usr/vpd/mvpd.H5
-rw-r--r--src/usr/vpd/runtime/rt_vpd.C73
-rw-r--r--[-rwxr-xr-x]src/usr/vpd/spd.C455
-rwxr-xr-xsrc/usr/vpd/spd.H79
-rwxr-xr-xsrc/usr/vpd/test/cvpdtest.H12
-rwxr-xr-xsrc/usr/vpd/test/mvpdtest.H12
-rwxr-xr-xsrc/usr/vpd/test/spdtest.H7
-rwxr-xr-x[-rw-r--r--]src/usr/vpd/vpd.C287
-rw-r--r--src/usr/vpd/vpd.H30
19 files changed, 1613 insertions, 290 deletions
diff --git a/src/usr/fsi/fsipres.C b/src/usr/fsi/fsipres.C
index dfc74c6a6..e47b67e7d 100644
--- a/src/usr/fsi/fsipres.C
+++ b/src/usr/fsi/fsipres.C
@@ -35,7 +35,6 @@
#include <targeting/common/predicates/predicatectm.H>
#include <config.h>
-
extern trace_desc_t* g_trac_fsi;
@@ -69,6 +68,7 @@ errlHndl_t procPresenceDetect(DeviceFW::OperationType i_opType,
va_list i_args)
{
errlHndl_t l_errl = NULL;
+ uint32_t l_saved_plid = 0;
if (unlikely(io_buflen < sizeof(bool)))
{
@@ -109,24 +109,50 @@ errlHndl_t procPresenceDetect(DeviceFW::OperationType i_opType,
}
// Next look for valid Module VPD
+ bool mvpd_present = false;
bool check_for_mvpd = true;
+
#ifdef CONFIG_MVPD_READ_FROM_HW
check_for_mvpd = fsi_present;
-#endif // CONFIG_MVPD_READ_FROM_HW
-
- bool mvpd_present = false;
+#endif
if ( check_for_mvpd )
{
mvpd_present = VPD::mvpdPresent( i_target );
}
+#if defined(CONFIG_MVPD_READ_FROM_HW) && defined(CONFIG_MVPD_READ_FROM_PNOR)
+ if( mvpd_present )
+ {
+ // Check if the VPD data in the PNOR matches the SEEPROM
+ l_errl = VPD::ensureCacheIsInSync( i_target );
+ if( l_errl )
+ {
+ // Save this plid to use later
+ l_saved_plid = l_errl->plid();
+ mvpd_present = false;
+
+ TRACFCOMP(g_trac_fsi,ERR_MRK "FSI::procPresenceDetect> Error during ensureCacheIsInSync (MVPD)" );
+ errlCommit( l_errl, FSI_COMP_ID );
+ }
+ }
+ else
+ {
+ // Invalidate MVPD in the PNOR
+ l_errl = VPD::invalidatePnorCache(i_target);
+ if (l_errl)
+ {
+ TRACFCOMP( g_trac_fsi, "Error invalidating MVPD in PNOR" );
+ errlCommit( l_errl, FSI_COMP_ID );
+ }
+ }
+#endif
// Finally compare the 2 methods
if( fsi_present != mvpd_present )
{
- TRACFCOMP(g_trac_fsi,
- ERR_MRK "FSI::procPresenceDetect> FSI (=%d) and MVPD (=%d) do not agree for %.8X",
+ TRACFCOMP(g_trac_fsi, ERR_MRK "FSI::procPresenceDetect> "
+ "FSI (=%d) and MVPD (=%d) do not agree for %.8X",
fsi_present, mvpd_present, TARGETING::get_huid(i_target));
/*@
* @errortype
@@ -153,15 +179,20 @@ errlHndl_t procPresenceDetect(DeviceFW::OperationType i_opType,
HWAS::GARD_NULL );
+ // If there is a saved PLID, apply it to this error log
+ if (l_saved_plid)
+ {
+ l_errl->plid(l_saved_plid);
+ }
+
// Add FFDC for the target to an error log
getFsiFFDC( FFDC_PRESENCE_FAIL, l_errl, i_target);
-
// Add FSI and VPD trace
l_errl->collectTrace("FSI");
l_errl->collectTrace("VPD");
- // commit this log and move on
+ // Commit this log and move on
errlCommit( l_errl,
FSI_COMP_ID );
}
@@ -200,6 +231,7 @@ errlHndl_t membPresenceDetect(DeviceFW::OperationType i_opType,
va_list i_args)
{
errlHndl_t l_errl = NULL;
+ uint32_t l_saved_plid = 0;
if (unlikely(io_buflen < sizeof(bool)))
{
@@ -227,24 +259,51 @@ errlHndl_t membPresenceDetect(DeviceFW::OperationType i_opType,
bool fsi_present = isSlavePresent(i_target);
// Next look for memb FRU VPD
+ bool cvpd_present = false;
bool check_for_cvpd = true;
+
#ifdef CONFIG_CVPD_READ_FROM_HW
check_for_cvpd = fsi_present;
-#endif // CONFIG_CVPD_READ_FROM_HW
-
- bool cvpd_present = false;
+#endif
if ( check_for_cvpd )
{
cvpd_present = VPD::cvpdPresent( i_target );
}
+#if defined(CONFIG_CVPD_READ_FROM_HW) && defined(CONFIG_CVPD_READ_FROM_PNOR)
+ if( cvpd_present )
+ {
+ // Check if the VPD data in the PNOR matches the SEEPROM
+ l_errl = VPD::ensureCacheIsInSync( i_target );
+ if( l_errl )
+ {
+ // Save this plid to use later
+ l_saved_plid = l_errl->plid();
+ cvpd_present = false;
+
+ TRACFCOMP(g_trac_fsi,ERR_MRK "FSI::procPresenceDetect> Error during ensureCacheIsInSync (CVPD)" );
+ errlCommit( l_errl, FSI_COMP_ID );
+ }
+ }
+ else
+ {
+ // FSI is not present, invalidate MVPD in the PNOR
+ l_errl = VPD::invalidatePnorCache(i_target);
+ if (l_errl)
+ {
+ TRACFCOMP( g_trac_fsi, "Error invalidating MVPD in PNOR" );
+ errlCommit( l_errl, FSI_COMP_ID );
+ }
+ }
+#endif
+
// Finally compare the 2 methods
if( fsi_present != cvpd_present )
{
- TRACFCOMP(g_trac_fsi,
- ERR_MRK "FSI::membPresenceDetect> FSI (=%d) and VPD (=%d) do not agree for %.8X",
+ TRACFCOMP(g_trac_fsi, ERR_MRK "FSI::membPresenceDetect> "
+ "FSI (=%d) and VPD (=%d) do not agree for %.8X",
fsi_present, cvpd_present, TARGETING::get_huid(i_target));
/*@
* @errortype
@@ -271,6 +330,12 @@ errlHndl_t membPresenceDetect(DeviceFW::OperationType i_opType,
HWAS::GARD_NULL );
+ // If there is a saved PLID, apply it to this error log
+ if (l_saved_plid)
+ {
+ l_errl->plid(l_saved_plid);
+ }
+
// Add FFDC for the target to an error log
getFsiFFDC( FFDC_PRESENCE_FAIL, l_errl, i_target);
diff --git a/src/usr/hwpf/hwp/mc_config/mc_config.C b/src/usr/hwpf/hwp/mc_config/mc_config.C
index 80c03f475..d6c649333 100644
--- a/src/usr/hwpf/hwp/mc_config/mc_config.C
+++ b/src/usr/hwpf/hwp/mc_config/mc_config.C
@@ -81,6 +81,7 @@
#ifdef CONFIG_DJVPD_READ_FROM_HW
#include <hwas/common/hwas.H>
#include <hwas/common/hwasCommon.H>
+#include <devicefw/driverif.H>
#endif // CONFIG_DJVPD_READ_FROM_HW
#ifdef CONFIG_PALMETTO_VDDR
@@ -110,31 +111,63 @@ static errlHndl_t detect_present_dimms() {
targetService().getAssociated( pCheckPres, pSys,
TargetService::CHILD, TargetService::ALL, &predDimm );
- // Actually check for present DIMMs by PNOR or SPD, this function will
- // prune missing DIMMs from its argument.
- l_err = HWAS::platPresenceDetect(pCheckPres);
-
- if (l_err != NULL)
- {
- return l_err;
- }
-
- // Mark remaining DIMMs as present.
- // @todo RTC:111211, may need to handle turning the dimms off
+ // Check for present DIMMs
+ // @todo RTC:111211, this should be removed when Mike's FSI changes are in
for (TargetHandleList::const_iterator pTarget_it = pCheckPres.begin();
pTarget_it != pCheckPres.end();
++pTarget_it)
{
- // set HWAS state to show DIMM is present, functional.
TARGETING::Target *target = *pTarget_it;
- HwasState hwasState = target->getAttr<ATTR_HWAS_STATE>();
- hwasState.poweredOn = true;
- hwasState.present = true;
- hwasState.functional = true;
- target->setAttr<ATTR_HWAS_STATE>( hwasState );
+
+
+ // call deviceRead() to see if they are present
+ bool present = false;
+ size_t presentSize = sizeof(present);
+ l_err = deviceRead(target, &present, presentSize,
+ DEVICE_PRESENT_ADDRESS());
+
+ if (l_err != NULL)
+ {
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "mc_config failed presence detect "
+ "target HUID %.8X", target->getAttr<ATTR_HUID>());
+
+ // commit the error but keep going
+ errlCommit(l_err, HWPF_COMP_ID);
+
+ // target is not present - fall thru
+ present = false;
+ }
+
+ if (present == true)
+ {
+ TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "mc_config detected present "
+ "target HUID %.8X", target->getAttr<ATTR_HUID>());
+
+ // set HWAS state to show DIMM is present, functional.
+ HwasState hwasState = target->getAttr<ATTR_HWAS_STATE>();
+ hwasState.poweredOn = true;
+ hwasState.present = true;
+ hwasState.functional = true;
+ target->setAttr<ATTR_HWAS_STATE>( hwasState );
+ }
+ else
+ {
+ TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "mc_config no presence target %.8X",
+ target->getAttr<ATTR_HUID>());
+
+ // set HWAS state to show DIMM is not present, not functional.
+ HwasState hwasState = target->getAttr<ATTR_HWAS_STATE>();
+ hwasState.poweredOn = false;
+ hwasState.present = false;
+ hwasState.functional = false;
+ target->setAttr<ATTR_HWAS_STATE>( hwasState );
+ }
}
- return l_err;
+ return NULL;
}
// Disable any MBAs that don't have any DIMMs under them, otherwise
@@ -810,7 +843,7 @@ errlHndl_t call_mss_eff_grouping()
(const_cast<TARGETING::Target*>(l_cpu_target)) );
TARGETING::TargetHandleList l_membufsList;
- getChildAffinityTargets(l_membufsList, l_cpu_target,
+ getChildAffinityTargets(l_membufsList, l_cpu_target,
CLASS_CHIP, TYPE_MEMBUF);
std::vector<fapi::Target> l_associated_centaurs;
diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
index 235b19438..ab7df54d6 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
@@ -665,4 +665,31 @@ Final values for the following HTMG attributes will come from the MRW -->
</attribute>
<!-- end HTMGT attributes -->
+<attribute>
+ <id>VPD_SWITCHES</id>
+ <description>Attribute storing VPD state information</description>
+ <complexType>
+ <description>VPD flags</description>
+ <field>
+ <name>pnorLoaded</name>
+ <description>Set when this target's VPD data has been loaded
+ into the PNOR.
+ </description>
+ <type>uint8_t</type>
+ <bits>1</bits>
+ <default>0</default>
+ </field>
+ <field>
+ <name>reserved</name>
+ <description>Reserved for future expansion</description>
+ <type>uint8_t</type>
+ <bits>7</bits>
+ <default>0</default>
+ </field>
+ </complexType>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+</attribute>
+
</attributes>
diff --git a/src/usr/targeting/common/xmltohb/target_types_hb.xml b/src/usr/targeting/common/xmltohb/target_types_hb.xml
index 78f0504e2..fd662b5b6 100644
--- a/src/usr/targeting/common/xmltohb/target_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/target_types_hb.xml
@@ -86,6 +86,7 @@
<attribute>
<id>HOMER_VIRT_ADDR</id>
</attribute>
+ <attribute><id>VPD_SWITCHES</id></attribute>
</targetTypeExtension>
<targetTypeExtension>
@@ -135,6 +136,7 @@
<attribute>
<id>GPIO_INFO</id>
</attribute>
+ <attribute><id>VPD_SWITCHES</id></attribute>
</targetTypeExtension>
<targetTypeExtension>
@@ -144,4 +146,9 @@
</attribute>
</targetTypeExtension>
+<targetTypeExtension>
+ <id>lcard-dimm</id>
+ <attribute><id>VPD_SWITCHES</id></attribute>
+</targetTypeExtension>
+
</attributes>
diff --git a/src/usr/vpd/HBconfig b/src/usr/vpd/HBconfig
index 76aeb7192..3995b1982 100644
--- a/src/usr/vpd/HBconfig
+++ b/src/usr/vpd/HBconfig
@@ -24,13 +24,11 @@ config CVPD_WRITE_TO_HW
config MVPD_READ_FROM_PNOR
default y
- depends on !MVPD_READ_FROM_HW
help
Read Module VPD data from PNOR cache
config MVPD_READ_FROM_HW
- default y if !MVPD_READ_FROM_PNOR
- depends on !MVPD_READ_FROM_PNOR
+ default n
help
Read Module VPD data from HW resources
@@ -48,13 +46,11 @@ config MVPD_WRITE_TO_HW
config DJVPD_READ_FROM_PNOR
default y
- depends on !DJVPD_READ_FROM_HW
help
Read Dimm JEDEC VPD/SPD data from PNOR cache
config DJVPD_READ_FROM_HW
- default y if !DJVPD_READ_FROM_PNOR
- depends on !DJVPD_READ_FROM_PNOR
+ default n
help
Read Dimm JEDEC VPD/SPD data from HW resources
diff --git a/src/usr/vpd/cvpd.C b/src/usr/vpd/cvpd.C
index 406511fb7..0febca385 100644
--- a/src/usr/vpd/cvpd.C
+++ b/src/usr/vpd/cvpd.C
@@ -105,6 +105,7 @@ namespace CVPD
IpVpdFacade::input_args_t args;
args.record = ((cvpdRecord)va_arg( i_args, uint64_t ));
args.keyword = ((cvpdKeyword)va_arg( i_args, uint64_t ));
+ args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));
TRACSSCOMP( g_trac_vpd,
ENTER_MRK"cvpdRead()" );
@@ -157,6 +158,7 @@ namespace CVPD
IpVpdFacade::input_args_t args;
args.record = ((cvpdRecord)va_arg( i_args, uint64_t ));
args.keyword = ((cvpdKeyword)va_arg( i_args, uint64_t ));
+ args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));
TRACSSCOMP( g_trac_vpd,
ENTER_MRK"cvpdWrite()" );
diff --git a/src/usr/vpd/dimmPres.C b/src/usr/vpd/dimmPres.C
index 32042fe6b..ca8b3f149 100755
--- a/src/usr/vpd/dimmPres.C
+++ b/src/usr/vpd/dimmPres.C
@@ -107,7 +107,8 @@ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
* @moduleid VPD::VPD_SPD_PRESENCE_DETECT
* @userdata1 Buffer Length
* @userdata2 <UNUSED>
- * @devdesc Buffer for checking Presence Detect was not the correct size.
+ * @devdesc Buffer for checking Presence Detect
+ * was not the correct size.
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
VPD::VPD_SPD_PRESENCE_DETECT,
@@ -137,9 +138,17 @@ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
if ( membuf_parent.size() != 1 )
{
present = false;
+
+ // Invalidate the SPD in PNOR
+ err = VPD::invalidatePnorCache(i_target);
+ if (err)
+ {
+ TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" );
+ }
break;
}
#endif
+
present = spdPresent( i_target );
if( present == false )
@@ -153,6 +162,29 @@ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
INFO_MRK"Dimm was found to be present." );
}
+#if defined(CONFIG_DJVPD_READ_FROM_HW) && defined(CONFIG_DJVPD_READ_FROM_PNOR)
+ if( present )
+ {
+ // Check if the VPD data in the PNOR matches the SEEPROM
+ err = VPD::ensureCacheIsInSync( i_target );
+ if( err )
+ {
+ present = false;
+
+ TRACFCOMP(g_trac_spd,ERR_MRK "dimmPresenceDetectt> Error during ensureCacheIsInSync (SPD)" );
+ break;
+ }
+ }
+ else
+ {
+ // SPD is not present, invalidate the SPD in PNOR
+ err = VPD::invalidatePnorCache(i_target);
+ if (err)
+ {
+ TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" );
+ }
+ }
+#endif
// copy present value into output buffer so caller can read it
memcpy( io_buffer, &present, presentSz );
io_buflen = presentSz;
diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C
index ed61de47a..f1ef73053 100644
--- a/src/usr/vpd/ipvpd.C
+++ b/src/usr/vpd/ipvpd.C
@@ -62,7 +62,11 @@ extern trace_desc_t* g_trac_vpd;
// Globals
// ----------------------------------------------
-static const uint64_t IPVPD_TOC_SIZE = 0x100;
+static const uint64_t IPVPD_TOC_SIZE = 0x100; //256
+static const uint64_t IPVPD_TOC_ENTRY_SIZE = 8;
+static const uint64_t IPVPD_TOC_INVALID_DATA = 0xFFFFFFFFFFFFFFFF;
+static const uint32_t IPVPD_MAX_ENTRY_SIZE = (64 * 1024);
+
/**
* @brief Constructor
@@ -112,7 +116,6 @@ errlHndl_t IpVpdFacade::read ( TARGETING::Target * i_target,
do
{
-
// Get the Record/keyword names
err = translateRecord(i_args.record,
recordName);
@@ -138,7 +141,6 @@ errlHndl_t IpVpdFacade::read ( TARGETING::Target * i_target,
recordOffset,
i_target,
i_args );
-
if( err )
{
break;
@@ -261,9 +263,322 @@ errlHndl_t IpVpdFacade::write ( TARGETING::Target * i_target,
}
// ------------------------------------------------------------------
+// IpVpdFacade::cmpPnorToSeeprom
+// ------------------------------------------------------------------
+errlHndl_t IpVpdFacade::cmpPnorToSeeprom ( TARGETING::Target * i_target,
+ VPD::vpdRecord i_record,
+ VPD::vpdKeyword i_keyword,
+ bool &o_match )
+{
+ errlHndl_t l_err = NULL;
+
+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"cmpPnorToSeeprom() " );
+
+ o_match = false;
+
+ input_args_t l_pnorArgs;
+ l_pnorArgs.record = i_record;
+ l_pnorArgs.keyword = i_keyword;
+ l_pnorArgs.location = VPD::PNOR;
+
+ input_args_t l_seepromArgs;
+ l_seepromArgs.record = i_record;
+ l_seepromArgs.keyword = i_keyword;
+ l_seepromArgs.location = VPD::SEEPROM;
+
+ do
+ {
+ // Get the PNOR size
+ size_t l_sizePnor = 0;
+ l_err = read( i_target,
+ NULL,
+ l_sizePnor,
+ l_pnorArgs );
+ if( l_err || (l_sizePnor == 0) )
+ {
+ // PNOR may not be loaded, ignore the error
+ delete l_err;
+ l_err = NULL;
+ break;
+ }
+
+ // Get the PNOR data
+ uint8_t l_dataPnor[l_sizePnor];
+ l_err = read( i_target,
+ l_dataPnor,
+ l_sizePnor,
+ l_pnorArgs );
+ if( l_err )
+ {
+ break;
+ }
+
+ // Get the SEEPROM size
+ size_t l_sizeSeeprom = 0;
+ l_err = read( i_target,
+ NULL,
+ l_sizeSeeprom,
+ l_seepromArgs );
+ if( l_err || (l_sizeSeeprom == 0) )
+ {
+ break;
+ }
+
+ // Get the SEEPROM data
+ uint8_t l_dataSeeprom[l_sizeSeeprom];
+ l_err = read( i_target,
+ l_dataSeeprom,
+ l_sizeSeeprom,
+ l_seepromArgs );
+ if( l_err )
+ {
+ break;
+ }
+
+ // Compare the PNOR/SEEPROM size/data
+ if( l_sizePnor != l_sizeSeeprom )
+ {
+ break;
+ }
+ if( memcmp( l_dataPnor,
+ l_dataSeeprom,
+ l_sizePnor ) != 0 )
+ {
+ break;
+ }
+
+ o_match = true;
+
+ } while(0);
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"cmpPnorToSeeprom()" );
+
+ return l_err;
+}
+
+/* IPVPD PNOR FORMAT
+ |-----------------------------------------------------------|----|
+ |TOC0|TOC1|...........................................|TOC31| |
+ |-----------------------------------------------------------|TARG0
+ |REC1DATA|.........................................|RECNDATA|64K |
+ |-----------------------------------------------------------|----|
+ |TOC0|TOC1|...........................................|TOC31| |
+ |-----------------------------------------------------------|TARG1
+ |REC1DATA|.........................................|RECNDATA|64K |
+ |-----------------------------------------------------------|----|
+ |TOC0|TOC1|...........................................|TOC31| |
+ |-----------------------------------------------------------|TARG2
+ |REC1DATA|.........................................|RECNDATA|64K |
+ |-----------------------------------------------------------|----|
+ ---- Till TARGN
+*/
+
+// ------------------------------------------------------------------
+// IpVpdFacade::loadPnor
+// ------------------------------------------------------------------
+errlHndl_t IpVpdFacade::loadPnor ( TARGETING::Target * i_target )
+{
+ errlHndl_t err = NULL;
+
+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"IpVpdFacade::loadPnor()" );
+
+ // Load PNOR TOC with invalid data
+ err = invalidatePnor( i_target );
+ if( err )
+ {
+ TRACFCOMP(g_trac_vpd,
+ "IpVpdFacade::loadPnor() Error invalidating PNOR Target %.8X",
+ TARGETING::get_huid(i_target));
+ return err;
+ }
+
+ // Temp data for entire VPD entry
+ uint8_t* tmpVpdPtr = new uint8_t[IPVPD_MAX_ENTRY_SIZE];
+
+ // Load the temp data with invalid TOC
+ uint64_t tocdata = IPVPD_TOC_INVALID_DATA;
+ for( uint32_t tocoffset = 0;
+ tocoffset < IPVPD_TOC_SIZE;
+ tocoffset += IPVPD_TOC_ENTRY_SIZE )
+ {
+ memcpy( (tmpVpdPtr + tocoffset),
+ &tocdata,
+ IPVPD_TOC_ENTRY_SIZE );
+ }
+
+ // Load PNOR cache from SEEPROM
+ // Variables starting with p=PNOR, s=SEEPROM
+
+ // Table of contents
+ tocData pTocEntry;
+ uint16_t pTocOffset = 0;
+
+ // Records
+ uint16_t sRecOffset = 0;
+ uint16_t sRecLength = 0;
+ uint16_t pRecOffset = IPVPD_TOC_SIZE; // Records begin after TOC
+ input_args_t sRecArgs;
+ sRecArgs.location = VPD::SEEPROM;
+
+ // Loop through all possible record types
+ for( uint32_t rec = 0; rec < iv_recSize; rec++ )
+ {
+ sRecArgs.record = iv_vpdRecords[rec].record;
+ // Read the record offset from SEEPROM
+ err = findRecordOffsetSeeprom ( iv_vpdRecords[rec].recordName,
+ sRecOffset,
+ sRecLength,
+ i_target,
+ sRecArgs );
+ if( err )
+ {
+ TRACDCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() "
+ "Did not find SEEPROM record %d recordName %s",
+ iv_vpdRecords[rec].record, iv_vpdRecords[rec].recordName);
+ // Not all records will be found, don't log the error
+ // @todo RTC 115944 Need specific list of records to check here
+ delete err;
+ err = NULL;
+ }
+ else
+ {
+ // Copy the record name to the toc structure asciiRec
+ memcpy( pTocEntry.asciiRec,
+ iv_vpdRecords[rec].recordName,
+ RECORD_BYTE_SIZE );
+
+ // Swap the bytes to match SEEPROM VPD format
+ pTocEntry.offset[0] = ((uint8_t*)(&pRecOffset))[1];
+ pTocEntry.offset[1] = ((uint8_t*)(&pRecOffset))[0];
+
+ // Just a signature after every TOC entry
+ pTocEntry.unusedByte[0] = 0x5A;
+ pTocEntry.unusedByte[1] = 0x5A;
+
+ // Write TOC to temp data
+ memcpy( (tmpVpdPtr + pTocOffset),
+ &pTocEntry,
+ IPVPD_TOC_ENTRY_SIZE );
+
+ // Read record data from SEEPROM, put it into temp data
+ uint8_t* pRecPtr = tmpVpdPtr + pRecOffset;
+ err = fetchData( sRecOffset,
+ sRecLength,
+ pRecPtr,
+ i_target,
+ sRecArgs.location );
+ if( err )
+ {
+ TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() "
+ "Error reading record data, record %d recordName %s",
+ iv_vpdRecords[rec].record,
+ iv_vpdRecords[rec].recordName);
+ break;
+ }
+
+ // Increment the PNOR TOC and record offsets
+ pTocOffset += IPVPD_TOC_ENTRY_SIZE;
+ pRecOffset += sRecLength;
+ }
+ }
+
+ if( !err )
+ {
+ // Setup info needed to write PNOR
+ VPD::pnorInformation pInfo;
+ pInfo.segmentSize = iv_vpdSectionSize;
+ pInfo.maxSegments = iv_vpdMaxSections;
+ pInfo.pnorSection = iv_pnorSection;
+
+ // Write the entire PNOR entry
+ err = VPD::writePNOR( 0x0, // start offset
+ pRecOffset, // size
+ tmpVpdPtr, // data
+ i_target,
+ pInfo,
+ iv_cachePnorAddr,
+ &iv_mutex );
+ if( err )
+ {
+ TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() "
+ "Error writing PNOR VPD data");
+ }
+ }
+ else
+ {
+ // Error reading record data, invalidate the TOC
+ // Use different errl so we don't overwrite the original
+ errlHndl_t invErr = NULL;
+ invErr = invalidatePnor( i_target );
+ if( invErr )
+ {
+ TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() "
+ "Error invalidating PNOR Target %.8X",
+ TARGETING::get_huid(i_target));
+ delete invErr;
+ invErr = NULL;
+ }
+ }
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"IpVpdFacade::loadPnor()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// IpVpdFacade::invalidatePnor
+// ------------------------------------------------------------------
+errlHndl_t IpVpdFacade::invalidatePnor ( TARGETING::Target * i_target )
+{
+ errlHndl_t err = NULL;
+
+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"IpVpdFacade::invalidatePnor()" );
+
+ // Setup info needed to write PNOR
+ VPD::pnorInformation pInfo;
+ pInfo.segmentSize = iv_vpdSectionSize;
+ pInfo.maxSegments = iv_vpdMaxSections;
+ pInfo.pnorSection = iv_pnorSection;
+
+ // Temp data for entire TOC
+ uint8_t* tmpTocPtr = new uint8_t[IPVPD_TOC_SIZE];
+
+ // Load the temp data with invalid TOC
+ uint64_t tocdata = IPVPD_TOC_INVALID_DATA;
+ for( uint32_t tocoffset = 0;
+ tocoffset < IPVPD_TOC_SIZE;
+ tocoffset += IPVPD_TOC_ENTRY_SIZE )
+ {
+ memcpy( (tmpTocPtr + tocoffset),
+ &tocdata,
+ IPVPD_TOC_ENTRY_SIZE );
+ }
+
+ // Write the entire PNOR TOC
+ err = VPD::writePNOR( 0x0, // start offset
+ IPVPD_TOC_SIZE, // size
+ tmpTocPtr, // data
+ i_target,
+ pInfo,
+ iv_cachePnorAddr,
+ &iv_mutex );
+ if( err )
+ {
+ TRACFCOMP(g_trac_vpd,
+ "IpVpdFacade::invalidatePnor() Error writing PNOR TOC");
+ return err;
+ }
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"IpVpdFacade::invalidatePnor()" );
+
+ return err;
+}
+
+// ------------------------------------------------------------------
// IpVpdFacade::translateRecord
// ------------------------------------------------------------------
-errlHndl_t IpVpdFacade::translateRecord ( ipVpdRecord i_record,
+errlHndl_t IpVpdFacade::translateRecord ( VPD::vpdRecord i_record,
const char *& o_record )
{
errlHndl_t err = NULL;
@@ -284,8 +599,8 @@ errlHndl_t IpVpdFacade::translateRecord ( ipVpdRecord i_record,
if( ( entry == &iv_vpdRecords[iv_recSize] )||
( i_record != entry->record ) )
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::translateRecord: No matching Record (0x%04x) found!",
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::translateRecord: "
+ "No matching Record (0x%04x) found!",
i_record );
/*@
@@ -324,7 +639,7 @@ errlHndl_t IpVpdFacade::translateRecord ( ipVpdRecord i_record,
// ------------------------------------------------------------------
// IpVpdFacade::translateKeyword
// ------------------------------------------------------------------
-errlHndl_t IpVpdFacade::translateKeyword ( ipVpdKeyword i_keyword,
+errlHndl_t IpVpdFacade::translateKeyword ( VPD::vpdKeyword i_keyword,
const char *& o_keyword )
{
errlHndl_t err = NULL;
@@ -345,8 +660,8 @@ errlHndl_t IpVpdFacade::translateKeyword ( ipVpdKeyword i_keyword,
if( ( entry == &iv_vpdKeywords[iv_keySize] ) ||
( i_keyword != entry->keyword ) )
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::translateKeyword: No matching Keyword found!" );
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::translateKeyword: "
+ "No matching Keyword found!" );
/*@
* @errortype
@@ -386,6 +701,7 @@ errlHndl_t IpVpdFacade::translateKeyword ( ipVpdKeyword i_keyword,
return err;
}
+
// ------------------------------------------------------------------
// IpVpdFacade::findRecordOffset
// ------------------------------------------------------------------
@@ -396,38 +712,64 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record,
{
errlHndl_t err = NULL;
- if ( iv_configInfo.vpdReadPNOR )
+ // Determine the VPD source (PNOR/SEEPROM)
+ VPD::vpdCmdTarget vpdSource = VPD::AUTOSELECT;
+ bool configError = false;
+ configError = VPD::resolveVpdSource( i_target,
+ iv_configInfo.vpdReadPNOR,
+ iv_configInfo.vpdReadHW,
+ i_args.location,
+ vpdSource );
+ // Get the record offset
+ if ( vpdSource == VPD::PNOR )
{
- return findRecordOffsetPnor(i_record, o_offset, i_target, i_args);
+ err = findRecordOffsetPnor(i_record, o_offset, i_target, i_args);
}
- else if ( iv_configInfo.vpdReadHW )
+ else if ( vpdSource == VPD::SEEPROM )
{
- return findRecordOffsetSeeprom(i_record, o_offset, i_target, i_args);
+ uint16_t o_length;
+ err = findRecordOffsetSeeprom(i_record,
+ o_offset,
+ o_length,
+ i_target,
+ i_args);
}
else
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::findRecordOffset:vpdReadPNOR and vpdReadHW false!");
+ configError = true;
+ }
+
+ if( configError )
+ {
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::findRecordOffset: "
+ "Error resolving VPD source (PNOR/SEEPROM)");
/*@
* @errortype
- * @reasoncode VPD::VPD_READ_CONFIG_NOT_SET
+ * @reasoncode VPD::VPD_READ_SOURCE_UNRESOLVED
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid VPD::VPD_IPVPD_FIND_RECORD_OFFSET
- * @userdata1 Target HUID
- * @userdata2 <UNUSED>
- * @devdesc Both VPD read PNOR and VPD read HW
- * configs are set to false
+ * @userdata1[0:31] Target HUID
+ * @userdata1[32:63] Requested VPD Source Location
+ * @userdata2[0:31] CONFIG_<vpd>_READ_FROM_PNOR
+ * @userdata2[32:63] CONFIG_<vpd>_READ_FROM_HW
+ * @devdesc Unable to resolve the VPD
+ * source (PNOR or SEEPROM)
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
VPD::VPD_IPVPD_FIND_RECORD_OFFSET,
- VPD::VPD_READ_CONFIG_NOT_SET,
- TARGETING::get_huid(i_target),
- 0x0,
+ VPD::VPD_READ_SOURCE_UNRESOLVED,
+ TWO_UINT32_TO_UINT64(
+ TARGETING::get_huid(i_target),
+ i_args.location ),
+ TWO_UINT32_TO_UINT64(
+ iv_configInfo.vpdReadPNOR,
+ iv_configInfo.vpdReadHW ),
true /*Add HB SW Callout*/ );
err->collectTrace( "VPD", 256 );
}
- return NULL;
+
+ return err;
}
@@ -436,8 +778,8 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record,
// IpVpdFacade::hasVpdPresent
// ------------------------------------------------------------------
bool IpVpdFacade::hasVpdPresent( TARGETING::Target * i_target,
- uint64_t i_record,
- uint64_t i_keyword )
+ VPD::vpdRecord i_record,
+ VPD::vpdRecord i_keyword )
{
errlHndl_t err = NULL;
uint16_t recordOffset = 0x0;
@@ -510,39 +852,41 @@ bool IpVpdFacade::recordPresent( const char * i_record,
// 8 bytes per entry - 32 entries possible
// Entry:
// byte 0 - 3: ASCII Record Name
- // byte 4 - 5: Size (byte swapped)
+ // byte 4 - 5: OFFSET (byte swapped)
// byte 6 - 7: UNUSED
// --------------------------------------
while( ( tmpOffset < IPVPD_TOC_SIZE ) &&
!matchFound )
{
- //Read Record Name
- err = fetchData( tmpOffset,
- RECORD_BYTE_SIZE,
- record,
- i_target );
- tmpOffset += RECORD_BYTE_SIZE;
+ //Read Record Name
+ err = fetchData( tmpOffset,
+ RECORD_BYTE_SIZE,
+ record,
+ i_target,
+ VPD::AUTOSELECT );
+ tmpOffset += RECORD_BYTE_SIZE;
+
+ if( err )
+ {
+ break;
+ }
+ if( !(memcmp(record, i_record, RECORD_BYTE_SIZE )) )
+ {
+ matchFound = true;
+
+ // Read the matching record's offset
+ err = fetchData( tmpOffset,
+ RECORD_ADDR_BYTE_SIZE,
+ &o_offset,
+ i_target,
+ VPD::AUTOSELECT );
if( err )
{
break;
}
-
- if( !(memcmp(record, i_record, RECORD_BYTE_SIZE )) )
- {
- matchFound = true;
-
- // Read the matching record's offset
- err = fetchData( tmpOffset,
- RECORD_ADDR_BYTE_SIZE,
- &o_offset,
- i_target );
- if( err )
- {
- break;
- }
- }
- tmpOffset += (RECORD_ADDR_BYTE_SIZE + RECORD_TOC_UNUSED);
+ }
+ tmpOffset += (RECORD_ADDR_BYTE_SIZE + RECORD_TOC_UNUSED);
}
if( err )
@@ -580,9 +924,8 @@ errlHndl_t IpVpdFacade::findRecordOffsetPnor ( const char * i_record,
if( !matchFound )
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::findRecordOffset: No matching\
- Record (%s) found in TOC!",
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::findRecordOffsetPnor: "
+ "No matching Record (%s) found in TOC!",
i_record );
/*@
@@ -622,7 +965,7 @@ errlHndl_t IpVpdFacade::findRecordOffsetPnor ( const char * i_record,
o_offset = le16toh( offset );
TRACSSCOMP( g_trac_vpd,
- EXIT_MRK"IpVpdFacade::findRecordOffset()" );
+ EXIT_MRK"IpVpdFacade::findRecordOffsetPnor()" );
return err;
}
@@ -632,6 +975,7 @@ errlHndl_t IpVpdFacade::findRecordOffsetPnor ( const char * i_record,
// ------------------------------------------------------------------
errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
uint16_t & o_offset,
+ uint16_t & o_length,
TARGETING::Target * i_target,
input_args_t i_args )
{
@@ -658,8 +1002,8 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
(memcmp(toc_rec->record_name, "VTOC",
sizeof(toc_rec->record_name)) != 0))
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::findRecordOffset: VHDR is invalid!");
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::findRecordOffsetSeeprom: "
+ "VHDR is invalid!");
/*@
* @errortype
@@ -670,11 +1014,12 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
* @userdata2 Target HUID
* @devdesc The VHDR was invalid
*/
- err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM,
- VPD::VPD_RECORD_INVALID_VHDR,
- pt_len,
- TARGETING::get_huid(i_target) );
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM,
+ VPD::VPD_RECORD_INVALID_VHDR,
+ pt_len,
+ TARGETING::get_huid(i_target) );
// Could be the VPD of the target wasn't set up properly
// -- DECONFIG so that we can possibly keep booting
@@ -718,6 +1063,7 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
{
// Byte swap field on output, skip 'large resource' byte
o_offset = le16toh( toc_rec->record_offset ) + 1;
+ o_length = le16toh( toc_rec->record_length );
found = true;
break;
}
@@ -739,13 +1085,14 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
* @userdata2 Target HUID
* @devdesc The requested record was not found in the VPD VTOC.
*/
- err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM,
- VPD::VPD_RECORD_NOT_FOUND,
- TWO_UINT32_TO_UINT64(i_args.record,
- i_args.keyword),
- TARGETING::get_huid(i_target) );
-
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM,
+ VPD::VPD_RECORD_NOT_FOUND,
+ TWO_UINT32_TO_UINT64(i_args.record,
+ i_args.keyword),
+ TARGETING::get_huid(i_target) );
+
// Could be the VPD of the target wasn't set up properly
// -- DECONFIG so that we can possibly keep booting
err->addHwCallout( i_target,
@@ -822,7 +1169,8 @@ errlHndl_t IpVpdFacade::retrieveKeyword ( const char * i_keywordName,
err = fetchData( i_offset+byteAddr,
keywordSize,
io_buffer,
- i_target );
+ i_target,
+ i_args.location );
if( err )
{
break;
@@ -845,42 +1193,65 @@ errlHndl_t IpVpdFacade::retrieveKeyword ( const char * i_keywordName,
errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr,
size_t i_numBytes,
void * o_data,
- TARGETING::Target * i_target )
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
- if ( iv_configInfo.vpdReadPNOR )
+ // Determine the VPD source (PNOR/SEEPROM)
+ VPD::vpdCmdTarget vpdSource = VPD::AUTOSELECT;
+ bool configError = false;
+ configError = VPD::resolveVpdSource( i_target,
+ iv_configInfo.vpdReadPNOR,
+ iv_configInfo.vpdReadHW,
+ i_location,
+ vpdSource );
+
+ // Get the data
+ if ( vpdSource == VPD::PNOR )
{
- return fetchDataFromPnor( i_byteAddr, i_numBytes, o_data, i_target );
+ err = fetchDataFromPnor( i_byteAddr, i_numBytes, o_data, i_target );
}
- else if ( iv_configInfo.vpdReadHW )
+ else if ( vpdSource == VPD::SEEPROM )
{
- return fetchDataFromEeprom( i_byteAddr, i_numBytes, o_data, i_target );
+ err = fetchDataFromEeprom( i_byteAddr, i_numBytes, o_data, i_target );
}
else
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::fetchData:vpdReadPNOR and vpdReadHW false!");
+ configError = true;
+ }
+
+ if( configError )
+ {
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::fetchData: "
+ "Error resolving VPD source (PNOR/SEEPROM)");
/*@
* @errortype
- * @reasoncode VPD::VPD_READ_CONFIG_NOT_SET
+ * @reasoncode VPD::VPD_READ_SOURCE_UNRESOLVED
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid VPD::VPD_IPVPD_FETCH_DATA
- * @userdata1 Target HUID
- * @userdata2 <UNUSED>
- * @devdesc Both VPD read PNOR and VPD read HW
- * configs are set to false
+ * @userdata1[0:31] Target HUID
+ * @userdata1[32:63] Requested VPD Source Location
+ * @userdata2[0:31] CONFIG_<vpd>_READ_FROM_PNOR
+ * @userdata2[32:63] CONFIG_<vpd>_READ_FROM_HW
+ * @devdesc Unable to resolve the VPD
+ * source (PNOR or SEEPROM)
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
VPD::VPD_IPVPD_FETCH_DATA,
- VPD::VPD_READ_CONFIG_NOT_SET,
- TARGETING::get_huid(i_target),
- 0x0,
+ VPD::VPD_READ_SOURCE_UNRESOLVED,
+ TWO_UINT32_TO_UINT64(
+ TARGETING::get_huid(i_target),
+ i_location ),
+ TWO_UINT32_TO_UINT64(
+ iv_configInfo.vpdReadPNOR,
+ iv_configInfo.vpdReadHW ),
true /*Add HB SW Callout*/ );
err->collectTrace( "VPD", 256 );
}
- return NULL;
+
+ return err;
}
// ------------------------------------------------------------------
@@ -892,10 +1263,8 @@ errlHndl_t IpVpdFacade::fetchDataFromPnor ( uint64_t i_byteAddr,
TARGETING::Target * i_target )
{
errlHndl_t err = NULL;
-
TRACSSCOMP( g_trac_vpd,
ENTER_MRK"IpVpdFacade::fetchDataFromPnor()" );
-
do
{
// Call a function in the common VPD code
@@ -932,7 +1301,6 @@ errlHndl_t IpVpdFacade::fetchDataFromEeprom ( uint64_t i_byteAddr,
TARGETING::Target * i_target )
{
errlHndl_t err = NULL;
-
TRACSSCOMP( g_trac_vpd,
ENTER_MRK"IpVpdFacade::fetchDataFromEeprom()" );
@@ -987,9 +1355,9 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
err = fetchData( offset,
RECORD_ADDR_BYTE_SIZE,
&recordSize,
- i_target );
+ i_target,
+ i_args.location );
offset += RECORD_ADDR_BYTE_SIZE;
-
if( err )
{
break;
@@ -1004,7 +1372,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
err = fetchData( offset,
RECORD_BYTE_SIZE,
record,
- i_target );
+ i_target,
+ i_args.location );
offset += RECORD_BYTE_SIZE;
if( err )
@@ -1014,8 +1383,9 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
if( memcmp( record, i_recordName, RECORD_BYTE_SIZE ) )
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::findKeywordAddr: Record(%s) for offset (0x%04x) did not match expected record(%s)!",
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::findKeywordAddr: "
+ "Record(%s) for offset (0x%04x) did not match "
+ "expected record(%s)!",
record,
i_offset,
i_recordName );
@@ -1062,15 +1432,16 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
// 2 bytes for the size value.
while( ( offset < (recordSize + i_offset + RECORD_ADDR_BYTE_SIZE) ) )
{
- TRACDCOMP( g_trac_vpd,
- INFO_MRK"IpVpdFacade::findKeywordAddr: Looking for keyword, reading offset: 0x%04x",
+ TRACDCOMP( g_trac_vpd, INFO_MRK"IpVpdFacade::findKeywordAddr: "
+ "Looking for keyword, reading offset: 0x%04x",
offset );
// read keyword name (2 bytes)
err = fetchData( offset,
KEYWORD_BYTE_SIZE,
keyword,
- i_target );
+ i_target,
+ i_args.location );
offset += KEYWORD_BYTE_SIZE;
if( err )
@@ -1078,8 +1449,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
break;
}
- TRACDCOMP( g_trac_vpd,
- INFO_MRK"IpVpdFacade::findKeywordAddr: Read keyword name: %s",
+ TRACDCOMP( g_trac_vpd, INFO_MRK"IpVpdFacade::findKeywordAddr: "
+ "Read keyword name: %s",
keyword );
// Check if we're reading a '#' keyword. They have a 2 byte size
@@ -1087,8 +1458,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
bool isPoundKwd = false;
if( !(memcmp( keyword, "#", 1 )) )
{
- TRACDCOMP( g_trac_vpd,
- INFO_MRK"IpVpdFacade::findKeywordAddr: Reading # keyword, adding 1 byte to size to read!" );
+ TRACDCOMP( g_trac_vpd, INFO_MRK"IpVpdFacade::findKeywordAddr: "
+ "Reading # keyword, adding 1 byte to size to read!");
isPoundKwd = true;
keywordLength++;
}
@@ -1097,7 +1468,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
err = fetchData( offset,
keywordLength,
&keywordSize,
- i_target );
+ i_target,
+ i_args.location );
offset += keywordLength;
if( err )
@@ -1115,8 +1487,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
keywordSize = keywordSize >> 8;
}
- TRACDCOMP( g_trac_vpd,
- INFO_MRK"IpVpdFacade::findKeywordAddr: Read keyword size: 0x%04x",
+ TRACDCOMP( g_trac_vpd, INFO_MRK"IpVpdFacade::findKeywordAddr: "
+ "Read keyword size: 0x%04x",
keywordSize );
// if keyword equal i_keywordName
@@ -1131,6 +1503,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
if ( matchesFound == i_index + 1 ) {
break;
}
+ // set offset to next keyword (based on current keyword size)
+ offset += keywordSize;
}
else
{
@@ -1150,8 +1524,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
if( matchesFound != i_index + 1 &&
NULL == err )
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::findKeywordAddr: No matching %s keyword found within %s record!",
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::findKeywordAddr: "
+ "No matching %s keyword found within %s record!",
i_keywordName,
i_recordName );
@@ -1317,8 +1691,8 @@ errlHndl_t IpVpdFacade::checkBufferSize( size_t i_bufferSize,
if( !(i_bufferSize >= i_expectedSize) )
{
- TRACFCOMP( g_trac_vpd,
- ERR_MRK"IpVpdFacade::checkBufferSize: Buffer size (%d) is not larger than expected size (%d)",
+ TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::checkBufferSize: "
+ "Buffer size (%d) is not larger than expected size (%d)",
i_bufferSize,
i_expectedSize );
diff --git a/src/usr/vpd/ipvpd.H b/src/usr/vpd/ipvpd.H
index d59e84608..7b01f86a4 100644
--- a/src/usr/vpd/ipvpd.H
+++ b/src/usr/vpd/ipvpd.H
@@ -37,7 +37,7 @@
/**
* @brief Base class for i/p-Series VPD
- *
+ *
*/
class IpVpdFacade
{
@@ -59,7 +59,7 @@ class IpVpdFacade
};
/**
- * @brief Structure representing the format of each record
+ * @brief Structure representing the format of each record
* in the PT keyword of the VTOC or VHDR.
*/
struct TocPtRecord {
@@ -73,21 +73,13 @@ class IpVpdFacade
} PACKED;
/**
- * @brief typdef for ipVpdRecord values
- */
- typedef uint32_t ipVpdRecord;
- /**
- * @brief typdef for ipVpdKeyword values
- */
- typedef uint32_t ipVpdKeyword;
-
- /**
* @brief Structure for all VPD dd input parameter arguments
*/
typedef struct
{
- ipVpdRecord record;
- ipVpdKeyword keyword;
+ VPD::vpdRecord record;
+ VPD::vpdKeyword keyword;
+ VPD::vpdCmdTarget location;
} input_args_t;
/**
@@ -96,7 +88,7 @@ class IpVpdFacade
*/
typedef struct
{
- ipVpdRecord record;
+ VPD::vpdRecord record;
char recordName[RECORD_BYTE_SIZE+1];
} recordInfo;
@@ -104,7 +96,7 @@ class IpVpdFacade
*/
typedef struct
{
- ipVpdKeyword keyword;
+ VPD::vpdKeyword keyword;
char keywordName[KEYWORD_BYTE_SIZE+1];
} keywordInfo;
@@ -120,6 +112,23 @@ class IpVpdFacade
} configInfo;
/**
+ * @brief - Data Struct for TOC Entry
+ */
+ struct tocData
+ {
+ tocData()
+ {
+ bzero(asciiRec, sizeof(asciiRec));
+ bzero(offset, sizeof(offset));
+ bzero(unusedByte, sizeof(unusedByte));
+ }
+
+ uint8_t asciiRec[RECORD_BYTE_SIZE];
+ uint8_t offset[RECORD_ADDR_BYTE_SIZE];
+ uint8_t unusedByte[RECORD_ADDR_BYTE_SIZE];
+ };
+
+ /**
* @brief Constructor
*
* @param[in] i_vpdSectionSize - Space allocated in PNOR for each
@@ -219,9 +228,51 @@ class IpVpdFacade
* @return - bool - true if vpd is present, false if it is not.
*/
bool hasVpdPresent ( TARGETING::Target * i_target,
- uint64_t record,
- uint64_t keyword );
+ VPD::vpdRecord record,
+ VPD::vpdKeyword keyword );
+ /**
+ * @brief This function compares the specified record/keyword
+ * in PNOR/SEEPROM and returns the result. A mismatch
+ * will not return an error.
+ *
+ * @param[in] i_target - Target device
+ *
+ * @param[in] i_record - Record to compare
+ *
+ * @param[in] i_keyword - Keyword to compare
+ *
+ * @param[out] o_match - Result of compare
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+ errlHndl_t cmpPnorToSeeprom ( TARGETING::Target * i_target,
+ VPD::vpdRecord i_record,
+ VPD::vpdKeyword i_keyword,
+ bool &o_match );
+
+ /**
+ * @brief This function will perform the steps required to load the
+ * MVPD data from SEEPROM into the PNOR cache.
+ *
+ * @param[in] i_target - Target device
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+ errlHndl_t loadPnor ( TARGETING::Target * i_target );
+
+ /**
+ * @brief This function will perform the steps required to invalidate
+ * the MVPD in the PNOR cache.
+ *
+ * @param[in] i_target - Target device
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+ errlHndl_t invalidatePnor ( TARGETING::Target * i_target );
protected:
@@ -237,7 +288,7 @@ class IpVpdFacade
* @return errHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
- errlHndl_t translateRecord ( ipVpdRecord i_record,
+ errlHndl_t translateRecord ( VPD::vpdRecord i_record,
const char *& o_record );
/**
@@ -252,7 +303,7 @@ class IpVpdFacade
* @return errHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
- errlHndl_t translateKeyword ( ipVpdKeyword i_keyword,
+ errlHndl_t translateKeyword ( VPD::vpdKeyword i_keyword,
const char *& o_keyword );
/**
@@ -322,6 +373,8 @@ class IpVpdFacade
*
* @param[out] o_offset - The offset where the record is located.
*
+ * @param[out] o_length - The length of the record.
+ *
* @param[in] i_target - The target to retrieve the data for.
*
* @param[in] i_args - The input arguments.
@@ -331,6 +384,7 @@ class IpVpdFacade
*/
errlHndl_t findRecordOffsetSeeprom ( const char * i_record,
uint16_t & o_offset,
+ uint16_t & o_length,
TARGETING::Target * i_target,
input_args_t i_args );
@@ -385,7 +439,7 @@ class IpVpdFacade
*
* @param[in] i_buflen - Length of the buffer to be written
* to the target's VPD area. This value should indicate the
- * size of the io_buffer parameter that has been allocated.
+ * size of the io_buffer parameter that has been allocated.
*
* @param[in] i_args - The input arguments.
*
@@ -433,7 +487,7 @@ class IpVpdFacade
size_t& o_keywordSize,
uint64_t& o_byteAddr,
input_args_t i_args );
-
+
/**
* @brief This function calls the PNOR or EEPROM version of
* the fetchData function based on the configInfo
@@ -446,13 +500,16 @@ class IpVpdFacade
*
* @param[in] i_target - Target device.
*
+ * @param[in] i_location - VPD location to fetch data from (PNOR/SEEPROM)
+ *
* @return errHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
errlHndl_t fetchData ( uint64_t i_byteAddr,
size_t i_numBytes,
void * o_data,
- TARGETING::Target * i_target );
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location );
/**
* @brief This function actually reads the data from PNOR
@@ -504,7 +561,7 @@ class IpVpdFacade
* @return bool - Whether or not the e2 value is larger than the e1 value.
*/
static bool compareKeywords ( const keywordInfo e1,
- const keywordInfo e2 );
+ const keywordInfo e2 );
/**
* @brief This function compares 2 vpd keyword values. Used for binary
@@ -517,7 +574,7 @@ class IpVpdFacade
* @return bool - Whether or not the e2 value is larger than the e1 value.
*/
static bool compareRecords ( const recordInfo e1,
- const recordInfo e2 );
+ const recordInfo e2 );
/**
* @brief This function compares sizes to be sure buffers are large enough
@@ -554,25 +611,25 @@ class IpVpdFacade
/**
* @brief Pointer to array of VPD Record information
- *
+ *
*/
const recordInfo* iv_vpdRecords;
/**
* @brief Number of VPD Records for current chip
- *
+ *
*/
uint64_t iv_recSize;
/**
* @brief Pointer to array of VPD Keyword information
- *
+ *
*/
const keywordInfo* iv_vpdKeywords;
/**
* @brief Number of VPD Keywords for current chip
- *
+ *
*/
uint64_t iv_keySize;
@@ -605,6 +662,7 @@ class IpVpdFacade
* VPD data
*/
configInfo iv_configInfo;
+
};
diff --git a/src/usr/vpd/mvpd.C b/src/usr/vpd/mvpd.C
index 6498e2561..9c3d6119f 100644
--- a/src/usr/vpd/mvpd.C
+++ b/src/usr/vpd/mvpd.C
@@ -103,6 +103,7 @@ namespace MVPD
IpVpdFacade::input_args_t args;
args.record = ((mvpdRecord)va_arg( i_args, uint64_t ));
args.keyword = ((mvpdKeyword)va_arg( i_args, uint64_t ));
+ args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));
TRACSSCOMP( g_trac_vpd,
ENTER_MRK"mvpdRead()" );
@@ -156,6 +157,7 @@ namespace MVPD
IpVpdFacade::input_args_t args;
args.record = ((mvpdRecord)va_arg( i_args, uint64_t ));
args.keyword = ((mvpdKeyword)va_arg( i_args, uint64_t ));
+ args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));
TRACSSCOMP( g_trac_vpd,
ENTER_MRK"mvpdWrite()" );
@@ -253,3 +255,4 @@ IpVpdFacade(MVPD::SECTION_SIZE,
iv_configInfo.vpdWriteHW = false;
#endif
}
+
diff --git a/src/usr/vpd/mvpd.H b/src/usr/vpd/mvpd.H
index b1b168cc6..591a2a250 100644
--- a/src/usr/vpd/mvpd.H
+++ b/src/usr/vpd/mvpd.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -159,4 +161,3 @@ class MvpdFacade: public IpVpdFacade
};
#endif /* _MVPD_H */
-
diff --git a/src/usr/vpd/runtime/rt_vpd.C b/src/usr/vpd/runtime/rt_vpd.C
index 23faab34f..d907aee2e 100644
--- a/src/usr/vpd/runtime/rt_vpd.C
+++ b/src/usr/vpd/runtime/rt_vpd.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -331,4 +333,73 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes,
return err;
}
+// ------------------------------------------------------------------
+// resolveVpdSource
+// ------------------------------------------------------------------
+bool resolveVpdSource( TARGETING::Target * i_target,
+ bool i_readFromPnorEnabled,
+ bool i_readFromHwEnabled,
+ vpdCmdTarget i_vpdCmdTarget,
+ vpdCmdTarget& o_vpdSource )
+{
+ bool badConfig = false;
+ o_vpdSource = VPD::INVALID_LOCATION;
+
+ if( i_vpdCmdTarget == VPD::PNOR )
+ {
+ if( i_readFromPnorEnabled )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else
+ {
+ badConfig = true;
+ }
+ }
+ else if( i_vpdCmdTarget == VPD::SEEPROM )
+ {
+ if( i_readFromHwEnabled )
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ else
+ {
+ badConfig = true;
+ }
+ }
+ else
+ {
+ if( i_readFromPnorEnabled &&
+ i_readFromHwEnabled )
+ {
+ // PNOR needs to be loaded before we can use it
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ if( vpdSwitches.pnorLoaded )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ }
+ else if( i_readFromPnorEnabled )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else if( i_readFromHwEnabled )
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ else
+ {
+ badConfig = true;
+ }
+ }
+
+ return badConfig;
+}
+
+
}; // end namepsace VPD
diff --git a/src/usr/vpd/spd.C b/src/usr/vpd/spd.C
index 4480b507c..18d4ed3ad 100755..100644
--- a/src/usr/vpd/spd.C
+++ b/src/usr/vpd/spd.C
@@ -112,11 +112,14 @@ bool compareEntries ( const KeywordData e1,
*
* @param[in] i_target - The target to read data from.
*
+ * @param[in] i_location - The SPD source (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer
* to the error log.
*/
errlHndl_t getMemType ( uint8_t & o_memType,
- TARGETING::Target * i_target );
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location );
/**
* @brief This function will read the DIMM module type.
@@ -127,12 +130,15 @@ errlHndl_t getMemType ( uint8_t & o_memType,
*
* @param[in] i_memType - The memory type
*
+ * @param[in] i_location - The SPD source (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer
* to the error log.
*/
errlHndl_t getModType ( modSpecTypes_t & o_memType,
TARGETING::Target * i_target,
- uint64_t i_memType );
+ uint64_t i_memType,
+ VPD::vpdCmdTarget i_location );
/**
* @brief This function will scan the table and return the entry
@@ -149,7 +155,7 @@ errlHndl_t getModType ( modSpecTypes_t & o_memType,
* @return errlHndl_t - NULL if successful, otherwise a pointer to
* the error log.
*/
-errlHndl_t getKeywordEntry ( uint64_t i_keyword,
+errlHndl_t getKeywordEntry ( VPD::vpdKeyword i_keyword,
uint64_t i_memType,
TARGETING::Target * i_target,
const KeywordData *& o_entry );
@@ -176,7 +182,8 @@ errlHndl_t spdGetKeywordValue ( DeviceFW::OperationType i_opType,
va_list i_args )
{
errlHndl_t err = NULL;
- uint64_t keyword = va_arg( i_args, uint64_t );
+ VPD::vpdKeyword keyword = va_arg( i_args, uint64_t );
+ VPD::vpdCmdTarget location = (VPD::vpdCmdTarget)va_arg( i_args, uint64_t );
TRACSSCOMP( g_trac_spd,
ENTER_MRK"spdGetKeywordValue(), io_buflen: %d, keyword: 0x%04x",
@@ -187,7 +194,8 @@ errlHndl_t spdGetKeywordValue ( DeviceFW::OperationType i_opType,
// Read the Basic Memory Type
uint8_t memType = 0x0;
err = getMemType( memType,
- i_target );
+ i_target,
+ location );
if( err )
{
@@ -214,7 +222,8 @@ errlHndl_t spdGetKeywordValue ( DeviceFW::OperationType i_opType,
io_buffer,
io_buflen,
i_target,
- memType );
+ memType,
+ location );
if( err )
{
@@ -289,7 +298,9 @@ errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType,
va_list i_args )
{
errlHndl_t err = NULL;
- uint64_t keyword = va_arg( i_args, uint64_t );
+ VPD::vpdKeyword keyword = va_arg( i_args, uint64_t );
+ VPD::vpdCmdTarget location =
+ (VPD::vpdCmdTarget)va_arg( i_args, uint64_t );
TRACSSCOMP( g_trac_spd,
ENTER_MRK"spdWriteKeywordValue()" );
@@ -299,7 +310,8 @@ errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType,
// Get memory type
uint8_t memType = 0x0;
err = getMemType( memType,
- i_target );
+ i_target,
+ location );
if( err )
{
@@ -313,7 +325,8 @@ errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType,
io_buffer,
io_buflen,
i_target,
- memType );
+ memType,
+ location );
if( err )
{
@@ -384,7 +397,8 @@ errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType,
errlHndl_t spdFetchData ( uint64_t i_byteAddr,
size_t i_numBytes,
void * o_data,
- TARGETING::Target * i_target )
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
@@ -393,18 +407,35 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr,
do
{
- if( likely( g_usePNOR ) )
+ if( unlikely( !g_usePNOR ) )
{
+ err = spdReadBinaryFile( i_byteAddr,
+ i_numBytes,
+ o_data );
+ break;
+ }
+
+ bool readFromPnorEnabled = false;
+#ifdef CONFIG_DJVPD_READ_FROM_PNOR
+ readFromPnorEnabled = true;
+#endif
+ bool readFromHwEnabled = false;
#ifdef CONFIG_DJVPD_READ_FROM_HW
- // Need to read directly from target's EEPROM.
- err = DeviceFW::deviceOp( DeviceFW::READ,
- i_target,
- o_data,
- i_numBytes,
- DEVICE_EEPROM_ADDRESS(
- EEPROM::VPD_PRIMARY,
- i_byteAddr ) );
-#elif CONFIG_DJVPD_READ_FROM_PNOR
+ readFromHwEnabled = true;
+#endif
+
+ // Determine the SPD source (PNOR/SEEPROM)
+ VPD::vpdCmdTarget vpdSource = VPD::AUTOSELECT;
+ bool configError = false;
+ configError = VPD::resolveVpdSource( i_target,
+ readFromPnorEnabled,
+ readFromHwEnabled,
+ i_location,
+ vpdSource );
+
+ // Get the data
+ if ( vpdSource == VPD::PNOR )
+ {
// Setup info needed to read from PNOR
VPD::pnorInformation info;
info.segmentSize = DIMM_SPD_SECTION_SIZE;
@@ -417,23 +448,61 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr,
info,
g_spdPnorAddr,
&g_spdMutex );
-#endif // CONFIG_DJVPD_READ_FROM_PNOR
if( err )
{
break;
}
}
- else
+ else if ( vpdSource == VPD::SEEPROM )
{
- err = spdReadBinaryFile( i_byteAddr,
- i_numBytes,
- o_data );
-
+ // Need to read directly from target's EEPROM.
+ err = DeviceFW::deviceOp( DeviceFW::READ,
+ i_target,
+ o_data,
+ i_numBytes,
+ DEVICE_EEPROM_ADDRESS(
+ EEPROM::VPD_PRIMARY,
+ i_byteAddr ) );
if( err )
{
break;
}
}
+ else
+ {
+ configError = true;
+ }
+
+ if( configError )
+ {
+ TRACFCOMP( g_trac_spd, ERR_MRK"spdFetchData: "
+ "Error resolving VPD source (PNOR/SEEPROM)");
+
+ /*@
+ * @errortype
+ * @reasoncode VPD::VPD_READ_SOURCE_UNRESOLVED
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid VPD::VPD_SPD_FETCH_DATA
+ * @userdata1[0:31] Target HUID
+ * @userdata1[32:63] Requested VPD Source Location
+ * @userdata2[0:31] CONFIG_DJVPD_READ_FROM_PNOR
+ * @userdata2[32:63] CONFIG_DJVPD_READ_FROM_HW
+ * @devdesc Unable to resolve the VPD
+ * source (PNOR or SEEPROM)
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD::VPD_SPD_FETCH_DATA,
+ VPD::VPD_READ_SOURCE_UNRESOLVED,
+ TWO_UINT32_TO_UINT64( TARGETING::get_huid(i_target),
+ i_location ),
+ TWO_UINT32_TO_UINT64( readFromHwEnabled,
+ readFromHwEnabled ),
+ true /*Add HB SW Callout*/ );
+ err->collectTrace( "VPD", 256 );
+ break;
+ }
+
} while( 0 );
TRACSSCOMP( g_trac_spd,
@@ -449,7 +518,8 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr,
errlHndl_t spdWriteData ( uint64_t i_offset,
size_t i_numBytes,
void * i_data,
- TARGETING::Target * i_target )
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
@@ -480,8 +550,8 @@ errlHndl_t spdWriteData ( uint64_t i_offset,
}
else
{
- TRACFCOMP( g_trac_spd,
- ERR_MRK"There is no way to write SPD when not using PNOR!" );
+ TRACFCOMP( g_trac_spd, ERR_MRK"spdWriteData: "
+ "There is no way to write SPD when not using PNOR!" );
/*@
* @errortype
@@ -518,11 +588,12 @@ errlHndl_t spdWriteData ( uint64_t i_offset,
// ------------------------------------------------------------------
// spdGetValue
// ------------------------------------------------------------------
-errlHndl_t spdGetValue ( uint64_t i_keyword,
+errlHndl_t spdGetValue ( VPD::vpdKeyword i_keyword,
void * io_buffer,
size_t & io_buflen,
TARGETING::Target * i_target,
- uint64_t i_DDRRev )
+ uint64_t i_DDRRev,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer);
@@ -579,7 +650,8 @@ errlHndl_t spdGetValue ( uint64_t i_keyword,
// correct values are in place to actually request it
err = checkModSpecificKeyword( (*entry),
i_DDRRev,
- i_target );
+ i_target,
+ i_location );
if( err )
{
@@ -603,7 +675,8 @@ errlHndl_t spdGetValue ( uint64_t i_keyword,
err = spdSpecialCases( (*entry),
io_buffer,
i_target,
- i_DDRRev );
+ i_DDRRev,
+ i_location );
if (err)
{
@@ -616,7 +689,8 @@ errlHndl_t spdGetValue ( uint64_t i_keyword,
err = spdFetchData( (*entry).offset,
(*entry).length,
tmpBuffer,
- i_target );
+ i_target,
+ i_location );
if( err )
{
@@ -653,11 +727,12 @@ errlHndl_t spdGetValue ( uint64_t i_keyword,
// ------------------------------------------------------------------
// spdWriteValue
// ------------------------------------------------------------------
-errlHndl_t spdWriteValue ( uint64_t i_keyword,
+errlHndl_t spdWriteValue ( VPD::vpdKeyword i_keyword,
void * io_buffer,
size_t & io_buflen,
TARGETING::Target * i_target,
- uint64_t i_DDRRev )
+ uint64_t i_DDRRev,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
@@ -758,8 +833,9 @@ errlHndl_t spdWriteValue ( uint64_t i_keyword,
if( entry->bitMask )
{
// Error if not writable
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Trying to write keyword (0x%04x) that is not a full byte size",
+ TRACFCOMP( g_trac_spd, ERR_MRK"spdWriteValue: "
+ "Trying to write keyword (0x%04x) that is not "
+ "a full byte size",
i_keyword );
/*@
@@ -795,7 +871,8 @@ errlHndl_t spdWriteValue ( uint64_t i_keyword,
err = spdWriteData( entry->offset,
io_buflen,
io_buffer,
- i_target );
+ i_target,
+ i_location );
if( err )
{
@@ -833,7 +910,7 @@ bool spdPresent ( TARGETING::Target * i_target )
{
errlHndl_t err = NULL;
bool pres = false;
-
+
TRACSSCOMP( g_trac_spd,
ENTER_MRK"spdPresent()" );
@@ -842,7 +919,8 @@ bool spdPresent ( TARGETING::Target * i_target )
// Read the Basic Memory Type
uint8_t memType = 0x0;
err = getMemType( memType,
- i_target );
+ i_target,
+ VPD::AUTOSELECT );
if( err )
{
@@ -861,7 +939,7 @@ bool spdPresent ( TARGETING::Target * i_target )
pres = true;
}
} while( 0 );
-
+
return pres;
}
@@ -872,7 +950,8 @@ bool spdPresent ( TARGETING::Target * i_target )
// ------------------------------------------------------------------
errlHndl_t ddr3SpecialCases(const KeywordData & i_kwdData,
void * io_buffer,
- TARGETING::Target * i_target)
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location)
{
errlHndl_t err = NULL;
uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer);
@@ -895,7 +974,8 @@ errlHndl_t ddr3SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( i_kwdData.offset,
1, /* Read 1 byte at a time */
&tmpBuffer[0],
- i_target );
+ i_target,
+ i_location );
if( err ) break;
@@ -910,7 +990,8 @@ errlHndl_t ddr3SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( (i_kwdData.offset - 1),
1, /* Read 1 byte at a time */
&tmpBuffer[1],
- i_target );
+ i_target,
+ i_location );
break;
// ==================================================
@@ -920,7 +1001,8 @@ errlHndl_t ddr3SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( i_kwdData.offset,
1, /* Read 1 byte at a time */
&tmpBuffer[0],
- i_target );
+ i_target,
+ i_location );
if( err ) break;
@@ -935,13 +1017,14 @@ errlHndl_t ddr3SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( (i_kwdData.offset + 2),
1, /* Read 1 byte at a time */
&tmpBuffer[1],
- i_target );
+ i_target,
+ i_location );
break;
// ==================================================
default:
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Unknown keyword (0x%04x) for DDR3 special cases!",
+ TRACFCOMP( g_trac_spd, ERR_MRK"ddr3SpecialCases: "
+ "Unknown keyword (0x%04x) for DDR3 special cases!",
i_kwdData.keyword );
/*@
@@ -976,7 +1059,8 @@ errlHndl_t ddr3SpecialCases(const KeywordData & i_kwdData,
// ------------------------------------------------------------------
errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
void * io_buffer,
- TARGETING::Target * i_target)
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location)
{
errlHndl_t err = NULL;
uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer);
@@ -1003,7 +1087,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( i_kwdData.offset,
1, /* Read 1 byte at a time */
&tmpBuffer[0],
- i_target );
+ i_target,
+ i_location );
if( err ) break;
@@ -1018,7 +1103,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( (i_kwdData.offset - 1),
1, /* Read 1 byte at a time */
&tmpBuffer[1],
- i_target );
+ i_target,
+ i_location );
break;
// ==================================================
@@ -1028,7 +1114,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( i_kwdData.offset,
1, /* Read 1 byte at a time */
&tmpBuffer[0],
- i_target );
+ i_target,
+ i_location );
if( err ) break;
@@ -1043,7 +1130,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( (i_kwdData.offset + 2),
1, /* Read 1 byte at a time */
&tmpBuffer[1],
- i_target );
+ i_target,
+ i_location );
break;
// ==================================================
@@ -1053,7 +1141,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( i_kwdData.offset,
1, /* Read 1 byte at a time */
&tmpBuffer[0],
- i_target );
+ i_target,
+ i_location );
if( err ) break;
@@ -1061,7 +1150,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( (i_kwdData.offset - 1),
1, /* Read 1 byte at a time */
&tmpBuffer[1],
- i_target );
+ i_target,
+ i_location );
if( err ) break;
@@ -1069,7 +1159,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( (i_kwdData.offset - 2),
1, /* Read 1 byte at a time */
&tmpBuffer[2],
- i_target );
+ i_target,
+ i_location );
if( err ) break;
@@ -1077,13 +1168,14 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
err = spdFetchData( (i_kwdData.offset - 3),
1, /* Read 1 byte at a time */
&tmpBuffer[3],
- i_target );
+ i_target,
+ i_location );
break;
// ==================================================
default:
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Unknown keyword (0x%04x) for DDR4 special cases!",
+ TRACFCOMP( g_trac_spd, ERR_MRK"ddr4SpecialCases: "
+ "Unknown keyword (0x%04x) for DDR4 special cases!",
i_kwdData.keyword );
/*@
@@ -1120,7 +1212,8 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
errlHndl_t spdSpecialCases ( const KeywordData & i_kwdData,
void * io_buffer,
TARGETING::Target * i_target,
- uint64_t i_DDRRev )
+ uint64_t i_DDRRev,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
@@ -1132,11 +1225,11 @@ errlHndl_t spdSpecialCases ( const KeywordData & i_kwdData,
// Handle each of the special cases here
if( SPD_DDR3 == i_DDRRev )
{
- err = ddr3SpecialCases(i_kwdData,io_buffer,i_target);
+ err = ddr3SpecialCases(i_kwdData,io_buffer,i_target,i_location);
}
else if (SPD_DDR4 == i_DDRRev)
{
- err = ddr4SpecialCases(i_kwdData,io_buffer,i_target);
+ err = ddr4SpecialCases(i_kwdData,io_buffer,i_target,i_location);
}
else
{
@@ -1191,7 +1284,7 @@ errlHndl_t spdSpecialCases ( const KeywordData & i_kwdData,
// ------------------------------------------------------------------
errlHndl_t spdCheckSize ( size_t i_bufferSz,
size_t i_expBufferSz,
- uint64_t i_keyword )
+ VPD::vpdKeyword i_keyword )
{
errlHndl_t err = NULL;
@@ -1200,8 +1293,8 @@ errlHndl_t spdCheckSize ( size_t i_bufferSz,
if( i_bufferSz < i_expBufferSz )
{
TRACFCOMP( g_trac_spd,
- ERR_MRK"Buffer Size (%d) for keyword (0x%04x) wasn't greater "
- "than or equal to expected size (%d)",
+ ERR_MRK"Buffer Size (%d) for keyword (0x%04x) wasn't greater"
+ " than or equal to expected size (%d)",
i_bufferSz, i_keyword, i_expBufferSz );
/*@
@@ -1286,8 +1379,8 @@ errlHndl_t spdReadBinaryFile ( uint64_t i_byteAddr,
if( err )
{
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Error getting starting address of binary SPD file: %s",
+ TRACFCOMP( g_trac_spd, ERR_MRK"spdReadBinaryFile: "
+ "Error getting starting address of binary SPD file: %s",
fileName );
break;
@@ -1300,8 +1393,8 @@ errlHndl_t spdReadBinaryFile ( uint64_t i_byteAddr,
if( (i_byteAddr + i_numBytes) > fileSize )
{
TRACFCOMP( g_trac_spd,
- ERR_MRK"Unable to read %d bytes from %s at offset 0x%08x "
- "because file size is only %d bytes!",
+ ERR_MRK"Unable to read %d bytes from %s at offset 0x%08x"
+ " because file size is only %d bytes!",
i_numBytes,
fileName,
i_byteAddr,
@@ -1377,7 +1470,8 @@ bool compareEntries ( const KeywordData e1,
// ------------------------------------------------------------------
errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
uint64_t i_memType,
- TARGETING::Target * i_target )
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
@@ -1395,7 +1489,7 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
// Check that a Module Specific keyword is being accessed from a DIMM
// of the correct Module Type.
modSpecTypes_t modType = NA;
- err = getModType(modType, i_target, i_memType);
+ err = getModType(modType, i_target, i_memType, i_location);
if( err )
{
@@ -1408,8 +1502,8 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
if ((UMM != i_kwdData.modSpec) &&
(ALL != i_kwdData.modSpec) )
{
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Keyword (0x%04x) is not valid with UMM modules!",
+ TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
+ "Keyword (0x%04x) is not valid with UMM modules!",
i_kwdData.keyword );
/*@
* @errortype
@@ -1454,8 +1548,8 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
if ((RMM != i_kwdData.modSpec) &&
(ALL != i_kwdData.modSpec) )
{
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Keyword (0x%04x) is not valid with RMM modules!",
+ TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
+ "Keyword (0x%04x) is not valid with RMM modules!",
i_kwdData.keyword );
/*@
* @errortype
@@ -1500,8 +1594,8 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
if ((CMM != i_kwdData.modSpec) &&
(ALL != i_kwdData.modSpec) )
{
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Keyword (0x%04x) is not valid with CMM modules!",
+ TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
+ "Keyword (0x%04x) is not valid with CMM modules!",
i_kwdData.keyword );
/*@
* @errortype
@@ -1546,8 +1640,8 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
if ((LRMM != i_kwdData.modSpec) &&
(ALL != i_kwdData.modSpec) )
{
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Keyword (0x%04x) is not valid with LRMM modules!",
+ TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
+ "Keyword (0x%04x) is not valid with LRMM modules!",
i_kwdData.keyword );
/*@
* @errortype
@@ -1588,11 +1682,11 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
}
else
{
- TRACFCOMP( g_trac_spd,
- ERR_MRK"Module specific keyword could not be matched with an "
+ TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
+ "Module specific keyword could not be matched with an "
"appropriate scenario!" );
- TRACFCOMP( g_trac_spd,
- ERR_MRK" Mem Type: 0x%04x, Mod Type: 0x%04x, Keyword: 0x%04x",
+ TRACFCOMP( g_trac_spd, ERR_MRK
+ " Mem Type: 0x%04x, Mod Type: 0x%04x, Keyword: 0x%04x",
i_memType,
modType,
i_kwdData.keyword );
@@ -1643,14 +1737,16 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
// getMemType
// ------------------------------------------------------------------
errlHndl_t getMemType ( uint8_t & o_memType,
- TARGETING::Target * i_target )
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
err = spdFetchData( MEM_TYPE_ADDR,
MEM_TYPE_SZ,
&o_memType,
- i_target );
+ i_target,
+ i_location );
TRACUCOMP( g_trac_spd,
"SPD::getMemType() - MemType: 0x%02x, Error: %s",
@@ -1665,7 +1761,8 @@ errlHndl_t getMemType ( uint8_t & o_memType,
// ------------------------------------------------------------------
errlHndl_t getModType ( modSpecTypes_t & o_modType,
TARGETING::Target * i_target,
- uint64_t i_memType )
+ uint64_t i_memType,
+ VPD::vpdCmdTarget i_location )
{
errlHndl_t err = NULL;
o_modType = NA;
@@ -1674,7 +1771,8 @@ errlHndl_t getModType ( modSpecTypes_t & o_modType,
err = spdFetchData( MOD_TYPE_ADDR,
MOD_TYPE_SZ,
&modTypeVal,
- i_target );
+ i_target,
+ i_location );
if (err)
{
@@ -1768,7 +1866,7 @@ errlHndl_t getModType ( modSpecTypes_t & o_modType,
// ------------------------------------------------------------------
// getKeywordEntry
// ------------------------------------------------------------------
-errlHndl_t getKeywordEntry ( uint64_t i_keyword,
+errlHndl_t getKeywordEntry ( VPD::vpdKeyword i_keyword,
uint64_t i_memType,
TARGETING::Target * i_target,
const KeywordData *& o_entry )
@@ -1878,4 +1976,181 @@ errlHndl_t getKeywordEntry ( uint64_t i_keyword,
}
-} // end namespace SPD
+// ------------------------------------------------------------------
+// cmpPnorSeeprom
+// ------------------------------------------------------------------
+errlHndl_t cmpPnorToSeeprom ( TARGETING::Target * i_target,
+ VPD::vpdKeyword i_keyword,
+ bool &o_match )
+{
+ errlHndl_t err = NULL;
+
+ TRACSSCOMP( g_trac_spd, ENTER_MRK"cmpPnorSeeprom()" );
+
+ o_match = false;
+
+ do
+ {
+ // Read the Basic Memory Type
+ uint8_t memType = 0x0;
+ err = getMemType( memType,
+ i_target,
+ VPD::AUTOSELECT );
+ if( err )
+ {
+ break;
+ }
+ if(( SPD_DDR3 != memType ) &&
+ ( SPD_DDR4 != memType ))
+ {
+ break;
+ }
+
+ // Get the keyword size
+ size_t dataSize = 0;
+ if( SPD_DDR3 == memType )
+ {
+ dataSize = ddr3Data[i_keyword].length;
+ }
+ else
+ {
+ dataSize = ddr4Data[i_keyword].length;
+ }
+
+ // Read the keyword from PNOR
+ size_t sizePnor = dataSize;
+ uint8_t dataPnor[sizePnor];
+ err = spdGetValue( i_keyword,
+ dataPnor,
+ sizePnor,
+ i_target,
+ memType,
+ VPD::PNOR );
+ if( err )
+ {
+ // PNOR may not be loaded, ignore the error
+ delete err;
+ err = NULL;
+ break;
+ }
+
+ // Read the keyword from SEEPROM
+ size_t sizeSeeprom = dataSize;
+ uint8_t dataSeeprom[sizeSeeprom];
+ err = spdGetValue( i_keyword,
+ dataSeeprom,
+ sizeSeeprom,
+ i_target,
+ memType,
+ VPD::SEEPROM );
+ if( err )
+ {
+ break;
+ }
+
+ // Compare the PNOR/SEEPROM size/data
+ if( sizePnor != sizeSeeprom )
+ {
+ break;
+ }
+ if( memcmp( dataPnor, dataSeeprom, sizePnor ) )
+ {
+ break;
+ }
+
+ o_match = true;
+
+ } while(0);
+
+ TRACSSCOMP( g_trac_spd, EXIT_MRK"cmpPnorSeeprom()" );
+
+ return err;
+ }
+
+
+// ------------------------------------------------------------------
+// loadPnor
+// ------------------------------------------------------------------
+errlHndl_t loadPnor ( TARGETING::Target * i_target )
+{
+ errlHndl_t err = NULL;
+
+ TRACSSCOMP( g_trac_spd, ENTER_MRK"loadPnorCache()" );
+
+ do
+ {
+ // Invalidate the SPD in PNOR
+ err = invalidatePnor( i_target );
+ if( err )
+ {
+ TRACFCOMP( g_trac_spd,
+ ERR_MRK"loadPnorCache: Error invalidating the SPD in PNOR" );
+ break;
+ }
+
+ // Load PNOR cache from SEEPROM
+
+ // Read the entire SPD section from SEEPROM
+ uint8_t writeData[DIMM_SPD_SECTION_SIZE];
+ err = spdFetchData ( 0x0,
+ DIMM_SPD_SECTION_SIZE,
+ writeData,
+ i_target,
+ VPD::SEEPROM );
+ if( err )
+ {
+ TRACFCOMP( g_trac_spd,
+ ERR_MRK"loadPnorCache: Error reading SEEPROM SPD data" );
+ break;
+ }
+
+ // Write the entire SPD section to PNOR
+ err = spdWriteData( 0x0,
+ DIMM_SPD_SECTION_SIZE,
+ writeData,
+ i_target,
+ VPD::PNOR );
+ if( err )
+ {
+ TRACFCOMP( g_trac_spd,ERR_MRK"loadPnorCache: Error writing PNOR SPD data" );
+ break;
+ }
+
+ } while(0);
+
+ TRACSSCOMP( g_trac_spd, EXIT_MRK"loadPnorCache()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// /*invalidatePnorCache*/
+// ------------------------------------------------------------------
+errlHndl_t invalidatePnor ( TARGETING::Target * i_target )
+{
+ errlHndl_t err = NULL;
+
+ TRACSSCOMP( g_trac_spd, ENTER_MRK"invalidatePnorCache()" );
+
+ // Write SPD section to all Fs
+ uint8_t writeData[DIMM_SPD_SECTION_SIZE];
+ memset( writeData, 0xFF, DIMM_SPD_SECTION_SIZE );
+ err = spdWriteData( 0x0,
+ DIMM_SPD_SECTION_SIZE,
+ writeData,
+ i_target,
+ VPD::PNOR );
+ if( err )
+ {
+ TRACFCOMP( g_trac_spd, ERR_MRK"invalidatePnorCache: "
+ "Error invalidating the SPD in PNOR" );
+ }
+
+ TRACSSCOMP( g_trac_spd, EXIT_MRK"invalidatePnorCache()" );
+
+ return err;
+}
+
+
+}; // end namespace SPD
diff --git a/src/usr/vpd/spd.H b/src/usr/vpd/spd.H
index 4ba41cc90..b47c78438 100755
--- a/src/usr/vpd/spd.H
+++ b/src/usr/vpd/spd.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -34,6 +36,7 @@
// Includes
// ----------------------------------------------
#include <errl/errlentry.H>
+#include <vpd/spdenums.H>
#include "vpd.H"
namespace SPD
@@ -184,13 +187,16 @@ errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType,
*
* @param[in] i_target - The target DIMM to access.
*
+ * @param[in] i_location - The SPD source (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
errlHndl_t spdFetchData ( uint64_t i_byteAddr,
size_t i_numBytes,
void * o_data,
- TARGETING::Target * i_target );
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location );
/**
* @brief This function is a wrapper for writing the correct keyword.
@@ -205,13 +211,16 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr,
*
* @param[in] i_target - The target DIMM to access.
*
+ * @param[in] i_location - The SPD destination (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
errlHndl_t spdWriteData ( uint64_t i_offset,
size_t i_numBytes,
void * i_data,
- TARGETING::Target * i_target );
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location );
/**
@@ -230,14 +239,17 @@ errlHndl_t spdWriteData ( uint64_t i_offset,
*
* @param[in] i_DDRRev - The DIMM DDR Revision.
*
+ * @param[in] i_location - The SPD source (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
-errlHndl_t spdGetValue ( uint64_t i_keyword,
+errlHndl_t spdGetValue ( VPD::vpdKeyword i_keyword,
void * io_buffer,
size_t & io_buflen,
TARGETING::Target * i_target,
- uint64_t i_DDRRev );
+ uint64_t i_DDRRev,
+ VPD::vpdCmdTarget i_location );
/**
@@ -256,14 +268,17 @@ errlHndl_t spdGetValue ( uint64_t i_keyword,
*
* @param[in] i_DDRRev - The DIMM DDR Revision.
*
+ * @param[in] i_location - The SPD destination (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
-errlHndl_t spdWriteValue ( uint64_t i_keyword,
+errlHndl_t spdWriteValue ( VPD::vpdKeyword i_keyword,
void * io_buffer,
size_t & io_buflen,
TARGETING::Target * i_target,
- uint64_t i_DDRRev );
+ uint64_t i_DDRRev,
+ VPD::vpdCmdTarget i_location );
/**
@@ -278,13 +293,16 @@ errlHndl_t spdWriteValue ( uint64_t i_keyword,
*
* @param[in] i_target - The target DIMM to access the data for.
*
+ * @param[in] i_location - The SPD source/destination (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
errlHndl_t spdSpecialCases ( const KeywordData & i_kwdData,
void * io_buffer,
TARGETING::Target * i_target,
- uint64_t i_DDRRev );
+ uint64_t i_DDRRev,
+ VPD::vpdCmdTarget i_location );
/**
* @brief This function checks to make sure that the buffer allocated
@@ -302,7 +320,7 @@ errlHndl_t spdSpecialCases ( const KeywordData & i_kwdData,
*/
errlHndl_t spdCheckSize ( size_t i_bufferSz,
size_t i_expBufferSz,
- uint64_t i_keyword );
+ VPD::vpdKeyword i_keyword );
/**
* @brief This function will read a binary file from PNOR. This is
@@ -372,12 +390,15 @@ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
*
* @param[in] i_target - The chip target.
*
+ * @param[in] i_location - The SPD source (PNOR/SEEPROM).
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer to the error
* log.
*/
errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
uint64_t i_memType,
- TARGETING::Target * i_target );
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location );
/**
* @brief This function is used to query the attribute code to get the VPD
@@ -394,6 +415,44 @@ errlHndl_t getVpdLocation ( int64_t & o_vpdLocation,
TARGETING::Target * i_target );
+/**
+ * @brief This function compares value of the keyword in PNOR/SEEPROM
+ * and returns the result
+ *
+ * @param[in] i_target - Target device
+ *
+ * @param [in] i_keyword - Keyword to compare
+ *
+ * @param [in] o_match - Result of keyword compare
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log. A mismatch will not return an error.
+ */
+errlHndl_t cmpPnorToSeeprom( TARGETING::Target * i_target,
+ VPD::vpdKeyword i_keyword,
+ bool &o_match );
+
+/**
+ * @brief This function loads the SPD data from the SEEPROM into the PNOR cache
+ *
+ * @param[in] i_target - Target device
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t loadPnor ( TARGETING::Target * i_target );
+
+/**
+ * @brief This function invalidates the SPD in the PNOR cache
+ *
+ * @param[in] i_target - Target device
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t invalidatePnor ( TARGETING::Target * i_target );
+
+
}; // end SPD namespace
#endif // __SPD_H
diff --git a/src/usr/vpd/test/cvpdtest.H b/src/usr/vpd/test/cvpdtest.H
index 136e1fd9a..46975c88e 100755
--- a/src/usr/vpd/test/cvpdtest.H
+++ b/src/usr/vpd/test/cvpdtest.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -51,8 +53,8 @@ using namespace TARGETING;
*/
struct cvpdTestData
{
- IpVpdFacade::ipVpdRecord record;
- IpVpdFacade::ipVpdRecord keyword;
+ VPD::vpdRecord record;
+ VPD::vpdRecord keyword;
};
/**
@@ -708,8 +710,8 @@ class CVPDTest: public CxxTest::TestSuite
void testCvpdCheckStructOrder ( void )
{
uint64_t fails = 0x0;
- IpVpdFacade::ipVpdRecord prevRecord = CVPD::CVPD_FIRST_RECORD;
- IpVpdFacade::ipVpdKeyword prevKeyword = CVPD::CVPD_FIRST_KEYWORD;
+ VPD::vpdRecord prevRecord = CVPD::CVPD_FIRST_RECORD;
+ VPD::vpdKeyword prevKeyword = CVPD::CVPD_FIRST_KEYWORD;
TRACFCOMP( g_trac_vpd,
ENTER_MRK"testCvpdCheckStructOrder()" );
diff --git a/src/usr/vpd/test/mvpdtest.H b/src/usr/vpd/test/mvpdtest.H
index 28c683817..b89bc3637 100755
--- a/src/usr/vpd/test/mvpdtest.H
+++ b/src/usr/vpd/test/mvpdtest.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -51,8 +53,8 @@ using namespace TARGETING;
*/
struct mvpdTestData
{
- IpVpdFacade::ipVpdRecord record;
- IpVpdFacade::ipVpdRecord keyword;
+ VPD::vpdRecord record;
+ VPD::vpdRecord keyword;
};
/**
@@ -859,8 +861,8 @@ class MVPDTest: public CxxTest::TestSuite
void testMvpdCheckStructOrder ( void )
{
uint64_t fails = 0x0;
- IpVpdFacade::ipVpdRecord prevRecord = MVPD::MVPD_FIRST_RECORD;
- IpVpdFacade::ipVpdKeyword prevKeyword = MVPD::MVPD_FIRST_KEYWORD;
+ VPD::vpdRecord prevRecord = MVPD::MVPD_FIRST_RECORD;
+ VPD::vpdKeyword prevKeyword = MVPD::MVPD_FIRST_KEYWORD;
TRACFCOMP( g_trac_vpd,
ENTER_MRK"testMvpdCheckStructOrder()" );
diff --git a/src/usr/vpd/test/spdtest.H b/src/usr/vpd/test/spdtest.H
index 7a3739760..83de74c7f 100755
--- a/src/usr/vpd/test/spdtest.H
+++ b/src/usr/vpd/test/spdtest.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -937,7 +939,8 @@ class SPDTest: public CxxTest::TestSuite
"valid for all types of modules. IGNORE!!" );
err = checkModSpecificKeyword( kwdData,
memType,
- theTarget );
+ theTarget,
+ VPD::AUTOSELECT );
if( err )
{
// This keyword isn't supported with this module type
diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C
index 64fa99f3f..cb08625cc 100644..100755
--- a/src/usr/vpd/vpd.C
+++ b/src/usr/vpd/vpd.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -26,7 +28,12 @@
#include <errl/errludtarget.H>
#include <vpd/vpdreasoncodes.H>
#include <initservice/initserviceif.H>
+#include <devicefw/driverif.H>
+#include <sys/mm.h>
#include "vpd.H"
+#include "mvpd.H"
+#include "cvpd.H"
+#include "spd.H"
// ----------------------------------------------
// Trace definitions
@@ -238,6 +245,31 @@ errlHndl_t writePNOR ( uint64_t i_byteAddr,
memcpy( (void*)(writeAddr),
i_data,
i_numBytes );
+
+ // @todo RTC:117042 - enable flush once PNOR writes supported
+ // Flush the page to make sure it gets to the PNOR
+#if 0
+ int rc = mm_remove_pages( FLUSH, (void*)addr, i_numBytes );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"writePNOR() Error from mm_remove_pages, rc=%d",rc);
+ /*@
+ * @errortype
+ * @moduleid VPD_WRITE_PNOR
+ * @reasoncode VPD_REMOVE_PAGES_FAIL
+ * @userdata1 Requested Address
+ * @userdata2 rc from mm_remove_pages
+ * @devdesc writePNOR mm_remove_pages FLUSH failed
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD_WRITE_PNOR,
+ VPD_REMOVE_PAGES_FAIL,
+ addr,
+ TO_UINT64(rc),
+ true /*Add HB Software Callout*/ );
+ }
+#endif
} while( 0 );
TRACSSCOMP( g_trac_vpd,
@@ -322,4 +354,257 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes,
}
+// ------------------------------------------------------------------
+// resolveVpdSource
+// ------------------------------------------------------------------
+bool resolveVpdSource( TARGETING::Target * i_target,
+ bool i_readFromPnorEnabled,
+ bool i_readFromHwEnabled,
+ vpdCmdTarget i_vpdCmdTarget,
+ vpdCmdTarget& o_vpdSource )
+{
+ bool badConfig = false;
+ o_vpdSource = VPD::INVALID_LOCATION;
+
+ if( i_vpdCmdTarget == VPD::PNOR )
+ {
+ if( i_readFromPnorEnabled )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else
+ {
+ badConfig = true;
+ TRACFCOMP(g_trac_vpd,"resolveVpdSource: VpdCmdTarget=PNOR but READ_FROM_PNOR is disabled");
+ }
+ }
+ else if( i_vpdCmdTarget == VPD::SEEPROM )
+ {
+ if( i_readFromHwEnabled )
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ else
+ {
+ badConfig = true;
+ TRACFCOMP(g_trac_vpd,"resolveVpdSource: VpdCmdTarget=SEEPROM but READ_FROM_HW is disabled");
+ }
+ }
+ else // i_vpdCmdTarget == VPD::AUTOSELECT
+ {
+ if( i_readFromPnorEnabled &&
+ i_readFromHwEnabled )
+ {
+ // PNOR needs to be loaded before we can use it
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ if( vpdSwitches.pnorLoaded )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ }
+ else if( i_readFromPnorEnabled )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else if( i_readFromHwEnabled )
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ else
+ {
+ badConfig = true;
+ TRACFCOMP(g_trac_vpd,"resolveVpdSource: READ_FROM_PNOR and READ_FROM_HW disabled");
+ }
+ }
+
+ return badConfig;
+}
+
+
+// ------------------------------------------------------------------
+// ensureCacheIsInSync
+// ------------------------------------------------------------------
+errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
+{
+ errlHndl_t l_err = NULL;
+
+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"ensureCacheIsInSync() " );
+
+ IpVpdFacade& l_ipvpd = Singleton<MvpdFacade>::instance();
+
+ vpdRecord l_record = 0;
+ vpdKeyword l_keywordPN = 0;
+ vpdKeyword l_keywordSN = 0;
+
+ TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();
+
+ if( l_type == TARGETING::TYPE_PROC )
+ {
+ l_record = MVPD::VINI;
+ l_keywordPN = MVPD::PN;
+ l_keywordSN = MVPD::SN;
+ }
+ else if( l_type == TARGETING::TYPE_MEMBUF )
+ {
+ l_ipvpd = Singleton<CvpdFacade>::instance();
+ l_record = CVPD::VINI;
+ l_keywordPN = CVPD::PN;
+ l_keywordSN = CVPD::SN;
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ // SPD does not have a singleton instance
+ // SPD does not use records
+ l_keywordPN = SPD::MODULE_PART_NUMBER;
+ l_keywordSN = SPD::MODULE_SERIAL_NUMBER;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"ensureCacheIsInSync() Unexpected target type, huid=0x%X",TARGETING::get_huid(i_target));
+ /*@
+ * @errortype
+ * @moduleid VPD_ENSURE_CACHE_IS_IN_SYNC
+ * @reasoncode VPD_UNEXPECTED_TARGET_TYPE
+ * @userdata1 Target HUID
+ * @userdata2 <UNUSED>
+ * @devdesc Unexpected target type
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD_ENSURE_CACHE_IS_IN_SYNC,
+ VPD_UNEXPECTED_TARGET_TYPE,
+ TO_UINT64(TARGETING::get_huid(i_target)),
+ 0x0,
+ true /*Add HB Software Callout*/ );
+ return l_err;
+ }
+
+ do
+ {
+ // Compare the Part Numbers in PNOR/SEEPROM
+ bool l_matchPN = false;
+ if( ( l_type == TARGETING::TYPE_PROC ) ||
+ ( l_type == TARGETING::TYPE_MEMBUF ) )
+ {
+ l_err = l_ipvpd.cmpPnorToSeeprom( i_target,
+ l_record,
+ l_keywordPN,
+ l_matchPN );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::cmpPnorToSeeprom( i_target,
+ l_keywordPN,
+ l_matchPN );
+ }
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureCacheIsInSync: Error checking for PNOR/SEEPROM PN match");
+ break;
+ }
+
+ // Compare the Serial Numbers in PNOR/SEEPROM
+ bool l_matchSN = false;
+ if( ( l_type == TARGETING::TYPE_PROC ) ||
+ ( l_type == TARGETING::TYPE_MEMBUF ) )
+ {
+ l_err = l_ipvpd.cmpPnorToSeeprom( i_target,
+ l_record,
+ l_keywordSN,
+ l_matchSN );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::cmpPnorToSeeprom( i_target,
+ l_keywordSN,
+ l_matchSN );
+ }
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureCacheIsInSync: Error checking for PNOR/SEEPROM SN match");
+ break;
+ }
+
+ // If we did not match, we need to load SEEPROM VPD data into PNOR
+ if( l_matchPN && l_matchSN )
+ {
+ TRACFCOMP(g_trac_vpd,"VPD::ensureCacheIsInSync: PNOR_PN/SN = SEEPROM_PN/SN");
+ }
+ else
+ {
+ TRACFCOMP(g_trac_vpd,"VPD::ensureCacheIsInSync: PNOR_PN/SN != SEEPROM_PN/SN, Loading PNOR from SEEPROM");
+
+ // @todo RTC 116553 - Need HCDB update call here
+ // Load the PNOR data from the SEEPROM
+ if( ( l_type == TARGETING::TYPE_PROC ) ||
+ ( l_type == TARGETING::TYPE_MEMBUF ) )
+ {
+ l_err = l_ipvpd.loadPnor( i_target );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::loadPnor( i_target );
+ }
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_vpd,"Error loading SEEPROM VPD into PNOR");
+ break;
+ }
+ }
+
+ // Set target attribute switch that says VPD is loaded into PNOR
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ vpdSwitches.pnorLoaded = 1;
+ i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );
+
+ } while(0);
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"ensureCacheIsInSync()" );
+
+ return l_err;
+}
+
+
+// ------------------------------------------------------------------
+// invalidatePnorCache
+// ------------------------------------------------------------------
+errlHndl_t invalidatePnorCache ( TARGETING::Target * i_target )
+{
+ errlHndl_t l_err = NULL;
+
+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"invalidatePnorCache() " );
+
+ TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();
+
+ if( l_type == TARGETING::TYPE_PROC )
+ {
+ l_err = Singleton<MvpdFacade>::instance().invalidatePnor( i_target );
+ }
+ else if( l_type == TARGETING::TYPE_MEMBUF )
+ {
+ l_err = Singleton<CvpdFacade>::instance().invalidatePnor( i_target );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::invalidatePnor( i_target );
+ }
+
+ // Clear target attribute switch that says VPD is loaded into PNOR
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ vpdSwitches.pnorLoaded = 0;
+ i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"invalidatePnorCache()" );
+
+ return l_err;
+}
+
+
}; //end VPD namespace
diff --git a/src/usr/vpd/vpd.H b/src/usr/vpd/vpd.H
index 5f3e82011..d8972fb46 100644
--- a/src/usr/vpd/vpd.H
+++ b/src/usr/vpd/vpd.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,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. */
@@ -24,6 +26,7 @@
#define __VPD_H
#include <pnor/pnorif.H>
+#include <vpd/vpd_if.H>
namespace VPD
{
@@ -190,6 +193,31 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes,
VPD_MSG_TYPE i_type,
VpdWriteMsg_t& i_record );
+/**
+ * @brief This function determines the VPD source (PNOR/SEEPROM)
+ * from configuration and target state information
+ *
+ * @param[in] i_target - Target device.
+ *
+ * @param[in] i_readFromPnorEnabled - Config value specifying
+ * whether PNOR reads are enabled for this VPD type
+ *
+ * @param[in] i_readFromHwEnabled - Config value specifying
+ * whether SEEPROM reads are enabled for this VPD type
+ *
+ * @param[in] i_location - The requested VPD source location
+ * (PNOR/SEEPROM) from the caller
+ *
+ * @param[out] o_source - The resolved VPD source to be accessed
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+bool resolveVpdSource( TARGETING::Target * i_target,
+ bool i_readFromPnorEnabled,
+ bool i_readFromHwEnabled,
+ vpdCmdTarget i_vpdCmdTarget,
+ vpdCmdTarget& o_vpdSource );
}; //end VPD namespace
OpenPOWER on IntegriCloud