smbioshandler:move bmc region complete,Write& Lock

Rewrite "MDR_COMPLETE, WRITE & LOCK" cmds to new IPMI provider API.

Tested:
verified using ipmitool smbioshandler commands.
a. bmc region update complete
Command: ipmitool raw 0x3E 0x21 0xff 0xff
Output: Unable to send RAW command (channel=0x0 netfn=0x3e lun=0x0
        cmd=0x21 rsp=0xc9): Parameter out of range
Command: ipmitool raw 0x3E 0x21 0xff 0x0
Output: Unable to send RAW command (channel=0x0 netfn=0x3e lun=0x0
        cmd=0x21 rsp=0xd5): Command not supported in present state

b. bmc region write
Command: ipmitool raw 0x3E 0X24 0x01 0x2 0x03 0x00 0x01 04 0x01 0x01
Output: Unable to send RAW command (channel=0x0 netfn=0x3e lun=0x0
        cmd=0x24 rsp=0xd5): Command not supported in present state

c. bmc region lock, before and after the changes.
Command: ipmitool raw 0x3E 0X25 0x00 0x01 0x01 0xff 0xff
Output: f3

Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
Change-Id: I05c572c2fe4bd38091301944e85d9246bcf1faa5
diff --git a/include/smbioshandler.hpp b/include/smbioshandler.hpp
index 4e403ca..40e081f 100644
--- a/include/smbioshandler.hpp
+++ b/include/smbioshandler.hpp
@@ -60,12 +60,6 @@
     MDRState State;
 } __attribute__((packed));
 
-struct RegionCompleteRequest
-{
-    uint8_t sessionId;
-    uint8_t regionId;
-} __attribute__((packed));
-
 struct RegionReadRequest
 {
     uint8_t regionId;
@@ -80,21 +74,4 @@
     uint8_t data[msgPayloadSize];
 } __attribute__((packed));
 
-struct RegionWriteRequest
-{
-    uint8_t sessionId;
-    uint8_t regionId;
-    uint8_t length;
-    uint16_t offset;
-    uint8_t data[msgPayloadSize];
-} __attribute__((packed));
-
-struct RegionLockRequest
-{
-    uint8_t sessionId;
-    uint8_t regionId;
-    uint8_t lockPolicy;
-    uint16_t msTimeout;
-} __attribute__((packed));
-
 constexpr size_t maxMDRId = 5;
diff --git a/src/smbioshandler.cpp b/src/smbioshandler.cpp
index 9eebf7f..0c288b1 100644
--- a/src/smbioshandler.cpp
+++ b/src/smbioshandler.cpp
@@ -34,6 +34,7 @@
 constexpr const char* DBUS_PROPERTIES = "org.freedesktop.DBus.Properties";
 constexpr const char* MDRV1_PATH = "/xyz/openbmc_project/Smbios/MDR_V1";
 constexpr const char* MDRV1_INTERFACE = "xyz.openbmc_project.Smbios.MDR_V1";
+static constexpr const uint8_t ccOemSetInProcess = 0x81;
 
 static void register_netfn_smbios_functions() __attribute__((constructor));
 
@@ -125,63 +126,62 @@
     return 0;
 }
 
