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