Rename tool/ as pldmtool/
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: I38d7a6ab907014cd5fca049b095d692d069feab1
diff --git a/pldmtool/meson.build b/pldmtool/meson.build
new file mode 100644
index 0000000..48f4c26
--- /dev/null
+++ b/pldmtool/meson.build
@@ -0,0 +1,25 @@
+libpldm_headers = ['.', './oem/ibm']
+
+sources = [
+ 'pldm_cmd_helper.cpp',
+ 'pldm_base_cmd.cpp',
+ 'pldm_platform_cmd.cpp',
+ 'pldm_bios_cmd.cpp',
+ 'pldm_fru_cmd.cpp',
+ 'pldmtool.cpp',
+]
+
+if get_option('oem-ibm').enabled()
+sources += [
+ 'oem/ibm/pldm_host_cmd.cpp'
+ ]
+endif
+
+executable(
+ 'pldmtool',
+ sources,
+ implicit_include_directories: false,
+ include_directories: include_directories(libpldm_headers),
+ dependencies: [libpldm, libpldmutils, dependency('sdbusplus')],
+ install: true,
+ install_dir: get_option('bindir'))
diff --git a/pldmtool/oem/ibm/pldm_host_cmd.cpp b/pldmtool/oem/ibm/pldm_host_cmd.cpp
new file mode 100644
index 0000000..4f14e8c
--- /dev/null
+++ b/pldmtool/oem/ibm/pldm_host_cmd.cpp
@@ -0,0 +1,87 @@
+#include "pldm_host_cmd.hpp"
+
+#include "oem/ibm/libpldm/host.h"
+
+#include "../../pldm_cmd_helper.hpp"
+
+namespace pldmtool
+{
+
+namespace oem_ibm
+{
+namespace power_host
+{
+using namespace pldmtool::helper;
+
+std::vector<std::unique_ptr<CommandInterface>> commands;
+
+class GetAlertStatus : public CommandInterface
+{
+ public:
+ ~GetAlertStatus() = default;
+ GetAlertStatus() = delete;
+ GetAlertStatus(const GetAlertStatus&) = delete;
+ GetAlertStatus(GetAlertStatus&&) = default;
+ GetAlertStatus& operator=(const GetAlertStatus&) = delete;
+ GetAlertStatus& operator=(GetAlertStatus&&) = default;
+
+ explicit GetAlertStatus(const char* type, const char* name, CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option(
+ "-i, --id", versionId,
+ "Version of the command/response format. 0x00 for this format")
+ ->required();
+ }
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_ALERT_STATUS_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_alert_status_req(instanceId, versionId, request,
+ PLDM_GET_ALERT_STATUS_REQ_BYTES);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t completionCode = 0;
+ uint32_t rack_entry = 0;
+ uint32_t pri_cec_node = 0;
+ auto rc = decode_get_alert_status_resp(responsePtr, payloadLength,
+ &completionCode, &rack_entry,
+ &pri_cec_node);
+
+ if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
+ return;
+ }
+
+ std::cout << "GetAlertStatus Success: " << std::endl;
+ std::cout << "rack entry: 0x" << std::setfill('0') << std::setw(8)
+ << std::hex << (int)rack_entry << std::endl;
+ std::cout << "pri cec node: 0x" << std::setfill('0') << std::setw(8)
+ << std::hex << (int)pri_cec_node << std::endl;
+ }
+
+ private:
+ uint8_t versionId;
+};
+
+void registerCommand(CLI::App& app)
+{
+ auto oem_ibm = app.add_subcommand("oem-ibm", "oem type command");
+ oem_ibm->require_subcommand(1);
+
+ auto getAlertStatus = oem_ibm->add_subcommand(
+ "GetAlertStatus", "get alert status descriptor");
+ commands.push_back(std::make_unique<GetAlertStatus>(
+ "oem_ibm", "getAlertStatus", getAlertStatus));
+}
+} // namespace power_host
+} // namespace oem_ibm
+} // namespace pldmtool
diff --git a/pldmtool/oem/ibm/pldm_host_cmd.hpp b/pldmtool/oem/ibm/pldm_host_cmd.hpp
new file mode 100644
index 0000000..d57ccd4
--- /dev/null
+++ b/pldmtool/oem/ibm/pldm_host_cmd.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <CLI/CLI.hpp>
+
+namespace pldmtool
+{
+
+namespace oem_ibm
+{
+namespace power_host
+{
+
+void registerCommand(CLI::App& app);
+
+}
+
+} // namespace oem_ibm
+
+} // namespace pldmtool
diff --git a/pldmtool/pldm_base_cmd.cpp b/pldmtool/pldm_base_cmd.cpp
new file mode 100644
index 0000000..8079850
--- /dev/null
+++ b/pldmtool/pldm_base_cmd.cpp
@@ -0,0 +1,356 @@
+#include "pldm_base_cmd.hpp"
+
+#include "libpldm/utils.h"
+
+#include "pldm_cmd_helper.hpp"
+
+#ifdef OEM_IBM
+#include "libpldm/file_io.h"
+#include "libpldm/host.h"
+#endif
+
+namespace pldmtool
+{
+
+namespace base
+{
+
+namespace
+{
+
+using namespace pldmtool::helper;
+
+std::vector<std::unique_ptr<CommandInterface>> commands;
+const std::map<const char*, pldm_supported_types> pldmTypes{
+ {"base", PLDM_BASE}, {"platform", PLDM_PLATFORM},
+ {"bios", PLDM_BIOS}, {"fru", PLDM_FRU},
+#ifdef OEM_IBM
+ {"oem-ibm", PLDM_OEM},
+#endif
+};
+
+const std::map<const char*, pldm_supported_commands> pldmBaseCmds{
+ {"GetTID", PLDM_GET_TID},
+ {"GetPLDMVersion", PLDM_GET_PLDM_VERSION},
+ {"GetPLDMTypes", PLDM_GET_PLDM_TYPES},
+ {"GetPLDMCommands", PLDM_GET_PLDM_COMMANDS}};
+
+const std::map<const char*, pldm_bios_commands> pldmBiosCmds{
+ {"GetBIOSTable", PLDM_GET_BIOS_TABLE},
+ {"SetBIOSAttributeCurrentValue", PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE},
+ {"GetBIOSAttributeCurrentValueByHandle",
+ PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE},
+ {"GetDateTime", PLDM_GET_DATE_TIME},
+ {"SetDateTime", PLDM_SET_DATE_TIME}};
+
+const std::map<const char*, pldm_platform_commands> pldmPlatformCmds{
+ {"SetNumericEffecterValue", PLDM_SET_NUMERIC_EFFECTER_VALUE},
+ {"SetStateEffecterStates", PLDM_SET_STATE_EFFECTER_STATES},
+ {"GetPDR", PLDM_GET_PDR}};
+
+const std::map<const char*, pldm_fru_commands> pldmFruCmds{
+ {"GetFRURecordTableMetadata", PLDM_GET_FRU_RECORD_TABLE_METADATA},
+ {"GetFRURecordTable", PLDM_GET_FRU_RECORD_TABLE}};
+
+#ifdef OEM_IBM
+const std::map<const char*, pldm_host_commands> pldmIBMHostCmds{
+ {"GetAlertStatus", PLDM_HOST_GET_ALERT_STATUS}};
+
+const std::map<const char*, pldm_fileio_commands> pldmIBMFileIOCmds{
+ {"GetFileTable", PLDM_GET_FILE_TABLE},
+ {"ReadFile", PLDM_READ_FILE},
+ {"WriteFile", PLDM_WRITE_FILE},
+ {"ReadFileInToMemory", PLDM_READ_FILE_INTO_MEMORY},
+ {"WriteFileFromMemory", PLDM_WRITE_FILE_FROM_MEMORY},
+ {"ReadFileByTypeIntoMemory", PLDM_READ_FILE_BY_TYPE_INTO_MEMORY},
+ {"WriteFileByTypeFromMemory", PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY},
+ {"NewFileAvailable", PLDM_NEW_FILE_AVAILABLE},
+ {"ReadFileByType", PLDM_READ_FILE_BY_TYPE},
+ {"WriteFileByType", PLDM_WRITE_FILE_BY_TYPE},
+ {"FileAck", PLDM_FILE_ACK}};
+#endif
+
+} // namespace
+
+class GetPLDMTypes : public CommandInterface
+{
+ public:
+ ~GetPLDMTypes() = default;
+ GetPLDMTypes() = delete;
+ GetPLDMTypes(const GetPLDMTypes&) = delete;
+ GetPLDMTypes(GetPLDMTypes&&) = default;
+ GetPLDMTypes& operator=(const GetPLDMTypes&) = delete;
+ GetPLDMTypes& operator=(GetPLDMTypes&&) = default;
+
+ using CommandInterface::CommandInterface;
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = encode_get_types_req(instanceId, request);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t cc = 0;
+ std::vector<bitfield8_t> types(8);
+ auto rc = decode_get_types_resp(responsePtr, payloadLength, &cc,
+ types.data());
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << "\n";
+ return;
+ }
+
+ printPldmTypes(types);
+ }
+
+ private:
+ void printPldmTypes(std::vector<bitfield8_t>& types)
+ {
+ std::cout << "Supported types:";
+ for (int i = 0; i < PLDM_MAX_TYPES; i++)
+ {
+ bitfield8_t b = types[i / 8];
+ if (b.byte & (1 << i % 8))
+ {
+ std::cout << " " << i;
+ auto it = std::find_if(
+ pldmTypes.begin(), pldmTypes.end(),
+ [i](const auto& typePair) { return typePair.second == i; });
+ if (it != pldmTypes.end())
+ {
+
+ std::cout << "(" << it->first << ")";
+ }
+ }
+ }
+
+ std::cout << std::endl;
+ }
+};
+
+class GetPLDMVersion : public CommandInterface
+{
+ public:
+ ~GetPLDMVersion() = default;
+ GetPLDMVersion() = delete;
+ GetPLDMVersion(const GetPLDMVersion&) = delete;
+ GetPLDMVersion(GetPLDMVersion&&) = default;
+ GetPLDMVersion& operator=(const GetPLDMVersion&) = delete;
+ GetPLDMVersion& operator=(GetPLDMVersion&&) = default;
+
+ explicit GetPLDMVersion(const char* type, const char* name, CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option("-t,--type", pldmType, "pldm supported type")
+ ->required()
+ ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case));
+ }
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_VERSION_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
+ pldmType, request);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t cc = 0, transferFlag = 0;
+ uint32_t transferHandle = 0;
+ ver32_t version;
+ auto rc =
+ decode_get_version_resp(responsePtr, payloadLength, &cc,
+ &transferHandle, &transferFlag, &version);
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << "\n";
+ return;
+ }
+ char buffer[16] = {0};
+ ver2str(&version, buffer, sizeof(buffer));
+ std::cout << "Type " << pldmType;
+ auto it = std::find_if(
+ pldmTypes.begin(), pldmTypes.end(),
+ [&](const auto& typePair) { return typePair.second == pldmType; });
+
+ if (it != pldmTypes.end())
+ {
+ std::cout << "(" << it->first << ")";
+ }
+ std::cout << ": " << buffer << std::endl;
+ }
+
+ private:
+ pldm_supported_types pldmType;
+};
+
+class GetTID : public CommandInterface
+{
+ public:
+ ~GetTID() = default;
+ GetTID() = delete;
+ GetTID(const GetTID&) = delete;
+ GetTID(GetTID&&) = default;
+ GetTID& operator=(const GetTID&) = delete;
+ GetTID& operator=(GetTID&&) = default;
+
+ using CommandInterface::CommandInterface;
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = encode_get_tid_req(instanceId, request);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t cc = 0;
+ uint8_t tid = 0;
+ std::vector<bitfield8_t> types(8);
+ auto rc = decode_get_tid_resp(responsePtr, payloadLength, &cc, &tid);
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << "\n";
+ return;
+ }
+ std::cout << "TID : " << static_cast<uint32_t>(tid) << std::endl;
+ }
+};
+
+class GetPLDMCommands : public CommandInterface
+{
+ public:
+ ~GetPLDMCommands() = default;
+ GetPLDMCommands() = delete;
+ GetPLDMCommands(const GetPLDMCommands&) = delete;
+ GetPLDMCommands(GetPLDMCommands&&) = default;
+ GetPLDMCommands& operator=(const GetPLDMCommands&) = delete;
+ GetPLDMCommands& operator=(GetPLDMCommands&&) = default;
+
+ explicit GetPLDMCommands(const char* type, const char* name,
+ CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option("-t,--type", pldmType, "pldm supported type")
+ ->required()
+ ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case));
+ }
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_COMMANDS_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
+ auto rc =
+ encode_get_commands_req(instanceId, pldmType, version, request);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t cc = 0;
+ std::vector<bitfield8_t> cmdTypes(32);
+ auto rc = decode_get_commands_resp(responsePtr, payloadLength, &cc,
+ cmdTypes.data());
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << "\n";
+ return;
+ }
+ printPldmCommands(cmdTypes, pldmType);
+ }
+
+ private:
+ pldm_supported_types pldmType;
+
+ template <typename CommandMap>
+ void printCommand(CommandMap& commandMap, int i)
+ {
+ auto it = std::find_if(
+ commandMap.begin(), commandMap.end(),
+ [i](const auto& typePair) { return typePair.second == i; });
+ if (it != commandMap.end())
+ {
+ std::cout << "(" << it->first << ")";
+ }
+ }
+
+ void printPldmCommands(std::vector<bitfield8_t>& cmdTypes,
+ pldm_supported_types pldmType)
+ {
+ std::cout << "Supported Commands :";
+ for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++)
+ {
+ bitfield8_t b = cmdTypes[i / 8];
+ if (b.byte & (1 << i % 8))
+ {
+ std::cout << " " << i;
+ switch (pldmType)
+ {
+ case PLDM_BASE:
+ printCommand(pldmBaseCmds, i);
+ break;
+ case PLDM_PLATFORM:
+ printCommand(pldmPlatformCmds, i);
+ break;
+ case PLDM_BIOS:
+ printCommand(pldmBiosCmds, i);
+ break;
+ case PLDM_FRU:
+ printCommand(pldmFruCmds, i);
+ break;
+ case PLDM_OEM:
+#ifdef OEM_IBM
+ printCommand(pldmIBMHostCmds, i);
+ printCommand(pldmIBMFileIOCmds, i);
+#endif
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ std::cout << std::endl;
+ }
+};
+
+void registerCommand(CLI::App& app)
+{
+ auto base = app.add_subcommand("base", "base type command");
+ base->require_subcommand(1);
+
+ auto getPLDMTypes =
+ base->add_subcommand("GetPLDMTypes", "get pldm supported types");
+ commands.push_back(
+ std::make_unique<GetPLDMTypes>("base", "GetPLDMTypes", getPLDMTypes));
+
+ auto getPLDMVersion =
+ base->add_subcommand("GetPLDMVersion", "get version of a certain type");
+ commands.push_back(std::make_unique<GetPLDMVersion>(
+ "base", "GetPLDMVersion", getPLDMVersion));
+
+ auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)");
+ commands.push_back(std::make_unique<GetTID>("base", "GetTID", getPLDMTID));
+
+ auto getPLDMCommands = base->add_subcommand(
+ "GetPLDMCommands", "get supported commands of pldm type");
+ commands.push_back(std::make_unique<GetPLDMCommands>(
+ "base", "GetPLDMCommands", getPLDMCommands));
+}
+
+} // namespace base
+} // namespace pldmtool
diff --git a/pldmtool/pldm_base_cmd.hpp b/pldmtool/pldm_base_cmd.hpp
new file mode 100644
index 0000000..2e8056d
--- /dev/null
+++ b/pldmtool/pldm_base_cmd.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <CLI/CLI.hpp>
+
+namespace pldmtool
+{
+
+namespace base
+{
+
+void registerCommand(CLI::App& app);
+}
+
+} // namespace pldmtool
diff --git a/pldmtool/pldm_bios_cmd.cpp b/pldmtool/pldm_bios_cmd.cpp
new file mode 100644
index 0000000..ba40dea
--- /dev/null
+++ b/pldmtool/pldm_bios_cmd.cpp
@@ -0,0 +1,949 @@
+#include "pldm_bios_cmd.hpp"
+
+#include "libpldm/bios_table.h"
+#include "libpldm/utils.h"
+
+#include "common/bios_utils.hpp"
+#include "common/utils.hpp"
+#include "pldm_cmd_helper.hpp"
+
+#include <map>
+#include <optional>
+
+namespace pldmtool
+{
+
+namespace bios
+{
+
+namespace
+{
+
+using namespace pldmtool::helper;
+using namespace pldm::bios::utils;
+
+std::vector<std::unique_ptr<CommandInterface>> commands;
+
+const std::map<const char*, pldm_bios_table_types> pldmBIOSTableTypes{
+ {"StringTable", PLDM_BIOS_STRING_TABLE},
+ {"AttributeTable", PLDM_BIOS_ATTR_TABLE},
+ {"AttributeValueTable", PLDM_BIOS_ATTR_VAL_TABLE},
+};
+
+} // namespace
+
+class GetDateTime : public CommandInterface
+{
+ public:
+ ~GetDateTime() = default;
+ GetDateTime() = delete;
+ GetDateTime(const GetDateTime&) = delete;
+ GetDateTime(GetDateTime&&) = default;
+ GetDateTime& operator=(const GetDateTime&) = delete;
+ GetDateTime& operator=(GetDateTime&&) = default;
+
+ using CommandInterface::CommandInterface;
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_date_time_req(instanceId, request);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t cc = 0;
+
+ uint8_t seconds, minutes, hours, day, month;
+ uint16_t year;
+ auto rc =
+ decode_get_date_time_resp(responsePtr, payloadLength, &cc, &seconds,
+ &minutes, &hours, &day, &month, &year);
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << std::endl;
+ return;
+ }
+ std::cout << "Date & Time : " << std::endl;
+ std::cout << "YYYY-MM-DD HH:MM:SS - ";
+ std::cout << bcd2dec16(year);
+ std::cout << "-";
+ setWidth(month);
+ std::cout << "-";
+ setWidth(day);
+ std::cout << " ";
+ setWidth(hours);
+ std::cout << ":";
+ setWidth(minutes);
+ std::cout << ":";
+ setWidth(seconds);
+ std::cout << std::endl;
+ }
+
+ private:
+ void setWidth(uint8_t data)
+ {
+ std::cout << std::setfill('0') << std::setw(2)
+ << static_cast<uint32_t>(bcd2dec8(data));
+ }
+};
+
+class SetDateTime : public CommandInterface
+{
+ public:
+ ~SetDateTime() = default;
+ SetDateTime() = delete;
+ SetDateTime(const SetDateTime&) = delete;
+ SetDateTime(SetDateTime&&) = default;
+ SetDateTime& operator=(const SetDateTime&) = delete;
+ SetDateTime& operator=(SetDateTime&&) = default;
+
+ explicit SetDateTime(const char* type, const char* name, CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option("-d,--data", tmData,
+ "set date time data\n"
+ "eg: YYYYMMDDHHMMSS")
+ ->required();
+ }
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+ sizeof(struct pldm_set_date_time_req));
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ uint16_t year = 0;
+ uint8_t month = 0;
+ uint8_t day = 0;
+ uint8_t hours = 0;
+ uint8_t minutes = 0;
+ uint8_t seconds = 0;
+
+ if (!uintToDate(tmData, &year, &month, &day, &hours, &minutes,
+ &seconds))
+ {
+ std::cerr << "decode date Error: "
+ << "tmData=" << tmData << std::endl;
+
+ return {PLDM_ERROR_INVALID_DATA, requestMsg};
+ }
+
+ auto rc = encode_set_date_time_req(
+ instanceId, seconds, minutes, hours, day, month, year, request,
+ sizeof(struct pldm_set_date_time_req));
+
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t completionCode = 0;
+ auto rc = decode_set_date_time_resp(responsePtr, payloadLength,
+ &completionCode);
+
+ if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)completionCode
+ << std::endl;
+ return;
+ }
+
+ std::cout << "SetDateTime: SUCCESS" << std::endl;
+ }
+
+ private:
+ uint64_t tmData;
+};
+
+class GetBIOSTableHandler : public CommandInterface
+{
+ public:
+ ~GetBIOSTableHandler() = default;
+ GetBIOSTableHandler() = delete;
+ GetBIOSTableHandler(const GetBIOSTableHandler&) = delete;
+ GetBIOSTableHandler(GetBIOSTableHandler&&) = delete;
+ GetBIOSTableHandler& operator=(const GetBIOSTableHandler&) = delete;
+ GetBIOSTableHandler& operator=(GetBIOSTableHandler&&) = delete;
+
+ using Table = std::vector<uint8_t>;
+
+ using CommandInterface::CommandInterface;
+
+ static inline const std::map<pldm_bios_attribute_type, const char*>
+ attrTypeMap = {
+ {PLDM_BIOS_ENUMERATION, "BIOSEnumeration"},
+ {PLDM_BIOS_ENUMERATION_READ_ONLY, "BIOSEnumerationReadOnly"},
+ {PLDM_BIOS_STRING, "BIOSString"},
+ {PLDM_BIOS_STRING_READ_ONLY, "BIOSStringReadOnly"},
+ {PLDM_BIOS_PASSWORD, "BIOSPassword"},
+ {PLDM_BIOS_PASSWORD_READ_ONLY, "BIOSPasswordReadOnly"},
+ {PLDM_BIOS_INTEGER, "BIOSInteger"},
+ {PLDM_BIOS_INTEGER_READ_ONLY, "BIOSIntegerReadOnly"},
+
+ };
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ return {PLDM_ERROR, {}};
+ }
+
+ void parseResponseMsg(pldm_msg*, size_t) override
+ {}
+
+ std::optional<Table> getBIOSTable(pldm_bios_table_types tableType)
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_BIOS_TABLE_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_bios_table_req(instanceId, 0, PLDM_GET_FIRSTPART,
+ tableType, request);
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "Encode GetBIOSTable Error, tableType=," << tableType
+ << " ,rc=" << rc << std::endl;
+ return std::nullopt;
+ }
+ std::vector<uint8_t> responseMsg;
+ rc = pldmSendRecv(requestMsg, responseMsg);
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl;
+ return std::nullopt;
+ }
+
+ uint8_t cc = 0, transferFlag = 0;
+ uint32_t nextTransferHandle = 0;
+ size_t bios_table_offset;
+ auto responsePtr =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr);
+
+ rc = decode_get_bios_table_resp(responsePtr, payloadLength, &cc,
+ &nextTransferHandle, &transferFlag,
+ &bios_table_offset);
+
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "GetBIOSTable Response Error: tableType=" << tableType
+ << ", rc=" << rc << ", cc=" << (int)cc << std::endl;
+ return std::nullopt;
+ }
+ auto tableData =
+ reinterpret_cast<char*>((responsePtr->payload) + bios_table_offset);
+ auto tableSize = payloadLength - sizeof(nextTransferHandle) -
+ sizeof(transferFlag) - sizeof(cc);
+ return std::make_optional<Table>(tableData, tableData + tableSize);
+ }
+
+ const pldm_bios_attr_table_entry*
+ findAttrEntryByName(const std::string& name, const Table& attrTable,
+ const Table& stringTable)
+ {
+ auto stringEntry = pldm_bios_table_string_find_by_string(
+ stringTable.data(), stringTable.size(), name.c_str());
+ if (stringEntry == nullptr)
+ {
+ return nullptr;
+ }
+
+ auto nameHandle =
+ pldm_bios_table_string_entry_decode_handle(stringEntry);
+
+ for (auto attr : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable.data(),
+ attrTable.size()))
+ {
+ auto attrNameHandle =
+ pldm_bios_table_attr_entry_decode_string_handle(attr);
+ if (attrNameHandle == nameHandle)
+ {
+ return attr;
+ }
+ }
+ return nullptr;
+ }
+
+ std::optional<uint16_t> findAttrHandleByName(const std::string& name,
+ const Table& attrTable,
+ const Table& stringTable)
+ {
+ auto attribute = findAttrEntryByName(name, attrTable, stringTable);
+ if (attribute == nullptr)
+ {
+ return std::nullopt;
+ }
+
+ return pldm_bios_table_attr_entry_decode_attribute_handle(attribute);
+ }
+
+ std::string decodeStringFromStringEntry(
+ const pldm_bios_string_table_entry* stringEntry)
+ {
+ auto strLength =
+ pldm_bios_table_string_entry_decode_string_length(stringEntry);
+ std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
+ pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
+ buffer.size());
+
+ return std::string(buffer.data(), buffer.data() + strLength);
+ }
+
+ std::string displayStringHandle(uint16_t handle,
+ const std::optional<Table>& stringTable,
+ bool displayHandle = true)
+ {
+ std::string displayString = std::to_string(handle);
+ if (!stringTable)
+ {
+ return displayString;
+ }
+ auto stringEntry = pldm_bios_table_string_find_by_handle(
+ stringTable->data(), stringTable->size(), handle);
+ if (stringEntry == nullptr)
+ {
+ return displayString;
+ }
+
+ auto decodedStr = decodeStringFromStringEntry(stringEntry);
+ if (!displayHandle)
+ {
+ return decodedStr;
+ }
+
+ return displayString + "(" + decodedStr + ")";
+ }
+
+ std::string displayEnumValueByIndex(uint16_t attrHandle, uint8_t index,
+ const std::optional<Table>& attrTable,
+ const std::optional<Table>& stringTable)
+ {
+ std::string displayString;
+ if (!attrTable)
+ {
+ return displayString;
+ }
+
+ auto attrEntry = pldm_bios_table_attr_find_by_handle(
+ attrTable->data(), attrTable->size(), attrHandle);
+ if (attrEntry == nullptr)
+ {
+ return displayString;
+ }
+ auto pvNum = pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry);
+ std::vector<uint16_t> pvHandls(pvNum);
+ pldm_bios_table_attr_entry_enum_decode_pv_hdls(
+ attrEntry, pvHandls.data(), pvHandls.size());
+ return displayStringHandle(pvHandls[index], stringTable, false);
+ }
+
+ void displayAttributeValueEntry(
+ const pldm_bios_attr_val_table_entry* tableEntry,
+ const std::optional<Table>& attrTable,
+ const std::optional<Table>& stringTable, bool verbose)
+ {
+ auto attrHandle =
+ pldm_bios_table_attr_value_entry_decode_attribute_handle(
+ tableEntry);
+ auto attrType = static_cast<pldm_bios_attribute_type>(
+ pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
+ if (verbose)
+ {
+ std::cout << "AttributeHandle: " << attrHandle << std::endl;
+ std::cout << "\tAttributeType: " << attrTypeMap.at(attrType)
+ << std::endl;
+ }
+ switch (attrType)
+ {
+ case PLDM_BIOS_ENUMERATION:
+ case PLDM_BIOS_ENUMERATION_READ_ONLY:
+ {
+ auto count =
+ pldm_bios_table_attr_value_entry_enum_decode_number(
+ tableEntry);
+ std::vector<uint8_t> handles(count);
+ pldm_bios_table_attr_value_entry_enum_decode_handles(
+ tableEntry, handles.data(), handles.size());
+ if (verbose)
+ {
+ std::cout << "\tNumberOfCurrentValues: " << (int)count
+ << std::endl;
+ }
+ for (size_t i = 0; i < handles.size(); i++)
+ {
+ if (verbose)
+ {
+ std::cout
+ << "\tCurrentValueStringHandleIndex[" << i
+ << "] = " << (int)handles[i] << ", StringHandle = "
+ << displayEnumValueByIndex(attrHandle, handles[i],
+ attrTable, stringTable)
+ << std::endl;
+ }
+ else
+ {
+ std::cout
+ << "CurrentValue: "
+ << displayEnumValueByIndex(attrHandle, handles[i],
+ attrTable, stringTable)
+ << std::endl;
+ }
+ }
+ break;
+ }
+ case PLDM_BIOS_INTEGER:
+ case PLDM_BIOS_INTEGER_READ_ONLY:
+ {
+ auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv(
+ tableEntry);
+ if (verbose)
+ {
+ std::cout << "\tCurrentValue: " << cv << std::endl;
+ }
+ else
+ {
+ std::cout << "CurrentValue: " << cv << std::endl;
+ }
+ break;
+ }
+ case PLDM_BIOS_STRING:
+ case PLDM_BIOS_STRING_READ_ONLY:
+ {
+ variable_field currentString;
+ pldm_bios_table_attr_value_entry_string_decode_string(
+ tableEntry, ¤tString);
+ if (verbose)
+ {
+ std::cout
+ << "\tCurrentStringLength: " << currentString.length
+ << std::endl
+ << "\tCurrentString: "
+ << std::string(
+ reinterpret_cast<const char*>(currentString.ptr),
+ currentString.length)
+ << std::endl;
+ }
+ else
+ {
+ std::cout << "CurrentValue: "
+ << std::string(reinterpret_cast<const char*>(
+ currentString.ptr),
+ currentString.length)
+ << std::endl;
+ }
+
+ break;
+ }
+ case PLDM_BIOS_PASSWORD:
+ case PLDM_BIOS_PASSWORD_READ_ONLY:
+ {
+ std::cout << "Password attribute: Not Supported" << std::endl;
+ break;
+ }
+ }
+ }
+};
+
+class GetBIOSTable : public GetBIOSTableHandler
+{
+ public:
+ ~GetBIOSTable() = default;
+ GetBIOSTable() = delete;
+ GetBIOSTable(const GetBIOSTable&) = delete;
+ GetBIOSTable(GetBIOSTable&&) = default;
+ GetBIOSTable& operator=(const GetBIOSTable&) = delete;
+ GetBIOSTable& operator=(GetBIOSTable&&) = default;
+
+ using Table = std::vector<uint8_t>;
+
+ explicit GetBIOSTable(const char* type, const char* name, CLI::App* app) :
+ GetBIOSTableHandler(type, name, app)
+ {
+ app->add_option("-t,--type", pldmBIOSTableType, "pldm bios table type")
+ ->required()
+ ->transform(
+ CLI::CheckedTransformer(pldmBIOSTableTypes, CLI::ignore_case));
+ }
+
+ void exec() override
+ {
+ switch (pldmBIOSTableType)
+ {
+ case PLDM_BIOS_STRING_TABLE:
+ {
+ auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
+ decodeStringTable(stringTable);
+ break;
+ }
+ case PLDM_BIOS_ATTR_TABLE:
+ {
+ auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
+ auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+
+ decodeAttributeTable(attrTable, stringTable);
+ break;
+ }
+ case PLDM_BIOS_ATTR_VAL_TABLE:
+ {
+ auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
+ auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+ auto attrValTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
+
+ decodeAttributeValueTable(attrValTable, attrTable, stringTable);
+ break;
+ }
+ }
+ }
+
+ private:
+ pldm_bios_table_types pldmBIOSTableType;
+
+ void decodeStringTable(const std::optional<Table>& stringTable)
+ {
+ if (!stringTable)
+ {
+ std::cerr << "GetBIOSStringTable Error" << std::endl;
+ return;
+ }
+ std::cout << "PLDM StringTable: " << std::endl;
+ std::cout << "BIOSStringHandle : BIOSString" << std::endl;
+
+ for (auto tableEntry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
+ stringTable->data(), stringTable->size()))
+ {
+ auto strHandle =
+ pldm_bios_table_string_entry_decode_handle(tableEntry);
+ auto strTableData = decodeStringFromStringEntry(tableEntry);
+ std::cout << strHandle << " : " << strTableData << std::endl;
+ }
+ }
+ void decodeAttributeTable(const std::optional<Table>& attrTable,
+ const std::optional<Table>& stringTable)
+ {
+ if (!stringTable)
+ {
+ std::cerr << "GetBIOSAttributeTable Error" << std::endl;
+ return;
+ }
+ std::cout << "PLDM AttributeTable: " << std::endl;
+ for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
+ attrTable->data(), attrTable->size()))
+ {
+ auto attrHandle =
+ pldm_bios_table_attr_entry_decode_attribute_handle(entry);
+ auto attrNameHandle =
+ pldm_bios_table_attr_entry_decode_string_handle(entry);
+ auto attrType = static_cast<pldm_bios_attribute_type>(
+ pldm_bios_table_attr_entry_decode_attribute_type(entry));
+ std::cout << "AttributeHandle: " << attrHandle
+ << ", AttributeNameHandle: "
+ << displayStringHandle(attrNameHandle, stringTable)
+ << std::endl;
+ std::cout << "\tAttributeType: " << attrTypeMap.at(attrType)
+ << std::endl;
+ switch (attrType)
+ {
+ case PLDM_BIOS_ENUMERATION:
+ case PLDM_BIOS_ENUMERATION_READ_ONLY:
+ {
+ auto pvNum =
+ pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
+ std::vector<uint16_t> pvHandls(pvNum);
+ pldm_bios_table_attr_entry_enum_decode_pv_hdls(
+ entry, pvHandls.data(), pvHandls.size());
+ auto defNum =
+ pldm_bios_table_attr_entry_enum_decode_def_num(entry);
+ std::vector<uint8_t> defIndices(defNum);
+ pldm_bios_table_attr_entry_enum_decode_def_indices(
+ entry, defIndices.data(), defIndices.size());
+ std::cout << "\tNumberOfPossibleValues: " << (int)pvNum
+ << std::endl;
+
+ for (size_t i = 0; i < pvHandls.size(); i++)
+ {
+ std::cout
+ << "\t\tPossibleValueStringHandle"
+ << "[" << i << "] = "
+ << displayStringHandle(pvHandls[i], stringTable)
+ << std::endl;
+ }
+ std::cout << "\tNumberOfDefaultValues: " << (int)defNum
+ << std::endl;
+ for (size_t i = 0; i < defIndices.size(); i++)
+ {
+ std::cout << "\t\tDefaultValueStringHandleIndex"
+ << "[" << i << "] = " << (int)defIndices[i]
+ << ", StringHandle = "
+ << displayStringHandle(
+ pvHandls[defIndices[i]], stringTable)
+ << std::endl;
+ }
+ break;
+ }
+ case PLDM_BIOS_INTEGER:
+ case PLDM_BIOS_INTEGER_READ_ONLY:
+ {
+ uint64_t lower, upper, def;
+ uint32_t scalar;
+ pldm_bios_table_attr_entry_integer_decode(
+ entry, &lower, &upper, &scalar, &def);
+ std::cout << "\tLowerBound: " << lower << std::endl
+ << "\tUpperBound: " << upper << std::endl
+ << "\tScalarIncrement: " << scalar << std::endl
+ << "\tDefaultValue: " << def << std::endl;
+ break;
+ }
+ case PLDM_BIOS_STRING:
+ case PLDM_BIOS_STRING_READ_ONLY:
+ {
+ auto strType =
+ pldm_bios_table_attr_entry_string_decode_string_type(
+ entry);
+ auto min =
+ pldm_bios_table_attr_entry_string_decode_min_length(
+ entry);
+ auto max =
+ pldm_bios_table_attr_entry_string_decode_max_length(
+ entry);
+ auto def =
+ pldm_bios_table_attr_entry_string_decode_def_string_length(
+ entry);
+ std::vector<char> defString(def + 1);
+ pldm_bios_table_attr_entry_string_decode_def_string(
+ entry, defString.data(), defString.size());
+ std::cout
+ << "\tStringType: 0x" << std::hex << std::setw(2)
+ << std::setfill('0') << (int)strType << std::dec
+ << std::setw(0) << std::endl
+ << "\tMinimumStringLength: " << (int)min << std::endl
+ << "\tMaximumStringLength: " << (int)max << std::endl
+ << "\tDefaultStringLength: " << (int)def << std::endl
+ << "\tDefaultString: " << defString.data() << std::endl;
+ break;
+ }
+ case PLDM_BIOS_PASSWORD:
+ case PLDM_BIOS_PASSWORD_READ_ONLY:
+ std::cout << "Password attribute: Not Supported"
+ << std::endl;
+ }
+ }
+ }
+ void decodeAttributeValueTable(const std::optional<Table>& attrValTable,
+ const std::optional<Table>& attrTable,
+ const std::optional<Table>& stringTable)
+ {
+ if (!attrValTable)
+ {
+ std::cerr << "GetBIOSAttributeValueTable Error" << std::endl;
+ return;
+ }
+ std::cout << "PLDM AttributeValueTable: " << std::endl;
+ for (auto tableEntry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
+ attrValTable->data(), attrValTable->size()))
+ {
+ displayAttributeValueEntry(tableEntry, attrTable, stringTable,
+ true);
+ }
+ }
+};
+
+class GetBIOSAttributeCurrentValueByHandle : public GetBIOSTableHandler
+{
+ public:
+ ~GetBIOSAttributeCurrentValueByHandle() = default;
+ GetBIOSAttributeCurrentValueByHandle(
+ const GetBIOSAttributeCurrentValueByHandle&) = delete;
+ GetBIOSAttributeCurrentValueByHandle(
+ GetBIOSAttributeCurrentValueByHandle&&) = delete;
+ GetBIOSAttributeCurrentValueByHandle&
+ operator=(const GetBIOSAttributeCurrentValueByHandle&) = delete;
+ GetBIOSAttributeCurrentValueByHandle&
+ operator=(GetBIOSAttributeCurrentValueByHandle&&) = delete;
+
+ explicit GetBIOSAttributeCurrentValueByHandle(const char* type,
+ const char* name,
+ CLI::App* app) :
+ GetBIOSTableHandler(type, name, app)
+ {
+ app->add_option("-a, --attribute", attrName, "pldm bios attribute name")
+ ->required();
+ }
+
+ void exec()
+ {
+ auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
+ auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+
+ if (!stringTable || !attrTable)
+ {
+ std::cout << "StringTable/AttrTable Unavaliable" << std::endl;
+ return;
+ }
+
+ auto handle = findAttrHandleByName(attrName, *attrTable, *stringTable);
+ if (!handle)
+ {
+
+ std::cerr << "Can not find the attribute " << attrName << std::endl;
+ return;
+ }
+
+ std::vector<uint8_t> requestMsg(
+ sizeof(pldm_msg_hdr) +
+ PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_bios_attribute_current_value_by_handle_req(
+ instanceId, 0, PLDM_GET_FIRSTPART, *handle, request);
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl;
+ return;
+ }
+
+ std::vector<uint8_t> responseMsg;
+ rc = pldmSendRecv(requestMsg, responseMsg);
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl;
+ return;
+ }
+
+ uint8_t cc = 0, transferFlag = 0;
+ uint32_t nextTransferHandle = 0;
+ struct variable_field attributeData;
+ auto responsePtr =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr);
+
+ rc = decode_get_bios_attribute_current_value_by_handle_resp(
+ responsePtr, payloadLength, &cc, &nextTransferHandle, &transferFlag,
+ &attributeData);
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << std::endl;
+ return;
+ }
+
+ auto tableEntry =
+ reinterpret_cast<const struct pldm_bios_attr_val_table_entry*>(
+ attributeData.ptr);
+
+ displayAttributeValueEntry(tableEntry, attrTable, stringTable, false);
+ }
+
+ private:
+ std::string attrName;
+};
+
+class SetBIOSAttributeCurrentValue : public GetBIOSTableHandler
+{
+ public:
+ ~SetBIOSAttributeCurrentValue() = default;
+ SetBIOSAttributeCurrentValue() = delete;
+ SetBIOSAttributeCurrentValue(const SetBIOSAttributeCurrentValue&) = delete;
+ SetBIOSAttributeCurrentValue(SetBIOSAttributeCurrentValue&&) = default;
+ SetBIOSAttributeCurrentValue&
+ operator=(const SetBIOSAttributeCurrentValue&) = delete;
+ SetBIOSAttributeCurrentValue&
+ operator=(SetBIOSAttributeCurrentValue&&) = default;
+
+ explicit SetBIOSAttributeCurrentValue(const char* type, const char* name,
+ CLI::App* app) :
+ GetBIOSTableHandler(type, name, app)
+ {
+ app->add_option("-a, --attribute", attrName, "pldm attribute name")
+ ->required();
+ app->add_option("-d, --data", attrValue, "pldm attribute value")
+ ->required();
+ // -v is conflict with --verbose in class CommandInterface, so used -d
+ }
+
+ void exec()
+ {
+ auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
+ auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+ auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
+
+ if (!stringTable || !attrTable)
+ {
+ std::cout << "StringTable/AttrTable Unavaliable" << std::endl;
+ return;
+ }
+
+ auto attrEntry =
+ findAttrEntryByName(attrName, *attrTable, *stringTable);
+ if (attrEntry == nullptr)
+ {
+ std::cout << "Could not find attribute :" << attrName << std::endl;
+ return;
+ }
+
+ std::vector<uint8_t> requestMsg;
+
+ int rc = 0;
+ auto attrType = attrEntry->attr_type;
+ size_t entryLength = 1;
+ std::vector<uint8_t> attrValueEntry(entryLength, 0);
+
+ switch (attrType)
+ {
+ case PLDM_BIOS_ENUMERATION_READ_ONLY:
+ case PLDM_BIOS_STRING_READ_ONLY:
+ case PLDM_BIOS_INTEGER_READ_ONLY:
+ {
+ std::cerr << "Set attribute error: " << attrName
+ << "is read only." << std::endl;
+ return;
+ }
+ case PLDM_BIOS_ENUMERATION:
+ {
+ entryLength =
+ pldm_bios_table_attr_value_entry_encode_enum_length(1);
+ auto pvNum =
+ pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry);
+ std::vector<uint16_t> pvHdls(pvNum, 0);
+ pldm_bios_table_attr_entry_enum_decode_pv_hdls(
+ attrEntry, pvHdls.data(), pvNum);
+ auto stringEntry = pldm_bios_table_string_find_by_string(
+ stringTable->data(), stringTable->size(),
+ attrValue.c_str());
+ if (stringEntry == nullptr)
+ {
+ std::cout
+ << "Set Attribute Error: It's not a possible value"
+ << std::endl;
+ return;
+ }
+ auto valueHandle =
+ pldm_bios_table_string_entry_decode_handle(stringEntry);
+
+ uint8_t i;
+ for (i = 0; i < pvNum; i++)
+ {
+ if (valueHandle == pvHdls[i])
+ break;
+ }
+ if (i == pvNum)
+ {
+ std::cout
+ << "Set Attribute Error: It's not a possible value"
+ << std::endl;
+ return;
+ }
+
+ attrValueEntry.resize(entryLength);
+ std::vector<uint8_t> handles = {i};
+ pldm_bios_table_attr_value_entry_encode_enum(
+ attrValueEntry.data(), attrValueEntry.size(),
+ attrEntry->attr_handle, attrType, 1, handles.data());
+ break;
+ }
+ case PLDM_BIOS_STRING:
+ {
+ entryLength =
+ pldm_bios_table_attr_value_entry_encode_string_length(
+ attrValue.size());
+
+ attrValueEntry.resize(entryLength);
+
+ pldm_bios_table_attr_value_entry_encode_string(
+ attrValueEntry.data(), entryLength, attrEntry->attr_handle,
+ attrType, attrValue.size(), attrValue.c_str());
+ break;
+ }
+ case PLDM_BIOS_INTEGER:
+ {
+ uint64_t value = std::stoll(attrValue);
+ entryLength =
+ pldm_bios_table_attr_value_entry_encode_integer_length();
+ attrValueEntry.resize(entryLength);
+ pldm_bios_table_attr_value_entry_encode_integer(
+ attrValueEntry.data(), entryLength, attrEntry->attr_handle,
+ attrType, value);
+ break;
+ }
+ }
+
+ requestMsg.resize(entryLength + sizeof(pldm_msg_hdr) +
+ PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES);
+
+ rc = encode_set_bios_attribute_current_value_req(
+ instanceId, 0, PLDM_START_AND_END, attrValueEntry.data(),
+ attrValueEntry.size(),
+ reinterpret_cast<pldm_msg*>(requestMsg.data()),
+ requestMsg.size() - sizeof(pldm_msg_hdr));
+
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl;
+ return;
+ }
+ std::vector<uint8_t> responseMsg;
+ rc = pldmSendRecv(requestMsg, responseMsg);
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl;
+ return;
+ }
+ uint8_t cc = 0;
+ uint32_t nextTransferHandle = 0;
+ auto responsePtr =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr);
+
+ rc = decode_set_bios_attribute_current_value_resp(
+ responsePtr, payloadLength, &cc, &nextTransferHandle);
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << std::endl;
+ return;
+ }
+
+ std::cout << "SetBIOSAttributeCurrentValue: SUCCESS" << std::endl;
+ }
+
+ private:
+ std::string attrName;
+ std::string attrValue;
+};
+
+void registerCommand(CLI::App& app)
+{
+ auto bios = app.add_subcommand("bios", "bios type command");
+ bios->require_subcommand(1);
+ auto getDateTime = bios->add_subcommand("GetDateTime", "get date time");
+ commands.push_back(
+ std::make_unique<GetDateTime>("bios", "GetDateTime", getDateTime));
+
+ auto setDateTime =
+ bios->add_subcommand("SetDateTime", "set host date time");
+ commands.push_back(
+ std::make_unique<SetDateTime>("bios", "setDateTime", setDateTime));
+
+ auto getBIOSTable = bios->add_subcommand("GetBIOSTable", "get bios table");
+ commands.push_back(
+ std::make_unique<GetBIOSTable>("bios", "GetBIOSTable", getBIOSTable));
+
+ auto getBIOSAttributeCurrentValueByHandle =
+ bios->add_subcommand("GetBIOSAttributeCurrentValueByHandle",
+ "get bios attribute current value by handle");
+ commands.push_back(std::make_unique<GetBIOSAttributeCurrentValueByHandle>(
+ "bios", "GetBIOSAttributeCurrentValueByHandle",
+ getBIOSAttributeCurrentValueByHandle));
+
+ auto setBIOSAttributeCurrentValue = bios->add_subcommand(
+ "SetBIOSAttributeCurrentValue", "set bios attribute current value");
+ commands.push_back(std::make_unique<SetBIOSAttributeCurrentValue>(
+ "bios", "SetBIOSAttributeCurrentValue", setBIOSAttributeCurrentValue));
+}
+
+} // namespace bios
+
+} // namespace pldmtool
diff --git a/pldmtool/pldm_bios_cmd.hpp b/pldmtool/pldm_bios_cmd.hpp
new file mode 100644
index 0000000..cb80b0f
--- /dev/null
+++ b/pldmtool/pldm_bios_cmd.hpp
@@ -0,0 +1,14 @@
+#pragma once
+#include <CLI/CLI.hpp>
+
+namespace pldmtool
+{
+
+namespace bios
+{
+
+void registerCommand(CLI::App& app);
+
+} // namespace bios
+
+} // namespace pldmtool
diff --git a/pldmtool/pldm_cmd_helper.cpp b/pldmtool/pldm_cmd_helper.cpp
new file mode 100644
index 0000000..7002c79
--- /dev/null
+++ b/pldmtool/pldm_cmd_helper.cpp
@@ -0,0 +1,247 @@
+#include "pldm_cmd_helper.hpp"
+
+#include "libpldm/requester/pldm.h"
+
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <systemd/sd-bus.h>
+
+#include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/Logging/Entry/server.hpp>
+
+#include <exception>
+
+namespace pldmtool
+{
+
+namespace helper
+{
+/*
+ * print the input buffer if pldm verbosity is enabled.
+ *
+ */
+void printBuffer(const std::vector<uint8_t>& buffer, bool pldmVerbose)
+{
+ if (pldmVerbose && !buffer.empty())
+ {
+ std::ostringstream tempStream;
+ for (int byte : buffer)
+ {
+ tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
+ << " ";
+ }
+ std::cout << tempStream.str() << std::endl;
+ }
+}
+/*
+ * Initialize the socket, send pldm command & recieve response from socket
+ *
+ */
+int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
+ std::vector<uint8_t>& responseMsg, bool pldmVerbose)
+{
+
+ const char devPath[] = "\0mctp-mux";
+ int returnCode = 0;
+
+ int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+ if (-1 == sockFd)
+ {
+ returnCode = -errno;
+ std::cerr << "Failed to create the socket : RC = " << sockFd << "\n";
+ return returnCode;
+ }
+ Logger(pldmVerbose, "Success in creating the socket : RC = ", sockFd);
+
+ struct sockaddr_un addr
+ {};
+ addr.sun_family = AF_UNIX;
+
+ memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
+
+ CustomFD socketFd(sockFd);
+ int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
+ sizeof(devPath) + sizeof(addr.sun_family) - 1);
+ if (-1 == result)
+ {
+ returnCode = -errno;
+ std::cerr << "Failed to connect to socket : RC = " << returnCode
+ << "\n";
+ return returnCode;
+ }
+ Logger(pldmVerbose, "Success in connecting to socket : RC = ", returnCode);
+
+ auto pldmType = MCTP_MSG_TYPE_PLDM;
+ result = write(socketFd(), &pldmType, sizeof(pldmType));
+ if (-1 == result)
+ {
+ returnCode = -errno;
+ std::cerr << "Failed to send message type as pldm to mctp : RC = "
+ << returnCode << "\n";
+ return returnCode;
+ }
+ Logger(
+ pldmVerbose,
+ "Success in sending message type as pldm to mctp : RC = ", returnCode);
+
+ result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
+ if (-1 == result)
+ {
+ returnCode = -errno;
+ std::cerr << "Write to socket failure : RC = " << returnCode << "\n";
+ return returnCode;
+ }
+ Logger(pldmVerbose, "Write to socket successful : RC = ", result);
+
+ // Read the response from socket
+ ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
+ if (0 == peekedLength)
+ {
+ std::cerr << "Socket is closed : peekedLength = " << peekedLength
+ << "\n";
+ return returnCode;
+ }
+ else if (peekedLength <= -1)
+ {
+ returnCode = -errno;
+ std::cerr << "recv() system call failed : RC = " << returnCode << "\n";
+ return returnCode;
+ }
+ else
+ {
+ auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&requestMsg[2]);
+ do
+ {
+ ssize_t peekedLength =
+ recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
+ responseMsg.resize(peekedLength);
+ auto recvDataLength =
+ recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
+ peekedLength, 0);
+ auto resphdr =
+ reinterpret_cast<const pldm_msg_hdr*>(&responseMsg[2]);
+ if (recvDataLength == peekedLength &&
+ resphdr->instance_id == reqhdr->instance_id &&
+ resphdr->request != PLDM_REQUEST)
+ {
+ Logger(pldmVerbose, "Total length:", recvDataLength);
+ break;
+ }
+ else if (recvDataLength != peekedLength)
+ {
+ std::cerr << "Failure to read response length packet: length = "
+ << recvDataLength << "\n";
+ return returnCode;
+ }
+ } while (1);
+ }
+
+ returnCode = shutdown(socketFd(), SHUT_RDWR);
+ if (-1 == returnCode)
+ {
+ returnCode = -errno;
+ std::cerr << "Failed to shutdown the socket : RC = " << returnCode
+ << "\n";
+ return returnCode;
+ }
+
+ Logger(pldmVerbose, "Shutdown Socket successful : RC = ", returnCode);
+ return PLDM_SUCCESS;
+}
+
+void CommandInterface::exec()
+{
+ static constexpr auto pldmObjPath = "/xyz/openbmc_project/pldm";
+ static constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
+ auto& bus = pldm::utils::DBusHandler::getBus();
+ try
+ {
+ auto service =
+ pldm::utils::DBusHandler().getService(pldmObjPath, pldmRequester);
+ auto method = bus.new_method_call(service.c_str(), pldmObjPath,
+ pldmRequester, "GetInstanceId");
+ method.append(mctp_eid);
+ auto reply = bus.call(method);
+ reply.read(instanceId);
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "GetInstanceId D-Bus call failed, MCTP id = " << mctp_eid
+ << ", error = " << e.what() << "\n";
+ return;
+ }
+ auto [rc, requestMsg] = createRequestMsg();
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "Failed to encode request message for " << pldmType << ":"
+ << commandName << " rc = " << rc << "\n";
+ return;
+ }
+
+ std::vector<uint8_t> responseMsg;
+ rc = pldmSendRecv(requestMsg, responseMsg);
+
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
+ return;
+ }
+
+ auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
+}
+
+int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
+ std::vector<uint8_t>& responseMsg)
+{
+
+ // Insert the PLDM message type and EID at the beginning of the
+ // msg.
+ requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
+ requestMsg.insert(requestMsg.begin(), mctp_eid);
+
+ bool mctpVerbose = pldmVerbose;
+
+ // By default enable request/response msgs for pldmtool raw commands.
+ if (CommandInterface::pldmType == "raw")
+ {
+ pldmVerbose = true;
+ }
+
+ Logger(pldmVerbose, "Request Message:", "");
+ printBuffer(requestMsg, pldmVerbose);
+
+ if (mctp_eid != PLDM_ENTITY_ID)
+ {
+ int fd = pldm_open();
+ if (-1 == fd)
+ {
+ std::cerr << "failed to init mctp "
+ << "\n";
+ return -1;
+ }
+ uint8_t* responseMessage = nullptr;
+ size_t responseMessageSize{};
+ pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
+ requestMsg.size() - 2, &responseMessage,
+ &responseMessageSize);
+
+ Logger(pldmVerbose, "Response Message:", "");
+ responseMsg.resize(responseMessageSize);
+ memcpy(responseMsg.data(), responseMessage, responseMsg.size());
+
+ free(responseMessage);
+ printBuffer(responseMsg, pldmVerbose);
+ }
+ else
+ {
+ mctpSockSendRecv(requestMsg, responseMsg, mctpVerbose);
+ Logger(pldmVerbose, "Response Message:", "");
+ printBuffer(responseMsg, pldmVerbose);
+ responseMsg.erase(responseMsg.begin(),
+ responseMsg.begin() + 2 /* skip the mctp header */);
+ }
+ return PLDM_SUCCESS;
+}
+} // namespace helper
+} // namespace pldmtool
diff --git a/pldmtool/pldm_cmd_helper.hpp b/pldmtool/pldm_cmd_helper.hpp
new file mode 100644
index 0000000..7e7f03a
--- /dev/null
+++ b/pldmtool/pldm_cmd_helper.hpp
@@ -0,0 +1,110 @@
+#pragma once
+
+#include "libpldm/base.h"
+#include "libpldm/bios.h"
+#include "libpldm/fru.h"
+#include "libpldm/platform.h"
+
+#include "common/utils.hpp"
+
+#include <err.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <CLI/CLI.hpp>
+
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <utility>
+
+namespace pldmtool
+{
+
+namespace helper
+{
+
+using namespace pldm::utils;
+constexpr uint8_t PLDM_ENTITY_ID = 8;
+constexpr uint8_t MCTP_MSG_TYPE_PLDM = 1;
+
+/** @brief Print the buffer
+ *
+ * @param[in] buffer - Buffer to print
+ * @param[in] pldmVerbose -verbosity flag - true/false
+ *
+ * @return - None
+ */
+void printBuffer(const std::vector<uint8_t>& buffer, bool pldmVerbose);
+
+/** @brief print the input message if pldmverbose is enabled
+ *
+ * @param[in] pldmVerbose - verbosity flag - true/false
+ * @param[in] msg - message to print
+ * @param[in] data - data to print
+ *
+ * @return - None
+ */
+
+template <class T>
+void Logger(bool pldmverbose, const char* msg, const T& data)
+{
+ if (pldmverbose)
+ {
+ std::stringstream s;
+ s << data;
+ std::cout << msg << s.str() << std::endl;
+ }
+}
+/** @brief MCTP socket read/recieve
+ *
+ * @param[in] requestMsg - Request message to compare against loopback
+ * message recieved from mctp socket
+ * @param[out] responseMsg - Response buffer recieved from mctp socket
+ * @param[in] pldmVerbose - verbosity flag - true/false
+ *
+ * @return - 0 on success.
+ * -1 or -errno on failure.
+ */
+int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
+ std::vector<uint8_t>& responseMsg, bool pldmVerbose);
+
+class CommandInterface
+{
+
+ public:
+ explicit CommandInterface(const char* type, const char* name,
+ CLI::App* app) :
+ pldmType(type),
+ commandName(name), mctp_eid(PLDM_ENTITY_ID), instanceId(0)
+ {
+ app->add_option("-m,--mctp_eid", mctp_eid, "MCTP endpoint ID");
+ app->add_flag("-v, --verbose", pldmVerbose);
+ app->callback([&]() { exec(); });
+ }
+
+ virtual ~CommandInterface() = default;
+
+ virtual std::pair<int, std::vector<uint8_t>> createRequestMsg() = 0;
+
+ virtual void parseResponseMsg(struct pldm_msg* responsePtr,
+ size_t payloadLength) = 0;
+
+ virtual void exec();
+
+ int pldmSendRecv(std::vector<uint8_t>& requestMsg,
+ std::vector<uint8_t>& responseMsg);
+
+ private:
+ const std::string pldmType;
+ const std::string commandName;
+ uint8_t mctp_eid;
+ bool pldmVerbose;
+
+ protected:
+ uint8_t instanceId;
+};
+
+} // namespace helper
+} // namespace pldmtool
diff --git a/pldmtool/pldm_fru_cmd.cpp b/pldmtool/pldm_fru_cmd.cpp
new file mode 100644
index 0000000..2075a48
--- /dev/null
+++ b/pldmtool/pldm_fru_cmd.cpp
@@ -0,0 +1,89 @@
+#include "pldm_fru_cmd.hpp"
+
+#include "pldm_cmd_helper.hpp"
+
+namespace pldmtool
+{
+
+namespace fru
+{
+
+namespace
+{
+
+using namespace pldmtool::helper;
+
+std::vector<std::unique_ptr<CommandInterface>> commands;
+
+} // namespace
+
+class GetFruRecordTableMetadata : public CommandInterface
+{
+ public:
+ ~GetFruRecordTableMetadata() = default;
+ GetFruRecordTableMetadata() = delete;
+ GetFruRecordTableMetadata(const GetFruRecordTableMetadata&) = delete;
+ GetFruRecordTableMetadata(GetFruRecordTableMetadata&&) = default;
+ GetFruRecordTableMetadata&
+ operator=(const GetFruRecordTableMetadata&) = delete;
+ GetFruRecordTableMetadata& operator=(GetFruRecordTableMetadata&&) = default;
+
+ using CommandInterface::CommandInterface;
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_fru_record_table_metadata_req(
+ instanceId, request, PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t cc = 0;
+ uint8_t fru_data_major_version, fru_data_minor_version;
+ uint32_t fru_table_maximum_size, fru_table_length;
+ uint16_t total_record_set_identifiers, total_table_records;
+ uint32_t checksum;
+
+ auto rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payloadLength, &cc, &fru_data_major_version,
+ &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)cc << std::endl;
+ return;
+ }
+ std::cout << "FRUDATAMajorVersion : "
+ << static_cast<uint32_t>(fru_data_major_version) << std::endl;
+ std::cout << "FRUDATAMinorVersion : "
+ << static_cast<uint32_t>(fru_data_minor_version) << std::endl;
+ std::cout << "FRUTableMaximumSize : " << fru_table_maximum_size
+ << std::endl;
+ std::cout << "FRUTableLength : " << fru_table_length << std::endl;
+ std::cout << "Total number of Record Set Identifiers in table : "
+ << total_record_set_identifiers << std::endl;
+ std::cout << "Total number of records in table : "
+ << total_table_records << std::endl;
+ std::cout << "FRU DATAStructureTableIntegrityChecksum : " << checksum
+ << std::endl;
+ }
+};
+
+void registerCommand(CLI::App& app)
+{
+ auto fru = app.add_subcommand("fru", "FRU type command");
+ fru->require_subcommand(1);
+ auto getFruRecordTableMetadata = fru->add_subcommand(
+ "GetFruRecordTableMetadata", "get FRU record table metadata");
+ commands.push_back(std::make_unique<GetFruRecordTableMetadata>(
+ "fru", "GetFruRecordTableMetadata", getFruRecordTableMetadata));
+}
+
+} // namespace fru
+
+} // namespace pldmtool
diff --git a/pldmtool/pldm_fru_cmd.hpp b/pldmtool/pldm_fru_cmd.hpp
new file mode 100644
index 0000000..1cb3210
--- /dev/null
+++ b/pldmtool/pldm_fru_cmd.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <CLI/CLI.hpp>
+
+namespace pldmtool
+{
+
+namespace fru
+{
+
+void registerCommand(CLI::App& app);
+}
+
+} // namespace pldmtool
diff --git a/pldmtool/pldm_platform_cmd.cpp b/pldmtool/pldm_platform_cmd.cpp
new file mode 100644
index 0000000..2c62f42
--- /dev/null
+++ b/pldmtool/pldm_platform_cmd.cpp
@@ -0,0 +1,647 @@
+#include "pldm_cmd_helper.hpp"
+
+namespace pldmtool
+{
+
+namespace platform
+{
+
+namespace
+{
+
+using namespace pldmtool::helper;
+std::vector<std::unique_ptr<CommandInterface>> commands;
+
+} // namespace
+
+class GetPDR : public CommandInterface
+{
+ public:
+ ~GetPDR() = default;
+ GetPDR() = delete;
+ GetPDR(const GetPDR&) = delete;
+ GetPDR(GetPDR&&) = default;
+ GetPDR& operator=(const GetPDR&) = delete;
+ GetPDR& operator=(GetPDR&&) = default;
+
+ using CommandInterface::CommandInterface;
+
+ // The maximum number of record bytes requested to be returned in the
+ // response to this instance of the GetPDR command.
+ static constexpr uint16_t requestCount = 128;
+
+ explicit GetPDR(const char* type, const char* name, CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option(
+ "-d,--data", recordHandle,
+ "retrieve individual PDRs from a PDR Repository\n"
+ "eg: The recordHandle value for the PDR to be retrieved and 0 "
+ "means get first PDR in the repository.")
+ ->required();
+ }
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_PDR_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_pdr_req(instanceId, recordHandle, 0,
+ PLDM_GET_FIRSTPART, requestCount, 0,
+ request, PLDM_GET_PDR_REQ_BYTES);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t completionCode = 0;
+ uint8_t recordData[65535] = {0};
+ uint32_t nextRecordHndl = 0;
+ uint32_t nextDataTransferHndl = 0;
+ uint8_t transferFlag = 0;
+ uint16_t respCnt = 0;
+ uint8_t transferCRC = 0;
+
+ auto rc = decode_get_pdr_resp(
+ responsePtr, payloadLength, &completionCode, &nextRecordHndl,
+ &nextDataTransferHndl, &transferFlag, &respCnt, recordData,
+ sizeof(recordData), &transferCRC);
+
+ if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)completionCode
+ << std::endl;
+ return;
+ }
+
+ printPDRMsg(nextRecordHndl, respCnt, recordData);
+ }
+
+ private:
+ const std::map<uint16_t, std::string> entityType = {
+ {64, "System Board"},
+ {66, "Memory Module"},
+ {67, "Processor Module"},
+ {137, "Management Controller"},
+ {69, "Chassis front panel board (control panel)"},
+ {123, "Power converter"},
+ {45, "System chassis (main enclosure)"},
+ {11521, "System (logical)"},
+ };
+
+ std::string getEntityName(uint16_t type)
+ {
+ try
+ {
+ return entityType.at(type);
+ }
+ catch (const std::out_of_range& e)
+ {
+ return std::to_string(static_cast<unsigned>(type)) + "(OEM)";
+ }
+ }
+
+ void printPDRFruRecordSet(uint8_t* data)
+ {
+ if (data == NULL)
+ {
+ return;
+ }
+
+ data += sizeof(pldm_pdr_hdr);
+ pldm_pdr_fru_record_set* pdr =
+ reinterpret_cast<pldm_pdr_fru_record_set*>(data);
+
+ std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
+ << std::endl;
+ std::cout << "FRURecordSetIdentifier: " << pdr->fru_rsi << std::endl;
+ std::cout << "entityType: " << getEntityName(pdr->entity_type)
+ << std::endl;
+ std::cout << "entityInstanceNumber: " << pdr->entity_instance_num
+ << std::endl;
+ std::cout << "containerID: " << pdr->container_id << std::endl;
+ }
+
+ void printPDREntityAssociation(uint8_t* data)
+ {
+ const std::map<uint8_t, const char*> assocationType = {
+ {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"},
+ {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"},
+ };
+
+ if (data == NULL)
+ {
+ return;
+ }
+
+ data += sizeof(pldm_pdr_hdr);
+ pldm_pdr_entity_association* pdr =
+ reinterpret_cast<pldm_pdr_entity_association*>(data);
+
+ std::cout << "containerID: " << pdr->container_id << std::endl;
+ std::cout << "associationType: "
+ << assocationType.at(pdr->association_type) << std::endl
+ << std::endl;
+
+ std::cout << "containerEntityType: "
+ << getEntityName(pdr->container.entity_type) << std::endl;
+ std::cout << "containerEntityInstanceNumber: "
+ << pdr->container.entity_instance_num << std::endl;
+ std::cout << "containerEntityContainerID: "
+ << pdr->container.entity_container_id << std::endl;
+
+ std::cout << "containedEntityCount: "
+ << static_cast<unsigned>(pdr->num_children) << std::endl
+ << std::endl;
+
+ auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]);
+ for (int i = 0; i < pdr->num_children; ++i)
+ {
+ std::cout << "containedEntityType[" << i + 1
+ << "]: " << getEntityName(child->entity_type)
+ << std::endl;
+ std::cout << "containedEntityInstanceNumber[" << i + 1
+ << "]: " << child->entity_instance_num << std::endl;
+ std::cout << "containedEntityContainerID[" << i + 1
+ << "]: " << child->entity_container_id << std::endl
+ << std::endl;
+ ++child;
+ }
+ }
+
+ void printEffecterHdrPDR(pldm_pdr_hdr* hdr)
+ {
+ std::cout << "recordHandle: " << hdr->record_handle << std::endl;
+ std::cout << "PDRHeaderVersion: " << unsigned(hdr->version)
+ << std::endl;
+ std::cout << "PDRType: " << unsigned(hdr->type) << std::endl;
+ std::cout << "recordChangeNumber: " << hdr->record_change_num
+ << std::endl;
+ std::cout << "dataLength: " << hdr->length << std::endl;
+ }
+
+ void printNumericEffecterPDR(uint8_t* data)
+ {
+ struct pldm_numeric_effecter_value_pdr* pdr =
+ (struct pldm_numeric_effecter_value_pdr*)data;
+ printEffecterHdrPDR(&pdr->hdr);
+ std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
+ << std::endl;
+ std::cout << "effecterID: " << pdr->effecter_id << std::endl;
+ std::cout << "entityType: " << pdr->entity_type << std::endl;
+ std::cout << "entityInstanceNumber: " << pdr->entity_instance
+ << std::endl;
+ std::cout << "containerID: " << pdr->container_id << std::endl;
+ std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
+ << std::endl;
+ std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
+ << std::endl;
+ std::cout << "effecterAuxiliaryNames: "
+ << (unsigned(pdr->effecter_auxiliary_names) ? "true"
+ : "false")
+ << std::endl;
+ std::cout << "baseUnit: " << unsigned(pdr->base_unit) << std::endl;
+ std::cout << "unitModifier: " << unsigned(pdr->unit_modifier)
+ << std::endl;
+ std::cout << "rateUnit: " << unsigned(pdr->rate_unit) << std::endl;
+ std::cout << "baseOEMUnitHandle: "
+ << unsigned(pdr->base_oem_unit_handle) << std::endl;
+ std::cout << "auxUnit: " << unsigned(pdr->aux_unit) << std::endl;
+ std::cout << "auxUnitModifier: " << unsigned(pdr->aux_unit_modifier)
+ << std::endl;
+ std::cout << "auxrateUnit: " << unsigned(pdr->aux_rate_unit)
+ << std::endl;
+ std::cout << "auxOEMUnitHandle: " << unsigned(pdr->aux_oem_unit_handle)
+ << std::endl;
+ std::cout << "isLinear: "
+ << (unsigned(pdr->is_linear) ? "true" : "false") << std::endl;
+ std::cout << "effecterDataSize: " << unsigned(pdr->effecter_data_size)
+ << std::endl;
+ std::cout << "resolution: " << pdr->resolution << std::endl;
+ std::cout << "offset: " << pdr->offset << std::endl;
+ std::cout << "accuracy: " << pdr->accuracy << std::endl;
+ std::cout << "plusTolerance: " << unsigned(pdr->plus_tolerance)
+ << std::endl;
+ std::cout << "minusTolerance: " << unsigned(pdr->minus_tolerance)
+ << std::endl;
+ std::cout << "stateTransitionInterval: "
+ << pdr->state_transition_interval << std::endl;
+ std::cout << "TransitionInterval: " << pdr->transition_interval
+ << std::endl;
+ switch (pdr->effecter_data_size)
+ {
+ case PLDM_EFFECTER_DATA_SIZE_UINT8:
+ std::cout << "maxSettable: "
+ << unsigned(pdr->max_set_table.value_u8) << std::endl;
+ std::cout << "minSettable: "
+ << unsigned(pdr->min_set_table.value_u8) << std::endl;
+ break;
+ case PLDM_EFFECTER_DATA_SIZE_SINT8:
+ std::cout << "maxSettable: "
+ << unsigned(pdr->max_set_table.value_s8) << std::endl;
+ std::cout << "minSettable: "
+ << unsigned(pdr->min_set_table.value_s8) << std::endl;
+ break;
+ case PLDM_EFFECTER_DATA_SIZE_UINT16:
+ std::cout << "maxSettable: " << pdr->max_set_table.value_u16
+ << std::endl;
+ std::cout << "minSettable: " << pdr->min_set_table.value_u16
+ << std::endl;
+ break;
+ case PLDM_EFFECTER_DATA_SIZE_SINT16:
+ std::cout << "maxSettable: " << pdr->max_set_table.value_s16
+ << std::endl;
+ std::cout << "minSettable: " << pdr->min_set_table.value_s16
+ << std::endl;
+ break;
+ case PLDM_EFFECTER_DATA_SIZE_UINT32:
+ std::cout << "maxSettable: " << pdr->max_set_table.value_u32
+ << std::endl;
+ std::cout << "minSettable: " << pdr->min_set_table.value_u32
+ << std::endl;
+ break;
+ case PLDM_EFFECTER_DATA_SIZE_SINT32:
+ std::cout << "maxSettable: " << pdr->max_set_table.value_s32
+ << std::endl;
+ std::cout << "minSettable: " << pdr->min_set_table.value_s32
+ << std::endl;
+ break;
+ default:
+ break;
+ }
+ std::cout << "rangeFieldFormat: " << unsigned(pdr->range_field_format)
+ << std::endl;
+ std::cout << "rangeFieldSupport: "
+ << unsigned(pdr->range_field_support.byte) << std::endl;
+ switch (pdr->range_field_format)
+ {
+ case PLDM_RANGE_FIELD_FORMAT_UINT8:
+ std::cout << "nominalValue: "
+ << unsigned(pdr->nominal_value.value_u8) << std::endl;
+ std::cout << "normalMax: " << unsigned(pdr->normal_max.value_u8)
+ << std::endl;
+ std::cout << "normalMin: " << unsigned(pdr->normal_min.value_u8)
+ << std::endl;
+ std::cout << "ratedMax: " << unsigned(pdr->rated_max.value_u8)
+ << std::endl;
+ std::cout << "ratedMin: " << unsigned(pdr->rated_min.value_u8)
+ << std::endl;
+ break;
+ case PLDM_RANGE_FIELD_FORMAT_SINT8:
+ std::cout << "nominalValue: "
+ << unsigned(pdr->nominal_value.value_s8) << std::endl;
+ std::cout << "normalMax: " << unsigned(pdr->normal_max.value_s8)
+ << std::endl;
+ std::cout << "normalMin: " << unsigned(pdr->normal_min.value_s8)
+ << std::endl;
+ std::cout << "ratedMax: " << unsigned(pdr->rated_max.value_s8)
+ << std::endl;
+ std::cout << "ratedMin: " << unsigned(pdr->rated_min.value_s8)
+ << std::endl;
+ break;
+ case PLDM_RANGE_FIELD_FORMAT_UINT16:
+ std::cout << "nominalValue: " << pdr->nominal_value.value_u16
+ << std::endl;
+ std::cout << "normalMax: " << pdr->normal_max.value_u16
+ << std::endl;
+ std::cout << "normalMin: " << pdr->normal_min.value_u16
+ << std::endl;
+ std::cout << "ratedMax: " << pdr->rated_max.value_u16
+ << std::endl;
+ std::cout << "ratedMin: " << pdr->rated_min.value_u16
+ << std::endl;
+ break;
+ case PLDM_RANGE_FIELD_FORMAT_SINT16:
+ std::cout << "nominalValue: " << pdr->nominal_value.value_s16
+ << std::endl;
+ std::cout << "normalMax: " << pdr->normal_max.value_s16
+ << std::endl;
+ std::cout << "normalMin: " << pdr->normal_min.value_s16
+ << std::endl;
+ std::cout << "ratedMax: " << pdr->rated_max.value_s16
+ << std::endl;
+ std::cout << "ratedMin: " << pdr->rated_min.value_s16
+ << std::endl;
+ break;
+ case PLDM_RANGE_FIELD_FORMAT_UINT32:
+ std::cout << "nominalValue: " << pdr->nominal_value.value_u32
+ << std::endl;
+ std::cout << "normalMax: " << pdr->normal_max.value_u32
+ << std::endl;
+ std::cout << "normalMin: " << pdr->normal_min.value_u32
+ << std::endl;
+ std::cout << "ratedMax: " << pdr->rated_max.value_u32
+ << std::endl;
+ std::cout << "ratedMin: " << pdr->rated_min.value_u32
+ << std::endl;
+ break;
+ case PLDM_RANGE_FIELD_FORMAT_SINT32:
+ std::cout << "nominalValue: " << pdr->nominal_value.value_s32
+ << std::endl;
+ std::cout << "normalMax: " << pdr->normal_max.value_s32
+ << std::endl;
+ std::cout << "normalMin: " << pdr->normal_min.value_s32
+ << std::endl;
+ std::cout << "ratedMax: " << pdr->rated_max.value_s32
+ << std::endl;
+ std::cout << "ratedMin: " << pdr->rated_min.value_s32
+ << std::endl;
+ break;
+ case PLDM_RANGE_FIELD_FORMAT_REAL32:
+ std::cout << "nominalValue: " << pdr->nominal_value.value_f32
+ << std::endl;
+ std::cout << "normalMax: " << pdr->normal_max.value_f32
+ << std::endl;
+ std::cout << "normalMin: " << pdr->normal_min.value_f32
+ << std::endl;
+ std::cout << "ratedMax: " << pdr->rated_max.value_f32
+ << std::endl;
+ std::cout << "ratedMin: " << pdr->rated_min.value_f32
+ << std::endl;
+ break;
+ default:
+ break;
+ }
+ }
+
+ void printStateEffecterPDR(uint8_t* data)
+ {
+ if (data == NULL)
+ {
+ return;
+ }
+
+ struct pldm_state_effecter_pdr* pdr =
+ (struct pldm_state_effecter_pdr*)data;
+ printEffecterHdrPDR(&pdr->hdr);
+
+ std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
+ << std::endl;
+ std::cout << "effecterID: " << pdr->effecter_id << std::endl;
+ std::cout << "entityType: " << pdr->entity_type << std::endl;
+ std::cout << "entityInstanceNumber: " << pdr->entity_instance
+ << std::endl;
+ std::cout << "containerID: " << pdr->container_id << std::endl;
+ std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
+ << std::endl;
+ std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
+ << std::endl;
+ std::cout << "effecterDescriptionPDR: "
+ << (unsigned(pdr->has_description_pdr) ? "true" : "false")
+ << std::endl;
+ std::cout << "compositeEffecterCount: "
+ << unsigned(pdr->composite_effecter_count) << std::endl;
+
+ for (size_t i = 0; i < pdr->composite_effecter_count; ++i)
+ {
+ struct state_effecter_possible_states* state =
+ (struct state_effecter_possible_states*)pdr->possible_states +
+ i * sizeof(state_effecter_possible_states);
+ std::cout << "stateSetID: " << state->state_set_id << std::endl;
+ std::cout << "possibleStatesSize: "
+ << unsigned(state->possible_states_size) << std::endl;
+ bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(state->states);
+ std::cout << "possibleStates: " << unsigned(bf->byte) << std::endl;
+ }
+ }
+
+ void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
+ uint8_t* data)
+ {
+ if (data == NULL)
+ {
+ return;
+ }
+
+ std::cout << "nextRecordHandle: " << nextRecordHndl << std::endl;
+ std::cout << "responseCount: " << respCnt << std::endl;
+
+ struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data;
+ std::cout << "recordHandle: " << pdr->record_handle << std::endl;
+ std::cout << "PDRHeaderVersion: " << unsigned(pdr->version)
+ << std::endl;
+ std::cout << "PDRType: " << unsigned(pdr->type) << std::endl;
+ std::cout << "recordChangeNumber: " << pdr->record_change_num
+ << std::endl;
+ std::cout << "dataLength: " << pdr->length << std::endl << std::endl;
+
+ switch (pdr->type)
+ {
+ case PLDM_NUMERIC_EFFECTER_PDR:
+ printNumericEffecterPDR(data);
+ break;
+ case PLDM_STATE_EFFECTER_PDR:
+ printStateEffecterPDR(data);
+ break;
+ case PLDM_PDR_ENTITY_ASSOCIATION:
+ printPDREntityAssociation(data);
+ break;
+ case PLDM_PDR_FRU_RECORD_SET:
+ printPDRFruRecordSet(data);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private:
+ uint32_t recordHandle;
+};
+
+class SetStateEffecter : public CommandInterface
+{
+ public:
+ ~SetStateEffecter() = default;
+ SetStateEffecter() = delete;
+ SetStateEffecter(const SetStateEffecter&) = delete;
+ SetStateEffecter(SetStateEffecter&&) = default;
+ SetStateEffecter& operator=(const SetStateEffecter&) = delete;
+ SetStateEffecter& operator=(SetStateEffecter&&) = default;
+
+ // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2)
+ static constexpr auto maxEffecterDataSize = 16;
+
+ // compositeEffecterCount(value: 0x01 to 0x08)
+ static constexpr auto minEffecterCount = 1;
+ static constexpr auto maxEffecterCount = 8;
+ explicit SetStateEffecter(const char* type, const char* name,
+ CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option(
+ "-i, --id", effecterId,
+ "A handle that is used to identify and access the effecter")
+ ->required();
+ app->add_option("-c, --count", effecterCount,
+ "The number of individual sets of effecter information")
+ ->required();
+ app->add_option(
+ "-d,--data", effecterData,
+ "Set effecter state data\n"
+ "eg: requestSet0 effecterState0 noChange1 dummyState1 ...")
+ ->required();
+ }
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(
+ sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ if (effecterCount > maxEffecterCount ||
+ effecterCount < minEffecterCount)
+ {
+ std::cerr << "Request Message Error: effecterCount size "
+ << effecterCount << "is invalid\n";
+ auto rc = PLDM_ERROR_INVALID_DATA;
+ return {rc, requestMsg};
+ }
+
+ if (effecterData.size() > maxEffecterDataSize)
+ {
+ std::cerr << "Request Message Error: effecterData size "
+ << effecterData.size() << "is invalid\n";
+ auto rc = PLDM_ERROR_INVALID_DATA;
+ return {rc, requestMsg};
+ }
+
+ auto stateField = parseEffecterData(effecterData, effecterCount);
+ if (!stateField)
+ {
+ std::cerr << "Failed to parse effecter data, effecterCount size "
+ << effecterCount << "\n";
+ auto rc = PLDM_ERROR_INVALID_DATA;
+ return {rc, requestMsg};
+ }
+
+ auto rc = encode_set_state_effecter_states_req(
+ instanceId, effecterId, effecterCount, stateField->data(), request);
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t completionCode = 0;
+ auto rc = decode_set_state_effecter_states_resp(
+ responsePtr, payloadLength, &completionCode);
+
+ if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
+ return;
+ }
+
+ std::cout << "SetStateEffecterStates: SUCCESS" << std::endl;
+ }
+
+ private:
+ uint16_t effecterId;
+ uint8_t effecterCount;
+ std::vector<uint8_t> effecterData;
+};
+
+class SetNumericEffecterValue : public CommandInterface
+{
+ public:
+ ~SetNumericEffecterValue() = default;
+ SetNumericEffecterValue() = delete;
+ SetNumericEffecterValue(const SetNumericEffecterValue&) = delete;
+ SetNumericEffecterValue(SetNumericEffecterValue&&) = default;
+ SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete;
+ SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = default;
+
+ explicit SetNumericEffecterValue(const char* type, const char* name,
+ CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option(
+ "-i, --id", effecterId,
+ "A handle that is used to identify and access the effecter")
+ ->required();
+ app->add_option("-s, --size", effecterDataSize,
+ "The bit width and format of the setting value for the "
+ "effecter. enum value: {uint8, sint8, uint16, sint16, "
+ "uint32, sint32}\n")
+ ->required();
+ app->add_option("-d,--data", maxEffecterValue,
+ "The setting value of numeric effecter being "
+ "requested\n")
+ ->required();
+ }
+
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+ {
+ std::vector<uint8_t> requestMsg(
+ sizeof(pldm_msg_hdr) +
+ PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3);
+
+ uint8_t* effecterValue = (uint8_t*)&maxEffecterValue;
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES;
+
+ if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
+ effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
+ {
+ payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1;
+ }
+ if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
+ effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
+ {
+ payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3;
+ }
+ auto rc = encode_set_numeric_effecter_value_req(
+ 0, effecterId, effecterDataSize, effecterValue, request,
+ payload_length);
+
+ return {rc, requestMsg};
+ }
+
+ void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+ {
+ uint8_t completionCode = 0;
+ auto rc = decode_set_numeric_effecter_value_resp(
+ responsePtr, payloadLength, &completionCode);
+
+ if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
+ {
+ std::cerr << "Response Message Error: "
+ << "rc=" << rc << ",cc=" << (int)completionCode
+ << std::endl;
+ return;
+ }
+
+ std::cout << "SetNumericEffecterValue: SUCCESS" << std::endl;
+ }
+
+ private:
+ uint16_t effecterId;
+ uint8_t effecterDataSize;
+ uint64_t maxEffecterValue;
+};
+
+void registerCommand(CLI::App& app)
+{
+ auto platform = app.add_subcommand("platform", "platform type command");
+ platform->require_subcommand(1);
+
+ auto getPDR =
+ platform->add_subcommand("GetPDR", "get platform descriptor records");
+ commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR));
+
+ auto setStateEffecterStates = platform->add_subcommand(
+ "SetStateEffecterStates", "set effecter states");
+ commands.push_back(std::make_unique<SetStateEffecter>(
+ "platform", "setStateEffecterStates", setStateEffecterStates));
+
+ auto setNumericEffecterValue = platform->add_subcommand(
+ "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter");
+ commands.push_back(std::make_unique<SetNumericEffecterValue>(
+ "platform", "setNumericEffecterValue", setNumericEffecterValue));
+}
+
+} // namespace platform
+} // namespace pldmtool
diff --git a/pldmtool/pldm_platform_cmd.hpp b/pldmtool/pldm_platform_cmd.hpp
new file mode 100644
index 0000000..45f15ba
--- /dev/null
+++ b/pldmtool/pldm_platform_cmd.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <CLI/CLI.hpp>
+
+namespace pldmtool
+{
+
+namespace platform
+{
+
+void registerCommand(CLI::App& app);
+
+} // namespace platform
+
+} // namespace pldmtool
diff --git a/pldmtool/pldmtool.cpp b/pldmtool/pldmtool.cpp
new file mode 100644
index 0000000..4b65b2a
--- /dev/null
+++ b/pldmtool/pldmtool.cpp
@@ -0,0 +1,82 @@
+#include "pldm_base_cmd.hpp"
+#include "pldm_bios_cmd.hpp"
+#include "pldm_cmd_helper.hpp"
+#include "pldm_fru_cmd.hpp"
+#include "pldm_platform_cmd.hpp"
+#include "pldmtool/oem/ibm/pldm_host_cmd.hpp"
+
+#include <CLI/CLI.hpp>
+
+namespace pldmtool
+{
+
+namespace raw
+{
+
+using namespace pldmtool::helper;
+
+namespace
+{
+std::vector<std::unique_ptr<CommandInterface>> commands;
+}
+
+class RawOp : public CommandInterface
+{
+ public:
+ ~RawOp() = default;
+ RawOp() = delete;
+ RawOp(const RawOp&) = delete;
+ RawOp(RawOp&&) = default;
+ RawOp& operator=(const RawOp&) = delete;
+ RawOp& operator=(RawOp&&) = default;
+
+ explicit RawOp(const char* type, const char* name, CLI::App* app) :
+ CommandInterface(type, name, app)
+ {
+ app->add_option("-d,--data", rawData, "raw data")
+ ->required()
+ ->expected(-3);
+ }
+ std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+
+ {
+ return {PLDM_SUCCESS, rawData};
+ }
+
+ void parseResponseMsg(pldm_msg* /* responsePtr */,
+ size_t /* payloadLength */) override
+ {}
+
+ private:
+ std::vector<uint8_t> rawData;
+};
+
+void registerCommand(CLI::App& app)
+{
+ auto raw =
+ app.add_subcommand("raw", "send a raw request and print response");
+ commands.push_back(std::make_unique<RawOp>("raw", "raw", raw));
+}
+
+} // namespace raw
+} // namespace pldmtool
+
+int main(int argc, char** argv)
+{
+
+ CLI::App app{"PLDM requester tool for OpenBMC"};
+ app.require_subcommand(1)->ignore_case();
+
+ pldmtool::raw::registerCommand(app);
+ pldmtool::base::registerCommand(app);
+ pldmtool::bios::registerCommand(app);
+ pldmtool::platform::registerCommand(app);
+ pldmtool::fru::registerCommand(app);
+
+#ifdef OEM_IBM
+ pldmtool::oem_ibm::power_host::registerCommand(app);
+#endif
+
+ CLI11_PARSE(app, argc, argv);
+ return 0;
+}