-ipmi_ret_t cmd_region_complete(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-                               ipmi_request_t request, ipmi_response_t response,
-                               ipmi_data_len_t data_len, ipmi_context_t context)
+/** @brief implements bmc region update Complete command
+ *  @param sessionId - session Lock Handle
+ *  @param regionId - data Region
+ *
+ *  @returns IPMI completion code
+ */
+ipmi::RspType<> bmcRegionUpdateComplete(uint8_t sessionId, uint8_t regionId)
 {
-    auto requestData = reinterpret_cast<const RegionCompleteRequest*>(request);
-    uint8_t status;
+    std::variant<uint8_t, uint16_t> value;
 
-    sdbusplus::message::variant<uint8_t, uint16_t> value;
-
-    if (*data_len != sizeof(RegionCompleteRequest))
-    {
-        *data_len = 0;
-        return IPMI_CC_REQ_DATA_LEN_INVALID;
-    }
-
-    uint8_t regionId = requestData->regionId - 1;
-    *data_len = 0;
-
-    if (regionId >= maxMDRId)
+    if ((regionId >= maxMDRId) || (regionId == 0))
     {
         phosphor::logging::log<level::ERR>("Invalid region");
-        return IPMI_CC_PARM_OUT_OF_RANGE;
+        return ipmi::responseParmOutOfRange();
     }
 
     std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
     std::string service = ipmi::getService(*bus, MDRV1_INTERFACE, MDRV1_PATH);
 
-    if (set_regionId(regionId, service) < 0)
+    uint8_t regionIdLocal = regionId - 1;
+
+    if (regionIdLocal == 0)
+    {
+        phosphor::logging::log<level::ERR>("Invalid region");
+        return ipmi::responseParmOutOfRange();
+    }
+    if (set_regionId(regionIdLocal, service) < 0)
     {
         phosphor::logging::log<level::ERR>("Error setting regionId");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
 
     if (0 > sdplus_mdrv1_get_property("LockPolicy", value, service))
     {
         phosphor::logging::log<level::ERR>("Error getting lockPolicy");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
     if (regionLockUnlocked == std::get<uint8_t>(value))
     {
-        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+        return ipmi::responseCommandNotAvailable();
     }
 
     if (0 > sdplus_mdrv1_get_property("SessionId", value, service))
     {
         phosphor::logging::log<level::ERR>("Error getting sessionId");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
-    if (requestData->sessionId != std::get<uint8_t>(value))
+    if (sessionId != std::get<uint8_t>(value))
     {
-        return IPMI_CC_OEM_SET_IN_PROCESS;
+        return ipmi::response(ccOemSetInProcess);
     }
 
     auto method = bus->new_method_call(service.c_str(), MDRV1_PATH,
                                        MDRV1_INTERFACE, "RegionComplete");
 
-    method.append(regionId);
+    method.append(regionIdLocal);
 
     auto reply = bus->call(method);
     if (reply.is_method_error())
@@ -190,16 +190,19 @@
             "Error set region complete",
             phosphor::logging::entry("SERVICE=%s", service.c_str()),
             phosphor::logging::entry("PATH=%s", MDRV1_PATH));
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
+    uint8_t status = 0;
     reply.read(status);
 
     if (status != 0)
+    {
         phosphor::logging::log<level::ERR>(
             "Error set region complete, unexpected error");
-    return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
+    }
 
-    return IPMI_CC_OK;
+    return ipmi::responseSuccess();
 }
 
 ipmi_ret_t cmd_region_read(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
@@ -290,71 +293,64 @@
     return IPMI_CC_OK;
 }
 
-ipmi_ret_t cmd_region_write(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-                            ipmi_request_t request, ipmi_response_t response,
-                            ipmi_data_len_t data_len, ipmi_context_t context)
+/** @brief implements bmc region write command
+ *  @parameter
+ *   - sessionId - session Lock Handle
+ *   - regionId - data Region
+ *   - length - data Length
+ *   - offset - data Offset
+ *   - data - data to be written
+ *
+ *  @returns IPMI completion code plus response data
+ *   - writeData - contains data Region, valid Data,
+ *                 lock Status, max Region Length, region Used (in bytes)
+ */
+ipmi::RspType<std::vector<uint8_t>>
+    bmcRegionWrite(uint8_t sessionId, uint8_t regionId, uint8_t length,
+                   uint16_t offset, std::vector<uint8_t> data)
 {
-    auto requestData = reinterpret_cast<const RegionWriteRequest*>(request);
-    uint8_t regionId = requestData->regionId - 1;
-    std::string res;
-    std::vector<uint8_t> writeData;
-    uint16_t index;
-    uint8_t tmp[255];
+    std::variant<uint8_t, uint16_t> value;
 
-    size_t minInputLen = &requestData->data[0] - &requestData->sessionId + 1;
-    if (*data_len < minInputLen)
-    { // this command need at least 6 bytes input
-        *data_len = 0;
-        return IPMI_CC_REQ_DATA_LEN_INVALID;
-    }
-
-    sdbusplus::message::variant<uint8_t, uint16_t> value;
-
-    *data_len = 0;
-
-    if (regionId >= maxMDRId)
+    if ((regionId >= maxMDRId) || (regionId == 0))
     {
         phosphor::logging::log<level::ERR>("Invalid region");
-        return IPMI_CC_PARM_OUT_OF_RANGE;
+        return ipmi::responseParmOutOfRange();
     }
 
     std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
     std::string service = ipmi::getService(*bus, MDRV1_INTERFACE, MDRV1_PATH);
 
-    if (set_regionId(regionId, service) < 0)
+    uint8_t regionIdLocal = regionId - 1;
+
+    if (set_regionId(regionIdLocal, service) < 0)
     {
         phosphor::logging::log<level::ERR>("Error setting regionId");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
 
     if (0 > sdplus_mdrv1_get_property("LockPolicy", value, service))
     {
         phosphor::logging::log<level::ERR>("Error getting lockPolicy");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
     if (regionLockUnlocked == std::get<uint8_t>(value))
     {
-        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+        return ipmi::responseCommandNotAvailable();
     }
 
     if (0 > sdplus_mdrv1_get_property("SessionId", value, service))
     {
         phosphor::logging::log<level::ERR>("Error getting sessionId");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
-    if (requestData->sessionId != std::get<uint8_t>(value))
+    if (sessionId != std::get<uint8_t>(value))
     {
-        return IPMI_CC_OEM_SET_IN_PROCESS;
+        return ipmi::response(ccOemSetInProcess);
     }
 
-    std::copy(&(requestData->length), &(requestData->data[requestData->length]),
-              tmp);
-    writeData.push_back(regionId);
-    for (index = 0; index < minInputLen + requestData->length - 2; index++)
-    {
-        writeData.push_back(tmp[index]);
-    }
-
+    std::vector<uint8_t> writeData;
+    std::copy(data.begin(), data.begin() + length,
+              writeData.data() + sizeof(regionIdLocal) + sizeof(length));
     auto method = bus->new_method_call(service.c_str(), MDRV1_PATH,
                                        MDRV1_INTERFACE, "RegionWrite");
 
@@ -367,67 +363,68 @@
             "Error write region data",
             phosphor::logging::entry("SERVICE=%s", service.c_str()),
             phosphor::logging::entry("PATH=%s", MDRV1_PATH));
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
+    std::string res;
     reply.read(res);
 
     if (res == "NoData")
     {
-        return IPMI_CC_PARM_OUT_OF_RANGE;
+        return ipmi::responseParmOutOfRange();
     }
     else if (res != "Success")
     {
         phosphor::logging::log<level::ERR>(
             "Error write region data, unexpected error");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
 
-    return IPMI_CC_OK;
+    return ipmi::responseSuccess(writeData);
 }
 
-ipmi_ret_t cmd_region_lock(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-                           ipmi_request_t request, ipmi_response_t response,
-                           ipmi_data_len_t data_len, ipmi_context_t context)
+/** @brief implements bmc region lock command
+ *  @parameter
+ *   - sessionId - session Lock Handle
+ *   - regionId - data Region
+ *   - lockPolicy - Lock Type
+ *   - msTimeout - timeout. Number of milliseconds allowed before lock is
+ * released
+ *
+ *  @returns IPMI completion code plus response data
+ *   - lockResponse - session Lock Handle
+ */
+ipmi::RspType<uint8_t> // lockResponse
+    bmcRegionLock(uint8_t sessionId, uint8_t regionId, uint8_t lockPolicy,
+                  uint16_t msTimeout)
 {
-    auto requestData = reinterpret_cast<const RegionLockRequest*>(request);
-    uint8_t regionId = requestData->regionId - 1;
-    sdbusplus::message::variant<uint8_t, uint16_t> value;
-    auto res = reinterpret_cast<uint8_t*>(response);
-    uint8_t lockResponse;
+    std::variant<uint8_t, uint16_t> value;
 
-    if (*data_len != sizeof(RegionLockRequest))
-    {
-        *data_len = 0;
-        return IPMI_CC_REQ_DATA_LEN_INVALID;
-    }
-
-    *data_len = 0;
-
-    if (regionId >= maxMDRId)
+    if ((regionId >= maxMDRId) || (regionId == 0))
     {
         phosphor::logging::log<level::ERR>("Invalid region");
-        return IPMI_CC_PARM_OUT_OF_RANGE;
+        return ipmi::responseParmOutOfRange();
     }
 
     std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
     std::string service = ipmi::getService(*bus, MDRV1_INTERFACE, MDRV1_PATH);
 
-    if (set_regionId(regionId, service) < 0)
+    uint8_t regionIdLocal = regionId - 1;
+    if (set_regionId(regionIdLocal, service) < 0)
     {
         phosphor::logging::log<level::ERR>("Error setting regionId");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
 
     if (0 > sdplus_mdrv1_get_property("LockPolicy", value, service))
     {
         phosphor::logging::log<level::ERR>("Error getting lockPolicy");
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
-    if (requestData->lockPolicy == regionLockUnlocked)
+    if (lockPolicy == regionLockUnlocked)
     {
         if (regionLockUnlocked == std::get<uint8_t>(value))
         {
-            return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+            return ipmi::responseCommandNotAvailable();
         }
     }
     if (regionLockUnlocked != std::get<uint8_t>(value))
@@ -435,21 +432,20 @@
         if (0 > sdplus_mdrv1_get_property("SessionId", value, service))
         {
             phosphor::logging::log<level::ERR>("Error getting sessionId");
-            return IPMI_CC_UNSPECIFIED_ERROR;
+            return ipmi::responseUnspecifiedError();
         }
-        if (requestData->sessionId != std::get<uint8_t>(value))
+        if (sessionId != std::get<uint8_t>(value))
         {
-            if (requestData->lockPolicy != regionLockStrict)
+            if (lockPolicy != regionLockStrict)
             {
-                return IPMI_CC_OEM_SET_IN_PROCESS;
+                return ipmi::response(ccOemSetInProcess);
             }
         }
     }
     auto method = bus->new_method_call(service.c_str(), MDRV1_PATH,
                                        MDRV1_INTERFACE, "RegionLock");
 
-    method.append(requestData->sessionId, regionId, requestData->lockPolicy,
-                  requestData->msTimeout);
+    method.append(sessionId, regionIdLocal, lockPolicy, msTimeout);
 
     auto reply = bus->call(method);
     if (reply.is_method_error())
@@ -458,13 +454,12 @@
             "Error lock region ",
             phosphor::logging::entry("SERVICE=%s", service.c_str()),
             phosphor::logging::entry("PATH=%s", MDRV1_PATH));
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
+    uint8_t lockResponse = 0;
     reply.read(lockResponse);
 
-    *data_len = sizeof(lockResponse);
-    *res = lockResponse;
-    return IPMI_CC_OK;
+    return ipmi::responseSuccess(lockResponse);
 }
 
 static void register_netfn_smbios_functions(void)
@@ -476,9 +471,9 @@
                            cmd_region_status, PRIVILEGE_OPERATOR);
 
     // <Update Complete Status Command>
-    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
-                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_COMPLETE, NULL,
-                           cmd_region_complete, PRIVILEGE_OPERATOR);
+    ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
+                          IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_COMPLETE,
+                          ipmi::Privilege::Operator, bmcRegionUpdateComplete);
 
     // <Read MDR Command>
     ipmi_register_callback(NETFUN_INTEL_APP_OEM,
@@ -486,12 +481,12 @@
                            cmd_region_read, PRIVILEGE_OPERATOR);
 
     // <Write MDR Command>
-    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
-                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_WRITE, NULL,
-                           cmd_region_write, PRIVILEGE_OPERATOR);
+    ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
+                          IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_WRITE,
+                          ipmi::Privilege::Operator, bmcRegionWrite);
 
     // <Lock MDR Command>
-    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
-                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_LOCK, NULL,
-                           cmd_region_lock, PRIVILEGE_OPERATOR);
+    ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
+                          IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_LOCK,
+                          ipmi::Privilege::Operator, bmcRegionLock);
 }