summaryrefslogtreecommitdiffstats
path: root/src/usr/vpd
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/vpd')
-rw-r--r--src/usr/vpd/HBconfig13
-rw-r--r--src/usr/vpd/cvpd.C1
-rw-r--r--src/usr/vpd/cvpd.H3
-rwxr-xr-xsrc/usr/vpd/dimmPres.C3
-rw-r--r--src/usr/vpd/dvpd.C1
-rw-r--r--src/usr/vpd/dvpd.H3
-rw-r--r--src/usr/vpd/errlud_vpd.C10
-rw-r--r--src/usr/vpd/ipvpd.C202
-rw-r--r--src/usr/vpd/ipvpd.H108
-rw-r--r--src/usr/vpd/makefile1
-rw-r--r--src/usr/vpd/mvpd.C3
-rw-r--r--src/usr/vpd/ocmb_spd.C368
-rw-r--r--src/usr/vpd/ocmb_spd.H102
-rw-r--r--src/usr/vpd/pvpd.C6
-rw-r--r--src/usr/vpd/pvpd.H3
-rw-r--r--src/usr/vpd/rtvpd_load.C18
-rw-r--r--src/usr/vpd/runtime/rt_vpd.C4
-rw-r--r--src/usr/vpd/spd.C851
-rwxr-xr-xsrc/usr/vpd/spd.H107
-rw-r--r--src/usr/vpd/spdDDR3.H136
-rwxr-xr-xsrc/usr/vpd/spdDDR4.H138
-rwxr-xr-xsrc/usr/vpd/spdDDR4_DDIMM.H141
-rwxr-xr-xsrc/usr/vpd/test/dvpdtest.H7
-rwxr-xr-xsrc/usr/vpd/test/spdtest.H130
-rwxr-xr-xsrc/usr/vpd/vpd.C410
-rw-r--r--src/usr/vpd/vpd.mk1
-rw-r--r--src/usr/vpd/vpd_common.C4
27 files changed, 2029 insertions, 745 deletions
diff --git a/src/usr/vpd/HBconfig b/src/usr/vpd/HBconfig
index 0d321192c..86979d7fa 100644
--- a/src/usr/vpd/HBconfig
+++ b/src/usr/vpd/HBconfig
@@ -1,10 +1,12 @@
config MEMVPD_READ_FROM_PNOR
default y
+ default n if SUPPORT_EEPROM_CACHING
help
Read memory VPD data from PNOR cache
config MEMVPD_READ_FROM_HW
default n
+ default y if SUPPORT_EEPROM_CACHING
depends on !PALMETTO_PASS1
help
Read memory VPD data from HW resources
@@ -17,12 +19,14 @@ config MEMVPD_READ
config MEMVPD_WRITE_TO_PNOR
default y if MEMVPD_READ_FROM_PNOR
+ default n if SUPPORT_EEPROM_CACHING
depends on MEMVPD_READ_FROM_PNOR
help
Write memory VPD data to PNOR cache
config MEMVPD_WRITE_TO_HW
default y if MEMVPD_READ_FROM_HW
+ default y if SUPPORT_EEPROM_CACHING
depends on !PALMETTO_PASS1 && MEMVPD_READ_FROM_HW
help
Write memory VPD data to HW resources
@@ -40,6 +44,7 @@ config PVPD_READ_FROM_PNOR
config PVPD_READ_FROM_HW
default n
+ default y if SUPPORT_EEPROM_CACHING
help
Read Planar VPD data from HW resources
@@ -51,17 +56,20 @@ config PVPD_WRITE_TO_PNOR
config PVPD_WRITE_TO_HW
default y if PVPD_READ_FROM_HW
+ default y if SUPPORT_EEPROM_CACHING
depends on PVPD_READ_FROM_HW
help
Write Planar VPD data to HW resources
config MVPD_READ_FROM_PNOR
default y
+ default n if SUPPORT_EEPROM_CACHING
help
Read Module VPD data from PNOR cache
config MVPD_READ_FROM_HW
default n
+ default y if SUPPORT_EEPROM_CACHING
help
Read Module VPD data from HW resources
@@ -73,11 +81,13 @@ config MVPD_READ
config MVPD_WRITE_TO_PNOR
default y if MVPD_READ_FROM_PNOR
+ default n if SUPPORT_EEPROM_CACHING
help
Write Module VPD data to PNOR cache
config MVPD_WRITE_TO_HW
default y if MVPD_READ_FROM_HW
+ default y if SUPPORT_EEPROM_CACHING
depends on MVPD_READ_FROM_HW
help
Write Module VPD data to HW resources
@@ -90,11 +100,13 @@ config MVPD_WRITE
config DJVPD_READ_FROM_PNOR
default y
+ default n if SUPPORT_EEPROM_CACHING
help
Read Dimm JEDEC VPD/SPD data from PNOR cache
config DJVPD_READ_FROM_HW
default n
+ default y if SUPPORT_EEPROM_CACHING
help
Read Dimm JEDEC VPD/SPD data from HW resources
@@ -106,6 +118,7 @@ config DJVPD_READ
config DJVPD_WRITE_TO_PNOR
default y if DJVPD_READ_FROM_PNOR
+ default n if SUPPORT_EEPROM_CACHING
help
Write Dimm JEDEC VPD/SPD data to PNOR cache
diff --git a/src/usr/vpd/cvpd.C b/src/usr/vpd/cvpd.C
index 354e76ab9..5b56655f0 100644
--- a/src/usr/vpd/cvpd.C
+++ b/src/usr/vpd/cvpd.C
@@ -41,7 +41,6 @@
#include <vpd/cvpdenums.H>
#include <vpd/vpd_if.H>
#include <i2c/eepromif.H>
-#include <config.h>
#include "cvpd.H"
#include "pvpd.H"
#include "vpd.H"
diff --git a/src/usr/vpd/cvpd.H b/src/usr/vpd/cvpd.H
index 31f89b29f..05f09386b 100644
--- a/src/usr/vpd/cvpd.H
+++ b/src/usr/vpd/cvpd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -40,7 +40,6 @@
#include <vpd/cvpdenums.H>
#include "ipvpd.H"
-#include <config.h>
namespace CVPD
{
diff --git a/src/usr/vpd/dimmPres.C b/src/usr/vpd/dimmPres.C
index a62d31f5e..dad7c027e 100755
--- a/src/usr/vpd/dimmPres.C
+++ b/src/usr/vpd/dimmPres.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2016 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -41,7 +41,6 @@
#include <devicefw/driverif.H>
#include <vpd/vpdreasoncodes.H>
#include <vpd/spdenums.H>
-#include <config.h>
#include <initservice/initserviceif.H>
#include <fsi/fsiif.H>
diff --git a/src/usr/vpd/dvpd.C b/src/usr/vpd/dvpd.C
index d0238b997..9d3bc796d 100644
--- a/src/usr/vpd/dvpd.C
+++ b/src/usr/vpd/dvpd.C
@@ -39,7 +39,6 @@
#include <vpd/dvpdenums.H>
#include <vpd/vpd_if.H>
#include <i2c/eepromif.H>
-#include <config.h>
#include "dvpd.H"
#include "cvpd.H"
#include "vpd.H"
diff --git a/src/usr/vpd/dvpd.H b/src/usr/vpd/dvpd.H
index 92985aebe..7517fce2a 100644
--- a/src/usr/vpd/dvpd.H
+++ b/src/usr/vpd/dvpd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -40,7 +40,6 @@
#include <vpd/dvpdenums.H>
#include "ipvpd.H"
-#include <config.h>
namespace DVPD
{
diff --git a/src/usr/vpd/errlud_vpd.C b/src/usr/vpd/errlud_vpd.C
index f24a5a030..8030e134c 100644
--- a/src/usr/vpd/errlud_vpd.C
+++ b/src/usr/vpd/errlud_vpd.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -61,8 +61,8 @@ UdVpdParms::UdVpdParms( TARGETING::Target * i_target,
reallocUsrBuf(sizeof(uint8_t)
+sizeof(uint32_t)
+sizeof(uint64_t)*3));
- uint32_t tmp64 = 0;
- uint16_t tmp32 = 0;
+ uint64_t tmp64 = 0;
+ uint32_t tmp32 = 0;
uint8_t tmp8 = 0;
tmp8 = read_notWrite;
@@ -124,8 +124,8 @@ UdConfigParms::UdConfigParms( TARGETING::Target * i_target,
char * l_pBuf = reinterpret_cast<char *>(
reallocUsrBuf(sizeof(uint32_t)
+sizeof(uint64_t)*7));
- uint32_t tmp64 = 0;
- uint16_t tmp32 = 0;
+ uint64_t tmp64 = 0;
+ uint32_t tmp32 = 0;
tmp32 = TARGETING::get_huid(i_target);
memcpy(l_pBuf, &tmp32, sizeof(tmp32));
diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C
index 168bc5d36..b38bd77a3 100644
--- a/src/usr/vpd/ipvpd.C
+++ b/src/usr/vpd/ipvpd.C
@@ -39,7 +39,6 @@
#include <vfs/vfs.H>
#include <vpd/vpdreasoncodes.H>
#include <vpd/vpd_if.H>
-#include <config.h>
#include <vpd/ipvpdenums.H>
#include <util/utilrsvdmem.H>
#include <util/runtime/util_rt.H>
@@ -319,6 +318,117 @@ errlHndl_t IpVpdFacade::write ( TARGETING::Target * i_target,
}
// ------------------------------------------------------------------
+// IpVpdFacade::cmpEecacheToEeprom
+// ------------------------------------------------------------------
+errlHndl_t IpVpdFacade::cmpEecacheToEeprom(TARGETING::Target * i_target,
+ VPD::vpdRecord i_record,
+ VPD::vpdKeyword i_keyword,
+ bool & o_match)
+{
+ errlHndl_t l_err = nullptr;
+
+ TRACSSCOMP(g_trac_vpd, ENTER_MRK"cmpEecacheToEeprom() ");
+
+ o_match = false;
+
+ input_args_t l_cacheArgs;
+ l_cacheArgs.record = i_record;
+ l_cacheArgs.keyword = i_keyword;
+ l_cacheArgs.location = VPD::SEEPROM;
+ l_cacheArgs.eepromSource = EEPROM::CACHE;
+
+ input_args_t l_hardwareArgs;
+ l_hardwareArgs.record = i_record;
+ l_hardwareArgs.keyword = i_keyword;
+ l_hardwareArgs.location = VPD::SEEPROM;
+ l_hardwareArgs.eepromSource = EEPROM::HARDWARE;
+
+ do
+ {
+ // Get the CACHE size
+ size_t l_sizeCache = 0;
+
+ l_err = read(i_target,
+ nullptr,
+ l_sizeCache,
+ l_cacheArgs);
+
+ if( l_err || (l_sizeCache == 0) )
+ {
+ TRACFCOMP(g_trac_vpd,
+ "cmpEecacheToEeprom() an error occurred reading the keyword size in cache");
+ break;
+ }
+
+ // Get the CACHE data
+ uint8_t l_dataCache[l_sizeCache];
+ l_err = read( i_target,
+ l_dataCache,
+ l_sizeCache,
+ l_cacheArgs );
+
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_vpd,
+ "cmpEecacheToEeprom() an error occurred reading the keyword in cache");
+ break;
+ }
+
+ // Get the HARDWARE size
+ size_t l_sizeHardware = 0;
+ l_err = read( i_target,
+ nullptr,
+ l_sizeHardware,
+ l_hardwareArgs );
+
+ if( l_err || (l_sizeHardware == 0) )
+ {
+ TRACFCOMP(g_trac_vpd,
+ "cmpEecacheToEeprom() an error occurred reading the keyword size in hardware");
+ break;
+ }
+
+ // Get the HARDWARE data
+ uint8_t l_dataHardware[l_sizeHardware];
+ l_err = read( i_target,
+ l_dataHardware,
+ l_sizeHardware,
+ l_hardwareArgs );
+
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_vpd,
+ "cmpEecacheToEeprom() an error occurred reading the keyword in hardware");
+ break;
+ }
+
+ // Compare the CACHE/HARDWARE keyword size/data
+ if( l_sizeCache != l_sizeHardware )
+ {
+ // Leave o_match == false since there isn't a match.
+ break;
+ }
+
+ if( memcmp( l_dataCache,
+ l_dataHardware,
+ l_sizeCache ) != 0 )
+ {
+ TRACFCOMP( g_trac_vpd, "cmpEecacheToEeprom found mismatch for HUID %.8X 0x%X:0x%X", TARGETING::get_huid(i_target), i_record, i_keyword );
+ TRACFBIN( g_trac_vpd, "HARDWARE", l_dataHardware, l_sizeHardware );
+ TRACFBIN( g_trac_vpd, "CACHE", l_dataCache, l_sizeCache );
+ break;
+ }
+
+ o_match = true;
+
+ } while(0);
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"cmpEecacheToEeprom()" );
+
+ return l_err;
+}
+
+// ------------------------------------------------------------------
// IpVpdFacade::cmpPnorToSeeprom
// ------------------------------------------------------------------
errlHndl_t IpVpdFacade::cmpPnorToSeeprom ( TARGETING::Target * i_target,
@@ -885,8 +995,12 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record,
return err;
}
- TRACFCOMP( g_trac_vpd, INFO_MRK" Record %s for target 0x%.8X exists at %p in PNOR",
+ // Don't trace that record exists in PNOR if it does not
+ if (l_overridePtr != nullptr)
+ {
+ TRACFCOMP( g_trac_vpd, INFO_MRK" Record %s for target 0x%.8X exists at %p in PNOR",
i_record, get_huid(i_target), l_overridePtr );
+ }
}
// If we have an override, the record is already pointed at directly
@@ -1180,7 +1294,7 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
TARGETING::Target * i_target,
input_args_t i_args )
{
- errlHndl_t err = NULL;
+ errlHndl_t err = nullptr;
char l_buffer[256] = { 0 };
uint16_t offset = 0x0;
@@ -1248,6 +1362,12 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
err = retrieveKeyword( "PT", "VTOC", offset, index, i_target, l_buffer,
pt_len, i_args );
if ( err ) {
+ // There may be only one PT record
+ if (index != 0)
+ {
+ delete err;
+ err = nullptr;
+ }
break;
}
@@ -1271,7 +1391,7 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record,
}
}
- if ( !found && err == NULL ) {
+ if ( !found && err == nullptr ) {
TRACFCOMP( g_trac_vpd,
ERR_MRK"IpVpdFacade::findRecordOffsetSeeprom: "
"No matching Record (%s) found in VTOC!", i_record );
@@ -1618,6 +1738,36 @@ errlHndl_t IpVpdFacade::retrieveRecord( const char * i_recordName,
return err;
}
+
+// ------------------------------------------------------------------
+// IpVpdFacade::fetchData
+// ------------------------------------------------------------------
+errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void * o_data,
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location,
+ const char* i_record )
+{
+ errlHndl_t err = nullptr;
+
+ // Create an input_args struct which will default EEPROM_SOURCE
+ // to EEPROM::AUTOSELECT.
+ input_args_t inputArgs;
+
+ // Set the VPD location to the given location (PNOR/SEEPROM).
+ inputArgs.location = i_location;
+
+ err = fetchData(i_byteAddr,
+ i_numBytes,
+ o_data,
+ i_target,
+ inputArgs,
+ i_record);
+
+ return err;
+}
+
// ------------------------------------------------------------------
// IpVpdFacade::fetchData
// ------------------------------------------------------------------
@@ -1625,7 +1775,7 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr,
size_t i_numBytes,
void * o_data,
TARGETING::Target * i_target,
- VPD::vpdCmdTarget i_location,
+ input_args_t i_args,
const char* i_record )
{
errlHndl_t err = NULL;
@@ -1636,12 +1786,12 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr,
configError = VPD::resolveVpdSource( i_target,
iv_configInfo.vpdReadPNOR,
iv_configInfo.vpdReadHW,
- i_location,
+ i_args.location,
vpdSource );
// Look for a record override in our image unless explicitly told not to
bool l_foundOverride = false;
- if( (i_location & VPD::OVERRIDE_MASK) != VPD::USEVPD )
+ if( (i_args.location & VPD::OVERRIDE_MASK) != VPD::USEVPD )
{
uint8_t* l_overridePtr = nullptr;
VPD::RecordTargetPair_t l_recTarg =
@@ -1694,7 +1844,11 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr,
}
else if ( (vpdSource == VPD::SEEPROM) && !l_foundOverride )
{
- err = fetchDataFromEeprom( i_byteAddr, i_numBytes, o_data, i_target );
+ err = fetchDataFromEeprom(i_byteAddr,
+ i_numBytes,
+ o_data,
+ i_target,
+ i_args.eepromSource);
}
else
{
@@ -1723,7 +1877,7 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr,
VPD::VPD_READ_SOURCE_UNRESOLVED,
TWO_UINT32_TO_UINT64(
TARGETING::get_huid(i_target),
- i_location ),
+ i_args.location ),
TWO_UINT32_TO_UINT64(
iv_configInfo.vpdReadPNOR,
iv_configInfo.vpdReadHW ),
@@ -1777,10 +1931,11 @@ errlHndl_t IpVpdFacade::fetchDataFromPnor ( uint64_t i_byteAddr,
// ------------------------------------------------------------------
// IpVpdFacade::fetchDataFromEeprom
// ------------------------------------------------------------------
-errlHndl_t IpVpdFacade::fetchDataFromEeprom ( uint64_t i_byteAddr,
- size_t i_numBytes,
- void * o_data,
- TARGETING::Target * i_target )
+errlHndl_t IpVpdFacade::fetchDataFromEeprom(uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void * o_data,
+ TARGETING::Target * i_target,
+ EEPROM::EEPROM_SOURCE i_eepromSource)
{
errlHndl_t err = NULL;
TRACSSCOMP( g_trac_vpd,
@@ -1797,7 +1952,8 @@ errlHndl_t IpVpdFacade::fetchDataFromEeprom ( uint64_t i_byteAddr,
i_numBytes,
DEVICE_EEPROM_ADDRESS(
EEPROM::VPD_PRIMARY,
- i_byteAddr, EEPROM::AUTOSELECT ) );
+ i_byteAddr,
+ i_eepromSource ) );
if( err )
{
break;
@@ -1896,21 +2052,31 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName,
offset,
i_recordName );
+ // convert data for SRC display
+ uint32_t exp_rec;
+ memcpy( &exp_rec, i_recordName, RECORD_BYTE_SIZE );
+ uint32_t act_rec;
+ memcpy( &act_rec, record, RECORD_BYTE_SIZE );
+
/*@
* @errortype
* @reasoncode VPD::VPD_RECORD_MISMATCH
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid VPD::VPD_IPVPD_FIND_KEYWORD_ADDR
- * @userdata1 Current offset into VPD
- * @userdata2 Start of Record offset
+ * @userdata1[00:31] Current offset into VPD
+ * @userdata1[32:63] Start of Record offset
+ * @userdata2[00:31] Expected record name
+ * @userdata2[32:63] Found record name
* @devdesc Record name does not match value expected for
* offset read.
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
VPD::VPD_IPVPD_FIND_KEYWORD_ADDR,
VPD::VPD_RECORD_MISMATCH,
- offset,
- i_offset );
+ TWO_UINT32_TO_UINT64(offset,
+ i_offset ),
+ TWO_UINT32_TO_UINT64(exp_rec,
+ act_rec) );
// Could be the VPD of the target wasn't set up properly
// -- DECONFIG so that we can possibly keep booting
diff --git a/src/usr/vpd/ipvpd.H b/src/usr/vpd/ipvpd.H
index 597c6e256..c47a241a6 100644
--- a/src/usr/vpd/ipvpd.H
+++ b/src/usr/vpd/ipvpd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -31,9 +31,8 @@
#include <map>
#include <pnor/pnorif.H>
#include <devicefw/driverif.H>
-#include <config.h>
#include "vpd.H"
-
+#include <i2c/eeprom_const.H>
/** @file ipvpd.H
* @brief Provides base support for i/p-Series style IBM VPD
@@ -79,11 +78,35 @@ class IpVpdFacade
/**
* @brief Structure for all VPD dd input parameter arguments
*/
- typedef struct
+ typedef struct device_driver_input_args
{
- VPD::vpdRecord record;
- VPD::vpdKeyword keyword;
- VPD::vpdCmdTarget location;
+ VPD::vpdRecord record;
+ VPD::vpdKeyword keyword;
+ VPD::vpdCmdTarget location;
+ EEPROM::EEPROM_SOURCE eepromSource;
+
+ // Default constructor
+ device_driver_input_args() : record(0xFFFFFFFF),
+ keyword(0xFFFFFFFF),
+ location(VPD::AUTOSELECT),
+ eepromSource(EEPROM::AUTOSELECT)
+ {};
+
+ // This constructor allows for existing code using brace-enclosed
+ // initializer lists of the first three arguments to continue to
+ // function normally. Since the default behavior for EEPROM_SOURCE is
+ // AUTOSELECT, setting it automatically here is done to maintain that
+ // default assumption.
+ device_driver_input_args(VPD::vpdRecord i_record,
+ VPD::vpdKeyword i_keyword,
+ VPD::vpdCmdTarget i_location)
+ : record(i_record),
+ keyword(i_keyword),
+ location(i_location),
+ eepromSource(EEPROM::AUTOSELECT)
+ {};
+
+
} input_args_t;
/**
@@ -237,6 +260,28 @@ class IpVpdFacade
VPD::vpdRecord record,
VPD::vpdKeyword keyword );
+
+ /**
+ * @brief This function compares the specified record/keyword
+ * in CACHE/HARDWARE 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 cmpEecacheToEeprom(TARGETING::Target * i_target,
+ VPD::vpdRecord i_record,
+ VPD::vpdKeyword i_keyword,
+ bool & o_match);
+
/**
* @brief This function compares the specified record/keyword
* in PNOR/SEEPROM and returns the result. A mismatch
@@ -594,6 +639,8 @@ class IpVpdFacade
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
@@ -613,12 +660,38 @@ class IpVpdFacade
* @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,
- VPD::vpdCmdTarget i_location,
- const char* i_record );
+ errlHndl_t fetchData(uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void * o_data,
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location,
+ const char* i_record);
+
+ /**
+ * @brief This function calls the PNOR or EEPROM version of
+ * the fetchData function based on the configInfo
+ *
+ * @param[in] i_byteAddr The offset to be read.
+ *
+ * @param[in] i_numBytes The number of bytes to read.
+ *
+ * @param[out] o_data The data buffer where the data will be placed.
+ *
+ * @param[in] i_target Target device.
+ *
+ * @param[in] i_args The input arguments
+ *
+ * @param[in] i_record String representation of the record.
+ *
+ * @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,
+ input_args_t i_args,
+ const char* i_record);
/**
* @brief This function actually reads the data from PNOR
@@ -653,10 +726,11 @@ class IpVpdFacade
* @return errHndl_t - NULL if successful, otherwise a pointer to the
* error log.
*/
- errlHndl_t fetchDataFromEeprom ( uint64_t i_byteAddr,
- size_t i_numBytes,
- void * o_data,
- TARGETING::Target * i_target );
+ errlHndl_t fetchDataFromEeprom(uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void * o_data,
+ TARGETING::Target * i_target,
+ EEPROM::EEPROM_SOURCE i_eepromSource = EEPROM::AUTOSELECT);
/**
* @brief This function compares 2 ipvpd record values. Used for binary
diff --git a/src/usr/vpd/makefile b/src/usr/vpd/makefile
index 728750fca..9ef60d788 100644
--- a/src/usr/vpd/makefile
+++ b/src/usr/vpd/makefile
@@ -31,7 +31,6 @@ include vpd.mk
#include unique objects
OBJS += vpd.o
OBJS += dimmPres.o
-OBJS += ocmb_spd.o
OBJS += rtvpd_load.o
SUBDIRS += test.d
diff --git a/src/usr/vpd/mvpd.C b/src/usr/vpd/mvpd.C
index 4de720594..242e3bab1 100644
--- a/src/usr/vpd/mvpd.C
+++ b/src/usr/vpd/mvpd.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -38,7 +38,6 @@
#include <vpd/mvpdenums.H>
#include <vpd/vpd_if.H>
#include <i2c/eepromif.H>
-#include <config.h>
#include "mvpd.H"
#include "ipvpd.H"
diff --git a/src/usr/vpd/ocmb_spd.C b/src/usr/vpd/ocmb_spd.C
index c4f8137cc..2767efca7 100644
--- a/src/usr/vpd/ocmb_spd.C
+++ b/src/usr/vpd/ocmb_spd.C
@@ -28,16 +28,24 @@
#include <errl/errlentry.H>
#include <vpd/vpdreasoncodes.H>
+#include "ocmb_spd.H"
+#include "spd.H"
+#include "errlud_vpd.H"
+#include <vpd/vpd_if.H>
+
extern trace_desc_t * g_trac_spd;
+//#define TRACSSCOMP(args...) TRACFCOMP(args)
+#define TRACSSCOMP(args...)
+
+// Namespace alias for targeting
+namespace T = TARGETING;
+
namespace SPD
{
/**
* @brief Handle SPD READ deviceOp to OCMB_CHIP targets
- * This function performs read operations on OCMBs by in turn performing
- * an EEPROM deviceOp on this target, reading the first 2 KB of the OCMB's
- * Primary VPD eeprom and returning it via a buffer
*
* @param[in] i_opType Operation type, see driverif.H
* @param[in] i_target MMIO target
@@ -50,107 +58,327 @@ namespace SPD
* In this function, there is one argument,
* the l_keyword, so far we only support ENTIRE_SPD
* @return errlHndl_t
- *
- * NOTE: ONLY ENTIRE_SPD READ SUPPORTED CURRENTLY
*/
errlHndl_t ocmbSPDPerformOp(DeviceFW::OperationType i_opType,
- TARGETING::Target* i_target,
- void* io_buffer,
- size_t& io_buflen,
- int64_t i_accessType,
- va_list i_args);
+ T::TargetHandle_t i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args);
// Register the perform Op with the routing code for OCMBs.
-DEVICE_REGISTER_ROUTE( DeviceFW::READ,
- DeviceFW::SPD,
- TARGETING::TYPE_OCMB_CHIP,
- ocmbSPDPerformOp );
+DEVICE_REGISTER_ROUTE(DeviceFW::READ,
+ DeviceFW::SPD,
+ 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] i_keyword keyword from spdenums.H to read
- * @param[in/out] io_buffer databuffer SPD will be written to
- * @param[in] i_buflen length of the given data buffer
- *
- * @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(const TARGETING::Target* i_target,
- const uint64_t & i_keyword,
- void* const io_buffer,
- const size_t& i_buflen)
+errlHndl_t ocmbGetSPD(T::TargetHandle_t i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ const VPD::vpdKeyword i_keyword,
+ const uint8_t i_memType,
+ EEPROM::EEPROM_SOURCE i_location)
{
errlHndl_t l_errl = nullptr;
- TRACFCOMP( g_trac_spd,
- ENTER_MRK"ocmbGetSPD()" );
-
- // If any of these asserts fail it is a SW error
- assert(io_buffer != nullptr, "io_buffer is nullptr in ocmbGetSPD");
assert(i_target != nullptr, "i_target is nullptr in ocmbGetSPD");
- assert(i_buflen >= SPD::OCMB_SPD_EFD_COMBINED_SIZE, "Buffer must be at least 2 KB in ocmbGetSPD");
do {
- if(i_keyword != ENTIRE_SPD)
+ const KeywordData* entry = nullptr;
+ l_errl = getKeywordEntry(i_keyword,
+ i_memType,
+ i_target,
+ entry);
+ if (l_errl != nullptr)
+ {
+ break;
+ }
+
+ // Check to be sure entry is not nullptr.
+ if (entry == nullptr)
{
- TRACFCOMP( g_trac_spd,
- "ocmbGetSPD() only entire SPD currently supported, 0x%X is not supported",
- i_keyword);
+ TRACFCOMP(g_trac_spd,
+ ERR_MRK"KeywordData entry pointer is nullptr!");
+
/*@
* @errortype
- * @moduleid VPD::VPD_OCMB_GET_SPD
- * @reasoncode VPD::VPD_NOT_SUPPORTED
- * @userdata1 Keyword Enum
- * @userdata2 Target huid
- * @devdesc Attempted to lookup SPD keyword not supported
- * @custdesc Firmware error during system IPL
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid VPD::VPD_OCMB_GET_SPD
+ * @reasoncode VPD::VPD_NULL_ENTRY
+ * @userdata1[00:31] Buffer Size
+ * @userdata1[32:63] Memory Type
+ * @userdata2[00:31] SPD Keyword
+ * @userdata2[32:63] Target HUID
+ * @devdesc SPD is not valid for this part
+ * @custdesc A problem occurred during the IPL
+ * of the system.
*/
l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_OCMB_GET_SPD,
- VPD::VPD_NOT_SUPPORTED,
- i_keyword,
- i_target->getAttr<TARGETING::ATTR_HUID>(),
- ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ VPD::VPD_OCMB_GET_SPD,
+ VPD::VPD_NULL_ENTRY,
+ TWO_UINT32_TO_UINT64(io_buflen,
+ i_memType),
+ TWO_UINT32_TO_UINT64(i_keyword,
+ T::get_huid(i_target)),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+
+ l_errl->collectTrace( "SPD", 256);
+
break;
+ }
+
+ // Only allow keywords supported by DDIMM
+ l_errl = checkModSpecificKeyword(*entry,
+ i_memType,
+ i_target,
+ VPD::SEEPROM);
+ if (l_errl != nullptr)
+ {
+ break;
+ }
+
+ if (entry->isSpecialCase)
+ {
+ l_errl = spdSpecialCases(*entry,
+ io_buffer,
+ i_target,
+ i_memType,
+ VPD::SEEPROM);
+ if (l_errl != nullptr)
+ {
+ break;
+ }
+ }
+
+ // Support passing in nullptr buffer to return VPD field size.
+ if (io_buffer == nullptr)
+ {
+ io_buflen = entry->length;
+ break;
}
- size_t l_spdReadBufferLen = SPD::OCMB_SPD_EFD_COMBINED_SIZE;
- l_errl = DeviceFW::deviceOp(DeviceFW::READ,
- const_cast<TARGETING::Target*>(i_target),
- io_buffer,
- l_spdReadBufferLen,
- DEVICE_EEPROM_ADDRESS(EEPROM::VPD_PRIMARY,
- 0,
- EEPROM::AUTOSELECT)
- );
+ l_errl = spdCheckSize(io_buflen,
+ entry->length,
+ i_keyword);
- }while(0);
+ if (l_errl != nullptr)
+ {
+ break;
+ }
+
+ l_errl = ocmbFetchData(i_target,
+ entry->offset,
+ entry->length,
+ io_buffer,
+ i_location);
+
+ if (l_errl != nullptr)
+ {
+ break;
+ }
+
+ // Return the size read.
+ io_buflen = entry->length;
+
+ } while(0);
return l_errl;
}
+// ------------------------------------------------------------------
+// ocmbFetchData
+// ------------------------------------------------------------------
+errlHndl_t ocmbFetchData(T::TargetHandle_t i_target,
+ uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void* o_data,
+ EEPROM::EEPROM_SOURCE i_location)
+{
+ errlHndl_t err = nullptr;
+
+ TRACSSCOMP(g_trac_spd,
+ ENTER_MRK"ocmbFetchData()"
+ " i_byteAddr = 0x%x i_numBytes = %d i_location = 0x%x",
+ i_byteAddr, i_numBytes, i_location);
+
+ do
+ {
+ // Get the data
+ err = DeviceFW::deviceOp(DeviceFW::READ,
+ i_target,
+ o_data,
+ i_numBytes,
+ DEVICE_EEPROM_ADDRESS(EEPROM::VPD_PRIMARY,
+ i_byteAddr,
+ i_location));
+ if( err )
+ {
+ TRACFCOMP(g_trac_spd,
+ ERR_MRK"ocmbFetchData(): failing out of deviceOp");
+ break;
+ }
+
+ } while(0);
+
+ TRACSSCOMP(g_trac_spd,
+ EXIT_MRK"ocmbFetchData(): returning %s errors",
+ ((err != nullptr) ? "with" : "with no") );
+
+ return err;
+}
+
+// ------------------------------------------------------------------
+// isValidOcmbDimmType
+// ------------------------------------------------------------------
+bool isValidOcmbDimmType(const uint8_t i_dimmType)
+{
+ return ((SPD_DDR4_TYPE == i_dimmType ));
+}
+
+// ------------------------------------------------------------------
+// getMemType
+// ------------------------------------------------------------------
+errlHndl_t getMemType(uint8_t& o_memType,
+ T::TargetHandle_t i_target,
+ EEPROM::EEPROM_SOURCE i_location)
+{
+ errlHndl_t err = nullptr;
+
+ err = ocmbFetchData(i_target,
+ MEM_TYPE_ADDR,
+ MEM_TYPE_SZ,
+ &o_memType,
+ i_location);
+
+ TRACSSCOMP(g_trac_spd,
+ EXIT_MRK"SPD::getMemType() - MemType: 0x%02x, Error: %s",
+ o_memType,
+ ((err != nullptr) ? "Yes" : "No"));
+
+ return err;
+}
+
// See above for details
errlHndl_t ocmbSPDPerformOp(DeviceFW::OperationType i_opType,
- TARGETING::Target* i_target,
+ T::TargetHandle_t i_target,
void* io_buffer,
size_t& io_buflen,
int64_t i_accessType,
va_list i_args)
{
- errlHndl_t l_errl = nullptr;
- const uint64_t l_keyword = va_arg(i_args, uint64_t);
- l_errl = ocmbGetSPD(i_target, l_keyword, io_buffer, io_buflen);
- return l_errl;
-}
+ errlHndl_t errl = nullptr;
+ const uint64_t keyword = va_arg(i_args, uint64_t);
+
+ TRACSSCOMP(g_trac_spd,
+ ENTER_MRK"ocmbSPDPerformOP(), io_buflen: %d, keyword: 0x%04x",
+ io_buflen, keyword );
+
+ do
+ {
+ // Read the Basic Memory Type
+ uint8_t memType(MEM_TYPE_INVALID);
+ errl = getMemType(memType, i_target, EEPROM::AUTOSELECT);
+
+ if( errl )
+ {
+ break;
+ }
+
+ TRACSSCOMP(g_trac_spd,
+ INFO_MRK"Mem Type: %04x",
+ memType);
+
+ // Check the Basic Memory Type
+ if (isValidOcmbDimmType(memType))
+ {
+ // If the user wanted the Basic memory type, return this now.
+ if(BASIC_MEMORY_TYPE == keyword)
+ {
+ io_buflen = MEM_TYPE_SZ;
+ if (io_buffer != nullptr)
+ {
+ memcpy(io_buffer, &memType, io_buflen);
+ }
+ break;
+ }
+
+ // Read the keyword value
+ errl = ocmbGetSPD(i_target,
+ io_buffer,
+ io_buflen,
+ keyword,
+ memType,
+ EEPROM::AUTOSELECT);
+
+ if( errl )
+ {
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP(g_trac_spd,
+ ERR_MRK"Invalid Basic Memory Type (0x%04x), "
+ "target huid = 0x%x",
+ memType,
+ T::get_huid(i_target));
+
+ /*@
+ * @errlortype
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid VPD::VPD_OCMB_SPD_PERFORM_OP
+ * @reasoncode VPD::VPD_INVALID_BASIC_MEMORY_TYPE
+ * @userdata1[00:31] Basic Memory Type (Byte 2)
+ * @userdata1[32:63] Target HUID
+ * @userdata2 Keyword Requested
+ * @devdesc Invalid Basic Memory Type
+ */
+ errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD::VPD_OCMB_SPD_PERFORM_OP,
+ VPD::VPD_INVALID_BASIC_MEMORY_TYPE,
+ TWO_UINT32_TO_UINT64(memType,
+ T::get_huid(i_target)),
+ keyword);
+ // User could have installed a bad/unsupported dimm
+ errl->addHwCallout(i_target,
+ HWAS::SRCI_PRIORITY_HIGH,
+ HWAS::DECONFIG,
+ HWAS::GARD_NULL);
+
+ errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_LOW);
+
+ errl->addProcedureCallout(HWAS::EPUB_PRC_SP_CODE,
+ HWAS::SRCI_PRIORITY_LOW);
+
+ errl->collectTrace("SPD", 256);
+
+ break;
+ }
+ } while(0);
+
+ // If there is an error, add parameter info to log
+ if ( errl != nullptr )
+ {
+ VPD::UdVpdParms(i_target,
+ io_buflen,
+ 0,
+ keyword,
+ true) // read
+ .addToLog(errl);
+ }
+
+ TRACSSCOMP(g_trac_spd,
+ EXIT_MRK"ocmbSPDPerformOP(): returning %s errors",
+ (errl ? "with" : "with no") );
+
+ return errl;
}
+
+
+} // End of SPD namespace
diff --git a/src/usr/vpd/ocmb_spd.H b/src/usr/vpd/ocmb_spd.H
new file mode 100644
index 000000000..91123dfd4
--- /dev/null
+++ b/src/usr/vpd/ocmb_spd.H
@@ -0,0 +1,102 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/vpd/ocmb_spd.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __OCMB_SPD_H
+#define __OCMB_SPD_H
+
+#include <i2c/eeprom_const.H>
+
+namespace SPD
+{
+
+/*
+ * @brief Read keyword from SPD
+ *
+ * @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.
+ * @param[in] i_location The EEPROM source (CACHE/HARDWARE).
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, error log.
+ */
+errlHndl_t ocmbGetSPD(TARGETING::TargetHandle_t i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ const VPD::vpdKeyword i_keyword,
+ const uint8_t i_memType,
+ EEPROM::EEPROM_SOURCE i_location);
+
+/*
+ * @brief Determine if the given DIMM type is a known DIMM type or not
+ *
+ * @param[in] i_dimmType - The DIMM to verify if valid
+ *
+ * @return boolean - return true if given parameter is a known DIMM type,
+ * false otherwise
+ */
+bool isValidOcmbDimmType(const uint8_t i_dimmType);
+
+/*
+ * @brief This function will read the DIMM memory type for OCMBs.
+ *
+ * @param[out] o_memType - The memory type value to return.
+ *
+ * @param[in] i_target - The target to read data from.
+ *
+ * @param[in] i_eepromSource - The EEPROM source (CACHE/HARDWARE).
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer
+ * to the error log.
+ */
+errlHndl_t getMemType(uint8_t& o_memType,
+ TARGETING::TargetHandle_t i_target,
+ EEPROM::EEPROM_SOURCE i_eepromSource);
+
+/**
+ * @param This function is a wrapper for reading the correct keyword.
+ *
+ * @param[in] i_target The target DDIMM to access.
+ *
+ * @param[in] i_byteAddr The offset into the JEDEC SPD layout.
+ *
+ * @param[in] i_numbytes Number of bytes to read.
+ *
+ * @param[out] o_data The data buffer that will return the data read.
+ *
+ * @param[in] i_location The EEPROM source (CACHE/HARDWARE).
+ *
+ * @return errlHndl_t nullptr if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t ocmbFetchData(TARGETING::TargetHandle_t i_target,
+ uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void* o_data,
+ EEPROM::EEPROM_SOURCE i_location);
+
+}
+
+#endif
diff --git a/src/usr/vpd/pvpd.C b/src/usr/vpd/pvpd.C
index 371a87deb..ae6442554 100644
--- a/src/usr/vpd/pvpd.C
+++ b/src/usr/vpd/pvpd.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -39,9 +39,9 @@
#include <vpd/pvpdenums.H>
#include <vpd/vpd_if.H>
#include <i2c/eepromif.H>
-#include <config.h>
#include "pvpd.H"
#include "cvpd.H"
+#include "dvpd.H"
#include "vpd.H"
#include <initservice/initserviceif.H>
@@ -245,7 +245,7 @@ errlHndl_t nodePresenceDetect(DeviceFW::OperationType i_opType,
}
pvpd_present = VPD::pvpdPresent( i_target );
-#if(defined( CONFIG_PVPD_READ_FROM_HW ) && !defined( __HOSTBOOT_RUNTIME) )
+#if(defined( CONFIG_PVPD_READ_FROM_HW ) && !defined( __HOSTBOOT_RUNTIME) && defined(CONFIG_PVPD_READ_FROM_PNOR))
if( pvpd_present )
{
// Check if the VPD data in the PNOR matches the SEEPROM
diff --git a/src/usr/vpd/pvpd.H b/src/usr/vpd/pvpd.H
index e3e947521..cd6115c26 100644
--- a/src/usr/vpd/pvpd.H
+++ b/src/usr/vpd/pvpd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -40,7 +40,6 @@
#include <vpd/pvpdenums.H>
#include "ipvpd.H"
-#include <config.h>
namespace PVPD
{
diff --git a/src/usr/vpd/rtvpd_load.C b/src/usr/vpd/rtvpd_load.C
index 26ad6f031..f12d23d01 100644
--- a/src/usr/vpd/rtvpd_load.C
+++ b/src/usr/vpd/rtvpd_load.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -108,6 +108,7 @@ errlHndl_t VPD::vpd_load_rt_image(uint64_t & i_vpd_addr)
do
{
+#ifndef CONFIG_SUPPORT_EEPROM_CACHING
void* vptr = reinterpret_cast<void*>(i_vpd_addr);
uint8_t* vpd_ptr = reinterpret_cast<uint8_t*>(vptr);
@@ -136,6 +137,21 @@ errlHndl_t VPD::vpd_load_rt_image(uint64_t & i_vpd_addr)
{
break;
}
+#else
+ // In Axone we store all contents of EEPROMs in EECACHE
+ // so copy the EECACHE pnor section to the space in reserved
+ // memory allocated for VPD.
+ void* vptr = reinterpret_cast<void*>(i_vpd_addr);
+ uint8_t* vpd_ptr = reinterpret_cast<uint8_t*>(vptr);
+
+ err = bld_vpd_image(PNOR::EECACHE,
+ vpd_ptr,
+ VMM_RT_VPD_SIZE);
+ if(err)
+ {
+ break;
+ }
+#endif
} while( 0 );
diff --git a/src/usr/vpd/runtime/rt_vpd.C b/src/usr/vpd/runtime/rt_vpd.C
index ba0335484..ee7fa9f7b 100644
--- a/src/usr/vpd/runtime/rt_vpd.C
+++ b/src/usr/vpd/runtime/rt_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. */
/* */
/* */
@@ -34,7 +34,7 @@
#include <util/runtime/rt_fwreq_helper.H> // firmware_request_helper
#include <targeting/common/util.H>
#include <util/runtime/util_rt.H>
-#include <runtime/rt_targeting.H>
+#include <targeting/runtime/rt_targeting.H>
#include <runtime/interface.h>
#include <initservice/initserviceif.H>
diff --git a/src/usr/vpd/spd.C b/src/usr/vpd/spd.C
index a58398e4a..47dfe0f83 100644
--- a/src/usr/vpd/spd.C
+++ b/src/usr/vpd/spd.C
@@ -48,10 +48,12 @@
#include <vpd/spdenums.H>
#include <algorithm>
#include "spd.H"
+#include "ocmb_spd.H"
#include "spdDDR3.H"
#include "spdDDR4.H"
+#include "spdDDR4_DDIMM.H"
#include "errlud_vpd.H"
-#include <config.h>
+#include "ocmb_spd.H"
// ----------------------------------------------
// Trace definitions
@@ -115,12 +117,27 @@ const bool g_usePNOR = true;
*
* @param[in] i_dimmType - The DIMM to verify if valid
*
-* @return boolean - return true if given paramter is a known DIMM type,
+* @return boolean - return true if given parameter is a known DIMM type,
* false otherwise
*/
bool isValidDimmType ( uint8_t i_dimmType );
/**
+ * @brief Determines if the given DIMM type is a known DIMM type or not by
+ * calling the correct isValidDimmType function for OCMB_SPD or SPD.
+ *
+ * @param[in] i_dimmType - The DIMM to verify if valid
+ *
+ * @param[in] i_eepromType - The eeprom content type of the DIMM
+ *
+ * @return boolean - return true if given paramter is a known DIMM type,
+ * false otherwise
+ */
+bool isValidDimmType(uint8_t i_dimmType,
+ 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
* search time down.
@@ -140,18 +157,42 @@ bool compareEntries ( const KeywordData e1,
/**
* @brief This function will read the DIMM memory type.
*
- * @param[out] o_memType - The memory type value to return.
+ * @param[out] o_memType - The memory type value to return.
*
- * @param[in] i_target - The target to read data from.
+ * @param[in] i_target - The target to read data from.
*
- * @param[in] i_location - The SPD source (PNOR/SEEPROM).
+ * @param[in] i_location - The SPD source (PNOR/SEEPROM).
+ *
+ * @param[in] i_eepromSource - The EEPROM source (CACHE/HARDWARE).
+ * Default to AUTOSELECT.
*
* @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);
+
+/**
+ * @brief This function will read the DIMM memory type by calling the correct
+ * function given the eeprom content type.
+ *
+ * @param[out] o_memType - The memory type value to return.
+ *
+ * @param[in] i_target - The target to read data from.
+ *
+ * @param[in] i_eepromType - The Eeprom content type of the target.
+ *
+ * @param[in] i_eepromSource - The EEPROM source (CACHE/HARDWARE).
+ *
+ * @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.
@@ -173,26 +214,6 @@ errlHndl_t getModType ( modSpecTypes_t & o_modType,
VPD::vpdCmdTarget i_location );
/**
- * @brief This function will scan the table and return the entry
- * corresponding to the keyword being requested.
- *
- * @param[in] i_keyword - The keyword being requested.
- *
- * @param[in] i_memType - The memory type of the target.
- *
- * @param[in] i_target - Target (only used for callouts)
- *
- * @param[out] o_entry - The table entry corresponding to the keyword.
- *
- * @return errlHndl_t - NULL if successful, otherwise a pointer to
- * the error log.
- */
-errlHndl_t getKeywordEntry ( VPD::vpdKeyword i_keyword,
- uint64_t i_memType,
- TARGETING::Target * i_target,
- const KeywordData *& o_entry );
-
-/**
* @brief This function will set the size of SPD for the given target based on
* the DIMM type.
*
@@ -226,6 +247,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
// ------------------------------------------------------------------
@@ -456,11 +500,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};
@@ -516,7 +561,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,
@@ -640,12 +685,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);
@@ -1247,6 +1293,36 @@ errlHndl_t ddr3SpecialCases(const KeywordData & i_kwdData,
return err;
}
+
+errlHndl_t fetchDataFromEepromType(uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void * o_data,
+ TARGETING::Target * i_target,
+ VPD::vpdCmdTarget i_location,
+ TARGETING::EEPROM_CONTENT_TYPE i_eepromType)
+{
+ errlHndl_t errl = nullptr;
+
+ if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_ISDIMM)
+ {
+ errl = spdFetchData(i_byteAddr,
+ i_numBytes,
+ o_data,
+ i_target,
+ i_location);
+ }
+ else if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM)
+ {
+ errl = ocmbFetchData(i_target,
+ i_byteAddr,
+ i_numBytes,
+ o_data,
+ EEPROM::AUTOSELECT);
+ }
+
+ return errl;
+}
+
// ------------------------------------------------------------------
// ddr4SpecialCases
// ------------------------------------------------------------------
@@ -1260,6 +1336,12 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
TRACSSCOMP( g_trac_spd, ENTER_MRK"ddr4SpecialCases()" );
+ auto eepromVpd =
+ i_target->getAttr<TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO>();
+
+ TARGETING::EEPROM_CONTENT_TYPE eepromType =
+ static_cast<TARGETING::EEPROM_CONTENT_TYPE>(eepromVpd.eepromContentType);
+
switch( i_kwdData.keyword )
{
// ==================================================
@@ -1276,12 +1358,14 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
case RMM_CRC:
case MODSPEC_MM_MFR_ID_CODE:
case LRMM_CRC:
+
// Get MSB
- err = spdFetchData( i_kwdData.offset,
- 1, /* Read 1 byte at a time */
- &tmpBuffer[0],
- i_target,
- i_location );
+ err = fetchDataFromEepromType(i_kwdData.offset,
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[0],
+ i_target,
+ i_location,
+ eepromType);
if( err ) break;
@@ -1293,22 +1377,24 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
}
// Get LSB
- err = spdFetchData( (i_kwdData.offset - 1),
- 1, /* Read 1 byte at a time */
- &tmpBuffer[1],
- i_target,
- i_location );
+ err = fetchDataFromEepromType((i_kwdData.offset - 1),
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[1],
+ i_target,
+ i_location,
+ eepromType);
break;
// ==================================================
// 2 byte - MSB with mask then LSB is 2 more than MSB
case TRC_MIN:
// Get MSB
- err = spdFetchData( i_kwdData.offset,
- 1, /* Read 1 byte at a time */
- &tmpBuffer[0],
- i_target,
- i_location );
+ err = fetchDataFromEepromType(i_kwdData.offset,
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[0],
+ i_target,
+ i_location,
+ eepromType);
if( err ) break;
@@ -1320,49 +1406,54 @@ errlHndl_t ddr4SpecialCases(const KeywordData & i_kwdData,
}
// Get LSB
- err = spdFetchData( (i_kwdData.offset + 2),
- 1, /* Read 1 byte at a time */
- &tmpBuffer[1],
- i_target,
- i_location );
+ err = fetchDataFromEepromType((i_kwdData.offset + 2),
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[1],
+ i_target,
+ i_location,
+ eepromType);
break;
// ==================================================
// 4 byte - LSB first, no mask
case CAS_LATENCIES_SUPPORTED_DDR4:
// Get 4th byte
- err = spdFetchData( i_kwdData.offset,
- 1, /* Read 1 byte at a time */
- &tmpBuffer[0],
- i_target,
- i_location );
+ err = fetchDataFromEepromType(i_kwdData.offset,
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[0],
+ i_target,
+ i_location,
+ eepromType);
if( err ) break;
// Get 3rd Byte
- err = spdFetchData( (i_kwdData.offset - 1),
- 1, /* Read 1 byte at a time */
- &tmpBuffer[1],
- i_target,
- i_location );
+ err = fetchDataFromEepromType((i_kwdData.offset - 1),
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[1],
+ i_target,
+ i_location,
+ eepromType);
if( err ) break;
// Get 2nd Byte
- err = spdFetchData( (i_kwdData.offset - 2),
- 1, /* Read 1 byte at a time */
- &tmpBuffer[2],
- i_target,
- i_location );
+ err = fetchDataFromEepromType((i_kwdData.offset - 2),
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[2],
+ i_target,
+ i_location,
+ eepromType);
if( err ) break;
// Get 1st Byte
- err = spdFetchData( (i_kwdData.offset - 3),
- 1, /* Read 1 byte at a time */
- &tmpBuffer[3],
- i_target,
- i_location );
+ err = fetchDataFromEepromType((i_kwdData.offset - 3),
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[3],
+ i_target,
+ i_location,
+ eepromType);
break;
// ==================================================
@@ -1685,12 +1776,6 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
do
{
- // If not a Module Specific keyword, skip this logic
- if( NA == i_kwdData.modSpec )
- {
- break;
- }
-
// Check that a Module Specific keyword is being accessed from a DIMM
// of the correct Module Type.
modSpecTypes_t modType = NA;
@@ -1701,263 +1786,43 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData,
break;
}
- // Check Unbuffered Memory Module (UMM)
- if (UMM == modType)
- {
- if ((UMM != i_kwdData.modSpec) &&
- (ALL != i_kwdData.modSpec) )
- {
- TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
- "Keyword (0x%04x) is not valid with UMM modules!",
- i_kwdData.keyword );
- /*@
- * @errortype
- * @reasoncode VPD::VPD_MOD_SPECIFIC_MISMATCH_UMM
- * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
- * @moduleid VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD
- * @userdata1[0:31] Module Type (byte 3[3:0])
- * @userdata1[32:63] Memory Type (byte 2)
- * @userdata2[0:31] SPD Keyword
- * @userdata2[32:63] Module Specific flag
- * @devdesc Keyword requested was not UMM Module
- * specific.
- * @custdesc A problem occurred during the IPL
- * of the system.
- */
- err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD,
- VPD::VPD_MOD_SPECIFIC_MISMATCH_UMM,
- TWO_UINT32_TO_UINT64( modType, i_memType ),
- TWO_UINT32_TO_UINT64( i_kwdData.keyword,
- i_kwdData.modSpec ) );
-
- // HB code asked for an unsupprted keyword for this Module
- err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
- HWAS::SRCI_PRIORITY_HIGH);
-
- // Or user could have installed a bad/unsupported dimm
- err->addHwCallout( i_target,
- HWAS::SRCI_PRIORITY_LOW,
- HWAS::DECONFIG,
- HWAS::GARD_NULL );
-
- err->collectTrace( "SPD", 256);
-
- break;
- }
- }
- // Check Registered Memory Module (RMM)
- else if (RMM == modType)
- {
- if ((RMM != i_kwdData.modSpec) &&
- (ALL != i_kwdData.modSpec) )
- {
- TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
- "Keyword (0x%04x) is not valid with RMM modules!",
- i_kwdData.keyword );
- /*@
- * @errortype
- * @reasoncode VPD::VPD_MOD_SPECIFIC_MISMATCH_RMM
- * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
- * @moduleid VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD
- * @userdata1[0:31] Module Type (byte 3[3:0])
- * @userdata1[32:63] Memory Type (byte 2)
- * @userdata2[0:31] SPD Keyword
- * @userdata2[32:63] Module Specific flag
- * @devdesc Keyword requested was not RMM Module
- * specific.
- * @custdesc A problem occurred during the IPL
- * of the system.
- */
- err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD,
- VPD::VPD_MOD_SPECIFIC_MISMATCH_RMM,
- TWO_UINT32_TO_UINT64( modType, i_memType ),
- TWO_UINT32_TO_UINT64( i_kwdData.keyword,
- i_kwdData.modSpec ) );
-
- // HB code asked for an unsupprted keyword for this Module
- err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
- HWAS::SRCI_PRIORITY_HIGH);
-
- // Or user could have installed a bad/unsupported dimm
- err->addHwCallout( i_target,
- HWAS::SRCI_PRIORITY_LOW,
- HWAS::DECONFIG,
- HWAS::GARD_NULL );
-
- err->collectTrace( "SPD", 256);
-
- break;
- }
- }
- // Check Clocked Memory Module (CMM)
- else if (CMM == modType)
- {
- if ((CMM != i_kwdData.modSpec) &&
- (ALL != i_kwdData.modSpec) )
- {
- TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
- "Keyword (0x%04x) is not valid with CMM modules!",
- i_kwdData.keyword );
- /*@
- * @errortype
- * @reasoncode VPD::VPD_MOD_SPECIFIC_MISMATCH_CMM
- * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
- * @moduleid VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD
- * @userdata1[0:31] Module Type (byte 3[3:0])
- * @userdata1[32:63] Memory Type (byte 2)
- * @userdata2[0:31] SPD Keyword
- * @userdata2[32:63] Module Specific flag
- * @devdesc Keyword requested was not CMM Module
- * specific.
- * @custdesc A problem occurred during the IPL
- * of the system.
- */
- err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD,
- VPD::VPD_MOD_SPECIFIC_MISMATCH_CMM,
- TWO_UINT32_TO_UINT64( modType, i_memType ),
- TWO_UINT32_TO_UINT64( i_kwdData.keyword,
- i_kwdData.modSpec ) );
-
- // HB code asked for an unsupprted keyword for this Module
- err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
- HWAS::SRCI_PRIORITY_HIGH);
-
- // Or user could have installed a bad/unsupported dimm
- err->addHwCallout( i_target,
- HWAS::SRCI_PRIORITY_LOW,
- HWAS::DECONFIG,
- HWAS::GARD_NULL );
-
- err->collectTrace( "SPD", 256);
-
- break;
- }
- }
- // Check Load Reduction Memory Module (LRMM)
- else if (LRMM == modType)
- {
- if ((LRMM != i_kwdData.modSpec) &&
- (ALL != i_kwdData.modSpec) )
- {
- TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
- "Keyword (0x%04x) is not valid with LRMM modules!",
- i_kwdData.keyword );
- /*@
- * @errortype
- * @reasoncode VPD::VPD_MOD_SPECIFIC_MISMATCH_LRMM
- * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
- * @moduleid VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD
- * @userdata1[0:31] Module Type (byte 3[3:0])
- * @userdata1[32:63] Memory Type (byte 2)
- * @userdata2[0:31] SPD Keyword
- * @userdata2[32:63] Module Specific flag
- * @devdesc Keyword requested was not LRMM Module
- * specific.
- * @custdesc A problem occurred during the IPL
- * of the system.
- */
- err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD,
- VPD::VPD_MOD_SPECIFIC_MISMATCH_LRMM,
- TWO_UINT32_TO_UINT64( modType, i_memType ),
- TWO_UINT32_TO_UINT64( i_kwdData.keyword,
- i_kwdData.modSpec ) );
-
- // HB code asked for an unsupprted keyword for this Module
- err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
- HWAS::SRCI_PRIORITY_HIGH);
-
- // Or user could have installed a bad/unsupported dimm
- err->addHwCallout( i_target,
- HWAS::SRCI_PRIORITY_LOW,
- HWAS::DECONFIG,
- HWAS::GARD_NULL );
-
- err->collectTrace( "SPD", 256);
-
- break;
- }
- }
- else if(DDIMM == modType)
- {
- if ((DDIMM != i_kwdData.modSpec) &&
- (ALL != i_kwdData.modSpec) )
- {
- TRACFCOMP( g_trac_spd, ERR_MRK"checkModSpecificKeyword: "
- "Keyword (0x%04x) is not valid with DDIMM modules!",
- i_kwdData.keyword );
- /*@
- * @errortype
- * @reasoncode VPD::VPD_MOD_SPECIFIC_MISMATCH_DDIMM
- * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
- * @moduleid VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD
- * @userdata1[0:31] Module Type (byte 3[3:0])
- * @userdata1[32:63] Memory Type (byte 2)
- * @userdata2[0:31] SPD Keyword
- * @userdata2[32:63] Module Specific flag
- * @devdesc Keyword requested was not LRMM Module
- * specific.
- * @custdesc A problem occurred during the IPL
- * of the system.
- */
- err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD,
- VPD::VPD_MOD_SPECIFIC_MISMATCH_DDIMM,
- TWO_UINT32_TO_UINT64( modType, i_memType ),
- TWO_UINT32_TO_UINT64( i_kwdData.keyword,
- i_kwdData.modSpec ) );
-
- // HB code asked for an unsupprted keyword for this Module
- err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
- HWAS::SRCI_PRIORITY_HIGH);
-
- // Or user could have installed a bad/unsupported dimm
- err->addHwCallout( i_target,
- HWAS::SRCI_PRIORITY_LOW,
- HWAS::DECONFIG,
- HWAS::GARD_NULL );
-
- err->collectTrace( "SPD", 256);
-
- break;
- }
- }
- else
+ if (!(modType & i_kwdData.modSpec))
{
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",
i_memType,
modType,
i_kwdData.keyword );
+
+ uint32_t udUpper32 = TWO_UINT16_TO_UINT32(modType, i_memType);
+ uint32_t udLower32 = TWO_UINT16_TO_UINT32(i_kwdData.keyword,
+ i_kwdData.modSpec);
+ uint64_t userdata1 = TWO_UINT32_TO_UINT64(udUpper32, udLower32);
+
/*@
* @errortype
- * @reasoncode VPD::VPD_MOD_SPECIFIC_UNSUPPORTED
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD
- * @userdata1 Module Type
- * @userdata2 Memory Type (byte 2)
+ * @reasoncode VPD::VPD_MOD_SPECIFIC_UNSUPPORTED
+ * @userdata1[00:15] Memory Module Type
+ * @userdata1[16:31] Memory Type (byte 2)
+ * @userdata1[32:47] SPD Keyword
+ * @userdata1[48:63] Module Specific Flag
+ * @userdata2 Target HUID
* @devdesc Unsupported Module Type.
* @custdesc A problem occurred during the IPL
* of the system.
*/
err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD,
- VPD::VPD_MOD_SPECIFIC_UNSUPPORTED,
- TWO_UINT32_TO_UINT64( modType, i_memType ),
- TWO_UINT32_TO_UINT64( i_kwdData.keyword,
- i_kwdData.modSpec ) );
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD::VPD_SPD_CHECK_MODULE_SPECIFIC_KEYWORD,
+ VPD::VPD_MOD_SPECIFIC_UNSUPPORTED,
+ userdata1,
+ TARGETING::get_huid(i_target));
// HB code asked for an unsupprted keyword for this Module
err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
@@ -1987,9 +1852,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};
@@ -1997,7 +1863,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",
@@ -2007,6 +1874,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
// ------------------------------------------------------------------
@@ -2018,12 +1936,19 @@ errlHndl_t getModType ( modSpecTypes_t & o_modType,
errlHndl_t err{nullptr};
o_modType = NA;
+ auto eepromVpd =
+ i_target->getAttr<TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO>();
+
+ TARGETING::EEPROM_CONTENT_TYPE eepromType =
+ static_cast<TARGETING::EEPROM_CONTENT_TYPE>(eepromVpd.eepromContentType);
+
uint8_t modTypeVal = 0;
- err = spdFetchData( MOD_TYPE_ADDR,
- MOD_TYPE_SZ,
- &modTypeVal,
- i_target,
- i_location );
+ err = fetchDataFromEepromType(MOD_TYPE_ADDR,
+ MOD_TYPE_SZ,
+ &modTypeVal,
+ i_target,
+ i_location,
+ eepromType);
if (err)
{
@@ -2145,8 +2070,18 @@ errlHndl_t getKeywordEntry ( VPD::vpdKeyword i_keyword,
}
else if ( SPD_DDR4_TYPE == i_memType )
{
- arraySize = (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
- kwdData = ddr4Data;
+ modSpecTypes_t modType = NA;
+ err = getModType(modType, i_target, i_memType, VPD::AUTOSELECT);
+ if (modType == DDIMM)
+ {
+ arraySize = (sizeof(ddr4DDIMMData)/sizeof(ddr4DDIMMData[0]));
+ kwdData = ddr4DDIMMData;
+ }
+ else
+ {
+ arraySize = (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
+ kwdData = ddr4Data;
+ }
}
else
{
@@ -2354,6 +2289,214 @@ void setPartAndSerialNumberAttributes( TARGETING::Target * i_target )
TRACSSCOMP(g_trac_spd, EXIT_MRK"spd.C::setPartAndSerialNumberAttributes()");
}
+/*
+ * @brief Read keyword from SPD by determining which function to call based on
+ * eeprom content type.
+ *
+ * @param[in] i_target target to read data from
+ * @param[in] i_eepromType Eeprom content type of the target.
+ * @param[in] i_keyword keyword from spdenums.H to read
+ * @param[in] i_memType The memory type of this target.
+ * @param[in/out] io_buffer data buffer SPD will be written to
+ * @param[in/out] io_buflen length of the given data buffer
+ * @param[in] i_eepromSource The EEPROM source (CACHE/HARDWARE).
+ *
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, error log.
+ */
+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;
+
+ TRACSSCOMP(g_trac_spd, ENTER_MRK
+ "readFromEepromSource: i_eepromSource %d , i_memType %d, i_eepromType %d",
+ i_eepromSource, i_memType, i_eepromType);
+
+// @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))
+ {
+ TRACFCOMP(g_trac_spd, ERR_MRK
+ "cmpEecacheToEeprom() Invalid DIMM type found in cache copy of eeprom,"
+ " we will not be able to understand contents");
+ 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.
+ TRACFCOMP(g_trac_spd, ERR_MRK"cmpEecacheToEeprom() Invalid DIMM type found in hw copy of eeprom");
+ 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);
+
+ TRACDBIN(g_trac_spd, "Hardware data : ", dataHardware, sizeHardware);
+ TRACDBIN(g_trac_spd, "Cache data : ", dataCache, sizeCache);
+
+ TRACSSCOMP( g_trac_spd, EXIT_MRK"cmpEecacheToEeprom(): returning %s errors. o_match = 0x%X ",
+ (err ? "with" : "with no"), o_match );
+
+ return err;
+ }
+
// ------------------------------------------------------------------
// cmpPnorToSeeprom
// ------------------------------------------------------------------
@@ -2368,17 +2511,37 @@ errlHndl_t cmpPnorToSeeprom ( TARGETING::Target * i_target,
o_match = false;
do
{
- // Read the Basic Memory Type
- uint8_t memType(MEM_TYPE_INVALID);
- err = getMemType( memType,
+ // Read the Basic Memory Type from the Seeprom
+ uint8_t memTypeSeeprom(MEM_TYPE_INVALID);
+ err = getMemType( memTypeSeeprom,
i_target,
- VPD::AUTOSELECT );
+ VPD::SEEPROM );
if( err )
{
break;
}
- if( false == isValidDimmType(memType) )
+ if( false == isValidDimmType(memTypeSeeprom) )
+ {
+ break;
+ }
+
+ // Read the Basic Memory Type from PNOR
+ uint8_t memTypePnor(MEM_TYPE_INVALID);
+ err = getMemType( memTypePnor,
+ i_target,
+ VPD::PNOR );
+ if( err )
+ {
+ break;
+ }
+
+ if( false == isValidDimmType(memTypePnor) )
+ {
+ break;
+ }
+
+ if (memTypeSeeprom != memTypePnor)
{
break;
}
@@ -2386,7 +2549,7 @@ errlHndl_t cmpPnorToSeeprom ( TARGETING::Target * i_target,
// Get the keyword size
const KeywordData* entry = NULL;
err = getKeywordEntry( i_keyword,
- memType,
+ memTypePnor,
i_target,
entry );
if( err )
@@ -2403,7 +2566,7 @@ errlHndl_t cmpPnorToSeeprom ( TARGETING::Target * i_target,
dataPnor,
sizePnor,
i_target,
- memType,
+ memTypePnor,
VPD::PNOR );
if( err )
{
@@ -2420,7 +2583,7 @@ errlHndl_t cmpPnorToSeeprom ( TARGETING::Target * i_target,
dataSeeprom,
sizeSeeprom,
i_target,
- memType,
+ memTypePnor,
VPD::SEEPROM );
if( err )
{
diff --git a/src/usr/vpd/spd.H b/src/usr/vpd/spd.H
index edf7d74c7..f0e1a157b 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
{
@@ -94,13 +96,13 @@ enum
*/
typedef enum
{
- NA = 0x00,
- UMM = 0x01, // Unbuffered Memory Modules
- RMM = 0x02, // Registered Memory Modules
- CMM = 0x04, // Clocked Memory Modules
- LRMM = 0x08, // Load Reduction Memory Modules
- DDIMM = 0x0A,
- ALL = 0xFFFF,
+ NA = 0x00, // Invalid Type
+ UMM = 0x01, // Unbuffered Memory Modules
+ RMM = 0x02, // Registered Memory Modules
+ CMM = 0x04, // Clocked Memory Modules
+ LRMM = 0x08, // Load Reduction Memory Modules
+ DDIMM = 0x10, // Differential DIMM
+ ALL = 0xFFFF,
} modSpecTypes_t;
@@ -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
+ );
/**
@@ -392,6 +404,45 @@ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
int64_t i_accessType,
va_list i_args );
+
+/**
+ * @brief This function will read the DIMM module type.
+ *
+ * @param[out] o_modType - The module type value to return.
+ *
+ * @param[in] i_target - The target to read data from.
+ *
+ * @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_modType,
+ TARGETING::Target * i_target,
+ uint64_t i_memType,
+ VPD::vpdCmdTarget i_location );
+
+/**
+ * @brief This function will scan the table and return the entry
+ * corresponding to the keyword being requested.
+ *
+ * @param[in] i_keyword - The keyword being requested.
+ *
+ * @param[in] i_memType - The memory type of the target.
+ *
+ * @param[in] i_target - Target (only used for callouts)
+ *
+ * @param[out] o_entry - The table entry corresponding to the keyword.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t getKeywordEntry(VPD::vpdKeyword i_keyword,
+ uint64_t i_memType,
+ TARGETING::Target* i_target,
+ const KeywordData* &o_entry );
/**
* @brief This function is used to check the parameters in the SPD data that
* indicate which module specific keywords are valid, and then check that
@@ -457,6 +508,26 @@ errlHndl_t cmpPnorToSeeprom( TARGETING::Target * i_target,
bool &o_match );
/**
+ * @brief This function compares value of the keyword in CACHE/HARDWARE
+ * 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/spdDDR3.H b/src/usr/vpd/spdDDR3.H
index 06fc33aa5..26aa36660 100644
--- a/src/usr/vpd/spdDDR3.H
+++ b/src/usr/vpd/spdDDR3.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -68,74 +68,74 @@ const KeywordData ddr3Data[] =
// Number Case able Spec
// ------------------------------------------------------------------------------------------
// Normal fields supported on both DDR3 and DDR4
- { CRC_EXCLUDE, 0x00, 0x01, 0x80, 0x07, false, false, NA },
- { SPD_BYTES_TOTAL, 0x00, 0x01, 0x70, 0x04, false, false, NA },
- { SPD_BYTES_USED, 0x00, 0x01, 0x0F, 0x00, false, false, NA },
- { SPD_MAJOR_REVISION, 0x01, 0x01, 0xF0, 0x04, false, false, NA },
- { SPD_MINOR_REVISION, 0x01, 0x01, 0x0F, 0x00, false, false, NA },
- { BASIC_MEMORY_TYPE, 0x02, 0x01, 0x00, 0x00, false, false, NA },
- { CUSTOM, 0x03, 0x01, 0x80, 0x07, false, false, NA },
- { MODULE_TYPE, 0x03, 0x01, 0x0F, 0x00, false, false, NA },
- { DENSITY, 0x04, 0x01, 0x0F, 0x00, false, false, NA },
- { ROW_ADDRESS, 0x05, 0x01, 0x38, 0x03, false, false, NA },
- { COL_ADDRESS, 0x05, 0x01, 0x07, 0x00, false, false, NA },
- { MODULE_RANKS, 0x07, 0x01, 0x38, 0x03, false, false, NA },
- { MODULE_DRAM_WIDTH, 0x07, 0x01, 0x07, 0x00, false, false, NA },
- { MODULE_MEMORY_BUS_WIDTH, 0x08, 0x01, 0x1f, 0x00, false, false, NA },
- { MODULE_MEMORY_BUS_WIDTH_EXT, 0x08, 0x01, 0x18, 0x03, false, false, NA },
- { MODULE_MEMORY_BUS_WIDTH_PRI, 0x08, 0x01, 0x07, 0x00, false, false, NA },
- { TCK_MIN, 0x0c, 0x01, 0x00, 0x00, false, false, NA },
- { MIN_CAS_LATENCY, 0x10, 0x01, 0x00, 0x00, false, false, NA },
- { TRCD_MIN, 0x12, 0x01, 0x00, 0x00, false, false, NA },
- { TRP_MIN, 0x14, 0x01, 0x00, 0x00, false, false, NA },
- { TRC_MIN, 0x15, 0x02, 0xF0, 0x04, true, false, NA },
- { TRAS_MIN, 0x15, 0x02, 0x0F, 0x00, false, false, NA },
- { TFAW_MIN, 0x1c, 0x02, 0x0F, 0x00, false, false, NA },
- { SDRAM_OPTIONAL_FEATURES, 0x1e, 0x01, 0x00, 0x00, false, false, NA },
- { SDRAM_THERMAL_REFRESH_OPTIONS, 0x1f, 0x01, 0x00, 0x00, false, false, NA },
- { MODULE_THERMAL_SENSOR, 0x20, 0x01, 0x00, 0x00, false, false, NA },
- { THERMAL_SENSOR_PRESENT, 0x20, 0x01, 0x80, 0x07, false, false, NA },
- { THERMAL_SENSOR_ACCURACY, 0x20, 0x01, 0x7F, 0x00, false, false, NA },
- { SDRAM_DEVICE_TYPE, 0x21, 0x01, 0x80, 0x07, false, false, NA },
- { SDRAM_DIE_COUNT, 0x21, 0x01, 0x70, 0x04, false, false, NA },
- { SDRAM_DEVICE_TYPE_SIGNAL_LOADING, 0x21, 0x01, 0x03, 0x00, false, false, NA },
- { TCKMIN_FINE_OFFSET, 0x22, 0x01, 0x00, 0x00, false, false, NA },
- { TAAMIN_FINE_OFFSET, 0x23, 0x01, 0x00, 0x00, false, false, NA },
- { TRCDMIN_FINE_OFFSET, 0x24, 0x01, 0x00, 0x00, false, false, NA },
- { TRPMIN_FINE_OFFSET, 0x25, 0x01, 0x00, 0x00, false, false, NA },
- { TRCMIN_FINE_OFFSET, 0x26, 0x01, 0x00, 0x00, false, false, NA },
- { MODULE_TYPE_SPECIFIC_SECTION, 0x3c, 0x39, 0x00, 0x00, false, false, NA },
- { MODULE_MANUFACTURER_ID, 0x76, 0x02, 0x00, 0x00, true, false, NA },
- { MODULE_MANUFACTURING_LOCATION, 0x77, 0x01, 0x00, 0x00, false, false, NA },
- { MODULE_MANUFACTURING_DATE, 0x78, 0x02, 0x00, 0x00, false, false, NA },
- { MODULE_SERIAL_NUMBER, 0x7a, 0x04, 0x00, 0x00, false, false, NA },
- { MODULE_PART_NUMBER, 0x80, 0x12, 0x00, 0x00, false, false, NA },
- { DRAM_MANUFACTURER_ID, 0x95, 0x02, 0x00, 0x00, true, false, NA },
- { MANUFACTURER_SPECIFIC_DATA, 0x96, 0x1a, 0x00, 0x00, false, false, NA },
- { DIMM_BAD_DQ_DATA, 0xb0, 0x50, 0x00, 0x00, false, true, NA },
+ { CRC_EXCLUDE, 0x00, 0x01, 0x80, 0x07, false, false, ALL },
+ { SPD_BYTES_TOTAL, 0x00, 0x01, 0x70, 0x04, false, false, ALL },
+ { SPD_BYTES_USED, 0x00, 0x01, 0x0F, 0x00, false, false, ALL },
+ { SPD_MAJOR_REVISION, 0x01, 0x01, 0xF0, 0x04, false, false, ALL },
+ { SPD_MINOR_REVISION, 0x01, 0x01, 0x0F, 0x00, false, false, ALL },
+ { BASIC_MEMORY_TYPE, 0x02, 0x01, 0x00, 0x00, false, false, ALL },
+ { CUSTOM, 0x03, 0x01, 0x80, 0x07, false, false, ALL },
+ { MODULE_TYPE, 0x03, 0x01, 0x0F, 0x00, false, false, ALL },
+ { DENSITY, 0x04, 0x01, 0x0F, 0x00, false, false, ALL },
+ { ROW_ADDRESS, 0x05, 0x01, 0x38, 0x03, false, false, ALL },
+ { COL_ADDRESS, 0x05, 0x01, 0x07, 0x00, false, false, ALL },
+ { MODULE_RANKS, 0x07, 0x01, 0x38, 0x03, false, false, ALL },
+ { MODULE_DRAM_WIDTH, 0x07, 0x01, 0x07, 0x00, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH, 0x08, 0x01, 0x1f, 0x00, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH_EXT, 0x08, 0x01, 0x18, 0x03, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH_PRI, 0x08, 0x01, 0x07, 0x00, false, false, ALL },
+ { TCK_MIN, 0x0c, 0x01, 0x00, 0x00, false, false, ALL },
+ { MIN_CAS_LATENCY, 0x10, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCD_MIN, 0x12, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRP_MIN, 0x14, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRC_MIN, 0x15, 0x02, 0xF0, 0x04, true, false, ALL },
+ { TRAS_MIN, 0x15, 0x02, 0x0F, 0x00, false, false, ALL },
+ { TFAW_MIN, 0x1c, 0x02, 0x0F, 0x00, false, false, ALL },
+ { SDRAM_OPTIONAL_FEATURES, 0x1e, 0x01, 0x00, 0x00, false, false, ALL },
+ { SDRAM_THERMAL_REFRESH_OPTIONS, 0x1f, 0x01, 0x00, 0x00, false, false, ALL },
+ { MODULE_THERMAL_SENSOR, 0x20, 0x01, 0x00, 0x00, false, false, ALL },
+ { THERMAL_SENSOR_PRESENT, 0x20, 0x01, 0x80, 0x07, false, false, ALL },
+ { THERMAL_SENSOR_ACCURACY, 0x20, 0x01, 0x7F, 0x00, false, false, ALL },
+ { SDRAM_DEVICE_TYPE, 0x21, 0x01, 0x80, 0x07, false, false, ALL },
+ { SDRAM_DIE_COUNT, 0x21, 0x01, 0x70, 0x04, false, false, ALL },
+ { SDRAM_DEVICE_TYPE_SIGNAL_LOADING, 0x21, 0x01, 0x03, 0x00, false, false, ALL },
+ { TCKMIN_FINE_OFFSET, 0x22, 0x01, 0x00, 0x00, false, false, ALL },
+ { TAAMIN_FINE_OFFSET, 0x23, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCDMIN_FINE_OFFSET, 0x24, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRPMIN_FINE_OFFSET, 0x25, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCMIN_FINE_OFFSET, 0x26, 0x01, 0x00, 0x00, false, false, ALL },
+ { MODULE_TYPE_SPECIFIC_SECTION, 0x3c, 0x39, 0x00, 0x00, false, false, ALL },
+ { MODULE_MANUFACTURER_ID, 0x76, 0x02, 0x00, 0x00, true, false, ALL },
+ { MODULE_MANUFACTURING_LOCATION, 0x77, 0x01, 0x00, 0x00, false, false, ALL },
+ { MODULE_MANUFACTURING_DATE, 0x78, 0x02, 0x00, 0x00, false, false, ALL },
+ { MODULE_SERIAL_NUMBER, 0x7a, 0x04, 0x00, 0x00, false, false, ALL },
+ { MODULE_PART_NUMBER, 0x80, 0x12, 0x00, 0x00, false, false, ALL },
+ { DRAM_MANUFACTURER_ID, 0x95, 0x02, 0x00, 0x00, true, false, ALL },
+ { MANUFACTURER_SPECIFIC_DATA, 0x96, 0x1a, 0x00, 0x00, false, false, ALL },
+ { DIMM_BAD_DQ_DATA, 0xb0, 0x50, 0x00, 0x00, false, true, ALL },
// Normal fields supported on DDR3 only
- { BANK_ADDRESS_BITS, 0x04, 0x01, 0x70, 0x04, false, false, NA },
- { MODULE_NOMINAL_VOLTAGE, 0x06, 0x01, 0x07, 0x00, false, false, NA },
- { FTB_DIVIDEND, 0x09, 0x01, 0xF0, 0x04, false, false, NA },
- { FTB_DIVISOR, 0x09, 0x01, 0x0F, 0x00, false, false, NA },
- { MTB_DIVIDEND, 0x0a, 0x01, 0x00, 0x00, false, false, NA },
- { MTB_DIVISOR, 0x0b, 0x01, 0x00, 0x00, false, false, NA },
- { CAS_LATENCIES_SUPPORTED, 0x0f, 0x02, 0x7F, 0x00, true, false, NA },
- { TWR_MIN, 0x11, 0x01, 0x00, 0x00, false, false, NA },
- { TRRD_MIN, 0x13, 0x01, 0x00, 0x00, false, false, NA },
- { TRFC_MIN, 0x19, 0x02, 0x00, 0x00, true, false, NA },
- { TWTR_MIN, 0x1a, 0x01, 0x00, 0x00, false, false, NA },
- { TRTP_MIN, 0x1b, 0x01, 0x00, 0x00, false, false, NA },
- { DLL_OFF, 0x1e, 0x01, 0x80, 0x07, false, false, NA },
- { RZQ_7, 0x1e, 0x01, 0x02, 0x01, false, false, NA },
- { RZQ_6, 0x1e, 0x01, 0x01, 0x00, false, false, NA },
- { PASR, 0x1f, 0x01, 0x80, 0x07, false, false, NA },
- { ODTS, 0x1f, 0x01, 0x08, 0x03, false, false, NA },
- { ASR, 0x1f, 0x01, 0x04, 0x02, false, false, NA },
- { ETR_1X, 0x1f, 0x01, 0x02, 0x01, false, false, NA },
- { ETR, 0x1f, 0x01, 0x01, 0x00, false, false, NA },
- { MODULE_CRC, 0x7f, 0x02, 0x00, 0x00, true, false, NA },
- { MODULE_REVISION_CODE, 0x93, 0x02, 0x00, 0x00, true, false, NA },
+ { BANK_ADDRESS_BITS, 0x04, 0x01, 0x70, 0x04, false, false, ALL },
+ { MODULE_NOMINAL_VOLTAGE, 0x06, 0x01, 0x07, 0x00, false, false, ALL },
+ { FTB_DIVIDEND, 0x09, 0x01, 0xF0, 0x04, false, false, ALL },
+ { FTB_DIVISOR, 0x09, 0x01, 0x0F, 0x00, false, false, ALL },
+ { MTB_DIVIDEND, 0x0a, 0x01, 0x00, 0x00, false, false, ALL },
+ { MTB_DIVISOR, 0x0b, 0x01, 0x00, 0x00, false, false, ALL },
+ { CAS_LATENCIES_SUPPORTED, 0x0f, 0x02, 0x7F, 0x00, true, false, ALL },
+ { TWR_MIN, 0x11, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRRD_MIN, 0x13, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRFC_MIN, 0x19, 0x02, 0x00, 0x00, true, false, ALL },
+ { TWTR_MIN, 0x1a, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRTP_MIN, 0x1b, 0x01, 0x00, 0x00, false, false, ALL },
+ { DLL_OFF, 0x1e, 0x01, 0x80, 0x07, false, false, ALL },
+ { RZQ_7, 0x1e, 0x01, 0x02, 0x01, false, false, ALL },
+ { RZQ_6, 0x1e, 0x01, 0x01, 0x00, false, false, ALL },
+ { PASR, 0x1f, 0x01, 0x80, 0x07, false, false, ALL },
+ { ODTS, 0x1f, 0x01, 0x08, 0x03, false, false, ALL },
+ { ASR, 0x1f, 0x01, 0x04, 0x02, false, false, ALL },
+ { ETR_1X, 0x1f, 0x01, 0x02, 0x01, false, false, ALL },
+ { ETR, 0x1f, 0x01, 0x01, 0x00, false, false, ALL },
+ { MODULE_CRC, 0x7f, 0x02, 0x00, 0x00, true, false, ALL },
+ { MODULE_REVISION_CODE, 0x93, 0x02, 0x00, 0x00, true, false, ALL },
// Module Specific fields supported on both DDR3 and DDR4
{ MODSPEC_COM_NOM_HEIGHT_MAX, 0x3c, 0x01, 0x1f, 0x00, false, false, ALL },
{ MODSPEC_COM_MAX_THICK_BACK, 0x3d, 0x01, 0xf0, 0x04, false, false, ALL },
diff --git a/src/usr/vpd/spdDDR4.H b/src/usr/vpd/spdDDR4.H
index 0d732fa92..b29a1043f 100755
--- a/src/usr/vpd/spdDDR4.H
+++ b/src/usr/vpd/spdDDR4.H
@@ -69,76 +69,76 @@ const KeywordData ddr4Data[] =
// ------------------------------------------------------------------------------------------
//
// Normal fields supported on both DDR3 and DDR4
- { SPD_BYTES_TOTAL, 0x00, 0x01, 0x70, 0x04, false, false, NA },
- { SPD_BYTES_USED, 0x00, 0x01, 0x0F, 0x00, false, false, NA },
- { SPD_MAJOR_REVISION, 0x01, 0x01, 0xF0, 0x04, false, false, NA },
- { SPD_MINOR_REVISION, 0x01, 0x01, 0x0F, 0x00, false, false, NA },
- { BASIC_MEMORY_TYPE, 0x02, 0x01, 0x00, 0x00, false, false, NA },
- { CUSTOM, 0x03, 0x01, 0x80, 0x07, false, false, NA },
- { MODULE_TYPE, 0x03, 0x01, 0x0F, 0x00, false, false, NA },
- { DENSITY, 0x04, 0x01, 0x0F, 0x00, false, false, NA },
- { ROW_ADDRESS, 0x05, 0x01, 0x38, 0x03, false, false, NA },
- { COL_ADDRESS, 0x05, 0x01, 0x07, 0x00, false, false, NA },
- { MODULE_RANKS, 0x0c, 0x01, 0x38, 0x03, false, false, NA },
- { MODULE_DRAM_WIDTH, 0x0c, 0x01, 0x07, 0x00, false, false, NA },
- { MODULE_MEMORY_BUS_WIDTH, 0x0d, 0x01, 0x1f, 0x00, false, false, NA },
- { MODULE_MEMORY_BUS_WIDTH_EXT, 0x0d, 0x01, 0x18, 0x03, false, false, NA },
- { MODULE_MEMORY_BUS_WIDTH_PRI, 0x0d, 0x01, 0x07, 0x00, false, false, NA },
- { TCK_MIN, 0x12, 0x01, 0x00, 0x00, false, false, NA },
- { MIN_CAS_LATENCY, 0x18, 0x01, 0x00, 0x00, false, false, NA },
- { TRCD_MIN, 0x19, 0x01, 0x00, 0x00, false, false, NA },
- { TRP_MIN, 0x1a, 0x01, 0x00, 0x00, false, false, NA },
- { TRC_MIN, 0x1b, 0x02, 0xF0, 0x04, true, false, NA },
- { TRAS_MIN, 0x1b, 0x02, 0x0F, 0x00, false, false, NA },
- { TFAW_MIN, 0x24, 0x02, 0x0F, 0x00, false, false, NA },
- { SDRAM_OPTIONAL_FEATURES, 0x07, 0x01, 0x00, 0x00, false, false, NA },
- { SDRAM_THERMAL_REFRESH_OPTIONS, 0x08, 0x01, 0x00, 0x00, false, false, NA },
- { MODULE_THERMAL_SENSOR, 0x0e, 0x01, 0x00, 0x00, false, false, NA },
- { THERMAL_SENSOR_PRESENT, 0x0e, 0x01, 0x80, 0x07, false, false, NA },
- { SDRAM_DEVICE_TYPE , 0x06, 0x01, 0x80, 0x07, false, false, NA },
- { SDRAM_DIE_COUNT, 0x06, 0x01, 0x70, 0x04, false, false, NA },
- { SDRAM_DEVICE_TYPE_SIGNAL_LOADING, 0x06, 0x01, 0x03, 0x00, false, false, NA },
- { TCKMIN_FINE_OFFSET, 0x7d, 0x01, 0x00, 0x00, false, false, NA },
- { TAAMIN_FINE_OFFSET, 0x7b, 0x01, 0x00, 0x00, false, false, NA },
- { TRCDMIN_FINE_OFFSET, 0x7a, 0x01, 0x00, 0x00, false, false, NA },
- { TRPMIN_FINE_OFFSET, 0x79, 0x01, 0x00, 0x00, false, false, NA },
- { TRCMIN_FINE_OFFSET, 0x78, 0x01, 0x00, 0x00, false, false, NA },
- // Note - All data below 128 is common across all DDR4 DIMMs, even DDIMM
- { MODULE_TYPE_SPECIFIC_SECTION, 0x80, 0x80, 0x00, 0x00, false, false, NA },
- { MODULE_MANUFACTURER_ID, 0x141, 0x02, 0x00, 0x00, true, false, NA },
- { MODULE_MANUFACTURING_LOCATION, 0x142, 0x01, 0x00, 0x00, false, false, NA },
- { MODULE_MANUFACTURING_DATE, 0x143, 0x02, 0x00, 0x00, false, false, NA },
- { MODULE_SERIAL_NUMBER, 0x145, 0x04, 0x00, 0x00, false, false, NA },
- { MODULE_PART_NUMBER, 0x149, 0x14, 0x00, 0x00, false, false, NA },
- { DRAM_MANUFACTURER_ID, 0x15f, 0x02, 0x00, 0x00, true, false, NA },
- { MANUFACTURER_SPECIFIC_DATA, 0x161, 0x1d, 0x00, 0x00, false, false, NA },
- { DIMM_BAD_DQ_DATA, 0x180, 0x50, 0x00, 0x00, false, true, NA },
- { MODULE_REVISION_CODE, 0x15d, 0x01, 0x00, 0x00, false, false, NA },
+ { SPD_BYTES_TOTAL, 0x00, 0x01, 0x70, 0x04, false, false, ALL },
+ { SPD_BYTES_USED, 0x00, 0x01, 0x0F, 0x00, false, false, ALL },
+ { SPD_MAJOR_REVISION, 0x01, 0x01, 0xF0, 0x04, false, false, ALL },
+ { SPD_MINOR_REVISION, 0x01, 0x01, 0x0F, 0x00, false, false, ALL },
+ { BASIC_MEMORY_TYPE, 0x02, 0x01, 0x00, 0x00, false, false, ALL },
+ { CUSTOM, 0x03, 0x01, 0x80, 0x07, false, false, ALL },
+ { MODULE_TYPE, 0x03, 0x01, 0x0F, 0x00, false, false, ALL },
+ { DENSITY, 0x04, 0x01, 0x0F, 0x00, false, false, ALL },
+ { ROW_ADDRESS, 0x05, 0x01, 0x38, 0x03, false, false, ALL },
+ { COL_ADDRESS, 0x05, 0x01, 0x07, 0x00, false, false, ALL },
+ { MODULE_RANKS, 0x0c, 0x01, 0x38, 0x03, false, false, ALL },
+ { MODULE_DRAM_WIDTH, 0x0c, 0x01, 0x07, 0x00, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH, 0x0d, 0x01, 0x1f, 0x00, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH_EXT, 0x0d, 0x01, 0x18, 0x03, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH_PRI, 0x0d, 0x01, 0x07, 0x00, false, false, ALL },
+ { TCK_MIN, 0x12, 0x01, 0x00, 0x00, false, false, ALL },
+ { MIN_CAS_LATENCY, 0x18, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCD_MIN, 0x19, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRP_MIN, 0x1a, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRC_MIN, 0x1b, 0x02, 0xF0, 0x04, true, false, ALL },
+ { TRAS_MIN, 0x1b, 0x02, 0x0F, 0x00, false, false, ALL },
+ { TFAW_MIN, 0x24, 0x02, 0x0F, 0x00, false, false, ALL },
+ { SDRAM_OPTIONAL_FEATURES, 0x07, 0x01, 0x00, 0x00, false, false, ALL },
+ { SDRAM_THERMAL_REFRESH_OPTIONS, 0x08, 0x01, 0x00, 0x00, false, false, ALL },
+ { MODULE_THERMAL_SENSOR, 0x0e, 0x01, 0x00, 0x00, false, false, ALL },
+ { THERMAL_SENSOR_PRESENT, 0x0e, 0x01, 0x80, 0x07, false, false, ALL },
+ { SDRAM_DEVICE_TYPE , 0x06, 0x01, 0x80, 0x07, false, false, ALL },
+ { SDRAM_DIE_COUNT, 0x06, 0x01, 0x70, 0x04, false, false, ALL },
+ { SDRAM_DEVICE_TYPE_SIGNAL_LOADING, 0x06, 0x01, 0x03, 0x00, false, false, ALL },
+ { TCKMIN_FINE_OFFSET, 0x7d, 0x01, 0x00, 0x00, false, false, ALL },
+ { TAAMIN_FINE_OFFSET, 0x7b, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCDMIN_FINE_OFFSET, 0x7a, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRPMIN_FINE_OFFSET, 0x79, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCMIN_FINE_OFFSET, 0x78, 0x01, 0x00, 0x00, false, false, ALL },
+ // Note - All data below 128 is common across all DDR4 DIMMs, except DDIMM
+ { MODULE_TYPE_SPECIFIC_SECTION, 0x80, 0x80, 0x00, 0x00, false, false, ALL },
+ { MODULE_MANUFACTURER_ID, 0x141, 0x02, 0x00, 0x00, true, false, ALL },
+ { MODULE_MANUFACTURING_LOCATION, 0x142, 0x01, 0x00, 0x00, false, false, ALL },
+ { MODULE_MANUFACTURING_DATE, 0x143, 0x02, 0x00, 0x00, false, false, ALL },
+ { MODULE_SERIAL_NUMBER, 0x145, 0x04, 0x00, 0x00, false, false, ALL },
+ { MODULE_PART_NUMBER, 0x149, 0x14, 0x00, 0x00, false, false, ALL },
+ { DRAM_MANUFACTURER_ID, 0x15f, 0x02, 0x00, 0x00, true, false, ALL },
+ { MANUFACTURER_SPECIFIC_DATA, 0x161, 0x1d, 0x00, 0x00, false, false, ALL },
+ { DIMM_BAD_DQ_DATA, 0x180, 0x50, 0x00, 0x00, false, true, ALL },
+ { MODULE_REVISION_CODE, 0x15d, 0x01, 0x00, 0x00, false, false, ALL },
// Normal fields supported on DDR4 only
- { BANK_GROUP_BITS, 0x04, 0x01, 0xC0, 0x06, false, false, NA },
- { BANK_ADDRESS_BITS_DDR4, 0x04, 0x01, 0x30, 0x04, false, false, NA },
- { MODULE_NOMINAL_VOLTAGE_DDR4, 0x0b, 0x01, 0x3F, 0x00, false, false, NA },
- { TIMEBASES_MTB , 0x11, 0x01, 0x0C, 0x02, false, false, NA },
- { TIMEBASES_FTB, 0x11, 0x01, 0x03, 0x00, false, false, NA },
- { TCK_MAX, 0x13, 0x01, 0x00, 0x00, false, false, NA },
- { CAS_LATENCIES_SUPPORTED_DDR4, 0x17, 0x04, 0x00, 0x00, true, false, NA },
- { TRFC1_MIN, 0x1f, 0x02, 0x00, 0x00, true, false, NA },
- { TRFC2_MIN, 0x21, 0x02, 0x00, 0x00, true, false, NA },
- { TRFC4_MIN, 0x23, 0x02, 0x00, 0x00, true, false, NA },
- { TRRDS_MIN, 0x26, 0x01, 0x00, 0x00, false, false, NA },
- { TRRDL_MIN, 0x27, 0x01, 0x00, 0x00, false, false, NA },
- { TCCDL_MIN, 0x28, 0x01, 0x00, 0x00, false, false, NA },
- { CONNECTOR_SDRAM_MAP, 0x3C, 0x12, 0x00, 0x00, false, false, NA },
- { TCCDL_FINE_OFFSET, 0x75, 0x01, 0x00, 0x00, false, false, NA },
- { TRRDL_FINE_OFFSET, 0x76, 0x01, 0x00, 0x00, false, false, NA },
- { TRRDS_FINE_OFFSET, 0x77, 0x01, 0x00, 0x00, false, false, NA },
- { TCKMAX_FINE_OFFSET, 0x7c, 0x01, 0x00, 0x00, false, false, NA },
- { BASE_CONFIG_CRC, 0x7f, 0x02, 0x00, 0x00, true, false, NA },
- { DRAM_STEPPING, 0x160, 0x01, 0x00, 0x00, false, false, NA },
- { MANUFACTURING_SECTION_CRC, 0x17f, 0x02, 0x00, 0x00, true, false, NA },
- { NVM_INIT_TIME, 0xCB, 0x01, 0x00, 0x00, false, false, NA },
- { RAW_MODULE_PRODUCT_ID, 0xc0, 0x02, 0x00, 0x00, false, false, NA },
- { RAW_MODULE_MANUFACTURER_ID, 0x140, 0x02, 0x00, 0x00, false, false, NA },
+ { BANK_GROUP_BITS, 0x04, 0x01, 0xC0, 0x06, false, false, ALL },
+ { BANK_ADDRESS_BITS_DDR4, 0x04, 0x01, 0x30, 0x04, false, false, ALL },
+ { MODULE_NOMINAL_VOLTAGE_DDR4, 0x0b, 0x01, 0x3F, 0x00, false, false, ALL },
+ { TIMEBASES_MTB, 0x11, 0x01, 0x0C, 0x02, false, false, ALL },
+ { TIMEBASES_FTB, 0x11, 0x01, 0x03, 0x00, false, false, ALL },
+ { TCK_MAX, 0x13, 0x01, 0x00, 0x00, false, false, ALL },
+ { CAS_LATENCIES_SUPPORTED_DDR4, 0x17, 0x04, 0x00, 0x00, true, false, ALL },
+ { TRFC1_MIN, 0x1f, 0x02, 0x00, 0x00, true, false, ALL },
+ { TRFC2_MIN, 0x21, 0x02, 0x00, 0x00, true, false, ALL },
+ { TRFC4_MIN, 0x23, 0x02, 0x00, 0x00, true, false, ALL },
+ { TRRDS_MIN, 0x26, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRRDL_MIN, 0x27, 0x01, 0x00, 0x00, false, false, ALL },
+ { TCCDL_MIN, 0x28, 0x01, 0x00, 0x00, false, false, ALL },
+ { CONNECTOR_SDRAM_MAP, 0x3C, 0x12, 0x00, 0x00, false, false, ALL },
+ { TCCDL_FINE_OFFSET, 0x75, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRRDL_FINE_OFFSET, 0x76, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRRDS_FINE_OFFSET, 0x77, 0x01, 0x00, 0x00, false, false, ALL },
+ { TCKMAX_FINE_OFFSET, 0x7c, 0x01, 0x00, 0x00, false, false, ALL },
+ { BASE_CONFIG_CRC, 0x7f, 0x02, 0x00, 0x00, true, false, ALL },
+ { DRAM_STEPPING, 0x160, 0x01, 0x00, 0x00, false, false, ALL },
+ { MANUFACTURING_SECTION_CRC, 0x17f, 0x02, 0x00, 0x00, true, false, ALL },
+ { NVM_INIT_TIME, 0xCB, 0x01, 0x00, 0x00, false, false, ALL },
+ { RAW_MODULE_PRODUCT_ID, 0xc0, 0x02, 0x00, 0x00, false, false, ALL },
+ { RAW_MODULE_MANUFACTURER_ID, 0x140, 0x02, 0x00, 0x00, false, false, ALL },
// Module Specific fields supported on both DDR3 and DDR4
{ MODSPEC_COM_NOM_HEIGHT_MAX, 0x80, 0x01, 0x1f, 0x00, false, false, ALL },
{ MODSPEC_COM_MAX_THICK_BACK, 0x81, 0x01, 0xf0, 0x04, false, false, ALL },
diff --git a/src/usr/vpd/spdDDR4_DDIMM.H b/src/usr/vpd/spdDDR4_DDIMM.H
new file mode 100755
index 000000000..38899b88e
--- /dev/null
+++ b/src/usr/vpd/spdDDR4_DDIMM.H
@@ -0,0 +1,141 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/vpd/spdDDR4_DDIMM.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
+/* [+] 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. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __SPDDDR4_DDIMM_H
+#define __SPDDDR4_DDIMM_H
+
+/**
+ * @file spdDDR4_DDIMM.H
+ *
+ * @brief Provides the DDR4 field information for DDIMM
+ *
+ */
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include "spd.H"
+
+namespace SPD
+{
+
+/**
+ * @brief Pre-defined lookup table for DDR4 keywords and the
+ * information needed to read that data from the SPD data.
+ */
+const KeywordData ddr4DDIMMData[] =
+{
+ // ----------------------------------------------------------------------------------
+ // NOTE: This list must remain an ordered list! The Keyword must be in numerical
+ // order (values defined in spdenums.H) to allow efficient searching, a unit
+ // test enforces this.
+ // ----------------------------------------------------------------------------------
+ // Bit order for each byte is [7:0] as defined by the JEDEC spec (little endian)
+ //
+ // For multi-byte fields, the offset specifies the byte that is placed at offset 0 in
+ // the output buffer.
+ // - If SpecialCase=false then the next byte in SPD is placed at the next offset in
+ // the output buffer until complete. Any bitmask/shift only affects the byte at
+ // offset 0
+ // - If SpecialCase=true then spd.C handles the field in a custom way (e.g. working
+ // backwards through SPD bytes).
+ // Typically for a 2-byte field consisting of (LSB,MSB), the offset points to MSB and
+ // it is a SpecialCase where spd.C first copies the MSB to the output buffer then
+ // copies the previous byte (LSB) to the output buffer (big endian).
+ // ------------------------------------------------------------------------------------------
+ // Keyword offset size Bitmsk Shift Spec Writ- Mod
+ // Number Case able Spec
+ // ------------------------------------------------------------------------------------------
+ //
+ // Normal fields supported on both DDR3 and DDR4
+ { SPD_BYTES_TOTAL, 0x00, 0x01, 0x70, 0x04, false, false, ALL },
+ { SPD_BYTES_USED, 0x00, 0x01, 0x0F, 0x00, false, false, ALL },
+ { SPD_MAJOR_REVISION, 0x01, 0x01, 0xF0, 0x04, false, false, ALL },
+ { SPD_MINOR_REVISION, 0x01, 0x01, 0x0F, 0x00, false, false, ALL },
+ { BASIC_MEMORY_TYPE, 0x02, 0x01, 0x00, 0x00, false, false, ALL },
+ { CUSTOM, 0x03, 0x01, 0x80, 0x07, false, false, ALL },
+ { MODULE_TYPE, 0x03, 0x01, 0x0F, 0x00, false, false, ALL },
+ { DENSITY, 0x04, 0x01, 0x0F, 0x00, false, false, ALL },
+ { ROW_ADDRESS, 0x05, 0x01, 0x38, 0x03, false, false, ALL },
+ { COL_ADDRESS, 0x05, 0x01, 0x07, 0x00, false, false, ALL },
+ { MODULE_RANKS, 0x0c, 0x01, 0x38, 0x03, false, false, ALL },
+ { MODULE_DRAM_WIDTH, 0x0c, 0x01, 0x07, 0x00, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH, 0x0d, 0x01, 0x1f, 0x00, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH_EXT, 0x0d, 0x01, 0x18, 0x03, false, false, ALL },
+ { MODULE_MEMORY_BUS_WIDTH_PRI, 0x0d, 0x01, 0x07, 0x00, false, false, ALL },
+ { TCK_MIN, 0x12, 0x01, 0x00, 0x00, false, false, ALL },
+ { MIN_CAS_LATENCY, 0x18, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCD_MIN, 0x19, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRP_MIN, 0x1a, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRC_MIN, 0x1b, 0x02, 0xF0, 0x04, true, false, ALL },
+ { TRAS_MIN, 0x1b, 0x02, 0x0F, 0x00, false, false, ALL },
+ { TFAW_MIN, 0x24, 0x02, 0x0F, 0x00, false, false, ALL },
+ { SDRAM_OPTIONAL_FEATURES, 0x07, 0x01, 0x00, 0x00, false, false, ALL },
+ { SDRAM_THERMAL_REFRESH_OPTIONS, 0x08, 0x01, 0x00, 0x00, false, false, ALL },
+ { MODULE_THERMAL_SENSOR, 0x0e, 0x01, 0x00, 0x00, false, false, ALL },
+ { THERMAL_SENSOR_PRESENT, 0x0e, 0x01, 0x80, 0x07, false, false, ALL },
+ { SDRAM_DEVICE_TYPE , 0x06, 0x01, 0x80, 0x07, false, false, ALL },
+ { SDRAM_DIE_COUNT, 0x06, 0x01, 0x70, 0x04, false, false, ALL },
+ { SDRAM_DEVICE_TYPE_SIGNAL_LOADING, 0x06, 0x01, 0x03, 0x00, false, false, ALL },
+ { TCKMIN_FINE_OFFSET, 0x7d, 0x01, 0x00, 0x00, false, false, ALL },
+ { TAAMIN_FINE_OFFSET, 0x7b, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCDMIN_FINE_OFFSET, 0x7a, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRPMIN_FINE_OFFSET, 0x79, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRCMIN_FINE_OFFSET, 0x78, 0x01, 0x00, 0x00, false, false, ALL },
+ // Note - All data below 128 is common across all DDR4 DIMMs, except DDIMM
+ { MODULE_MANUFACTURER_ID, 0x200, 0x02, 0x00, 0x00, true, false, ALL },
+ { MODULE_SERIAL_NUMBER, 0x205, 0x04, 0x00, 0x00, false, false, ALL },
+ { MODULE_PART_NUMBER, 0x209, 0x1E, 0x00, 0x00, false, false, ALL },
+ { DIMM_BAD_DQ_DATA, 0x280, 0x50, 0x00, 0x00, false, true, ALL },
+ { MODULE_REVISION_CODE, 0x277, 0x01, 0x00, 0x00, false, false, ALL },
+ // Normal fields supported on DDR4 only
+ { BANK_GROUP_BITS, 0x04, 0x01, 0xC0, 0x06, false, false, ALL },
+ { BANK_ADDRESS_BITS_DDR4, 0x04, 0x01, 0x30, 0x04, false, false, ALL },
+ { MODULE_NOMINAL_VOLTAGE_DDR4, 0x0b, 0x01, 0x3F, 0x00, false, false, ALL },
+ { TIMEBASES_MTB, 0x11, 0x01, 0x0C, 0x02, false, false, ALL },
+ { TIMEBASES_FTB, 0x11, 0x01, 0x03, 0x00, false, false, ALL },
+ { TCK_MAX, 0x13, 0x01, 0x00, 0x00, false, false, ALL },
+ { CAS_LATENCIES_SUPPORTED_DDR4, 0x17, 0x04, 0x00, 0x00, true, false, ALL },
+ { TRFC1_MIN, 0x1f, 0x02, 0x00, 0x00, true, false, ALL },
+ { TRFC2_MIN, 0x21, 0x02, 0x00, 0x00, true, false, ALL },
+ { TRFC4_MIN, 0x23, 0x02, 0x00, 0x00, true, false, ALL },
+ { TRRDS_MIN, 0x26, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRRDL_MIN, 0x27, 0x01, 0x00, 0x00, false, false, ALL },
+ { TCCDL_MIN, 0x28, 0x01, 0x00, 0x00, false, false, ALL },
+ { CONNECTOR_SDRAM_MAP, 0x3C, 0x12, 0x00, 0x00, false, false, ALL },
+ { TCCDL_FINE_OFFSET, 0x75, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRRDL_FINE_OFFSET, 0x76, 0x01, 0x00, 0x00, false, false, ALL },
+ { TRRDS_FINE_OFFSET, 0x77, 0x01, 0x00, 0x00, false, false, ALL },
+ { TCKMAX_FINE_OFFSET, 0x7c, 0x01, 0x00, 0x00, false, false, ALL },
+ { BASE_CONFIG_CRC, 0x7f, 0x02, 0x00, 0x00, true, false, ALL },
+ // Module Specific fields supported on DDR4 only
+ { ENTIRE_SPD_WITHOUT_EFD, 0x00, 0x280, 0x00, 0x00, false, false, ALL },
+ { ENTIRE_SPD, 0x00, 0x800, 0x00, 0x00, false, false, ALL },
+ //---------------------------------------------------------------------------------------
+};
+
+
+}; // end SPD namespace
+
+#endif // __SPDDDR4_DDR4_H
diff --git a/src/usr/vpd/test/dvpdtest.H b/src/usr/vpd/test/dvpdtest.H
index b0d62a062..3f16139f3 100755
--- a/src/usr/vpd/test/dvpdtest.H
+++ b/src/usr/vpd/test/dvpdtest.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -37,7 +37,6 @@
#include <errl/errlentry.H>
#include <devicefw/driverif.H>
#include <targeting/common/predicates/predicatectm.H>
-#include <config.h>
#include <vpd/dvpdenums.H>
#include <vpd/vpdreasoncodes.H>
@@ -732,7 +731,7 @@ class DVPDTest: public CxxTest::TestSuite
DVPDTest() : CxxTest::TestSuite()
{
TRACFCOMP( g_trac_vpd, "Starting DVPDTest" );
-#ifdef CONFIG_SECUREBOOT
+#if (defined CONFIG_SECUREBOOT && ! defined CONFIG_AXONE)
#ifndef __HOSTBOOT_RUNTIME
errlHndl_t l_err = loadSecureSection(PNOR::MEMD);
if(l_err)
@@ -746,7 +745,7 @@ class DVPDTest: public CxxTest::TestSuite
~DVPDTest()
{
-#ifdef CONFIG_SECUREBOOT
+#if (defined CONFIG_SECUREBOOT && ! defined CONFIG_AXONE)
#ifndef __HOSTBOOT_RUNTIME
errlHndl_t l_err = unloadSecureSection(PNOR::MEMD);
TRACFCOMP( g_trac_vpd, "Ending DVPDTest" );
diff --git a/src/usr/vpd/test/spdtest.H b/src/usr/vpd/test/spdtest.H
index bd7f6ef5b..a2e4c7b70 100755
--- a/src/usr/vpd/test/spdtest.H
+++ b/src/usr/vpd/test/spdtest.H
@@ -43,6 +43,7 @@
#include <vpd/spdenums.H>
#include "../spdDDR3.H"
#include "../spdDDR4.H"
+#include "../spdDDR4_DDIMM.H"
#include "../spd.H"
extern trace_desc_t* g_trac_spd;
@@ -117,16 +118,31 @@ class SPDTest: public CxxTest::TestSuite
uint8_t memType = 0x0;
err = getMemType( theTarget,
memType );
+ if( err )
+ {
+ fails++;
+ TS_FAIL("testSpdRead- Failure reading Basic memory type!" );
+ errlCommit( err,
+ VPD_COMP_ID );
+ break;
+ }
+ // Get the module type.
+ modSpecTypes_t modType = NA;
+ err = getModType(modType,
+ theTarget,
+ memType,
+ VPD::AUTOSELECT);
if( err )
{
fails++;
- TS_FAIL( "testSpdRead- Failure reading Basic memory type!" );
+ TS_FAIL("testSpdRead- Failure reading memory module type!");
errlCommit( err,
VPD_COMP_ID );
- break;;
+ break;
}
+
for( uint64_t keyword = SPD::SPD_FIRST_NORM_KEYWORD;
keyword <= SPD::SPD_LAST_NORM_KEYWORD; keyword++ )
{
@@ -154,14 +170,29 @@ class SPDTest: public CxxTest::TestSuite
}
else if( SPD_DDR4_TYPE == memType )
{
+ size_t dataSize = (modType == DDIMM)
+ ? (sizeof(ddr4DDIMMData)/sizeof(ddr4DDIMMData[0]))
+ : (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
+
for( entry = 0;
- entry < (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
+ entry < dataSize;
entry++ )
{
- if( keyword == ddr4Data[entry].keyword )
+ if (modType == DDIMM)
{
- theSize = ddr4Data[entry].length;
- break;
+ if( keyword == ddr4DDIMMData[entry].keyword )
+ {
+ theSize = ddr4DDIMMData[entry].length;
+ break;
+ }
+ }
+ else
+ {
+ if( keyword == ddr4Data[entry].keyword )
+ {
+ theSize = ddr4Data[entry].length;
+ break;
+ }
}
}
}
@@ -304,6 +335,21 @@ class SPDTest: public CxxTest::TestSuite
break;
}
+ // Get the module type.
+ modSpecTypes_t modType = NA;
+ err = getModType(modType,
+ theTarget,
+ memType,
+ VPD::AUTOSELECT);
+ if( err )
+ {
+ fails++;
+ TS_FAIL("testSpdRead- Failure reading memory module type!");
+ errlCommit( err,
+ VPD_COMP_ID );
+ break;
+ }
+
// Get the size
if( SPD_DDR3_TYPE == memType )
{
@@ -320,14 +366,29 @@ class SPDTest: public CxxTest::TestSuite
}
else if( SPD_DDR4_TYPE == memType )
{
+ size_t dataSize = (modType == DDIMM)
+ ? (sizeof(ddr4DDIMMData)/sizeof(ddr4DDIMMData[0]))
+ : (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
+
for( uint32_t entry = 0;
- entry < (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
+ entry < dataSize;
entry++ )
{
- if( SPD::DIMM_BAD_DQ_DATA == ddr4Data[entry].keyword )
+ if (modType == DDIMM)
{
- theSize = ddr4Data[entry].length;
- break;
+ if( SPD::DIMM_BAD_DQ_DATA == ddr4DDIMMData[entry].keyword )
+ {
+ theSize = ddr4DDIMMData[entry].length;
+ break;
+ }
+ }
+ else
+ {
+ if( SPD::DIMM_BAD_DQ_DATA == ddr4Data[entry].keyword )
+ {
+ theSize = ddr4Data[entry].length;
+ break;
+ }
}
}
}
@@ -343,6 +404,14 @@ class SPDTest: public CxxTest::TestSuite
break;
}
+ if( 0 == theSize )
+ {
+ // memType not supported or Keyword not supported on
+ // this memType
+ cmds++;
+ break;
+ }
+
// Allocate data buffer
origData = static_cast<uint8_t*>(malloc( theSize ));
@@ -892,6 +961,21 @@ class SPDTest: public CxxTest::TestSuite
break;
}
+ // Get the module type.
+ modSpecTypes_t modType = NA;
+ err = getModType(modType,
+ theTarget,
+ memType,
+ VPD::AUTOSELECT);
+ if( err )
+ {
+ fails++;
+ TS_FAIL("testSpdRead- Failure reading memory module type!");
+ errlCommit( err,
+ VPD_COMP_ID );
+ break;
+ }
+
// The real Keyword read testing
for( uint64_t keyword = SPD::SPD_FIRST_MOD_SPEC;
keyword <= SPD::SPD_LAST_MOD_SPEC; keyword++ )
@@ -922,15 +1006,31 @@ class SPDTest: public CxxTest::TestSuite
}
else if( SPD_DDR4_TYPE == memType )
{
+ size_t dataSize = (modType == DDIMM)
+ ? (sizeof(ddr4DDIMMData)/sizeof(ddr4DDIMMData[0]))
+ : (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
+
for( entry = 0;
- entry < (sizeof(ddr4Data)/sizeof(ddr4Data[0]));
+ entry < dataSize;
entry++ )
{
- if( keyword == ddr4Data[entry].keyword )
+ if (modType == DDIMM)
{
- kwdData = ddr4Data[entry];
- theSize = ddr4Data[entry].length;
- break;
+ if( keyword == ddr4DDIMMData[entry].keyword )
+ {
+ kwdData = ddr4DDIMMData[entry];
+ theSize = ddr4DDIMMData[entry].length;
+ break;
+ }
+ }
+ else
+ {
+ if( keyword == ddr4Data[entry].keyword )
+ {
+ kwdData = ddr4Data[entry];
+ theSize = ddr4Data[entry].length;
+ break;
+ }
}
}
}
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
diff --git a/src/usr/vpd/vpd.mk b/src/usr/vpd/vpd.mk
index d5717e653..aa3333291 100644
--- a/src/usr/vpd/vpd.mk
+++ b/src/usr/vpd/vpd.mk
@@ -34,4 +34,5 @@ OBJS += cvpd.o
OBJS += pvpd.o
OBJS += dvpd.o
OBJS += spd.o
+OBJS += ocmb_spd.o
OBJS += errlud_vpd.o
diff --git a/src/usr/vpd/vpd_common.C b/src/usr/vpd/vpd_common.C
index 0196b8be8..92c4e9294 100644
--- a/src/usr/vpd/vpd_common.C
+++ b/src/usr/vpd/vpd_common.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -156,6 +156,8 @@ bool resolveVpdSource( TARGETING::Target * i_target,
}
}
+ TRACDCOMP(g_trac_vpd,"resolveVpdSource: o_vpdSource = %s" ,o_vpdSource == VPD::PNOR ? "PNOR" : "SEEPROM" );
+
return badConfig;
}
OpenPOWER on IntegriCloud