Implement get payload instance info command

Resolves openbmc/openbmc#2892

Change-Id: Id5f95df64bcdc97646f11d6d3630eead062c4193
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
index 0cc52cc..2215046 100644
--- a/command/payload_cmds.cpp
+++ b/command/payload_cmds.cpp
@@ -189,6 +189,40 @@
     return outPayload;
 }
 
+std::vector<uint8_t> getPayloadInfo(const std::vector<uint8_t>& inPayload,
+                                    const message::Handler& handler)
+{
+    std::vector<uint8_t> outPayload(sizeof(GetPayloadInfoResponse));
+    auto request = reinterpret_cast<const GetPayloadInfoRequest*>
+                   (inPayload.data());
+    auto response = reinterpret_cast<GetPayloadInfoResponse*>
+                    (outPayload.data());
+
+    // SOL is the payload currently supported for payload status & only one
+    // instance of SOL is supported.
+    if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType
+        || request->payloadInstance != 1)
+    {
+        response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+        return outPayload;
+    }
+
+    auto status = std::get<sol::Manager&>(singletonPool).isPayloadActive(
+            request->payloadInstance);
+
+    if (!status)
+    {
+        response->completionCode = IPMI_CC_RESPONSE_ERROR;
+        return outPayload;
+    }
+
+    auto& context = std::get<sol::Manager&>(singletonPool).getContext
+            (request->payloadInstance);
+    response->sessionID = context.sessionID;
+
+    return outPayload;
+}
+
 } // namespace command
 
 } // namespace sol
diff --git a/command/payload_cmds.hpp b/command/payload_cmds.hpp
index 6901256..d751a95 100644
--- a/command/payload_cmds.hpp
+++ b/command/payload_cmds.hpp
@@ -251,6 +251,41 @@
 std::vector<uint8_t> getPayloadStatus(const std::vector<uint8_t>& inPayload,
                                       const message::Handler& handler);
 
+/** @struct GetPayloadInfoRequest
+ *
+ *  IPMI payload for Get Payload Instance info command request.
+ */
+struct GetPayloadInfoRequest
+{
+    uint8_t payloadType;    //!< Payload type
+    uint8_t payloadInstance;//!< Payload instance
+} __attribute__((packed));
+
+/** @struct GetPayloadInfoResponse
+ *
+ *  IPMI payload for Get Payload Instance info command response.
+ */
+struct GetPayloadInfoResponse
+{
+    uint8_t completionCode; //!< Completion code.
+    uint32_t sessionID;     //!< Session ID
+    uint8_t portNumber;     //!< Port number
+    uint8_t reserved[7];    //!< Reserved
+} __attribute__((packed));
+
+/** @brief Get Payload Instance Info Command.
+ *
+ *  This command returns information about a specific instance of a payload
+ *  type. Session ID is returned by this 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> getPayloadInfo(const std::vector<uint8_t>& inPayload,
+                                    const message::Handler& handler);
+
 } // namespace command
 
 } // namespace sol
diff --git a/sol_module.cpp b/sol_module.cpp
index 203ec72..e055817 100644
--- a/sol_module.cpp
+++ b/sol_module.cpp
@@ -44,6 +44,14 @@
             },
             &getPayloadStatus, session::Privilege::USER, false
         },
+        // Get Payload Instance Info Command
+        {
+            {
+                (static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+                static_cast<uint16_t>(::command::NetFns::APP) | 0x4B
+            },
+            &getPayloadInfo, session::Privilege::USER, false
+        },
         // Set SOL Configuration Parameters
         {
             {