summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/vpd/vpd_if.H21
-rw-r--r--src/include/usr/vpd/vpdreasoncodes.H2
-rw-r--r--src/usr/i2c/eepromCache.C159
-rw-r--r--src/usr/vpd/ocmb_spd.C38
-rw-r--r--src/usr/vpd/spd.C325
-rwxr-xr-xsrc/usr/vpd/spd.H54
-rwxr-xr-xsrc/usr/vpd/vpd.C140
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 )
OpenPOWER on IntegriCloud