diff options
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/fsi/fsipres.C | 91 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/mc_config/mc_config.C | 71 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/attribute_types_hb.xml | 27 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/target_types_hb.xml | 7 | ||||
-rw-r--r-- | src/usr/vpd/HBconfig | 8 | ||||
-rw-r--r-- | src/usr/vpd/cvpd.C | 2 | ||||
-rwxr-xr-x | src/usr/vpd/dimmPres.C | 34 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.C | 586 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.H | 114 | ||||
-rw-r--r-- | src/usr/vpd/mvpd.C | 3 | ||||
-rw-r--r-- | src/usr/vpd/mvpd.H | 5 | ||||
-rw-r--r-- | src/usr/vpd/runtime/rt_vpd.C | 73 | ||||
-rw-r--r--[-rwxr-xr-x] | src/usr/vpd/spd.C | 455 | ||||
-rwxr-xr-x | src/usr/vpd/spd.H | 79 | ||||
-rwxr-xr-x | src/usr/vpd/test/cvpdtest.H | 12 | ||||
-rwxr-xr-x | src/usr/vpd/test/mvpdtest.H | 12 | ||||
-rwxr-xr-x | src/usr/vpd/test/spdtest.H | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | src/usr/vpd/vpd.C | 287 | ||||
-rw-r--r-- | src/usr/vpd/vpd.H | 30 |
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 |