cater for fru read callback functions

Change-Id: I2fdaef98faa6adc19efce0ede93b4ee728b9404c
Signed-off-by: Marri Devender Rao <devenrao@in.ibm.com>
diff --git a/storagehandler.cpp b/storagehandler.cpp
index a1b3f03..36e1bb4 100644
--- a/storagehandler.cpp
+++ b/storagehandler.cpp
@@ -5,6 +5,7 @@
 #include <mapper.h>
 #include <chrono>
 #include "selutility.hpp"
+#include <algorithm>
 #include "storagehandler.h"
 #include "storageaddsel.h"
 #include "utils.hpp"
@@ -13,10 +14,11 @@
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/server.hpp>
 #include "xyz/openbmc_project/Common/error.hpp"
+#include "read_fru_data.hpp"
+#include <phosphor-logging/elog-errors.hpp>
 
 void register_netfn_storage_functions() __attribute__((constructor));
 
-
 unsigned int   g_sel_time    = 0xFFFFFFFF;
 extern unsigned short g_sel_reserve;
 
@@ -42,6 +44,17 @@
 using InternalFailure =
         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 using namespace phosphor::logging;
+using namespace ipmi::fru;
+
+/**
+ * @enum Device access mode
+ */
+enum class AccessMode
+{
+    bytes, ///< Device is accessed by bytes
+    words  ///< Device is accessed by words
+};
+
 
 ipmi_ret_t ipmi_storage_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                               ipmi_request_t request, ipmi_response_t response,
@@ -579,6 +592,29 @@
         ipmi_context_t context)
 {
     ipmi_ret_t rc = IPMI_CC_OK;
+    const FruInvenAreaInfoRequest* reqptr =
+        reinterpret_cast<const FruInvenAreaInfoRequest*>(request);
+    try
+    {
+        const auto& fruArea = getFruAreaData(reqptr->fruID);
+        auto size = static_cast<uint16_t>(fruArea.size());
+        FruInvenAreaInfoResponse resp;
+        resp.sizems = size >> 8;
+        resp.sizels = size;
+        resp.access = static_cast<uint8_t>(AccessMode::bytes);
+
+        *data_len = sizeof(resp);
+
+        // Pack the actual response
+        memcpy(response, &resp, *data_len);
+    }
+    catch(const InternalFailure& e)
+    {
+        rc = IPMI_CC_UNSPECIFIED_ERROR;
+        *data_len = 0;
+        log<level::ERR>(e.what());
+        report<InternalFailure>();
+    }
     return rc;
 }
 
@@ -589,11 +625,36 @@
         ipmi_context_t context)
 {
     ipmi_ret_t rc = IPMI_CC_OK;
+    const ReadFruDataRequest* reqptr =
+         reinterpret_cast<const ReadFruDataRequest*>(request);
+    auto offset =
+        static_cast<uint16_t>(reqptr->offsetMS << 8 | reqptr->offsetLS);
+    try
+    {
+        const auto& fruArea = getFruAreaData(reqptr->fruID);
+        auto size = fruArea.size();
+        if ((offset + reqptr->count) > size)
+        {
+            log<level::ERR>("Invalid offset and count",
+                entry("Offset=%d Count=%d SizeOfFruArea=%d",
+                offset, reqptr->count, size));
+            return IPMI_CC_INVALID;
+        }
+        std::copy((fruArea.begin() + offset), (fruArea.begin() + reqptr->count),
+                (static_cast<uint8_t*>(response)));
+        *data_len = reqptr->count;
+    }
+    catch (const InternalFailure& e)
+    {
+        rc = IPMI_CC_UNSPECIFIED_ERROR;
+        *data_len = 0;
+        log<level::ERR>(e.what());
+        report<InternalFailure>();
+    }
     return rc;
 }
 
 
-
 void register_netfn_storage_functions()
 {
     // <Wildcard Command>
@@ -648,9 +709,9 @@
     // <Add READ FRU Data
     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_STORAGE,
             IPMI_CMD_READ_FRU_DATA);
-
     ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_READ_FRU_DATA, NULL,
             ipmi_storage_read_fru_data, PRIVILEGE_OPERATOR);
+
     return;
 }
 
diff --git a/storagehandler.h b/storagehandler.h
index 7f1b67d..a971f77 100644
--- a/storagehandler.h
+++ b/storagehandler.h
@@ -30,4 +30,36 @@
 	uint8_t eventdir;
 	uint8_t eventdata[3];
 };
+
+/**
+ * @struct Read FRU Data command request data
+ */
+struct ReadFruDataRequest
+{
+    uint8_t  fruID; ///< FRU Device ID. FFh = reserved
+    uint8_t  offsetLS; ///< FRU Inventory Offset to read, LS Byte
+    uint8_t  offsetMS; ///< FRU Inventory Offset ro read, MS Byte
+    uint8_t  count; ///< Count to read
+}__attribute__ ((packed));
+
+/**
+ * @struct Get FRU inventory area info command request data
+ */
+struct FruInvenAreaInfoRequest
+{
+    uint8_t fruID; ///< FRU Device ID. FFH = reserved.
+}__attribute__ ((packed));
+
+
+/**
+ * @struct Get FRU inventory area info command response
+ */
+struct FruInvenAreaInfoResponse
+{
+    uint8_t  completionCode;  ///< Completion code
+    uint8_t  sizels;          ///< Fru Inventory area size in bytes, LS Byte
+    uint8_t  sizems;          ///< Fru Inventory are size in bytes, MS Byte
+    uint8_t  access;    ///< 0b Devices is accessed by bytes, 1b - by words
+}__attribute__ ((packed));
+
 #endif