summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/sbeio/sbe_ffdc_package_parser.H283
-rw-r--r--src/include/usr/sbeio/sbe_ffdc_parser.H8
-rw-r--r--src/usr/sbeio/makefile2
-rw-r--r--src/usr/sbeio/sbe_ffdc_package_parser.C299
-rw-r--r--src/usr/sbeio/sbe_ffdc_parser.C19
-rw-r--r--src/usr/sbeio/sbe_fifo_buffer.C306
-rw-r--r--src/usr/sbeio/sbe_fifo_buffer.H318
-rw-r--r--src/usr/sbeio/sbe_fifodd.C158
-rw-r--r--src/usr/sbeio/sbe_fifodd.H2
-rw-r--r--src/usr/sbeio/sbe_psudd.C43
-rw-r--r--src/usr/sbeio/test/makefile4
-rw-r--r--src/usr/sbeio/test/sbe_ffdc_package_parser_test.H688
-rw-r--r--src/usr/sbeio/test/sbe_fifo_buffer_test.H1866
-rw-r--r--src/usr/sbeio/test/sbe_test_support.H91
14 files changed, 3975 insertions, 112 deletions
diff --git a/src/include/usr/sbeio/sbe_ffdc_package_parser.H b/src/include/usr/sbeio/sbe_ffdc_package_parser.H
new file mode 100644
index 000000000..1fa9cada9
--- /dev/null
+++ b/src/include/usr/sbeio/sbe_ffdc_package_parser.H
@@ -0,0 +1,283 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/sbeio/sbe_ffdc_package_parser.H $ */
+/* */
+/* 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 */
+#ifndef __SBEIO_SBE_FFDC_PACKAGE_PARSER_H
+#define __SBEIO_SBE_FFDC_PACKAGE_PARSER_H
+
+#include <stdint.h>
+#include <memory>
+
+#include <errl/errlentry.H>
+#include <sbeio/sbe_ffdc_parser.H>
+#include <targeting/common/target.H>
+
+namespace SBEIO
+{
+
+/**
+ * @brief A class to support processing of parsed ffdc data.
+ *
+ * FFDC data schema is related to RC codes. There does not
+ * exist a facility code to identify common types of FFDC data.
+ * Instead, each RC code is given an FFDC schema based upon settings
+ * in the error_info xml files. Although many error codes share the same
+ * FFDC format, there is nothing to relate similar FFDC schemas to RC values,
+ * The mapping is the other way around, individual fapi RC codes map to
+ * FFDC formats. In addition, because of the use of template type deduction
+ * in populating FFDC data, type information which may prove useful for parsing
+ * is lost. To illustrate, the SBE uses a global variable to hold FFDC data for
+ * a request. The global variable contains a field for storing the fapiRC code
+ * and an array of up to 10 sbeFfdc_t structs used to hold the FFDC data. For a
+ * Scom PIB error, the schema of the FFDC places the scom address and size in
+ * first sbeFfdc_t struct and the pib rc in the second struct. Each sbeFfdc_t
+ * struct is just a uint64_t for the data and a uint32_t for the size. There
+ * is no type information stored. The uint64_t in some instances can hold
+ * a pointer to a target, in other instances data such as the PIB RC code and
+ * yet in other cases an address such as the scom address. The Scom PIB errors
+ * from the SBE uses only two of the sbeFfdc_t slots. Other errors use 3,4 or
+ * more sbeFfdc_t data.
+ * Because of the lack of parsing support available, this base class and
+ * derived classes are manually coded to group fapi RC values with similar FFDC
+ * formats in order to aid parsing of FFDC data. Currently, we only parse the
+ * format used for the scom pib memory errors returned from the SBE.
+ *
+ *
+ */
+class FfdcParsedPackage
+{
+public:
+
+ /**
+ * @brief Used to identify FFDC schema.
+ *
+ */
+ enum class ParsedType{
+ NONE,
+ SBE_SCOM_PIB_ERROR
+ };
+
+ virtual ~FfdcParsedPackage() = default;
+
+ /**
+ * @brief Determines if the FFDC package was successfully parsed.
+ *
+ * @return True if the ffdc package was parsed, false otherwise.
+ */
+ bool isValid() const {return iv_packageType != ParsedType::NONE;}
+
+ /**
+ * @brief Obtain the FFDC package type that was parsed.
+ */
+ ParsedType parsedType() const {return iv_packageType;}
+
+ /**
+ * @brief Perform the default action on the parsed
+ * ffdc data.
+ *
+ * @param[in] i_target, the target of the request.
+ * @param[in] i_errl, error entry for processing.
+ *
+ */
+ virtual void operator()(TARGETING::Target* i_target,
+ errlHndl_t i_errl
+ ) const {};
+
+ /**
+ * @brief bool operator for isValid.
+ *
+ */
+ operator bool() const {return isValid();}
+
+ /**
+ * @brief Convert fapiRC to a ParsedType.
+ *
+ * @param[in] fapiRc, the rc to convert.
+ *
+ * @return The ParsedType corresponding to fapiRc
+ *
+ */
+ static ParsedType rcToParsedType(uint32_t fapiRc);
+
+ /**
+ * @brief parse the FFDC package and perform the default
+ * operation if parsing was successful.
+ *
+ * @param[in] i_ffdc_package, the ffdc to parse and process.
+ * @param[in] i_target, the target of the default processing.
+ * @param[in] i_errl, the ErrlEntry to be used for default processing.
+ *
+ */
+ static void doDefaultProcessing(const ffdc_package& i_ffdc_package,
+ TARGETING::Target* i_target,
+ errlHndl_t i_errl
+ );
+
+ /**
+ * @brief Parse the given FFDC data.
+ *
+ * @param[in] i_ffdc_package to parse.
+ *
+ * @return a shared pointer to an object derived from FfdcParsedPackage.
+ * If the package could not be parsed a raw FfdcParsedPackage
+ * is returned.
+ */
+ static std::shared_ptr<const FfdcParsedPackage>
+ getParsedPackage(const ffdc_package& i_ffdc_package);
+
+protected:
+
+ /**
+ * @brief Set the parsed ffdc type.
+ *
+ * @param[in] The new Parsed FFDC Type value.
+ *
+ */
+ void parsedType(const ParsedType& i_parsedType)
+ {
+ iv_packageType = i_parsedType;
+ }
+
+private:
+
+ ParsedType iv_packageType{ParsedType::NONE}; /**< The FFDC type */
+};
+
+
+
+/**
+ * @brief Processing for SBE scom pib FFDC.
+ *
+ * The FFDC schema parsed by this class is as follows:
+ *
+ * u32 u32 u64 u32 u64
+ * | FapiRC | Scom Addr Size | Scom Addr | PIB RC Size | PIB RC |
+ *
+ */
+class FfdcScomPibErrorPackage: public FfdcParsedPackage
+{
+public:
+ /**
+ * @brief Contsructor
+ *
+ * @param[in] i_ffdc, the unparsed raw ffdc data.
+ * @param[in] i_ignoreRC, if true then validation of the ffdc
+ * schema has already been performed by the
+ * static method doesPackageMatchSchema. In this
+ * case the rc of the ffdc does not match the list of
+ * known fapiRC values that correspond to the ffdc
+ * schema parsed by this class. However, if it is assumed
+ * that a new fapiRC is responsible for this condition
+ * then we may use this class to process the FFDC regardless
+ * of the corresponding fapiRC. This could prove useful as
+ * SBE errors in messaging currently only send Scom Pib errors
+ * as the first FFDC entry.
+ */
+ explicit FfdcScomPibErrorPackage(const ffdc_package& i_ffdc,
+ bool i_ignoreRC = false);
+
+ virtual ~FfdcScomPibErrorPackage() = default;
+
+ /**
+ * @brief Call operator for default processing. For this FFDC schema
+ * we call the addFruCallouts method.
+ *
+ * @param[in] i_target, the target of the default processing.
+ * @param[in] i_errl, the ErrlEntry to be used for default processing.
+ *
+ */
+ void operator() (TARGETING::Target* i_target,
+ errlHndl_t i_errl
+ ) const override;
+
+ /**
+ * @brief Use parsed data to add Fru Callouts. The method
+ * is virtual to facilitate a unit test seam.
+ *
+ * @param[in] i_target, the target for the callout.
+ * @param[in] i_errl, the ErrlEntry to which to add the callout.
+ *
+ */
+ virtual void addFruCallouts (TARGETING::Target* i_target,
+ errlHndl_t i_errl
+ ) const;
+
+ /**
+ * @brief Accessor for the PIB RC parsed data.
+ *
+ * @return The PIB RC Code from the FFDC data.
+ *
+ */
+ uint64_t getPibRc() const {return iv_pibRc;}
+
+ /**
+ * @brief Accessor for the PIB RC parsed data.
+ *
+ * @return The PIB RC Code from the FFDC data.
+ *
+ */
+ uint64_t getScomAddress() const {return iv_scomAddress;}
+
+ /**
+ * @brief Check if the FFDC schema matches that expected by this class,
+ * with the exception of the RC code. This is intended for use
+ * when we are always expecting a certain FFDC schema from a
+ * function call but perhaps a new RC has been added that has not
+ * yet been added to those we know of.
+ *
+ * @param[in] i_ffdc: the ffdc data to validate.
+ *
+ * @return True if the FFDC schema matches what we are expecting, false
+ * otherwise.
+ *
+ */
+ static bool doesPackageMatchSchema(const ffdc_package& i_ffdc);
+
+ static const uint64_t INVALID_DATA = uint64_t(-1);
+
+private:
+
+ /**
+ * @brief Validate that the passed in FFDC data has a schema consistent
+ * with what we are expecting.
+ *
+ * @param[in] i_ffdc, the FFDC data to validate.
+ * @param[in] i_ignoreRC, Do not base validation on RC value. Setting
+ * this parameter to true indicates that the schema has already
+ * been checked by the doesPackageMatchSchema function and
+ * as such we just need to parse the data and not validate.
+ *
+ * @return True if the FFDC data was successfully validated and parsed,
+ * False otherwise.
+ *
+ */
+ bool validateFFDCPackage(const ffdc_package& i_ffdc, bool i_ignoreRC);
+
+ uint64_t iv_pibRc{INVALID_DATA}; /**< parsed pib rc code */
+ uint64_t iv_scomAddress{INVALID_DATA}; /**< parsed scom address */
+};
+
+
+}
+
+#endif
diff --git a/src/include/usr/sbeio/sbe_ffdc_parser.H b/src/include/usr/sbeio/sbe_ffdc_parser.H
index a18d8a1ad..41ebe52ce 100644
--- a/src/include/usr/sbeio/sbe_ffdc_parser.H
+++ b/src/include/usr/sbeio/sbe_ffdc_parser.H
@@ -83,6 +83,14 @@ class SbeFFDCParser
void * getFFDCPackage(uint8_t i_index);
/**
+ * @brief Get the raw ffdc package stored
+ * @retval: True if an ffdc package is stored at index, else false.
+ * @param[in] i_index index number
+ * @param[out] o_package The package structure to fill.
+ */
+ bool getFFDCPackage(uint8_t i_index, ffdc_package& o_package);
+
+ /**
* @brief Get the return code of the package
* @retval: return code of the ffdc package
* @param[in] i_index index number
diff --git a/src/usr/sbeio/makefile b/src/usr/sbeio/makefile
index d1369e485..4174a0181 100644
--- a/src/usr/sbeio/makefile
+++ b/src/usr/sbeio/makefile
@@ -45,6 +45,8 @@ OBJS += sbe_scomAccessdd.o
OBJS += sbe_ffdc_parser.o
OBJS += sbe_setFFDCAddr.o
OBJS += sbe_memRegionMgr.o
+OBJS += sbe_fifo_buffer.o
+OBJS += sbe_ffdc_package_parser.o
VPATH += ${ROOTPATH}/src/import/chips/p9/procedures/hwp/perv/
include ${ROOTPATH}/procedure.rules.mk
diff --git a/src/usr/sbeio/sbe_ffdc_package_parser.C b/src/usr/sbeio/sbe_ffdc_package_parser.C
new file mode 100644
index 000000000..213d6133b
--- /dev/null
+++ b/src/usr/sbeio/sbe_ffdc_package_parser.C
@@ -0,0 +1,299 @@
+/* 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 <sbeio/sbe_ffdc_package_parser.H>
+
+#include <hwp_return_codes.H>
+#include <trace/interface.H>
+#include <xscom/piberror.H>
+
+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<uint16_t>(l_type)
+ );
+ break;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+std::shared_ptr<const FfdcParsedPackage>
+FfdcParsedPackage::getParsedPackage(const ffdc_package& i_ffdc_package)
+{
+ std::shared_ptr<const FfdcParsedPackage> 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<const char*>(i_ffdc.ffdcPtr);
+
+ iv_scomAddress = *(reinterpret_cast<const uint64_t*>
+ (l_buffer + scomAddressOffset));
+
+ iv_pibRc = *(reinterpret_cast<const uint64_t*>
+ (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<const char*>(i_ffdc.ffdcPtr);
+
+ if(l_expectedScomAddrSize != *(reinterpret_cast<const uint32_t*>
+ (l_buffer + scomAddrSizeOffset)))
+ {
+ break;
+ }
+
+ uint32_t l_pibSize = *(reinterpret_cast<const uint32_t*>
+ (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);
+ }
+}
+
+}
diff --git a/src/usr/sbeio/sbe_ffdc_parser.C b/src/usr/sbeio/sbe_ffdc_parser.C
index b742c8cb8..029f9182c 100644
--- a/src/usr/sbeio/sbe_ffdc_parser.C
+++ b/src/usr/sbeio/sbe_ffdc_parser.C
@@ -223,6 +223,25 @@ void * SbeFFDCParser::getFFDCPackage(uint8_t i_index)
}
/*
+ * @brief returns the FFDC package
+ */
+bool SbeFFDCParser::getFFDCPackage(uint8_t i_index, ffdc_package& o_package)
+{
+ bool retval{false};
+ uint8_t l_size = getTotalPackages();
+ if((i_index >= 0) && (i_index < l_size))
+ {
+ ffdc_package *l_ffdcPkg = iv_ffdcPackages.at(i_index);
+ if(l_ffdcPkg)
+ {
+ o_package = *l_ffdcPkg;
+ retval = true;
+ }
+ }
+ return retval;
+}
+
+/*
* @brief returns the RC word
*/
uint32_t SbeFFDCParser::getPackageRC(uint8_t i_index)
diff --git a/src/usr/sbeio/sbe_fifo_buffer.C b/src/usr/sbeio/sbe_fifo_buffer.C
new file mode 100644
index 000000000..c6a9914a1
--- /dev/null
+++ b/src/usr/sbeio/sbe_fifo_buffer.C
@@ -0,0 +1,306 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/sbe_fifo_buffer.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 "sbe_fifo_buffer.H"
+#include <trace/interface.H>
+
+#include <algorithm>
+#include <string.h>
+
+extern trace_desc_t* g_trac_sbeio;
+
+#define SBE_TRACF(printf_string,args...) \
+ TRACFCOMP(g_trac_sbeio, printf_string,##args)
+
+constexpr size_t STATUS_WORD_SIZE =
+ sizeof(SBEIO::SbeFifo::statusHeader)/sizeof(uint32_t);
+
+namespace SBEIO
+{
+
+//------------------------------------------------------------------------
+const char* SbeFifoRespBuffer::cv_stateStrings[] = {
+ "INVALID_CALLER_BUFFER",
+ "OVERRUN",
+ "MSG_SHORT_READ",
+ "MSG_INVALID_OFFSET",
+ "MSG_COMPLETE",
+ "MSG_INCOMPLETE"
+ };
+
+//-------------------------------------------------------------------------
+SbeFifoRespBuffer::SbeFifoRespBuffer(uint32_t* i_fifoBuffer,
+ size_t bufferWordSize):
+ iv_callerBufferPtr(i_fifoBuffer),
+ iv_callerWordSize(
+ std::min(bufferWordSize,
+ MSG_BUFFER_SIZE)
+ )
+{
+ do
+ {
+ memset(iv_localMsgBuffer, 0, sizeof(iv_localMsgBuffer));
+
+ if(not i_fifoBuffer || iv_callerWordSize < STATUS_WORD_SIZE)
+ {
+ SBE_TRACF(ERR_MRK"SbeFifoRespBuffer CTOR: Caller buffer invalid.");
+ iv_state = INVALID_CALLER_BUFFER;
+ break;
+ }
+
+ memset(iv_callerBufferPtr, 0, iv_callerWordSize*sizeof(uint32_t));
+ }
+ while(0);
+}
+
+//---------------------------------------------------------------------
+bool SbeFifoRespBuffer::append(uint32_t i_value)
+{
+ bool retval = false;
+
+ if(iv_state == MSG_INCOMPLETE)
+ {
+ if(iv_index < iv_callerWordSize)
+ {
+ iv_callerBufferPtr[iv_index] = i_value;
+ }
+
+ if(iv_index < MSG_BUFFER_SIZE)
+ {
+ iv_localMsgBuffer[iv_index] = i_value;
+ ++iv_index;
+ retval = true;
+ }
+ else
+ {
+ SBE_TRACF(ERR_MRK"SbeFifoRespBuffer::append: Overran buffer.");
+ iv_state = OVERRUN;
+ }
+ }
+ else
+ {
+ SBE_TRACF(INFO_MRK"SbeFifoRespBuffer::append. "
+ "Invalid state for append, current state %s",
+ getStateString()
+ );
+ }
+
+ return retval;
+}
+
+//-------------------------------------------------------------------
+void SbeFifoRespBuffer::completeMessage()
+{
+ do
+ {
+ if(MSG_INCOMPLETE == iv_state)
+ {
+ //Message Schema:
+ // |Return Data (optional)| Status Header | FFDC (optional)
+ // |Offset to Status Header (starting from EOT) | EOT |
+
+ //Final index for a minimum complete message (No return data
+ //and no FFDC):
+ //Word Length of status header +
+ //Length of Offset (1) + Length of EOT (1)
+ if(iv_index < (STATUS_WORD_SIZE + 2))
+ {
+ SBE_TRACF(ERR_MRK"SbeFifoRespBuffer::completeMessage: "
+ "Complete call caused short read."
+ );
+ iv_state = MSG_SHORT_READ;
+ break;
+ }
+
+ // |offset to header| EOT marker | current insert pos | <- iv_index
+ // The offset is how far to move back from from the EOT position to
+ // to get the index of the Status Header.
+ iv_offsetIndex = (iv_index - 2);
+
+ //Validate that the offset to the status header is in range
+ if((iv_localMsgBuffer[iv_offsetIndex] - 1) > iv_offsetIndex)
+ {
+ //offset is to large - would go before the buffer.
+ SBE_TRACF(ERR_MRK"SbeFifoRespBuffer::completeMessage: "
+ "The offset to the StatusHeader is too large."
+ );
+ iv_state = MSG_INVALID_OFFSET;
+ break;
+ }
+ else if(iv_localMsgBuffer[iv_offsetIndex] <
+ (STATUS_WORD_SIZE + 1))
+ {
+ //Minimum offset (no ffdc) is StatusHeader size + 1
+ SBE_TRACF(ERR_MRK"SbeFifoRespBuffer::completeMessage: "
+ "The offset to the StatusHeader is too small."
+ );
+ iv_state = MSG_INVALID_OFFSET;
+ break;
+ }
+
+ //Set The StatusHeader index
+ iv_statusIndex = iv_offsetIndex -
+ (iv_localMsgBuffer[iv_offsetIndex] - 1);
+
+ //Determine if there is FFDC data in the buffer. We do this by
+ //checking that the index after the status header is less than the
+ //offset index. If the offset index immediately follows the status
+ //header then there is no FFDC in the header.
+ if((iv_statusIndex + STATUS_WORD_SIZE) < iv_offsetIndex)
+ {
+ iv_ffdcIndex = iv_statusIndex + STATUS_WORD_SIZE;
+ iv_ffdcSize = (iv_offsetIndex - iv_ffdcIndex);
+ }
+
+ iv_state = MSG_COMPLETE;
+ }
+ }
+ while(0);
+
+ return;
+}
+
+//-------------------------------------------------------------------------
+bool SbeFifoRespBuffer::msgContainsFFDC()
+{
+ bool retval{false};
+
+ if(isMsgComplete())
+ {
+ if(INVALID_INDEX != iv_ffdcIndex)
+ {
+ retval = true;
+ }
+ }
+
+ return retval;
+}
+
+//------------------------------------------------------------------------
+const void * SbeFifoRespBuffer::getFFDCPtr()
+{
+ const void* retval{};
+
+ if(msgContainsFFDC())
+ {
+ retval =
+ reinterpret_cast<const void*>(&iv_localMsgBuffer[iv_ffdcIndex]);
+ }
+
+ return retval;
+}
+
+//--------------------------------------------------------------------------
+size_t SbeFifoRespBuffer::getFFDCByteSize()
+{
+ size_t retval = 0;
+
+ if(msgContainsFFDC())
+ {
+ retval = iv_ffdcSize * sizeof(uint32_t);
+ }
+
+ return retval;
+}
+
+//--------------------------------------------------------------------------
+size_t SbeFifoRespBuffer::getFFDCWordSize()
+{
+ size_t retval = 0;
+
+ if(msgContainsFFDC())
+ {
+ retval = iv_ffdcSize;
+ }
+
+ return retval;
+}
+
+//---------------------------------------------------------------------------
+const SbeFifo::statusHeader * SbeFifoRespBuffer::getStatusHeader()
+{
+ const SbeFifo::statusHeader* retval{};
+
+ if(isMsgComplete())
+ {
+ retval = reinterpret_cast<const SbeFifo::statusHeader *>
+ (&iv_localMsgBuffer[iv_statusIndex]);
+ }
+
+ return retval;
+}
+
+//---------------------------------------------------------------------------
+bool SbeFifoRespBuffer::msgContainsReturnData()
+{
+ bool retval{false};
+
+ if(isMsgComplete())
+ {
+ retval = (iv_statusIndex > 0);
+ }
+
+ return retval;
+}
+
+//---------------------------------------------------------------------------
+const void * SbeFifoRespBuffer::getReturnData()
+{
+ const void * retval{};
+
+ if(msgContainsReturnData())
+ {
+ retval = reinterpret_cast<const void*>(&iv_localMsgBuffer[0]);
+ }
+
+ return retval;
+}
+
+//----------------------------------------------------------------------------
+size_t SbeFifoRespBuffer::getReturnDataByteSize()
+{
+ size_t retval = 0;
+
+ if(msgContainsReturnData())
+ {
+ retval = iv_statusIndex * sizeof(uint32_t);
+ }
+
+ return retval;
+}
+
+//---------------------------------------------------------------------------
+size_t SbeFifoRespBuffer::getReturnDataWordSize()
+{
+ size_t retval = 0;
+
+ if(msgContainsReturnData())
+ {
+ retval = iv_statusIndex;
+ }
+
+ return retval;
+}
+
+} //End Namespace SBEIO
diff --git a/src/usr/sbeio/sbe_fifo_buffer.H b/src/usr/sbeio/sbe_fifo_buffer.H
new file mode 100644
index 000000000..fe5e50092
--- /dev/null
+++ b/src/usr/sbeio/sbe_fifo_buffer.H
@@ -0,0 +1,318 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/sbe_fifo_buffer.H $ */
+/* */
+/* 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 */
+#ifndef __SBEIO_SBE_FIFO_BUFFER_H
+#define __SBEIO_SBE_FIFO_BUFFER_H
+
+#include <stdint.h>
+
+#include "sbe_fifodd.H"
+
+namespace SBEIO
+{
+
+/**
+ * @brief A class for managing duel input buffers for sbeio fifo response
+ * messaging.
+ *
+ * Sbeio messaging uses a pair of buffers for parsing fifo response
+ * messages. The first buffer is a caller supplied buffer that must be large
+ * enough to hold required data for a given message response. For example,
+ * a read command will have a response that will contain the data read and a
+ * status header. A write command will have a response that will contain
+ * only a status header detailing the result of the command. In addition,
+ * response data can include FFDC data upon an error. The user supplied
+ * buffer does not need to be big enough to hold the extra data since this
+ * information is processed by the messaging code before returning to the
+ * caller. As a result, a second buffer which should be large enough to
+ * to contain any FFDC information is processed in parallel with the caller
+ * supplied buffer in order to capture a full response.
+ */
+class SbeFifoRespBuffer
+{
+public:
+
+ /**
+ * @brief Constructor.
+ *
+ * @param[in] i_fifoBuffer - The caller supplied buffer.
+ * @param[in] bufferWordSize - The size of the caller supplied buffer in
+ * uint32_t units.
+ */
+ explicit SbeFifoRespBuffer(uint32_t * i_fifoBuffer, size_t bufferWordSize);
+
+ //This is a helper class intended for local use only.
+ SbeFifoRespBuffer(const SbeFifoRespBuffer&) = delete;
+ SbeFifoRespBuffer(SbeFifoRespBuffer&&) = delete;
+
+ SbeFifoRespBuffer& operator=(const SbeFifoRespBuffer&) = delete;
+ SbeFifoRespBuffer& operator=(SbeFifoRespBuffer&&) = delete;
+
+ //=======================
+ // Message construction
+ //========================
+
+ /**
+ * @brief append a uint32 to the next buffer insert position.
+ *
+ * @param[in] i_value - The value to add to the buffers.
+ *
+ * @return True if the value was able to be stored in at least the local
+ * buffer, false otherwise.
+ */
+ bool append(uint32_t i_value);
+
+ /**
+ * @brief When the DN FIFO Dequeued EOT flag is detected
+ * externally, this method is called to validate
+ * the buffer data and set indexes to the status
+ * and ffdc areas.
+ */
+ void completeMessage();
+
+ //============================
+ // Messaging State
+ //============================
+
+ /**
+ * @brief operator that returns true if the messaging
+ * state is MSG_INCOMPLETE. This indicates that
+ * data is able to be appended to the buffer(s)
+ */
+ operator bool() const {return MSG_INCOMPLETE == iv_state;}
+
+ /**
+ * @brief Current state of the messaging buffer
+ *
+ */
+ enum State{
+ INVALID_CALLER_BUFFER = 0, /**< enum Caller buffer too short */
+ OVERRUN = 1, /**< enum message larger than local
+ buffer */
+ MSG_SHORT_READ = 2, /**< enum Message is shorter that
+ header */
+ MSG_INVALID_OFFSET = 3, /**< enum The message contains an
+ invalid status header offset */
+ MSG_COMPLETE = 4, /**< enum The message was read in
+ successfully */
+ MSG_INCOMPLETE = 5 /**< enum The message is being
+ constructed */
+ };
+
+ /**
+ * @brief Accessor for messaging state.
+ *
+ * @return The state of the messaging buffers.
+ */
+ State getState() const {return iv_state;}
+
+ /**
+ * @brief A simplified state accessor.
+ *
+ * @return True if the state is MSG_COMPLETE or MSG_INCOMPLETE
+ * False otherwise.
+ */
+ bool getStatus() const {return (MSG_COMPLETE == iv_state ||
+ MSG_INCOMPLETE == iv_state);}
+
+ /**
+ * @brief Accessor for if the message has been successfully completed.
+ *
+ * @return True if the message has been successfully completed.
+ */
+ bool isMsgComplete() const {return MSG_COMPLETE == iv_state;}
+
+ //=================
+ //FFDC
+ //=================
+
+ /**
+ * @brief Does the message contain FFDC data.
+ *
+ * @return True if the message is complete and contains FFDC data
+ * False otherwise.
+ */
+ bool msgContainsFFDC();
+
+ /**
+ * @brief Accessor to FFDC data.
+ *
+ * @returns pointer to FFDC data if the message is complete and contains
+ * FFDC data. A nullptr is returned otherwise.
+ *
+ */
+ const void * getFFDCPtr();
+
+ /**
+ * @brief FFDC data size.
+ *
+ * @return FFDC data size in bytes or 0 if the message is incomplete
+ * or does not have FFDC data.
+ */
+ size_t getFFDCByteSize();
+
+ /**
+ * @brief FFDC data size.
+ *
+ * @return FFDC data size in words or 0 if the message is incomplete
+ * or does not have FFDC data.
+ */
+ size_t getFFDCWordSize();
+
+ //=================================
+ // Status Header
+ //=================================
+
+ /**
+ * @brief Returns a pointer to the StatusHeader struct.
+ *
+ * @return A pointer to the StatusHeader struct if the
+ * buffer state is MSG_COMPLETE, or a NULL pointer
+ * otherwise.
+ */
+ const SbeFifo::statusHeader * getStatusHeader();
+
+ //================================
+ // Return Data
+ //================================
+
+ /**
+ * @brief Determine if the message contains return data.
+ *
+ * @return True if the message is complete and has return data
+ * False otherwise.
+ *
+ */
+ bool msgContainsReturnData();
+
+ /**
+ * @brief Obtain a pointer to return data
+ *
+ * @return A pointer to return data if the message is complete and
+ * contains return data. A nullptr is returned otherwise.
+ */
+ const void * getReturnData();
+
+ /**
+ * @brief Obtain the return data size in bytes.
+ *
+ * @return The return data size in bytes if the message is complete and
+ * contains return data, 0 is returned otherwise.
+ */
+ size_t getReturnDataByteSize();
+
+ /**
+ * @brief Obtain the return data size in uint32_t words.
+ *
+ * @return The return data size in bytes if the message is complete and
+ * contains return data, 0 is returned otherwise.
+ */
+ size_t getReturnDataWordSize();
+
+ /*
+ * @brief Obtain the local buffer for debugging.
+ *
+ * @return A pointer to the local buffer.
+ */
+ const uint32_t * localBuffer() const {return iv_localMsgBuffer;}
+
+ /*
+ * @brief Obtain the current index for debugging
+ *
+ * @return - The current Index
+ */
+ size_t index() const {return iv_index;}
+
+ /*
+ * @brief Obtain the offset Index for debugging
+ *
+ * @return - The offset Index
+ *
+ */
+ size_t offsetIndex() const {return iv_offsetIndex;}
+
+ /*
+ * @brief Obtain the offset to the Status Header
+ * for debugging and error reporting.
+ *
+ * @return - The offset to the status header.
+ *
+ */
+ size_t offset() const {return iv_localMsgBuffer[iv_offsetIndex];}
+
+ //=========================
+ // Class Constants
+ //=========================
+ static const size_t MSG_BUFFER_SIZE = 2048;
+ static const size_t INVALID_INDEX = size_t(-1);
+
+protected:
+
+ //=====================
+ // Unit Test Access
+ //=====================
+ const uint32_t * callerBuffer() const {return iv_callerBufferPtr;}
+ size_t callerWordSize() const {return iv_callerWordSize;}
+
+ size_t statusIndex() const {return iv_statusIndex;}
+ size_t ffdcIndex() const {return iv_ffdcIndex;}
+
+ const char* getStateString() const {return cv_stateStrings[iv_state];}
+
+ void setBufferState(State newValue){iv_state = newValue;}
+
+private:
+
+ //====================
+ // Buffers
+ //====================
+
+ uint32_t iv_localMsgBuffer[MSG_BUFFER_SIZE]; /**< local buffer large enough
+ to hold FFDC data */
+
+ uint32_t * const iv_callerBufferPtr{}; /**< caller supplied buffer should
+ be large enough to hold at least
+ return data and status */
+
+ const size_t iv_callerWordSize; /**< caller buffer size in uint32_t units */
+
+ //====================
+ // Index and State
+ //====================
+
+ size_t iv_index{}; /**< denotes the next insert position */
+ size_t iv_offsetIndex{INVALID_INDEX}; /**< position of offset to the
+ status header */
+ size_t iv_statusIndex{INVALID_INDEX}; /**< position of the status header */
+ size_t iv_ffdcIndex{INVALID_INDEX}; /**< position of FFDC data if any */
+ size_t iv_ffdcSize{0}; /**< size of ffdc data if any is present */
+
+ State iv_state{MSG_INCOMPLETE}; /**< Messaging State */
+
+ static const char* cv_stateStrings[]; /**< Messaging State Strings */
+};
+
+} //End Namespace SBEIO
+
+#endif
diff --git a/src/usr/sbeio/sbe_fifodd.C b/src/usr/sbeio/sbe_fifodd.C
index 43342b790..7a26b5b71 100644
--- a/src/usr/sbeio/sbe_fifodd.C
+++ b/src/usr/sbeio/sbe_fifodd.C
@@ -37,7 +37,9 @@
#include <targeting/common/targetservice.H>
#include <sbeio/sbeioreasoncodes.H>
#include <errl/errlreasoncodes.H>
+#include "sbe_fifo_buffer.H"
#include "sbe_fifodd.H"
+#include <sbeio/sbe_ffdc_package_parser.H>
#include <sbeio/sbe_ffdc_parser.H>
#include <initservice/initserviceif.H>
#include <kernel/pagemgr.H>
@@ -315,7 +317,8 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
uint32_t i_responseSize)
{
errlHndl_t errl = NULL;
- uint32_t l_readBuffer[READ_BUFFER_SIZE];
+ SbeFifoRespBuffer l_fifoBuffer{o_pFifoResponse,
+ i_responseSize/sizeof(uint32_t)};
SBE_TRACD(ENTER_MRK "readResponse");
@@ -327,21 +330,10 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
// to the status, which is placed at the end of the returned data
// in order to reflect errors during transfer.
- uint32_t * l_pReceived = o_pFifoResponse; //advance as words received
- uint32_t l_maxWords = i_responseSize / sizeof(uint32_t);
- //Number of words in response buffer.
- uint32_t l_recWords = 0; //Number of words received.
- //Used validate "distance" to status
- //and pointer to status.
bool l_EOT = false;
- uint32_t l_last = 0; // last word received. The "current" word.
- // Final read is "distance" in words to
- // status header including the final
- // distance word.
- // receive words until EOT, but do not exceed response buffer size
- bool l_overRun = false;
-
- do
+
+ while(l_fifoBuffer) //keep reading data until an error or until the
+ //message is completely read.
{
// Wait for data to be ready to receive (download) or if the EOT
// has been sent. If not EOT, then data ready to receive.
@@ -356,52 +348,21 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
if (l_status & DNFIFO_STATUS_DEQUEUED_EOT_FLAG)
{
l_EOT = true;
- // ignore EOT dummy word
- if (l_recWords >= (sizeof(statusHeader)/sizeof(uint32_t)) )
- {
- if(l_overRun == false) {
- l_pReceived--;
- l_recWords--;
- l_last = o_pFifoResponse[l_recWords-1];
- } else {
- l_last = (uint32_t) l_readBuffer[l_recWords-2];
- }
- }
- break;
+ l_fifoBuffer.completeMessage();
}
-
- // When error occurs, SBE will write more than l_maxWords
- // we have to keep reading 1 word at a time until we get EOT
- // or more than READ_BUFFER_SIZE. Save what we read in the buffer
- if (l_recWords >= l_maxWords)
+ else
{
- l_overRun = true;
- }
-
- // read next word
- errl = readFsi(i_target,SBE_FIFO_DNFIFO_DATA_OUT,&l_last);
- if (errl) break;
+ uint32_t l_data{};
+ // read next word
+ errl = readFsi(i_target,SBE_FIFO_DNFIFO_DATA_OUT,&l_data);
+ if (errl) break;
- l_readBuffer[l_recWords] = l_last;
-
- if(l_overRun == false) {
- *l_pReceived = l_last; //copy to returned output buffer
- l_pReceived++; //advance to next position
- }
- l_recWords++; //count word received
- SBE_TRACD("Read a byte from data reg: 0x%.8X",l_last);
- if(l_recWords > READ_BUFFER_SIZE) {
- SBE_TRACF(ERR_MRK "readResponse: data overflow without EOT");
- break;
+ l_fifoBuffer.append(l_data);
}
}
- while (1); // exit check in middle of loop
if (errl) break;
- // At this point,
- // l_recWords of words received.
- // l_pReceived points to 1 word past last word received.
- // l_last has last word received, which is "distance" to status
+
// EOT is expected before running out of response buffer
if (!l_EOT)
{
@@ -439,23 +400,19 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
if (errl) break;
//Determine if successful.
- //Last word received has distance to status in words including itself.
- //l_recWords has number of words received.
- //Need to have received at least status header and distance word.
- if ( (l_last < (sizeof(statusHeader)/sizeof(uint32_t) + 1)) ||
- (l_recWords < (sizeof(statusHeader)/sizeof(uint32_t) + 1)) ||
- (l_last > (l_recWords)) )
+ if (!l_fifoBuffer.getStatus())
{
SBE_TRACF(ERR_MRK "readResponse: invalid status distance "
"cmd=0x%08x distance=%d allocated response size=%d "
"received word size=%d" ,
i_pFifoRequest[1],
- l_last,
+ l_fifoBuffer.offset(),
i_responseSize,
- l_recWords);
+ l_fifoBuffer.index());
SBE_TRACFBIN("Invalid Response from SBE",
- o_pFifoResponse,l_recWords*sizeof(l_last));
+ l_fifoBuffer.localBuffer(),
+ l_fifoBuffer.index()*sizeof(uint32_t));
/*@
* @errortype
@@ -473,8 +430,8 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
SBEIO_FIFO_INVALID_STATUS_DISTANCE,
i_pFifoRequest[1],
TWO_UINT32_TO_UINT64(
- TWO_UINT16_TO_UINT32(l_last,
- l_recWords*sizeof(uint32_t)),
+ TWO_UINT16_TO_UINT32(l_fifoBuffer.offset(),
+ l_fifoBuffer.index()*sizeof(uint32_t)),
i_responseSize));
errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
@@ -488,13 +445,7 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
}
// Check status for success.
- // l_pReceived points one word past last word received.
- // l_last has number of words to status header including self.
-
- uint32_t * l_pStatusTmp = (l_overRun == false) ?
- l_pReceived - l_last : //do word ptr math
- &l_readBuffer[l_recWords - 1];
- statusHeader * l_pStatusHeader = (statusHeader *)l_pStatusTmp;
+ const statusHeader * l_pStatusHeader = l_fifoBuffer.getStatusHeader();
if ((FIFO_STATUS_MAGIC != l_pStatusHeader->magic) ||
(SBE_PRI_OPERATION_SUCCESSFUL != l_pStatusHeader->primaryStatus) ||
(SBE_SEC_OPERATION_SUCCESSFUL != l_pStatusHeader->secondaryStatus))
@@ -529,21 +480,15 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
l_pStatusHeader->primaryStatus,
l_pStatusHeader->secondaryStatus));
- /*
- * The FFDC package should start at l_pReceived.
- * Size of the FFDC package should be l_maxWords - l_recWords
- */
- if(l_overRun == false) {
- writeFFDCBuffer(l_pReceived,
- sizeof(uint32_t) * (l_maxWords - l_recWords - 1));
- } else {
- // If Overrun, FFDC should be
- // l_recWords (words read) - l_last (distance to status) + 1
- // in l_readBuffer
- writeFFDCBuffer(&l_readBuffer[l_recWords - l_last + 1],
- sizeof(uint32_t) * (l_last + 1));
+ if(!l_fifoBuffer.msgContainsFFDC())
+ {
+ break;
}
+
+ writeFFDCBuffer(l_fifoBuffer.getFFDCPtr(),
+ l_fifoBuffer.getFFDCByteSize());
+
SbeFFDCParser * l_ffdc_parser = new SbeFFDCParser();
l_ffdc_parser->parseFFDCData(iv_ffdcPackageBuffer);
@@ -551,13 +496,19 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
uint8_t l_pkgs = l_ffdc_parser->getTotalPackages();
for(uint8_t i = 0; i < l_pkgs; i++)
{
- uint32_t l_rc = l_ffdc_parser->getPackageRC(i);
+ ffdc_package l_package = {nullptr, 0, 0};
+ if(!l_ffdc_parser->getFFDCPackage(i, l_package))
+ {
+ continue;
+ }
+
+ uint32_t l_rc = l_package.rc;
// If fapiRC, add data to errorlog
if(l_rc == fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA)
{
errl->addFFDC( SBEIO_COMP_ID,
- l_ffdc_parser->getFFDCPackage(i),
- l_ffdc_parser->getPackageLength(i),
+ l_package.ffdcPtr,
+ l_package.size,
0,
SBEIO_UDT_PARAMETERS,
false );
@@ -573,9 +524,9 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
* call FAPI_SET_SBE_ERROR
*/
sbeFfdc_t * l_ffdcBuf = new sbeFfdc_t();
- l_ffdcBuf->size = l_ffdc_parser->getPackageLength(i);
+ l_ffdcBuf->size = l_package.size;
l_ffdcBuf->data = reinterpret_cast<uint64_t>(
- l_ffdc_parser->getFFDCPackage(i));
+ l_package.ffdcPtr);
FAPI_SET_SBE_ERROR(l_fapiRC,
l_rc,
@@ -588,15 +539,19 @@ errlHndl_t SbeFifo::readResponse(TARGETING::Target * i_target,
ERRORLOG::errlCommit( sbe_errl, SBEIO_COMP_ID );
}
}
- PIB::PibError l_pibRc = l_ffdc_parser->getPibRc(i);
- if (l_pibRc != PIB::PIB_NO_ERROR)
- {
- //this is pibrc, call addFruCallouts to log the error
- auto l_fifoReq =
- (SbeFifo::fifoGetScomRequest*)i_pFifoRequest;
- PIB::addFruCallouts
- (i_target, l_pibRc, l_fifoReq->address, errl);
- }
+
+ //If FFDC schema is known and a processing routine
+ //is defined then perform the processing.
+ //For scom PIB errors, addFruCallputs is invoked.
+ //Only processing known FFDC schemas protects us
+ //from trying to process FFDC formats we do not
+ //anticipate. For example, the SBE can send
+ //user and attribute FFDC information after the
+ //Scom Error FFDC. We do not want to process that
+ //type of data here.
+ FfdcParsedPackage::doDefaultProcessing(l_package,
+ i_target,
+ errl);
}
errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
@@ -650,7 +605,8 @@ errlHndl_t SbeFifo::waitDnFifoReady(TARGETING::Target * i_target,
}
else
{
- SBE_TRACD("SBE status reg returned fifo empty or dequeued eot flag 0x%.8X",
+ SBE_TRACD("SBE status reg returned fifo empty or "
+ "dequeued eot flag 0x%.8X",
o_status);
}
@@ -756,7 +712,7 @@ void SbeFifo::initFFDCPackageBuffer()
* @param[in] i_data FFDC error data
* @param[in] i_len data buffer len to copy
*/
-void SbeFifo::writeFFDCBuffer( void * i_data, uint32_t i_len) {
+void SbeFifo::writeFFDCBuffer(const void * i_data, uint32_t i_len) {
if(i_len <= PAGESIZE * ffdcPackageSize)
{
initFFDCPackageBuffer();
diff --git a/src/usr/sbeio/sbe_fifodd.H b/src/usr/sbeio/sbe_fifodd.H
index dd23e3c54..121d68c63 100644
--- a/src/usr/sbeio/sbe_fifodd.H
+++ b/src/usr/sbeio/sbe_fifodd.H
@@ -282,7 +282,7 @@ class SbeFifo
* @param[in] i_len data buffer len to copy
*/
- void writeFFDCBuffer(void * i_data, uint32_t i_len);
+ void writeFFDCBuffer(const void * i_data, uint32_t i_len);
private:
diff --git a/src/usr/sbeio/sbe_psudd.C b/src/usr/sbeio/sbe_psudd.C
index c27fdf15c..7c24cf327 100644
--- a/src/usr/sbeio/sbe_psudd.C
+++ b/src/usr/sbeio/sbe_psudd.C
@@ -38,6 +38,7 @@
#include <errl/errlreasoncodes.H>
#include <sbeio/sbeioreasoncodes.H>
#include <initservice/initserviceif.H> //@todo-RTC:149454-Remove
+#include <sbeio/sbe_ffdc_package_parser.H>
#include <sbeio/sbe_psudd.H>
#include <sbeio/sbe_ffdc_parser.H>
#include <arch/ppc.H>
@@ -360,17 +361,21 @@ errlHndl_t SbePsu::readResponse(TARGETING::Target * i_target,
o_pPsuResponse->secondaryStatus,
i_pPsuRequest->seqID,
o_pPsuResponse->seqID);
- SBE_TRACFBIN( "Full response:", o_pPsuResponse, sizeof(psuResponse) );
+ SBE_TRACFBIN( "Full response:",
+ o_pPsuResponse,
+ sizeof(psuResponse));
break;
}
//check status and seq ID in response messages
- else if ((SBE_PRI_OPERATION_SUCCESSFUL != o_pPsuResponse->primaryStatus) ||
- (SBE_SEC_OPERATION_SUCCESSFUL != o_pPsuResponse->secondaryStatus) ||
- (i_pPsuRequest->seqID != o_pPsuResponse->seqID) )
+ else if ((SBE_PRI_OPERATION_SUCCESSFUL !=
+ o_pPsuResponse->primaryStatus) ||
+ (SBE_SEC_OPERATION_SUCCESSFUL != o_pPsuResponse->secondaryStatus) ||
+ (i_pPsuRequest->seqID != o_pPsuResponse->seqID))
{
- SBE_TRACF(ERR_MRK "sbe_psudd.C :: readResponse: failing response status "
+ SBE_TRACF(ERR_MRK "sbe_psudd.C :: readResponse: "
+ "failing response status "
" cmd=0x%02x%02x prim=0x%08x secondary=0x%08x"
" expected seqID=%d actual seqID=%d",
i_pPsuRequest->commandClass,
@@ -379,7 +384,7 @@ errlHndl_t SbePsu::readResponse(TARGETING::Target * i_target,
o_pPsuResponse->secondaryStatus,
i_pPsuRequest->seqID,
o_pPsuResponse->seqID);
- SBE_TRACFBIN( "Full response:", o_pPsuResponse, sizeof(psuResponse) );
+ SBE_TRACFBIN("Full response:", o_pPsuResponse, sizeof(psuResponse));
/*@
@@ -427,12 +432,31 @@ errlHndl_t SbePsu::readResponse(TARGETING::Target * i_target,
uint8_t i;
for(i = 0; i < l_pkgs; i++)
{
+ ffdc_package l_package = {nullptr, 0, 0};
+ if(!l_ffdc_parser->getFFDCPackage(i, l_package))
+ {
+ continue;
+ }
+
errl->addFFDC( SBEIO_COMP_ID,
- l_ffdc_parser->getFFDCPackage(i),
- l_ffdc_parser->getPackageLength(i),
+ l_package.ffdcPtr,
+ l_package.size,
0,
SBEIO_UDT_PARAMETERS,
false );
+
+ //If FFDC schema is known and a processing routine
+ //is defined then perform the processing.
+ //For scom PIB errors, addFruCallputs is invoked.
+ //Only processing known FFDC schemas protects us
+ //from trying to process FFDC formats we do not
+ //anticipate. For example, the SBE can send
+ //user and attribute FFDC information after the
+ //Scom Error FFDC. We do not want to process that
+ //type of data here.
+ FfdcParsedPackage::doDefaultProcessing(l_package,
+ i_target,
+ errl);
}
delete l_ffdc_parser;
}
@@ -696,7 +720,8 @@ errlHndl_t SbePsu::allocateFFDCBuffer(TARGETING::Target * i_target)
if(errl)
{
PageManager::freePage(l_ffdcPtr);
- SBE_TRACF(ERR_MRK"Error setting FFDC address for proc huid=0x%08lx", l_huid);
+ SBE_TRACF(ERR_MRK"Error setting FFDC address for "
+ "proc huid=0x%08lx", l_huid);
}
else
{
diff --git a/src/usr/sbeio/test/makefile b/src/usr/sbeio/test/makefile
index 2017d8aab..8dfb21f98 100644
--- a/src/usr/sbeio/test/makefile
+++ b/src/usr/sbeio/test/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2016
+# Contributors Listed Below - COPYRIGHT 2011,2017
# [+] International Business Machines Corp.
#
#
@@ -25,6 +25,8 @@
ROOTPATH = ../../../..
EXTRAINCDIR += ${ROOTPATH}/src/usr/sbeio/
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2/
+EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include/
MODULE = testsbeio
diff --git a/src/usr/sbeio/test/sbe_ffdc_package_parser_test.H b/src/usr/sbeio/test/sbe_ffdc_package_parser_test.H
new file mode 100644
index 000000000..f7de533e5
--- /dev/null
+++ b/src/usr/sbeio/test/sbe_ffdc_package_parser_test.H
@@ -0,0 +1,688 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/test/sbe_ffdc_package_parser_test.H $ */
+/* */
+/* 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 */
+#ifndef __SBEIO_SBE_FFDC_PACKAGE_PARSER_TEST_H
+#define __SBEIO_SBE_FFDC_PACKAGE_PARSER_TEST_H
+
+#include <hwp_return_codes.H>
+
+#include <sbeio/sbe_ffdc_package_parser.H>
+#include <trace/interface.H>
+
+#include <cxxtest/TestSuite.H>
+#include "sbe_test_support.H"
+
+extern trace_desc_t* g_trac_sbeio;
+
+#define SBE_FFDC_TRACD(printf_string,args...) \
+ TRACDCOMP(g_trac_sbeio,"sbeFFDCParserTest: " printf_string,##args)
+
+using namespace SBEIO;
+
+class FfdcScomPibErrorPackageTestFixure: public SBEIO::FfdcScomPibErrorPackage
+{
+public:
+
+ FfdcScomPibErrorPackageTestFixure(const ffdc_package& i_ffdc,
+ bool i_ignoreRC = false):
+ FfdcScomPibErrorPackage(i_ffdc,
+ i_ignoreRC)
+ {
+ clearCounts();
+ }
+
+//Mock the addFruCallouts method.
+void addFruCallouts (TARGETING::Target* i_target,
+ errlHndl_t i_errHndl
+ ) const override
+{
+ ++cv_defaultActionInvoked;
+
+ if(not i_target)
+ {
+ ++cv_nullTargetCount;
+ }
+
+ if(not i_errHndl)
+ {
+ ++cv_nullErrlHndlCount;
+ }
+}
+
+static size_t callCount() {return cv_defaultActionInvoked;}
+static size_t nullTargetCount() {return cv_nullTargetCount;}
+static size_t nullErrlHndlCount() {return cv_nullErrlHndlCount;}
+
+static void clearCounts()
+{
+ cv_defaultActionInvoked = 0;
+ cv_nullTargetCount = 0;
+ cv_nullErrlHndlCount = 0;
+}
+
+private:
+
+ static size_t cv_defaultActionInvoked;
+ static size_t cv_nullTargetCount;
+ static size_t cv_nullErrlHndlCount;
+};
+
+size_t FfdcScomPibErrorPackageTestFixure::cv_defaultActionInvoked = 0;
+size_t FfdcScomPibErrorPackageTestFixure::cv_nullTargetCount = 0;
+size_t FfdcScomPibErrorPackageTestFixure::cv_nullErrlHndlCount = 0;
+
+
+std::vector<uint32_t> bufferFFDC = {
+ 0xFFDC0009, //FFDC 1 - Magic + Len
+ 0x0000A807, //FFDC 2 - Seq, Cmd class, cmd
+ 0x00983AB6, //FFDC 3 - RC_SBE_SCOM_FAILURE
+ 0x00000008, //FFDC 4 - scom addr size
+ 0x12345678, //FFDC 5 - scom addr msb
+ 0x9ABCDEF0, //FFDC 6 - scom addr lsb
+ 0x00000008, //FFDC 7 - PIB RC size
+ 0x00000000, //FFDC 8 - PIB_PARITY_ERROR msb
+ 0x00000006 //FFDC 9 - PIB_PARITY_ERROR lsb
+ };
+
+std::vector<uint32_t> bufferUnknownRCFFDC = {
+ 0xFFDC0009, //FFDC 1 - Magic + Len
+ 0x0000A807, //FFDC 2 - Seq, Cmd class, cmd
+ 0xFF983AB6, //FFDC 3 - FAPI RC
+ 0x00000008, //FFDC 4 - scom addr size
+ 0x12345678, //FFDC 5 - scom addr msb
+ 0x9ABCDEF0, //FFDC 6 - scom addr lsb
+ 0x00000008, //FFDC 7 - PIB RC size
+ 0x00000000, //FFDC 8 - PIB_PARITY_ERROR msb
+ 0x00000006 //FFDC 9 - PIB_PARITY_ERROR lsb
+ };
+
+std::vector<uint32_t> bufferBadSchemaFFDC = {
+ 0xFFDC000A, //FFDC 1 - Magic + Len
+ 0x0000A807, //FFDC 2 - Seq, Cmd class, cmd
+ 0x00983AB6, //FFDC 3 - RC_SBE_SCOM_FAILURE
+ 0x00000008, //FFDC 4 - scom addr size
+ 0x12345678, //FFDC 5 - scom addr msb
+ 0x9ABCDEF0, //FFDC 6 - scom addr lsb
+ 0x00000008, //FFDC 7 - PIB RC size
+ 0x00000000, //FFDC 8 - PIB_PARITY_ERROR msb
+ 0x00000006, //FFDC 9 - PIB_PARITY_ERROR lsb
+ 0xFFEEDDCC //FFDC 10 Extra Garbage Word
+ };
+
+uint64_t addr = 0x1234567890ABCDEF;
+TARGETING::Target* g_testTarget = reinterpret_cast<TARGETING::Target*>(addr);
+errlHndl_t g_errl = reinterpret_cast<errlHndl_t>(addr);
+
+ffdc_package g_testPackage = {nullptr, 0, 0};
+
+//============================================================
+class SbeFFDCPackageParserTest : public CxxTest::TestSuite
+{
+public:
+
+ void testGoodFFDC()
+ {
+ SBE_FFDC_TRACD("ENTER sbeFFDCParserTest testGoodFFDC");
+
+ bool result{true};
+
+ do
+ {
+ bufferFFDC[2] = static_cast<uint32_t>(fapi2::RC_SBE_SCOM_FAILURE);
+ g_testPackage.ffdcPtr = &bufferFFDC[2];
+ g_testPackage.size = (bufferFFDC.size() - 2) * sizeof(uint32_t);
+ g_testPackage.rc = fapi2::RC_SBE_SCOM_FAILURE;
+
+ bool matchesSchema =
+ FfdcScomPibErrorPackage::doesPackageMatchSchema(g_testPackage);
+
+ if(not matchesSchema)
+ {
+ char strFfdc[64];
+ xxdPrint(g_testPackage.ffdcPtr, g_testPackage.size, strFfdc);
+
+ SBE_FFDC_TRACD("sbeFFDCParserTest testGoodFFDC: "
+ "doesPackageMatchSchema unexpectedly "
+ "returned false. Input FFDC:\n%s",
+ strFfdc
+ );
+
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "doesPackageMatchSchema unexpectedly result = false."
+ );
+
+ result = false;
+ break;
+ }
+
+ FfdcScomPibErrorPackageTestFixure l_ffdcPackage{g_testPackage};
+
+ if(not l_ffdcPackage.isValid())
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "ffdc package was not successfully parsed."
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not l_ffdcPackage)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "operator bool failed. ffdc package was not "
+ "successfully parsed."
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ l_ffdcPackage.parsedType())
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "Did not receive ParsedType SBE_SCOM_PIB_ERROR "
+ "from ParsedType() call."
+ );
+
+ result = false;
+ break;
+ }
+
+ uint64_t scomAddr = l_ffdcPackage.getScomAddress();
+ uint64_t expectedScomAddr = *(reinterpret_cast<const uint64_t*>
+ (&bufferFFDC[4]));
+ if(expectedScomAddr != scomAddr)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "Did not receive scom addr 0x%08X as expected. "
+ "scom addr: 0x%08X",
+ expectedScomAddr,
+ scomAddr
+ );
+
+ result = false;
+ break;
+ }
+
+ uint64_t pibRc = l_ffdcPackage.getPibRc();
+ uint64_t expectedPibRc = *(reinterpret_cast<const uint64_t*>
+ (&bufferFFDC[7]));
+ if(expectedPibRc != pibRc)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "Did not receive pib rc 0x%08X as expected. "
+ "pib rc: 0x%08X",
+ expectedPibRc,
+ pibRc
+ );
+
+ result = false;
+ break;
+ }
+
+ l_ffdcPackage(g_testTarget, g_errl);
+
+ if(FfdcScomPibErrorPackageTestFixure::callCount() == 0)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "call operator did not invoke addFruCallouts"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcScomPibErrorPackageTestFixure::nullTargetCount() != 0)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "call operator invoked addFruCallouts with a "
+ "null target argument."
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcScomPibErrorPackageTestFixure::nullErrlHndlCount() != 0)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDC: "
+ "call operator invoked addFruCallouts with a "
+ "null errlHndl_t argument."
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testGoodFFDC test passed!");
+ }
+ else
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testGoodFFDC test failed!");
+ }
+ }
+
+ //------------------------------------------------------------------
+ void testGoodFFDCBaseClass()
+ {
+ SBE_FFDC_TRACD("ENTER sbeFFDCParserTest TestGoodFFDCBaseClass");
+
+ bool result{true};
+
+ do
+ {
+ bufferFFDC[2] = static_cast<uint32_t>(fapi2::RC_SBE_SCOM_FAILURE);
+ bufferFFDC[6] = 4; // test with size of PIB RC = 4
+ g_testPackage.ffdcPtr = &bufferFFDC[2];
+ g_testPackage.size = (bufferFFDC.size() - 2) * sizeof(uint32_t);
+ g_testPackage.rc = fapi2::RC_SBE_SCOM_FAILURE;
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(fapi2::RC_SBE_SCOM_FAILURE))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_SCOM_FAILURE did not map to SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(
+ fapi2::RC_SBE_PIB_XSCOM_ERROR))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_PIB_XSCOM_ERROR did not map to "
+ "SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(
+ fapi2::RC_SBE_PIB_OFFLINE_ERROR))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_PIB_OFFLINE_ERROR did not map to "
+ "SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(
+ fapi2::RC_SBE_PIB_PARTIAL_ERROR))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_PIB_PARTIAL_ERROR did not map to "
+ "SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(
+ fapi2::RC_SBE_PIB_ADDRESS_ERROR))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_PIB_ADDRESS_ERROR did not map to "
+ "SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(
+ fapi2::RC_SBE_PIB_CLOCK_ERROR))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_PIB_CLOCK_ERROR did not map to "
+ "SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(
+ fapi2::RC_SBE_PIB_PARITY_ERROR))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_PIB_PARITY_ERROR did not map to "
+ "SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR !=
+ FfdcParsedPackage::rcToParsedType(
+ fapi2::RC_SBE_PIB_TIMEOUT_ERROR))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "RC_SBE_PIB_TIMEOUT_ERROR did not map to "
+ "SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR ==
+ FfdcParsedPackage::rcToParsedType(0xFFEEDDCC))
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "0xFFEEDDCC mapped to SBE_SCOM_PIB_ERROR"
+ );
+
+ result = false;
+ break;
+ }
+
+ std::shared_ptr<const FfdcParsedPackage> l_package =
+ FfdcParsedPackage::getParsedPackage(g_testPackage);
+
+ if(not l_package)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "getParsedPackage result = returned a null pointer."
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not l_package->isValid())
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "getParsedPackage did not parse the ffdc package."
+ );
+
+ result = false;
+ break;
+ }
+
+
+ if(FfdcParsedPackage::ParsedType::SBE_SCOM_PIB_ERROR
+ != l_package->parsedType())
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "getParsedPackage did not parse the ffdc package "
+ "to the correct type."
+ );
+
+ result = false;
+ break;
+ }
+
+ FfdcScomPibErrorPackageTestFixure l_ffdcPackage{g_testPackage};
+
+ if(not l_ffdcPackage.isValid())
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "ffdc package was not successfully parsed."
+ );
+
+ result = false;
+ break;
+ }
+
+ FfdcScomPibErrorPackageTestFixure::clearCounts();
+ l_ffdcPackage(g_testTarget, g_errl);
+
+ if(FfdcScomPibErrorPackageTestFixure::callCount() == 0)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "call operator did not invoke addFruCallouts"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcScomPibErrorPackageTestFixure::nullTargetCount() != 0)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "call operator invoked addFruCallouts with a "
+ "null target argument."
+ );
+
+ result = false;
+ break;
+ }
+
+ if(FfdcScomPibErrorPackageTestFixure::nullErrlHndlCount() != 0)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "call operator invoked addFruCallouts with a "
+ "null errlHndl_t argument."
+ );
+
+ result = false;
+ break;
+ }
+
+ g_testPackage.ffdcPtr = &bufferBadSchemaFFDC[2];
+ g_testPackage.size = (bufferBadSchemaFFDC.size() - 2) *
+ sizeof(uint32_t);
+ g_testPackage.rc = 0xFF983AB6; //arbitrary value
+
+ FfdcScomPibErrorPackageTestFixure
+ l_ffdcPackage_badschema{g_testPackage};
+
+ FfdcScomPibErrorPackageTestFixure::clearCounts();
+ l_ffdcPackage_badschema(g_testTarget, g_errl);
+
+ if(FfdcScomPibErrorPackageTestFixure::callCount() != 0)
+ {
+ TS_FAIL("sbeFFDCParserTest testGoodFFDCBaseClass: "
+ "call operator invoked addFruCallouts on bad FFDC"
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testGoodFFDCBaseClass "
+ "test passed!");
+ }
+ else
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testGoodFFDCBaseClass "
+ "test failed!");
+ }
+ }
+
+
+ //------------------------------------------------------------------
+ void testbadFFDCSchema()
+ {
+ SBE_FFDC_TRACD("ENTER sbeFFDCParserTest testbadFFDCSchema");
+
+ bufferBadSchemaFFDC[2] = static_cast<uint32_t>
+ (fapi2::RC_SBE_SCOM_FAILURE);
+
+ g_testPackage.ffdcPtr = &bufferBadSchemaFFDC[2];
+ g_testPackage.size = (bufferBadSchemaFFDC.size() - 2) *
+ sizeof(uint32_t);
+ g_testPackage.rc = fapi2::RC_SBE_SCOM_FAILURE;
+
+ FfdcScomPibErrorPackageTestFixure l_ffdcPackage{g_testPackage};
+
+ bool result{true};
+
+ do
+ {
+ if(l_ffdcPackage.isValid())
+ {
+ TS_FAIL("sbeFFDCParserTest testbadFFDCSchema: "
+ "ffdc package was unexpectedly successfully parsed."
+ );
+
+ result = false;
+ break;
+ }
+
+ if(l_ffdcPackage)
+ {
+ TS_FAIL("sbeFFDCParserTest testbadFFDCSchema: "
+ "operator bool returned true. The ffdc package was "
+ "unexpectedly successfully parsed."
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testbadFFDCSchema test passed!");
+ }
+ else
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testbadFFDCSchema test failed!");
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void testWithFFDCParser()
+ {
+
+ bool result{true};
+
+ SbeFFDCParser ffdcParser;
+ ffdcParser.parseFFDCData(&bufferFFDC[0]);
+
+ do
+ {
+ if(1 != ffdcParser.getTotalPackages())
+ {
+ TS_FAIL("sbeFFDCParserTest testWithFFDCParser: "
+ "ffdcParser.getTotalPackages() returned %d, "
+ "expected 1.",
+ ffdcParser.getTotalPackages()
+ );
+
+ result = false;
+ break;
+ }
+
+ ffdc_package package;
+ package.ffdcPtr = ffdcParser.getFFDCPackage(0);
+ package.rc = ffdcParser.getPackageRC(0);
+ package.size = ffdcParser.getPackageLength(0);
+
+ FfdcScomPibErrorPackageTestFixure l_ffdcPackage{package};
+
+ if(not l_ffdcPackage.isValid())
+ {
+ char strFfdc[64];
+ xxdPrint(package.ffdcPtr, package.size, strFfdc);
+ SBE_FFDC_TRACD("testWithFFDCParser "
+ "Ffdc package was not successfully parsed. "
+ "FFDC Data:\n%s",
+ strFfdc
+ );
+
+ TS_FAIL("sbeFFDCParserTest testWithFFDCParser: "
+ "Ffdc package was not successfully parsed."
+ );
+
+ result = true;
+ break;
+ }
+
+ ffdc_package package2 = {nullptr, 0, 0};
+ bool rc = ffdcParser.getFFDCPackage(0, package2);
+
+ if(not rc)
+ {
+ TS_FAIL("sbeFFDCParserTest testWithFFDCParser: "
+ "ffdcParser.getFFDCPackage(0, package2) failed."
+ );
+
+ result = true;
+ break;
+ }
+
+ FfdcScomPibErrorPackageTestFixure l_ffdcPackage2{package2};
+
+ if(not l_ffdcPackage2.isValid())
+ {
+ char strFfdc[64];
+ xxdPrint(package.ffdcPtr, package.size, strFfdc);
+ SBE_FFDC_TRACD("testWithFFDCParser "
+ "Ffdc package 2 was not successfully parsed. "
+ "FFDC Data:\n%s",
+ strFfdc
+ );
+
+ TS_FAIL("sbeFFDCParserTest testWithFFDCParser: "
+ "Ffdc package 2 was not successfully parsed."
+ );
+
+ result = true;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testWithFFDCParser "
+ "test passed!");
+ }
+ else
+ {
+ SBE_FFDC_TRACD("sbeFFDCParserTest testWithFFDCParser "
+ "test failed!");
+ }
+ }
+};
+
+#endif
diff --git a/src/usr/sbeio/test/sbe_fifo_buffer_test.H b/src/usr/sbeio/test/sbe_fifo_buffer_test.H
new file mode 100644
index 000000000..0383ebe7b
--- /dev/null
+++ b/src/usr/sbeio/test/sbe_fifo_buffer_test.H
@@ -0,0 +1,1866 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/test/sbe_fifo_buffer_test.H $ */
+/* */
+/* 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 */
+#ifndef __SBEIO_SBE_FIFO_BUFFER_TEST_H
+#define __SBEIO_SBE_FIFO_BUFFER_TEST_H
+
+#include <vector>
+
+#include <cxxtest/TestSuite.H>
+#include "sbe_test_support.H"
+
+#include <sbe_fifo_buffer.H>
+#include <trace/interface.H>
+
+extern trace_desc_t* g_trac_sbeio;
+
+#define SBE_BUFFER_TRACD(printf_string,args...) \
+ TRACDCOMP(g_trac_sbeio,"sbeFifoBufferTest: " printf_string,##args)
+
+using namespace SBEIO;
+
+class SbeFifoRespBufferTestFixture:public SbeFifoRespBuffer
+{
+public:
+
+ explicit SbeFifoRespBufferTestFixture(uint32_t * i_fifoBuffer,
+ size_t bufferWordSize):
+ SbeFifoRespBuffer(i_fifoBuffer,
+ bufferWordSize)
+ {
+ }
+
+ //expose data for testing
+ using SbeFifoRespBuffer::localBuffer;
+ using SbeFifoRespBuffer::callerBuffer;
+ using SbeFifoRespBuffer::callerWordSize;
+ using SbeFifoRespBuffer::index;
+ using SbeFifoRespBuffer::offsetIndex;
+ using SbeFifoRespBuffer::statusIndex;
+ using SbeFifoRespBuffer::ffdcIndex;
+ using SbeFifoRespBuffer::getStateString;
+ using SbeFifoRespBuffer::setBufferState;
+};
+
+
+std::vector<uint32_t> bufferNoReturnNoFFDC = {
+ 0xC0DEA807, //Status Header 1
+ 0x00000000, //Status Header 2
+ 0x00000003, //Offset to Status Header
+ 0x00000001 //EOT
+ };
+
+std::vector<uint32_t> bufferReturnNoFFDC = {
+ 0x00010002, //Return Data 1
+ 0x00030004, //Return Data 2
+ 0xC0DEA807, //Status Header 1
+ 0x00000000, //Status Header 2
+ 0x00000003, //Offset to Status Header
+ 0x00000001 //EOT
+ };
+
+std::vector<uint32_t> bufferNoReturnFFDC = {
+ 0xC0DEA807, //Status Header 1
+ 0x00FE0099, //Status Header 2
+ 0xFFDC0024, //FFDC 1
+ 0x00983AB6, //FFDC 2 - RC_SBE_SCOM_FAILURE
+ 0x00000008, //FFDC 3 - scom addr size
+ 0x12345678, //FFDC 4 - scom addr
+ 0x00000008, //FFDC 5 - PIB RC size
+ 0x00000006, //FFDC 6 - PIB_PARITY_ERROR
+ 0x00000009, //Offset to Status Header
+ 0x00000001, //EOT
+ };
+
+std::vector<uint32_t> bufferReturnFFDC = {
+ 0x00000001, //Return Data 1
+ 0x00000002, //Return Data 2
+ 0x00000003, //Return Data 3
+ 0xC0DEA807, //Status Header 1
+ 0x00FE0099, //Status Header 2
+ 0xFFDC0024, //FFDC 1
+ 0x00983AB6, //FFDC 2 - RC_SBE_SCOM_FAILURE
+ 0x00000008, //FFDC 3 - scom addr size
+ 0x12345678, //FFDC 4 - scom addr
+ 0x00000008, //FFDC 5 - PIB RC size
+ 0x00000006, //FFDC 6 - PIB_PARITY_ERROR
+ 0x00000009, //Offset to Status Header
+ 0x00000001, //EOT
+ };
+
+std::vector<uint32_t> bufferLongOffset = {
+ 0xC0DEA807, //Status Header 1
+ 0x00000000, //Status Header 2
+ 0x00000004, //Offset to Status Header
+ 0x00000001 //EOT
+ };
+
+std::vector<uint32_t> bufferShortOffset = {
+ 0xC0DEA807, //Status Header 1
+ 0x00000000, //Status Header 2
+ 0x00000002, //Offset to Status Header
+ 0x00000001 //EOT
+ };
+
+std::vector<uint32_t> bufferShortRead = {
+ 0xC0DEA807, //Status Header 1
+ 0x00000000, //Status Header 2
+ 0x00000001 //EOT
+ };
+
+size_t overrun_element_count{2096};
+uint32_t overrun_element_value{34};
+std::vector<uint32_t> bufferOverrun(overrun_element_count,
+ overrun_element_value);
+
+//===================================================
+class SbeFifoBufferTest : public CxxTest::TestSuite
+{
+public:
+
+ struct expected_data
+ {
+ const char* test_name;
+ size_t index;
+ size_t offset_index;
+ size_t offset;
+
+ size_t statusIndex;
+ const void* expected_status;
+
+ bool expectFFDC;
+ size_t ffdcIndex;
+ size_t ffdcByteSize;
+ const void* expected_ffdc_data;
+
+ bool expectReturnData;
+ size_t dataByteSize;
+ const void* expected_data;
+
+ char strMessage[512];
+ };
+
+ //------------------------------------------------
+ void testState()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testState");
+
+ bool result{true};
+
+ //Set buffer to various states and test responses
+
+ /* The operator bool is implemented so that the fifobuffer object can
+ * be used as a control variable for a while loop. The operator bool
+ * only returns true if data is allowed to be added to the buffer
+ * (i.e. the state is MSG_INCOMPLETE). A SbeFifoRespBuffer object which
+ * is in an error state or contains a complete message is no longer
+ * able to accept new data to add to the internal buffers and as such
+ * will return false for the conversion operator.
+ */
+
+ /* The getStatus method on the other hand returns true if the
+ * SbeFifoRespBuffer object is not in an error state. The MSG_COMPLETE
+ * and MSG_INCOMPLETE are the non-error states, any other state will
+ * cause getStatus to return false.
+ */
+
+ do
+ {
+ uint32_t callerBuffer[4] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ fifoBuffer.setBufferState(
+ SbeFifoRespBuffer::INVALID_CALLER_BUFFER);
+
+ if(fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The operator bool unexpectedly returned true "
+ "after setting the state to INVALID_CALLER_BUFFER"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned true "
+ "after setting the state to INVALID_CALLER_BUFFER"
+ );
+
+ result = false;
+ break;
+ }
+
+ fifoBuffer.setBufferState(SbeFifoRespBuffer::OVERRUN);
+
+ if(fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The operator bool unexpectedly returned true "
+ "after setting the state to OVERRUN"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned true "
+ "after setting the state to OVERRUN"
+ );
+
+ result = false;
+ break;
+ }
+
+ fifoBuffer.setBufferState(SbeFifoRespBuffer::MSG_SHORT_READ);
+
+ if(fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The operator bool unexpectedly returned true "
+ "after setting the state to MSG_SHORT_READ"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned true "
+ "after setting the state to MSG_SHORT_READ"
+ );
+
+ result = false;
+ break;
+ }
+
+ fifoBuffer.setBufferState(SbeFifoRespBuffer::MSG_INVALID_OFFSET);
+
+ if(fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The operator bool unexpectedly returned true "
+ "after setting the state to MSG_INVALID_OFFSET"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned true "
+ "after setting the state to MSG_INVALID_OFFSET"
+ );
+
+ result = false;
+ break;
+ }
+
+ fifoBuffer.setBufferState(SbeFifoRespBuffer::MSG_COMPLETE);
+
+ if(fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The operator bool unexpectedly returned true "
+ "after setting the state to MSG_COMPLETE"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned false "
+ "after setting the state to MSG_COMPLETE"
+ );
+
+ result = false;
+ break;
+ }
+
+ fifoBuffer.setBufferState(SbeFifoRespBuffer::MSG_INCOMPLETE);
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The operator bool unexpectedly returned false "
+ "after setting the state to MSG_INCOMPLETE"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned false "
+ "after setting the state to MSG_INCOMPLETE"
+ );
+
+ result = false;
+ break;
+ }
+
+ SbeFifoRespBufferTestFixture fifoBuffer_null(nullptr,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(fifoBuffer_null)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The FIFO buffer unexpectedly indicates a good state "
+ "after passing a null pointer to the CTOR. "
+ "Buffer state: %s",
+ fifoBuffer_null.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer_null.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned true "
+ "after passing a null pointer to the CTOR. "
+ "Buffer state: %s",
+ fifoBuffer_null.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(SbeFifoRespBuffer::INVALID_CALLER_BUFFER !=
+ fifoBuffer_null.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "Buffer in unexpected state after calling CTOR "
+ "w/nullptr. Buffer State: %s",
+ fifoBuffer_null.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ SbeFifoRespBufferTestFixture fifoBuffer_short(callerBuffer, 1);
+
+ if(fifoBuffer_short)
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "The FIFO buffer unexpectedly indicates a good state "
+ "after passing a small buffer to the CTOR. "
+ "Buffer state: %s",
+ fifoBuffer_short.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer_short.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "getStatus unexpectedly returned true "
+ "after passing a small buffer to the CTOR. "
+ "Buffer state: %s",
+ fifoBuffer_short.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(SbeFifoRespBuffer::INVALID_CALLER_BUFFER !=
+ fifoBuffer_short.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testState: "
+ "Buffer in unexpected state after calling CTOR "
+ "with a small buffer. Buffer State: %s",
+ fifoBuffer_short.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testState test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testState test failed!");
+ }
+ }
+
+ //------------------------------------------------
+ void testNoReturnNoFFDC()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testNoReturnNoFFDC");
+
+ //Test with buffer data that has No Return data and No FFDC
+ //A successful write message will have this format.
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[2] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnNoFFDC: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferNoReturnNoFFDC);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc)
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnNoFFDC: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::MSG_COMPLETE != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnNoFFDC: "
+ "Buffer unexpectedly not in the complete state after "
+ "populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnNoFFDC: "
+ "unexpectedly returned false for isMsgComplete"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnNoFFDC: "
+ "unexpectedly returned false for getStatus"
+ );
+
+ result = false;
+ break;
+ }
+
+ expected_data expData;
+ memset(&expData, 0, sizeof(expData));
+
+ expData.test_name = "sbeFifoBufferTest testNoReturnNoFFDC";
+ expData.index = 4;
+ expData.offset_index = 2;
+ expData.offset = 3;
+
+ expData.statusIndex = 0;
+ expData.expected_status = &bufferNoReturnNoFFDC[0];
+
+ expData.expectFFDC = false;
+ expData.expectReturnData = false;
+
+ bool check_result = runChecks(expData, fifoBuffer);
+
+ if(not check_result)
+ {
+ TS_FAIL("%s", expData.strMessage);
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testNoReturnNoFFDC "
+ "test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testNoReturnNoFFDC "
+ "test failed!");
+ }
+ }
+
+ //-----------------------------------------------------
+ void testReturnNoFFDC()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testReturnNoFFDC");
+
+ //Test with buffer data that has Return data and No FFDC
+ //A successful read message will have this format.
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[4] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnNoFFDC: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferReturnNoFFDC);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc)
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnNoFFDC: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::MSG_COMPLETE != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnNoFFDC: "
+ "Buffer unexpectedly not in the complete state after "
+ "populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnNoFFDC: "
+ "unexpectedly returned false for isMsgComplete"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnNoFFDC: "
+ "unexpectedly returned false for getStatus"
+ );
+
+ result = false;
+ break;
+ }
+
+ expected_data expData;
+ memset(&expData, 0, sizeof(expData));
+
+ expData.test_name = "sbeFifoBufferTest testReturnNoFFDC";
+ expData.index = 6;
+ expData.offset_index = 4;
+ expData.offset = 3;
+
+ expData.statusIndex = 2;
+ expData.expected_status = &bufferReturnNoFFDC[2];
+
+ expData.expectFFDC = false;
+
+ expData.expectReturnData = true;
+ expData.dataByteSize = sizeof(uint32_t) * 2;
+ expData.expected_data = &bufferReturnNoFFDC[0];
+
+ bool check_result = runChecks(expData, fifoBuffer);
+
+ if(not check_result)
+ {
+ TS_FAIL("%s", expData.strMessage);
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testReturnNoFFDC "
+ "test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testReturnNoFFDC "
+ "test failed!");
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void testNoReturnFFDC()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testNoReturnFFDC");
+
+ //Test with buffer data that has No Return data and FFDC data
+ //An unsuccessful write message will have this format.
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[2] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnFFDC: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferNoReturnFFDC);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc)
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnFFDC: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::MSG_COMPLETE != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnFFDC: "
+ "Buffer unexpectedly not in the complete state after "
+ "populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnFFDC: "
+ "unexpectedly returned false for isMsgComplete"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testNoReturnFFDC: "
+ "unexpectedly returned false for getStatus"
+ );
+
+ result = false;
+ break;
+ }
+
+ expected_data expData;
+ memset(&expData, 0, sizeof(expData));
+
+ expData.test_name = "sbeFifoBufferTest testNoReturnFFDC";
+ expData.index = 10;
+ expData.offset_index = 8;
+ expData.offset = 9;
+
+ expData.statusIndex = 0;
+ expData.expected_status = &bufferNoReturnFFDC[0];
+
+ expData.expectFFDC = true;
+ expData.ffdcIndex = 2;
+ expData.ffdcByteSize = sizeof(uint32_t)*6;
+ expData.expected_ffdc_data = &bufferNoReturnFFDC[2];
+
+ expData.expectReturnData = false;
+
+ bool check_result = runChecks(expData, fifoBuffer);
+
+ if(not check_result)
+ {
+ TS_FAIL("%s", expData.strMessage);
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testNoReturnFFDC "
+ "test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testNoReturnFFDC "
+ "test failed!");
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ void testReturnFFDC()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testReturnFFDC");
+
+ //Test with buffer data that has both Return data and FFDC data
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[5] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnFFDC: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferReturnFFDC);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc)
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnFFDC: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::MSG_COMPLETE != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnFFDC: "
+ "Buffer unexpectedly not in the complete state after "
+ "populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnFFDC: "
+ "unexpectedly returned false for isMsgComplete"
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getStatus())
+ {
+ TS_FAIL("sbeFifoBufferTest testReturnFFDC: "
+ "unexpectedly returned false for getStatus"
+ );
+
+ result = false;
+ break;
+ }
+
+ expected_data expData;
+ memset(&expData, 0, sizeof(expData));
+
+ expData.test_name = "ReturnFFDC";
+ expData.index = 13;
+ expData.offset_index = 11;
+ expData.offset = 9;
+
+ expData.statusIndex = 3;
+ expData.expected_status = &bufferReturnFFDC[3];
+
+ expData.expectFFDC = true;
+ expData.ffdcIndex = 5;
+ expData.ffdcByteSize = sizeof(uint32_t)*6;
+ expData.expected_ffdc_data = &bufferReturnFFDC[5];
+
+ expData.expectReturnData = true;
+ expData.dataByteSize = sizeof(uint32_t) * 3;
+ expData.expected_data = &bufferReturnFFDC[0];
+
+ bool check_result = runChecks(expData, fifoBuffer);
+
+ if(not check_result)
+ {
+ TS_FAIL("%s", expData.strMessage);
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testReturnFFDC test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testReturnFFDC test failed!");
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void testBadOffsetLong()
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest Enter testBadOffsetLong");
+
+ //Test with an offset that points to beyond that start of the buffer
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[2] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetLong: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferLongOffset);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc)
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetLong: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::MSG_INVALID_OFFSET != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetLong: "
+ "Buffer unexpectedly not in the INVALID_OFFSET state "
+ "after populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetLong: "
+ "unexpectedly returned true for isMsgComplete"
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testBadOffsetLong "
+ "test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testBadOffsetLong "
+ "test failed!");
+ }
+ }
+
+ //----------------------------------------------------------------------
+ void testBadOffsetShort()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testBadOffsetShort");
+
+ //Test with an offset that is too short to reach the Status Header
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[2] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetShort: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferShortOffset);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc)
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetShort: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::MSG_INVALID_OFFSET != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetShort: "
+ "Buffer unexpectedly not in the INVALID_OFFSET state "
+ "after populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testBadOffsetShort: "
+ "unexpectedly returned true for isMsgComplete."
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testBadOffsetShort "
+ "test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testBadOffsetShort "
+ "test failed!");
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void testShortRead()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testShortRead");
+ //Test case where message is completed prematurely
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[2] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testShortRead: "
+ "The FIFO buffer is not in a good state after "
+ "CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferShortRead);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc)
+ {
+ TS_FAIL("sbeFifoBufferTest testShortRead: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::MSG_SHORT_READ != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testShortRead: "
+ "Buffer unexpectedly not in the MSG_SHORT_READ state "
+ "after populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testShortRead: "
+ "unexpectedly returned true for isMsgComplete"
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testShortRead test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testShortRead test failed!");
+ }
+ }
+
+ //-----------------------------------------------------------
+ void testOverrun()
+ {
+ SBE_BUFFER_TRACD("Enter sbeFifoBufferTest testOverrun");
+
+ //Test the case where the message is not completed and
+ //overruns the local buffer.
+
+ bool result{true};
+
+ do
+ {
+ uint32_t callerBuffer[2] = {0};
+ SbeFifoRespBufferTestFixture fifoBuffer(callerBuffer,
+ sizeof(callerBuffer)/sizeof(uint32_t));
+
+ if(not fifoBuffer)
+ {
+ TS_FAIL("sbeFifoBufferTest testOverrun: "
+ "The FIFO buffer is not in a good state after "
+ " CTOR call. Buffer state: %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ setTestData(&bufferOverrun);
+
+ while(fifoBuffer)
+ {
+ uint32_t value{};
+ bool rc = readTestData(value);
+ if(rc)
+ {
+ rc = fifoBuffer.append(value);
+ if(not rc && SbeFifoRespBuffer::OVERRUN !=
+ fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testOverrun: "
+ "append operation unexpectedly failed. "
+ "Fifo Buffer state = %s",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ fifoBuffer.completeMessage();
+ }
+ }
+
+ if(not result)
+ {
+ break;
+ }
+
+ if(SbeFifoRespBuffer::OVERRUN != fifoBuffer.getState())
+ {
+ TS_FAIL("sbeFifoBufferTest testOverrun: "
+ "Buffer unexpectedly not in the OVERRUN state "
+ "after populating buffer. State = %s.",
+ fifoBuffer.getStateString()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.isMsgComplete())
+ {
+ TS_FAIL("sbeFifoBufferTest testOverrun: "
+ "unexpectedly returned true for isMsgComplete"
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ if(result)
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testOverrun test passed!");
+ }
+ else
+ {
+ SBE_BUFFER_TRACD("sbeFifoBufferTest testOverrun test failed!");
+ }
+ }
+
+private:
+
+ std::vector<uint32_t>* iv_testData{};
+ std::vector<uint32_t>::const_iterator iv_itr;
+
+ //--------------------------------------------------------
+ void setTestData(std::vector<uint32_t>* i_testData)
+ {
+ iv_testData = i_testData;
+ resetTestData();
+ }
+
+ //---------------------------------------------------------
+ void resetTestData()
+ {
+ if(iv_testData)
+ {
+ iv_itr = iv_testData->begin();
+ }
+ }
+
+ //---------------------------------------------------------
+ bool readTestData(uint32_t& value)
+ {
+ bool retval{false};
+ if(iv_testData)
+ {
+ if(iv_itr != iv_testData->end())
+ {
+ value = *iv_itr;
+ ++iv_itr;
+ retval = true;
+ }
+ }
+
+ return retval;
+ }
+
+ //------------------------------------------------------------------
+ bool runChecks(expected_data& expData,
+ SbeFifoRespBufferTestFixture& fifoBuffer)
+ {
+
+ bool result{true};
+
+ do
+ {
+ if(expData.index != fifoBuffer.index())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s index not at %d as expected. Index = %d",
+ expData.test_name,
+ expData.index,
+ fifoBuffer.index()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(expData.offset_index != fifoBuffer.offsetIndex())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: offset index not at %d as expected. "
+ "Offset index = %d",
+ expData.test_name,
+ expData.offset_index,
+ fifoBuffer.offsetIndex()
+ );
+
+ result = false;
+ break;
+ }
+
+ uint32_t offset =
+ fifoBuffer.localBuffer()[fifoBuffer.offsetIndex()];
+
+ if(expData.offset != offset)
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "The offset is not %d as expected. Buffer Offset: %d",
+ expData.test_name,
+ expData.offset,
+ offset);
+
+ result = false;
+ break;
+ }
+
+ if(expData.statusIndex != fifoBuffer.statusIndex())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: status index not at %d as expected. "
+ "Status index = %d",
+ expData.test_name,
+ expData.statusIndex,
+ fifoBuffer.statusIndex()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getStatusHeader())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getStatusHeader unexpectedly returned a nullptr.",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(memcmp(expData.expected_status, fifoBuffer.getStatusHeader(),
+ sizeof(SbeFifo::statusHeader)) != 0)
+ {
+ char expected_xxd[128];
+ char actual_xxd[128];
+
+ xxdPrint(fifoBuffer.getStatusHeader(),
+ sizeof(SbeFifo::statusHeader),
+ actual_xxd);
+
+ xxdPrint(expData.expected_status,
+ sizeof(SbeFifo::statusHeader),
+ expected_xxd);
+
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "Buffer StatusHeader not as expected.\n"
+ "Status data: \n%s\n"
+ "Expected data: \n%s",
+ expData.test_name,
+ actual_xxd,
+ expected_xxd
+ );
+
+ result = false;
+ break;
+ }
+
+ if(expData.expectFFDC)
+ {
+ if(expData.ffdcIndex != fifoBuffer.ffdcIndex())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "ffdc index not at %d as expected. ffdc index %d",
+ expData.test_name,
+ expData.ffdcIndex,
+ fifoBuffer.ffdcIndex()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.msgContainsFFDC())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "msgContainsFFDC incorrectly returned false",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getFFDCPtr())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getFFDCPtr unexpectedly returned a nullptr.",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(expData.ffdcByteSize != fifoBuffer.getFFDCByteSize())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "Buffer FFDC size %d not as expected %d",
+ expData.test_name,
+ fifoBuffer.getFFDCByteSize(),
+ expData.ffdcByteSize
+ );
+
+ result = false;
+ break;
+ }
+
+ if(expData.ffdcByteSize/sizeof(uint32_t) !=
+ fifoBuffer.getFFDCWordSize())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "Buffer FFDC word size %d not as expected %d",
+ expData.test_name,
+ fifoBuffer.getFFDCWordSize(),
+ expData.ffdcByteSize/sizeof(uint32_t)
+ );
+
+ result = false;
+ break;
+ }
+
+ if(memcmp(fifoBuffer.getFFDCPtr(),
+ expData.expected_ffdc_data, expData.ffdcByteSize) != 0)
+ {
+ char expected_xxd[128];
+ char ffdc_xxd[128];
+
+ xxdPrint(fifoBuffer.getFFDCPtr(),
+ expData.ffdcByteSize,
+ ffdc_xxd);
+
+ xxdPrint(expData.expected_ffdc_data,
+ expData.ffdcByteSize,
+ expected_xxd);
+
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "Buffer FFDC data not as expected.\n"
+ "FFDC data: \n%s\n"
+ "Expected data: \n%s",
+ expData.test_name,
+ ffdc_xxd,
+ expected_xxd
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ if(SbeFifoRespBuffer::INVALID_INDEX != fifoBuffer.ffdcIndex())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "ffdc index not INVALID_INDEX as expected. "
+ "ffdc index = 0x%08X",
+ expData.test_name,
+ fifoBuffer.ffdcIndex()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.msgContainsFFDC())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "msgContainsFFDC incorrectly returned true",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getFFDCPtr())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getFFDCPtr unexpectedly returned a non-nullptr.",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getFFDCByteSize() > 0)
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getFFDCByteSize unexpectedly returned a "
+ "non zero value: 0x%08X",
+ expData.test_name,
+ fifoBuffer.getFFDCByteSize()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getFFDCWordSize() > 0)
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getFFDCWordSize unexpectedly returned a "
+ "non zero value: 0x%08X",
+ expData.test_name,
+ fifoBuffer.getFFDCWordSize()
+ );
+
+ result = false;
+ break;
+ }
+ }
+
+ if(expData.expectReturnData)
+ {
+ if(not fifoBuffer.msgContainsReturnData())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "msgContainsReturnData incorrectly returned false",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(not fifoBuffer.getReturnData())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getReturnData unexpectedly returned a nullptr.",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(expData.dataByteSize != fifoBuffer.getReturnDataByteSize())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "Buffer return data size %d not as expected %d",
+ expData.test_name,
+ fifoBuffer.getReturnDataByteSize(),
+ expData.dataByteSize
+ );
+
+ result = false;
+ break;
+ }
+
+ if(expData.dataByteSize/sizeof(uint32_t) !=
+ fifoBuffer.getReturnDataWordSize())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: Buffer Return data word size "
+ "%d not as expected %d",
+ expData.test_name,
+ fifoBuffer.getReturnDataWordSize(),
+ expData.dataByteSize/sizeof(uint32_t)
+ );
+
+ result = false;
+ break;
+ }
+
+ if(memcmp(fifoBuffer.getReturnData(),
+ expData.expected_data, expData.dataByteSize) != 0)
+ {
+ char expected_xxd[128];
+ char data_xxd[128];
+
+ xxdPrint(fifoBuffer.getReturnData(),
+ expData.dataByteSize,
+ data_xxd);
+
+ xxdPrint(expData.expected_data,
+ expData.dataByteSize,
+ expected_xxd);
+
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "Buffer Return data not as expected.\n"
+ "Return data: \n%s\n"
+ "Expected data: \n%s",
+ expData.test_name,
+ data_xxd,
+ expected_xxd
+ );
+
+ result = false;
+ break;
+ }
+ }
+ else
+ {
+ if(fifoBuffer.msgContainsReturnData())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "msgContainsReturnData incorrectly returned true",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getReturnData())
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: getReturnData unexpectedly "
+ "returned a non-nullptr.",
+ expData.test_name
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getReturnDataByteSize() > 0)
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getReturnDataByteSize unexpectedly returned a "
+ "non zero value: 0x%08X",
+ expData.test_name,
+ fifoBuffer.getReturnDataByteSize()
+ );
+
+ result = false;
+ break;
+ }
+
+ if(fifoBuffer.getReturnDataWordSize() > 0)
+ {
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "getReturnDataWordSize unexpectedly returned a "
+ "non zero value: 0x%08X",
+ expData.test_name,
+ fifoBuffer.getReturnDataWordSize()
+ );
+
+ result = false;
+ break;
+ }
+ }
+
+ //test that the caller buffer was populated
+ if(memcmp(fifoBuffer.callerBuffer(),
+ &((*iv_testData)[0]),
+ fifoBuffer.callerWordSize()*sizeof(uint32_t)) != 0)
+ {
+ char expected_xxd[128];
+ char caller_xxd[128];
+
+ size_t data_size = fifoBuffer.callerWordSize()*sizeof(uint32_t);
+
+ xxdPrint(fifoBuffer.callerBuffer(),
+ data_size,
+ caller_xxd);
+
+ xxdPrint(&((*iv_testData)[0]),
+ data_size,
+ expected_xxd);
+
+ snprintf(expData.strMessage,
+ sizeof(expData.strMessage),
+ "%s: "
+ "Caller buffer not as expected.\n"
+ "Caller Buffer: \n%s\n"
+ "Expected data: \n%s",
+ expData.test_name,
+ caller_xxd,
+ expected_xxd
+ );
+
+ result = false;
+ break;
+ }
+ }
+ while(0);
+
+ return result;
+ }
+
+};
+
+#endif
diff --git a/src/usr/sbeio/test/sbe_test_support.H b/src/usr/sbeio/test/sbe_test_support.H
new file mode 100644
index 000000000..606313a9e
--- /dev/null
+++ b/src/usr/sbeio/test/sbe_test_support.H
@@ -0,0 +1,91 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/test/sbe_test_support.H $ */
+/* */
+/* 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 */
+#ifndef __SBE_TEST_SUPPORT_H
+#define __SBE_TEST_SUPPORT_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+//---------------------------------------------------------------------
+template <size_t N>
+void xxdPrint(const void* pvbuffer,
+ size_t bufferSize,
+ char (&strBuffer)[N])
+{
+ if(nullptr == pvbuffer || 0 == bufferSize)
+ {
+ return;
+ }
+
+ const char* pbuffer = reinterpret_cast<const char*>(pvbuffer);
+
+ char* pstr = strBuffer;
+
+ int remaining = static_cast<int>(sizeof(strBuffer));
+ memset(strBuffer, 0, sizeof(strBuffer));
+
+ for(size_t i=0; i < bufferSize; ++i)
+ {
+ int rc{};
+ const uint8_t byteVal =
+ *(reinterpret_cast<const uint8_t*>(pbuffer++));
+ if(i == 0)
+ {
+ rc = snprintf(pstr, remaining, "\t\t\t\t%02X", byteVal);
+ }
+ else if(i%16 == 0)
+ {
+ rc = snprintf(pstr, remaining, "\n\t\t\t\t%02X", byteVal);
+ }
+ else
+ {
+ if(i%2 == 1)
+ {
+ rc = snprintf(pstr, remaining, "%02X ", byteVal);
+ }
+ else
+ {
+ rc = snprintf(pstr, remaining, "%02X", byteVal);
+ }
+ }
+
+ if(rc > 0 && rc < remaining)
+ {
+ remaining -= rc;
+ pstr += rc;
+
+ if(remaining <= 0)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+#endif
OpenPOWER on IntegriCloud