Implement parsing of SBE response data

Changes include:
- Utility interface for parsing the response from the SBE.

Change-Id: Ib05d40a7b9257f0cd53597e1fdee5677994072b1
Signed-off-by: Murulidhar Nataraju <murulidhar@in.ibm.com>
diff --git a/sbe_chipOp_handler.cpp b/sbe_chipOp_handler.cpp
new file mode 100644
index 0000000..f662690
--- /dev/null
+++ b/sbe_chipOp_handler.cpp
@@ -0,0 +1,116 @@
+#include <stdexcept>
+#include <array>
+#include <sbe_chipOp_handler.hpp>
+namespace openpower
+{
+namespace sbe
+{
+namespace internal
+{
+/*! \union sbeRespHeader_t
+ *  Defines the breakup of the SBE FIFO chip operation response header.
+ */
+union sbeRespHeader_t
+{
+    uint32_t commandWord; /**<Entire 32 bit command word */
+    struct
+    {
+        uint8_t command: 8; /**<command value for which response is obtained */
+        uint8_t commandClass: 8; /**< Class of the command */
+        uint16_t magic: 16; /**< Magic code obtained in the response */
+    };
+} __attribute__((packed));
+
+
+constexpr uint16_t MAGIC_CODE = 0xC0DE;
+constexpr auto SBE_OPERATION_SUCCESSFUL = 0;
+constexpr auto LENGTH_OF_DISTANCE_HEADER_IN_WORDS = 0x1;
+constexpr auto LENGTH_OF_RESP_HEADER_IN_WORDS = 0x2;
+constexpr auto SBEI_SBE_RESPONSE_SIZE_IN_WORDS = ((sizeof(sbeRespHeader_t) + \
+        sizeof(sbe_word_t)) / 4);
+constexpr auto DISTANCE_TO_RESP_CODE = 0x1;
+
+std::vector<sbe_word_t> write(const char* devPath,
+                              const sbe_word_t* cmdBuffer,
+                              size_t cmdBufLen,
+                              size_t respBufLen)
+{
+    //TODO: Add support for reading and writing from the FIFO device
+    std::vector<sbe_word_t> response(respBufLen);
+    return response;
+}
+
+std::vector<sbe_word_t> parseResponse(
+    const std::vector<sbe_word_t>& sbeDataBuf)
+{
+
+    //Number of 32-bit words obtained from the SBE
+    size_t lengthObtained = sbeDataBuf.size();
+
+    //Fetch the SBE header and SBE chiop primary and secondary status
+    //Last value in the buffer will have the offset for the SBE header
+    size_t distanceToStatusHeader =  sbeDataBuf[sbeDataBuf.size() - 1];
+
+    if (lengthObtained < distanceToStatusHeader)
+    {
+        //TODO:use elog infrastructure
+        std::ostringstream errMsg;
+        errMsg << "Distance to SBE status header value " <<
+               distanceToStatusHeader << " is greater then total lenght of "
+               "response buffer " << lengthObtained;
+        throw std::runtime_error(errMsg.str().c_str());
+    }
+
+    //Fetch the response header contents
+    sbeRespHeader_t l_respHeader{};
+    auto iter = sbeDataBuf.begin();
+    std::advance(iter, (lengthObtained - distanceToStatusHeader));
+    l_respHeader.commandWord = *iter;
+
+    //Fetch the primary and secondary response code
+    std::advance(iter, DISTANCE_TO_RESP_CODE);
+    auto l_priSecResp = *iter;
+
+    //Validate the magic code obtained in the response
+    if (l_respHeader.magic != MAGIC_CODE)
+    {
+        //TODO:use elog infrastructure
+        std::ostringstream errMsg;
+        errMsg << "Invalid MAGIC keyword in the response header (" <<
+               l_respHeader.magic << "),expected keyword " << MAGIC_CODE;
+        throw std::runtime_error(errMsg.str().c_str());
+    }
+
+    //Validate the Primary and Secondary response value
+    if (l_priSecResp != SBE_OPERATION_SUCCESSFUL)
+    {
+        //Extract the SBE FFDC and throw it to the caller
+        size_t ffdcLen = (distanceToStatusHeader -
+                          SBEI_SBE_RESPONSE_SIZE_IN_WORDS -
+                          LENGTH_OF_DISTANCE_HEADER_IN_WORDS);
+        if (ffdcLen)
+        {
+            std::vector<sbe_word_t> ffdcData(ffdcLen);
+            //Fetch the offset of FFDC data
+            auto ffdcOffset = (lengthObtained - distanceToStatusHeader) +
+                              LENGTH_OF_RESP_HEADER_IN_WORDS;
+            std::copy_n((sbeDataBuf.begin() + ffdcOffset), ffdcLen,
+                        ffdcData.begin());
+        }
+
+        //TODO:use elog infrastructure to return the SBE and Hardware procedure
+        //FFDC container back to the caller.
+        std::ostringstream errMsg;
+        errMsg << "Chip operation failed with SBE response code:" << l_priSecResp
+               << ".Length of FFDC data of obtained:" << ffdcLen;
+        throw std::runtime_error(errMsg.str().c_str());
+    }
+    return sbeDataBuf;
+
+}
+
+}
+}
+}
+
+