#include "pldm_base_cmd.hpp" #include "pldm_cmd_helper.hpp" #include #ifdef OEM_IBM #include #include #endif #include namespace pldmtool { namespace base { namespace { using namespace pldmtool::helper; std::vector> commands; const std::map pldmTypes{ {"base", PLDM_BASE}, {"platform", PLDM_PLATFORM}, {"bios", PLDM_BIOS}, {"fru", PLDM_FRU}, #ifdef OEM_IBM {"oem-ibm", PLDM_OEM}, #endif }; const std::map pldmBaseCmds{ {"GetTID", PLDM_GET_TID}, {"GetPLDMVersion", PLDM_GET_PLDM_VERSION}, {"GetPLDMTypes", PLDM_GET_PLDM_TYPES}, {"GetPLDMCommands", PLDM_GET_PLDM_COMMANDS}}; const std::map pldmBiosCmds{ {"GetBIOSTable", PLDM_GET_BIOS_TABLE}, {"SetBIOSTable", PLDM_SET_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 pldmPlatformCmds{ {"SetNumericEffecterValue", PLDM_SET_NUMERIC_EFFECTER_VALUE}, {"SetStateEffecterStates", PLDM_SET_STATE_EFFECTER_STATES}, {"GetPDR", PLDM_GET_PDR}, {"GetNumericEffecterValue", PLDM_GET_NUMERIC_EFFECTER_VALUE}, {"SetEventReceiver", PLDM_SET_EVENT_RECEIVER}, {"GetSensorReading", PLDM_GET_SENSOR_READING}, {"GetStateSensorReadings", PLDM_GET_STATE_SENSOR_READINGS}, {"PlatformEventMessage", PLDM_PLATFORM_EVENT_MESSAGE}}; const std::map pldmFruCmds{ {"GetFRURecordTableMetadata", PLDM_GET_FRU_RECORD_TABLE_METADATA}, {"GetFRURecordTable", PLDM_GET_FRU_RECORD_TABLE}, {"GetFRURecordByOption", PLDM_GET_FRU_RECORD_BY_OPTION}}; #ifdef OEM_IBM const std::map pldmIBMHostCmds{ {"GetAlertStatus", PLDM_HOST_GET_ALERT_STATUS}}; const std::map 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&&) = delete; using CommandInterface::CommandInterface; std::pair> createRequestMsg() override { std::vector requestMsg(sizeof(pldm_msg_hdr)); auto request = reinterpret_cast(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 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& types) { ordered_json data; ordered_json jarray; for (int i = 0; i < PLDM_MAX_TYPES; i++) { bitfield8_t b = types[i / 8]; if (b.byte & (1 << i % 8)) { auto it = std::find_if( pldmTypes.begin(), pldmTypes.end(), [i](const auto& typePair) { return typePair.second == i; }); if (it != pldmTypes.end()) { jarray["PLDM Type"] = it->first; jarray["PLDM Type Code"] = i; data.emplace_back(jarray); } } } pldmtool::helper::DisplayInJson(data); } }; class GetPLDMVersion : public CommandInterface { public: ~GetPLDMVersion() = default; GetPLDMVersion() = delete; GetPLDMVersion(const GetPLDMVersion&) = delete; GetPLDMVersion(GetPLDMVersion&&) = default; GetPLDMVersion& operator=(const GetPLDMVersion&) = delete; GetPLDMVersion& operator=(GetPLDMVersion&&) = delete; 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> createRequestMsg() override { std::vector requestMsg(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES); auto request = reinterpret_cast(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)); ordered_json data; auto it = std::find_if( pldmTypes.begin(), pldmTypes.end(), [&](const auto& typePair) { return typePair.second == pldmType; }); if (it != pldmTypes.end()) { data["Response"] = buffer; } pldmtool::helper::DisplayInJson(data); } 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&&) = delete; using CommandInterface::CommandInterface; std::pair> createRequestMsg() override { std::vector requestMsg(sizeof(pldm_msg_hdr)); auto request = reinterpret_cast(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 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; } ordered_json data; data["Response"] = static_cast(tid); pldmtool::helper::DisplayInJson(data); } }; class GetPLDMCommands : public CommandInterface { public: ~GetPLDMCommands() = default; GetPLDMCommands() = delete; GetPLDMCommands(const GetPLDMCommands&) = delete; GetPLDMCommands(GetPLDMCommands&&) = default; GetPLDMCommands& operator=(const GetPLDMCommands&) = delete; GetPLDMCommands& operator=(GetPLDMCommands&&) = delete; 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> createRequestMsg() override { std::vector requestMsg(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES); auto request = reinterpret_cast(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 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 void printCommand(CommandMap& commandMap, int i, ordered_json& jarray) { auto it = std::find_if( commandMap.begin(), commandMap.end(), [i](const auto& typePair) { return typePair.second == i; }); if (it != commandMap.end()) { jarray["PLDM Command Code"] = i; jarray["PLDM Command"] = it->first; } } void printPldmCommands(std::vector& cmdTypes, pldm_supported_types pldmType) { ordered_json output; for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++) { ordered_json cmdinfo; bitfield8_t b = cmdTypes[i / 8]; if (b.byte & (1 << i % 8)) { switch (pldmType) { case PLDM_BASE: printCommand(pldmBaseCmds, i, cmdinfo); break; case PLDM_PLATFORM: printCommand(pldmPlatformCmds, i, cmdinfo); break; case PLDM_BIOS: printCommand(pldmBiosCmds, i, cmdinfo); break; case PLDM_FRU: printCommand(pldmFruCmds, i, cmdinfo); break; case PLDM_OEM: #ifdef OEM_IBM printCommand(pldmIBMHostCmds, i, cmdinfo); printCommand(pldmIBMFileIOCmds, i, cmdinfo); #endif break; default: break; } output.emplace_back(cmdinfo); } } pldmtool::helper::DisplayInJson(output); } }; 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("base", "GetPLDMTypes", getPLDMTypes)); auto getPLDMVersion = base->add_subcommand("GetPLDMVersion", "get version of a certain type"); commands.push_back(std::make_unique( "base", "GetPLDMVersion", getPLDMVersion)); auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)"); commands.push_back(std::make_unique("base", "GetTID", getPLDMTID)); auto getPLDMCommands = base->add_subcommand( "GetPLDMCommands", "get supported commands of pldm type"); commands.push_back(std::make_unique( "base", "GetPLDMCommands", getPLDMCommands)); } } // namespace base } // namespace pldmtool