Add get channel payload version command

Implement get channel payload version command (IPMI specification
section 24.9). As per the specification, this command is basically a
hard-coded value that says we are using IPMI 2.0.

Tested:
    ipmitool raw 6 0x4F 3 1 // Command
     10                     // Response

Change-Id: Id16723e7257361814b98f3c14d759f2919ad4c03
Signed-off-by: Ayushi Smriti <smriti.ayushi@intel.com>
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
index 961214d..038db34 100644
--- a/host-ipmid-whitelist.conf
+++ b/host-ipmid-whitelist.conf
@@ -27,6 +27,7 @@
 0x06:0x37    //<App>:<Get System GUID>
 0x06:0x42    //<App>:<Get Channel Info Command>
 0x06:0x4E    //<App>:<Get Channel Payload Support>
+0x06:0x4F    //<App>:<Get Channel Payload Version>
 0x06:0x54    //<App>:<Get Channel Cipher Suites>
 0x0A:0x10    //<Storage>:<Get FRU Inventory Area Info>
 0x0A:0x11    //<Storage>:<Read FRU Data>
diff --git a/user_channel/channel_layer.cpp b/user_channel/channel_layer.cpp
index da9c613..122b3ea 100644
--- a/user_channel/channel_layer.cpp
+++ b/user_channel/channel_layer.cpp
@@ -146,4 +146,15 @@
 {
     return getChannelConfigObject().getChannelByName(chName);
 }
+
+bool isValidPayloadType(const PayloadType payloadType)
+{
+    return (
+        payloadType == PayloadType::IPMI || payloadType == PayloadType::SOL ||
+        payloadType == PayloadType::OPEN_SESSION_REQUEST ||
+        payloadType == PayloadType::OPEN_SESSION_RESPONSE ||
+        payloadType == PayloadType::RAKP1 ||
+        payloadType == PayloadType::RAKP2 ||
+        payloadType == PayloadType::RAKP3 || payloadType == PayloadType::RAKP4);
+}
 } // namespace ipmi
diff --git a/user_channel/channel_layer.hpp b/user_channel/channel_layer.hpp
index 6dc9fe2..580c4ee 100644
--- a/user_channel/channel_layer.hpp
+++ b/user_channel/channel_layer.hpp
@@ -375,4 +375,12 @@
  */
 uint8_t getChannelByName(const std::string& chName);
 
+/** @brief determines whether payload type is valid
+ *
+ *	@param[in] payload type - Payload Type
+ *
+ *	@return true if valid, false otherwise
+ */
+bool isValidPayloadType(const PayloadType payloadType);
+
 } // namespace ipmi
diff --git a/user_channel/channelcommands.cpp b/user_channel/channelcommands.cpp
index 2e1b196..9d3b4d2 100644
--- a/user_channel/channelcommands.cpp
+++ b/user_channel/channelcommands.cpp
@@ -344,6 +344,43 @@
                            rspRsvd);
 }
 
+/** @brief implements the get channel payload version command
+ *  @param ctx - IPMI context pointer (for channel)
+ *  @param chNum - channel number to get info about
+ *  @param reserved - skip 4 bits
+ *  @param payloadTypeNum - to get payload type info
+
+ *  @returns IPMI completion code plus response data
+ *   - formatVersion - BCD encoded format version info
+ */
+
+RspType<uint8_t> // formatVersion
+    ipmiGetChannelPayloadVersion(Context::ptr ctx, uint4_t chNum,
+                                 uint4_t reserved, uint8_t payloadTypeNum)
+{
+    uint8_t channel =
+        convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
+
+    if (reserved || !isValidChannel(channel) ||
+        (getChannelSessionSupport(channel)) == EChannelSessSupported::none)
+    {
+        return responseInvalidFieldRequest();
+    }
+
+    if (!isValidPayloadType(static_cast<PayloadType>(payloadTypeNum)))
+    {
+        log<level::ERR>("Channel payload version - Payload type unavailable");
+
+        constexpr uint8_t payloadTypeNotSupported = 0x80;
+        return response(payloadTypeNotSupported);
+    }
+
+    // BCD encoded version representation - 1.0
+    constexpr uint8_t formatVersion = 0x10;
+
+    return responseSuccess(formatVersion);
+}
+
 void registerChannelFunctions() __attribute__((constructor));
 void registerChannelFunctions()
 {
@@ -360,6 +397,9 @@
 
     registerHandler(prioOpenBmcBase, netFnApp, app::cmdGetChannelPayloadSupport,
                     Privilege::User, ipmiGetChannelPayloadSupport);
+
+    registerHandler(prioOpenBmcBase, netFnApp, app::cmdGetChannelPayloadVersion,
+                    Privilege::User, ipmiGetChannelPayloadVersion);
 }
 
 } // namespace ipmi