Refactor Set Firmware Update Mode command

Refactor Set firmware Update Mode command
along with fixing issues around completion code.

Tested:
Tested scenario's for proper completion code
 - Invalid random number length: rsp=0xc7
 - Wrong random number : rsp=0xcc
 - Random number expired : rsp=0xcc
 - Already update in progress: rsp=0xc0(busy)
 - All good : 0x00

Change-Id: I9c4dbfeed43ee6f218633cc8f4fd26d82eb07f49
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
diff --git a/src/firmware-update.cpp b/src/firmware-update.cpp
index e836458..f9cd153 100644
--- a/src/firmware-update.cpp
+++ b/src/firmware-update.cpp
@@ -288,48 +288,40 @@
     return IPMI_CC_OK;
 }
 
-static ipmi_ret_t ipmi_firmware_enter_fw_transfer_mode(
-    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 Set Firmware Update Mode
+ *
+ *  This function sets BMC into firmware update mode
+ *  after validating Random number obtained from the Get
+ *  Firmware Update Random Number command
+ *
+ *  @parameter
+ *   -  randNum - Random number(token)
+ *  @returns IPMI completion code
+ **/
+ipmi::RspType<> ipmiSetFirmwareUpdateMode(
+    std::array<uint8_t, FW_RANDOM_NUMBER_LENGTH> &randNum)
 {
-    if (DEBUG)
-        std::cerr << "Enter FW transfer mode requested, data_len = "
-                  << *data_len << '\n';
-
-    if (*data_len != FW_RANDOM_NUMBER_LENGTH)
-    {
-        *data_len = 0;
-        return IPMI_CC_REQ_DATA_LEN_INVALID;
-    }
-    *data_len = 0;
-
-    auto rq_time = std::chrono::steady_clock::now();
-    if (DEBUG)
-        std::cerr << "now - fwts = "
-                  << std::chrono::duration_cast<std::chrono::microseconds>(
-                         rq_time - fw_random_number_timestamp)
-                         .count()
-                  << " us\n";
-    if (std::chrono::duration_cast<std::chrono::microseconds>(
-            rq_time - fw_random_number_timestamp)
+    /* Firmware Update Random number is valid for 30 seconds only */
+    auto timeElapsed =
+        (std::chrono::steady_clock::now() - fw_random_number_timestamp);
+    if (std::chrono::duration_cast<std::chrono::microseconds>(timeElapsed)
             .count() > std::chrono::duration_cast<std::chrono::microseconds>(
                            FW_RANDOM_NUMBER_TTL)
                            .count())
     {
-        if (DEBUG)
-            std::cerr << "key timeout\n";
-        return IPMI_CC_PARM_OUT_OF_RANGE;
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "Firmware update random number expired.");
+        return ipmi::responseInvalidFieldRequest();
     }
 
-    uint8_t *msg_request = static_cast<uint8_t *>(request);
+    /* Validate random number */
     for (int i = 0; i < FW_RANDOM_NUMBER_LENGTH; i++)
     {
-        if (fw_random_number[i] != msg_request[i])
+        if (fw_random_number[i] != randNum[i])
         {
-            if (DEBUG)
-                std::cerr << "key error" << (int)fw_random_number[i]
-                          << "!=" << (int)msg_request[i] << "\n";
-            return IPMI_CC_INVALID_FIELD_REQUEST;
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                "Invalid random number specified.");
+            return ipmi::responseInvalidFieldRequest();
         }
     }
 
@@ -340,21 +332,21 @@
         // mechanism at finer grain
         && fw_update_status.state() != fw_update_status_cache::FW_STATE_INIT)
     {
-        if (DEBUG)
-            std::cerr << "not in INIT or IDLE\n";
-        return IPMI_CC_INVALID_FIELD_REQUEST;
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "Already firmware update is in progress.");
+        return ipmi::responseBusy();
     }
     // FIXME? c++ doesn't off an option for exclusive file creation
     FILE *fp = fopen(FIRMWARE_BUFFER_FILE, "wx");
     if (!fp)
     {
-        if (DEBUG)
-            std::cerr << "failed to create buffer file\n";
-        return IPMI_CC_INVALID_FIELD_REQUEST;
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "Unable to open file.");
+        return ipmi::responseUnspecifiedError();
     }
     fclose(fp);
 
-    return IPMI_CC_OK;
+    return ipmi::responseSuccess();
 }
 
 static ipmi_ret_t ipmi_firmware_exit_fw_update_mode(
@@ -1722,10 +1714,10 @@
                            NULL, ipmi_firmware_get_fw_random_number,
                            PRIVILEGE_ADMIN);
 
-    // enter firmware update mode
-    ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_SET_FW_UPDATE_MODE,
-                           NULL, ipmi_firmware_enter_fw_transfer_mode,
-                           PRIVILEGE_ADMIN);
+    // Set Firmware Update Mode(0x27)
+    ipmi::registerHandler(ipmi::prioOemBase, NETFUN_FIRMWARE,
+                          IPMI_CMD_FW_SET_FW_UPDATE_MODE,
+                          ipmi::Privilege::Admin, ipmiSetFirmwareUpdateMode);
 
     // exit firmware update mode
     ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_EXIT_FW_UPDATE_MODE,