PLDMTOOL : Implement a PLDM requester tool.

Implemented a way for sending PLDM requests for specific PLDM commands.
This tool will interact with MCTP daemon using UNIX domain socket, The
response got from socket will be displayed on the console in raw format.

Tested following PLDM commands:
    1) GetPLDMTypes
    2) GetPLDMVersion

Tested : Verified the RAW response data.

./pldmtool -c GetPLDMTypes
Encoded request succesfully : RC = 0
Request Message:
08 01 9b 00 04 00 00
Success in creating the socket : RC = 3
Success in connecting to socket : RC = 0
Success in sending message type as pldm to mctp : RC = 0
Write to socket successful : RC = 7
Total length:7
Loopback response message:
08 01 9b 00 04 00 00
On first recv(),response == request : RC = 0
Total length: 14
Shutdown Socket successful :  RC = 0
Socket recv() successful : RC = 0
Response Message :
08 01 00 00 04 00 01 00 00 00 00 00 00 00

./pldmtool -c GetPLDMVersion base
PLDM Type requested : base
Encoded request succesfully : RC = 0
Request Message:
08 01 9b 00 03 00 00 00 00 01 00
Success in creating the socket : RC = 3
Success in connecting to socket : RC = 0
Success in sending message type as pldm to mctp : RC = 0
Write to socket successful : RC = 11
Total length:11
Loopback response message:
08 01 9b 00 03 00 00 00 00 01 00
On first recv(),response == request : RC = 0
Total length: 15
Shutdown Socket successful :  RC = 0
Socket recv() successful : RC = 0
Response Message:
08 01 00 00 03 00 00 00 00 00 05 f1 f0 f0 00

./pldmtool -h
PLDM requester tool for OpenBMC
Usage: ./pldmtool [OPTIONS] —command... [GetPLDMTypes] [GetPLDMVersion] SUBCOMMA                                                                             ND

Positionals:
  —command TEXT ... REQUIRED
                              PLDM request command
  GetPLDMTypes TEXT           Get PLDM Type
  GetPLDMVersion TEXT         Get PLDM Version

Options:
  -h,--help                   Print this help message and exit
  -c TEXT ... REQUIRED        PLDM request command

Subcommands:
  BASE                        PLDM Command Type = BASE
  BIOS                        PLDM Command Type = BIOS
  OEM                         PLDM Command Type = OEM

Signed-off-by: Lakshminarayana R. Kammath <lkammath@in.ibm.com>
Change-Id: I758b5f5cf03ad9b91ce47144fe46cd79b41381f3
diff --git a/tool/pldm_base_cmd.cpp b/tool/pldm_base_cmd.cpp
new file mode 100644
index 0000000..aa5b668
--- /dev/null
+++ b/tool/pldm_base_cmd.cpp
@@ -0,0 +1,134 @@
+#include "pldm_base_cmd.hpp"
+
+#include "pldm_cmd_helper.hpp"
+
+#include <string>
+
+constexpr uint8_t PLDM_ENTITY_ID = 8;
+constexpr uint8_t MCTP_MSG_TYPE_PLDM = 1;
+constexpr uint8_t PLDM_LOCAL_INSTANCE_ID = 0;
+
+using namespace std;
+
+/*
+ * Main function that handles the GetPLDMTypes response callback via mctp
+ *
+ */
+void getPLDMTypes(vector<std::string>&& args)
+{
+    // Create and encode the request message
+    vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+                               sizeof(MCTP_MSG_TYPE_PLDM) +
+                               sizeof(PLDM_ENTITY_ID));
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+    // Encode the get_types request message
+    uint8_t instanceId = PLDM_LOCAL_INSTANCE_ID;
+    auto returnCode = encode_get_types_req(instanceId, request);
+    if (returnCode)
+    {
+        cerr << "Failed to encode request msg for GetPLDMType : RC = "
+             << returnCode << endl;
+        return;
+    }
+    cout << "Encoded request succesfully : RC = " << returnCode << endl;
+
+    // Insert the PLDM message type and EID at the begining of the request msg.
+    requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
+    requestMsg.insert(requestMsg.begin(), PLDM_ENTITY_ID);
+
+    cout << "Request Message:" << endl;
+    printBuffer(requestMsg);
+
+    // Create the response message
+    vector<uint8_t> responseMsg;
+
+    // Compares the response with request packet on first socket recv() call.
+    // If above condition is qualified then, reads the actual response from
+    // the socket to output buffer responseMsg.
+    returnCode = mctpSockSendRecv(requestMsg, responseMsg);
+    if (!returnCode)
+    {
+        cout << "Socket recv() successful : RC = " << returnCode << endl;
+        cout << "Response Message : " << endl;
+        printBuffer(responseMsg);
+    }
+    else
+    {
+        cerr << "Failed to recieve from socket : RC = " << returnCode << endl;
+        return;
+    }
+}
+
+/*
+ * Main function that handles the GetPLDMVersion response callback via mctp
+ *
+ */
+void getPLDMVersion(vector<std::string>&& args)
+{
+    // Create a request packet
+    std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+                                    PLDM_GET_VERSION_REQ_BYTES);
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    uint8_t pldmType = 0x0;
+
+    if (!args[1].c_str())
+    {
+        cout << "Mandatory argument PLDM Command Type not provided!" << endl;
+        cout << "Run pldmtool --help for more information" << endl;
+        return;
+    }
+
+    if (!strcasecmp(args[1].c_str(), "base"))
+    {
+        cout << "PLDM Type requested : " << args[1] << endl;
+        pldmType = PLDM_BASE;
+    }
+    else
+    {
+        cerr << "Unsupported pldm command type OR not supported yet : "
+             << args[1] << endl;
+        return;
+    }
+
+    uint8_t instanceId = PLDM_LOCAL_INSTANCE_ID;
+    uint32_t transferHandle = 0x0;
+    transfer_op_flag opFlag = PLDM_GET_FIRSTPART;
+
+    // encode the get_version request
+    auto returnCode = encode_get_version_req(instanceId, transferHandle, opFlag,
+                                             pldmType, request);
+    if (returnCode)
+    {
+        cerr << "Failed to encode request msg for GetPLDMVersion. RC = "
+             << returnCode << endl;
+        return;
+    }
+    cout << "Encoded request succesfully : RC = " << returnCode << endl;
+
+    // Insert the PLDM message type and EID at the begining of the request msg.
+    requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
+    requestMsg.insert(requestMsg.begin(), PLDM_ENTITY_ID);
+
+    cout << "Request Message:" << endl;
+    printBuffer(requestMsg);
+
+    // Create the response message
+    vector<uint8_t> responseMsg;
+
+    // Compares the response with request packet on first socket recv() call.
+    // If above condition is qualified then, reads the actual response from
+    // the socket to output buffer responseMsg.
+    returnCode = mctpSockSendRecv(requestMsg, responseMsg);
+    if (!returnCode)
+    {
+        cout << "Socket recv() successful : RC = " << returnCode << endl;
+        cout << "Response Message:" << endl;
+        printBuffer(responseMsg);
+    }
+    else
+    {
+        cerr << "Failed to recieve from socket : RC = " << returnCode << endl;
+        return;
+    }
+}