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