dcmi: asset-tag: Implement Set Asset tag command

Resolves openbmc/openbmc#1854

Change-Id: Iba00a732aa30fb60fc0b1550daec0e4055af74fa
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index 5b83ac8..0b98036 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -182,6 +182,66 @@
     return IPMI_CC_OK;
 }
 
+ipmi_ret_t setAssetTag(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)
+{
+    auto requestData = reinterpret_cast<const dcmi::SetAssetTagRequest*>
+                   (request);
+    std::vector<uint8_t> outPayload(sizeof(dcmi::SetAssetTagResponse));
+    auto responseData = reinterpret_cast<dcmi::SetAssetTagResponse*>
+            (outPayload.data());
+
+    if (requestData->groupID != dcmi::groupExtId)
+    {
+        *data_len = 0;
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+
+    // Verify offset to read and number of bytes to read are not exceeding the
+    // range.
+    if ((requestData->offset > dcmi::assetTagMaxOffset) ||
+        (requestData->bytes > dcmi::maxBytes) ||
+        ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize))
+    {
+        *data_len = 0;
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string assetTag;
+
+    try
+    {
+        assetTag = dcmi::readAssetTag();
+
+        if (requestData->offset > assetTag.size())
+        {
+            *data_len = 0;
+            return IPMI_CC_PARM_OUT_OF_RANGE;
+        }
+
+        assetTag.replace(requestData->offset,
+                         assetTag.size() - requestData->offset,
+                         static_cast<const char*>(request) +
+                         sizeof(dcmi::SetAssetTagRequest),
+                         requestData->bytes);
+
+        dcmi::writeAssetTag(assetTag);
+
+        responseData->groupID = dcmi::groupExtId;
+        responseData->tagLength = assetTag.size();
+        memcpy(response, outPayload.data(), outPayload.size());
+        *data_len = outPayload.size();
+
+        return IPMI_CC_OK;
+    }
+    catch (InternalFailure& e)
+    {
+        *data_len = 0;
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+}
+
 void register_netfn_dcmi_functions()
 {
     // <Get Power Limit>
@@ -193,6 +253,11 @@
     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_ASSET_TAG);
     ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_ASSET_TAG, NULL, getAssetTag,
                            PRIVILEGE_USER);
+
+    // <Set Asset Tag>
+    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, IPMI_CMD_DCMI_SET_ASSET_TAG);
+    ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_SET_ASSET_TAG, NULL, setAssetTag,
+                           PRIVILEGE_OPERATOR);
     return;
 }
 // 956379