diff options
author | Bill Schwartz <whs@us.ibm.com> | 2015-02-27 15:41:10 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-05-21 18:00:20 -0500 |
commit | 56a2bf579633fec26b0b6afaec01314a15dddb9d (patch) | |
tree | ea9806eab8006f92437e13935a5bcb79c7cdb8a6 /src | |
parent | 9bd763dd507380adf58bd7d20d0c030706d6e979 (diff) | |
download | talos-hostboot-56a2bf579633fec26b0b6afaec01314a15dddb9d.tar.gz talos-hostboot-56a2bf579633fec26b0b6afaec01314a15dddb9d.zip |
Add support for backplane VPD
Replace the temporary use of mem buf to access planar vpd with new
planar vpd interfaces.
Change-Id: I24cda4d713806330a9f61d588006d63966f92550
RTC: 118373
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/16326
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/devicefw/userif.H | 23 | ||||
-rw-r--r-- | src/include/usr/vpd/cvpdenums.H | 1 | ||||
-rw-r--r-- | src/include/usr/vpd/pvpdenums.H | 96 | ||||
-rw-r--r-- | src/include/usr/vpd/vpd_if.H | 8 | ||||
-rw-r--r-- | src/include/usr/vpd/vpdreasoncodes.H | 4 | ||||
-rw-r--r-- | src/usr/devtree/bld_devtree.C | 85 | ||||
-rw-r--r-- | src/usr/hwas/hwasPlat.C | 6 | ||||
-rw-r--r-- | src/usr/hwas/hwasPlatCallout.C | 6 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 5 | ||||
-rw-r--r-- | src/usr/ipmi/ipmifruinv.C | 502 | ||||
-rw-r--r-- | src/usr/ipmi/ipmifruinvprvt.H | 112 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/target_types.xml | 2 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/target_types_hb.xml | 5 | ||||
-rw-r--r-- | src/usr/vpd/HBconfig | 27 | ||||
-rw-r--r-- | src/usr/vpd/cvpd.C | 36 | ||||
-rw-r--r-- | src/usr/vpd/cvpd.H | 22 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.C | 50 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.H | 22 | ||||
-rw-r--r-- | src/usr/vpd/pvpd.C | 369 | ||||
-rw-r--r-- | src/usr/vpd/pvpd.H | 149 | ||||
-rwxr-xr-x | src/usr/vpd/vpd.C | 17 | ||||
-rw-r--r-- | src/usr/vpd/vpd.H | 1 | ||||
-rw-r--r-- | src/usr/vpd/vpd.mk | 5 |
23 files changed, 1307 insertions, 246 deletions
diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H index 6d041f2ee..eac5366aa 100644 --- a/src/include/usr/devicefw/userif.H +++ b/src/include/usr/devicefw/userif.H @@ -61,6 +61,7 @@ namespace DeviceFW GPIO, LPC, IPMIBT, // As opposed to other phy's + PVPD, LAST_ACCESS_TYPE, }; @@ -166,6 +167,28 @@ namespace DeviceFW static_cast<uint64_t>(( i_location )) /** + * Construct the device addressing parameters for the PVPD device ops. + * @param[in] i_record - The enumeration of the PVPD record to access. + * @param[in] i_keyword - The enumeration of the PVPD keyword, located + * within the i_record Record to access. + */ + #define DEVICE_PVPD_ADDRESS( i_record, i_keyword )\ + DEVICE_PVPD_FORCE_ADDRESS( i_record, i_keyword, VPD::AUTOSELECT ) + + /** + * Construct the device addressing parameters for the PVPD device ops. + * @param[in] i_record - The enumeration of the PVPD record to access. + * @param[in] i_keyword - The enumeration of the PVPD keyword, located + * within the i_record Record to access. + * @param[in] i_location - The location of the data (PNOR/SEEPROM) + see vpd_if.H + */ + #define DEVICE_PVPD_FORCE_ADDRESS( i_record, i_keyword, i_location )\ + DeviceFW::PVPD, static_cast<uint64_t>(( i_record )),\ + static_cast<uint64_t>(( i_keyword )),\ + static_cast<uint64_t>(( i_location )) + + /** * Construct the device addressing parameters for the SCAN device ops. * @param[in] i_ring - The ring address to scan * @param[in] i_ringlen - The length of the ring to scan in bits diff --git a/src/include/usr/vpd/cvpdenums.H b/src/include/usr/vpd/cvpdenums.H index 4b5adb271..79b81093c 100644 --- a/src/include/usr/vpd/cvpdenums.H +++ b/src/include/usr/vpd/cvpdenums.H @@ -45,7 +45,6 @@ namespace CVPD OPFR = 0x05, VNDR = 0x06, SPDX = 0x07, - OSYS = 0x08, // Last Record CVPD_LAST_RECORD, CVPD_TEST_RECORD, // Test purposes ONLY! diff --git a/src/include/usr/vpd/pvpdenums.H b/src/include/usr/vpd/pvpdenums.H new file mode 100644 index 000000000..acf3bbd22 --- /dev/null +++ b/src/include/usr/vpd/pvpdenums.H @@ -0,0 +1,96 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/vpd/pvpdenums.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* [+] 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 __PVPDENUMS_H +#define __PVPDENUMS_H + +#include <vpd/ipvpdenums.H> + +namespace PVPD +{ + + /** + * @brief Enumeration for the PVPD Records that contain + * the keyword enumerations below. + * + */ + enum pvpdRecord + { + PVPD_FIRST_RECORD = 0x00, + VINI = PVPD_FIRST_RECORD, + OSYS = 0x01, + OPFR = 0x02, + VNDR = 0x03, + // Last Record + PVPD_LAST_RECORD, + PVPD_TEST_RECORD, // Test purposes ONLY! + + //Start common IPVPD enums + PVPD_INVALID_RECORD = IPVPD::INVALID_RECORD, + }; + + /** + * @brief Enumerations for PVPD keywords that can be + * accessed in the PVPD. + */ + enum pvpdKeyword + { + PVPD_FIRST_KEYWORD = 0x00, + pdI = PVPD_FIRST_KEYWORD, + B3 = 0x01, + B4 = 0x02, + B7 = 0x03, + CC = 0x04, + CE = 0x05, + CT = 0x06, + DR = 0x07, + ET = 0x08, + FN = 0x09, + HE = 0x0a, + HW = 0x0b, + IN = 0x0c, + MM = 0x0d, + PF = 0x0e, + PN = 0x0f, + RT = 0x10, + SN = 0x11, + SS = 0x12, + VD = 0x13, + VN = 0x14, + VP = 0x15, + VS = 0x16, + VZ = 0x17, + + // Last Keyword + PVPD_LAST_KEYWORD, + PVPD_TEST_KEYWORD, // Test purposes ONLY! + + //Start common IPVPD enums + FULL_RECORD = IPVPD::FULL_RECORD, + PVPD_INVALID_KEYWORD = IPVPD::INVALID_KEYWORD, + }; + +}; // end PVPD + +#endif diff --git a/src/include/usr/vpd/vpd_if.H b/src/include/usr/vpd/vpd_if.H index 0b3298a80..d3915ee6a 100644 --- a/src/include/usr/vpd/vpd_if.H +++ b/src/include/usr/vpd/vpd_if.H @@ -71,6 +71,14 @@ namespace VPD bool cvpdPresent ( TARGETING::Target * i_target ); /** + * @brief This function checks to see if the given pvpd target + * is present + * @param[in] i_target - Target device to search for pvpd + * @return bool - true if pvpd is present, false if it is not. + */ + bool pvpdPresent ( TARGETING::Target * i_target ); + + /** * @brief This function checks if the PNOR cache for this target is in * sync with the SEEPROM, if not it loads the PNOR cache from SEEPROM. * @param[in] i_target - Target device diff --git a/src/include/usr/vpd/vpdreasoncodes.H b/src/include/usr/vpd/vpdreasoncodes.H index 88668b70c..2cfe8a68a 100644 --- a/src/include/usr/vpd/vpdreasoncodes.H +++ b/src/include/usr/vpd/vpdreasoncodes.H @@ -61,6 +61,9 @@ enum vpdModuleId VPD_IPVPD_LOAD_PNOR = 0x33, VPD_IPVPD_GET_RECORD_LIST_SEEPROM = 0x34, + // PVPD + VPD_PVPD_PRESENCEDETECT = 0x50, + // DIMM SPD VPD_SPD_GET_KEYWORD_VALUE = 0x61, VPD_SPD_GET_VALUE = 0x62, @@ -131,6 +134,7 @@ enum vpdReasonCode VPD_UNEXPECTED_TARGET_TYPE = VPD_COMP_ID | 0x33, VPD_WRITE_DEST_UNRESOLVED = VPD_COMP_ID | 0x34, VPD_CACHE_SIZE_EXCEEDED = VPD_COMP_ID | 0x35, + VPD_INVALID_LENGTH = VPD_COMP_ID | 0x36, }; diff --git a/src/usr/devtree/bld_devtree.C b/src/usr/devtree/bld_devtree.C index a8ece978a..a311efe04 100644 --- a/src/usr/devtree/bld_devtree.C +++ b/src/usr/devtree/bld_devtree.C @@ -45,7 +45,7 @@ #include <fsi/fsiif.H> #include <config.h> #include <devicefw/userif.H> -#include <vpd/cvpdenums.H> +#include <vpd/pvpdenums.H> #include <i2c/i2cif.H> #include <i2c/eepromif.H> #include <ipmi/ipmisensor.H> @@ -351,12 +351,9 @@ void add_i2c_info( const TARGETING::Target* i_targ, } else if( l_type == TARGETING::TYPE_MEMBUF ) { - //@fixme-RTC:118373-Remove Hab/Palm workaround - // once node vpd is supported - sprintf( l_label, "system-vpd" ); - /*sprintf( l_label, "memb-vpd-%d", + sprintf( l_label, "memb-vpd-%d", eep2->assocTarg - ->getAttr<TARGETING::ATTR_POSITION>() );*/ + ->getAttr<TARGETING::ATTR_POSITION>() ); } else if( l_type == TARGETING::TYPE_DIMM ) { @@ -1054,39 +1051,46 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree) 3) Default to 'unknown' */ bool foundvpd = false; - // TODO RTC 118373 -- update to account for firestone/memory riser - TARGETING::TargetHandleList l_membTargetList; - getAllChips(l_membTargetList, TYPE_MEMBUF); - - //if can't find a centaur for the CVPD, default to unknown - if (l_membTargetList.size()) + TARGETING::TargetHandleList l_nodeTargetList; + PredicateCTM predNode(CLASS_ENC, TYPE_NODE); + PredicateHwas predFunctional; + predFunctional.functional(true); + PredicatePostfixExpr nodeCheckExpr; + nodeCheckExpr.push(&predNode).push(&predFunctional).And(); + + targetService().getAssociated(l_nodeTargetList, sys, + TargetService::CHILD, TargetService::IMMEDIATE, + &nodeCheckExpr); + + //if can't find a node for the PVPD, default to unknown + if (l_nodeTargetList.size()) { - TARGETING::Target * l_pMem = l_membTargetList[0]; + TARGETING::Target * l_pNode = l_nodeTargetList[0]; size_t vpdSize = 0x0; // Note: First read with NULL for o_buffer sets vpdSize to the // correct length - errhdl = deviceRead( l_pMem, + errhdl = deviceRead( l_pNode, NULL, vpdSize, - DEVICE_CVPD_ADDRESS( CVPD::OSYS, - CVPD::MM )); + DEVICE_PVPD_ADDRESS( PVPD::OSYS, + PVPD::MM )); if(errhdl) { TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't get OSYS:MM size for HUID=0x%.8X", - TARGETING::get_huid(l_pMem)); + TARGETING::get_huid(l_pNode)); // Try the OPFR record - errlHndl_t opfr_errhdl = deviceRead( l_pMem, + errlHndl_t opfr_errhdl = deviceRead( l_pNode, NULL, vpdSize, - DEVICE_CVPD_ADDRESS( CVPD::OPFR, - CVPD::DR )); + DEVICE_PVPD_ADDRESS( PVPD::OPFR, + PVPD::DR )); if(opfr_errhdl) { TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't get OPFR:DR size for HUID=0x%.8X", - TARGETING::get_huid(l_pMem)); + TARGETING::get_huid(l_pNode)); delete opfr_errhdl; //delete OPFR log, VPD is just bad } else @@ -1095,16 +1099,16 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree) errhdl = NULL; char drBuf[vpdSize+1]; memset(&drBuf, 0x0, (vpdSize+1)); //null terminated str - errhdl = deviceRead( l_pMem, + errhdl = deviceRead( l_pNode, reinterpret_cast<void*>( &drBuf ), vpdSize, - DEVICE_CVPD_ADDRESS( CVPD::OPFR, - CVPD::DR )); + DEVICE_PVPD_ADDRESS( PVPD::OPFR, + PVPD::DR )); if(errhdl) { TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't read OPFR:DR for HUID=0x%.8X", - TARGETING::get_huid(l_pMem)); + TARGETING::get_huid(l_pNode)); } else { @@ -1117,16 +1121,16 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree) { char mmBuf[vpdSize+1]; memset(&mmBuf, 0x0, (vpdSize+1)); //ensure null terminated str - errhdl = deviceRead( l_pMem, + errhdl = deviceRead( l_pNode, reinterpret_cast<void*>( &mmBuf ), vpdSize, - DEVICE_CVPD_ADDRESS( CVPD::OSYS, - CVPD::MM )); + DEVICE_PVPD_ADDRESS( PVPD::OSYS, + PVPD::MM )); if(errhdl) { TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't read OSYS:MM for HUID=0x%.8X", - TARGETING::get_huid(l_pMem)); + TARGETING::get_huid(l_pNode)); } else { @@ -1153,42 +1157,40 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree) 1) OSYS:SS 2) Default to 'unavailable' */ - // TODO RTC 118373 -- update to account for firestone/memory riser foundvpd = false; - if( l_membTargetList.size() ) + if( l_nodeTargetList.size() ) { - // TODO RTC 118373 - Should be able to read from attribute - TARGETING::Target * l_pMem = l_membTargetList[0]; + TARGETING::Target * l_pNode = l_nodeTargetList[0]; size_t vpdSize = 0x0; // Note: First read with NULL for o_buffer sets vpdSize to the // correct length - errhdl = deviceRead( l_pMem, + errhdl = deviceRead( l_pNode, NULL, vpdSize, - DEVICE_CVPD_ADDRESS( CVPD::OSYS, - CVPD::SS )); + DEVICE_PVPD_ADDRESS( PVPD::OSYS, + PVPD::SS )); if(errhdl) { TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't get OSYS:SS size for HUID=0x%.8X", - TARGETING::get_huid(l_pMem)); + TARGETING::get_huid(l_pNode)); // Note - not supporting old vpd versions without OSYS here } else { char ssBuf[vpdSize+1]; memset(&ssBuf, 0x0, (vpdSize+1)); //ensure null terminated str - errhdl = deviceRead( l_pMem, + errhdl = deviceRead( l_pNode, reinterpret_cast<void*>( &ssBuf ), vpdSize, - DEVICE_CVPD_ADDRESS( CVPD::OSYS, - CVPD::SS )); + DEVICE_PVPD_ADDRESS( PVPD::OSYS, + PVPD::SS )); if(errhdl) { TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't read OSYS:SS for HUID=0x%.8X", - TARGETING::get_huid(l_pMem)); + TARGETING::get_huid(l_pNode)); } else { @@ -1205,7 +1207,6 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree) delete errhdl; errhdl = NULL; } - if( !foundvpd ) //serial number not found, default to unavailable { i_dt->addPropertyString(rootNode, "system-id", "unavailable"); diff --git a/src/usr/hwas/hwasPlat.C b/src/usr/hwas/hwasPlat.C index 80c36f95d..ef631b50a 100644 --- a/src/usr/hwas/hwasPlat.C +++ b/src/usr/hwas/hwasPlat.C @@ -421,9 +421,13 @@ errlHndl_t platPresenceDetect(TargetHandleList &io_targets) HWAS_DBG("pTarget %.8X - detected present", pTarget->getAttr<ATTR_HUID>()); - // on to the next target + // If there is planar VPD, then don't skip the presence detect. + // The presence detect will log any problems and load pnor. +#if !defined(CONFIG_HAVE_PVPD) + // on to the next target if there is no Planar VPD pTarget_it++; continue; +#endif } // call deviceRead() to see if they are present diff --git a/src/usr/hwas/hwasPlatCallout.C b/src/usr/hwas/hwasPlatCallout.C index 0f15082a7..03756a85f 100644 --- a/src/usr/hwas/hwasPlatCallout.C +++ b/src/usr/hwas/hwasPlatCallout.C @@ -122,10 +122,12 @@ errlHndl_t platHandleHWCallout( } // switch i_deconfigState // check to see if this target is the master processor - // and if it's been deconfigured. + // and if it's being deconfigured. + // NOTE: will be non-functional early in IPL before discovery complete. TARGETING::Target *l_masterProc; TARGETING::targetService().masterProcChipTargetHandle(l_masterProc); - if (i_pTarget == l_masterProc) + if ( (i_pTarget == l_masterProc) && + (NO_DECONFIG != i_deconfigState) ) { const TARGETING::HwasState hwasState = l_masterProc->getAttr<TARGETING::ATTR_HWAS_STATE>(); diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index 372fcc75a..b2e1c90e3 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -97,6 +97,11 @@ DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, TARGETING::TYPE_MEMBUF, eepromPerformOp ); +// Register the perform Op with the routing code for Nodes. +DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, + DeviceFW::EEPROM, + TARGETING::TYPE_NODE, + eepromPerformOp ); // ------------------------------------------------------------------ // eepromPerformOp diff --git a/src/usr/ipmi/ipmifruinv.C b/src/usr/ipmi/ipmifruinv.C index cc2f06ad9..49c5e7e1d 100644 --- a/src/usr/ipmi/ipmifruinv.C +++ b/src/usr/ipmi/ipmifruinv.C @@ -29,6 +29,7 @@ #include <devicefw/userif.H> #include <vpd/spdenums.H> #include <vpd/cvpdenums.H> +#include <vpd/pvpdenums.H> #include <targeting/common/commontargeting.H> #include <targeting/common/utilFilter.H> #include <errl/errlmanager.H> @@ -51,7 +52,17 @@ inline static bool comparePairs( const std::pair<TARGETING::TargetHandle_t, uint8_t>& i_lhs, const std::pair<TARGETING::TargetHandle_t, uint8_t>& i_rhs) { - return (i_lhs.second < i_rhs.second); + bool l_compare = i_lhs.second < i_rhs.second; + + // in case of a tie, if the left is a Node, sort it first. + if (i_lhs.second == i_rhs.second) + { + if (TARGETING::TYPE_NODE==i_lhs.first->getAttr<TARGETING::ATTR_TYPE>()) + { + l_compare = true; + } + } + return l_compare; } IpmiFruInv::IpmiFruInv(TARGETING::TargetHandle_t i_target) @@ -82,7 +93,14 @@ IpmiFruInv *IpmiFruInv::Factory(TARGETING::TargetHandleList i_targets, l_fru = new procIpmiFruInv(l_target, i_updateData); break; case TARGETING::TYPE_MEMBUF: - // @todo-RTC:117702 + // A memory riser card will have a mem buff with a distinct FRU ID + l_fru = new membufIpmiFruInv(l_target, i_targets, i_updateData); + break; + case TARGETING::TYPE_NODE: + // When the planar eeprom is shared for planar vpd and memory vpd, + // the node and membufs will have the same FRU ID. The node has + // been sorted ahead of the membufs. The membufs are extra targets + // for their ECIDs. l_fru = new backplaneIpmiFruInv(l_target, i_targets, i_updateData); break; case TARGETING::TYPE_SYS: @@ -425,11 +443,11 @@ errlHndl_t isdimmIpmiFruInv::buildProductInfoArea(std::vector<uint8_t> &io_data) io_data.push_back(uint8_t(0)); // Empty FRU File ID bytes io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS); - //Finalize section formatting - postFormatProcessing(io_data); - } while (0); + //Finalize section formatting + postFormatProcessing(io_data); + if (l_errl) { TRACFCOMP(g_trac_ipmi,"isdimIpmiFruInv::buildProductInfoArea - Errors " @@ -580,11 +598,11 @@ errlHndl_t procIpmiFruInv::buildBoardInfoArea(std::vector<uint8_t> &io_data) //Indicate end of custom fields io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS); - //Complete formatting for this data record - postFormatProcessing(io_data); - } while (0); + //Complete formatting for this data record + postFormatProcessing(io_data); + if (l_errl) { TRACFCOMP(g_trac_ipmi,"buildBoardInfoArea - Errors Collecting ISDimm " @@ -610,64 +628,18 @@ errlHndl_t procIpmiFruInv::buildMultiRecordInfoArea( errlHndl_t procIpmiFruInv::addVpdData(std::vector<uint8_t> &io_data, uint8_t i_record, uint8_t i_keyword, - bool i_ascii) + bool i_ascii, + bool i_typeLengthByte) { - size_t l_vpdSize = 0; errlHndl_t l_errl = NULL; - do { - - //First get size of data by passing NULL - l_errl = deviceRead(iv_target, - NULL, - l_vpdSize, - DEVICE_MVPD_ADDRESS(i_record, i_keyword)); - - if (l_errl) - { - TRACFCOMP(g_trac_ipmi,"procIpmiFruInv::addVpdData - Error while " - "reading MVPD keyword size"); - break; - } - - //Assert if vpd field is too large to fit in IPMI fru inventory format - assert(l_vpdSize < IPMIFRUINV::TYPELENGTH_BYTE_ASCII); - - if (l_vpdSize > 0) - { - //Determine how big data is and expand it to handle the soon to - //be read VPD data - uint8_t l_offset = io_data.size(); - io_data.resize(l_offset + 1 + l_vpdSize); - - //Add on the data to the type/length byte indicating it is ascii - // otherwise leave it as binary - if (i_ascii) - { - io_data.at(l_offset) = l_vpdSize - + IPMIFRUINV::TYPELENGTH_BYTE_ASCII; - } - else - { - io_data.at(l_offset) = l_vpdSize; - } - - //Read the VPD data directly into fru inventory data buffer - l_errl = deviceRead(iv_target,&io_data[l_offset+1],l_vpdSize, - DEVICE_MVPD_ADDRESS(i_record, i_keyword)); - } - else - { - TRACFCOMP(g_trac_ipmi,"procIpmiFruInv::addVpdData - " - " No size returned for MVPD keyword"); - } - } while(0); - - if (l_errl) - { - TRACFCOMP(g_trac_ipmi, "addVpdData - Error acquiring data from Vpd."); - } - + l_errl = addCommonVpdData(iv_target, + io_data, + DeviceFW::MVPD, + i_record, + i_keyword, + i_ascii, + i_typeLengthByte); return l_errl; } @@ -699,8 +671,7 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea( preFormatProcessing(io_data, false); //Set Chassis Enclosure Type - Not Ascii // Also, do not include type/length byte - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OSYS, CVPD::ET, false, false); + l_errl = addVpdData(io_data, PVPD::OSYS, PVPD::ET, false, false); //Support Legacy VPD without OSYS record if (l_errl) @@ -714,12 +685,10 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea( //Set default chassis type io_data.push_back(IPMIFRUINV::DEFAULT_CHASSIS_TYPE); //Set chassis part number - ascii formatted field - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VP, true); + l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VP, true); if (l_errl) { break; } //Set chassis serial number - ascii formatted field - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VS, true); + l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VS, true); if (l_errl) { break; } } else @@ -728,13 +697,11 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea( " Using NEW OSYS RECORD FOR Chassis VPD Data"); //Set chassis part number - ascii formatted field - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OSYS, CVPD::MM, true); + l_errl = addVpdData(io_data, PVPD::OSYS, PVPD::MM, true); if (l_errl) { break; } //Set chassis serial number - ascii formatted field - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OSYS, CVPD::SS, true); + l_errl = addVpdData(io_data, PVPD::OSYS, PVPD::SS, true); if (l_errl) { break; } } @@ -743,10 +710,11 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea( io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL); io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS); - //Complete record data formatting - postFormatProcessing(io_data); } while (0); + //Complete record data formatting + postFormatProcessing(io_data); + if (l_errl) { TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::buildChassisInfoArea - " @@ -771,67 +739,39 @@ errlHndl_t backplaneIpmiFruInv::buildBoardInfoArea( io_data.push_back(0); //Set Vendor Name - ascii formatted data - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VN, true); + l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VN, true); if (l_errl) { break; } //Set Product Name - ascii formatted data - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::DR, true); + l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::DR, true); if (l_errl) { break; } //Set Product Serial number - ascii formatted data - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VS, true); + //TODO RTC:117702 use attribute when 122890 is available + l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VS, true); if (l_errl) { break; } //Set Product Part number - ascii formatted data - //@fixme RTC Story 118373 - l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VP, true); - if (l_errl) { break; } + //TODO RTC:117702 use attribute when 122890 is available + l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VP, true); //Push Fru File ID Byte - NULL io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL); - bool l_setCustomData = false; - // Check if we should add ECID - for (TARGETING::TargetHandleList::const_iterator extraTargets_it = - iv_extraTargets.begin(); - extraTargets_it != iv_extraTargets.end(); - ++extraTargets_it - ) + //Only set the ECID Data during an update scenario + if (iv_isUpdate == true) { - TARGETING::TargetHandle_t l_extraTarget = *extraTargets_it; - - //Only set the ECID Data during an update scenario - if (iv_isUpdate == true && - (l_extraTarget->getAttr<TARGETING::ATTR_TYPE>() == - TARGETING::TYPE_MEMBUF)) - { - TARGETING::ATTR_ECID_type ecidInfo; - bool getEcid = - l_extraTarget->tryGetAttr<TARGETING::ATTR_ECID>(ecidInfo); - if (getEcid) - { - l_setCustomData = true; - addEcidData(l_extraTarget, ecidInfo, io_data); - } - } + customEcidData (iv_extraTargets, io_data); } - //If no Custom data was sent, an Empty Byte is needed - if (!l_setCustomData) - { - io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL); - } //Indicate End of Custom Fields io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS); - //Complete record data formatting - postFormatProcessing(io_data); - } while (0); + //Complete record data formatting + postFormatProcessing(io_data); + if (l_errl) { TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::buildBoardInfoArea - " @@ -860,74 +800,17 @@ errlHndl_t backplaneIpmiFruInv::addVpdData(std::vector<uint8_t> &io_data, uint8_t i_keyword, bool i_ascii, bool i_typeLengthByte) + { - size_t l_vpdSize = 0; errlHndl_t l_errl = NULL; - do { - //First get size of data with NULL parameter - l_errl = deviceRead(iv_target, - NULL, - l_vpdSize, - //@fixme RTC Story 118373 - DEVICE_CVPD_ADDRESS(i_record, i_keyword)); - - if (l_errl) - { - TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::addVpdData - Error " - "while reading CVPD keyword size"); - break; - } - - //Assert if vpd field is too large to fit in IPMI fru inventory format - assert(l_vpdSize < IPMIFRUINV::TYPELENGTH_BYTE_ASCII); - - if (l_vpdSize > 0) - { - uint8_t l_offset = 0; - //Add on the typelength byte if requested - if (i_typeLengthByte) - { - //Determine how big data is and expand it to handle the soon to - //be read VPD data - l_offset = io_data.size(); - io_data.resize(l_offset + 1 + l_vpdSize); - //Add on the data to the type/length byte indicating it is ascii - // otherwise leave it as binary - if (i_ascii) - { - io_data.at(l_offset) = l_vpdSize - + IPMIFRUINV::TYPELENGTH_BYTE_ASCII; - } - else - { - io_data.at(l_offset) = l_vpdSize; - } - l_offset += 1; - } - else - { - //Determine how big data is and expand it to handle the soon to - //be read VPD data - l_offset = io_data.size(); - io_data.resize(l_offset + l_vpdSize); - } - //Read the VPD data directly into fru inventory data buffer - l_errl = deviceRead(iv_target,&io_data[l_offset],l_vpdSize, - DEVICE_CVPD_ADDRESS(i_record, i_keyword)); - } - else - { - TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::addVpdData - " - " No size returned for CVPD keyword"); - } - } while(0); - - if (l_errl) - { - TRACFCOMP(g_trac_ipmi, "backplaneIpmiFruInv::addVpdData - Error " - "acquiring data from Vpd."); - } + l_errl = addCommonVpdData(iv_target, + io_data, + DeviceFW::PVPD, + i_record, + i_keyword, + i_ascii, + i_typeLengthByte); return l_errl; } @@ -1106,11 +989,11 @@ errlHndl_t systemFwIpmiFruInv::buildProductInfoArea(std::vector<uint8_t> io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS); - //Finalize section formatting - postFormatProcessing(io_data); - } while(0); + //Finalize section formatting + postFormatProcessing(io_data); + return l_errl; } @@ -1121,7 +1004,155 @@ errlHndl_t systemFwIpmiFruInv::buildMultiRecordInfoArea(std::vector<uint8_t> return IpmiFruInv::buildEmptyArea(io_data); } +//############################################################################## +membufIpmiFruInv::membufIpmiFruInv( TARGETING::TargetHandle_t i_target, + TARGETING::TargetHandleList i_extraTargets, + bool i_isUpdate) + :IpmiFruInv(i_target), + iv_isUpdate(i_isUpdate), + iv_extraTargets(i_extraTargets) +{ +}; + +errlHndl_t membufIpmiFruInv::buildInternalUseArea( + std::vector<uint8_t> &io_data) +{ + //This section not needed for the mem buf type + return IpmiFruInv::buildEmptyArea(io_data); +} + +errlHndl_t membufIpmiFruInv::buildChassisInfoArea( + std::vector<uint8_t> &io_data) +{ + //This section not needed for the mem buf type + return IpmiFruInv::buildEmptyArea(io_data); +} + +errlHndl_t membufIpmiFruInv::buildBoardInfoArea( + std::vector<uint8_t> &io_data) +{ + errlHndl_t l_errl = NULL; + + do { + //Set formatting data that goes at the beginning of the record + preFormatProcessing(io_data, true); + + //Set MFG Date/Time - Blank + io_data.push_back(0); + io_data.push_back(0); + io_data.push_back(0); + + //Set Vendor Name - ascii formatted data + l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VN, true); + if (l_errl) { break; } + + //Set Product Name - ascii formatted data + l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::DR, true); + if (l_errl) { break; } + + //Set Product Serial number - ascii formatted data + //TODO RTC:117702 use attribute when 122890 is available + l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VS, true); + if (l_errl) { break; } + + //Set Product Part number - ascii formatted data + //TODO RTC:117702 use attribute when 122890 is available + l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VP, true); + if (l_errl) { break; } + + //Push Fru File ID Byte - NULL + io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL); + + //Only set the ECID Data during an update scenario + if (iv_isUpdate == true) + { + customEcidData (iv_extraTargets, io_data); + } + + //Indicate End of Custom Fields + io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS); + + } while (0); + + //Complete record data formatting + postFormatProcessing(io_data); + + if (l_errl) + { + TRACFCOMP(g_trac_ipmi,"membufIpmiFruInv::buildBoardInfoArea - " + "Errors collecting board info data"); + } + + return l_errl; +} + +errlHndl_t membufIpmiFruInv::buildProductInfoArea( + std::vector<uint8_t> &io_data) +{ + //This section not needed for the mem buf type + return IpmiFruInv::buildEmptyArea(io_data); +} + +errlHndl_t membufIpmiFruInv::buildMultiRecordInfoArea( + std::vector<uint8_t> &io_data) +{ + //This section not needed for the mem buf type + return IpmiFruInv::buildEmptyArea(io_data); +} + +errlHndl_t membufIpmiFruInv::addVpdData(std::vector<uint8_t> &io_data, + uint8_t i_record, + uint8_t i_keyword, + bool i_ascii, + bool i_typeLengthByte) +{ + errlHndl_t l_errl = NULL; + + l_errl = addCommonVpdData(iv_target, + io_data, + DeviceFW::CVPD, + i_record, + i_keyword, + i_ascii, + i_typeLengthByte); + return l_errl; +} +//############################################################################## +void IpmiFruInv::customEcidData(TARGETING::TargetHandleList i_extraTargets, + std::vector<uint8_t> &io_data) +{ + + bool l_setCustomData = false; + // Check if we should add ECID + for (TARGETING::TargetHandleList::const_iterator extraTargets_it = + i_extraTargets.begin(); + extraTargets_it != i_extraTargets.end(); + ++extraTargets_it + ) + { + TARGETING::TargetHandle_t l_extraTarget = *extraTargets_it; + + //Only set the ECID Data during an update scenario + if ( l_extraTarget->getAttr<TARGETING::ATTR_TYPE>() == + TARGETING::TYPE_MEMBUF) + { + TARGETING::ATTR_ECID_type ecidInfo; + bool getEcid = + l_extraTarget->tryGetAttr<TARGETING::ATTR_ECID>(ecidInfo); + if (getEcid) + { + l_setCustomData = true; + addEcidData(l_extraTarget, ecidInfo, io_data); + } + } + } + //If no Custom data was sent, an Empty Byte is needed + if (!l_setCustomData) + { + io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL); + } +} void IpmiFruInv::addEcidData(const TARGETING::TargetHandle_t& i_target, const TARGETING::ATTR_ECID_type& i_ecidInfo, @@ -1149,6 +1180,94 @@ void IpmiFruInv::addEcidData(const TARGETING::TargetHandle_t& i_target, return; } +errlHndl_t IpmiFruInv::addCommonVpdData( + const TARGETING::TargetHandle_t& i_target, + std::vector<uint8_t> &io_data, + DeviceFW::AccessType i_accessType, + uint8_t i_record, + uint8_t i_keyword, + bool i_ascii, + bool i_typeLengthByte) +{ + size_t l_vpdSize = 0; + errlHndl_t l_errl = NULL; + + do { + // First get size with NULL call: + // Bypass DEVICE_?VPD_ADDRESS inorder to maximize common code + l_errl = deviceRead(i_target, + NULL, + l_vpdSize, + i_accessType, + i_record, + i_keyword, + VPD::AUTOSELECT); + + if (l_errl) + { + TRACFCOMP(g_trac_ipmi,"addCommonVpdData - Error " + "while reading keyword size"); + break; + } + + //Assert if vpd field is too large to fit in IPMI fru inventory format + assert(l_vpdSize < IPMIFRUINV::TYPELENGTH_BYTE_ASCII); + + if (l_vpdSize > 0) + { + uint8_t l_offset = 0; + //Add on the typelength byte if requested + if (i_typeLengthByte) + { + //Determine how big data is and expand it to handle the soon to + //be read VPD data + l_offset = io_data.size(); + io_data.resize(l_offset + 1 + l_vpdSize); + //Add on the data to the type/length byte indicating it is ascii + // otherwise leave it as binary + if (i_ascii) + { + io_data.at(l_offset) = l_vpdSize + + IPMIFRUINV::TYPELENGTH_BYTE_ASCII; + } + else + { + io_data.at(l_offset) = l_vpdSize; + } + l_offset += 1; + } + else + { + //Determine how big data is and expand it to handle the soon to + //be read VPD data + l_offset = io_data.size(); + io_data.resize(l_offset + l_vpdSize); + } + //Read the VPD data directly into fru inventory data buffer + l_errl = deviceRead(i_target, + &io_data[l_offset], + l_vpdSize, + i_accessType, + i_record, + i_keyword, + VPD::AUTOSELECT); + } + else + { + TRACFCOMP(g_trac_ipmi,"addCommonVpdData - " + " No size returned for keyword"); + } + } while(0); + + if (l_errl) + { + TRACFCOMP(g_trac_ipmi, "addCommonVpdData - Error " + "acquiring data from Vpd."); + } + + return l_errl; +} + void IPMIFRUINV::clearData(uint8_t i_fruId) { uint8_t l_clearData[] = @@ -1292,10 +1411,12 @@ void IPMIFRUINV::gatherClearData(const TARGETING::Target* i_pSys, std::map<uint8_t,bool>& io_frusToClear) { TARGETING::PredicateCTM predChip(TARGETING::CLASS_CHIP); + TARGETING::PredicateCTM predNode(TARGETING::CLASS_ENC, + TARGETING::TYPE_NODE); TARGETING::PredicateCTM predDimm(TARGETING::CLASS_LOGICAL_CARD, TARGETING::TYPE_DIMM); TARGETING::PredicatePostfixExpr checkAllExpr; - checkAllExpr.push(&predChip).push(&predDimm).Or(); + checkAllExpr.push(&predChip).push(&predNode).Or().push(&predDimm).Or(); TARGETING::TargetHandleList l_allPossibleFrus; TARGETING::targetService().getAssociated( l_allPossibleFrus, i_pSys, TARGETING::TargetService::CHILD, TARGETING::TargetService::ALL, @@ -1336,14 +1457,19 @@ void IPMIFRUINV::gatherSetData(const TARGETING::Target* i_pSys, // may be needed l_present.present(true); + checkExpr.push(&predChip); + TARGETING::PredicateCTM predNode(TARGETING::CLASS_ENC, + TARGETING::TYPE_NODE); + checkExpr.push(&predNode).Or(); + //When updating data on a later pass ignore dimms if (i_updateData) { - checkExpr.push(&predChip).push(&l_present).And(); + checkExpr.push(&l_present).And(); } else { - checkExpr.push(&predChip).push(&predDimm).Or().push(&l_present).And(); + checkExpr.push(&predDimm).Or().push(&l_present).And(); } TARGETING::TargetHandleList pCheckPres; @@ -1374,6 +1500,10 @@ void IPMIFRUINV::gatherSetData(const TARGETING::Target* i_pSys, } //Sort the vector by FRU_ID for later use. + //When the planar eeprom is shared for planar and memory buffer vpd, the + //node and membuffs will have the same FRU ID. For this case, sort the Node + //to be ahead of the mem buffs. The mem buffs will be extra targets for + //their ECIDs. std::sort(io_potentialFrus.begin(), io_potentialFrus.end(), comparePairs); diff --git a/src/usr/ipmi/ipmifruinvprvt.H b/src/usr/ipmi/ipmifruinvprvt.H index 468a47f80..57d6e13cd 100644 --- a/src/usr/ipmi/ipmifruinvprvt.H +++ b/src/usr/ipmi/ipmifruinvprvt.H @@ -186,6 +186,32 @@ class IpmiFruInv const TARGETING::ATTR_ECID_type& i_ecidInfo, std::vector<uint8_t> &io_data); + /** + * @brief Adds Ecid attribute data from extra targets as custom data + * @param[in] TargetHandleList, Handle to list of extra + * targets associated with this FRU Record + * @param[in/out] data, The container to put ECID attribute data in + */ + void customEcidData(TARGETING::TargetHandleList i_extraTargets, + std::vector<uint8_t> &io_data); + + /** + * @brief Retrieve vpd record keyword and add to IPMI Fru Inventory record + * @param[in/out] data, The container with record data + * @param[in] access, Indicates vpd module to access (MVPD,PVPD,CPVD) + * @param[in] record, Indicates major offset in the VPD to get more data + * @param[in] keyword, Indicates minor offset in the VPD to get more data + * @param[in] ascii, Indicates if VPD field is in ascii format or not + */ + errlHndl_t addCommonVpdData( + const TARGETING::TargetHandle_t& i_target, + std::vector<uint8_t> &io_data, + DeviceFW::AccessType i_accessType, + uint8_t i_record, + uint8_t i_keyword, + bool i_ascii, + bool i_typeLengthByte); + private: /** @@ -376,11 +402,13 @@ class procIpmiFruInv : public IpmiFruInv * @param[in] record, Indicates major offset in the VPD to get more data * @param[in] keyword, Indicates minor offset in the VPD to get more data * @param[in] ascii, Indicates if VPD field is in ascii format or not + * @param[in] typeLengthBtye, Indicates whether type length to be added. */ errlHndl_t addVpdData(std::vector<uint8_t> &io_data, uint8_t i_record, uint8_t i_keyword, - bool i_ascii=false); + bool i_ascii=false, + bool i_typeLengthByte=true); }; @@ -453,13 +481,13 @@ class backplaneIpmiFruInv : public IpmiFruInv * @param[in] record, Indicates major offset in the VPD to get more data * @param[in] keyword, Indicates minor offset in the VPD to get more data * @param[in] ascii, Indicates if VPD field is in ascii format or not + * @param[in] typeLengthBtye, Indicates whether type length to be added. */ errlHndl_t addVpdData(std::vector<uint8_t> &io_data, uint8_t i_record, uint8_t i_keyword, bool i_ascii=false, bool i_typeLengthByte=true); - }; //Child class for building up System Firwmare Fru Inventory Record Data @@ -507,4 +535,84 @@ class systemFwIpmiFruInv : public IpmiFruInv }; +//Child class for building up membuf Fru Inventory Record Data. For example, +//for a memory riser card Fru. +class membufIpmiFruInv : public IpmiFruInv +{ + + public: + + /** + * @brief Constructor + * + * @param[in] TargetHandle_t, Handle to target for which + * to get relevant IPMI FRU Data from + * @param[in] TargetHandleList, Handle to list of extra + * targets associated with this FRU Record + * @param[in] isUpdate, Indicator if the code is updating + * existing data, or setting base data. + */ + membufIpmiFruInv( TARGETING::TargetHandle_t i_target, + TARGETING::TargetHandleList i_extraTargets, + bool i_isUpdate ); + + /** + * @brief Builds the Internal Use Area Data Section + * @param[in/out] data, The container to put internal use area data in + */ + errlHndl_t buildInternalUseArea(std::vector<uint8_t> &io_data); + + /** + * @brief Builds the Chassis Info Area Data Section + * @param[in/out] data, The container to put chassis info area data in + */ + errlHndl_t buildChassisInfoArea(std::vector<uint8_t> &io_data); + + /** + * @brief Builds the Board Info Area Data Section + * @param[in/out] data, The container to put board info area data in + */ + errlHndl_t buildBoardInfoArea(std::vector<uint8_t> &io_data); + + /** + * @brief Builds the Product Info Area Data Section + * @param[in/out] data, The container to put product info area data in + */ + errlHndl_t buildProductInfoArea(std::vector<uint8_t>& io_data); + + /** + * @brief Builds the MultiRecord Info Area Data Section + * @param[in/out] data, The container to put multirecord info area data in + */ + errlHndl_t buildMultiRecordInfoArea(std::vector<uint8_t>& io_data); + + protected: + //Indicator if a data update is happening. + //True - means we are solely updating certain data + //False - means we are doing the initial 'base' data set + bool iv_isUpdate; + + //The list of Extra Targets if multiple targets are + //associated with one FRU_ID + TARGETING::TargetHandleList iv_extraTargets; + + private: + + /** + * @brief Adds the specified VPD data to the data to build up a given + * IPMI Fru Inventory record + * @param[in/out] data, The container with record data + * @param[in] record, Indicates major offset in the VPD to get more data + * @param[in] keyword, Indicates minor offset in the VPD to get more data + * @param[in] ascii, Indicates if VPD field is in ascii format or not + * @param[in] typeLengthBtye, Indicates whether type length to be added. + */ + errlHndl_t addVpdData(std::vector<uint8_t> &io_data, + uint8_t i_record, + uint8_t i_keyword, + bool i_ascii=false, + bool i_typeLengthByte=true); + +}; + #endif diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index 5503e3ce1..6506a7a2a 100644 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -917,6 +917,8 @@ <attribute><id>FRU_ID</id></attribute> <attribute><id>TPM_PRIMARY_INFO</id></attribute> <attribute><id>TPM_BACKUP_INFO</id></attribute> + <attribute><id>EEPROM_VPD_PRIMARY_INFO</id></attribute> + <attribute><id>VPD_REC_NUM</id></attribute> </targetType> <targetType> diff --git a/src/usr/targeting/common/xmltohb/target_types_hb.xml b/src/usr/targeting/common/xmltohb/target_types_hb.xml index b0429daf0..d023f507c 100644 --- a/src/usr/targeting/common/xmltohb/target_types_hb.xml +++ b/src/usr/targeting/common/xmltohb/target_types_hb.xml @@ -180,6 +180,11 @@ </targetTypeExtension> <targetTypeExtension> + <id>enc-node-power8</id> + <attribute><id>VPD_SWITCHES</id></attribute> +</targetTypeExtension> + +<targetTypeExtension> <id>lcard-dimm</id> <attribute><id>VPD_SWITCHES</id></attribute> <attribute><id>IPMI_SENSORS</id></attribute> diff --git a/src/usr/vpd/HBconfig b/src/usr/vpd/HBconfig index 136183442..1d6e6f1b8 100644 --- a/src/usr/vpd/HBconfig +++ b/src/usr/vpd/HBconfig @@ -33,6 +33,28 @@ config CVPD_WRITE help Ensure at least one of the CVPD WRITEs are enabled +config PVPD_READ_FROM_PNOR + default n + help + Read Planar VPD data from PNOR cache + +config PVPD_READ_FROM_HW + default n + help + Read Planar VPD data from HW resources + +config PVPD_WRITE_TO_PNOR + default y if PVPD_READ_FROM_PNOR + depends on PVPD_READ_FROM_PNOR + help + Write Planar VPD data to PNOR cache + +config PVPD_WRITE_TO_HW + default y if PVPD_READ_FROM_HW + depends on PVPD_READ_FROM_HW + help + Write Planar VPD data to HW resources + config MVPD_READ_FROM_PNOR default y help @@ -105,6 +127,11 @@ config HAVE_MBVPD help Have MemBuff/Centaur VPD, PNOR or HW +config HAVE_PVPD + default y if PVPD_READ_FROM_PNOR || PVPD_READ_FROM_HW + help + Have Planar VPD, PNOR or HW + config PALMETTO_PASS1 default n help diff --git a/src/usr/vpd/cvpd.C b/src/usr/vpd/cvpd.C index 50815f135..fa37dc978 100644 --- a/src/usr/vpd/cvpd.C +++ b/src/usr/vpd/cvpd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -31,7 +31,10 @@ #include <trace/interface.H> #include <errl/errlentry.H> #include <errl/errlmanager.H> +#include <targeting/common/commontargeting.H> #include <targeting/common/targetservice.H> +#include <targeting/common/util.H> +#include <targeting/common/utilFilter.H> #include <devicefw/driverif.H> #include <vfs/vfs.H> #include <vpd/vpdreasoncodes.H> @@ -40,6 +43,7 @@ #include <i2c/eepromif.H> #include <config.h> #include "cvpd.H" +#include "pvpd.H" #include "vpd.H" // ---------------------------------------------- @@ -233,15 +237,41 @@ IpVpdFacade(CVPD::SECTION_SIZE, iv_configInfo.vpdReadHW = true; #else iv_configInfo.vpdReadHW = false; -#endif +#endif #ifdef CONFIG_CVPD_WRITE_TO_PNOR iv_configInfo.vpdWritePNOR = true; #else iv_configInfo.vpdWritePNOR = false; -#endif +#endif #ifdef CONFIG_CVPD_WRITE_TO_HW iv_configInfo.vpdWriteHW = true; #else iv_configInfo.vpdWriteHW = false; #endif } + +// Retrun lists of records that should be copied to pnor. +void CvpdFacade::getRecordLists( + const recordInfo* & o_primaryVpdRecords, + uint64_t & o_primaryRecSize, + const recordInfo* & o_altVpdRecords, + uint64_t & o_altRecSize) +{ + // Always return this object's list + o_primaryVpdRecords = iv_vpdRecords; + o_primaryRecSize = iv_recSize; + + // If the planar errprom being shared with a mem buf, + // then return the pvpd list as the alternative record list. + // At thip point, if the membufs are be processed, then the node + // might not have been discovered yet. If pvpd is being cached, then + // include the pvpd list as the altnative. +#ifdef CONFIG_PVPD_READ_FROM_PNOR + o_altVpdRecords = Singleton<PvpdFacade>::instance().iv_vpdRecords; + o_altRecSize = Singleton<PvpdFacade>::instance().iv_recSize; +#else + o_altVpdRecords = NULL; + o_altRecSize = 0; +#endif +} + diff --git a/src/usr/vpd/cvpd.H b/src/usr/vpd/cvpd.H index e7a2d9f06..9c729c389 100644 --- a/src/usr/vpd/cvpd.H +++ b/src/usr/vpd/cvpd.H @@ -79,7 +79,6 @@ namespace CVPD { OPFR, "OPFR" }, { VNDR, "VNDR" }, { SPDX, "SPDX" }, - { OSYS, "OSYS" }, // ------------------------------------------------------------------- // DO NOT USE!! This is for test purposes ONLY! { CVPD_TEST_RECORD, "TEST" }, @@ -182,5 +181,26 @@ class CvpdFacade: public IpVpdFacade */ CvpdFacade( ); + private: + + /** + * @brief This function returns a primary and an alternate list of records + * that should be copied to pnor. The Alternate list is optional. + * + * @param[out] o_primaryVpdRecords - Pointer to array of VPD Records to use + * + * @param[out] o_primaryRecSize - Size of o_primaryVpdRecords array + * + * @param[out] o_altVpdRecords - Pointer to array of VPD Records to use + * + * @param[out] o_altRecSize - Size of o_altVpdRecords array + * + */ + void getRecordLists( + const recordInfo* & o_primaryVpdRecords, + uint64_t & o_primaryRecSize, + const recordInfo* & o_altVpdRecords, + uint64_t & o_altRecSize); + }; #endif // __CVPD_H diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C index 3da20b2ec..e148bc970 100644 --- a/src/usr/vpd/ipvpd.C +++ b/src/usr/vpd/ipvpd.C @@ -43,6 +43,7 @@ #include <vpd/ipvpdenums.H> #include "vpd.H" +#include "cvpd.H" #include "ipvpd.H" #include "errlud_vpd.H" @@ -1336,6 +1337,19 @@ IpVpdFacade::getRecordListSeeprom ( std::list<TocPtRecord> & o_recList, return err; } + // Get the list of records that should be copied to pnor. + // The list of records for this vpd sub class will be the primary list. + // If the eeprom is being shared, then their might be an alternate list + // to also include. + const recordInfo* l_primaryVpdRecords = NULL; + uint64_t l_primaryRecSize = 0; + const recordInfo* l_altVpdRecords = NULL; + uint64_t l_altRecSize = 0; + getRecordLists(l_primaryVpdRecords, + l_primaryRecSize, + l_altVpdRecords, + l_altRecSize); + offset = le16toh( toc_rec->record_offset ) + 1; // skip 'large resource' // Read the PT keyword(s) from the VTOC @@ -1367,20 +1381,36 @@ IpVpdFacade::getRecordListSeeprom ( std::list<TocPtRecord> & o_recList, vtoc_pt_offset < pt_len; vtoc_pt_offset += sizeof(TocPtRecord) ) { + bool l_found = false; toc_rec = reinterpret_cast<TocPtRecord*>(l_buffer + vtoc_pt_offset); // Save record if on the list for this target - for ( uint32_t rec = 0; rec < iv_recSize; rec++ ) + for ( uint32_t rec = 0; rec < l_primaryRecSize; rec++ ) { if ( memcmp( toc_rec->record_name, - iv_vpdRecords[rec].recordName, + l_primaryVpdRecords[rec].recordName, RECORD_BYTE_SIZE ) == 0 ) { o_recList.push_back(*toc_rec); + l_found = true; break; } } + // if not found, check the alternate list + if (!l_found) + { + for ( uint32_t rec = 0; rec < l_altRecSize; rec++ ) + { + if ( memcmp( toc_rec->record_name, + l_altVpdRecords[rec].recordName, + RECORD_BYTE_SIZE ) == 0 ) + { + o_recList.push_back(*toc_rec); + break; + } + } + } } } @@ -2182,3 +2212,19 @@ void IpVpdFacade::setConfigFlagsHW ( ) iv_configInfo.vpdWriteHW = true; } } + +// Return the lists of records that should be copied to pnor. +// The default lists to use are this object's record list and size. +// No Alternate. +void IpVpdFacade::getRecordLists( + const recordInfo* & o_primaryVpdRecords, + uint64_t & o_primaryRecSize, + const recordInfo* & o_altVpdRecords, + uint64_t & o_altRecSize) +{ + o_primaryVpdRecords = iv_vpdRecords; + o_primaryRecSize = iv_recSize; + o_altVpdRecords = NULL; + o_altRecSize = 0; +} + diff --git a/src/usr/vpd/ipvpd.H b/src/usr/vpd/ipvpd.H index 5cc7bec7e..e4c416238 100644 --- a/src/usr/vpd/ipvpd.H +++ b/src/usr/vpd/ipvpd.H @@ -677,7 +677,24 @@ class IpVpdFacade errlHndl_t checkBufferSize( size_t i_bufferSize, size_t i_expectedSize, TARGETING::Target * i_target ); - + /** + * @brief This function returns a primary and an alternate list of records + * that should be copied to pnor. The Alternate list is optional. + * + * @param[out] o_primaryVpdRecords - Pointer to array of VPD Records to use + * + * @param[out] o_primaryRecSize - Size of o_primaryVpdRecords array + * + * @param[out] o_altVpdRecords - Pointer to array of VPD Records to use + * + * @param[out] o_altRecSize - Size of o_altVpdRecords array + * + */ + virtual void getRecordLists( + const recordInfo* & o_primaryVpdRecords, + uint64_t & o_primaryRecSize, + const recordInfo* & o_altVpdRecords, + uint64_t & o_altRecSize); protected: // Variables @@ -693,6 +710,8 @@ class IpVpdFacade */ uint64_t iv_vpdMaxSections; + + public: // Variables /** * @brief Pointer to array of VPD Record information * @@ -705,6 +724,7 @@ class IpVpdFacade */ uint64_t iv_recSize; + protected: // Variables /** * @brief Pointer to array of VPD Keyword information * diff --git a/src/usr/vpd/pvpd.C b/src/usr/vpd/pvpd.C new file mode 100644 index 000000000..ec6223709 --- /dev/null +++ b/src/usr/vpd/pvpd.C @@ -0,0 +1,369 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/vpd/pvpd.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* [+] 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 */ +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +#include <string.h> +#include <endian.h> +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <targeting/common/targetservice.H> +#include <targeting/common/util.H> +#include <targeting/common/utilFilter.H> +#include <devicefw/driverif.H> +#include <vfs/vfs.H> +#include <vpd/vpdreasoncodes.H> +#include <vpd/pvpdenums.H> +#include <vpd/vpd_if.H> +#include <i2c/eepromif.H> +#include <config.h> +#include "pvpd.H" +#include "cvpd.H" +#include "vpd.H" + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +extern trace_desc_t* g_trac_vpd; + + +// ------------------------ +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) +//#define TRACSSCOMP(args...) TRACFCOMP(args) +#define TRACSSCOMP(args...) + +namespace PVPD +{ + // ---------------------------------------------- + // Globals + // ---------------------------------------------- + mutex_t g_mutex = MUTEX_INITIALIZER; + + + /** + * @brief This function will perform the steps required to do a read from + * the Hostboot PVPD data. + * + * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in + * driververif.H + * + * @param[in] i_target - Processor Target device + * + * @param [in/out] io_buffer - Pointer to the data that was read from + * the target device. This parameter, when set to NULL, will return + * the keyword size value in io_buflen. + * + * @param [in/out] io_buflen - Length of the buffer to be read or written + * to/from the target. This value should indicate the size of the + * io_buffer parameter that has been allocated. Being returned it + * will indicate the number of valid bytes in the buffer being + * returned. This parameter will contain the size of a keyword when + * the io_buffer parameter is passed in NULL. + * + * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in + * usrif.H + * + * @param [in] i_args - This is an argument list for the device driver + * framework. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t pvpdRead ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t & io_buflen, + int64_t i_accessType, + va_list i_args ) + { + errlHndl_t err = NULL; + IpVpdFacade::input_args_t args; + args.record = ((pvpdRecord)va_arg( i_args, uint64_t )); + args.keyword = ((pvpdKeyword)va_arg( i_args, uint64_t )); + args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); + + TRACSSCOMP( g_trac_vpd, + ENTER_MRK"pvpdRead()" ); + + err = Singleton<PvpdFacade>::instance().read(i_target, + io_buffer, + io_buflen, + args); + + return err; + } + + + /** + * @brief This function will perform the steps required to do a write to + * the Hostboot PVPD data. + * + * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in + * driververif.H + * + * @param[in] i_target - Processor Target device + * + * @param [in/out] io_buffer - Pointer to the data that was read from + * the target device. It will also be used to contain data to + * be written to the device. + * + * @param [in/out] io_buflen - Length of the buffer to be read or written + * to/from the target. This value should indicate the size of the + * io_buffer parameter that has been allocated. Being returned it + * will indicate the number of valid bytes in the buffer being + * returned. + * + * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in + * usrif.H + * + * @param [in] i_args - This is an argument list for the device driver + * framework. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t pvpdWrite ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t & io_buflen, + int64_t i_accessType, + va_list i_args ) + { + errlHndl_t err = NULL; + IpVpdFacade::input_args_t args; + args.record = ((pvpdRecord)va_arg( i_args, uint64_t )); + args.keyword = ((pvpdKeyword)va_arg( i_args, uint64_t )); + args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); + + TRACSSCOMP( g_trac_vpd, + ENTER_MRK"pvpdWrite()" ); + + + err = Singleton<PvpdFacade>::instance().write(i_target, + io_buffer, + io_buflen, + args); + + return err; + } + + // Register with the routing code + DEVICE_REGISTER_ROUTE( DeviceFW::READ, + DeviceFW::PVPD, + TARGETING::TYPE_NODE, + pvpdRead ); + DEVICE_REGISTER_ROUTE( DeviceFW::WRITE, + DeviceFW::PVPD, + TARGETING::TYPE_NODE, + pvpdWrite ); + +}; // end namespace PVPD + +#if !defined(__HOSTBOOT_RUNTIME) +// -------------------------------------------------------- +// Presence Detection +//--------------------------------------------------------- + +/** + * @brief Performs a presence detect operation on a Node card. + * + * There is no FSI presence detection, just Planar vpd detection. + * Presence is always returned as Success (unless the unlikely case of too + * small of a buffer passed). A problem with planar EEPROM is logged but + * not passed up so that the enclosure and everything inside is not + * deconfigured. + * + * @param[in] i_opType Operation type, see DeviceFW::OperationType + * in driverif.H + * @param[in] i_target Presence detect target + * @param[in/out] io_buffer Read: Pointer to output data storage + * Write: Pointer to input data storage + * @param[in/out] io_buflen Input: size of io_buffer (in bytes, always 1) + * Output: Success = 1, Failure = 0 + * @param[in] i_accessType DeviceFW::AccessType enum (userif.H) + * @param[in] i_args This is an argument list for DD framework. + * In this function, there are no arguments. + * @return errlHndl_t + */ +errlHndl_t nodePresenceDetect(DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + int64_t i_accessType, + va_list i_args) +{ + errlHndl_t l_errl = NULL; + bool pvpd_present = true; + + if (unlikely(io_buflen < sizeof(bool))) + { + TRACFCOMP(g_trac_vpd, + ERR_MRK "nodePresenceDetect> Invalid data length: %d", + io_buflen); + /*@ + * @errortype + * @moduleid VPD::VPD_PVPD_PRESENCEDETECT + * @reasoncode VPD::VPD_INVALID_LENGTH + * @userdata1 Data Length + * @devdesc presenceDetect> Invalid data length (!= 1 bytes) + */ + l_errl = + new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_PVPD_PRESENCEDETECT, + VPD::VPD_INVALID_LENGTH, + TO_UINT64(io_buflen), + true /*SW error*/); + io_buflen = 0; + return l_errl; + } + +#if defined(CONFIG_PVPD_READ_FROM_HW) && defined(CONFIG_PVPD_READ_FROM_PNOR) + pvpd_present = VPD::pvpdPresent( i_target ); + if( pvpd_present ) + { + // Check if the VPD data in the PNOR matches the SEEPROM + l_errl = VPD::ensureCacheIsInSync( i_target ); + if( l_errl ) + { + TRACFCOMP(g_trac_vpd,ERR_MRK "nodePresenceDetect>" + " Error during ensureCacheIsInSync (PVPD)" ); + errlCommit( l_errl, FSI_COMP_ID ); + } + } + else + { + TRACFCOMP(g_trac_vpd, + ERR_MRK "nodePresenceDetect> failed presence detect"); + + // Invalidate PVPD in the PNOR + l_errl = VPD::invalidatePnorCache(i_target); + if (l_errl) + { + TRACFCOMP( g_trac_vpd, "Error invalidating PVPD in PNOR" ); + errlCommit( l_errl, VPD_COMP_ID ); + } + pvpd_present = true; + } +#endif + + // Always return presence. + // A returned error deconfigures the node and stops the IPL. + memcpy(io_buffer, &pvpd_present, sizeof(pvpd_present)); + io_buflen = sizeof(pvpd_present); + + return NULL; +} + +// Register as the presence detect for nodes. +DEVICE_REGISTER_ROUTE(DeviceFW::READ, + DeviceFW::PRESENT, + TARGETING::TYPE_NODE, + nodePresenceDetect); +#endif + +bool VPD::pvpdPresent( TARGETING::Target * i_target ) +{ + TRACSSCOMP( g_trac_vpd, ENTER_MRK"pvpdPresent()"); +#if(defined( CONFIG_PVPD_READ_FROM_HW ) && !defined( __HOSTBOOT_RUNTIME) ) + + return EEPROM::eepromPresence( i_target ); + +#else + return Singleton<PvpdFacade>::instance().hasVpdPresent( i_target, + PVPD::OPFR, + PVPD::VP ); +#endif +} + + +//PVPD Class Functions +/** + * @brief Constructor + * Planar VPD is included in the Centaur PNOR section. + * Including with Centaur vpd minimizes the number of PNOR sections. + */ +PvpdFacade::PvpdFacade() : +IpVpdFacade(CVPD::SECTION_SIZE, // note use of CVPD + CVPD::MAX_SECTIONS, // note use of CVPD + PVPD::pvpdRecords, + (sizeof(PVPD::pvpdRecords)/sizeof(PVPD::pvpdRecords[0])), + PVPD::pvpdKeywords, + (sizeof(PVPD::pvpdKeywords)/sizeof(PVPD::pvpdKeywords[0])), + PNOR::CENTAUR_VPD, // note use of CVPD + PVPD::g_mutex, + VPD::VPD_WRITE_PLANAR) +{ + TRACUCOMP(g_trac_vpd, "PvpdFacade::PvpdFacade> " ); + +#ifdef CONFIG_PVPD_READ_FROM_PNOR + iv_configInfo.vpdReadPNOR = true; +#else + iv_configInfo.vpdReadPNOR = false; +#endif +#ifdef CONFIG_PVPD_READ_FROM_HW + iv_configInfo.vpdReadHW = true; +#else + iv_configInfo.vpdReadHW = false; +#endif +#ifdef CONFIG_PVPD_WRITE_TO_PNOR + iv_configInfo.vpdWritePNOR = true; +#else + iv_configInfo.vpdWritePNOR = false; +#endif +#ifdef CONFIG_PVPD_WRITE_TO_HW + iv_configInfo.vpdWriteHW = true; +#else + iv_configInfo.vpdWriteHW = false; +#endif +} + +// Retrun lists of records that should be copied to pnor. +void PvpdFacade::getRecordLists( + const recordInfo* & o_primaryVpdRecords, + uint64_t & o_primaryRecSize, + const recordInfo* & o_altVpdRecords, + uint64_t & o_altRecSize) +{ + // Always return this object's list + o_primaryVpdRecords = iv_vpdRecords; + o_primaryRecSize = iv_recSize; + + // If the planar eeprom is being shared with a mem buf, + // then return the cvpd list as the alternative record list. + // At thip point, if the node is be processed, then the mem buffs + // might have not been discovered yet. If cvpd is being cached, then + // include the cvpd list as the altnative. +#ifdef CONFIG_CVPD_READ_FROM_PNOR + o_altVpdRecords = Singleton<CvpdFacade>::instance().iv_vpdRecords; + o_altRecSize = Singleton<CvpdFacade>::instance().iv_recSize; +#else + o_altVpdRecords = NULL; + o_altRecSize = 0; +#endif +} + diff --git a/src/usr/vpd/pvpd.H b/src/usr/vpd/pvpd.H new file mode 100644 index 000000000..092dd45f7 --- /dev/null +++ b/src/usr/vpd/pvpd.H @@ -0,0 +1,149 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/vpd/pvpd.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* [+] 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 __PVPD_H +#define __PVPD_H + + +/** + * @file pvpd.H + * + * @brief Provides the interfaces for the PVPD device driver + * + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +#include <errl/errlentry.H> +#include <vpd/pvpdenums.H> + +#include "ipvpd.H" +#include <config.h> + +namespace PVPD +{ + + /** + * @brief Conversion of PVPD Records to corresponding character + * representation. + */ + const IpVpdFacade::recordInfo pvpdRecords[] = + { + // ------------------------------------------------------------------- + // NOTE: This list must remain an ordered list! There will be a + // testcase that checks this. When adding new entries to the + // list, be sure that the keyword in each entry (value 0) + // are in ascending order. + // ------------------------------------------------------------------- + { VINI, "VINI" }, + { OSYS, "OSYS" }, + { OPFR, "OPFR" }, + { VNDR, "VNDR" }, + // ------------------------------------------------------------------- + // DO NOT USE!! This is for test purposes ONLY! + { PVPD_TEST_RECORD, "TEST" }, + // ------------------------------------------------------------------- + }; + + /** + * @brief Conversion of PVPD Keywords to corresponding character + * representation. + */ + const IpVpdFacade::keywordInfo pvpdKeywords[] = + { + // ------------------------------------------------------------------- + // NOTE: This list must remain an ordered list! There will be a + // testcase that checks this. When adding new entries to + // the list, be sure that the keyword in each entry (value 0) + // are in ascending order. + // ------------------------------------------------------------------- + { pdI, "#I" }, + { B3, "B3" }, + { B4, "B4" }, + { B7, "B7" }, + { CC, "CC" }, + { CE, "CE" }, + { CT, "CT" }, + { DR, "DR" }, + { ET, "ET" }, + { FN, "FN" }, + { HE, "HE" }, + { HW, "HW" }, + { IN, "IN" }, + { MM, "MM" }, + { PF, "PF" }, + { PN, "PN" }, + { RT, "RT" }, + { SN, "SN" }, + { SS, "SS" }, + { VD, "VD" }, + { VN, "VN" }, + { VP, "VP" }, + { VS, "VS" }, + { VZ, "VZ" }, + + // ------------------------------------------------------------------- + // DO NOT USE!! This is for test purposes ONLY! + { PVPD_TEST_KEYWORD, "XX" }, + // ------------------------------------------------------------------- + + //Common ipvpd + { FULL_RECORD, "FL"}, + }; + +}; // end PVPD namespace + +class PvpdFacade: public IpVpdFacade +{ + public: + + /** + * @brief Constructor + */ + PvpdFacade( ); + + private: + + /** + * @brief This function returns a primary and an alternate list of records + * that should be copied to pnor. The Alternate list is optional. + * + * @param[out] o_primaryVpdRecords - Pointer to array of VPD Records to use + * + * @param[out] o_primaryRecSize - Size of o_primaryVpdRecords array + * + * @param[out] o_altVpdRecords - Pointer to array of VPD Records to use + * + * @param[out] o_altRecSize - Size of o_altVpdRecords array + * + */ + void getRecordLists( + const recordInfo* & o_primaryVpdRecords, + uint64_t & o_primaryRecSize, + const recordInfo* & o_altVpdRecords, + uint64_t & o_altRecSize); + +}; +#endif // __PVPD_H diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C index 9b4e1f82c..3656696c4 100755 --- a/src/usr/vpd/vpd.C +++ b/src/usr/vpd/vpd.C @@ -34,10 +34,9 @@ #include "vpd.H" #include "mvpd.H" #include "cvpd.H" +#include "pvpd.H" #include "spd.H" - - // ---------------------------------------------- // Trace definitions // ---------------------------------------------- @@ -456,6 +455,13 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target ) l_keywordPN = CVPD::VP; l_keywordSN = CVPD::VS; } + else if( l_type == TARGETING::TYPE_NODE ) + { + l_ipvpd = &(Singleton<PvpdFacade>::instance()); + l_record = PVPD::OPFR; + l_keywordPN = PVPD::VP; + l_keywordSN = PVPD::VS; + } else if( l_type == TARGETING::TYPE_DIMM ) { // SPD does not have a singleton instance @@ -487,7 +493,8 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target ) do { // Make sure we are comparing the correct pn/sn for CVPD - if( l_type == TARGETING::TYPE_MEMBUF ) + if( ( l_type == TARGETING::TYPE_MEMBUF ) || + ( l_type == TARGETING::TYPE_NODE ) ) { bool l_zeroPN; l_err = l_ipvpd->cmpSeepromToZero( i_target, @@ -523,6 +530,7 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target ) // Compare the Part Numbers in PNOR/SEEPROM bool l_matchPN = false; if( ( l_type == TARGETING::TYPE_PROC ) || + ( l_type == TARGETING::TYPE_NODE ) || ( l_type == TARGETING::TYPE_MEMBUF ) ) { l_err = l_ipvpd->cmpPnorToSeeprom( i_target, @@ -577,7 +585,8 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target ) HWAS::markTargetChanged(i_target); // Load the PNOR data from the SEEPROM - if( ( l_type == TARGETING::TYPE_PROC ) || + if( ( l_type == TARGETING::TYPE_PROC ) || + ( l_type == TARGETING::TYPE_NODE ) || ( l_type == TARGETING::TYPE_MEMBUF ) ) { l_err = l_ipvpd->loadPnor( i_target ); diff --git a/src/usr/vpd/vpd.H b/src/usr/vpd/vpd.H index 9c39a7f3d..e6cada716 100644 --- a/src/usr/vpd/vpd.H +++ b/src/usr/vpd/vpd.H @@ -50,6 +50,7 @@ enum VPD_MSG_TYPE VPD_WRITE_DIMM = 0x00C1, //< DIMM SPD VPD_WRITE_PROC = 0x00C2, //< Processor MVPD VPD_WRITE_MEMBUF = 0x00C3, //< Centaur FRU VPD + VPD_WRITE_PLANAR = 0x00C4, //< Planar VPD }; /** diff --git a/src/usr/vpd/vpd.mk b/src/usr/vpd/vpd.mk index 9f857554e..65d22e344 100644 --- a/src/usr/vpd/vpd.mk +++ b/src/usr/vpd/vpd.mk @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2013,2014 +# Contributors Listed Below - COPYRIGHT 2013,2015 +# [+] 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. @@ -24,5 +26,6 @@ OBJS += ipvpd.o OBJS += mvpd.o OBJS += cvpd.o +OBJS += pvpd.o OBJS += spd.o OBJS += errlud_vpd.o |