diff options
Diffstat (limited to 'src/usr/vpd/vpd.C')
-rwxr-xr-x | src/usr/vpd/vpd.C | 410 |
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 |