summaryrefslogtreecommitdiffstats
path: root/src/usr/vpd/vpd.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/vpd/vpd.C')
-rwxr-xr-xsrc/usr/vpd/vpd.C410
1 files changed, 313 insertions, 97 deletions
diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C
index a9bc590b5..490c8bbc8 100755
--- a/src/usr/vpd/vpd.C
+++ b/src/usr/vpd/vpd.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -475,55 +475,55 @@ void setPartAndSerialNumberAttributes( TARGETING::Target * i_target )
void updateSerialNumberFromBMC( TARGETING::Target * i_nodetarget )
{
#ifdef CONFIG_UPDATE_SN_FROM_BMC
- errlHndl_t l_errl = NULL;
- size_t l_vpdSize = 0;
-
- //Get Product Serial Number from Backplane
- char* l_sn_prod = NULL;
- l_sn_prod = IPMIFRUINV::getProductSN(0);
- if (l_sn_prod != NULL)
- {
- TRACFCOMP(g_trac_vpd, "Got system serial number from BMC.");
- TRACFCOMP(g_trac_vpd, "SN from BMC is: %s", l_sn_prod);
-
- l_errl = deviceRead(i_nodetarget, NULL, l_vpdSize,
- DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
-
- if(l_errl == NULL)
- {
- uint8_t l_vpddata[l_vpdSize];
-
- l_errl = deviceRead(i_nodetarget, l_vpddata, l_vpdSize,
- DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
-
- if(l_errl == NULL)
- {
- TRACFCOMP(g_trac_vpd, "SN in PVPD::OSYS:SS: %s, size: %d", l_vpddata, l_vpdSize);
-
- if (strncmp(l_sn_prod, l_vpddata, l_vpdSize) != 0)
- {
- l_errl = deviceWrite(i_nodetarget, l_sn_prod, l_vpdSize,
- DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
- CONSOLE::displayf(NULL, "updated SN from BMC into PVPD.");
- CONSOLE::flush();
- CONSOLE::displayf(NULL, "Need a reboot.");
- CONSOLE::flush();
- INITSERVICE::requestReboot();
- }
- }
- }
-
- if(l_errl)
- {
- ERRORLOG::errlCommit(l_errl,VPD_COMP_ID);
- }
-
- //getProductSN requires the caller to delete the char array
- delete[] l_sn_prod;
- l_sn_prod = NULL;
-
- TRACFCOMP(g_trac_vpd, "End updateSerialNumberFromBMC.");
- }
+ errlHndl_t l_errl = NULL;
+ size_t l_vpdSize = 0;
+
+ //Get Product Serial Number from Backplane
+ char* l_sn_prod = NULL;
+ l_sn_prod = IPMIFRUINV::getProductSN(0);
+ if (l_sn_prod != NULL)
+ {
+ TRACFCOMP(g_trac_vpd, "Got system serial number from BMC.");
+ TRACFCOMP(g_trac_vpd, "SN from BMC is: %s", l_sn_prod);
+
+ l_errl = deviceRead(i_nodetarget, NULL, l_vpdSize,
+ DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
+
+ if(l_errl == NULL)
+ {
+ uint8_t l_vpddata[l_vpdSize];
+
+ l_errl = deviceRead(i_nodetarget, l_vpddata, l_vpdSize,
+ DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
+
+ if(l_errl == NULL)
+ {
+ TRACFCOMP(g_trac_vpd, "SN in PVPD::OSYS:SS: %s, size: %d", l_vpddata, l_vpdSize);
+
+ if (strncmp(l_sn_prod, l_vpddata, l_vpdSize) != 0)
+ {
+ l_errl = deviceWrite(i_nodetarget, l_sn_prod, l_vpdSize,
+ DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
+ CONSOLE::displayf(NULL, "updated SN from BMC into PVPD.");
+ CONSOLE::flush();
+ CONSOLE::displayf(NULL, "Need a reboot.");
+ CONSOLE::flush();
+ INITSERVICE::requestReboot();
+ }
+ }
+ }
+
+ if(l_errl)
+ {
+ ERRORLOG::errlCommit(l_errl,VPD_COMP_ID);
+ }
+
+ //getProductSN requires the caller to delete the char array
+ delete[] l_sn_prod;
+ l_sn_prod = NULL;
+
+ TRACFCOMP(g_trac_vpd, "End updateSerialNumberFromBMC.");
+ }
#endif
}
@@ -590,56 +590,19 @@ errlHndl_t getPnAndSnRecordAndKeywords( TARGETING::Target * i_target,
io_keywordSN = CVPD::SN;
#endif
}
- else if( i_type == TARGETING::TYPE_DIMM )
+ else if(( i_type == TARGETING::TYPE_DIMM )
+ || (i_type == TARGETING::TYPE_OCMB_CHIP))
{
// SPD does not have singleton instance
- // SPD does not use records
+ // SPD does not use record
io_keywordPN = SPD::MODULE_PART_NUMBER;
io_keywordSN = SPD::MODULE_SERIAL_NUMBER;
}
else if( i_type == TARGETING::TYPE_NODE )
{
-#if defined(CONFIG_PVPD_READ_FROM_HW) && defined(CONFIG_PVPD_READ_FROM_PNOR)
- IpVpdFacade* l_ipvpd = &(Singleton<PvpdFacade>::instance());
io_record = PVPD::OPFR;
io_keywordPN = PVPD::VP;
io_keywordSN = PVPD::VS;
-
- bool l_zeroPN;
- l_err = l_ipvpd->cmpSeepromToZero( i_target,
- io_record,
- io_keywordPN,
- l_zeroPN );
- if (l_err)
- {
- TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::getPnAndSnRecordAndKeywords: Error checking if OPFR:VP == 0");
- break;
- }
-
- bool l_zeroSN;
- l_err = l_ipvpd->cmpSeepromToZero( i_target,
- io_record,
- io_keywordSN,
- l_zeroSN );
- if (l_err)
- {
- TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::getPnAndSnRecordAndKeywords: Error checking if OPFR:VS == 0");
- break;
- }
-
- // If VP and VS are zero, use VINI instead
- if( l_zeroPN && l_zeroSN )
- {
- TRACFCOMP(g_trac_vpd, "setting cvpd to VINI PN SN");
- io_record = PVPD::VINI;
- io_keywordPN = PVPD::PN;
- io_keywordSN = PVPD::SN;
- }
-#else
- io_record = PVPD::VINI;
- io_keywordPN = PVPD::PN;
- io_keywordSN = PVPD::SN;
-#endif
}
else if( i_type == TARGETING::TYPE_MCS )
{
@@ -672,6 +635,249 @@ errlHndl_t getPnAndSnRecordAndKeywords( TARGETING::Target * i_target,
return l_err;
}
+/**
+ * @brief This function compares the specified record/keyword in
+ * CACHE/HARDWARE by calling the correct function based on the
+ * target's eeprom content type and returns the result. A mismatch
+ * will not return an error.
+ *
+ * @param[in] i_target Target device
+ *
+ * @param[in] i_eepromType Eeprom content type for the target.
+ *
+ * @param[in] i_keyword Keyword to compare
+ *
+ * @param[in] i_record Record to compare
+ *
+ * @param[out] o_match Result of compare
+ *
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t cmpEecacheToEeprom(TARGETING::Target * i_target,
+ TARGETING::EEPROM_CONTENT_TYPE i_eepromType,
+ vpdKeyword i_keyword,
+ vpdRecord i_record,
+ bool& o_match)
+{
+ errlHndl_t l_err = nullptr;
+
+ if ( (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_IBM_MVPD)
+ || (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_IBM_FRUVPD))
+ {
+ auto l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();
+ IpVpdFacade* l_ipvpd = &(Singleton<MvpdFacade>::instance());
+
+ // If we have a NODE, use pvpd api
+ if(l_type == TARGETING::TYPE_NODE)
+ {
+ l_ipvpd = &(Singleton<PvpdFacade>::instance());
+ }
+
+ l_err = l_ipvpd->cmpEecacheToEeprom(i_target,
+ i_record,
+ i_keyword,
+ o_match);
+ }
+ else if ( (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_ISDIMM)
+ || (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM))
+ {
+ l_err = SPD::cmpEecacheToEeprom(i_target,
+ i_eepromType,
+ i_keyword,
+ o_match);
+ }
+ else
+ {
+ assert(false, "Error, invalid EEPROM type 0x%x for target HUID 0x%X passed to cmpEecacheToEeprom",
+ i_eepromType, get_huid(i_target));
+ }
+
+ return l_err;
+}
+
+
+// ------------------------------------------------------------------
+// ensureEepromCacheIsInSync
+// ------------------------------------------------------------------
+errlHndl_t ensureEepromCacheIsInSync(TARGETING::Target * i_target,
+ TARGETING::EEPROM_CONTENT_TYPE i_eepromType,
+ bool & o_isInSync)
+{
+ errlHndl_t l_err = nullptr;
+
+ TRACDCOMP(g_trac_vpd, ENTER_MRK"ensureEepromCacheIsInSync() ");
+
+ vpdRecord l_record = 0;
+ vpdKeyword l_keywordPN = 0;
+ vpdKeyword l_keywordSN = 0;
+ TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();
+
+ do
+ {
+ // Get the correct Part and serial numbers
+ l_err = getPnAndSnRecordAndKeywords(i_target,
+ i_target->
+ getAttr<TARGETING::ATTR_TYPE>(),
+ l_record,
+ l_keywordPN,
+ l_keywordSN);
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_vpd,
+ "VPD::ensureEepromCacheIsInSync: "
+ "Error getting part and serial numbers");
+ break;
+ }
+
+ // Compare the Part Numbers in CACHE/HARDWARE
+ bool l_matchPN = false;
+ l_err = cmpEecacheToEeprom(i_target,
+ i_eepromType,
+ l_keywordPN,
+ l_record,
+ l_matchPN);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK
+ "VPD::ensureEepromCacheIsInSync: "
+ "Error checking for CACHE/HARDWARE PN match");
+ break;
+ }
+
+ // Compare the Serial Numbers in CACHE/HARDWARE
+ bool l_matchSN = false;
+ l_err = cmpEecacheToEeprom(i_target,
+ i_eepromType,
+ l_keywordSN,
+ l_record,
+ l_matchSN);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_vpd, ERR_MRK
+ "VPD::ensureEepromCacheIsInSync: Error checking for "
+ "CACHE/HARDWARE SN match");
+ break;
+ }
+
+ // Check the serial number and part number of the system if the previous
+ // record/key pair matched. Note that this time the record/key pairs are
+ // OSYS/SS and OSYS/MM for serial number and part number, respectively
+ if (l_type == TARGETING::TYPE_NODE &&
+ (l_matchSN && l_matchPN))
+ {
+ // If we have a NODE, use pvpd api
+ IpVpdFacade* l_ipvpd = &(Singleton<PvpdFacade>::instance());
+ bool l_zeroPN = false;
+ bool l_zeroSN = false;
+ l_err = l_ipvpd->cmpSeepromToZero(i_target,
+ PVPD::OSYS,
+ PVPD::MM,
+ l_zeroPN);
+ if(l_err)
+ {
+ TRACDCOMP(g_trac_vpd,ERR_MRK"VPD::ensureEepromCacheIsInSync: "
+ "cmpSeepromToZero returned an error. Assuming this error is "
+ "related to OSYS/MM not being present in SEEPROM. Skipping "
+ "this error. HUID: 0x%.8X",
+ TARGETING::get_huid(i_target));
+ delete l_err;
+ l_err = nullptr;
+ l_zeroPN = true;
+
+ }
+
+ l_err = l_ipvpd->cmpSeepromToZero(i_target,
+ PVPD::OSYS,
+ PVPD::SS,
+ l_zeroSN);
+ if(l_err)
+ {
+ TRACDCOMP(g_trac_vpd,ERR_MRK"VPD::ensureEepromCacheIsInSync: "
+ "cmpSeepromToZero returned an error. Assuming this error is "
+ "related to OSYS/SS not being present in SEEPROM. Skipping "
+ "this error. HUID: 0x%.8X",
+ TARGETING::get_huid(i_target));
+ delete l_err;
+ l_err = nullptr;
+ l_zeroSN = true;
+ }
+
+ //Only compare the SN/PN between SEEPROM and EECACHE if they are
+ //nonzero.
+ if(!l_zeroPN)
+ {
+ l_err = cmpEecacheToEeprom(i_target,
+ i_eepromType,
+ PVPD::MM,
+ PVPD::OSYS,
+ l_matchPN);
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureEepromCacheIsInSync: Error"
+ " checking for EECACHE/SEEPROM PN match for NODE target 0x%.8X",
+ TARGETING::get_huid(i_target));
+ break;
+ }
+ }
+
+ if(!l_zeroSN)
+ {
+ l_err = cmpEecacheToEeprom(i_target,
+ i_eepromType,
+ PVPD::SS,
+ PVPD::OSYS,
+ l_matchSN);
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureEepromCacheIsInSync: Error"
+ " checking for EECACHE/SEEPROM SN match for NODE target 0x%.8X",
+ TARGETING::get_huid(i_target));
+ break;
+ }
+ }
+ }
+
+ o_isInSync = (l_matchPN && l_matchSN);
+
+ // If we did not match, we need to load HARDWARE VPD data into CACHE
+ if (o_isInSync)
+ {
+ TRACFCOMP(g_trac_vpd,
+ "VPD::ensureEepromCacheIsInSync: "
+ "CACHE_PN/SN == HARDWARE_PN/SN for target %.8X",
+ TARGETING::get_huid(i_target));
+ }
+ else
+ {
+ TRACFCOMP(g_trac_vpd,
+ "VPD::ensureEepromCacheIsInSync: CACHE_PN/SN != HARDWARE_PN/SN,CACHE must be loaded from HARDWARE for target %.8X",
+ TARGETING::get_huid(i_target));
+ const char* l_pathstring
+ = i_target->getAttr<TARGETING::ATTR_PHYS_PATH>().toString();
+ CONSOLE::displayf(NULL,"Detected new part : %.8X (%s)",
+ TARGETING::get_huid(i_target),
+ l_pathstring);
+ free((void*)(l_pathstring));
+ l_pathstring = nullptr;
+ CONSOLE::flush();
+#ifndef CONFIG_SUPPORT_EEPROM_CACHING
+ //Set the targets as changed since the p/n's don't match
+ HWAS::markTargetChanged(i_target);
+#else
+ //No need to mark target changed here, it will be handled by eecache code
+#endif
+ }
+
+ } while(0);
+
+ TRACDCOMP(g_trac_vpd, EXIT_MRK"ensureEepromCacheIsInSync()");
+
+ return l_err;
+}
+
// ------------------------------------------------------------------
// ensureCacheIsInSync
// ------------------------------------------------------------------
@@ -842,6 +1048,14 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
else
{
TRACFCOMP(g_trac_vpd,"VPD::ensureCacheIsInSync: PNOR_PN/SN != SEEPROM_PN/SN, Loading PNOR from SEEPROM for target %.8X",TARGETING::get_huid(i_target));
+ const char* l_pathstring =
+ i_target->getAttr<TARGETING::ATTR_PHYS_PATH>().toString();
+ CONSOLE::displayf(NULL,"Detected new part : %.8X (%s)",
+ TARGETING::get_huid(i_target),
+ l_pathstring);
+ free((void*)(l_pathstring));
+ l_pathstring = nullptr;
+ CONSOLE::flush();
//Set the targets as changed since the p/n's don't match
HWAS::markTargetChanged(i_target);
@@ -1122,14 +1336,16 @@ void getListOfOverrideSections( OverrideRsvMemMap_t& o_overrides )
delete l_elog;
return;
}
+ else
+ {
+ // Add MEMD section
+ OverrideSpecifier_t l_memd = {
+ PNOR::MEMD,
+ l_memd_info.size
+ };
- // Add MEMD section
- OverrideSpecifier_t l_memd = {
- PNOR::MEMD,
- l_memd_info.size
- };
-
- o_overrides[0x4D454D44/*MEMD*/] = l_memd;
+ o_overrides[0x4D454D44/*MEMD*/] = l_memd;
+ }
}
}; //end VPD namespace
OpenPOWER on IntegriCloud