Add Set Special user password command

Set special user password command support added.
This will be used to set the password for the linux
uid 0 (root) user.

Tested:
1. Verified able to change the root password using this command
2. Command responds only to host interface is verified by adding
manual channel number fix from host-ipmid

Change-Id: I6ccd61b6f924cd7337c4c8125fc890cac30aaf48
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 7896786..80e7ad8 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -789,6 +789,53 @@
     return ipmi::response(ipmi::ccCommandNotAvailable);
 }
 
+/** @brief implementes setting password for special user
+ *  @param[in] specialUserIndex
+ *  @param[in] userPassword - new password in 20 bytes
+ *  @returns ipmi completion code.
+ */
+ipmi::RspType<> ipmiOEMSetSpecialUserPassword(ipmi::Context::ptr ctx,
+                                              uint8_t specialUserIndex,
+                                              std::vector<uint8_t> userPassword)
+{
+    ChannelInfo chInfo;
+    try
+    {
+        getChannelInfo(ctx->channel, chInfo);
+    }
+    catch (sdbusplus::exception_t& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmiOEMSetSpecialUserPassword: Failed to get Channel Info",
+            phosphor::logging::entry("MSG: %s", e.description()));
+        return ipmi::responseUnspecifiedError();
+    }
+    if (chInfo.mediumType !=
+        static_cast<uint8_t>(EChannelMediumType::systemInterface))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmiOEMSetSpecialUserPassword: Error - supported only in KCS "
+            "interface");
+        return ipmi::responseCommandNotAvailable();
+    }
+    if (specialUserIndex != 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmiOEMSetSpecialUserPassword: Invalid user account");
+        return ipmi::responseParmOutOfRange();
+    }
+    constexpr uint8_t minPasswordSizeRequired = 6;
+    if (userPassword.size() < minPasswordSizeRequired ||
+        userPassword.size() > ipmi::maxIpmi20PasswordSize)
+    {
+        return ipmi::responseReqDataLenInvalid();
+    }
+    std::string passwd;
+    passwd.assign(reinterpret_cast<const char*>(userPassword.data()),
+                  userPassword.size());
+    return ipmi::response(ipmiSetSpecialUserPassword("root", passwd));
+}
+
 namespace ledAction
 {
 using namespace sdbusplus::xyz::openbmc_project::Led::server;
@@ -1603,6 +1650,12 @@
             IPMINetfnIntelOEMGeneralCmd::cmdSetOEMUser2Activation),
         ipmi::Privilege::Callback, ipmiOEMSetUser2Activation);
 
+    ipmi::registerHandler(
+        ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
+        static_cast<ipmi::Cmd>(
+            IPMINetfnIntelOEMGeneralCmd::cmdSetSpecialUserPassword),
+        ipmi::Privilege::Callback, ipmiOEMSetSpecialUserPassword);
+
     ipmiPrintAndRegister(
         netfnIntcOEMGeneral,
         static_cast<ipmi_cmd_t>(