1 #include "common/types.hpp" 2 #include "pldm_cmd_helper.hpp" 3 4 #include <libpldm/entity.h> 5 #include <libpldm/platform.h> 6 #include <libpldm/state_set.h> 7 8 #include <algorithm> 9 #include <cstddef> 10 #include <format> 11 #include <map> 12 #include <memory> 13 #include <ranges> 14 15 #ifdef OEM_IBM 16 #include "oem/ibm/oem_ibm_state_set.hpp" 17 #endif 18 19 using namespace pldm::utils; 20 21 namespace pldmtool 22 { 23 namespace platform 24 { 25 namespace 26 { 27 using namespace pldmtool::helper; 28 29 static const std::map<uint8_t, std::string> sensorPresState{ 30 {PLDM_SENSOR_UNKNOWN, "Sensor Unknown"}, 31 {PLDM_SENSOR_NORMAL, "Sensor Normal"}, 32 {PLDM_SENSOR_WARNING, "Sensor Warning"}, 33 {PLDM_SENSOR_CRITICAL, "Sensor Critical"}, 34 {PLDM_SENSOR_FATAL, "Sensor Fatal"}, 35 {PLDM_SENSOR_LOWERWARNING, "Sensor Lower Warning"}, 36 {PLDM_SENSOR_LOWERCRITICAL, "Sensor Lower Critical"}, 37 {PLDM_SENSOR_LOWERFATAL, "Sensor Lower Fatal"}, 38 {PLDM_SENSOR_UPPERWARNING, "Sensor Upper Warning"}, 39 {PLDM_SENSOR_UPPERCRITICAL, "Sensor Upper Critical"}, 40 {PLDM_SENSOR_UPPERFATAL, "Sensor Upper Fatal"}}; 41 42 static const std::map<uint8_t, std::string> sensorOpState{ 43 {PLDM_SENSOR_ENABLED, "Sensor Enabled"}, 44 {PLDM_SENSOR_DISABLED, "Sensor Disabled"}, 45 {PLDM_SENSOR_UNAVAILABLE, "Sensor Unavailable"}, 46 {PLDM_SENSOR_STATUSUNKOWN, "Sensor Status Unknown"}, 47 {PLDM_SENSOR_FAILED, "Sensor Failed"}, 48 {PLDM_SENSOR_INITIALIZING, "Sensor Sensor Initializing"}, 49 {PLDM_SENSOR_SHUTTINGDOWN, "Sensor Shutting down"}, 50 {PLDM_SENSOR_INTEST, "Sensor Intest"}}; 51 52 const std::map<uint8_t, std::string> effecterOpState{ 53 {EFFECTER_OPER_STATE_ENABLED_UPDATEPENDING, 54 "Effecter Enabled Update Pending"}, 55 {EFFECTER_OPER_STATE_ENABLED_NOUPDATEPENDING, 56 "Effecter Enabled No Update Pending"}, 57 {EFFECTER_OPER_STATE_DISABLED, "Effecter Disabled"}, 58 {EFFECTER_OPER_STATE_UNAVAILABLE, "Effecter Unavailable"}, 59 {EFFECTER_OPER_STATE_STATUSUNKNOWN, "Effecter Status Unknown"}, 60 {EFFECTER_OPER_STATE_FAILED, "Effecter Failed"}, 61 {EFFECTER_OPER_STATE_INITIALIZING, "Effecter Initializing"}, 62 {EFFECTER_OPER_STATE_SHUTTINGDOWN, "Effecter Shutting Down"}, 63 {EFFECTER_OPER_STATE_INTEST, "Effecter In Test"}}; 64 65 std::string getEffecterOpState(uint8_t state) 66 { 67 return effecterOpState.contains(state) ? effecterOpState.at(state) 68 : std::to_string(state); 69 } 70 71 std::vector<std::unique_ptr<CommandInterface>> commands; 72 73 } // namespace 74 75 using ordered_json = nlohmann::ordered_json; 76 77 class GetPDR : public CommandInterface 78 { 79 public: 80 ~GetPDR() = default; 81 GetPDR() = delete; 82 GetPDR(const GetPDR&) = delete; 83 GetPDR(GetPDR&&) = default; 84 GetPDR& operator=(const GetPDR&) = delete; 85 GetPDR& operator=(GetPDR&&) = delete; 86 87 using CommandInterface::CommandInterface; 88 89 explicit GetPDR(const char* type, const char* name, CLI::App* app) : 90 CommandInterface(type, name, app), dataTransferHandle(0), 91 operationFlag(PLDM_GET_FIRSTPART), requestCount(UINT16_MAX), 92 recordChangeNumber(0), nextPartRequired(false) 93 { 94 auto pdrOptionGroup = app->add_option_group( 95 "Required Option", 96 "Retrieve individual PDR, all PDRs, PDRs of a requested type or retrieve all PDRs of the requested terminusID"); 97 pdrOptionGroup->add_option( 98 "-d,--data", recordHandle, 99 "retrieve individual PDRs from a PDR Repository\n" 100 "eg: The recordHandle value for the PDR to be retrieved and 0 " 101 "means get first PDR in the repository."); 102 pdrRecType = ""; 103 pdrOptionGroup->add_option( 104 "-t, --type", pdrRecType, 105 "retrieve all PDRs of the requested type\n" 106 "supported types:\n" 107 "[terminusLocator, stateSensor, " 108 "numericEffecter, stateEffecter, " 109 "compactNumericSensor, sensorauxname, " 110 "efffecterAuxName, numericsensor, " 111 "EntityAssociation, fruRecord, ... ]"); 112 113 getPDRGroupOption = pdrOptionGroup->add_option( 114 "-i, --terminusID", pdrTerminus, 115 "retrieve all PDRs of the requested terminusID\n" 116 "supported IDs:\n [1, 2, 208...]"); 117 118 allPDRs = false; 119 pdrOptionGroup->add_flag("-a, --all", allPDRs, 120 "retrieve all PDRs from a PDR repository"); 121 122 pdrOptionGroup->require_option(1); 123 } 124 125 void parseGetPDROptions() 126 { 127 optTIDSet = false; 128 if (getPDRGroupOption->count() > 0) 129 { 130 optTIDSet = true; 131 getPDRs(); 132 } 133 } 134 135 void getPDRs() 136 { 137 // start the array 138 std::cout << "["; 139 140 recordHandle = 0; 141 do 142 { 143 CommandInterface::exec(); 144 } while (recordHandle != 0); 145 146 // close the array 147 std::cout << "]\n"; 148 149 if (handleFound) 150 { 151 recordHandle = 0; 152 uint32_t prevRecordHandle = 0; 153 do 154 { 155 CommandInterface::exec(); 156 if (recordHandle == prevRecordHandle) 157 { 158 return; 159 } 160 prevRecordHandle = recordHandle; 161 } while (recordHandle != 0); 162 } 163 } 164 165 void exec() override 166 { 167 if (allPDRs || !pdrRecType.empty()) 168 { 169 if (!pdrRecType.empty()) 170 { 171 std::transform(pdrRecType.begin(), pdrRecType.end(), 172 pdrRecType.begin(), tolower); 173 } 174 175 // start the array 176 std::cout << "[\n"; 177 178 // Retrieve all PDR records starting from the first 179 recordHandle = 0; 180 uint32_t prevRecordHandle = 0; 181 std::map<uint32_t, uint32_t> recordsSeen; 182 do 183 { 184 CommandInterface::exec(); 185 // recordHandle is updated to nextRecord when 186 // CommandInterface::exec() is successful. 187 // In case of any error, return. 188 if (recordHandle == prevRecordHandle && !nextPartRequired) 189 { 190 return; 191 } 192 193 // check for circular references. 194 auto result = 195 recordsSeen.emplace(recordHandle, prevRecordHandle); 196 if (!result.second && !nextPartRequired) 197 { 198 std::cerr 199 << "Record handle " << recordHandle 200 << " has multiple references: " << result.first->second 201 << ", " << prevRecordHandle << "\n"; 202 return; 203 } 204 prevRecordHandle = recordHandle; 205 206 if (recordHandle != 0) 207 { 208 // close the array 209 std::cout << ","; 210 } 211 } while (recordHandle != 0); 212 213 // close the array 214 std::cout << "]\n"; 215 } 216 else 217 { 218 do 219 { 220 CommandInterface::exec(); 221 } while (nextPartRequired); 222 } 223 } 224 225 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 226 { 227 std::vector<uint8_t> requestMsg( 228 sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES); 229 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 230 231 auto rc = encode_get_pdr_req( 232 instanceId, recordHandle, dataTransferHandle, operationFlag, 233 requestCount, recordChangeNumber, request, PLDM_GET_PDR_REQ_BYTES); 234 return {rc, requestMsg}; 235 } 236 237 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 238 { 239 uint8_t completionCode = 0; 240 uint8_t respRecordData[UINT16_MAX] = {0}; 241 uint32_t nextRecordHndl = 0; 242 uint32_t nextDataTransferHndl = 0; 243 uint8_t transferFlag = 0; 244 uint16_t respCnt = 0; 245 uint8_t transferCRC = 0; 246 247 auto rc = decode_get_pdr_resp( 248 responsePtr, payloadLength, &completionCode, &nextRecordHndl, 249 &nextDataTransferHndl, &transferFlag, &respCnt, respRecordData, 250 sizeof(respRecordData), &transferCRC); 251 252 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 253 { 254 std::cerr << "Response Message Error: " 255 << "rc=" << rc << ",cc=" << (int)completionCode 256 << std::endl; 257 nextPartRequired = false; 258 return; 259 } 260 261 if (optTIDSet && !handleFound) 262 { 263 terminusHandle = getTerminusHandle(respRecordData, pdrTerminus); 264 if (terminusHandle.has_value()) 265 { 266 recordHandle = 0; 267 return; 268 } 269 else 270 { 271 recordHandle = nextRecordHndl; 272 return; 273 } 274 } 275 else 276 { 277 recordData.insert(recordData.end(), respRecordData, 278 respRecordData + respCnt); 279 280 // End or StartAndEnd 281 if (transferFlag == PLDM_PLATFORM_TRANSFER_END || 282 transferFlag == PLDM_PLATFORM_TRANSFER_START_AND_END) 283 { 284 printPDRMsg(nextRecordHndl, respCnt, recordData.data(), 285 terminusHandle); 286 nextPartRequired = false; 287 recordHandle = nextRecordHndl; 288 dataTransferHandle = 0; 289 recordChangeNumber = 0; 290 operationFlag = PLDM_GET_FIRSTPART; 291 recordData.clear(); 292 } 293 else 294 { 295 nextPartRequired = true; 296 dataTransferHandle = nextDataTransferHndl; 297 struct pldm_pdr_hdr* pdr_hdr = 298 reinterpret_cast<struct pldm_pdr_hdr*>(respRecordData); 299 recordChangeNumber = pdr_hdr->record_change_num; 300 operationFlag = PLDM_GET_NEXTPART; 301 } 302 } 303 } 304 305 private: 306 const std::map<pldm::pdr::EntityType, std::string> entityType = { 307 {PLDM_ENTITY_UNSPECIFIED, "Unspecified"}, 308 {PLDM_ENTITY_OTHER, "Other"}, 309 {PLDM_ENTITY_NETWORK, "Network"}, 310 {PLDM_ENTITY_GROUP, "Group"}, 311 {PLDM_ENTITY_REMOTE_MGMT_COMM_DEVICE, 312 "Remote Management Communication Device"}, 313 {PLDM_ENTITY_EXTERNAL_ENVIRONMENT, "External Environment"}, 314 {PLDM_ENTITY_COMM_CHANNEL, " Communication Channel"}, 315 {PLDM_ENTITY_TERMINUS, "PLDM Terminus"}, 316 {PLDM_ENTITY_PLATFORM_EVENT_LOG, " Platform Event Log"}, 317 {PLDM_ENTITY_KEYPAD, "keypad"}, 318 {PLDM_ENTITY_SWITCH, "Switch"}, 319 {PLDM_ENTITY_PUSHBUTTON, "Pushbutton"}, 320 {PLDM_ENTITY_DISPLAY, "Display"}, 321 {PLDM_ENTITY_INDICATOR, "Indicator"}, 322 {PLDM_ENTITY_SYS_MGMT_SW, "System Management Software"}, 323 {PLDM_ENTITY_SYS_FIRMWARE, "System Firmware"}, 324 {PLDM_ENTITY_OPERATING_SYS, "Operating System"}, 325 {PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER, "Virtual Machine Manager"}, 326 {PLDM_ENTITY_OS_LOADER, "OS Loader"}, 327 {PLDM_ENTITY_DEVICE_DRIVER, "Device Driver"}, 328 {PLDM_ENTITY_MGMT_CONTROLLER_FW, "Management Controller Firmware"}, 329 {PLDM_ENTITY_SYSTEM_CHASSIS, "System chassis (main enclosure)"}, 330 {PLDM_ENTITY_SUB_CHASSIS, "Sub-chassis"}, 331 {PLDM_ENTITY_DISK_DRIVE_BAY, "Disk Drive Bay"}, 332 {PLDM_ENTITY_PERIPHERAL_BAY, "Peripheral Bay"}, 333 {PLDM_ENTITY_DEVICE_BAY, "Device bay"}, 334 {PLDM_ENTITY_DOOR, "Door"}, 335 {PLDM_ENTITY_ACCESS_PANEL, "Access Panel"}, 336 {PLDM_ENTITY_COVER, "Cover"}, 337 {PLDM_ENTITY_BOARD, "Board"}, 338 {PLDM_ENTITY_CARD, "Card"}, 339 {PLDM_ENTITY_MODULE, "Module"}, 340 {PLDM_ENTITY_SYS_MGMT_MODULE, "System management module"}, 341 {PLDM_ENTITY_SYS_BOARD, "System Board"}, 342 {PLDM_ENTITY_MEMORY_BOARD, "Memory Board"}, 343 {PLDM_ENTITY_MEMORY_MODULE, "Memory Module"}, 344 {PLDM_ENTITY_PROC_MODULE, "Processor Module"}, 345 {PLDM_ENTITY_ADD_IN_CARD, "Add-in Card"}, 346 {PLDM_ENTITY_CHASSIS_FRONT_PANEL_BOARD, 347 "Chassis front panel board(control panel)"}, 348 {PLDM_ENTITY_BACK_PANEL_BOARD, "Back panel board"}, 349 {PLDM_ENTITY_POWER_MGMT, "Power management board"}, 350 {PLDM_ENTITY_POWER_SYS_BOARD, "Power system board"}, 351 {PLDM_ENTITY_DRIVE_BACKPLANE, "Drive backplane"}, 352 {PLDM_ENTITY_SYS_INTERNAL_EXPANSION_BOARD, 353 "System internal expansion board"}, 354 {PLDM_ENTITY_OTHER_SYS_BOARD, "Other system board"}, 355 {PLDM_ENTITY_CHASSIS_BACK_PANEL_BOARD, "Chassis back panel board"}, 356 {PLDM_ENTITY_PROCESSING_BLADE, "Processing blade"}, 357 {PLDM_ENTITY_CONNECTIVITY_SWITCH, "Connectivity switch"}, 358 {PLDM_ENTITY_PROC_MEMORY_MODULE, "Processor/Memory Module"}, 359 {PLDM_ENTITY_IO_MODULE, "I/O Module"}, 360 {PLDM_ENTITY_PROC_IO_MODULE, "Processor I/O Module"}, 361 {PLDM_ENTITY_COOLING_DEVICE, "Cooling device"}, 362 {PLDM_ENTITY_COOLING_SUBSYSTEM, "Cooling subsystem"}, 363 {PLDM_ENTITY_COOLING_UNIT, "Cooling Unit"}, 364 {PLDM_ENTITY_FAN, "Fan"}, 365 {PLDM_ENTITY_PELTIER_COOLING_DEVICE, "Peltier Cooling Device"}, 366 {PLDM_ENTITY_LIQUID_COOLING_DEVICE, "Liquid Cooling Device"}, 367 {PLDM_ENTITY_LIQUID_COOLING_SUBSYSTEM, "Liquid Colling Subsystem"}, 368 {PLDM_ENTITY_OTHER_STORAGE_DEVICE, "Other Storage Device"}, 369 {PLDM_ENTITY_FLOPPY_DRIVE, "Floppy Drive"}, 370 {PLDM_ENTITY_FIXED_DISK_HARD_DRIVE, "Hard Drive"}, 371 {PLDM_ENTITY_CD_DRIVE, "CD Drive"}, 372 {PLDM_ENTITY_CD_DVD_DRIVE, "CD/DVD Drive"}, 373 {PLDM_ENTITY_OTHER_SILICON_STORAGE_DEVICE, 374 "Other Silicon Storage Device"}, 375 {PLDM_ENTITY_SOLID_STATE_SRIVE, "Solid State Drive"}, 376 {PLDM_ENTITY_POWER_SUPPLY, "Power supply"}, 377 {PLDM_ENTITY_BATTERY, "Battery"}, 378 {PLDM_ENTITY_SUPER_CAPACITOR, "Super Capacitor"}, 379 {PLDM_ENTITY_POWER_CONVERTER, "Power Converter"}, 380 {PLDM_ENTITY_DC_DC_CONVERTER, "DC-DC Converter"}, 381 {PLDM_ENTITY_AC_MAINS_POWER_SUPPLY, "AC mains power supply"}, 382 {PLDM_ENTITY_DC_MAINS_POWER_SUPPLY, "DC mains power supply"}, 383 {PLDM_ENTITY_PROC, "Processor"}, 384 {PLDM_ENTITY_CHIPSET_COMPONENT, "Chipset Component"}, 385 {PLDM_ENTITY_MGMT_CONTROLLER, "Management Controller"}, 386 {PLDM_ENTITY_PERIPHERAL_CONTROLLER, "Peripheral Controller"}, 387 {PLDM_ENTITY_SEEPROM, "SEEPROM"}, 388 {PLDM_ENTITY_NVRAM_CHIP, "NVRAM Chip"}, 389 {PLDM_ENTITY_FLASH_MEMORY_CHIP, "FLASH Memory chip"}, 390 {PLDM_ENTITY_MEMORY_CHIP, "Memory Chip"}, 391 {PLDM_ENTITY_MEMORY_CONTROLLER, "Memory Controller"}, 392 {PLDM_ENTITY_NETWORK_CONTROLLER, "Network Controller"}, 393 {PLDM_ENTITY_IO_CONTROLLER, "I/O Controller"}, 394 {PLDM_ENTITY_SOUTH_BRIDGE, "South Bridge"}, 395 {PLDM_ENTITY_REAL_TIME_CLOCK, "Real Time Clock (RTC)"}, 396 {PLDM_ENTITY_FPGA_CPLD_DEVICE, "FPGA/CPLD Configurable Logic Device"}, 397 {PLDM_ENTITY_OTHER_BUS, "Other Bus"}, 398 {PLDM_ENTITY_SYS_BUS, "System Bus"}, 399 {PLDM_ENTITY_I2C_BUS, "I2C Bus"}, 400 {PLDM_ENTITY_SMBUS_BUS, "SMBus Bus"}, 401 {PLDM_ENTITY_SPI_BUS, "SPI Bus"}, 402 {PLDM_ENTITY_PCI_BUS, "PCI Bus"}, 403 {PLDM_ENTITY_PCI_EXPRESS_BUS, "PCI Express Bus"}, 404 {PLDM_ENTITY_PECI_BUS, "PECI Bus"}, 405 {PLDM_ENTITY_LPC_BUS, "LPC Bus"}, 406 {PLDM_ENTITY_USB_BUS, "USB Bus"}, 407 {PLDM_ENTITY_FIREWIRE_BUS, "FireWire Bus"}, 408 {PLDM_ENTITY_SCSI_BUS, "SCSI Bus"}, 409 {PLDM_ENTITY_SATA_SAS_BUS, "SATA/SAS Bus"}, 410 {PLDM_ENTITY_PROC_FRONT_SIDE_BUS, "Processor/Front-side Bus"}, 411 {PLDM_ENTITY_INTER_PROC_BUS, "Inter-processor Bus"}, 412 {PLDM_ENTITY_CONNECTOR, "Connector"}, 413 {PLDM_ENTITY_SLOT, "Slot"}, 414 {PLDM_ENTITY_CABLE, "Cable(electrical or optical)"}, 415 {PLDM_ENTITY_INTERCONNECT, "Interconnect"}, 416 {PLDM_ENTITY_PLUG, "Plug"}, 417 {PLDM_ENTITY_SOCKET, "Socket"}, 418 }; 419 420 const std::map<uint16_t, std::string> stateSet = { 421 {PLDM_STATE_SET_HEALTH_STATE, "Health State"}, 422 {PLDM_STATE_SET_AVAILABILITY, "Availability"}, 423 {PLDM_STATE_SET_PREDICTIVE_CONDITION, "Predictive Condition"}, 424 {PLDM_STATE_SET_REDUNDANCY_STATUS, "Redundancy Status"}, 425 {PLDM_STATE_SET_HEALTH_REDUNDANCY_TREND, "Health/Redundancy Trend"}, 426 {PLDM_STATE_SET_GROUP_RESOURCE_LEVEL, "Group Resource Level"}, 427 {PLDM_STATE_SET_REDUNDANCY_ENTITY_ROLE, "Redundancy Entity Role"}, 428 {PLDM_STATE_SET_OPERATIONAL_STATUS, "Operational Status"}, 429 {PLDM_STATE_SET_OPERATIONAL_STRESS_STATUS, "Operational Stress Status"}, 430 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, "Operational Fault Status"}, 431 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 432 "Operational Running Status"}, 433 {PLDM_STATE_SET_OPERATIONAL_CONNECTION_STATUS, 434 "Operational Connection Status"}, 435 {PLDM_STATE_SET_PRESENCE, "Presence"}, 436 {PLDM_STATE_SET_PERFORMANCE, "Performance"}, 437 {PLDM_STATE_SET_CONFIGURATION_STATE, "Configuration State"}, 438 {PLDM_STATE_SET_CHANGED_CONFIGURATION, "Changed Configuration"}, 439 {PLDM_STATE_SET_IDENTIFY_STATE, "Identify State"}, 440 {PLDM_STATE_SET_VERSION, "Version"}, 441 {PLDM_STATE_SET_ALARM_STATE, "Alarm State"}, 442 {PLDM_STATE_SET_DEVICE_INITIALIZATION, "Device Initialization"}, 443 {PLDM_STATE_SET_THERMAL_TRIP, "Thermal Trip"}, 444 {PLDM_STATE_SET_HEARTBEAT, "Heartbeat"}, 445 {PLDM_STATE_SET_LINK_STATE, "Link State"}, 446 {PLDM_STATE_SET_SMOKE_STATE, "Smoke State"}, 447 {PLDM_STATE_SET_HUMIDITY_STATE, "Humidity State"}, 448 {PLDM_STATE_SET_DOOR_STATE, "Door State"}, 449 {PLDM_STATE_SET_SWITCH_STATE, "Switch State"}, 450 {PLDM_STATE_SET_LOCK_STATE, "Lock State"}, 451 {PLDM_STATE_SET_PHYSICAL_SECURITY, "Physical Security"}, 452 {PLDM_STATE_SET_DOCK_AUTHORIZATION, "Dock Authorization"}, 453 {PLDM_STATE_SET_HW_SECURITY, "Hardware Security"}, 454 {PLDM_STATE_SET_PHYSICAL_COMM_CONNECTION, 455 "Physical Communication Connection"}, 456 {PLDM_STATE_SET_COMM_LEASH_STATUS, "Communication Leash Status"}, 457 {PLDM_STATE_SET_FOREIGN_NW_DETECTION_STATUS, 458 "Foreign Network Detection Status"}, 459 {PLDM_STATE_SET_PASSWORD_PROTECTED_ACCESS_SECURITY, 460 "Password-Protected Access Security"}, 461 {PLDM_STATE_SET_SECURITY_ACCESS_PRIVILEGE_LEVEL, 462 "Security Access –PrivilegeLevel"}, 463 {PLDM_STATE_SET_SESSION_AUDIT, "PLDM Session Audit"}, 464 {PLDM_STATE_SET_SW_TERMINATION_STATUS, "Software Termination Status"}, 465 {PLDM_STATE_SET_STORAGE_MEDIA_ACTIVITY, "Storage Media Activity"}, 466 {PLDM_STATE_SET_BOOT_RESTART_CAUSE, "Boot/Restart Cause"}, 467 {PLDM_STATE_SET_BOOT_RESTART_REQUEST, "Boot/Restart Request"}, 468 {PLDM_STATE_SET_ENTITY_BOOT_STATUS, "Entity Boot Status"}, 469 {PLDM_STATE_SET_BOOT_ERROR_STATUS, "Boot ErrorStatus"}, 470 {PLDM_STATE_SET_BOOT_PROGRESS, "Boot Progress"}, 471 {PLDM_STATE_SET_SYS_FIRMWARE_HANG, "System Firmware Hang"}, 472 {PLDM_STATE_SET_POST_ERRORS, "POST Errors"}, 473 {PLDM_STATE_SET_LOG_FILL_STATUS, "Log Fill Status"}, 474 {PLDM_STATE_SET_LOG_FILTER_STATUS, "Log Filter Status"}, 475 {PLDM_STATE_SET_LOG_TIMESTAMP_CHANGE, "Log Timestamp Change"}, 476 {PLDM_STATE_SET_INTERRUPT_REQUESTED, "Interrupt Requested"}, 477 {PLDM_STATE_SET_INTERRUPT_RECEIVED, "Interrupt Received"}, 478 {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_REQUESTED, 479 "Diagnostic Interrupt Requested"}, 480 {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_RECEIVED, 481 "Diagnostic Interrupt Received"}, 482 {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_REQUESTED, 483 "I/O Channel Check NMI Requested"}, 484 {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_RECEIVED, 485 "I/O Channel Check NMI Received"}, 486 {PLDM_STATE_SET_FATAL_NMI_REQUESTED, "Fatal NMI Requested"}, 487 {PLDM_STATE_SET_FATAL_NMI_RECEIVED, "Fatal NMI Received"}, 488 {PLDM_STATE_SET_SOFTWARE_NMI_REQUESTED, "Software NMI Requested"}, 489 {PLDM_STATE_SET_SOFTWARE_NMI_RECEIVED, "Software NMI Received"}, 490 {PLDM_STATE_SET_SMI_REQUESTED, "SMI Requested"}, 491 {PLDM_STATE_SET_SMI_RECEIVED, "SMI Received"}, 492 {PLDM_STATE_SET_PCI_PERR_REQUESTED, "PCI PERR Requested"}, 493 {PLDM_STATE_SET_PCI_PERR_RECEIVED, "PCI PERR Received"}, 494 {PLDM_STATE_SET_PCI_SERR_REQUESTED, "PCI SERR Requested "}, 495 {PLDM_STATE_SET_PCI_SERR_RECEIVED, "PCI SERR Received"}, 496 {PLDM_STATE_SET_BUS_ERROR_STATUS, "Bus Error Status"}, 497 {PLDM_STATE_SET_WATCHDOG_STATUS, "Watchdog Status"}, 498 {PLDM_STATE_SET_POWER_SUPPLY_STATE, "Power Supply State"}, 499 {PLDM_STATE_SET_DEVICE_POWER_STATE, "Device Power State"}, 500 {PLDM_STATE_SET_ACPI_POWER_STATE, "ACPI Power State"}, 501 {PLDM_STATE_SET_BACKUP_POWER_SOURCE, "Backup Power Source"}, 502 {PLDM_STATE_SET_SYSTEM_POWER_STATE, "System Power State "}, 503 {PLDM_STATE_SET_BATTERY_ACTIVITY, "Battery Activity"}, 504 {PLDM_STATE_SET_BATTERY_STATE, "Battery State"}, 505 {PLDM_STATE_SET_PROC_POWER_STATE, "Processor Power State"}, 506 {PLDM_STATE_SET_POWER_PERFORMANCE_STATE, "Power-Performance State"}, 507 {PLDM_STATE_SET_PROC_ERROR_STATUS, "Processor Error Status"}, 508 {PLDM_STATE_SET_BIST_FAILURE_STATUS, "BIST FailureStatus"}, 509 {PLDM_STATE_SET_IBIST_FAILURE_STATUS, "IBIST FailureStatus"}, 510 {PLDM_STATE_SET_PROC_HANG_IN_POST, "Processor Hang in POST"}, 511 {PLDM_STATE_SET_PROC_STARTUP_FAILURE, "Processor Startup Failure"}, 512 {PLDM_STATE_SET_UNCORRECTABLE_CPU_ERROR, "Uncorrectable CPU Error"}, 513 {PLDM_STATE_SET_MACHINE_CHECK_ERROR, "Machine Check Error"}, 514 {PLDM_STATE_SET_CORRECTED_MACHINE_CHECK, "Corrected Machine Check"}, 515 {PLDM_STATE_SET_CACHE_STATUS, "Cache Status"}, 516 {PLDM_STATE_SET_MEMORY_ERROR_STATUS, "Memory Error Status"}, 517 {PLDM_STATE_SET_REDUNDANT_MEMORY_ACTIVITY_STATUS, 518 "Redundant Memory Activity Status"}, 519 {PLDM_STATE_SET_ERROR_DETECTION_STATUS, "Error Detection Status"}, 520 {PLDM_STATE_SET_STUCK_BIT_STATUS, "Stuck Bit Status"}, 521 {PLDM_STATE_SET_SCRUB_STATUS, "Scrub Status"}, 522 {PLDM_STATE_SET_SLOT_OCCUPANCY, "Slot Occupancy"}, 523 {PLDM_STATE_SET_SLOT_STATE, "Slot State"}, 524 }; 525 526 const std::array<std::string_view, 4> sensorInit = { 527 "noInit", "useInitPDR", "enableSensor", "disableSensor"}; 528 529 const std::array<std::string_view, 4> effecterInit = { 530 "noInit", "useInitPDR", "enableEffecter", "disableEffecter"}; 531 532 const std::map<uint8_t, std::string> pdrType = { 533 {PLDM_TERMINUS_LOCATOR_PDR, "Terminus Locator PDR"}, 534 {PLDM_NUMERIC_SENSOR_PDR, "Numeric Sensor PDR"}, 535 {PLDM_NUMERIC_SENSOR_INITIALIZATION_PDR, 536 "Numeric Sensor Initialization PDR"}, 537 {PLDM_STATE_SENSOR_PDR, "State Sensor PDR"}, 538 {PLDM_STATE_SENSOR_INITIALIZATION_PDR, 539 "State Sensor Initialization PDR"}, 540 {PLDM_SENSOR_AUXILIARY_NAMES_PDR, "Sensor Auxiliary Names PDR"}, 541 {PLDM_OEM_UNIT_PDR, "OEM Unit PDR"}, 542 {PLDM_OEM_STATE_SET_PDR, "OEM State Set PDR"}, 543 {PLDM_NUMERIC_EFFECTER_PDR, "Numeric Effecter PDR"}, 544 {PLDM_NUMERIC_EFFECTER_INITIALIZATION_PDR, 545 "Numeric Effecter Initialization PDR"}, 546 {PLDM_COMPACT_NUMERIC_SENSOR_PDR, "Compact Numeric Sensor PDR"}, 547 {PLDM_STATE_EFFECTER_PDR, "State Effecter PDR"}, 548 {PLDM_STATE_EFFECTER_INITIALIZATION_PDR, 549 "State Effecter Initialization PDR"}, 550 {PLDM_EFFECTER_AUXILIARY_NAMES_PDR, "Effecter Auxiliary Names PDR"}, 551 {PLDM_EFFECTER_OEM_SEMANTIC_PDR, "Effecter OEM Semantic PDR"}, 552 {PLDM_PDR_ENTITY_ASSOCIATION, "Entity Association PDR"}, 553 {PLDM_ENTITY_AUXILIARY_NAMES_PDR, "Entity Auxiliary Names PDR"}, 554 {PLDM_OEM_ENTITY_ID_PDR, "OEM Entity ID PDR"}, 555 {PLDM_INTERRUPT_ASSOCIATION_PDR, "Interrupt Association PDR"}, 556 {PLDM_EVENT_LOG_PDR, "PLDM Event Log PDR"}, 557 {PLDM_PDR_FRU_RECORD_SET, "FRU Record Set PDR"}, 558 {PLDM_OEM_DEVICE_PDR, "OEM Device PDR"}, 559 {PLDM_OEM_PDR, "OEM PDR"}, 560 }; 561 562 static inline const std::map<uint8_t, std::string> setThermalTrip{ 563 {PLDM_STATE_SET_THERMAL_TRIP_STATUS_NORMAL, "Normal"}, 564 {PLDM_STATE_SET_THERMAL_TRIP_STATUS_THERMAL_TRIP, "Thermal Trip"}}; 565 566 static inline const std::map<uint8_t, std::string> setIdentifyState{ 567 {PLDM_STATE_SET_IDENTIFY_STATE_UNASSERTED, "Identify State Unasserted"}, 568 {PLDM_STATE_SET_IDENTIFY_STATE_ASSERTED, "Identify State Asserted"}}; 569 570 static inline const std::map<uint8_t, std::string> setBootProgressState{ 571 {PLDM_STATE_SET_BOOT_PROG_STATE_NOT_ACTIVE, "Boot Not Active"}, 572 {PLDM_STATE_SET_BOOT_PROG_STATE_COMPLETED, "Boot Completed"}, 573 {PLDM_STATE_SET_BOOT_PROG_STATE_MEM_INITIALIZATION, 574 "Memory Initialization"}, 575 {PLDM_STATE_SET_BOOT_PROG_STATE_SEC_PROC_INITIALIZATION, 576 "Secondary Processor(s) Initialization"}, 577 {PLDM_STATE_SET_BOOT_PROG_STATE_PCI_RESORUCE_CONFIG, 578 "PCI Resource Configuration"}, 579 {PLDM_STATE_SET_BOOT_PROG_STATE_STARTING_OP_SYS, 580 "Starting Operating System"}, 581 {PLDM_STATE_SET_BOOT_PROG_STATE_BASE_BOARD_INITIALIZATION, 582 "Baseboard Initialization"}, 583 {PLDM_STATE_SET_BOOT_PROG_STATE_PRIMARY_PROC_INITIALIZATION, 584 "Primary Processor Initialization"}, 585 {PLDM_STATE_SET_BOOT_PROG_STATE_OSSTART, "OSStart"}}; 586 587 static inline const std::map<uint8_t, std::string> setOpFaultStatus{ 588 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_NORMAL, "Normal"}, 589 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_ERROR, "Error"}, 590 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_NON_RECOVERABLE_ERROR, 591 "Non Recoverable Error"}}; 592 593 static inline const std::map<uint8_t, std::string> setSysPowerState{ 594 {PLDM_STATE_SET_SYS_POWER_STATE_OFF_SOFT_GRACEFUL, 595 "Off-Soft Graceful"}}; 596 597 static inline const std::map<uint8_t, std::string> setSWTerminationStatus{ 598 {PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED, 599 "Graceful Restart Requested"}}; 600 601 static inline const std::map<uint8_t, std::string> setAvailability{ 602 {PLDM_STATE_SET_AVAILABILITY_REBOOTING, "Rebooting"}}; 603 604 static inline const std::map<uint8_t, std::string> setHealthState{ 605 {PLDM_STATE_SET_HEALTH_STATE_NORMAL, "Normal"}, 606 {PLDM_STATE_SET_HEALTH_STATE_NON_CRITICAL, "Non-Critical"}, 607 {PLDM_STATE_SET_HEALTH_STATE_CRITICAL, "Critical"}, 608 {PLDM_STATE_SET_HEALTH_STATE_FATAL, "Fatal"}, 609 {PLDM_STATE_SET_HEALTH_STATE_UPPER_NON_CRITICAL, "Upper Non-Critical"}, 610 {PLDM_STATE_SET_HEALTH_STATE_LOWER_NON_CRITICAL, "Lower Non-Critical"}, 611 {PLDM_STATE_SET_HEALTH_STATE_UPPER_CRITICAL, "Upper Critical"}, 612 {PLDM_STATE_SET_HEALTH_STATE_LOWER_CRITICAL, "Lower Critical"}, 613 {PLDM_STATE_SET_HEALTH_STATE_UPPER_FATAL, "Upper Fatal"}, 614 {PLDM_STATE_SET_HEALTH_STATE_LOWER_FATAL, "Lower Fatal"}}; 615 616 static inline const std::map<uint8_t, std::string> 617 setOperationalRunningState{ 618 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STARTING, "Starting"}, 619 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPING, "Stopping"}, 620 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED, "Stopped"}, 621 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE, 622 "In Service"}, 623 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_ABORTED, "Aborted"}, 624 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT, "Dormant"}}; 625 626 static inline const std::map<uint8_t, std::string> setPowerDeviceState{ 627 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_UNKNOWN, "Unknown"}, 628 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_FULLY_ON, "Fully-On"}, 629 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_INTERMEDIATE_1, 630 "Intermediate State-1"}, 631 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_INTERMEDIATE_2, 632 "Intermediate State-2"}, 633 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_OFF, "Off"}}; 634 635 static inline const std::map<uint16_t, const std::map<uint8_t, std::string>> 636 populatePStateMaps{ 637 {PLDM_STATE_SET_THERMAL_TRIP, setThermalTrip}, 638 {PLDM_STATE_SET_IDENTIFY_STATE, setIdentifyState}, 639 {PLDM_STATE_SET_BOOT_PROGRESS, setBootProgressState}, 640 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, setOpFaultStatus}, 641 {PLDM_STATE_SET_SYSTEM_POWER_STATE, setSysPowerState}, 642 {PLDM_STATE_SET_SW_TERMINATION_STATUS, setSWTerminationStatus}, 643 {PLDM_STATE_SET_AVAILABILITY, setAvailability}, 644 {PLDM_STATE_SET_HEALTH_STATE, setHealthState}, 645 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 646 setOperationalRunningState}, 647 {PLDM_STATE_SET_DEVICE_POWER_STATE, setPowerDeviceState}, 648 }; 649 650 const std::map<std::string, uint8_t> strToPdrType = { 651 {"terminuslocator", PLDM_TERMINUS_LOCATOR_PDR}, 652 {"statesensor", PLDM_STATE_SENSOR_PDR}, 653 {"sensorauxname", PLDM_SENSOR_AUXILIARY_NAMES_PDR}, 654 {"numericeffecter", PLDM_NUMERIC_EFFECTER_PDR}, 655 {"efffecterauxname", PLDM_EFFECTER_AUXILIARY_NAMES_PDR}, 656 {"numericsensor", PLDM_NUMERIC_SENSOR_PDR}, 657 {"compactnumericsensor", PLDM_COMPACT_NUMERIC_SENSOR_PDR}, 658 {"stateeffecter", PLDM_STATE_EFFECTER_PDR}, 659 {"entityassociation", PLDM_PDR_ENTITY_ASSOCIATION}, 660 {"frurecord", PLDM_PDR_FRU_RECORD_SET}, 661 // Add other types 662 }; 663 664 bool isLogicalBitSet(const uint16_t entity_type) 665 { 666 return entity_type & 0x8000; 667 } 668 669 uint16_t getEntityTypeForLogicalEntity(const uint16_t logical_entity_type) 670 { 671 return logical_entity_type & 0x7FFF; 672 } 673 674 std::string getEntityName(pldm::pdr::EntityType type) 675 { 676 uint16_t entityNumber = type; 677 std::string entityName = "[Physical] "; 678 679 if (isLogicalBitSet(type)) 680 { 681 entityName = "[Logical] "; 682 entityNumber = getEntityTypeForLogicalEntity(type); 683 } 684 685 try 686 { 687 return entityName + entityType.at(entityNumber); 688 } 689 catch (const std::out_of_range& e) 690 { 691 auto OemString = 692 std::to_string(static_cast<unsigned>(entityNumber)); 693 if (type >= PLDM_OEM_ENTITY_TYPE_START && 694 type <= PLDM_OEM_ENTITY_TYPE_END) 695 { 696 #ifdef OEM_IBM 697 if (OemIBMEntityType.contains(entityNumber)) 698 { 699 return entityName + OemIBMEntityType.at(entityNumber) + 700 "(OEM)"; 701 } 702 #endif 703 return entityName + OemString + "(OEM)"; 704 } 705 return OemString; 706 } 707 } 708 709 std::string getStateSetName(uint16_t id) 710 { 711 auto typeString = std::to_string(id); 712 try 713 { 714 return stateSet.at(id) + "(" + typeString + ")"; 715 } 716 catch (const std::out_of_range& e) 717 { 718 return typeString; 719 } 720 } 721 722 std::vector<std::string> getStateSetPossibleStateNames( 723 uint16_t stateId, const std::vector<uint8_t>& value) 724 { 725 std::vector<std::string> data{}; 726 727 for (const auto& s : value) 728 { 729 std::map<uint8_t, std::string> stateNameMaps; 730 auto pstr = std::to_string(s); 731 732 #ifdef OEM_IBM 733 if (stateId >= PLDM_OEM_STATE_SET_ID_START && 734 stateId < PLDM_OEM_STATE_SET_ID_END) 735 { 736 if (populateOemIBMStateMaps.contains(stateId)) 737 { 738 const std::map<uint8_t, std::string> stateNames = 739 populateOemIBMStateMaps.at(stateId); 740 stateNameMaps.insert(stateNames.begin(), stateNames.end()); 741 } 742 } 743 #endif 744 if (populatePStateMaps.contains(stateId)) 745 { 746 const std::map<uint8_t, std::string> stateNames = 747 populatePStateMaps.at(stateId); 748 stateNameMaps.insert(stateNames.begin(), stateNames.end()); 749 } 750 if (stateNameMaps.contains(s)) 751 { 752 data.push_back(stateNameMaps.at(s) + "(" + pstr + ")"); 753 } 754 else 755 { 756 data.push_back(pstr); 757 } 758 } 759 return data; 760 } 761 762 std::string getPDRType(uint8_t type) 763 { 764 auto typeString = std::to_string(type); 765 try 766 { 767 return pdrType.at(type); 768 } 769 catch (const std::out_of_range& e) 770 { 771 return typeString; 772 } 773 } 774 775 void printCommonPDRHeader(const pldm_pdr_hdr* hdr, ordered_json& output) 776 { 777 output["recordHandle"] = hdr->record_handle; 778 output["PDRHeaderVersion"] = unsigned(hdr->version); 779 output["PDRType"] = getPDRType(hdr->type); 780 output["recordChangeNumber"] = hdr->record_change_num; 781 output["dataLength"] = hdr->length; 782 } 783 784 std::vector<uint8_t> printPossibleStates(uint8_t possibleStatesSize, 785 const bitfield8_t* states) 786 { 787 uint8_t possibleStatesPos{}; 788 std::vector<uint8_t> data{}; 789 auto printStates = [&possibleStatesPos, &data](const bitfield8_t& val) { 790 std::stringstream pstates; 791 for (int i = 0; i < CHAR_BIT; i++) 792 { 793 if (val.byte & (1 << i)) 794 { 795 pstates << (possibleStatesPos * CHAR_BIT + i); 796 data.push_back( 797 static_cast<uint8_t>(std::stoi(pstates.str()))); 798 pstates.str(""); 799 } 800 } 801 possibleStatesPos++; 802 }; 803 std::for_each(states, states + possibleStatesSize, printStates); 804 return data; 805 } 806 807 void printStateSensorPDR(const uint8_t* data, ordered_json& output) 808 { 809 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(data); 810 output["PLDMTerminusHandle"] = pdr->terminus_handle; 811 output["sensorID"] = pdr->sensor_id; 812 output["entityType"] = getEntityName(pdr->entity_type); 813 output["entityInstanceNumber"] = pdr->entity_instance; 814 output["containerID"] = pdr->container_id; 815 output["sensorInit"] = sensorInit[pdr->sensor_init]; 816 output["sensorAuxiliaryNamesPDR"] = 817 (pdr->sensor_auxiliary_names_pdr ? true : false); 818 output["compositeSensorCount"] = unsigned(pdr->composite_sensor_count); 819 820 auto statesPtr = pdr->possible_states; 821 auto compCount = pdr->composite_sensor_count; 822 823 while (compCount--) 824 { 825 auto state = reinterpret_cast<const state_sensor_possible_states*>( 826 statesPtr); 827 output.emplace(("stateSetID[" + std::to_string(compCount) + "]"), 828 getStateSetName(state->state_set_id)); 829 output.emplace( 830 ("possibleStatesSize[" + std::to_string(compCount) + "]"), 831 state->possible_states_size); 832 output.emplace( 833 ("possibleStates[" + std::to_string(compCount) + "]"), 834 getStateSetPossibleStateNames( 835 state->state_set_id, 836 printPossibleStates(state->possible_states_size, 837 state->states))); 838 839 if (compCount) 840 { 841 statesPtr += sizeof(state_sensor_possible_states) + 842 state->possible_states_size - 1; 843 } 844 } 845 } 846 847 void printPDRFruRecordSet(uint8_t* data, ordered_json& output) 848 { 849 if (data == NULL) 850 { 851 return; 852 } 853 854 data += sizeof(pldm_pdr_hdr); 855 pldm_pdr_fru_record_set* pdr = 856 reinterpret_cast<pldm_pdr_fru_record_set*>(data); 857 if (!pdr) 858 { 859 std::cerr << "Failed to get the FRU record set PDR" << std::endl; 860 return; 861 } 862 863 output["PLDMTerminusHandle"] = unsigned(pdr->terminus_handle); 864 output["FRURecordSetIdentifier"] = unsigned(pdr->fru_rsi); 865 output["entityType"] = getEntityName(pdr->entity_type); 866 output["entityInstanceNumber"] = unsigned(pdr->entity_instance); 867 output["containerID"] = unsigned(pdr->container_id); 868 } 869 870 void printPDREntityAssociation(uint8_t* data, ordered_json& output) 871 { 872 const std::map<uint8_t, const char*> assocationType = { 873 {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"}, 874 {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"}, 875 }; 876 877 if (data == NULL) 878 { 879 return; 880 } 881 882 data += sizeof(pldm_pdr_hdr); 883 pldm_pdr_entity_association* pdr = 884 reinterpret_cast<pldm_pdr_entity_association*>(data); 885 if (!pdr) 886 { 887 std::cerr << "Failed to get the PDR eneity association" 888 << std::endl; 889 return; 890 } 891 892 output["containerID"] = int(pdr->container_id); 893 if (assocationType.contains(pdr->association_type)) 894 { 895 output["associationType"] = 896 assocationType.at(pdr->association_type); 897 } 898 else 899 { 900 std::cout << "Get associationType failed.\n"; 901 } 902 output["containerEntityType"] = 903 getEntityName(pdr->container.entity_type); 904 output["containerEntityInstanceNumber"] = 905 int(pdr->container.entity_instance_num); 906 output["containerEntityContainerID"] = 907 int(pdr->container.entity_container_id); 908 output["containedEntityCount"] = 909 static_cast<unsigned>(pdr->num_children); 910 911 auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]); 912 for (int i = 0; i < pdr->num_children; ++i) 913 { 914 output.emplace("containedEntityType[" + std::to_string(i + 1) + "]", 915 getEntityName(child->entity_type)); 916 output.emplace("containedEntityInstanceNumber[" + 917 std::to_string(i + 1) + "]", 918 unsigned(child->entity_instance_num)); 919 output.emplace("containedEntityContainerID[" + 920 std::to_string(i + 1) + "]", 921 unsigned(child->entity_container_id)); 922 923 ++child; 924 } 925 } 926 927 /** @brief Format the Sensor/Effecter Aux Name PDR types to json output 928 * 929 * @param[in] data - reference to the Sensor/Effecter Aux Name PDR 930 * @param[out] output - PDRs data fields in Json format 931 */ 932 void printAuxNamePDR(uint8_t* data, ordered_json& output) 933 { 934 constexpr uint8_t nullTerminator = 0; 935 struct pldm_effecter_aux_name_pdr* auxNamePdr = 936 (struct pldm_effecter_aux_name_pdr*)data; 937 938 if (!auxNamePdr) 939 { 940 std::cerr << "Failed to get Aux Name PDR" << std::endl; 941 return; 942 } 943 944 std::string sPrefix = "effecter"; 945 if (auxNamePdr->hdr.type == PLDM_SENSOR_AUXILIARY_NAMES_PDR) 946 { 947 sPrefix = "sensor"; 948 } 949 output["terminusHandle"] = int(auxNamePdr->terminus_handle); 950 output[sPrefix + "Id"] = int(auxNamePdr->effecter_id); 951 output[sPrefix + "Count"] = int(auxNamePdr->effecter_count); 952 953 const uint8_t* ptr = auxNamePdr->effecter_names; 954 for (auto i : std::views::iota(0, (int)auxNamePdr->effecter_count)) 955 { 956 const uint8_t nameStringCount = static_cast<uint8_t>(*ptr); 957 ptr += sizeof(uint8_t); 958 for (auto j : std::views::iota(0, (int)nameStringCount)) 959 { 960 std::string nameLanguageTagKey = 961 sPrefix + std::to_string(j) + "_nameLanguageTag" + 962 std::to_string(i); 963 std::string entityAuxNameKey = 964 sPrefix + std::to_string(j) + "_entityAuxName" + 965 std::to_string(i); 966 std::string nameLanguageTag(reinterpret_cast<const char*>(ptr), 967 0, PLDM_STR_UTF_8_MAX_LEN); 968 ptr += nameLanguageTag.size() + sizeof(nullTerminator); 969 std::u16string u16NameString( 970 reinterpret_cast<const char16_t*>(ptr), 0, 971 PLDM_STR_UTF_16_MAX_LEN); 972 ptr += (u16NameString.size() + sizeof(nullTerminator)) * 973 sizeof(uint16_t); 974 std::transform(u16NameString.cbegin(), u16NameString.cend(), 975 u16NameString.begin(), 976 [](uint16_t utf16) { return be16toh(utf16); }); 977 std::string nameString = 978 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, 979 char16_t>{} 980 .to_bytes(u16NameString); 981 output[nameLanguageTagKey] = nameLanguageTag; 982 output[entityAuxNameKey] = nameString; 983 } 984 } 985 } 986 987 void printNumericEffecterPDR(uint8_t* data, ordered_json& output) 988 { 989 struct pldm_numeric_effecter_value_pdr* pdr = 990 (struct pldm_numeric_effecter_value_pdr*)data; 991 if (!pdr) 992 { 993 std::cerr << "Failed to get numeric effecter PDR" << std::endl; 994 return; 995 } 996 997 output["PLDMTerminusHandle"] = int(pdr->terminus_handle); 998 output["effecterID"] = int(pdr->effecter_id); 999 output["entityType"] = int(pdr->entity_type); 1000 output["entityInstanceNumber"] = int(pdr->entity_instance); 1001 output["containerID"] = int(pdr->container_id); 1002 output["effecterSemanticID"] = int(pdr->effecter_semantic_id); 1003 output["effecterInit"] = unsigned(pdr->effecter_init); 1004 output["effecterAuxiliaryNames"] = 1005 (unsigned(pdr->effecter_auxiliary_names) ? true : false); 1006 output["baseUnit"] = unsigned(pdr->base_unit); 1007 output["unitModifier"] = unsigned(pdr->unit_modifier); 1008 output["rateUnit"] = unsigned(pdr->rate_unit); 1009 output["baseOEMUnitHandle"] = unsigned(pdr->base_oem_unit_handle); 1010 output["auxUnit"] = unsigned(pdr->aux_unit); 1011 output["auxUnitModifier"] = unsigned(pdr->aux_unit_modifier); 1012 output["auxrateUnit"] = unsigned(pdr->aux_rate_unit); 1013 output["auxOEMUnitHandle"] = unsigned(pdr->aux_oem_unit_handle); 1014 output["isLinear"] = (unsigned(pdr->is_linear) ? true : false); 1015 output["effecterDataSize"] = unsigned(pdr->effecter_data_size); 1016 output["resolution"] = unsigned(pdr->resolution); 1017 output["offset"] = unsigned(pdr->offset); 1018 output["accuracy"] = unsigned(pdr->accuracy); 1019 output["plusTolerance"] = unsigned(pdr->plus_tolerance); 1020 output["minusTolerance"] = unsigned(pdr->minus_tolerance); 1021 output["stateTransitionInterval"] = 1022 unsigned(pdr->state_transition_interval); 1023 output["TransitionInterval"] = unsigned(pdr->transition_interval); 1024 1025 switch (pdr->effecter_data_size) 1026 { 1027 case PLDM_EFFECTER_DATA_SIZE_UINT8: 1028 output["maxSettable"] = unsigned(pdr->max_settable.value_u8); 1029 output["minSettable"] = unsigned(pdr->min_settable.value_u8); 1030 break; 1031 case PLDM_EFFECTER_DATA_SIZE_SINT8: 1032 output["maxSettable"] = unsigned(pdr->max_settable.value_s8); 1033 output["minSettable"] = unsigned(pdr->min_settable.value_s8); 1034 break; 1035 case PLDM_EFFECTER_DATA_SIZE_UINT16: 1036 output["maxSettable"] = unsigned(pdr->max_settable.value_u16); 1037 output["minSettable"] = unsigned(pdr->min_settable.value_u16); 1038 break; 1039 case PLDM_EFFECTER_DATA_SIZE_SINT16: 1040 output["maxSettable"] = unsigned(pdr->max_settable.value_s16); 1041 output["minSettable"] = unsigned(pdr->min_settable.value_s16); 1042 break; 1043 case PLDM_EFFECTER_DATA_SIZE_UINT32: 1044 output["maxSettable"] = unsigned(pdr->max_settable.value_u32); 1045 output["minSettable"] = unsigned(pdr->min_settable.value_u32); 1046 break; 1047 case PLDM_EFFECTER_DATA_SIZE_SINT32: 1048 output["maxSettable"] = unsigned(pdr->max_settable.value_s32); 1049 output["minSettable"] = unsigned(pdr->min_settable.value_s32); 1050 break; 1051 default: 1052 break; 1053 } 1054 1055 output["rangeFieldFormat"] = unsigned(pdr->range_field_format); 1056 output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte); 1057 1058 switch (pdr->range_field_format) 1059 { 1060 case PLDM_RANGE_FIELD_FORMAT_UINT8: 1061 output["nominalValue"] = unsigned(pdr->nominal_value.value_u8); 1062 output["normalMax"] = unsigned(pdr->normal_max.value_u8); 1063 output["normalMin"] = unsigned(pdr->normal_min.value_u8); 1064 output["ratedMax"] = unsigned(pdr->rated_max.value_u8); 1065 output["ratedMin"] = unsigned(pdr->rated_min.value_u8); 1066 break; 1067 case PLDM_RANGE_FIELD_FORMAT_SINT8: 1068 output["nominalValue"] = unsigned(pdr->nominal_value.value_s8); 1069 output["normalMax"] = unsigned(pdr->normal_max.value_s8); 1070 output["normalMin"] = unsigned(pdr->normal_min.value_s8); 1071 output["ratedMax"] = unsigned(pdr->rated_max.value_s8); 1072 output["ratedMin"] = unsigned(pdr->rated_min.value_s8); 1073 break; 1074 case PLDM_RANGE_FIELD_FORMAT_UINT16: 1075 output["nominalValue"] = unsigned(pdr->nominal_value.value_u16); 1076 output["normalMax"] = unsigned(pdr->normal_max.value_u16); 1077 output["normalMin"] = unsigned(pdr->normal_min.value_u16); 1078 output["ratedMax"] = unsigned(pdr->rated_max.value_u16); 1079 output["ratedMin"] = unsigned(pdr->rated_min.value_u16); 1080 break; 1081 case PLDM_RANGE_FIELD_FORMAT_SINT16: 1082 output["nominalValue"] = unsigned(pdr->nominal_value.value_s16); 1083 output["normalMax"] = unsigned(pdr->normal_max.value_s16); 1084 output["normalMin"] = unsigned(pdr->normal_min.value_s16); 1085 output["ratedMax"] = unsigned(pdr->rated_max.value_s16); 1086 output["ratedMin"] = unsigned(pdr->rated_min.value_s16); 1087 break; 1088 case PLDM_RANGE_FIELD_FORMAT_UINT32: 1089 output["nominalValue"] = unsigned(pdr->nominal_value.value_u32); 1090 output["normalMax"] = unsigned(pdr->normal_max.value_u32); 1091 output["normalMin"] = unsigned(pdr->normal_min.value_u32); 1092 output["ratedMax"] = unsigned(pdr->rated_max.value_u32); 1093 output["ratedMin"] = unsigned(pdr->rated_min.value_u32); 1094 break; 1095 case PLDM_RANGE_FIELD_FORMAT_SINT32: 1096 output["nominalValue"] = unsigned(pdr->nominal_value.value_s32); 1097 output["normalMax"] = unsigned(pdr->normal_max.value_s32); 1098 output["normalMin"] = unsigned(pdr->normal_min.value_s32); 1099 output["ratedMax"] = unsigned(pdr->rated_max.value_s32); 1100 output["ratedMin"] = unsigned(pdr->rated_min.value_s32); 1101 break; 1102 case PLDM_RANGE_FIELD_FORMAT_REAL32: 1103 output["nominalValue"] = unsigned(pdr->nominal_value.value_f32); 1104 output["normalMax"] = unsigned(pdr->normal_max.value_f32); 1105 output["normalMin"] = unsigned(pdr->normal_min.value_f32); 1106 output["ratedMax"] = unsigned(pdr->rated_max.value_f32); 1107 output["ratedMin"] = unsigned(pdr->rated_min.value_f32); 1108 break; 1109 default: 1110 break; 1111 } 1112 } 1113 1114 void printStateEffecterPDR(const uint8_t* data, ordered_json& output) 1115 { 1116 auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(data); 1117 1118 output["PLDMTerminusHandle"] = pdr->terminus_handle; 1119 output["effecterID"] = pdr->effecter_id; 1120 output["entityType"] = getEntityName(pdr->entity_type); 1121 output["entityInstanceNumber"] = pdr->entity_instance; 1122 output["containerID"] = pdr->container_id; 1123 output["effecterSemanticID"] = pdr->effecter_semantic_id; 1124 output["effecterInit"] = effecterInit[pdr->effecter_init]; 1125 output["effecterDescriptionPDR"] = 1126 (pdr->has_description_pdr ? true : false); 1127 output["compositeEffecterCount"] = 1128 unsigned(pdr->composite_effecter_count); 1129 1130 auto statesPtr = pdr->possible_states; 1131 auto compEffCount = pdr->composite_effecter_count; 1132 1133 while (compEffCount--) 1134 { 1135 auto state = 1136 reinterpret_cast<const state_effecter_possible_states*>( 1137 statesPtr); 1138 output.emplace(("stateSetID[" + std::to_string(compEffCount) + "]"), 1139 getStateSetName(state->state_set_id)); 1140 output.emplace( 1141 ("possibleStatesSize[" + std::to_string(compEffCount) + "]"), 1142 state->possible_states_size); 1143 output.emplace( 1144 ("possibleStates[" + std::to_string(compEffCount) + "]"), 1145 getStateSetPossibleStateNames( 1146 state->state_set_id, 1147 printPossibleStates(state->possible_states_size, 1148 state->states))); 1149 1150 if (compEffCount) 1151 { 1152 statesPtr += sizeof(state_effecter_possible_states) + 1153 state->possible_states_size - 1; 1154 } 1155 } 1156 } 1157 1158 bool checkTerminusHandle(const uint8_t* data, 1159 std::optional<uint16_t> terminusHandle) 1160 { 1161 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; 1162 1163 if (pdr->type == PLDM_TERMINUS_LOCATOR_PDR) 1164 { 1165 auto tlpdr = 1166 reinterpret_cast<const pldm_terminus_locator_pdr*>(data); 1167 1168 if (tlpdr->terminus_handle != terminusHandle) 1169 { 1170 return true; 1171 } 1172 } 1173 else if (pdr->type == PLDM_STATE_SENSOR_PDR) 1174 { 1175 auto sensor = reinterpret_cast<const pldm_state_sensor_pdr*>(data); 1176 1177 if (sensor->terminus_handle != terminusHandle) 1178 { 1179 return true; 1180 } 1181 } 1182 else if (pdr->type == PLDM_NUMERIC_EFFECTER_PDR) 1183 { 1184 auto numericEffecter = 1185 reinterpret_cast<const pldm_numeric_effecter_value_pdr*>(data); 1186 1187 if (numericEffecter->terminus_handle != terminusHandle) 1188 { 1189 return true; 1190 } 1191 } 1192 1193 else if (pdr->type == PLDM_STATE_EFFECTER_PDR) 1194 { 1195 auto stateEffecter = 1196 reinterpret_cast<const pldm_state_effecter_pdr*>(data); 1197 if (stateEffecter->terminus_handle != terminusHandle) 1198 { 1199 return true; 1200 } 1201 } 1202 else if (pdr->type == PLDM_PDR_FRU_RECORD_SET) 1203 { 1204 data += sizeof(pldm_pdr_hdr); 1205 auto fru = reinterpret_cast<const pldm_pdr_fru_record_set*>(data); 1206 1207 if (fru->terminus_handle != terminusHandle) 1208 { 1209 return true; 1210 } 1211 } 1212 else 1213 { 1214 // Entity association PDRs does not have terminus handle 1215 return true; 1216 } 1217 1218 return false; 1219 } 1220 1221 void printTerminusLocatorPDR(const uint8_t* data, ordered_json& output) 1222 { 1223 const std::array<std::string_view, 4> terminusLocatorType = { 1224 "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"}; 1225 1226 auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data); 1227 1228 output["PLDMTerminusHandle"] = pdr->terminus_handle; 1229 output["validity"] = (pdr->validity ? "valid" : "notValid"); 1230 output["TID"] = unsigned(pdr->tid); 1231 output["containerID"] = pdr->container_id; 1232 output["terminusLocatorType"] = 1233 terminusLocatorType[pdr->terminus_locator_type]; 1234 output["terminusLocatorValueSize"] = 1235 unsigned(pdr->terminus_locator_value_size); 1236 1237 if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID) 1238 { 1239 auto locatorValue = 1240 reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>( 1241 pdr->terminus_locator_value); 1242 output["EID"] = unsigned(locatorValue->eid); 1243 } 1244 } 1245 1246 std::optional<uint16_t> getTerminusHandle(uint8_t* data, 1247 std::optional<uint8_t> tid) 1248 { 1249 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; 1250 if (pdr->type == PLDM_TERMINUS_LOCATOR_PDR) 1251 { 1252 auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data); 1253 if (pdr->tid == tid) 1254 { 1255 handleFound = true; 1256 return pdr->terminus_handle; 1257 } 1258 } 1259 return std::nullopt; 1260 } 1261 1262 /** @brief Format the Numeric Sensor PDR types to json output 1263 * 1264 * @param[in] data - reference to the Numeric Sensor PDR 1265 * @param[in] data_length - number of PDR data bytes 1266 * @param[out] output - PDRs data fields in Json format 1267 */ 1268 void printNumericSensorPDR(const uint8_t* data, const uint16_t data_length, 1269 ordered_json& output) 1270 { 1271 struct pldm_numeric_sensor_value_pdr pdr; 1272 int rc = 1273 decode_numeric_sensor_pdr_data(data, (size_t)data_length, &pdr); 1274 if (rc != PLDM_SUCCESS) 1275 { 1276 std::cerr << "Failed to get numeric sensor PDR" << std::endl; 1277 return; 1278 } 1279 output["PLDMTerminusHandle"] = pdr.terminus_handle; 1280 output["sensorID"] = pdr.sensor_id; 1281 output["entityType"] = getEntityName(pdr.entity_type); 1282 output["entityInstanceNumber"] = pdr.entity_instance_num; 1283 output["containerID"] = pdr.container_id; 1284 output["sensorInit"] = pdr.sensor_init; 1285 output["sensorAuxiliaryNamesPDR"] = 1286 (pdr.sensor_auxiliary_names_pdr) ? true : false; 1287 output["baseUnit"] = pdr.base_unit; 1288 output["unitModifier"] = pdr.unit_modifier; 1289 output["rateUnit"] = pdr.rate_unit; 1290 output["baseOEMUnitHandle"] = pdr.base_oem_unit_handle; 1291 output["auxUnit"] = pdr.aux_unit; 1292 output["auxUnitModifier"] = pdr.aux_unit_modifier; 1293 output["auxrateUnit"] = pdr.aux_rate_unit; 1294 output["rel"] = pdr.rel; 1295 output["auxOEMUnitHandle"] = pdr.aux_oem_unit_handle; 1296 output["isLinear"] = (pdr.is_linear) ? true : false; 1297 output["sensorDataSize"] = pdr.sensor_data_size; 1298 output["resolution"] = pdr.resolution; 1299 output["offset"] = pdr.offset; 1300 output["accuracy"] = pdr.accuracy; 1301 output["plusTolerance"] = pdr.plus_tolerance; 1302 output["minusTolerance"] = pdr.minus_tolerance; 1303 1304 switch (pdr.sensor_data_size) 1305 { 1306 case PLDM_SENSOR_DATA_SIZE_UINT8: 1307 output["hysteresis"] = pdr.hysteresis.value_u8; 1308 output["maxReadable"] = pdr.max_readable.value_u8; 1309 output["minReadable"] = pdr.min_readable.value_u8; 1310 break; 1311 case PLDM_SENSOR_DATA_SIZE_SINT8: 1312 output["hysteresis"] = pdr.hysteresis.value_s8; 1313 output["maxReadable"] = pdr.max_readable.value_s8; 1314 output["minReadable"] = pdr.min_readable.value_s8; 1315 break; 1316 case PLDM_SENSOR_DATA_SIZE_UINT16: 1317 output["hysteresis"] = pdr.hysteresis.value_u16; 1318 output["maxReadable"] = pdr.max_readable.value_u16; 1319 output["minReadable"] = pdr.min_readable.value_u16; 1320 break; 1321 case PLDM_SENSOR_DATA_SIZE_SINT16: 1322 output["hysteresis"] = pdr.hysteresis.value_s16; 1323 output["maxReadable"] = pdr.max_readable.value_s16; 1324 output["minReadable"] = pdr.min_readable.value_s16; 1325 break; 1326 case PLDM_SENSOR_DATA_SIZE_UINT32: 1327 output["hysteresis"] = pdr.hysteresis.value_u32; 1328 output["maxReadable"] = pdr.max_readable.value_u32; 1329 output["minReadable"] = pdr.min_readable.value_u32; 1330 break; 1331 case PLDM_SENSOR_DATA_SIZE_SINT32: 1332 output["hysteresis"] = pdr.hysteresis.value_s32; 1333 output["maxReadable"] = pdr.max_readable.value_s32; 1334 output["minReadable"] = pdr.min_readable.value_s32; 1335 break; 1336 default: 1337 break; 1338 } 1339 1340 output["supportedThresholds"] = pdr.supported_thresholds.byte; 1341 output["thresholAndHysteresisVolatility"] = 1342 pdr.threshold_and_hysteresis_volatility.byte; 1343 output["stateTransitionInterval"] = pdr.state_transition_interval; 1344 output["updateInterval"] = pdr.update_interval; 1345 output["rangeFieldFormat"] = pdr.range_field_format; 1346 output["rangeFieldSupport"] = pdr.range_field_support.byte; 1347 1348 switch (pdr.range_field_format) 1349 { 1350 case PLDM_RANGE_FIELD_FORMAT_UINT8: 1351 output["nominalValue"] = pdr.nominal_value.value_u8; 1352 output["normalMax"] = pdr.normal_max.value_u8; 1353 output["normalMin"] = pdr.normal_min.value_u8; 1354 output["warningHigh"] = pdr.warning_high.value_u8; 1355 output["warningLow"] = pdr.warning_low.value_u8; 1356 output["criticalHigh"] = pdr.critical_high.value_u8; 1357 output["criticalLow"] = pdr.critical_low.value_u8; 1358 output["fatalHigh"] = pdr.fatal_high.value_u8; 1359 output["fatalLeow"] = pdr.fatal_low.value_u8; 1360 break; 1361 case PLDM_RANGE_FIELD_FORMAT_SINT8: 1362 output["nominalValue"] = pdr.nominal_value.value_s8; 1363 output["normalMax"] = pdr.normal_max.value_s8; 1364 output["normalMin"] = pdr.normal_min.value_s8; 1365 output["warningHigh"] = pdr.warning_high.value_s8; 1366 output["warningLow"] = pdr.warning_low.value_s8; 1367 output["criticalHigh"] = pdr.critical_high.value_s8; 1368 output["criticalLow"] = pdr.critical_low.value_s8; 1369 output["fatalHigh"] = pdr.fatal_high.value_s8; 1370 output["fatalLeow"] = pdr.fatal_low.value_s8; 1371 break; 1372 case PLDM_RANGE_FIELD_FORMAT_UINT16: 1373 output["nominalValue"] = pdr.nominal_value.value_u16; 1374 output["normalMax"] = pdr.normal_max.value_u16; 1375 output["normalMin"] = pdr.normal_min.value_u16; 1376 output["warningHigh"] = pdr.warning_high.value_u16; 1377 output["warningLow"] = pdr.warning_low.value_u16; 1378 output["criticalHigh"] = pdr.critical_high.value_u16; 1379 output["criticalLow"] = pdr.critical_low.value_u16; 1380 output["fatalHigh"] = pdr.fatal_high.value_u16; 1381 output["fatalLeow"] = pdr.fatal_low.value_u16; 1382 break; 1383 case PLDM_RANGE_FIELD_FORMAT_SINT16: 1384 output["nominalValue"] = pdr.nominal_value.value_s16; 1385 output["normalMax"] = pdr.normal_max.value_s16; 1386 output["normalMin"] = pdr.normal_min.value_s16; 1387 output["warningHigh"] = pdr.warning_high.value_s16; 1388 output["warningLow"] = pdr.warning_low.value_s16; 1389 output["criticalHigh"] = pdr.critical_high.value_s16; 1390 output["criticalLow"] = pdr.critical_low.value_s16; 1391 output["fatalHigh"] = pdr.fatal_high.value_s16; 1392 output["fatalLeow"] = pdr.fatal_low.value_s16; 1393 break; 1394 case PLDM_RANGE_FIELD_FORMAT_UINT32: 1395 output["nominalValue"] = pdr.nominal_value.value_u32; 1396 output["normalMax"] = pdr.normal_max.value_u32; 1397 output["normalMin"] = pdr.normal_min.value_u32; 1398 output["warningHigh"] = pdr.warning_high.value_u32; 1399 output["warningLow"] = pdr.warning_low.value_u32; 1400 output["criticalHigh"] = pdr.critical_high.value_u32; 1401 output["criticalLow"] = pdr.critical_low.value_u32; 1402 output["fatalHigh"] = pdr.fatal_high.value_u32; 1403 output["fatalLeow"] = pdr.fatal_low.value_u32; 1404 break; 1405 case PLDM_RANGE_FIELD_FORMAT_SINT32: 1406 output["nominalValue"] = pdr.nominal_value.value_s32; 1407 output["normalMax"] = pdr.normal_max.value_s32; 1408 output["normalMin"] = pdr.normal_min.value_s32; 1409 output["warningHigh"] = pdr.warning_high.value_s32; 1410 output["warningLow"] = pdr.warning_low.value_s32; 1411 output["criticalHigh"] = pdr.critical_high.value_s32; 1412 output["criticalLow"] = pdr.critical_low.value_s32; 1413 output["fatalHigh"] = pdr.fatal_high.value_s32; 1414 output["fatalLeow"] = pdr.fatal_low.value_s32; 1415 break; 1416 case PLDM_RANGE_FIELD_FORMAT_REAL32: 1417 output["nominalValue"] = pdr.nominal_value.value_f32; 1418 output["normalMax"] = pdr.normal_max.value_f32; 1419 output["normalMin"] = pdr.normal_min.value_f32; 1420 output["warningHigh"] = pdr.warning_high.value_f32; 1421 output["warningLow"] = pdr.warning_low.value_f32; 1422 output["criticalHigh"] = pdr.critical_high.value_f32; 1423 output["criticalLow"] = pdr.critical_low.value_f32; 1424 output["fatalHigh"] = pdr.fatal_high.value_f32; 1425 output["fatalLeow"] = pdr.fatal_low.value_f32; 1426 break; 1427 default: 1428 break; 1429 } 1430 } 1431 1432 /** @brief Format the Compact Numeric Sensor PDR types to json output 1433 * 1434 * @param[in] data - reference to the Compact Numeric Sensor PDR 1435 * @param[out] output - PDRs data fields in Json format 1436 */ 1437 void printCompactNumericSensorPDR(const uint8_t* data, ordered_json& output) 1438 { 1439 struct pldm_compact_numeric_sensor_pdr* pdr = 1440 (struct pldm_compact_numeric_sensor_pdr*)data; 1441 if (!pdr) 1442 { 1443 std::cerr << "Failed to get compact numeric sensor PDR" 1444 << std::endl; 1445 return; 1446 } 1447 output["PLDMTerminusHandle"] = int(pdr->terminus_handle); 1448 output["sensorID"] = int(pdr->sensor_id); 1449 output["entityType"] = getEntityName(pdr->entity_type); 1450 output["entityInstanceNumber"] = int(pdr->entity_instance); 1451 output["containerID"] = int(pdr->container_id); 1452 output["sensorNameStringByteLength"] = int(pdr->sensor_name_length); 1453 if (pdr->sensor_name_length == 0) 1454 { 1455 output["Name"] = std::format("PLDM_Device_TID{}_SensorId{}", 1456 unsigned(pdr->terminus_handle), 1457 unsigned(pdr->sensor_id)); 1458 } 1459 else 1460 { 1461 std::string sTemp(reinterpret_cast<const char*>(pdr->sensor_name), 1462 pdr->sensor_name_length); 1463 output["Name"] = sTemp; 1464 } 1465 output["baseUnit"] = unsigned(pdr->base_unit); 1466 output["unitModifier"] = signed(pdr->unit_modifier); 1467 output["occurrenceRate"] = unsigned(pdr->occurrence_rate); 1468 output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte); 1469 if (pdr->range_field_support.bits.bit0) 1470 { 1471 output["warningHigh"] = int(pdr->warning_high); 1472 } 1473 if (pdr->range_field_support.bits.bit1) 1474 { 1475 output["warningLow"] = int(pdr->warning_low); 1476 } 1477 if (pdr->range_field_support.bits.bit2) 1478 { 1479 output["criticalHigh"] = int(pdr->critical_high); 1480 } 1481 if (pdr->range_field_support.bits.bit3) 1482 { 1483 output["criticalLow"] = int(pdr->critical_low); 1484 } 1485 if (pdr->range_field_support.bits.bit4) 1486 { 1487 output["fatalHigh"] = int(pdr->fatal_high); 1488 } 1489 if (pdr->range_field_support.bits.bit5) 1490 { 1491 output["fatalLow"] = int(pdr->fatal_low); 1492 } 1493 } 1494 1495 void printPDRMsg(uint32_t& nextRecordHndl, const uint16_t respCnt, 1496 uint8_t* data, std::optional<uint16_t> terminusHandle) 1497 { 1498 if (data == NULL) 1499 { 1500 std::cerr << "Failed to get PDR message" << std::endl; 1501 return; 1502 } 1503 1504 ordered_json output; 1505 output["nextRecordHandle"] = nextRecordHndl; 1506 output["responseCount"] = respCnt; 1507 1508 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; 1509 if (!pdr) 1510 { 1511 return; 1512 } 1513 1514 if (!pdrRecType.empty()) 1515 { 1516 // Need to return if the requested PDR type 1517 // is not supported 1518 if (!strToPdrType.contains(pdrRecType)) 1519 { 1520 std::cerr << "PDR type '" << pdrRecType 1521 << "' is not supported or invalid\n"; 1522 // PDR type not supported, setting next record handle to 1523 // 0 to avoid looping through all PDR records 1524 nextRecordHndl = 0; 1525 return; 1526 } 1527 1528 // Do not print PDR record if the current record 1529 // PDR type does not match with requested type 1530 if (pdr->type != strToPdrType.at(pdrRecType)) 1531 { 1532 return; 1533 } 1534 } 1535 1536 if (pdrTerminus.has_value()) 1537 { 1538 if (checkTerminusHandle(data, terminusHandle)) 1539 { 1540 std::cerr << "The Terminus handle doesn't match return" 1541 << std::endl; 1542 return; 1543 } 1544 } 1545 1546 printCommonPDRHeader(pdr, output); 1547 1548 switch (pdr->type) 1549 { 1550 case PLDM_TERMINUS_LOCATOR_PDR: 1551 printTerminusLocatorPDR(data, output); 1552 break; 1553 case PLDM_STATE_SENSOR_PDR: 1554 printStateSensorPDR(data, output); 1555 break; 1556 case PLDM_NUMERIC_EFFECTER_PDR: 1557 printNumericEffecterPDR(data, output); 1558 break; 1559 case PLDM_NUMERIC_SENSOR_PDR: 1560 printNumericSensorPDR(data, respCnt, output); 1561 break; 1562 case PLDM_SENSOR_AUXILIARY_NAMES_PDR: 1563 printAuxNamePDR(data, output); 1564 break; 1565 case PLDM_EFFECTER_AUXILIARY_NAMES_PDR: 1566 printAuxNamePDR(data, output); 1567 break; 1568 case PLDM_STATE_EFFECTER_PDR: 1569 printStateEffecterPDR(data, output); 1570 break; 1571 case PLDM_PDR_ENTITY_ASSOCIATION: 1572 printPDREntityAssociation(data, output); 1573 break; 1574 case PLDM_PDR_FRU_RECORD_SET: 1575 printPDRFruRecordSet(data, output); 1576 break; 1577 case PLDM_COMPACT_NUMERIC_SENSOR_PDR: 1578 printCompactNumericSensorPDR(data, output); 1579 break; 1580 default: 1581 break; 1582 } 1583 pldmtool::helper::DisplayInJson(output); 1584 } 1585 1586 private: 1587 bool optTIDSet = false; 1588 uint32_t recordHandle; 1589 bool allPDRs; 1590 std::string pdrRecType; 1591 std::optional<uint8_t> pdrTerminus; 1592 std::optional<uint16_t> terminusHandle; 1593 bool handleFound = false; 1594 CLI::Option* getPDRGroupOption = nullptr; 1595 uint32_t dataTransferHandle; 1596 uint8_t operationFlag; 1597 uint16_t requestCount; 1598 uint16_t recordChangeNumber; 1599 std::vector<uint8_t> recordData; 1600 bool nextPartRequired; 1601 }; 1602 1603 class SetStateEffecter : public CommandInterface 1604 { 1605 public: 1606 ~SetStateEffecter() = default; 1607 SetStateEffecter() = delete; 1608 SetStateEffecter(const SetStateEffecter&) = delete; 1609 SetStateEffecter(SetStateEffecter&&) = default; 1610 SetStateEffecter& operator=(const SetStateEffecter&) = delete; 1611 SetStateEffecter& operator=(SetStateEffecter&&) = delete; 1612 1613 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2) 1614 static constexpr auto maxEffecterDataSize = 16; 1615 1616 // compositeEffecterCount(value: 0x01 to 0x08) 1617 static constexpr auto minEffecterCount = 1; 1618 static constexpr auto maxEffecterCount = 8; 1619 explicit SetStateEffecter(const char* type, const char* name, 1620 CLI::App* app) : CommandInterface(type, name, app) 1621 { 1622 app->add_option( 1623 "-i, --id", effecterId, 1624 "A handle that is used to identify and access the effecter") 1625 ->required(); 1626 app->add_option("-c, --count", effecterCount, 1627 "The number of individual sets of effecter information") 1628 ->required(); 1629 app->add_option( 1630 "-d,--data", effecterData, 1631 "Set effecter state data\n" 1632 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...") 1633 ->required(); 1634 } 1635 1636 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1637 { 1638 std::vector<uint8_t> requestMsg( 1639 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES); 1640 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1641 1642 if (effecterCount > maxEffecterCount || 1643 effecterCount < minEffecterCount) 1644 { 1645 std::cerr << "Request Message Error: effecterCount size " 1646 << effecterCount << "is invalid\n"; 1647 auto rc = PLDM_ERROR_INVALID_DATA; 1648 return {rc, requestMsg}; 1649 } 1650 1651 if (effecterData.size() > maxEffecterDataSize) 1652 { 1653 std::cerr << "Request Message Error: effecterData size " 1654 << effecterData.size() << "is invalid\n"; 1655 auto rc = PLDM_ERROR_INVALID_DATA; 1656 return {rc, requestMsg}; 1657 } 1658 1659 auto stateField = parseEffecterData(effecterData, effecterCount); 1660 if (!stateField) 1661 { 1662 std::cerr << "Failed to parse effecter data, effecterCount size " 1663 << effecterCount << "\n"; 1664 auto rc = PLDM_ERROR_INVALID_DATA; 1665 return {rc, requestMsg}; 1666 } 1667 1668 auto rc = encode_set_state_effecter_states_req( 1669 instanceId, effecterId, effecterCount, stateField->data(), request); 1670 return {rc, requestMsg}; 1671 } 1672 1673 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1674 { 1675 uint8_t completionCode = 0; 1676 auto rc = decode_set_state_effecter_states_resp( 1677 responsePtr, payloadLength, &completionCode); 1678 1679 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1680 { 1681 std::cerr << "Response Message Error: " 1682 << "rc=" << rc << ",cc=" << (int)completionCode << "\n"; 1683 return; 1684 } 1685 1686 ordered_json data; 1687 data["Response"] = "SUCCESS"; 1688 pldmtool::helper::DisplayInJson(data); 1689 } 1690 1691 private: 1692 uint16_t effecterId; 1693 uint8_t effecterCount; 1694 std::vector<uint8_t> effecterData; 1695 }; 1696 1697 class SetNumericEffecterValue : public CommandInterface 1698 { 1699 public: 1700 ~SetNumericEffecterValue() = default; 1701 SetNumericEffecterValue() = delete; 1702 SetNumericEffecterValue(const SetNumericEffecterValue&) = delete; 1703 SetNumericEffecterValue(SetNumericEffecterValue&&) = default; 1704 SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete; 1705 SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = delete; 1706 1707 explicit SetNumericEffecterValue(const char* type, const char* name, 1708 CLI::App* app) : 1709 CommandInterface(type, name, app) 1710 { 1711 app->add_option( 1712 "-i, --id", effecterId, 1713 "A handle that is used to identify and access the effecter") 1714 ->required(); 1715 app->add_option("-s, --size", effecterDataSize, 1716 "The bit width and format of the setting value for the " 1717 "effecter. enum value: {uint8, sint8, uint16, sint16, " 1718 "uint32, sint32}\n") 1719 ->required(); 1720 app->add_option("-d,--data", maxEffecterValue, 1721 "The setting value of numeric effecter being " 1722 "requested\n") 1723 ->required(); 1724 } 1725 1726 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1727 { 1728 std::vector<uint8_t> requestMsg( 1729 sizeof(pldm_msg_hdr) + 1730 PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3); 1731 1732 uint8_t* effecterValue = (uint8_t*)&maxEffecterValue; 1733 1734 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1735 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES; 1736 1737 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 || 1738 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) 1739 { 1740 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1; 1741 } 1742 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 || 1743 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) 1744 { 1745 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3; 1746 } 1747 auto rc = encode_set_numeric_effecter_value_req( 1748 0, effecterId, effecterDataSize, effecterValue, request, 1749 payload_length); 1750 1751 return {rc, requestMsg}; 1752 } 1753 1754 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1755 { 1756 uint8_t completionCode = 0; 1757 auto rc = decode_set_numeric_effecter_value_resp( 1758 responsePtr, payloadLength, &completionCode); 1759 1760 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1761 { 1762 std::cerr << "Response Message Error: " 1763 << "rc=" << rc << ",cc=" << (int)completionCode 1764 << std::endl; 1765 return; 1766 } 1767 1768 ordered_json data; 1769 data["Response"] = "SUCCESS"; 1770 pldmtool::helper::DisplayInJson(data); 1771 } 1772 1773 private: 1774 uint16_t effecterId; 1775 uint8_t effecterDataSize; 1776 uint64_t maxEffecterValue; 1777 }; 1778 1779 class GetStateSensorReadings : public CommandInterface 1780 { 1781 public: 1782 ~GetStateSensorReadings() = default; 1783 GetStateSensorReadings() = delete; 1784 GetStateSensorReadings(const GetStateSensorReadings&) = delete; 1785 GetStateSensorReadings(GetStateSensorReadings&&) = default; 1786 GetStateSensorReadings& operator=(const GetStateSensorReadings&) = delete; 1787 GetStateSensorReadings& operator=(GetStateSensorReadings&&) = delete; 1788 1789 explicit GetStateSensorReadings(const char* type, const char* name, 1790 CLI::App* app) : 1791 CommandInterface(type, name, app) 1792 { 1793 app->add_option( 1794 "-i, --sensor_id", sensorId, 1795 "Sensor ID that is used to identify and access the sensor") 1796 ->required(); 1797 app->add_option("-r, --rearm", sensorRearm, 1798 "Each bit location in this field corresponds to a " 1799 "particular sensor") 1800 ->required(); 1801 } 1802 1803 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1804 { 1805 std::vector<uint8_t> requestMsg( 1806 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES); 1807 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1808 1809 uint8_t reserved = 0; 1810 bitfield8_t bf; 1811 bf.byte = sensorRearm; 1812 auto rc = encode_get_state_sensor_readings_req(instanceId, sensorId, bf, 1813 reserved, request); 1814 1815 return {rc, requestMsg}; 1816 } 1817 1818 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1819 { 1820 uint8_t completionCode = 0; 1821 uint8_t compSensorCount = 0; 1822 std::array<get_sensor_state_field, 8> stateField{}; 1823 auto rc = decode_get_state_sensor_readings_resp( 1824 responsePtr, payloadLength, &completionCode, &compSensorCount, 1825 stateField.data()); 1826 1827 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1828 { 1829 std::cerr << "Response Message Error: " 1830 << "rc=" << rc << ",cc=" << (int)completionCode 1831 << std::endl; 1832 return; 1833 } 1834 ordered_json output; 1835 output["compositeSensorCount"] = (int)compSensorCount; 1836 1837 for (size_t i = 0; i < compSensorCount; i++) 1838 { 1839 if (sensorOpState.contains(stateField[i].sensor_op_state)) 1840 { 1841 output.emplace(("sensorOpState[" + std::to_string(i) + "]"), 1842 sensorOpState.at(stateField[i].sensor_op_state)); 1843 } 1844 1845 if (sensorPresState.contains(stateField[i].present_state)) 1846 { 1847 output.emplace(("presentState[" + std::to_string(i) + "]"), 1848 sensorPresState.at(stateField[i].present_state)); 1849 } 1850 1851 if (sensorPresState.contains(stateField[i].previous_state)) 1852 { 1853 output.emplace( 1854 ("previousState[" + std::to_string(i) + "]"), 1855 sensorPresState.at(stateField[i].previous_state)); 1856 } 1857 1858 if (sensorPresState.contains(stateField[i].event_state)) 1859 { 1860 output.emplace(("eventState[" + std::to_string(i) + "]"), 1861 sensorPresState.at(stateField[i].event_state)); 1862 } 1863 } 1864 1865 pldmtool::helper::DisplayInJson(output); 1866 } 1867 1868 private: 1869 uint16_t sensorId; 1870 uint8_t sensorRearm; 1871 }; 1872 1873 class GetSensorReading : public CommandInterface 1874 { 1875 public: 1876 ~GetSensorReading() = default; 1877 GetSensorReading() = delete; 1878 GetSensorReading(const GetSensorReading&) = delete; 1879 GetSensorReading(GetSensorReading&&) = default; 1880 GetSensorReading& operator=(const GetSensorReading&) = delete; 1881 GetSensorReading& operator=(GetSensorReading&&) = delete; 1882 1883 explicit GetSensorReading(const char* type, const char* name, 1884 CLI::App* app) : CommandInterface(type, name, app) 1885 { 1886 app->add_option( 1887 "-i, --sensor_id", sensorId, 1888 "Sensor ID that is used to identify and access the sensor") 1889 ->required(); 1890 app->add_option("-r, --rearm", rearm, 1891 "Manually re-arm EventState after " 1892 "responding to this request") 1893 ->required(); 1894 } 1895 1896 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1897 { 1898 std::vector<uint8_t> requestMsg( 1899 sizeof(pldm_msg_hdr) + PLDM_GET_SENSOR_READING_REQ_BYTES); 1900 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1901 1902 auto rc = 1903 encode_get_sensor_reading_req(instanceId, sensorId, rearm, request); 1904 1905 return {rc, requestMsg}; 1906 } 1907 1908 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1909 { 1910 uint8_t completionCode = 0; 1911 uint8_t sensorDataSize = 0; 1912 uint8_t sensorOperationalState = 0; 1913 uint8_t sensorEventMessageEnable = 0; 1914 uint8_t presentState = 0; 1915 uint8_t previousState = 0; 1916 uint8_t eventState = 0; 1917 std::array<uint8_t, sizeof(uint32_t)> 1918 presentReading{}; // maximum size for the present Value is uint32 1919 // according to spec DSP0248 1920 1921 auto rc = decode_get_sensor_reading_resp( 1922 responsePtr, payloadLength, &completionCode, &sensorDataSize, 1923 &sensorOperationalState, &sensorEventMessageEnable, &presentState, 1924 &previousState, &eventState, presentReading.data()); 1925 1926 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1927 { 1928 std::cerr << "Response Message Error: " 1929 << "rc=" << rc << ",cc=" << (int)completionCode 1930 << std::endl; 1931 return; 1932 } 1933 1934 ordered_json output; 1935 output["sensorDataSize"] = 1936 getSensorState(sensorDataSize, &sensorDataSz); 1937 output["sensorOperationalState"] = 1938 getSensorState(sensorOperationalState, &sensorOpState); 1939 output["sensorEventMessageEnable"] = 1940 getSensorState(sensorEventMessageEnable, &sensorEventMsgEnable); 1941 output["presentState"] = getSensorState(presentState, &sensorPresState); 1942 output["previousState"] = 1943 getSensorState(previousState, &sensorPresState); 1944 output["eventState"] = getSensorState(eventState, &sensorPresState); 1945 1946 switch (sensorDataSize) 1947 { 1948 case PLDM_SENSOR_DATA_SIZE_UINT8: 1949 { 1950 output["presentReading"] = 1951 *(reinterpret_cast<uint8_t*>(presentReading.data())); 1952 break; 1953 } 1954 case PLDM_SENSOR_DATA_SIZE_SINT8: 1955 { 1956 output["presentReading"] = 1957 *(reinterpret_cast<int8_t*>(presentReading.data())); 1958 break; 1959 } 1960 case PLDM_SENSOR_DATA_SIZE_UINT16: 1961 { 1962 output["presentReading"] = 1963 *(reinterpret_cast<uint16_t*>(presentReading.data())); 1964 break; 1965 } 1966 case PLDM_SENSOR_DATA_SIZE_SINT16: 1967 { 1968 output["presentReading"] = 1969 *(reinterpret_cast<int16_t*>(presentReading.data())); 1970 break; 1971 } 1972 case PLDM_SENSOR_DATA_SIZE_UINT32: 1973 { 1974 output["presentReading"] = 1975 *(reinterpret_cast<uint32_t*>(presentReading.data())); 1976 break; 1977 } 1978 case PLDM_SENSOR_DATA_SIZE_SINT32: 1979 { 1980 output["presentReading"] = 1981 *(reinterpret_cast<int32_t*>(presentReading.data())); 1982 break; 1983 } 1984 default: 1985 { 1986 std::cerr << "Unknown Sensor Data Size : " 1987 << static_cast<int>(sensorDataSize) << std::endl; 1988 break; 1989 } 1990 } 1991 1992 pldmtool::helper::DisplayInJson(output); 1993 } 1994 1995 private: 1996 uint16_t sensorId; 1997 uint8_t rearm; 1998 1999 const std::map<uint8_t, std::string> sensorDataSz = { 2000 {PLDM_SENSOR_DATA_SIZE_UINT8, "uint8"}, 2001 {PLDM_SENSOR_DATA_SIZE_SINT8, "uint8"}, 2002 {PLDM_SENSOR_DATA_SIZE_UINT16, "uint16"}, 2003 {PLDM_SENSOR_DATA_SIZE_SINT16, "uint16"}, 2004 {PLDM_SENSOR_DATA_SIZE_UINT32, "uint32"}, 2005 {PLDM_SENSOR_DATA_SIZE_SINT32, "uint32"}}; 2006 2007 static inline const std::map<uint8_t, std::string> sensorEventMsgEnable{ 2008 {PLDM_NO_EVENT_GENERATION, "Sensor No Event Generation"}, 2009 {PLDM_EVENTS_DISABLED, "Sensor Events Disabled"}, 2010 {PLDM_EVENTS_ENABLED, "Sensor Events Enabled"}, 2011 {PLDM_OP_EVENTS_ONLY_ENABLED, "Sensor Op Events Only Enabled"}, 2012 {PLDM_STATE_EVENTS_ONLY_ENABLED, "Sensor State Events Only Enabled"}}; 2013 2014 std::string getSensorState(uint8_t state, 2015 const std::map<uint8_t, std::string>* cont) 2016 { 2017 auto typeString = std::to_string(state); 2018 try 2019 { 2020 return cont->at(state); 2021 } 2022 catch (const std::out_of_range& e) 2023 { 2024 return typeString; 2025 } 2026 } 2027 }; 2028 2029 class GetStateEffecterStates : public CommandInterface 2030 { 2031 public: 2032 ~GetStateEffecterStates() = default; 2033 GetStateEffecterStates() = delete; 2034 GetStateEffecterStates(const GetStateEffecterStates&) = delete; 2035 GetStateEffecterStates(GetStateEffecterStates&&) = default; 2036 GetStateEffecterStates& operator=(const GetStateEffecterStates&) = delete; 2037 GetStateEffecterStates& operator=(GetStateEffecterStates&&) = delete; 2038 2039 explicit GetStateEffecterStates(const char* type, const char* name, 2040 CLI::App* app) : 2041 CommandInterface(type, name, app) 2042 { 2043 app->add_option( 2044 "-i, --effecter_id", effecter_id, 2045 "Effecter ID that is used to identify and access the effecter") 2046 ->required(); 2047 } 2048 2049 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 2050 { 2051 std::vector<uint8_t> requestMsg( 2052 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES); 2053 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 2054 2055 auto rc = encode_get_state_effecter_states_req( 2056 instanceId, effecter_id, request, 2057 PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES); 2058 2059 return {rc, requestMsg}; 2060 } 2061 2062 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 2063 { 2064 struct pldm_get_state_effecter_states_resp resp; 2065 auto rc = decode_get_state_effecter_states_resp(responsePtr, 2066 payloadLength, &resp); 2067 2068 if (rc || resp.completion_code != PLDM_SUCCESS) 2069 { 2070 std::cerr << "Response Message Error: " 2071 << "rc=" << rc << ",cc=" 2072 << static_cast<int>(resp.completion_code) << std::endl; 2073 return; 2074 } 2075 ordered_json output; 2076 auto comp_effecter_count = static_cast<int>(resp.comp_effecter_count); 2077 output["compositeEffecterCount"] = comp_effecter_count; 2078 2079 for (auto i : std::views::iota(0, comp_effecter_count)) 2080 { 2081 output[std::format("effecterOpState[{}])", i)] = 2082 getEffecterOpState(resp.field[i].effecter_op_state); 2083 2084 output[std::format("pendingState[{}]", i)] = 2085 resp.field[i].pending_state; 2086 2087 output[std::format("presentState[{}]", i)] = 2088 resp.field[i].present_state; 2089 } 2090 2091 pldmtool::helper::DisplayInJson(output); 2092 } 2093 2094 private: 2095 uint16_t effecter_id; 2096 }; 2097 2098 class GetNumericEffecterValue : public CommandInterface 2099 { 2100 public: 2101 ~GetNumericEffecterValue() = default; 2102 GetNumericEffecterValue() = delete; 2103 GetNumericEffecterValue(const GetNumericEffecterValue&) = delete; 2104 GetNumericEffecterValue(GetNumericEffecterValue&&) = default; 2105 GetNumericEffecterValue& operator=(const GetNumericEffecterValue&) = delete; 2106 GetNumericEffecterValue& operator=(GetNumericEffecterValue&&) = delete; 2107 2108 explicit GetNumericEffecterValue(const char* type, const char* name, 2109 CLI::App* app) : 2110 CommandInterface(type, name, app) 2111 { 2112 app->add_option( 2113 "-i, --effecter_id", effecterId, 2114 "A handle that is used to identify and access the effecter") 2115 ->required(); 2116 } 2117 2118 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 2119 { 2120 std::vector<uint8_t> requestMsg( 2121 sizeof(pldm_msg_hdr) + PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES); 2122 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 2123 2124 auto rc = encode_get_numeric_effecter_value_req(instanceId, effecterId, 2125 request); 2126 2127 return {rc, requestMsg}; 2128 } 2129 2130 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 2131 { 2132 uint8_t completionCode = 0; 2133 uint8_t effecterDataSize = 0; 2134 uint8_t effecterOperationalState = 0; 2135 std::array<uint8_t, sizeof(uint32_t)> 2136 pendingValue{}; // maximum size for the pending Value is uint32 2137 // according to spec DSP0248 2138 std::array<uint8_t, sizeof(uint32_t)> 2139 presentValue{}; // maximum size for the present Value is uint32 2140 // according to spec DSP0248 2141 2142 auto rc = decode_get_numeric_effecter_value_resp( 2143 responsePtr, payloadLength, &completionCode, &effecterDataSize, 2144 &effecterOperationalState, pendingValue.data(), 2145 presentValue.data()); 2146 2147 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 2148 { 2149 std::cerr << "Response Message Error: " 2150 << "rc=" << rc << ",cc=" 2151 << static_cast<int>(completionCode) << std::endl; 2152 return; 2153 } 2154 2155 ordered_json output; 2156 output["effecterDataSize"] = static_cast<int>(effecterDataSize); 2157 output["effecterOperationalState"] = 2158 getEffecterOpState(effecterOperationalState); 2159 2160 switch (effecterDataSize) 2161 { 2162 case PLDM_EFFECTER_DATA_SIZE_UINT8: 2163 { 2164 output["pendingValue"] = 2165 *(reinterpret_cast<uint8_t*>(pendingValue.data())); 2166 output["presentValue"] = 2167 *(reinterpret_cast<uint8_t*>(presentValue.data())); 2168 break; 2169 } 2170 case PLDM_EFFECTER_DATA_SIZE_SINT8: 2171 { 2172 output["pendingValue"] = 2173 *(reinterpret_cast<int8_t*>(pendingValue.data())); 2174 output["presentValue"] = 2175 *(reinterpret_cast<int8_t*>(presentValue.data())); 2176 break; 2177 } 2178 case PLDM_EFFECTER_DATA_SIZE_UINT16: 2179 { 2180 output["pendingValue"] = 2181 *(reinterpret_cast<uint16_t*>(pendingValue.data())); 2182 output["presentValue"] = 2183 *(reinterpret_cast<uint16_t*>(presentValue.data())); 2184 break; 2185 } 2186 case PLDM_EFFECTER_DATA_SIZE_SINT16: 2187 { 2188 output["pendingValue"] = 2189 *(reinterpret_cast<int16_t*>(pendingValue.data())); 2190 output["presentValue"] = 2191 *(reinterpret_cast<int16_t*>(presentValue.data())); 2192 break; 2193 } 2194 case PLDM_EFFECTER_DATA_SIZE_UINT32: 2195 { 2196 output["pendingValue"] = 2197 *(reinterpret_cast<uint32_t*>(pendingValue.data())); 2198 output["presentValue"] = 2199 *(reinterpret_cast<uint32_t*>(presentValue.data())); 2200 break; 2201 } 2202 case PLDM_EFFECTER_DATA_SIZE_SINT32: 2203 { 2204 output["pendingValue"] = 2205 *(reinterpret_cast<int32_t*>(pendingValue.data())); 2206 output["presentValue"] = 2207 *(reinterpret_cast<int32_t*>(presentValue.data())); 2208 break; 2209 } 2210 default: 2211 { 2212 std::cerr << "Unknown Effecter Data Size : " 2213 << static_cast<int>(effecterDataSize) << std::endl; 2214 break; 2215 } 2216 } 2217 2218 pldmtool::helper::DisplayInJson(output); 2219 } 2220 2221 private: 2222 uint16_t effecterId; 2223 }; 2224 2225 void registerCommand(CLI::App& app) 2226 { 2227 auto platform = app.add_subcommand("platform", "platform type command"); 2228 platform->require_subcommand(1); 2229 2230 auto getPDR = 2231 platform->add_subcommand("GetPDR", "get platform descriptor records"); 2232 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR)); 2233 2234 auto setStateEffecterStates = platform->add_subcommand( 2235 "SetStateEffecterStates", "set effecter states"); 2236 commands.push_back(std::make_unique<SetStateEffecter>( 2237 "platform", "setStateEffecterStates", setStateEffecterStates)); 2238 2239 auto setNumericEffecterValue = platform->add_subcommand( 2240 "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter"); 2241 commands.push_back(std::make_unique<SetNumericEffecterValue>( 2242 "platform", "setNumericEffecterValue", setNumericEffecterValue)); 2243 2244 auto getStateSensorReadings = platform->add_subcommand( 2245 "GetStateSensorReadings", "get the state sensor readings"); 2246 commands.push_back(std::make_unique<GetStateSensorReadings>( 2247 "platform", "getStateSensorReadings", getStateSensorReadings)); 2248 2249 auto getNumericEffecterValue = platform->add_subcommand( 2250 "GetNumericEffecterValue", "get the numeric effecter value"); 2251 commands.push_back(std::make_unique<GetNumericEffecterValue>( 2252 "platform", "getNumericEffecterValue", getNumericEffecterValue)); 2253 2254 auto getSensorReading = platform->add_subcommand( 2255 "GetSensorReading", "get the numeric sensor reading"); 2256 commands.push_back(std::make_unique<GetSensorReading>( 2257 "platform", "getSensorReading", getSensorReading)); 2258 2259 auto getStateEffecterStates = platform->add_subcommand( 2260 "GetStateEffecterStates", "get the state effecter states"); 2261 commands.push_back(std::make_unique<GetStateEffecterStates>( 2262 "platform", "getStateEffecterStates", getStateEffecterStates)); 2263 } 2264 2265 void parseGetPDROption() 2266 { 2267 for (const auto& command : commands) 2268 { 2269 if (command.get()->getPLDMType() == "platform" && 2270 command.get()->getCommandName() == "getPDR") 2271 { 2272 auto getPDR = dynamic_cast<GetPDR*>(command.get()); 2273 getPDR->parseGetPDROptions(); 2274 } 2275 } 2276 } 2277 2278 } // namespace platform 2279 } // namespace pldmtool 2280