Add support for Set SOL Configuration parameters command.

Change-Id: I82618bc21c426e37f0110b11aeba9855e588bb6c
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp
index 344b6d8..f18bc8b 100644
--- a/command/sol_cmds.cpp
+++ b/command/sol_cmds.cpp
@@ -68,6 +68,91 @@
                                           outPayload);
 }
 
+std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
+                                   const message::Handler& handler)
+{
+    std::vector<uint8_t> outPayload(sizeof(SetConfParamsResponse));
+    auto request = reinterpret_cast<const SetConfParamsRequest*>
+                   (inPayload.data());
+    auto response = reinterpret_cast<SetConfParamsResponse*>
+                    (outPayload.data());
+    response->completionCode = IPMI_CC_OK;
+
+    switch (static_cast<Parameter>(request->paramSelector))
+    {
+        case Parameter::PROGRESS:
+        {
+            uint8_t progress = request->value & progressMask;
+            std::get<sol::Manager&>(singletonPool).progress = progress;
+            break;
+        }
+        case Parameter::ENABLE:
+        {
+            bool enable = request->value & enableMask;
+            std::get<sol::Manager&>(singletonPool).enable = enable;
+            break;
+        }
+        case Parameter::AUTHENTICATION:
+        {
+            if (!request->auth.auth || !request->auth.encrypt)
+            {
+                response->completionCode = ipmiCCWriteReadParameter;
+            }
+            else if (request->auth.privilege <
+                     static_cast<uint8_t>(session::Privilege::USER) ||
+                     request->auth.privilege >
+                     static_cast<uint8_t>(session::Privilege::OEM))
+            {
+                response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+            }
+            else
+            {
+                std::get<sol::Manager&>(singletonPool).solMinPrivilege =
+                       static_cast<session::Privilege>(request->auth.privilege);
+            }
+            break;
+        }
+        case Parameter::ACCUMULATE:
+        {
+            using namespace std::chrono_literals;
+
+            if (request->acc.threshold == 0)
+            {
+                response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                break;
+            }
+
+            std::get<sol::Manager&>(singletonPool).accumulateInterval =
+                    request->acc.interval * sol::accIntervalFactor * 1ms;
+            std::get<sol::Manager&>(singletonPool).sendThreshold =
+                    request->acc.threshold;
+            break;
+        }
+        case Parameter::RETRY:
+        {
+            using namespace std::chrono_literals;
+
+            std::get<sol::Manager&>(singletonPool).retryCount =
+                    request->retry.count;
+            std::get<sol::Manager&>(singletonPool).retryInterval =
+                    request->retry.interval * sol::retryIntervalFactor * 1ms;
+            break;
+        }
+        case Parameter::PORT:
+        {
+            response->completionCode = ipmiCCWriteReadParameter;
+            break;
+        }
+        case Parameter::NVBITRATE:
+        case Parameter::VBITRATE:
+        case Parameter::CHANNEL:
+        default:
+            response->completionCode = ipmiCCParamNotSupported;
+    }
+
+    return outPayload;
+}
+
 } // namespace command
 
 } // namespace sol
diff --git a/command/sol_cmds.hpp b/command/sol_cmds.hpp
index 2b0a55a..2336f02 100644
--- a/command/sol_cmds.hpp
+++ b/command/sol_cmds.hpp
@@ -61,6 +61,131 @@
  */
 void activating(uint8_t payloadInstance, uint32_t sessionID);
 
+/** @enum Parameter
+ *
+ *  SOL parameters are volatile, they are initialized by the SOL manager.
+ *  They can be read using Get SOL configuration parameters command and updated
+ *  using Set SOL configuration parameters command.
+ */
+enum class Parameter
+{
+    PROGRESS,       //!< Set In Progress.
+    ENABLE,         //!< SOL Enable.
+    AUTHENTICATION, //!< SOL Authentication.
+    ACCUMULATE,     //!< Character Accumulate Interval & Send Threshold.
+    RETRY,          //!< SOL Retry.
+    NVBITRATE,      //!< SOL non-volatile bit rate.
+    VBITRATE,       //!< SOL volatile bit rate.
+    CHANNEL,        //!< SOL payload channel.
+    PORT,           //!< SOL payload port.
+};
+
+constexpr uint8_t progressMask = 0x03;
+constexpr uint8_t enableMask = 0x01;
+
+/** @struct Auth
+ *
+ *  SOL authentication parameter.
+ */
+struct Auth
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t privilege : 4;          //!< SOL privilege level.
+    uint8_t reserved : 2;           //!< Reserved.
+    uint8_t auth : 1;               //!< Force SOL payload Authentication.
+    uint8_t encrypt : 1;            //!< Force SOL payload encryption.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+    uint8_t encrypt : 1;            //!< Force SOL payload encryption.
+    uint8_t auth : 1;               //!< Force SOL payload Authentication.
+    uint8_t reserved : 2;           //!< Reserved.
+    uint8_t privilege : 4;          //!< SOL privilege level.
+#endif
+} __attribute__((packed));
+
+/** @struct Accumulate
+ *
+ *  Character accumulate interval & Character send threshold.
+ */
+struct Accumulate
+{
+    uint8_t interval;               //!< Character accumulate interval.
+    uint8_t threshold;              //!< Character send threshold.
+} __attribute__((packed));
+
+constexpr uint8_t retryCountMask = 0x07;
+
+/** @struct Retry
+ *
+ *  SOL retry count and interval.
+ */
+struct Retry
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t count : 3;              //!< SOL retry count.
+    uint8_t reserved : 5;           //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+    uint8_t reserved : 5;           //!< Reserved.
+    uint8_t count : 3;              //!< SOL retry count.
+#endif
+
+    uint8_t interval;               //!< SOL retry interval.
+} __attribute__((packed));
+
+constexpr uint8_t ipmiCCParamNotSupported = 0x80;
+constexpr uint8_t ipmiCCInvalidSetInProgress = 0x81;
+constexpr uint8_t ipmiCCWriteReadParameter = 0x82;
+constexpr uint8_t ipmiCCReadWriteParameter = 0x83;
+constexpr uint8_t parameterRevision = 0x11;
+
+/** @struct SetConfParamsRequest
+ *
+ *  IPMI payload for Set SOL configuration parameters command request.
+ */
+struct SetConfParamsRequest
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t channelNumber : 4;      //!< Channel number.
+    uint8_t reserved : 4;           //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+    uint8_t reserved : 4;           //!< Reserved.
+    uint8_t channelNumber : 4;      //!< Channel number.
+#endif
+
+    uint8_t paramSelector;          //!< Parameter selector.
+    union
+    {
+        uint8_t value;              //!< Represents one byte SOL parameters.
+        struct Accumulate acc;      //!< Character accumulate values.
+        struct Retry retry;         //!< Retry values.
+        struct Auth auth;           //!< Authentication parameters.
+    };
+} __attribute__((packed));
+
+/** @struct SetConfParamsResponse
+ *
+ *  IPMI payload for Set SOL configuration parameters command response.
+ */
+struct SetConfParamsResponse
+{
+    uint8_t completionCode;          //!< Completion code.
+} __attribute__((packed));
+
+/** @brief Set SOL configuration parameters command.
+ *
+ *  @param[in] inPayload - Request data for the command.
+ *  @param[in] handler - Reference to the message handler.
+ *
+ *  @return Response data for the command.
+ */
+std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
+                                   const message::Handler& handler);
+
 } // namespace command
 
 } // namespace sol