| From 9597cf58b44fd0c16da9d3592e8fd586a4dbf04d Mon Sep 17 00:00:00 2001 |
| From: Bill Schwartz <whs@us.ibm.com> |
| Date: Fri, 27 Feb 2015 15:41:10 -0600 |
| Subject: [PATCH] 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> |
| --- |
| src/include/usr/devicefw/userif.H | 23 + |
| src/include/usr/vpd/cvpdenums.H | 1 - |
| src/include/usr/vpd/pvpdenums.H | 96 ++++ |
| src/include/usr/vpd/vpd_if.H | 8 + |
| src/include/usr/vpd/vpdreasoncodes.H | 4 + |
| src/usr/devtree/bld_devtree.C | 85 ++-- |
| src/usr/hwas/hwasPlat.C | 6 +- |
| src/usr/hwas/hwasPlatCallout.C | 6 +- |
| src/usr/i2c/eepromdd.C | 5 + |
| src/usr/ipmi/ipmifruinv.C | 502 +++++++++++++-------- |
| src/usr/ipmi/ipmifruinvprvt.H | 112 ++++- |
| src/usr/targeting/common/xmltohb/target_types.xml | 2 + |
| .../targeting/common/xmltohb/target_types_hb.xml | 5 + |
| src/usr/vpd/HBconfig | 27 ++ |
| src/usr/vpd/cvpd.C | 36 +- |
| src/usr/vpd/cvpd.H | 22 +- |
| src/usr/vpd/ipvpd.C | 50 +- |
| src/usr/vpd/ipvpd.H | 22 +- |
| src/usr/vpd/pvpd.C | 369 +++++++++++++++ |
| src/usr/vpd/pvpd.H | 149 ++++++ |
| src/usr/vpd/vpd.C | 17 +- |
| src/usr/vpd/vpd.H | 1 + |
| src/usr/vpd/vpd.mk | 5 +- |
| 23 files changed, 1307 insertions(+), 246 deletions(-) |
| create mode 100644 src/include/usr/vpd/pvpdenums.H |
| create mode 100644 src/usr/vpd/pvpd.C |
| create mode 100644 src/usr/vpd/pvpd.H |
| |
| diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H |
| index 6d041f2..eac5366 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 4b5adb2..79b8109 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 0000000..acf3bbd |
| --- /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 0b3298a..d3915ee 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 88668b7..2cfe8a6 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 a8ece97..a311efe 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 80c36f9..ef631b5 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 0f15082..03756a8 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 372fcc7..b2e1c90 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 cc2f06a..49c5e7e 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 468a47f..57d6e13 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 82ec014..759b73e 100644 |
| --- a/src/usr/targeting/common/xmltohb/target_types.xml |
| +++ b/src/usr/targeting/common/xmltohb/target_types.xml |
| @@ -913,6 +913,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 b0429da..d023f50 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 1361834..1d6e6f1 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 50815f1..fa37dc9 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 e7a2d9f..9c729c3 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 3da20b2..e148bc9 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 5cc7bec..e4c4162 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 0000000..ec62237 |
| --- /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 0000000..092dd45 |
| --- /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 9b4e1f8..3656696 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 9c39a7f..e6cada7 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 9f85755..65d22e3 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 |
| -- |
| 1.8.2.2 |
| |