Refactor to use new version of OEM IPMI Handler

Using the new version of ipmi handler provide a higher level wrapper
over the same functionalities. It helps us parse the input and output to
have more control of the input/output we see.

Changes to note,
- All cmd are removed from the request data. That is automatically
  extracted now.

Tested:
Unit Test Passed.

All IPMI OEM command still works the same as before this change.

```
$ burn_my_bmc -command stage -image /tmp/test.txt -interface ipmipci
Set up ipmi flash updater with /flash/dummy
Received failure on delete: Received IPMI_CC: 255
Sending over the firmware image.
Find [0x1050 0x750]
bar0[0x94000000]
Upload to BMC 100% |Goooooooooooooooooooooooooooooooooooooooooooooooooooooooogle| Time: 00:00:00
Opening the verification file
Committing to /flash/verify to trigger service
Calling stat on /flash/verify session to check status
success
succeeded
```

Also tested gBMC Update workflow which worked fine.

Change-Id: Ib2bfeab0c2ec5aa72ede1ff457ef5f90e488053c
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/process.cpp b/process.cpp
index 2481fa2..46ffea5 100644
--- a/process.cpp
+++ b/process.cpp
@@ -20,7 +20,10 @@
 
 #include <cstring>
 #include <ipmiblob/crc.hpp>
+#include <ipmid/api-types.hpp>
+#include <span>
 #include <unordered_map>
+#include <utility>
 #include <vector>
 
 namespace blobs
@@ -29,7 +32,6 @@
 /* Used by all commands with data. */
 struct BmcRx
 {
-    uint8_t cmd;
     uint16_t crc;
     uint8_t data; /* one byte minimum of data. */
 } __attribute__((packed));
@@ -48,29 +50,29 @@
     {BlobOEMCommands::bmcBlobWriteMeta, writeMeta},
 };
 
-IpmiBlobHandler validateBlobCommand(const uint8_t* reqBuf,
-                                    uint8_t* /*replyCmdBuf*/, size_t* dataLen,
-                                    ipmi_ret_t* code)
+IpmiBlobHandler validateBlobCommand(uint8_t cmd, std::span<const uint8_t> data)
 {
-    size_t requestLength = (*dataLen);
+    size_t requestLength = data.size();
     /* We know dataLen is at least 1 already */
-    auto command = static_cast<BlobOEMCommands>(reqBuf[0]);
+    auto command = static_cast<BlobOEMCommands>(cmd);
 
     /* Validate it's at least well-formed. */
     if (!validateRequestLength(command, requestLength))
     {
-        *code = IPMI_CC_REQ_DATA_LEN_INVALID;
-        return nullptr;
+        return [](ManagerInterface*, std::span<const uint8_t>) {
+            return ipmi::responseReqDataLenInvalid();
+        };
     }
 
     /* If there is a payload. */
-    if (requestLength > sizeof(uint8_t))
+    if (requestLength > sizeof(cmd))
     {
         /* Verify the request includes: command, crc16, data */
         if (requestLength < sizeof(struct BmcRx))
         {
-            *code = IPMI_CC_REQ_DATA_LEN_INVALID;
-            return nullptr;
+            return [](ManagerInterface*, std::span<const uint8_t>) {
+                return ipmi::responseReqDataLenInvalid();
+            };
         }
 
         /* We don't include the command byte at offset 0 as part of the crc
@@ -81,44 +83,58 @@
         /* We start after the command byte. */
         std::vector<uint8_t> bytes(requestBodyLen);
 
-        /* It likely has a well-formed payload. */
-        struct BmcRx request;
-        std::memcpy(&request, reqBuf, sizeof(request));
-        uint16_t crcValue = request.crc;
+        /* It likely has a well-formed payload.
+         * Get the first two bytes of the request for crc.
+         */
+        uint16_t crc;
+        if (data.size() < sizeof(crc))
+        {
+            return [](ManagerInterface*, std::span<const uint8_t>) {
+                return ipmi::responseReqDataLenInvalid();
+            };
+        }
+        std::memcpy(&crc, data.data(), sizeof(crc));
 
-        /* Set the in-place CRC to zero. */
-        std::memcpy(bytes.data(), &reqBuf[3], requestBodyLen);
+        /* Set the in-place CRC to zero.
+         * Remove the first two bytes for crc and get the reset of the request.
+         */
+        data = data.subspan(sizeof(crc));
 
         /* Crc expected but didn't match. */
-        if (crcValue != ipmiblob::generateCrc(bytes))
+        if (crc != ipmiblob::generateCrc(
+                       std::vector<uint8_t>(data.begin(), data.end())))
         {
-            *code = IPMI_CC_UNSPECIFIED_ERROR;
-            return nullptr;
-        }
+            return [](ManagerInterface*, std::span<const uint8_t>) {
+                return ipmi::responseUnspecifiedError();
+            };
+        };
     }
 
     /* Grab the corresponding handler for the command. */
     auto found = handlers.find(command);
     if (found == handlers.end())
     {
-        *code = IPMI_CC_INVALID_FIELD_REQUEST;
-        return nullptr;
+        return [](ManagerInterface*, std::span<const uint8_t>) {
+            return ipmi::responseInvalidFieldRequest();
+        };
     }
 
     return found->second;
 }
 
