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 if (!pdr) 295 { 296 std::cerr << "Failed to get the FRU record set PDR" << std::endl; 297 return; 298 } 299 300 output["PLDMTerminusHandle"] = unsigned(pdr->terminus_handle); 301 output["FRURecordSetIdentifier"] = unsigned(pdr->fru_rsi); 302 output["entityType"] = getEntityName(pdr->entity_type); 303 output["entityInstanceNumber"] = unsigned(pdr->entity_instance_num); 304 output["containerID"] = unsigned(pdr->container_id); 305 } 306 307 void printPDREntityAssociation(uint8_t* data, ordered_json& output) 308 { 309 const std::map<uint8_t, const char*> assocationType = { 310 {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"}, 311 {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"}, 312 }; 313 314 if (data == NULL) 315 { 316 return; 317 } 318 319 data += sizeof(pldm_pdr_hdr); 320 pldm_pdr_entity_association* pdr = 321 reinterpret_cast<pldm_pdr_entity_association*>(data); 322 if (!pdr) 323 { 324 std::cerr << "Failed to get the PDR eneity association" 325 << std::endl; 326 return; 327 } 328 329 output["containerID"] = int(pdr->container_id); 330 output["associationType"] = assocationType.at(pdr->association_type); 331 output["containerEntityType"] = 332 getEntityName(pdr->container.entity_type); 333 output["containerEntityInstanceNumber"] = 334 int(pdr->container.entity_instance_num); 335 output["containerEntityContainerID"] = 336 int(pdr->container.entity_container_id); 337 output["containedEntityCount"] = 338 static_cast<unsigned>(pdr->num_children); 339 340 auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]); 341 for (int i = 0; i < pdr->num_children; ++i) 342 { 343 output.emplace("containedEntityType[" + std::to_string(i + 1) + "]", 344 getEntityName(child->entity_type)); 345 output.emplace("containedEntityInstanceNumber[" + 346 std::to_string(i + 1) + "]", 347 unsigned(child->entity_instance_num)); 348 output.emplace("containedEntityContainerID[" + 349 std::to_string(i + 1) + "]", 350 unsigned(child->entity_container_id)); 351 352 ++child; 353 } 354 } 355 356 void printNumericEffecterPDR(uint8_t* data, ordered_json& output) 357 { 358 struct pldm_numeric_effecter_value_pdr* pdr = 359 (struct pldm_numeric_effecter_value_pdr*)data; 360 if (!pdr) 361 { 362 std::cerr << "Failed to get numeric effecter PDR" << std::endl; 363 return; 364 } 365 366 output["PLDMTerminusHandle"] = int(pdr->terminus_handle); 367 output["effecterID"] = int(pdr->effecter_id); 368 output["entityType"] = int(pdr->entity_type); 369 output["entityInstanceNumber"] = int(pdr->entity_instance); 370 output["containerID"] = int(pdr->container_id); 371 output["effecterSemanticID"] = int(pdr->effecter_semantic_id); 372 output["effecterInit"] = unsigned(pdr->effecter_init); 373 output["effecterAuxiliaryNames"] = 374 (unsigned(pdr->effecter_auxiliary_names) ? true : false); 375 output["baseUnit"] = unsigned(pdr->base_unit); 376 output["unitModifier"] = unsigned(pdr->unit_modifier); 377 output["rateUnit"] = unsigned(pdr->rate_unit); 378 output["baseOEMUnitHandle"] = unsigned(pdr->base_oem_unit_handle); 379 output["auxUnit"] = unsigned(pdr->aux_unit); 380 output["auxUnitModifier"] = unsigned(pdr->aux_unit_modifier); 381 output["auxrateUnit"] = unsigned(pdr->aux_rate_unit); 382 output["auxOEMUnitHandle"] = unsigned(pdr->aux_oem_unit_handle); 383 output["isLinear"] = (unsigned(pdr->is_linear) ? true : false); 384 output["effecterDataSize"] = unsigned(pdr->effecter_data_size); 385 output["resolution"] = unsigned(pdr->resolution); 386 output["offset"] = unsigned(pdr->offset); 387 output["accuracy"] = unsigned(pdr->accuracy); 388 output["plusTolerance"] = unsigned(pdr->plus_tolerance); 389 output["minusTolerance"] = unsigned(pdr->minus_tolerance); 390 output["stateTransitionInterval"] = 391 unsigned(pdr->state_transition_interval); 392 output["TransitionInterval"] = unsigned(pdr->transition_interval); 393 394 switch (pdr->effecter_data_size) 395 { 396 case PLDM_EFFECTER_DATA_SIZE_UINT8: 397 output["maxSettable"] = unsigned(pdr->max_set_table.value_u8); 398 output["minSettable"] = unsigned(pdr->min_set_table.value_u8); 399 break; 400 case PLDM_EFFECTER_DATA_SIZE_SINT8: 401 output["maxSettable"] = unsigned(pdr->max_set_table.value_s8); 402 output["minSettable"] = unsigned(pdr->min_set_table.value_s8); 403 break; 404 case PLDM_EFFECTER_DATA_SIZE_UINT16: 405 output["maxSettable"] = unsigned(pdr->max_set_table.value_u16); 406 output["minSettable"] = unsigned(pdr->min_set_table.value_u16); 407 break; 408 case PLDM_EFFECTER_DATA_SIZE_SINT16: 409 output["maxSettable"] = unsigned(pdr->max_set_table.value_s16); 410 output["minSettable"] = unsigned(pdr->min_set_table.value_s16); 411 break; 412 case PLDM_EFFECTER_DATA_SIZE_UINT32: 413 output["maxSettable"] = unsigned(pdr->max_set_table.value_u32); 414 output["minSettable"] = unsigned(pdr->min_set_table.value_u32); 415 break; 416 case PLDM_EFFECTER_DATA_SIZE_SINT32: 417 output["maxSettable"] = unsigned(pdr->max_set_table.value_s32); 418 output["minSettable"] = unsigned(pdr->min_set_table.value_s32); 419 break; 420 default: 421 break; 422 } 423 424 output["rangeFieldFormat"] = unsigned(pdr->range_field_format); 425 output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte); 426 427 switch (pdr->range_field_format) 428 { 429 case PLDM_RANGE_FIELD_FORMAT_UINT8: 430 output["nominalValue"] = unsigned(pdr->nominal_value.value_u8); 431 output["normalMax"] = unsigned(pdr->normal_max.value_u8); 432 output["normalMin"] = unsigned(pdr->normal_min.value_u8); 433 output["ratedMax"] = unsigned(pdr->rated_max.value_u8); 434 output["ratedMin"] = unsigned(pdr->rated_min.value_u8); 435 break; 436 case PLDM_RANGE_FIELD_FORMAT_SINT8: 437 output["nominalValue"] = unsigned(pdr->nominal_value.value_s8); 438 output["normalMax"] = unsigned(pdr->normal_max.value_s8); 439 output["normalMin"] = unsigned(pdr->normal_min.value_s8); 440 output["ratedMax"] = unsigned(pdr->rated_max.value_s8); 441 output["ratedMin"] = unsigned(pdr->rated_min.value_s8); 442 break; 443 case PLDM_RANGE_FIELD_FORMAT_UINT16: 444 output["nominalValue"] = unsigned(pdr->nominal_value.value_u16); 445 output["normalMax"] = unsigned(pdr->normal_max.value_u16); 446 output["normalMin"] = unsigned(pdr->normal_min.value_u16); 447 output["ratedMax"] = unsigned(pdr->rated_max.value_u16); 448 output["ratedMin"] = unsigned(pdr->rated_min.value_u16); 449 break; 450 case PLDM_RANGE_FIELD_FORMAT_SINT16: 451 output["nominalValue"] = unsigned(pdr->nominal_value.value_s16); 452 output["normalMax"] = unsigned(pdr->normal_max.value_s16); 453 output["normalMin"] = unsigned(pdr->normal_min.value_s16); 454 output["ratedMax"] = unsigned(pdr->rated_max.value_s16); 455 output["ratedMin"] = unsigned(pdr->rated_min.value_s16); 456 break; 457 case PLDM_RANGE_FIELD_FORMAT_UINT32: 458 output["nominalValue"] = unsigned(pdr->nominal_value.value_u32); 459 output["normalMax"] = unsigned(pdr->normal_max.value_u32); 460 output["normalMin"] = unsigned(pdr->normal_min.value_u32); 461 output["ratedMax"] = unsigned(pdr->rated_max.value_u32); 462 output["ratedMin"] = unsigned(pdr->rated_min.value_u32); 463 break; 464 case PLDM_RANGE_FIELD_FORMAT_SINT32: 465 output["nominalValue"] = unsigned(pdr->nominal_value.value_s32); 466 output["normalMax"] = unsigned(pdr->normal_max.value_s32); 467 output["normalMin"] = unsigned(pdr->normal_min.value_s32); 468 output["ratedMax"] = unsigned(pdr->rated_max.value_s32); 469 output["ratedMin"] = unsigned(pdr->rated_min.value_s32); 470 break; 471 case PLDM_RANGE_FIELD_FORMAT_REAL32: 472 output["nominalValue"] = unsigned(pdr->nominal_value.value_f32); 473 output["normalMax"] = unsigned(pdr->normal_max.value_f32); 474 output["normalMin"] = unsigned(pdr->normal_min.value_f32); 475 output["ratedMax"] = unsigned(pdr->rated_max.value_f32); 476 output["ratedMin"] = unsigned(pdr->rated_min.value_f32); 477 break; 478 default: 479 break; 480 } 481 } 482 483 void printStateEffecterPDR(const uint8_t* data, ordered_json& output) 484 { 485 auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(data); 486 487 output["PLDMTerminusHandle"] = pdr->terminus_handle; 488 output["effecterID"] = pdr->effecter_id; 489 output["entityType"] = getEntityName(pdr->entity_type); 490 output["entityInstanceNumber"] = pdr->entity_instance; 491 output["containerID"] = pdr->container_id; 492 output["effecterSemanticID"] = pdr->effecter_semantic_id; 493 output["effecterInit"] = effecterInit[pdr->effecter_init]; 494 output["effecterDescriptionPDR"] = 495 (pdr->has_description_pdr ? true : false); 496 output["compositeEffecterCount"] = 497 unsigned(pdr->composite_effecter_count); 498 499 auto statesPtr = pdr->possible_states; 500 auto compEffCount = pdr->composite_effecter_count; 501 502 while (compEffCount--) 503 { 504 auto state = 505 reinterpret_cast<const state_effecter_possible_states*>( 506 statesPtr); 507 output.emplace(("stateSetID[" + std::to_string(compEffCount) + "]"), 508 getStateSetName(state->state_set_id)); 509 output.emplace( 510 ("possibleStatesSize[" + std::to_string(compEffCount) + "]"), 511 state->possible_states_size); 512 output.emplace( 513 ("possibleStates[" + std::to_string(compEffCount) + "]"), 514 printPossibleStates(state->possible_states_size, 515 state->states)); 516 517 if (compEffCount) 518 { 519 statesPtr += sizeof(state_effecter_possible_states) + 520 state->possible_states_size - 1; 521 } 522 } 523 } 524 525 void printTerminusLocatorPDR(const uint8_t* data, ordered_json& output) 526 { 527 const std::array<std::string_view, 4> terminusLocatorType = { 528 "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"}; 529 530 auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data); 531 532 output["PLDMTerminusHandle"] = pdr->terminus_handle; 533 output["validity"] = (pdr->validity ? "valid" : "notValid"); 534 output["TID"] = unsigned(pdr->tid); 535 output["containerID"] = pdr->container_id; 536 output["terminusLocatorType"] = 537 terminusLocatorType[pdr->terminus_locator_type]; 538 output["terminusLocatorValueSize"] = 539 unsigned(pdr->terminus_locator_value_size); 540 541 if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID) 542 { 543 auto locatorValue = 544 reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>( 545 pdr->terminus_locator_value); 546 output["EID"] = unsigned(locatorValue->eid); 547 } 548 } 549 550 void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt, 551 uint8_t* data) 552 { 553 if (data == NULL) 554 { 555 std::cerr << "Failed to get PDR message" << std::endl; 556 return; 557 } 558 559 ordered_json output; 560 output["nextRecordHandle"] = nextRecordHndl; 561 output["responseCount"] = respCnt; 562 563 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; 564 if (!pdr) 565 { 566 return; 567 } 568 printCommonPDRHeader(pdr, output); 569 570 switch (pdr->type) 571 { 572 case PLDM_TERMINUS_LOCATOR_PDR: 573 printTerminusLocatorPDR(data, output); 574 break; 575 case PLDM_STATE_SENSOR_PDR: 576 printStateSensorPDR(data, output); 577 break; 578 case PLDM_NUMERIC_EFFECTER_PDR: 579 printNumericEffecterPDR(data, output); 580 break; 581 case PLDM_STATE_EFFECTER_PDR: 582 printStateEffecterPDR(data, output); 583 break; 584 case PLDM_PDR_ENTITY_ASSOCIATION: 585 printPDREntityAssociation(data, output); 586 break; 587 case PLDM_PDR_FRU_RECORD_SET: 588 printPDRFruRecordSet(data, output); 589 break; 590 default: 591 break; 592 } 593 pldmtool::helper::DisplayInJson(output); 594 } 595 596 private: 597 uint32_t recordHandle; 598 }; 599 600 class SetStateEffecter : public CommandInterface 601 { 602 public: 603 ~SetStateEffecter() = default; 604 SetStateEffecter() = delete; 605 SetStateEffecter(const SetStateEffecter&) = delete; 606 SetStateEffecter(SetStateEffecter&&) = default; 607 SetStateEffecter& operator=(const SetStateEffecter&) = delete; 608 SetStateEffecter& operator=(SetStateEffecter&&) = default; 609 610 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2) 611 static constexpr auto maxEffecterDataSize = 16; 612 613 // compositeEffecterCount(value: 0x01 to 0x08) 614 static constexpr auto minEffecterCount = 1; 615 static constexpr auto maxEffecterCount = 8; 616 explicit SetStateEffecter(const char* type, const char* name, 617 CLI::App* app) : 618 CommandInterface(type, name, app) 619 { 620 app->add_option( 621 "-i, --id", effecterId, 622 "A handle that is used to identify and access the effecter") 623 ->required(); 624 app->add_option("-c, --count", effecterCount, 625 "The number of individual sets of effecter information") 626 ->required(); 627 app->add_option( 628 "-d,--data", effecterData, 629 "Set effecter state data\n" 630 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...") 631 ->required(); 632 } 633 634 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 635 { 636 std::vector<uint8_t> requestMsg( 637 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES); 638 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 639 640 if (effecterCount > maxEffecterCount || 641 effecterCount < minEffecterCount) 642 { 643 std::cerr << "Request Message Error: effecterCount size " 644 << effecterCount << "is invalid\n"; 645 auto rc = PLDM_ERROR_INVALID_DATA; 646 return {rc, requestMsg}; 647 } 648 649 if (effecterData.size() > maxEffecterDataSize) 650 { 651 std::cerr << "Request Message Error: effecterData size " 652 << effecterData.size() << "is invalid\n"; 653 auto rc = PLDM_ERROR_INVALID_DATA; 654 return {rc, requestMsg}; 655 } 656 657 auto stateField = parseEffecterData(effecterData, effecterCount); 658 if (!stateField) 659 { 660 std::cerr << "Failed to parse effecter data, effecterCount size " 661 << effecterCount << "\n"; 662 auto rc = PLDM_ERROR_INVALID_DATA; 663 return {rc, requestMsg}; 664 } 665 666 auto rc = encode_set_state_effecter_states_req( 667 instanceId, effecterId, effecterCount, stateField->data(), request); 668 return {rc, requestMsg}; 669 } 670 671 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 672 { 673 uint8_t completionCode = 0; 674 auto rc = decode_set_state_effecter_states_resp( 675 responsePtr, payloadLength, &completionCode); 676 677 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 678 { 679 std::cerr << "Response Message Error: " 680 << "rc=" << rc << ",cc=" << (int)completionCode << "\n"; 681 return; 682 } 683 684 ordered_json data; 685 data["Response"] = "SUCCESS"; 686 pldmtool::helper::DisplayInJson(data); 687 } 688 689 private: 690 uint16_t effecterId; 691 uint8_t effecterCount; 692 std::vector<uint8_t> effecterData; 693 }; 694 695 class SetNumericEffecterValue : public CommandInterface 696 { 697 public: 698 ~SetNumericEffecterValue() = default; 699 SetNumericEffecterValue() = delete; 700 SetNumericEffecterValue(const SetNumericEffecterValue&) = delete; 701 SetNumericEffecterValue(SetNumericEffecterValue&&) = default; 702 SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete; 703 SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = default; 704 705 explicit SetNumericEffecterValue(const char* type, const char* name, 706 CLI::App* app) : 707 CommandInterface(type, name, app) 708 { 709 app->add_option( 710 "-i, --id", effecterId, 711 "A handle that is used to identify and access the effecter") 712 ->required(); 713 app->add_option("-s, --size", effecterDataSize, 714 "The bit width and format of the setting value for the " 715 "effecter. enum value: {uint8, sint8, uint16, sint16, " 716 "uint32, sint32}\n") 717 ->required(); 718 app->add_option("-d,--data", maxEffecterValue, 719 "The setting value of numeric effecter being " 720 "requested\n") 721 ->required(); 722 } 723 724 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 725 { 726 std::vector<uint8_t> requestMsg( 727 sizeof(pldm_msg_hdr) + 728 PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3); 729 730 uint8_t* effecterValue = (uint8_t*)&maxEffecterValue; 731 732 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 733 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES; 734 735 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 || 736 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) 737 { 738 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1; 739 } 740 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 || 741 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) 742 { 743 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3; 744 } 745 auto rc = encode_set_numeric_effecter_value_req( 746 0, effecterId, effecterDataSize, effecterValue, request, 747 payload_length); 748 749 return {rc, requestMsg}; 750 } 751 752 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 753 { 754 uint8_t completionCode = 0; 755 auto rc = decode_set_numeric_effecter_value_resp( 756 responsePtr, payloadLength, &completionCode); 757 758 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 759 { 760 std::cerr << "Response Message Error: " 761 << "rc=" << rc << ",cc=" << (int)completionCode 762 << std::endl; 763 return; 764 } 765 766 ordered_json data; 767 data["Response"] = "SUCCESS"; 768 pldmtool::helper::DisplayInJson(data); 769 } 770 771 private: 772 uint16_t effecterId; 773 uint8_t effecterDataSize; 774 uint64_t maxEffecterValue; 775 }; 776 777 class GetStateSensorReadings : public CommandInterface 778 { 779 public: 780 ~GetStateSensorReadings() = default; 781 GetStateSensorReadings() = delete; 782 GetStateSensorReadings(const GetStateSensorReadings&) = delete; 783 GetStateSensorReadings(GetStateSensorReadings&&) = default; 784 GetStateSensorReadings& operator=(const GetStateSensorReadings&) = delete; 785 GetStateSensorReadings& operator=(GetStateSensorReadings&&) = default; 786 787 explicit GetStateSensorReadings(const char* type, const char* name, 788 CLI::App* app) : 789 CommandInterface(type, name, app) 790 { 791 app->add_option( 792 "-i, --sensor_id", sensorId, 793 "Sensor ID that is used to identify and access the sensor") 794 ->required(); 795 app->add_option("-r, --rearm", sensorRearm, 796 "Each bit location in this field corresponds to a " 797 "particular sensor") 798 ->required(); 799 } 800 801 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 802 { 803 std::vector<uint8_t> requestMsg( 804 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES); 805 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 806 807 uint8_t reserved = 0; 808 bitfield8_t bf; 809 bf.byte = sensorRearm; 810 auto rc = encode_get_state_sensor_readings_req(instanceId, sensorId, bf, 811 reserved, request); 812 813 return {rc, requestMsg}; 814 } 815 816 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 817 { 818 uint8_t completionCode = 0; 819 uint8_t compSensorCount = 0; 820 std::array<get_sensor_state_field, 8> stateField{}; 821 auto rc = decode_get_state_sensor_readings_resp( 822 responsePtr, payloadLength, &completionCode, &compSensorCount, 823 stateField.data()); 824 825 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 826 { 827 std::cerr << "Response Message Error: " 828 << "rc=" << rc << ",cc=" << (int)completionCode 829 << std::endl; 830 return; 831 } 832 ordered_json output; 833 output["compositeSensorCount"] = (int)compSensorCount; 834 835 for (size_t i = 0; i < compSensorCount; i++) 836 { 837 838 output.emplace(("sensorOpState[" + std::to_string(i) + "]"), 839 sensorOpState.at(stateField[i].sensor_op_state)); 840 output.emplace(("presentState[" + std::to_string(i) + "]"), 841 sensorPresState.at(stateField[i].present_state)); 842 output.emplace(("previousState[" + std::to_string(i) + "]"), 843 sensorPresState.at(stateField[i].previous_state)); 844 output.emplace(("eventState[" + std::to_string(i) + "]"), 845 sensorPresState.at(stateField[i].event_state)); 846 } 847 848 pldmtool::helper::DisplayInJson(output); 849 } 850 851 private: 852 uint16_t sensorId; 853 uint8_t sensorRearm; 854 }; 855 856 void registerCommand(CLI::App& app) 857 { 858 auto platform = app.add_subcommand("platform", "platform type command"); 859 platform->require_subcommand(1); 860 861 auto getPDR = 862 platform->add_subcommand("GetPDR", "get platform descriptor records"); 863 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR)); 864 865 auto setStateEffecterStates = platform->add_subcommand( 866 "SetStateEffecterStates", "set effecter states"); 867 commands.push_back(std::make_unique<SetStateEffecter>( 868 "platform", "setStateEffecterStates", setStateEffecterStates)); 869 870 auto setNumericEffecterValue = platform->add_subcommand( 871 "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter"); 872 commands.push_back(std::make_unique<SetNumericEffecterValue>( 873 "platform", "setNumericEffecterValue", setNumericEffecterValue)); 874 875 auto getStateSensorReadings = platform->add_subcommand( 876 "GetStateSensorReadings", "get the state sensor readings"); 877 commands.push_back(std::make_unique<GetStateSensorReadings>( 878 "platform", "getStateSensorReadings", getStateSensorReadings)); 879 } 880 881 } // namespace platform 882 } // namespace pldmtool 883