diff options
Diffstat (limited to 'src/usr/vpd')
-rw-r--r-- | src/usr/vpd/HBconfig | 13 | ||||
-rw-r--r-- | src/usr/vpd/cvpd.C | 1 | ||||
-rw-r--r-- | src/usr/vpd/cvpd.H | 3 | ||||
-rwxr-xr-x | src/usr/vpd/dimmPres.C | 3 | ||||
-rw-r--r-- | src/usr/vpd/dvpd.C | 1 | ||||
-rw-r--r-- | src/usr/vpd/dvpd.H | 3 | ||||
-rw-r--r-- | src/usr/vpd/errlud_vpd.C | 10 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.C | 202 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.H | 108 | ||||
-rw-r--r-- | src/usr/vpd/makefile | 1 | ||||
-rw-r--r-- | src/usr/vpd/mvpd.C | 3 | ||||
-rw-r--r-- | src/usr/vpd/ocmb_spd.C | 368 | ||||
-rw-r--r-- | src/usr/vpd/ocmb_spd.H | 102 | ||||
-rw-r--r-- | src/usr/vpd/pvpd.C | 6 | ||||
-rw-r--r-- | src/usr/vpd/pvpd.H | 3 | ||||
-rw-r--r-- | src/usr/vpd/rtvpd_load.C | 18 | ||||
-rw-r--r-- | src/usr/vpd/runtime/rt_vpd.C | 4 | ||||
-rw-r--r-- | src/usr/vpd/spd.C | 851 | ||||
-rwxr-xr-x | src/usr/vpd/spd.H | 107 | ||||
-rw-r--r-- | src/usr/vpd/spdDDR3.H | 136 | ||||
-rwxr-xr-x | src/usr/vpd/spdDDR4.H | 138 | ||||
-rwxr-xr-x | src/usr/vpd/spdDDR4_DDIMM.H | 141 | ||||
-rwxr-xr-x | src/usr/vpd/test/dvpdtest.H | 7 | ||||
-rwxr-xr-x | src/usr/vpd/test/spdtest.H | 130 | ||||
-rwxr-xr-x | src/usr/vpd/vpd.C | 410 | ||||
-rw-r--r-- | src/usr/vpd/vpd.mk | 1 | ||||
-rw-r--r-- | src/usr/vpd/vpd_common.C | 4 |
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; } |