1 #include "libpldm/entity.h" 2 #include "libpldm/state_set.h" 3 4 #include "common/types.hpp" 5 #include "pldm_cmd_helper.hpp" 6 7 namespace pldmtool 8 { 9 10 namespace platform 11 { 12 13 namespace 14 { 15 16 using namespace pldmtool::helper; 17 std::vector<std::unique_ptr<CommandInterface>> commands; 18 19 } // namespace 20 21 using ordered_json = nlohmann::ordered_json; 22 23 class GetPDR : public CommandInterface 24 { 25 public: 26 ~GetPDR() = default; 27 GetPDR() = delete; 28 GetPDR(const GetPDR&) = delete; 29 GetPDR(GetPDR&&) = default; 30 GetPDR& operator=(const GetPDR&) = delete; 31 GetPDR& operator=(GetPDR&&) = default; 32 33 using CommandInterface::CommandInterface; 34 35 explicit GetPDR(const char* type, const char* name, CLI::App* app) : 36 CommandInterface(type, name, app) 37 { 38 app->add_option( 39 "-d,--data", recordHandle, 40 "retrieve individual PDRs from a PDR Repository\n" 41 "eg: The recordHandle value for the PDR to be retrieved and 0 " 42 "means get first PDR in the repository.") 43 ->required(); 44 } 45 46 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 47 { 48 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 49 PLDM_GET_PDR_REQ_BYTES); 50 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 51 52 auto rc = 53 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART, 54 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES); 55 return {rc, requestMsg}; 56 } 57 58 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 59 { 60 uint8_t completionCode = 0; 61 uint8_t recordData[UINT16_MAX] = {0}; 62 uint32_t nextRecordHndl = 0; 63 uint32_t nextDataTransferHndl = 0; 64 uint8_t transferFlag = 0; 65 uint16_t respCnt = 0; 66 uint8_t transferCRC = 0; 67 68 auto rc = decode_get_pdr_resp( 69 responsePtr, payloadLength, &completionCode, &nextRecordHndl, 70 &nextDataTransferHndl, &transferFlag, &respCnt, recordData, 71 sizeof(recordData), &transferCRC); 72 73 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 74 { 75 std::cerr << "Response Message Error: " 76 << "rc=" << rc << ",cc=" << (int)completionCode 77 << std::endl; 78 return; 79 } 80 81 printPDRMsg(nextRecordHndl, respCnt, recordData); 82 } 83 84 private: 85 const std::map<pldm::pdr::EntityType, std::string> entityType = { 86 {PLDM_ENTITY_COMM_CHANNEL, "Communication Channel"}, 87 {PLDM_ENTITY_SYS_FIRMWARE, "System Firmware"}, 88 {PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER, "Virtual Machine Manager"}, 89 {PLDM_ENTITY_SYSTEM_CHASSIS, "System chassis (main enclosure)"}, 90 {PLDM_ENTITY_SYS_BOARD, "System Board"}, 91 {PLDM_ENTITY_MEMORY_MODULE, "Memory Module"}, 92 {PLDM_ENTITY_PROC_MODULE, "Processor Module"}, 93 {PLDM_ENTITY_CHASSIS_FRONT_PANEL_BOARD, 94 "Chassis front panel board (control panel)"}, 95 {PLDM_ENTITY_POWER_CONVERTER, "Power converter"}, 96 {PLDM_ENTITY_PROC, "Processor"}, 97 {PLDM_ENTITY_MGMT_CONTROLLER, "Management Controller"}, 98 {PLDM_ENTITY_CONNECTOR, "Connector"}, 99 {PLDM_ENTITY_POWER_SUPPLY, "Power Supply"}, 100 {11521, "System (logical)"}, 101 }; 102 103 const std::map<uint16_t, std::string> stateSet = { 104 {PLDM_STATE_SET_HEALTH_STATE, "Health State"}, 105 {PLDM_STATE_SET_AVAILABILITY, "Availability"}, 106 {PLDM_STATE_SET_OPERATIONAL_STATUS, "Operational Status"}, 107 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 108 "Operational Running Status"}, 109 {PLDM_STATE_SET_PRESENCE, "Presence"}, 110 {PLDM_STATE_SET_CONFIGURATION_STATE, "Configuration State"}, 111 {PLDM_STATE_SET_LINK_STATE, "Link State"}, 112 {PLDM_STATE_SET_SW_TERMINATION_STATUS, "Software Termination Status"}, 113 {PLDM_STATE_SET_BOOT_RESTART_CAUSE, "Boot/Restart Cause"}, 114 {PLDM_STATE_SET_BOOT_PROGRESS, "Boot Progress"}, 115 {PLDM_STATE_SET_SYSTEM_POWER_STATE, "System Power State"}, 116 }; 117 118 const std::array<std::string_view, 4> sensorInit = { 119 "noInit", "useInitPDR", "enableSensor", "disableSensor"}; 120 121 const std::array<std::string_view, 4> effecterInit = { 122 "noInit", "useInitPDR", "enableEffecter", "disableEffecter"}; 123 124 const std::map<uint8_t, std::string> pdrType = { 125 {PLDM_TERMINUS_LOCATOR_PDR, "Terminus Locator PDR"}, 126 {PLDM_NUMERIC_SENSOR_PDR, "Numeric Sensor PDR"}, 127 {PLDM_NUMERIC_SENSOR_INITIALIZATION_PDR, 128 "Numeric Sensor Initialization PDR"}, 129 {PLDM_STATE_SENSOR_PDR, "State Sensor PDR"}, 130 {PLDM_STATE_SENSOR_INITIALIZATION_PDR, 131 "State Sensor Initialization PDR"}, 132 {PLDM_SENSOR_AUXILIARY_NAMES_PDR, "Sensor Auxiliary Names PDR"}, 133 {PLDM_OEM_UNIT_PDR, "OEM Unit PDR"}, 134 {PLDM_OEM_STATE_SET_PDR, "OEM State Set PDR"}, 135 {PLDM_NUMERIC_EFFECTER_PDR, "Numeric Effecter PDR"}, 136 {PLDM_NUMERIC_EFFECTER_INITIALIZATION_PDR, 137 "Numeric Effecter Initialization PDR"}, 138 {PLDM_STATE_EFFECTER_PDR, "State Effecter PDR"}, 139 {PLDM_STATE_EFFECTER_INITIALIZATION_PDR, 140 "State Effecter Initialization PDR"}, 141 {PLDM_EFFECTER_AUXILIARY_NAMES_PDR, "Effecter Auxiliary Names PDR"}, 142 {PLDM_EFFECTER_OEM_SEMANTIC_PDR, "Effecter OEM Semantic PDR"}, 143 {PLDM_PDR_ENTITY_ASSOCIATION, "Entity Association PDR"}, 144 {PLDM_ENTITY_AUXILIARY_NAMES_PDR, "Entity Auxiliary Names PDR"}, 145 {PLDM_OEM_ENTITY_ID_PDR, "OEM Entity ID PDR"}, 146 {PLDM_INTERRUPT_ASSOCIATION_PDR, "Interrupt Association PDR"}, 147 {PLDM_EVENT_LOG_PDR, "PLDM Event Log PDR"}, 148 {PLDM_PDR_FRU_RECORD_SET, "FRU Record Set PDR"}, 149 {PLDM_OEM_DEVICE_PDR, "OEM Device PDR"}, 150 {PLDM_OEM_PDR, "OEM PDR"}, 151 }; 152 153 std::string getEntityName(pldm::pdr::EntityType type) 154 { 155 try 156 { 157 return entityType.at(type); 158 } 159 catch (const std::out_of_range& e) 160 { 161 return std::to_string(static_cast<unsigned>(type)) + "(OEM)"; 162 } 163 } 164 165 std::string getStateSetName(uint16_t id) 166 { 167 auto typeString = std::to_string(id); 168 try 169 { 170 return stateSet.at(id) + "(" + typeString + ")"; 171 } 172 catch (const std::out_of_range& e) 173 { 174 return typeString; 175 } 176 } 177 178 std::string getPDRType(uint8_t type) 179 { 180 auto typeString = std::to_string(type); 181 try 182 { 183 return pdrType.at(type); 184 } 185 catch (const std::out_of_range& e) 186 { 187 return typeString; 188 } 189 } 190 191 void printCommonPDRHeader(const pldm_pdr_hdr* hdr, ordered_json& output) 192 { 193 output["recordHandle"] = hdr->record_handle; 194 output["PDRHeaderVersion"] = unsigned(hdr->version); 195 output["PDRType"] = getPDRType(hdr->type); 196 output["recordChangeNumber"] = hdr->record_change_num; 197 output["dataLength"] = hdr->length; 198 } 199 200 std::string printPossibleStates(uint8_t possibleStatesSize, 201 const bitfield8_t* states) 202 { 203 uint8_t possibleStatesPos{}; 204 std::string data; 205 auto printStates = [&possibleStatesPos, &data](const bitfield8_t& val) { 206 std::stringstream pstates; 207 for (int i = 0; i < CHAR_BIT; i++) 208 { 209 if (val.byte & (1 << i)) 210 { 211 pstates << " " << (possibleStatesPos * CHAR_BIT + i); 212 data.append(pstates.str()); 213 pstates.str(""); 214 } 215 } 216 possibleStatesPos++; 217 }; 218 std::for_each(states, states + possibleStatesSize, printStates); 219 return data; 220 } 221 222 void printStateSensorPDR(const uint8_t* data, ordered_json& output) 223 { 224 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(data); 225 output["PLDMTerminusHandle"] = pdr->terminus_handle; 226 output["sensorID"] = pdr->sensor_id; 227 output["entityType"] = getEntityName(pdr->entity_type); 228 output["entityInstanceNumber"] = pdr->entity_instance; 229 output["containerID"] = pdr->container_id; 230 output["sensorInit"] = sensorInit[pdr->sensor_init]; 231 output["sensorAuxiliaryNamesPDR"] = 232 (pdr->sensor_auxiliary_names_pdr ? true : false); 233 output["compositeSensorCount"] = unsigned(pdr->composite_sensor_count); 234 235 auto statesPtr = pdr->possible_states; 236 auto compCount = pdr->composite_sensor_count; 237 238 while (compCount--) 239 { 240 auto state = reinterpret_cast<const state_sensor_possible_states*>( 241 statesPtr); 242 output.emplace(("stateSetID[" + std::to_string(compCount) + "]"), 243 getStateSetName(state->state_set_id)); 244 output.emplace( 245 ("possibleStatesSize[" + std::to_string(compCount) + "]"), 246 state->possible_states_size); 247 output.emplace( 248 ("possibleStates[" + std::to_string(compCount) + "]"), 249 printPossibleStates(state->possible_states_size, 250 state->states)); 251 252 if (compCount) 253 { 254 statesPtr += sizeof(state_sensor_possible_states) + 255 state->possible_states_size - 1; 256 } 257 } 258 } 259 260 void printPDRFruRecordSet(uint8_t* data, ordered_json& output) 261 { 262 if (data == NULL) 263 { 264 return; 265 } 266 267 data += sizeof(pldm_pdr_hdr); 268 pldm_pdr_fru_record_set* pdr = 269 reinterpret_cast<pldm_pdr_fru_record_set*>(data); 270 271 output["PLDMTerminusHandle"] = unsigned(pdr->terminus_handle); 272 output["FRURecordSetIdentifier"] = unsigned(pdr->fru_rsi); 273 output["entityType"] = getEntityName(pdr->entity_type); 274 output["entityInstanceNumber"] = unsigned(pdr->entity_instance_num); 275 output["containerID"] = unsigned(pdr->container_id); 276 } 277 278 void printPDREntityAssociation(uint8_t* data, ordered_json& output) 279 { 280 const std::map<uint8_t, const char*> assocationType = { 281 {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"}, 282 {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"}, 283 }; 284 285 if (data == NULL) 286 { 287 return; 288 } 289 290 data += sizeof(pldm_pdr_hdr); 291 pldm_pdr_entity_association* pdr = 292 reinterpret_cast<pldm_pdr_entity_association*>(data); 293 294 output["containerID"] = int(pdr->container_id); 295 output["associationType"] = assocationType.at(pdr->association_type); 296 output["containerEntityType"] = 297 getEntityName(pdr->container.entity_type); 298 output["containerEntityInstanceNumber"] = 299 int(pdr->container.entity_instance_num); 300 output["containerEntityContainerID"] = 301 int(pdr->container.entity_container_id); 302 output["containedEntityCount"] = 303 static_cast<unsigned>(pdr->num_children); 304 305 auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]); 306 for (int i = 0; i < pdr->num_children; ++i) 307 { 308 output.emplace("containedEntityType[" + std::to_string(i + 1) + "]", 309 getEntityName(child->entity_type)); 310 output.emplace("containedEntityInstanceNumber[" + 311 std::to_string(i + 1) + "]", 312 unsigned(child->entity_instance_num)); 313 output.emplace("containedEntityContainerID[" + 314 std::to_string(i + 1) + "]", 315 unsigned(child->entity_container_id)); 316 317 ++child; 318 } 319 } 320 321 void printNumericEffecterPDR(uint8_t* data, ordered_json& output) 322 { 323 struct pldm_numeric_effecter_value_pdr* pdr = 324 (struct pldm_numeric_effecter_value_pdr*)data; 325 326 output["PLDMTerminusHandle"] = int(pdr->terminus_handle); 327 output["effecterID"] = int(pdr->effecter_id); 328 output["entityType"] = int(pdr->entity_type); 329 output["entityInstanceNumber"] = int(pdr->entity_instance); 330 output["containerID"] = int(pdr->container_id); 331 output["effecterSemanticID"] = int(pdr->effecter_semantic_id); 332 output["effecterInit"] = unsigned(pdr->effecter_init); 333 output["effecterAuxiliaryNames"] = 334 (unsigned(pdr->effecter_auxiliary_names) ? true : false); 335 output["baseUnit"] = unsigned(pdr->base_unit); 336 output["unitModifier"] = unsigned(pdr->unit_modifier); 337 output["rateUnit"] = unsigned(pdr->rate_unit); 338 output["baseOEMUnitHandle"] = unsigned(pdr->base_oem_unit_handle); 339 output["auxUnit"] = unsigned(pdr->aux_unit); 340 output["auxUnitModifier"] = unsigned(pdr->aux_unit_modifier); 341 output["auxrateUnit"] = unsigned(pdr->aux_rate_unit); 342 output["auxOEMUnitHandle"] = unsigned(pdr->aux_oem_unit_handle); 343 output["isLinear"] = (unsigned(pdr->is_linear) ? true : false); 344 output["effecterDataSize"] = unsigned(pdr->effecter_data_size); 345 output["resolution"] = unsigned(pdr->resolution); 346 output["offset"] = unsigned(pdr->offset); 347 output["accuracy"] = unsigned(pdr->accuracy); 348 output["plusTolerance"] = unsigned(pdr->plus_tolerance); 349 output["minusTolerance"] = unsigned(pdr->minus_tolerance); 350 output["stateTransitionInterval"] = 351 unsigned(pdr->state_transition_interval); 352 output["TransitionInterval"] = unsigned(pdr->transition_interval); 353 354 switch (pdr->effecter_data_size) 355 { 356 case PLDM_EFFECTER_DATA_SIZE_UINT8: 357 output["maxSettable"] = unsigned(pdr->max_set_table.value_u8); 358 output["minSettable"] = unsigned(pdr->min_set_table.value_u8); 359 break; 360 case PLDM_EFFECTER_DATA_SIZE_SINT8: 361 output["maxSettable"] = unsigned(pdr->max_set_table.value_s8); 362 output["minSettable"] = unsigned(pdr->min_set_table.value_s8); 363 break; 364 case PLDM_EFFECTER_DATA_SIZE_UINT16: 365 output["maxSettable"] = unsigned(pdr->max_set_table.value_u16); 366 output["minSettable"] = unsigned(pdr->min_set_table.value_u16); 367 break; 368 case PLDM_EFFECTER_DATA_SIZE_SINT16: 369 output["maxSettable"] = unsigned(pdr->max_set_table.value_s16); 370 output["minSettable"] = unsigned(pdr->min_set_table.value_s16); 371 break; 372 case PLDM_EFFECTER_DATA_SIZE_UINT32: 373 output["maxSettable"] = unsigned(pdr->max_set_table.value_u32); 374 output["minSettable"] = unsigned(pdr->min_set_table.value_u32); 375 break; 376 case PLDM_EFFECTER_DATA_SIZE_SINT32: 377 output["maxSettable"] = unsigned(pdr->max_set_table.value_s32); 378 output["minSettable"] = unsigned(pdr->min_set_table.value_s32); 379 break; 380 default: 381 break; 382 } 383 384 output["rangeFieldFormat"] = unsigned(pdr->range_field_format); 385 output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte); 386 387 switch (pdr->range_field_format) 388 { 389 case PLDM_RANGE_FIELD_FORMAT_UINT8: 390 output["nominalValue"] = unsigned(pdr->nominal_value.value_u8); 391 output["normalMax"] = unsigned(pdr->normal_max.value_u8); 392 output["normalMin"] = unsigned(pdr->normal_min.value_u8); 393 output["ratedMax"] = unsigned(pdr->rated_max.value_u8); 394 output["ratedMin"] = unsigned(pdr->rated_min.value_u8); 395 break; 396 case PLDM_RANGE_FIELD_FORMAT_SINT8: 397 output["nominalValue"] = unsigned(pdr->nominal_value.value_s8); 398 output["normalMax"] = unsigned(pdr->normal_max.value_s8); 399 output["normalMin"] = unsigned(pdr->normal_min.value_s8); 400 output["ratedMax"] = unsigned(pdr->rated_max.value_s8); 401 output["ratedMin"] = unsigned(pdr->rated_min.value_s8); 402 break; 403 case PLDM_RANGE_FIELD_FORMAT_UINT16: 404 output["nominalValue"] = unsigned(pdr->nominal_value.value_u16); 405 output["normalMax"] = unsigned(pdr->normal_max.value_u16); 406 output["normalMin"] = unsigned(pdr->normal_min.value_u16); 407 output["ratedMax"] = unsigned(pdr->rated_max.value_u16); 408 output["ratedMin"] = unsigned(pdr->rated_min.value_u16); 409 break; 410 case PLDM_RANGE_FIELD_FORMAT_SINT16: 411 output["nominalValue"] = unsigned(pdr->nominal_value.value_s16); 412 output["normalMax"] = unsigned(pdr->normal_max.value_s16); 413 output["normalMin"] = unsigned(pdr->normal_min.value_s16); 414 output["ratedMax"] = unsigned(pdr->rated_max.value_s16); 415 output["ratedMin"] = unsigned(pdr->rated_min.value_s16); 416 break; 417 case PLDM_RANGE_FIELD_FORMAT_UINT32: 418 output["nominalValue"] = unsigned(pdr->nominal_value.value_u32); 419 output["normalMax"] = unsigned(pdr->normal_max.value_u32); 420 output["normalMin"] = unsigned(pdr->normal_min.value_u32); 421 output["ratedMax"] = unsigned(pdr->rated_max.value_u32); 422 output["ratedMin"] = unsigned(pdr->rated_min.value_u32); 423 break; 424 case PLDM_RANGE_FIELD_FORMAT_SINT32: 425 output["nominalValue"] = unsigned(pdr->nominal_value.value_s32); 426 output["normalMax"] = unsigned(pdr->normal_max.value_s32); 427 output["normalMin"] = unsigned(pdr->normal_min.value_s32); 428 output["ratedMax"] = unsigned(pdr->rated_max.value_s32); 429 output["ratedMin"] = unsigned(pdr->rated_min.value_s32); 430 break; 431 case PLDM_RANGE_FIELD_FORMAT_REAL32: 432 output["nominalValue"] = unsigned(pdr->nominal_value.value_f32); 433 output["normalMax"] = unsigned(pdr->normal_max.value_f32); 434 output["normalMin"] = unsigned(pdr->normal_min.value_f32); 435 output["ratedMax"] = unsigned(pdr->rated_max.value_f32); 436 output["ratedMin"] = unsigned(pdr->rated_min.value_f32); 437 break; 438 default: 439 break; 440 } 441 } 442 443 void printStateEffecterPDR(const uint8_t* data, ordered_json& output) 444 { 445 auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(data); 446 447 output["PLDMTerminusHandle"] = pdr->terminus_handle; 448 output["effecterID"] = pdr->effecter_id; 449 output["entityType"] = getEntityName(pdr->entity_type); 450 output["entityInstanceNumber"] = pdr->entity_instance; 451 output["containerID"] = pdr->container_id; 452 output["effecterSemanticID"] = pdr->effecter_semantic_id; 453 output["effecterInit"] = effecterInit[pdr->effecter_init]; 454 output["effecterDescriptionPDR"] = 455 (pdr->has_description_pdr ? true : false); 456 output["compositeEffecterCount"] = 457 unsigned(pdr->composite_effecter_count); 458 459 auto statesPtr = pdr->possible_states; 460 auto compEffCount = pdr->composite_effecter_count; 461 462 while (compEffCount--) 463 { 464 auto state = 465 reinterpret_cast<const state_effecter_possible_states*>( 466 statesPtr); 467 output.emplace(("stateSetID[" + std::to_string(compEffCount) + "]"), 468 getStateSetName(state->state_set_id)); 469 output.emplace( 470 ("possibleStatesSize[" + std::to_string(compEffCount) + "]"), 471 state->possible_states_size); 472 output.emplace( 473 ("possibleStates[" + std::to_string(compEffCount) + "]"), 474 printPossibleStates(state->possible_states_size, 475 state->states)); 476 477 if (compEffCount) 478 { 479 statesPtr += sizeof(state_effecter_possible_states) + 480 state->possible_states_size - 1; 481 } 482 } 483 } 484 485 void printTerminusLocatorPDR(const uint8_t* data, ordered_json& output) 486 { 487 const std::array<std::string_view, 4> terminusLocatorType = { 488 "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"}; 489 490 auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data); 491 492 output["PLDMTerminusHandle"] = pdr->terminus_handle; 493 output["validity"] = (pdr->validity ? "valid" : "notValid"); 494 output["TID"] = unsigned(pdr->tid); 495 output["containerID"] = pdr->container_id; 496 output["terminusLocatorType"] = 497 terminusLocatorType[pdr->terminus_locator_type]; 498 output["terminusLocatorValueSize"] = 499 unsigned(pdr->terminus_locator_value_size); 500 501 if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID) 502 { 503 auto locatorValue = 504 reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>( 505 pdr->terminus_locator_value); 506 output["EID"] = unsigned(locatorValue->eid); 507 } 508 } 509 510 void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt, 511 uint8_t* data) 512 { 513 if (data == NULL) 514 { 515 return; 516 } 517 518 ordered_json output; 519 output["nextRecordHandle"] = nextRecordHndl; 520 output["responseCount"] = respCnt; 521 522 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; 523 printCommonPDRHeader(pdr, output); 524 525 switch (pdr->type) 526 { 527 case PLDM_TERMINUS_LOCATOR_PDR: 528 printTerminusLocatorPDR(data, output); 529 break; 530 case PLDM_STATE_SENSOR_PDR: 531 printStateSensorPDR(data, output); 532 break; 533 case PLDM_NUMERIC_EFFECTER_PDR: 534 printNumericEffecterPDR(data, output); 535 break; 536 case PLDM_STATE_EFFECTER_PDR: 537 printStateEffecterPDR(data, output); 538 break; 539 case PLDM_PDR_ENTITY_ASSOCIATION: 540 printPDREntityAssociation(data, output); 541 break; 542 case PLDM_PDR_FRU_RECORD_SET: 543 printPDRFruRecordSet(data, output); 544 break; 545 default: 546 break; 547 } 548 pldmtool::helper::DisplayInJson(output); 549 } 550 551 private: 552 uint32_t recordHandle; 553 }; 554 555 class SetStateEffecter : public CommandInterface 556 { 557 public: 558 ~SetStateEffecter() = default; 559 SetStateEffecter() = delete; 560 SetStateEffecter(const SetStateEffecter&) = delete; 561 SetStateEffecter(SetStateEffecter&&) = default; 562 SetStateEffecter& operator=(const SetStateEffecter&) = delete; 563 SetStateEffecter& operator=(SetStateEffecter&&) = default; 564 565 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2) 566 static constexpr auto maxEffecterDataSize = 16; 567 568 // compositeEffecterCount(value: 0x01 to 0x08) 569 static constexpr auto minEffecterCount = 1; 570 static constexpr auto maxEffecterCount = 8; 571 explicit SetStateEffecter(const char* type, const char* name, 572 CLI::App* app) : 573 CommandInterface(type, name, app) 574 { 575 app->add_option( 576 "-i, --id", effecterId, 577 "A handle that is used to identify and access the effecter") 578 ->required(); 579 app->add_option("-c, --count", effecterCount, 580 "The number of individual sets of effecter information") 581 ->required(); 582 app->add_option( 583 "-d,--data", effecterData, 584 "Set effecter state data\n" 585 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...") 586 ->required(); 587 } 588 589 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 590 { 591 std::vector<uint8_t> requestMsg( 592 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES); 593 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 594 595 if (effecterCount > maxEffecterCount || 596 effecterCount < minEffecterCount) 597 { 598 std::cerr << "Request Message Error: effecterCount size " 599 << effecterCount << "is invalid\n"; 600 auto rc = PLDM_ERROR_INVALID_DATA; 601 return {rc, requestMsg}; 602 } 603 604 if (effecterData.size() > maxEffecterDataSize) 605 { 606 std::cerr << "Request Message Error: effecterData size " 607 << effecterData.size() << "is invalid\n"; 608 auto rc = PLDM_ERROR_INVALID_DATA; 609 return {rc, requestMsg}; 610 } 611 612 auto stateField = parseEffecterData(effecterData, effecterCount); 613 if (!stateField) 614 { 615 std::cerr << "Failed to parse effecter data, effecterCount size " 616 << effecterCount << "\n"; 617 auto rc = PLDM_ERROR_INVALID_DATA; 618 return {rc, requestMsg}; 619 } 620 621 auto rc = encode_set_state_effecter_states_req( 622 instanceId, effecterId, effecterCount, stateField->data(), request); 623 return {rc, requestMsg}; 624 } 625 626 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 627 { 628 uint8_t completionCode = 0; 629 auto rc = decode_set_state_effecter_states_resp( 630 responsePtr, payloadLength, &completionCode); 631 632 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 633 { 634 std::cerr << "Response Message Error: " 635 << "rc=" << rc << ",cc=" << (int)completionCode << "\n"; 636 return; 637 } 638 639 ordered_json data; 640 data["Response"] = "SUCCESS"; 641 pldmtool::helper::DisplayInJson(data); 642 } 643 644 private: 645 uint16_t effecterId; 646 uint8_t effecterCount; 647 std::vector<uint8_t> effecterData; 648 }; 649 650 class SetNumericEffecterValue : public CommandInterface 651 { 652 public: 653 ~SetNumericEffecterValue() = default; 654 SetNumericEffecterValue() = delete; 655 SetNumericEffecterValue(const SetNumericEffecterValue&) = delete; 656 SetNumericEffecterValue(SetNumericEffecterValue&&) = default; 657 SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete; 658 SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = default; 659 660 explicit SetNumericEffecterValue(const char* type, const char* name, 661 CLI::App* app) : 662 CommandInterface(type, name, app) 663 { 664 app->add_option( 665 "-i, --id", effecterId, 666 "A handle that is used to identify and access the effecter") 667 ->required(); 668 app->add_option("-s, --size", effecterDataSize, 669 "The bit width and format of the setting value for the " 670 "effecter. enum value: {uint8, sint8, uint16, sint16, " 671 "uint32, sint32}\n") 672 ->required(); 673 app->add_option("-d,--data", maxEffecterValue, 674 "The setting value of numeric effecter being " 675 "requested\n") 676 ->required(); 677 } 678 679 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 680 { 681 std::vector<uint8_t> requestMsg( 682 sizeof(pldm_msg_hdr) + 683 PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3); 684 685 uint8_t* effecterValue = (uint8_t*)&maxEffecterValue; 686 687 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 688 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES; 689 690 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 || 691 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) 692 { 693 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1; 694 } 695 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 || 696 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) 697 { 698 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3; 699 } 700 auto rc = encode_set_numeric_effecter_value_req( 701 0, effecterId, effecterDataSize, effecterValue, request, 702 payload_length); 703 704 return {rc, requestMsg}; 705 } 706 707 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 708 { 709 uint8_t completionCode = 0; 710 auto rc = decode_set_numeric_effecter_value_resp( 711 responsePtr, payloadLength, &completionCode); 712 713 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 714 { 715 std::cerr << "Response Message Error: " 716 << "rc=" << rc << ",cc=" << (int)completionCode 717 << std::endl; 718 return; 719 } 720 721 ordered_json data; 722 data["Response"] = "SUCCESS"; 723 pldmtool::helper::DisplayInJson(data); 724 } 725 726 private: 727 uint16_t effecterId; 728 uint8_t effecterDataSize; 729 uint64_t maxEffecterValue; 730 }; 731 732 void registerCommand(CLI::App& app) 733 { 734 auto platform = app.add_subcommand("platform", "platform type command"); 735 platform->require_subcommand(1); 736 737 auto getPDR = 738 platform->add_subcommand("GetPDR", "get platform descriptor records"); 739 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR)); 740 741 auto setStateEffecterStates = platform->add_subcommand( 742 "SetStateEffecterStates", "set effecter states"); 743 commands.push_back(std::make_unique<SetStateEffecter>( 744 "platform", "setStateEffecterStates", setStateEffecterStates)); 745 746 auto setNumericEffecterValue = platform->add_subcommand( 747 "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter"); 748 commands.push_back(std::make_unique<SetNumericEffecterValue>( 749 "platform", "setNumericEffecterValue", setNumericEffecterValue)); 750 } 751 752 } // namespace platform 753 } // namespace pldmtool 754