-ipmi_ret_t processBlobCommand(IpmiBlobHandler cmd, ManagerInterface* mgr,
-                              const uint8_t* reqBuf, uint8_t* replyCmdBuf,
-                              size_t* dataLen)
+Resp processBlobCommand(IpmiBlobHandler cmd, ManagerInterface* mgr,
+                        std::span<const uint8_t> data)
 {
-    ipmi_ret_t result = cmd(mgr, reqBuf, replyCmdBuf, dataLen);
-    if (result != IPMI_CC_OK)
+    Resp result = cmd(mgr, data);
+    if (std::get<0>(result) != ipmi::ccSuccess)
     {
         return result;
     }
 
-    size_t replyLength = (*dataLen);
+    std::vector<uint8_t>& response = std::get<0>(
+        // std::variant<std::vector<uint8_t>>
+        *std::get<1>(result));
+    size_t replyLength = response.size();
 
     /* The command, whatever it was, returned success. */
     if (replyLength == 0)
@@ -131,42 +147,30 @@
      */
     if (replyLength < (sizeof(uint16_t)))
     {
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::responseUnspecifiedError();
     }
 
     /* The command, whatever it was, replied, so let's set the CRC. */
-    std::vector<std::uint8_t> crcBuffer(replyCmdBuf + sizeof(uint16_t),
-                                        replyCmdBuf + replyLength);
+    std::span<const uint8_t> responseView = response;
+    responseView = responseView.subspan(sizeof(uint16_t));
+    std::vector<std::uint8_t> crcBuffer(responseView.begin(),
+                                        responseView.end());
     /* Copy the CRC into place. */
     uint16_t crcValue = ipmiblob::generateCrc(crcBuffer);
-    std::memcpy(replyCmdBuf, &crcValue, sizeof(crcValue));
+    if (response.size() < sizeof(crcValue))
+    {
+        return ipmi::responseReqDataLenInvalid();
+    }
+    std::memcpy(response.data(), &crcValue, sizeof(crcValue));
 
     return result;
 }
 
-ipmi_ret_t handleBlobCommand(ipmi_cmd_t, const uint8_t* reqBuf,
-                             uint8_t* replyCmdBuf, size_t* dataLen)
+Resp handleBlobCommand(uint8_t cmd, std::vector<uint8_t> data)
 {
-    /* It's holding at least a sub-command.  The OEN is trimmed from the bytes
-     * before this is called.
-     */
-    if ((*dataLen) < 1)
-    {
-        return IPMI_CC_REQ_DATA_LEN_INVALID;
-    }
-
     /* on failure rc is set to the corresponding IPMI error. */
-    ipmi_ret_t rc = IPMI_CC_OK;
-    IpmiBlobHandler command =
-        validateBlobCommand(reqBuf, replyCmdBuf, dataLen, &rc);
-    if (command == nullptr)
-    {
-        (*dataLen) = 0;
-        return rc;
-    }
-
-    return processBlobCommand(command, getBlobManager(), reqBuf, replyCmdBuf,
-                              dataLen);
+    return processBlobCommand(validateBlobCommand(cmd, data), getBlobManager(),
+                              data);
 }
 
 } // namespace blobs