PLDMTOOL: Implement raw option in the pldmtool
raw option enables user sending raw bytes and printing response
HELP OUTPUT:
root@witherspoon-128:/tmp# ./pldmtool -h
PLDM requester tool for OpenBMC
Usage: ./pldmtool [OPTIONS] [—command...] [raw] [GetPLDMTypes] [GetPLDMVersion] [SUBCOMMAND]
Positionals:
—command TEXT ... PLDM request command
raw TEXT Send a RAW PLDM request and print response
GetPLDMTypes TEXT Get PLDM Type
GetPLDMVersion TEXT Get PLDM Version
Options:
-h,--help Print this help message and exit
-c TEXT ... PLDM request command
Subcommands:
BASE PLDM Command Type = BASE
BIOS PLDM Command Type = BIOS
OEM PLDM Command Type = OEM
Currently option to be given as raw instead of --raw because
of bug in the CLI11 :
FIX: required positional arguments and a vector positionals #306
pldm_set_state_effecter_states:
root@witherspoon-128:/tmp# ./pldmtool raw 0x80 0x02 0x39 0x00 0x01 0x00 0x01 0x09
Request Message
08 01 80 02 39 00 01 00 01 09
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 = 10
Total length:10
Loopback response message:
08 01 80 02 39 00 01 00 01 09
On first recv(),response == request : RC = 0
Total length: 6
Shutdown Socket successful : RC = 0
Socket recv() successful : RC = 0
Response Message:
08 01 00 02 39 00
GetPLDMVersion:
./pldmtool raw 0x80 0x00 0x03 0x00 0x00 0x00 0x00 0x01 0x00
Request Message
08 01 80 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 80 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
Signed-off-by: Lakshminarayana R. Kammath <lkammath@in.ibm.com>
Change-Id: I4057108444db8f8809f4310e1ffbb0565adbbf3c
diff --git a/tool/handler.hpp b/tool/handler.hpp
index 4ee7fe8..086c132 100644
--- a/tool/handler.hpp
+++ b/tool/handler.hpp
@@ -16,5 +16,7 @@
{"GetPLDMTypes",
[](Args&& args) { return getPLDMTypes(std::move(args)); }},
{"GetPLDMVersion",
- [](Args&& args) { return getPLDMVersion(std::move(args)); }}};
+ [](Args&& args) { return getPLDMVersion(std::move(args)); }},
+ {"HandleRawOp",
+ [](Args&& args) { return handleRawOp(std::move(args)); }}};
};
diff --git a/tool/pldm_base_cmd.cpp b/tool/pldm_base_cmd.cpp
index 3ebd123..b203423 100644
--- a/tool/pldm_base_cmd.cpp
+++ b/tool/pldm_base_cmd.cpp
@@ -70,6 +70,7 @@
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())
@@ -132,3 +133,112 @@
return;
}
}
+
+/*
+ * Main function that handles the PLDM raw command response callback via mctp
+ *
+ */
+void handleRawOp(vector<std::string>&& args)
+{
+ // Minimu 3 bytes of header data needs to passed. else its a invalid request
+ if (size(args) < 3)
+ {
+ cerr << "Not enough arguments passed."
+ " Minimum, need to pass PLDM header raw data"
+ << endl;
+ return;
+ }
+
+ // Create a request packet and initialize it
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
+ requestMsg.clear();
+
+ // Read the raw data passed in the command line
+ // Form request message from the raw data passed
+ for (auto&& rawByte : args)
+ {
+ requestMsg.insert(requestMsg.end(), stoi(rawByte, nullptr, 16));
+ }
+
+ // Validating the payload raw data based on pldm command type
+ uint8_t pldmCmd = requestMsg[2];
+ switch (pldmCmd)
+ {
+ case PLDM_GET_PLDM_VERSION:
+ if (size(requestMsg) !=
+ (sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES))
+ {
+ cerr << "Not enough raw data provided." << endl;
+ cerr << "Total length can be = 3 bytes of header + 6 bytes"
+ " for payload. Please refer spec for details"
+ << endl;
+ return;
+ }
+ break;
+ case PLDM_GET_TID:
+ case PLDM_GET_PLDM_TYPES:
+ if (size(requestMsg) != sizeof(pldm_msg_hdr))
+ {
+ cerr << "Total length can be = 3 bytes of header + 0 bytes"
+ " for payload. Please refer spec for details"
+ << endl;
+ return;
+ }
+ break;
+ case PLDM_GET_PLDM_COMMANDS:
+ if (size(requestMsg) !=
+ sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES)
+ {
+ cerr << "Total length can be = 3 bytes of header + 5 bytes"
+ " for payload. Please refer spec for details"
+ << endl;
+ return;
+ }
+ break;
+ case PLDM_SET_STATE_EFFECTER_STATES:
+ // payload size depends on comp_effecter_count
+ // if count=1 then, request size will be 8 bytes including header
+ // if count=9 then, request size will be 19 bytes including header
+ if ((size(requestMsg) < 8) ||
+ (size(requestMsg) >
+ sizeof(pldm_msg_hdr) +
+ PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES))
+ {
+ cerr << "Total length can be = 3 bytes of header + min/max 8/19"
+ " bytes for payload. Please refer spec for details"
+ << endl;
+ return;
+ }
+ break;
+ default:
+ cerr << "Command Not supported/implemented : " << args[2] << endl;
+ cerr << "Contact backend Team" << endl;
+ return;
+ }
+
+ // Add the MCTP type and PLDM entity id at the end
+ 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.
+ int 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;
+ }
+}
diff --git a/tool/pldm_base_cmd.hpp b/tool/pldm_base_cmd.hpp
index fefdcd1..d709ede 100644
--- a/tool/pldm_base_cmd.hpp
+++ b/tool/pldm_base_cmd.hpp
@@ -24,4 +24,14 @@
*/
void getPLDMVersion(std::vector<std::string>&& args);
+/** @brief Handler for Raw PLDM commands
+ *
+ *
+ * @param[in] args - Argument to be passed to the handler
+ * e.g : PLDM raw commands.
+ *
+ * @return - None
+ */
+void handleRawOp(std::vector<std::string>&& args);
+
#endif /* PLDM_BASE_CMD_H */
diff --git a/tool/pldm_cmd_helper.hpp b/tool/pldm_cmd_helper.hpp
index 6a4f087..8032c9a 100644
--- a/tool/pldm_cmd_helper.hpp
+++ b/tool/pldm_cmd_helper.hpp
@@ -15,6 +15,7 @@
#include <iostream>
#include "libpldm/base.h"
+#include "libpldm/platform.h"
using namespace pldm::responder::utils;
diff --git a/tool/pldmtool.cpp b/tool/pldmtool.cpp
index 6956845..c3e2186 100644
--- a/tool/pldmtool.cpp
+++ b/tool/pldmtool.cpp
@@ -11,24 +11,71 @@
// bool verbose_flag = false;
// app.add_flag("-v, --verbose", verbose_flag, "Output debug logs ");
std::vector<std::string> args{};
- app.add_option("-c, —command", args, "PLDM request command")->required();
+ app.add_option("-c, —command", args, " PLDM request command");
+
+ std::string rawCmd;
+ app.add_option("raw", rawCmd, "Send a RAW PLDM request and print response");
std::string pldmCmdName;
app.add_option("GetPLDMTypes", pldmCmdName, "Get PLDM Type");
app.add_option("GetPLDMVersion", pldmCmdName, "Get PLDM Version");
- app.add_subcommand("base", "PLDM Command Type = base");
- app.add_subcommand("bios", "PLDM Command Type = bios");
- app.add_subcommand("oem", "PLDM Command Type = oem");
+ app.add_subcommand("BASE", "PLDM Command Type = BASE");
+ app.add_subcommand("BIOS", "PLDM Command Type = BIOS");
+ app.add_subcommand("OEM", "PLDM Command Type = OEM");
CLI11_PARSE(app, argc, argv);
- Handler handler;
-
- // Parse args to program
- std::string cmdName = args[0];
+ std::string cmdName;
int rc = 0;
+ if (args[0] != "raw")
+ {
+ // Parse args to program
+ cmdName = args[0];
+ }
+ else
+ {
+ // removing 'raw' from the args list since it is positional argument
+ // and not an input value.
+ args.erase(args.begin());
+
+ // loop through the remaining argument list
+ for (auto&& item : args)
+ {
+
+ if (item[0] == '0' && (item[1] == 'x' || item[1] == 'X'))
+ {
+
+ // Erase 0x from input
+ item.erase(0, 2);
+
+ // Check for hex input value validity
+ if (std::all_of(item.begin(), item.end(), ::isxdigit))
+ {
+
+ // Parse args to program
+ cmdName = "HandleRawOp";
+ }
+ else
+ {
+ std::cerr << item << " contains non hex digits. Re-enter"
+ << std::endl;
+ rc = -1;
+ return rc;
+ }
+ }
+ else
+ {
+ std::cout << item << " Input hex value starting with 0x "
+ << std::endl;
+ rc = -1;
+ return rc;
+ }
+ }
+ }
+
+ Handler handler;
try
{
handler.dispatcher.at(cmdName)(std::move(args));
@@ -38,5 +85,5 @@
std::cerr << cmdName << " is not supported!" << std::endl;
rc = -1;
}
- return (rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+ return rc;
}