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