/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/usr/sbeio/sbe_ffdc_package_parser.C $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2017 */ /* [+] 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 */ #include #include #include #include extern trace_desc_t* g_trac_sbeio; #define SBE_TRACF(printf_string,args...) \ TRACFCOMP(g_trac_sbeio, "sbe ffdc: " printf_string,##args) namespace SBEIO { //--------------------------------------------------------------------------- FfdcParsedPackage::ParsedType FfdcParsedPackage::rcToParsedType(uint32_t fapiRc) { ParsedType retval{ParsedType::NONE}; switch(fapiRc) { case fapi2::RC_SBE_SCOM_FAILURE: case fapi2::RC_SBE_PIB_XSCOM_ERROR: case fapi2::RC_SBE_PIB_OFFLINE_ERROR: case fapi2::RC_SBE_PIB_PARTIAL_ERROR: case fapi2::RC_SBE_PIB_ADDRESS_ERROR: case fapi2::RC_SBE_PIB_CLOCK_ERROR: case fapi2::RC_SBE_PIB_PARITY_ERROR: case fapi2::RC_SBE_PIB_TIMEOUT_ERROR: { retval = ParsedType::SBE_SCOM_PIB_ERROR; break; } } return retval; } //--------------------------------------------------------------------------- void FfdcParsedPackage::doDefaultProcessing( const ffdc_package& i_ffdc_package, TARGETING::Target* i_target, errlHndl_t i_errl ) { ParsedType l_type = rcToParsedType(i_ffdc_package.rc); switch(l_type) { case ParsedType::SBE_SCOM_PIB_ERROR: { FfdcScomPibErrorPackage ffdcPackage{i_ffdc_package}; ffdcPackage(i_target, i_errl); break; } case ParsedType::NONE: { //If the schema matches then we probably have a new rc //that has yet to be accounted for. if(0 != i_ffdc_package.rc) { if(FfdcScomPibErrorPackage::doesPackageMatchSchema (i_ffdc_package)) { SBE_TRACF(WARN_MRK"Unknown RC matches " "SBE_SCOM_PIB_ERROR FFDC schema. RC: 0x%08X", i_ffdc_package.rc ); FfdcScomPibErrorPackage ffdcPackage{i_ffdc_package, true }; ffdcPackage(i_target, i_errl); } } break; } default: { SBE_TRACF(INFO_MRK"Unknown FFDC schema type encountered. " "Parsed Type: 0x%04X", static_cast(l_type) ); break; } } } //--------------------------------------------------------------------------- std::shared_ptr FfdcParsedPackage::getParsedPackage(const ffdc_package& i_ffdc_package) { std::shared_ptr retval; ParsedType l_type = rcToParsedType(i_ffdc_package.rc); switch(l_type) { case ParsedType::SBE_SCOM_PIB_ERROR: { FfdcParsedPackage* ptr = new FfdcScomPibErrorPackage(i_ffdc_package); retval.reset(ptr); break; } default: { SBE_TRACF(WARN_MRK"No FFDC schema found for RC 0x%08X", i_ffdc_package.rc ); retval.reset(new FfdcParsedPackage()); break; } } return retval; } //---------------------------------------------------------------------------- FfdcScomPibErrorPackage::FfdcScomPibErrorPackage(const ffdc_package& i_ffdc, bool ignoreRC ) { validateFFDCPackage(i_ffdc, ignoreRC); } //---------------------------------------------------------------------------- bool FfdcScomPibErrorPackage::validateFFDCPackage(const ffdc_package& i_ffdc, bool ignoreRC) { //Schema // u32 u32 u64 u32 u64 // | FAPI RC | SCOM ADDR SIZE | SCOM ADDR | PIB RC SIZE | PIB RC | bool retval{false}; do { if(nullptr == i_ffdc.ffdcPtr) { parsedType(ParsedType::NONE); break; } //if ignoreRC is true then schema validation has already been done. //Skip this step and parse the FFDC data. if(not ignoreRC) { if(ParsedType::SBE_SCOM_PIB_ERROR != rcToParsedType(i_ffdc.rc)) { parsedType(ParsedType::NONE); break; } if(not doesPackageMatchSchema(i_ffdc)) { parsedType(ParsedType::NONE); break; } } constexpr size_t scomAddressOffset = sizeof(uint32_t) + //FAPI RC sizeof(uint32_t); //size of Scom //Addr constexpr size_t pibRcOffset = sizeof(uint32_t) + //FAPI RC sizeof(uint32_t) + //size of Scom Addr sizeof(uint64_t) + //Scom Address sizeof(uint32_t); //size of PIB RC const char* l_buffer = reinterpret_cast(i_ffdc.ffdcPtr); iv_scomAddress = *(reinterpret_cast (l_buffer + scomAddressOffset)); iv_pibRc = *(reinterpret_cast (l_buffer + pibRcOffset)); //Make this instance valid by assigning a ParsedType other than none. parsedType(ParsedType::SBE_SCOM_PIB_ERROR); retval = true; } while(0); return retval; } //------------------------------------------------------------------------ bool FfdcScomPibErrorPackage::doesPackageMatchSchema(const ffdc_package& i_ffdc) { //Schema // u32 u32 u64 u32 u64 // | FAPI RC | SCOM ADDR SIZE | SCOM ADDR | PIB RC SIZE | PIB RC | bool retval{false}; do { if(nullptr == i_ffdc.ffdcPtr) { return retval; } constexpr uint32_t l_expectedPIBSize = sizeof(uint64_t); constexpr uint32_t l_expectedScomAddrSize{sizeof(uint64_t)}; constexpr size_t expectedSize = sizeof(uint32_t) + //FAPI RC sizeof(uint32_t) + //size of Scom Addr sizeof(uint64_t) + //Scom Address sizeof(uint32_t) + //size of PIB RC sizeof(uint64_t); //PIB RC constexpr size_t scomAddrSizeOffset = sizeof(uint32_t); //FAPI RC constexpr size_t pibSizeOffset = sizeof(uint32_t) + //FAPI RC sizeof(uint32_t) + //size of Scom Addr sizeof(uint64_t); //Scom Address if(expectedSize != i_ffdc.size) { break; } const char* l_buffer = reinterpret_cast(i_ffdc.ffdcPtr); if(l_expectedScomAddrSize != *(reinterpret_cast (l_buffer + scomAddrSizeOffset))) { break; } uint32_t l_pibSize = *(reinterpret_cast (l_buffer + pibSizeOffset)); if(l_expectedPIBSize != l_pibSize) { //This can be deduced as uint32_t, we'll check uint16_t as well if(not (l_pibSize < l_expectedPIBSize && l_pibSize != 0 && 0 == l_pibSize%sizeof(uint16_t))) { break; } } retval = true; } while(0); return retval; } //-------------------------------------------------------------------------- void FfdcScomPibErrorPackage::addFruCallouts(TARGETING::Target* i_target, errlHndl_t i_errl ) const { if(isValid()) { if(PIB::PIB_NO_ERROR != iv_pibRc && INVALID_DATA != iv_pibRc) { PIB::addFruCallouts (i_target, iv_pibRc, iv_scomAddress, i_errl); } } } //--------------------------------------------------------------------------- void FfdcScomPibErrorPackage::operator()(TARGETING::Target* i_target, errlHndl_t i_errl ) const { if(isValid()) { addFruCallouts(i_target, i_errl); } } }