1 #include "pldm_base_cmd.hpp" 2 3 #include "pldm_cmd_helper.hpp" 4 5 #include <libpldm/utils.h> 6 7 #ifdef OEM_IBM 8 #include <libpldm/oem/ibm/file_io.h> 9 #include <libpldm/oem/ibm/host.h> 10 #endif 11 12 #include <string> 13 14 namespace pldmtool 15 { 16 17 namespace base 18 { 19 20 namespace 21 { 22 23 using namespace pldmtool::helper; 24 25 std::vector<std::unique_ptr<CommandInterface>> commands; 26 const std::map<const char*, pldm_supported_types> pldmTypes{ 27 {"base", PLDM_BASE}, {"platform", PLDM_PLATFORM}, 28 {"bios", PLDM_BIOS}, {"fru", PLDM_FRU}, 29 #ifdef OEM_IBM 30 {"oem-ibm", PLDM_OEM}, 31 #endif 32 }; 33 34 const std::map<const char*, pldm_supported_commands> pldmBaseCmds{ 35 {"SetTID", PLDM_SET_TID}, 36 {"GetTID", PLDM_GET_TID}, 37 {"GetPLDMVersion", PLDM_GET_PLDM_VERSION}, 38 {"GetPLDMTypes", PLDM_GET_PLDM_TYPES}, 39 {"GetPLDMCommands", PLDM_GET_PLDM_COMMANDS}, 40 {"SelectPLDMVersion", PLDM_SELECT_PLDM_VERSION}, 41 {"NegotiateTransferParameters", PLDM_NEGOTIATE_TRANSFER_PARAMETERS}, 42 {"MultipartSend", PLDM_MULTIPART_SEND}, 43 {"MultipartReceive", PLDM_MULTIPART_RECEIVE}, 44 {"GetMultipartTransferSupport", PLDM_GET_MULTIPART_TRANSFER_SUPPORT}}; 45 46 const std::map<const char*, pldm_bios_commands> pldmBiosCmds{ 47 {"GetBIOSTable", PLDM_GET_BIOS_TABLE}, 48 {"SetBIOSTable", PLDM_SET_BIOS_TABLE}, 49 {"SetBIOSAttributeCurrentValue", PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE}, 50 {"GetBIOSAttributeCurrentValueByHandle", 51 PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE}, 52 {"GetDateTime", PLDM_GET_DATE_TIME}, 53 {"SetDateTime", PLDM_SET_DATE_TIME}}; 54 55 const std::map<const char*, pldm_platform_commands> pldmPlatformCmds{ 56 {"GetTerminusUID", PLDM_GET_TERMINUS_UID}, 57 {"SetEventReceiver", PLDM_SET_EVENT_RECEIVER}, 58 {"GetEventReceiver", PLDM_GET_EVENT_RECEIVER}, 59 {"PlatformEventMessage", PLDM_PLATFORM_EVENT_MESSAGE}, 60 {"PollForPlatformEventMessage", PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE}, 61 {"EventMessageSupported", PLDM_EVENT_MESSAGE_SUPPORTED}, 62 {"EventMessageBufferSize", PLDM_EVENT_MESSAGE_BUFFER_SIZE}, 63 {"SetNumericSensorEnable", PLDM_SET_NUMERIC_SENSOR_ENABLE}, 64 {"GetSensorReading", PLDM_GET_SENSOR_READING}, 65 {"GetSensorThresholds", PLDM_GET_SENSOR_THRESHOLDS}, 66 {"SetSensorThresholds", PLDM_SET_SENSOR_THRESHOLDS}, 67 {"RestoreSensorThresholds", PLDM_RESTORE_SENSOR_THRESHOLDS}, 68 {"GetSensorHysteresis", PLDM_GET_SENSOR_HYSTERESIS}, 69 {"SetSensorHysteresis", PLDM_SET_SENSOR_HYSTERESIS}, 70 {"InitNumericSensor", PLDM_INIT_NUMERIC_SENSOR}, 71 {"SetStateSensorEnables", PLDM_SET_STATE_SENSOR_ENABLES}, 72 {"GetStateSensorReadings", PLDM_GET_STATE_SENSOR_READINGS}, 73 {"InitStateSensor", PLDM_INIT_STATE_SENSOR}, 74 {"SetNumericEffecterEnable", PLDM_SET_NUMERIC_EFFECTER_ENABLE}, 75 {"SetNumericEffecterValue", PLDM_SET_NUMERIC_EFFECTER_VALUE}, 76 {"GetNumericEffecterValue", PLDM_GET_NUMERIC_EFFECTER_VALUE}, 77 {"SetStateEffecterEnables", PLDM_SET_STATE_EFFECTER_ENABLES}, 78 {"SetStateEffecterStates", PLDM_SET_STATE_EFFECTER_STATES}, 79 {"GetStateEffecterStates", PLDM_GET_STATE_EFFECTER_STATES}, 80 {"GetPLDMEventLogInfo", PLDM_GET_PLDM_EVENT_LOG_INFO}, 81 {"EnablePLDMEventLogging", PLDM_ENABLE_PLDM_EVENT_LOGGING}, 82 {"ClearPLDMEventLog", PLDM_CLEAR_PLDM_EVENT_LOG}, 83 {"GetPLDMEventLogTimestamp", PLDM_GET_PLDM_EVENT_LOG_TIMESTAMP}, 84 {"SetPLDMEventLogTimestamp", PLDM_SET_PLDM_EVENT_LOG_TIMESTAMP}, 85 {"ReadPLDMEventLog", PLDM_READ_PLDM_EVENT_LOG}, 86 {"GetPLDMEventLogPolicyInfo", PLDM_GET_PLDM_EVENT_LOG_POLICY_INFO}, 87 {"SetPLDMEventLogPolicy", PLDM_SET_PLDM_EVENT_LOG_POLICY}, 88 {"FindPLDMEventLogEntry", PLDM_FIND_PLDM_EVENT_LOG_ENTRY}, 89 {"GetPDRRepositoryInfo", PLDM_GET_PDR_REPOSITORY_INFO}, 90 {"GetPDR", PLDM_GET_PDR}, 91 {"FindPDR", PLDM_FIND_PDR}, 92 {"RunInitAgent", PLDM_RUN_INIT_AGENT}, 93 {"GetPDRRepositorySignature", PLDM_GET_PDR_REPOSITORY_SIGNATURE}}; 94 95 const std::map<const char*, pldm_fru_commands> pldmFruCmds{ 96 {"GetFRURecordTableMetadata", PLDM_GET_FRU_RECORD_TABLE_METADATA}, 97 {"GetFRURecordTable", PLDM_GET_FRU_RECORD_TABLE}, 98 {"GetFRURecordByOption", PLDM_GET_FRU_RECORD_BY_OPTION}}; 99 100 #ifdef OEM_IBM 101 const std::map<const char*, pldm_host_commands> pldmIBMHostCmds{ 102 {"GetAlertStatus", PLDM_HOST_GET_ALERT_STATUS}}; 103 104 const std::map<const char*, pldm_fileio_commands> pldmIBMFileIOCmds{ 105 {"GetFileTable", PLDM_GET_FILE_TABLE}, 106 {"ReadFile", PLDM_READ_FILE}, 107 {"WriteFile", PLDM_WRITE_FILE}, 108 {"ReadFileInToMemory", PLDM_READ_FILE_INTO_MEMORY}, 109 {"WriteFileFromMemory", PLDM_WRITE_FILE_FROM_MEMORY}, 110 {"ReadFileByTypeIntoMemory", PLDM_READ_FILE_BY_TYPE_INTO_MEMORY}, 111 {"WriteFileByTypeFromMemory", PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY}, 112 {"NewFileAvailable", PLDM_NEW_FILE_AVAILABLE}, 113 {"ReadFileByType", PLDM_READ_FILE_BY_TYPE}, 114 {"WriteFileByType", PLDM_WRITE_FILE_BY_TYPE}, 115 {"FileAck", PLDM_FILE_ACK}}; 116 #endif 117 118 } // namespace 119 120 class GetPLDMTypes : public CommandInterface 121 { 122 public: 123 ~GetPLDMTypes() = default; 124 GetPLDMTypes() = delete; 125 GetPLDMTypes(const GetPLDMTypes&) = delete; 126 GetPLDMTypes(GetPLDMTypes&&) = default; 127 GetPLDMTypes& operator=(const GetPLDMTypes&) = delete; 128 GetPLDMTypes& operator=(GetPLDMTypes&&) = delete; 129 130 using CommandInterface::CommandInterface; 131 132 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 133 { 134 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 135 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 136 auto rc = encode_get_types_req(instanceId, request); 137 return {rc, requestMsg}; 138 } 139 140 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 141 { 142 uint8_t cc = 0; 143 std::vector<bitfield8_t> types(8); 144 auto rc = decode_get_types_resp(responsePtr, payloadLength, &cc, 145 types.data()); 146 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 147 { 148 std::cerr << "Response Message Error: " 149 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 150 return; 151 } 152 153 printPldmTypes(types); 154 } 155 156 private: 157 void printPldmTypes(std::vector<bitfield8_t>& types) 158 { 159 ordered_json data; 160 ordered_json jarray; 161 for (int i = 0; i < PLDM_MAX_TYPES; i++) 162 { 163 bitfield8_t b = types[i / 8]; 164 if (b.byte & (1 << i % 8)) 165 { 166 auto it = std::find_if( 167 pldmTypes.begin(), pldmTypes.end(), 168 [i](const auto& typePair) { return typePair.second == i; }); 169 if (it != pldmTypes.end()) 170 { 171 jarray["PLDM Type"] = it->first; 172 jarray["PLDM Type Code"] = i; 173 data.emplace_back(jarray); 174 } 175 } 176 } 177 pldmtool::helper::DisplayInJson(data); 178 } 179 }; 180 181 class GetPLDMVersion : public CommandInterface 182 { 183 public: 184 ~GetPLDMVersion() = default; 185 GetPLDMVersion() = delete; 186 GetPLDMVersion(const GetPLDMVersion&) = delete; 187 GetPLDMVersion(GetPLDMVersion&&) = default; 188 GetPLDMVersion& operator=(const GetPLDMVersion&) = delete; 189 GetPLDMVersion& operator=(GetPLDMVersion&&) = delete; 190 191 explicit GetPLDMVersion(const char* type, const char* name, CLI::App* app) : 192 CommandInterface(type, name, app) 193 { 194 app->add_option("-t,--type", pldmType, "pldm supported type") 195 ->required() 196 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case)); 197 } 198 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 199 { 200 std::vector<uint8_t> requestMsg( 201 sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES); 202 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 203 204 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART, 205 pldmType, request); 206 return {rc, requestMsg}; 207 } 208 209 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 210 { 211 uint8_t cc = 0, transferFlag = 0; 212 uint32_t transferHandle = 0; 213 ver32_t version; 214 auto rc = 215 decode_get_version_resp(responsePtr, payloadLength, &cc, 216 &transferHandle, &transferFlag, &version); 217 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 218 { 219 std::cerr << "Response Message Error: " 220 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 221 return; 222 } 223 char buffer[16] = {0}; 224 ver2str(&version, buffer, sizeof(buffer)); 225 ordered_json data; 226 auto it = std::find_if( 227 pldmTypes.begin(), pldmTypes.end(), 228 [&](const auto& typePair) { return typePair.second == pldmType; }); 229 230 if (it != pldmTypes.end()) 231 { 232 data["Response"] = buffer; 233 } 234 pldmtool::helper::DisplayInJson(data); 235 } 236 237 private: 238 pldm_supported_types pldmType; 239 }; 240 241 class GetTID : public CommandInterface 242 { 243 public: 244 ~GetTID() = default; 245 GetTID() = delete; 246 GetTID(const GetTID&) = delete; 247 GetTID(GetTID&&) = default; 248 GetTID& operator=(const GetTID&) = delete; 249 GetTID& operator=(GetTID&&) = delete; 250 251 using CommandInterface::CommandInterface; 252 253 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 254 { 255 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 256 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 257 auto rc = encode_get_tid_req(instanceId, request); 258 return {rc, requestMsg}; 259 } 260 261 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 262 { 263 uint8_t cc = 0; 264 uint8_t tid = 0; 265 std::vector<bitfield8_t> types(8); 266 auto rc = decode_get_tid_resp(responsePtr, payloadLength, &cc, &tid); 267 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 268 { 269 std::cerr << "Response Message Error: " 270 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 271 return; 272 } 273 ordered_json data; 274 data["Response"] = static_cast<uint32_t>(tid); 275 pldmtool::helper::DisplayInJson(data); 276 } 277 }; 278 279 class GetPLDMCommands : public CommandInterface 280 { 281 public: 282 ~GetPLDMCommands() = default; 283 GetPLDMCommands() = delete; 284 GetPLDMCommands(const GetPLDMCommands&) = delete; 285 GetPLDMCommands(GetPLDMCommands&&) = default; 286 GetPLDMCommands& operator=(const GetPLDMCommands&) = delete; 287 GetPLDMCommands& operator=(GetPLDMCommands&&) = delete; 288 289 explicit GetPLDMCommands(const char* type, const char* name, 290 CLI::App* app) : CommandInterface(type, name, app) 291 { 292 app->add_option("-t,--type", pldmType, "pldm supported type") 293 ->required() 294 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case)); 295 app->add_option( 296 "-d,--data", inputVersion, 297 "Set PLDM type version. Which is got from GetPLDMVersion\n" 298 "eg: version 1.1.0 then data will be `0xf1 0xf1 0xf0 0x00`"); 299 } 300 301 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 302 { 303 std::vector<uint8_t> requestMsg( 304 sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES); 305 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 306 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF}; 307 if (inputVersion.size() != 0) 308 { 309 if (inputVersion.size() != 4) 310 { 311 std::cerr << "Invalid version format. " 312 << "\n"; 313 } 314 else 315 { 316 version.major = inputVersion[3]; 317 version.minor = inputVersion[2]; 318 version.update = inputVersion[1]; 319 version.alpha = inputVersion[0]; 320 } 321 } 322 auto rc = 323 encode_get_commands_req(instanceId, pldmType, version, request); 324 return {rc, requestMsg}; 325 } 326 327 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 328 { 329 uint8_t cc = 0; 330 std::vector<bitfield8_t> cmdTypes(32); 331 auto rc = decode_get_commands_resp(responsePtr, payloadLength, &cc, 332 cmdTypes.data()); 333 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 334 { 335 std::cerr << "Response Message Error: " 336 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 337 return; 338 } 339 printPldmCommands(cmdTypes, pldmType); 340 } 341 342 private: 343 pldm_supported_types pldmType; 344 std::vector<uint8_t> inputVersion; 345 346 template <typename CommandMap> 347 void printCommand(CommandMap& commandMap, int i, ordered_json& jarray) 348 { 349 auto it = std::find_if( 350 commandMap.begin(), commandMap.end(), 351 [i](const auto& typePair) { return typePair.second == i; }); 352 if (it != commandMap.end()) 353 { 354 jarray["PLDM Command Code"] = i; 355 jarray["PLDM Command"] = it->first; 356 } 357 } 358 359 void printPldmCommands(std::vector<bitfield8_t>& cmdTypes, 360 pldm_supported_types pldmType) 361 { 362 ordered_json output; 363 for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++) 364 { 365 ordered_json cmdinfo; 366 bitfield8_t b = cmdTypes[i / 8]; 367 if (b.byte & (1 << i % 8)) 368 { 369 switch (pldmType) 370 { 371 case PLDM_BASE: 372 printCommand(pldmBaseCmds, i, cmdinfo); 373 break; 374 case PLDM_PLATFORM: 375 printCommand(pldmPlatformCmds, i, cmdinfo); 376 break; 377 case PLDM_BIOS: 378 printCommand(pldmBiosCmds, i, cmdinfo); 379 break; 380 case PLDM_FRU: 381 printCommand(pldmFruCmds, i, cmdinfo); 382 break; 383 case PLDM_OEM: 384 #ifdef OEM_IBM 385 printCommand(pldmIBMHostCmds, i, cmdinfo); 386 printCommand(pldmIBMFileIOCmds, i, cmdinfo); 387 #endif 388 break; 389 default: 390 break; 391 } 392 output.emplace_back(cmdinfo); 393 } 394 } 395 pldmtool::helper::DisplayInJson(output); 396 } 397 }; 398 399 void registerCommand(CLI::App& app) 400 { 401 auto base = app.add_subcommand("base", "base type command"); 402 base->require_subcommand(1); 403 404 auto getPLDMTypes = 405 base->add_subcommand("GetPLDMTypes", "get pldm supported types"); 406 commands.push_back( 407 std::make_unique<GetPLDMTypes>("base", "GetPLDMTypes", getPLDMTypes)); 408 409 auto getPLDMVersion = 410 base->add_subcommand("GetPLDMVersion", "get version of a certain type"); 411 commands.push_back(std::make_unique<GetPLDMVersion>( 412 "base", "GetPLDMVersion", getPLDMVersion)); 413 414 auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)"); 415 commands.push_back(std::make_unique<GetTID>("base", "GetTID", getPLDMTID)); 416 417 auto getPLDMCommands = base->add_subcommand( 418 "GetPLDMCommands", "get supported commands of pldm type"); 419 commands.push_back(std::make_unique<GetPLDMCommands>( 420 "base", "GetPLDMCommands", getPLDMCommands)); 421 } 422 423 } // namespace base 424 } // namespace pldmtool 425