diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/vpd/vpd_if.H | 21 | ||||
-rw-r--r-- | src/include/usr/vpd/vpdreasoncodes.H | 2 | ||||
-rw-r--r-- | src/usr/i2c/eepromCache.C | 159 | ||||
-rw-r--r-- | src/usr/vpd/ocmb_spd.C | 38 | ||||
-rw-r--r-- | src/usr/vpd/spd.C | 325 | ||||
-rwxr-xr-x | src/usr/vpd/spd.H | 54 | ||||
-rwxr-xr-x | src/usr/vpd/vpd.C | 140 |
7 files changed, 640 insertions, 99 deletions
diff --git a/src/include/usr/vpd/vpd_if.H b/src/include/usr/vpd/vpd_if.H index 4e63a0965..a995fe06c 100644 --- a/src/include/usr/vpd/vpd_if.H +++ b/src/include/usr/vpd/vpd_if.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2018 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -108,6 +108,25 @@ namespace VPD errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target ); /** + * @brief This function checks if the eeprom cache for the target is in + * sync with hardware and returns the result in o_isInSync. + * + * @param[in] i_target Target device + * + * + * @param[in] i_eepromType Eeprom content type of target device + * + * @param[out] o_isInSync true if part and serial numbers in cache match + * hardware. Otherwise, false. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t ensureEepromCacheIsInSync(TARGETING::Target * i_target, + TARGETING::EEPROM_CONTENT_TYPE i_eepromType, + bool & o_isInSync); + + /** * @brief This function invalidates the VPD data in the PNOR cache. * @param[in] i_target - Target device * @return errlHndl_t - NULL if successful, otherwise a pointer to the diff --git a/src/include/usr/vpd/vpdreasoncodes.H b/src/include/usr/vpd/vpdreasoncodes.H index 8d9d6943b..9307af7b7 100644 --- a/src/include/usr/vpd/vpdreasoncodes.H +++ b/src/include/usr/vpd/vpdreasoncodes.H @@ -101,6 +101,8 @@ enum vpdModuleId VPD_OCMB_GET_SPD = 0x90, VPD_OCMB_SPD_PERFORM_OP = 0x91, + VPD_READ_FROM_EEPROM_SOURCE = 0x92, + VPD_GET_MEMTYPE = 0x93, }; diff --git a/src/usr/i2c/eepromCache.C b/src/usr/i2c/eepromCache.C index 7fb6e3bf8..7fa2b9861 100644 --- a/src/usr/i2c/eepromCache.C +++ b/src/usr/i2c/eepromCache.C @@ -39,6 +39,7 @@ #include <initservice/initsvcreasoncodes.H> #include <pnor/pnorif.H> #include <vpd/vpd_if.H> + #include <errl/errludtarget.H> #include <config.h> #ifdef CONFIG_CONSOLE @@ -216,6 +217,7 @@ bool addEepromToCachedList(const eepromRecordHeader & i_eepromRecordHeader) i_eepromRecordHeader.completeRecord.devAddr, i_eepromRecordHeader.completeRecord.mux_select, i_eepromRecordHeader.completeRecord.cache_copy_size); + l_matchFound = false; } @@ -271,7 +273,7 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, if(l_errl) { // buildEepromRecordHeader should have traced any relavent information if - // is was needed, just break out and pass the error along + // it was needed, just break out and pass the error along break; } @@ -416,61 +418,138 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, INITSERVICE::doShutdown(INITSERVICE::SHUTDOWN_DO_RECONFIG_LOOP); } - // - // At this point we have found a match in the PNOR but we need - // to decide what all needs an update - // - - // Stash the internal_offset of the section we found in so we can add - // this record to g_cachedEeproms for later use + // Stash the internal_offset of the section we found in so we + // can add this record to g_cachedEeproms for later use l_eepromRecordHeader.completeRecord.internal_offset = - l_recordHeaderToUpdate->completeRecord.internal_offset; + l_recordHeaderToUpdate->completeRecord.internal_offset; + TRACSSCOMP(g_trac_eeprom, + "cacheEeprom() already found copy for eeprom role %d for target w/ HUID 0x.%08X", + i_eepromType , TARGETING::get_huid(i_target)); + break; + } + } - if(l_recordHeaderToUpdate->completeRecord.cached_copy_valid) - { - // If the existing eeprom record is valid, then only update the - // contents if the SN/PN for current HW do not match the eeprom - // record. (target must be present to cache) + if(!addEepromToCachedList(l_eepromRecordHeader)) + { + TRACSSCOMP( g_trac_eeprom, + "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X added to cached list", + i_eepromType , TARGETING::get_huid(i_target)); + } + else + { + TRACSSCOMP( g_trac_eeprom, + "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X already in cached list", + i_eepromType , TARGETING::get_huid(i_target)); + } - // TODO RTC:203788 add lookup for PN and SN matches - //if( !i_present || PNandSNMatch ) - { - l_updateContents = false; - } - // If target is present there is nothing in the - // header to update - if( i_present ) - { - l_updateHeader = false; - } + uint64_t l_eepromCacheVaddr = lookupEepromAddr(l_eepromRecordHeader); + const uint64_t l_invalidAddress = 0xFFFFFFFFFFFFFFFF; + + // If the virtual address of the eeprom record header is an invalid + // address then this is the first time this target's eeprom is being + // cached. + bool l_isNewCacheEntry = false; + if (memcmp( + reinterpret_cast<void *>(l_eepromCacheVaddr), + &l_invalidAddress, sizeof(uint64_t)) == 0) + { + l_isNewCacheEntry = true; + } + + // At this point we have found a match in the PNOR but we need + // to decide what all needs an update. + // + // Only check if the cache is in sync with HARDWARE if there is an + // existing EECACHE section. Otherwise, the code after this logic will + // take care of adding a new eeprom cache section for the target. + if ( l_recordHeaderToUpdate->completeRecord.cached_copy_valid + && !l_isNewCacheEntry) + { + // Create namespace alias for targeting to reduce number of + // new lines required to be within line character limit. + namespace T = TARGETING; + + // If the existing eeprom record is valid, then only update + // the contents if the SN/PN for current HW do not match the + // eeprom record. (target must be present to cache) + T::EEPROM_CONTENT_TYPE l_eepromContentType = + T::EEPROM_CONTENT_TYPE_RAW; + + if (i_eepromType == EEPROM::VPD_PRIMARY) + { + auto l_eepromVpd = + i_target->getAttr<T::ATTR_EEPROM_VPD_PRIMARY_INFO>(); + + l_eepromContentType = + static_cast<T::EEPROM_CONTENT_TYPE>( + l_eepromVpd.eepromContentType); + } + else + { + auto l_eepromVpd = + i_target->getAttr<T::ATTR_EEPROM_VPD_BACKUP_INFO>(); + + l_eepromContentType = + static_cast<T::EEPROM_CONTENT_TYPE>( + l_eepromVpd.eepromContentType); + } + + TRACSSCOMP(g_trac_eeprom, + "cacheEeprom() Target 0x%.8X " + "EEPROM_CONTENT_TYPE 0x%X", + T::get_huid(i_target), + l_eepromContentType); + + bool l_isInSync = false; + + if (i_present) + { + l_errl = VPD::ensureEepromCacheIsInSync(i_target, + l_eepromContentType, + l_isInSync); + + if (l_errl != nullptr) + { + break; } - else if(!i_present) + + if(l_isInSync) { - // If the target is not present, then do not update contents or header l_updateContents = false; - l_updateHeader = false; } - TRACSSCOMP( g_trac_eeprom, "cacheEeprom() already found copy for eeprom role %d for target w/ HUID 0x.%08X", - i_eepromType , TARGETING::get_huid(i_target)); - break; } - } + else + { + // Clear out the contents of the cache for this eeprom if we have detected that it + // was once valid, indicating it was present at one time, and is now showing + // up as not present. We want to clear the contents of cache so we can achieve + // the replug behavior where a tester can remove the part, boot, then plug in the + // same part and boot again fresh. + void * l_internalSectionAddr = + reinterpret_cast<uint8_t *>(l_eecacheSectionHeaderPtr) + l_eepromRecordHeader.completeRecord.internal_offset; + memset( l_internalSectionAddr, 0xFF , + (l_recordHeaderToUpdate->completeRecord.cache_copy_size * KILOBYTE)); + l_updateContents = false; + } - if(!addEepromToCachedList(l_eepromRecordHeader)) - { - TRACSSCOMP( g_trac_eeprom, "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X added to cached list", - i_eepromType , TARGETING::get_huid(i_target)); + // If target is present there is nothing in the + // header to update + if( i_present ) + { + l_updateHeader = false; + } } - else + else if(!i_present) { - TRACSSCOMP( g_trac_eeprom, "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X already in cached list", - i_eepromType , TARGETING::get_huid(i_target)); + // If the target is not present, then do not update contents + // or header + l_updateContents = false; + l_updateHeader = false; } - // Above we have determined whether the contents of the eeprom at // hand need to have their contents updated. Only do the following // steps that update the eeprom's cached data if we were told to do so. diff --git a/src/usr/vpd/ocmb_spd.C b/src/usr/vpd/ocmb_spd.C index 454f7a327..567ab43b1 100644 --- a/src/usr/vpd/ocmb_spd.C +++ b/src/usr/vpd/ocmb_spd.C @@ -31,6 +31,7 @@ #include "ocmb_spd.H" #include "spd.H" #include "errlud_vpd.H" +#include <vpd/vpd_if.H> extern trace_desc_t * g_trac_spd; @@ -71,27 +72,12 @@ DEVICE_REGISTER_ROUTE(DeviceFW::READ, T::TYPE_OCMB_CHIP, ocmbSPDPerformOp); -/** - * @brief Read keyword from SPD - * - * Currently used to detect I2C_MUTEX and OCMB_CHIP targets - * - * @param[in] i_target OCMB target to read data from - * @param[in/out] io_buffer databuffer SPD will be written to - * @param[in/out] io_buflen length of the given data buffer - * @param[in] i_keyword keyword from spdenums.H to read - * @param[in] i_memType The memory type of this target. - * - * @pre io_buffer and i_target must be non-null - * @pre currenlty only supported value for i_keyword is ENTIRE_SPD - * - * @return errlHndl_t - */ errlHndl_t ocmbGetSPD(T::TargetHandle_t i_target, - void* const io_buffer, + void* io_buffer, size_t& io_buflen, - const uint64_t & i_keyword, - const uint8_t i_memType) + const VPD::vpdKeyword i_keyword, + const uint8_t i_memType, + EEPROM::EEPROM_SOURCE i_location) { errlHndl_t l_errl = nullptr; @@ -196,7 +182,7 @@ errlHndl_t ocmbGetSPD(T::TargetHandle_t i_target, entry->offset, dataSize, io_buffer, - EEPROM::AUTOSELECT); + i_location); if (l_errl != nullptr) { @@ -262,8 +248,9 @@ bool isValidOcmbDimmType(const uint8_t i_dimmType) // ------------------------------------------------------------------ // getMemType // ------------------------------------------------------------------ -errlHndl_t getMemType(uint8_t& o_memType, - T::TargetHandle_t i_target) +errlHndl_t getMemType(uint8_t& o_memType, + T::TargetHandle_t i_target, + EEPROM::EEPROM_SOURCE i_location) { errlHndl_t err = nullptr; @@ -271,7 +258,7 @@ errlHndl_t getMemType(uint8_t& o_memType, MEM_TYPE_ADDR, MEM_TYPE_SZ, &o_memType, - EEPROM::AUTOSELECT); + i_location); TRACSSCOMP(g_trac_spd, EXIT_MRK"SPD::getMemType() - MemType: 0x%02x, Error: %s", @@ -300,7 +287,7 @@ errlHndl_t ocmbSPDPerformOp(DeviceFW::OperationType i_opType, { // Read the Basic Memory Type uint8_t memType(MEM_TYPE_INVALID); - errl = getMemType(memType, i_target); + errl = getMemType(memType, i_target, EEPROM::AUTOSELECT); if( errl ) { @@ -330,7 +317,8 @@ errlHndl_t ocmbSPDPerformOp(DeviceFW::OperationType i_opType, io_buffer, io_buflen, keyword, - memType); + memType, + EEPROM::AUTOSELECT); if( errl ) { diff --git a/src/usr/vpd/spd.C b/src/usr/vpd/spd.C index 247a60cc2..828f1c83b 100644 --- a/src/usr/vpd/spd.C +++ b/src/usr/vpd/spd.C @@ -53,6 +53,7 @@ #include "spdDDR4.H" #include "spdDDR4_DDIMM.H" #include "errlud_vpd.H" +#include "ocmb_spd.H" #include <config.h> // ---------------------------------------------- @@ -122,6 +123,11 @@ const bool g_usePNOR = true; */ bool isValidDimmType ( uint8_t i_dimmType ); +//@TODO RTC 203788 doxygen +bool isValidDimmType(uint8_t i_memType, + TARGETING::EEPROM_CONTENT_TYPE i_eepromType); + + /** * @brief Compare two values and return whether e2 is greater than * the e1 value. This is used during lower_bound to cut @@ -139,6 +145,7 @@ bool isValidDimmType ( uint8_t i_dimmType ); bool compareEntries ( const KeywordData e1, const KeywordData e2 ); +// @TODO RTC 203788 update comment block /** * @brief This function will read the DIMM memory type. * @@ -151,9 +158,28 @@ bool compareEntries ( const KeywordData e1, * @return errlHndl_t - NULL if successful, otherwise a pointer * to the error log. */ -errlHndl_t getMemType ( uint8_t & o_memType, - TARGETING::Target * i_target, - VPD::vpdCmdTarget i_location ); +errlHndl_t getMemType(uint8_t & o_memType, + TARGETING::Target * i_target, + VPD::vpdCmdTarget i_location, + EEPROM::EEPROM_SOURCE i_eepromSource = EEPROM::AUTOSELECT); + +// @TODO RTC 203788 update comment block +/** + * @brief This function will read the DIMM memory type. + * + * @param[out] o_memType - The memory type value to return. + * + * @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::EEPROM_CONTENT_TYPE i_eepromType, + EEPROM::EEPROM_SOURCE i_eepromSource); /** * @brief This function will read the DIMM module type. @@ -208,6 +234,29 @@ bool isValidDimmType ( const uint8_t i_dimmType ) ( SPD_DDR4_TYPE == i_dimmType ) ); } + +bool isValidDimmType(uint8_t i_memType, + TARGETING::EEPROM_CONTENT_TYPE i_eepromType) +{ + bool isValid = false; + +// TODO RTC:204341 Add support for reading/write EECACHE during runtime +#ifndef __HOSTBOOT_RUNTIME + if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_ISDIMM) + { + isValid = isValidDimmType(i_memType); + } + else if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM) + { + isValid = isValidOcmbDimmType(i_memType); + } + +#endif + + return isValid; +} + + // ------------------------------------------------------------------ // spdGetKeywordValue // ------------------------------------------------------------------ @@ -438,11 +487,12 @@ errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType, // ------------------------------------------------------------------ // spdFetchData // ------------------------------------------------------------------ -errlHndl_t spdFetchData ( uint64_t i_byteAddr, - size_t i_numBytes, - void * o_data, - TARGETING::Target * i_target, - VPD::vpdCmdTarget i_location ) +errlHndl_t spdFetchData ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target, + VPD::vpdCmdTarget i_location, + EEPROM::EEPROM_SOURCE i_eepromSource) { errlHndl_t err{nullptr}; @@ -498,7 +548,7 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, DEVICE_EEPROM_ADDRESS( EEPROM::VPD_PRIMARY, i_byteAddr, - EEPROM::AUTOSELECT) ); + i_eepromSource)); if( err ) { TRACFCOMP(g_trac_spd, @@ -622,12 +672,13 @@ errlHndl_t spdWriteData ( uint64_t i_offset, // ------------------------------------------------------------------ // spdGetValue // ------------------------------------------------------------------ -errlHndl_t spdGetValue ( VPD::vpdKeyword i_keyword, - void * io_buffer, - size_t & io_buflen, - TARGETING::Target * i_target, - uint64_t i_DDRRev, - VPD::vpdCmdTarget i_location ) +errlHndl_t spdGetValue(VPD::vpdKeyword i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target, + uint64_t i_DDRRev, + VPD::vpdCmdTarget i_location, + EEPROM::EEPROM_SOURCE i_eepromSource) { errlHndl_t err{nullptr}; uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer); @@ -1790,9 +1841,10 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData, // ------------------------------------------------------------------ // getMemType // ------------------------------------------------------------------ -errlHndl_t getMemType ( uint8_t & o_memType, - TARGETING::Target * i_target, - VPD::vpdCmdTarget i_location ) +errlHndl_t getMemType(uint8_t & o_memType, + TARGETING::Target * i_target, + VPD::vpdCmdTarget i_location, + EEPROM::EEPROM_SOURCE i_eepromSource) { errlHndl_t err{nullptr}; @@ -1800,7 +1852,8 @@ errlHndl_t getMemType ( uint8_t & o_memType, MEM_TYPE_SZ, &o_memType, i_target, - i_location ); + i_location, + i_eepromSource); TRACUCOMP( g_trac_spd, EXIT_MRK"SPD::getMemType() - MemType: 0x%02x, Error: %s", @@ -1810,6 +1863,57 @@ errlHndl_t getMemType ( uint8_t & o_memType, return err; } + +errlHndl_t getMemType(uint8_t & o_memType, + TARGETING::Target * i_target, + TARGETING::EEPROM_CONTENT_TYPE i_eepromType, + EEPROM::EEPROM_SOURCE i_eepromSource) +{ + errlHndl_t err = nullptr; + +// @TODO RTC 204341 Implement for runtime +#ifndef __HOSTBOOT_RUNTIME + + if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_ISDIMM) + { + err = getMemType(o_memType, + i_target, + VPD::AUTOSELECT, + i_eepromSource); + } + else if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM) + { + err = getMemType(o_memType, + i_target, + i_eepromSource); + } + else + { + /*@ + * @errortype + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_GET_MEMTYPE + * @reasoncode VPD::VPD_INVALID_EEPROM_CONTENT_TYPE + * @userdata1 Eeprom Content Type Given + * @userdata2 Target HUID + * @devdesc An unsupported eeprom content type was supplied. + * @custdesc A problem occurred during the IPL + * of the system. + */ + err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_GET_MEMTYPE, + VPD::VPD_INVALID_EEPROM_CONTENT_TYPE, + i_eepromType, + TARGETING::get_huid(i_target), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + } + +#endif + + return err; + +} + // ------------------------------------------------------------------ // getModType // ------------------------------------------------------------------ @@ -2174,6 +2278,189 @@ void setPartAndSerialNumberAttributes( TARGETING::Target * i_target ) TRACSSCOMP(g_trac_spd, EXIT_MRK"spd.C::setPartAndSerialNumberAttributes()"); } +// @TODO RTC 203788 Doxygen +errlHndl_t readFromEepromSource(TARGETING::Target* i_target, + TARGETING::EEPROM_CONTENT_TYPE i_eepromType, + const VPD::vpdKeyword i_keyword, + const uint8_t i_memType, + void* io_buffer, + size_t& io_buflen, + EEPROM::EEPROM_SOURCE i_eepromSource) +{ + errlHndl_t err = nullptr; + +// @TODO RTC 204341 Implement for runtime +#ifndef __HOSTBOOT_RUNTIME + if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_ISDIMM) + { + err = spdGetValue(i_keyword, + io_buffer, + io_buflen, + i_target, + i_memType, + VPD::SEEPROM, + i_eepromSource); + } + else if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM) + { + err = ocmbGetSPD(i_target, + io_buffer, + io_buflen, + i_keyword, + i_memType, + i_eepromSource); + } + else + { + /*@ + * @errortype + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_READ_FROM_EEPROM_SOURCE + * @reasoncode VPD::VPD_INVALID_EEPROM_CONTENT_TYPE + * @userdata1 Eeprom Content Type Given + * @userdata2 Target HUID + * @devdesc An unsupported eeprom content type was supplied. + * @custdesc A problem occurred during the IPL + * of the system. + */ + err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_READ_FROM_EEPROM_SOURCE, + VPD::VPD_INVALID_EEPROM_CONTENT_TYPE, + i_eepromType, + TARGETING::get_huid(i_target), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + } +#endif + + return err; +} + + +// ------------------------------------------------------------------ +// cmpEecacheToEeprom +// ------------------------------------------------------------------ +errlHndl_t cmpEecacheToEeprom(TARGETING::Target * i_target, + TARGETING::EEPROM_CONTENT_TYPE i_eepromType, + VPD::vpdKeyword i_keyword, + bool &o_match) +{ + errlHndl_t err = nullptr; + + TRACSSCOMP(g_trac_spd, ENTER_MRK"cmpEecacheToEeprom()"); + + o_match = false; + do + { + // Read the Basic Memory Type from the Eeprom Cache + uint8_t memTypeCache(MEM_TYPE_INVALID); + err = getMemType(memTypeCache, + i_target, + i_eepromType, + EEPROM::CACHE); + if (err) + { + break; + } + + if (!isValidDimmType(memTypeCache, i_eepromType)) + { + break; + } + + // Read the Basic Memory Type from HARDWARE + uint8_t memTypeHardware(MEM_TYPE_INVALID); + err = getMemType(memTypeHardware, + i_target, + i_eepromType, + EEPROM::HARDWARE); + if (err) + { + break; + } + + if (!isValidDimmType(memTypeHardware, i_eepromType)) + { + // Leave o_match == false and exit. + break; + } + + if (memTypeCache != memTypeHardware) + { + // CACHE and HARDWARE don't match. + // Leave o_match == false and exit. + break; + } + + // Get the keyword size + const KeywordData* entry = nullptr; + err = getKeywordEntry(i_keyword, + memTypeHardware, + i_target, + entry); + if (err) + { + break; + } + size_t dataSize = entry->length; + + + // Read the keyword from HARDWARE + size_t sizeHardware = dataSize; + uint8_t dataHardware[sizeHardware]; + err = readFromEepromSource(i_target, + i_eepromType, + i_keyword, + memTypeHardware, + dataHardware, + sizeHardware, + EEPROM::HARDWARE); + if (err) + { + break; + } + + // Read the keyword from CACHE + size_t sizeCache = dataSize; + uint8_t dataCache[sizeCache]; + err = readFromEepromSource(i_target, + i_eepromType, + i_keyword, + memTypeHardware, + dataCache, + sizeCache, + EEPROM::CACHE); + if (err) + { + // CACHE may not be loaded, ignore the error + delete err; + err = NULL; + break; + } + + // Compare the HARDWARE/CACHE keyword size/data + if (sizeHardware != sizeCache) + { + // CACHE and HARDWARE don't match. + // Leave o_match == false and exit. + break; + } + if (memcmp(dataHardware, dataCache, sizeHardware)) + { + // CACHE and HARDWARE don't match. + // Leave o_match == false and exit. + break; + } + + o_match = true; + + } while(0); + + TRACSSCOMP( g_trac_spd, EXIT_MRK"cmpEecacheToEeprom(): returning %s errors. o_match = 0x%X ", + (err ? "with" : "with no"), o_match ); + + return err; + } + // ------------------------------------------------------------------ // cmpPnorToSeeprom // ------------------------------------------------------------------ diff --git a/src/usr/vpd/spd.H b/src/usr/vpd/spd.H index b5cd95f82..6fb3658d7 100755 --- a/src/usr/vpd/spd.H +++ b/src/usr/vpd/spd.H @@ -39,6 +39,8 @@ #include <errl/errlentry.H> #include <vpd/spdenums.H> #include "vpd.H" +#include <attributeenums.H> +#include <i2c/eeprom_const.H> namespace SPD { @@ -202,14 +204,19 @@ errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType, * * @param[in] i_location - The SPD source (PNOR/SEEPROM). * + * @param[in] i_eepromSource Eeprom source (CACHE/HARDWARE). + * Default AUTOSELECT + * * @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, - VPD::vpdCmdTarget i_location ); +errlHndl_t spdFetchData(uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target, + VPD::vpdCmdTarget i_location, + EEPROM::EEPROM_SOURCE i_eepromSource = EEPROM::AUTOSELECT + ); /** * @brief This function is a wrapper for writing the correct keyword. @@ -254,15 +261,20 @@ errlHndl_t spdWriteData ( uint64_t i_offset, * * @param[in] i_location - The SPD source (PNOR/SEEPROM). * + * @param[in] i_eepromSource The eeprom source (CACHE/HARDWARE). + * Default AUTOSELECT + * * @return errlHndl_t - NULL if successful, otherwise a pointer to the * error log. */ -errlHndl_t spdGetValue ( VPD::vpdKeyword i_keyword, - void * io_buffer, - size_t & io_buflen, - TARGETING::Target * i_target, - uint64_t i_DDRRev, - VPD::vpdCmdTarget i_location ); +errlHndl_t spdGetValue(VPD::vpdKeyword i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target, + uint64_t i_DDRRev, + VPD::vpdCmdTarget i_location, + EEPROM::EEPROM_SOURCE i_eepromSource = EEPROM::AUTOSELECT + ); /** @@ -496,6 +508,26 @@ errlHndl_t cmpPnorToSeeprom( TARGETING::Target * i_target, bool &o_match ); /** + * @brief This function compares value of the keyword in PNOR/SEEPROM + * and returns the result + * + * @param[in] i_target - Target device + * + * @param[in] i_eepromType - Eeprom content type of 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 cmpEecacheToEeprom(TARGETING::Target * i_target, + TARGETING::EEPROM_CONTENT_TYPE i_eepromType, + 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 diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C index a9bc590b5..24728c2b8 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. */ /* */ /* */ @@ -590,10 +590,11 @@ 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; } @@ -673,6 +674,139 @@ errlHndl_t getPnAndSnRecordAndKeywords( TARGETING::Target * i_target, } // ------------------------------------------------------------------ +// 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>(); + + //@TODO RTC 203788 Uncomment when used for IBM_MVPD and IBM_FRUVPD content + // types. +// 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()); +// } +// + do + { + // Get the correct Part and serial numbers + l_err = getPnAndSnRecordAndKeywords(i_target, + l_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; + if ( (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_IBM_MVPD) + || (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_IBM_FRUVPD)) + { + // @TODO: RTC 203788 Implement cmpEecacheToEeprom + // l_err = l_ipvpd->cmpEecacheToEeprom(i_target, + // l_record, + // l_keywordPN, + // l_matchPN); + } + else if ( (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_ISDIMM) + || (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM)) + { + l_err = SPD::cmpEecacheToEeprom(i_target, + i_eepromType, + l_keywordPN, + l_matchPN); + } + + if (l_err) + { + TRACDCOMP(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; + if ( (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_IBM_MVPD) + || (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_IBM_FRUVPD)) + { + //@TODO RTC 203788: Implement for this case + // l_err = l_ipvpd->cmpEecacheToEeprom(i_target, + // l_record, + // l_keywordSN, + // l_matchSN); + } + else if ( (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_ISDIMM) + || (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM)) + { + l_err = SPD::cmpEecacheToEeprom(i_target, + i_eepromType, + l_keywordSN, + l_matchSN); + } + + if (l_err) + { + TRACDCOMP(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 + // @TODO RTC 210350 Handle this case. +// if (l_type == TARGETING::TYPE_NODE && +// (l_matchSN && l_matchPN)) +// { +// +// } + + 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)); + + //Set the targets as changed since the p/n's don't match + HWAS::markTargetChanged(i_target); + } + + } while(0); + + TRACDCOMP(g_trac_vpd, EXIT_MRK"ensureEepromCacheIsInSync()"); + + return l_err; +} + +// ------------------------------------------------------------------ // ensureCacheIsInSync // ------------------------------------------------------------------ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target ) |