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("-t, --type", pdrRecType, 104 "retrieve all PDRs of the requested type\n" 105 "supported types:\n" 106 "[terminusLocator, stateSensor, " 107 "numericEffecter, stateEffecter, " 108 "compactNumericSensor, sensorauxname, " 109 "efffecterAuxName, numericsensor, " 110 "EntityAssociation, fruRecord, ... ]"); 111 112 getPDRGroupOption = pdrOptionGroup->add_option( 113 "-i, --terminusID", pdrTerminus, 114 "retrieve all PDRs of the requested terminusID\n" 115 "supported IDs:\n [1, 2, 208...]"); 116 117 allPDRs = false; 118 pdrOptionGroup->add_flag("-a, --all", allPDRs, 119 "retrieve all PDRs from a PDR repository"); 120 121 pdrOptionGroup->require_option(1); 122 } 123 124 void parseGetPDROptions() 125 { 126 optTIDSet = false; 127 if (getPDRGroupOption->count() > 0) 128 { 129 optTIDSet = true; 130 getPDRs(); 131 } 132 } 133 134 void getPDRs() 135 { 136 // start the array 137 std::cout << "["; 138 139 recordHandle = 0; 140 do 141 { 142 CommandInterface::exec(); 143 } while (recordHandle != 0); 144 145 // close the array 146 std::cout << "]\n"; 147 148 if (handleFound) 149 { 150 recordHandle = 0; 151 uint32_t prevRecordHandle = 0; 152 do 153 { 154 CommandInterface::exec(); 155 if (recordHandle == prevRecordHandle) 156 { 157 return; 158 } 159 prevRecordHandle = recordHandle; 160 } while (recordHandle != 0); 161 } 162 } 163 164 void exec() override 165 { 166 if (allPDRs || !pdrRecType.empty()) 167 { 168 if (!pdrRecType.empty()) 169 { 170 std::transform(pdrRecType.begin(), pdrRecType.end(), 171 pdrRecType.begin(), tolower); 172 } 173 174 // start the array 175 std::cout << "[\n"; 176 177 // Retrieve all PDR records starting from the first 178 recordHandle = 0; 179 uint32_t prevRecordHandle = 0; 180 std::map<uint32_t, uint32_t> recordsSeen; 181 do 182 { 183 CommandInterface::exec(); 184 // recordHandle is updated to nextRecord when 185 // CommandInterface::exec() is successful. 186 // In case of any error, return. 187 if (recordHandle == prevRecordHandle && !nextPartRequired) 188 { 189 return; 190 } 191 192 // check for circular references. 193 auto result = recordsSeen.emplace(recordHandle, 194 prevRecordHandle); 195 if (!result.second && !nextPartRequired) 196 { 197 std::cerr 198 << "Record handle " << recordHandle 199 << " has multiple references: " << result.first->second 200 << ", " << prevRecordHandle << "\n"; 201 return; 202 } 203 prevRecordHandle = recordHandle; 204 205 if (recordHandle != 0) 206 { 207 // close the array 208 std::cout << ","; 209 } 210 } while (recordHandle != 0); 211 212 // close the array 213 std::cout << "]\n"; 214 } 215 else 216 { 217 do 218 { 219 CommandInterface::exec(); 220 } while (nextPartRequired); 221 } 222 } 223 224 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 225 { 226 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 227 PLDM_GET_PDR_REQ_BYTES); 228 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 229 230 auto rc = encode_get_pdr_req( 231 instanceId, recordHandle, dataTransferHandle, operationFlag, 232 requestCount, recordChangeNumber, request, PLDM_GET_PDR_REQ_BYTES); 233 return {rc, requestMsg}; 234 } 235 236 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 237 { 238 uint8_t completionCode = 0; 239 uint8_t respRecordData[UINT16_MAX] = {0}; 240 uint32_t nextRecordHndl = 0; 241 uint32_t nextDataTransferHndl = 0; 242 uint8_t transferFlag = 0; 243 uint16_t respCnt = 0; 244 uint8_t transferCRC = 0; 245 246 auto rc = decode_get_pdr_resp( 247 responsePtr, payloadLength, &completionCode, &nextRecordHndl, 248 &nextDataTransferHndl, &transferFlag, &respCnt, respRecordData, 249 sizeof(respRecordData), &transferCRC); 250 251 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 252 { 253 std::cerr << "Response Message Error: " 254 << "rc=" << rc << ",cc=" << (int)completionCode 255 << std::endl; 256 nextPartRequired = false; 257 return; 258 } 259 260 if (optTIDSet && !handleFound) 261 { 262 terminusHandle = getTerminusHandle(respRecordData, pdrTerminus); 263 if (terminusHandle.has_value()) 264 { 265 recordHandle = 0; 266 return; 267 } 268 else 269 { 270 recordHandle = nextRecordHndl; 271 return; 272 } 273 } 274 else 275 { 276 recordData.insert(recordData.end(), respRecordData, 277 respRecordData + respCnt); 278 279 // End or StartAndEnd 280 if (transferFlag == PLDM_PLATFORM_TRANSFER_END || 281 transferFlag == PLDM_PLATFORM_TRANSFER_START_AND_END) 282 { 283 printPDRMsg(nextRecordHndl, respCnt, recordData.data(), 284 terminusHandle); 285 nextPartRequired = false; 286 recordHandle = nextRecordHndl; 287 dataTransferHandle = 0; 288 recordChangeNumber = 0; 289 operationFlag = PLDM_GET_FIRSTPART; 290 recordData.clear(); 291 } 292 else 293 { 294 nextPartRequired = true; 295 dataTransferHandle = nextDataTransferHndl; 296 struct pldm_pdr_hdr* pdr_hdr = 297 reinterpret_cast<struct pldm_pdr_hdr*>(respRecordData); 298 recordChangeNumber = pdr_hdr->record_change_num; 299 operationFlag = PLDM_GET_NEXTPART; 300 } 301 } 302 } 303 304 private: 305 const std::map<pldm::pdr::EntityType, std::string> entityType = { 306 {PLDM_ENTITY_UNSPECIFIED, "Unspecified"}, 307 {PLDM_ENTITY_OTHER, "Other"}, 308 {PLDM_ENTITY_NETWORK, "Network"}, 309 {PLDM_ENTITY_GROUP, "Group"}, 310 {PLDM_ENTITY_REMOTE_MGMT_COMM_DEVICE, 311 "Remote Management Communication Device"}, 312 {PLDM_ENTITY_EXTERNAL_ENVIRONMENT, "External Environment"}, 313 {PLDM_ENTITY_COMM_CHANNEL, " Communication Channel"}, 314 {PLDM_ENTITY_TERMINUS, "PLDM Terminus"}, 315 {PLDM_ENTITY_PLATFORM_EVENT_LOG, " Platform Event Log"}, 316 {PLDM_ENTITY_KEYPAD, "keypad"}, 317 {PLDM_ENTITY_SWITCH, "Switch"}, 318 {PLDM_ENTITY_PUSHBUTTON, "Pushbutton"}, 319 {PLDM_ENTITY_DISPLAY, "Display"}, 320 {PLDM_ENTITY_INDICATOR, "Indicator"}, 321 {PLDM_ENTITY_SYS_MGMT_SW, "System Management Software"}, 322 {PLDM_ENTITY_SYS_FIRMWARE, "System Firmware"}, 323 {PLDM_ENTITY_OPERATING_SYS, "Operating System"}, 324 {PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER, "Virtual Machine Manager"}, 325 {PLDM_ENTITY_OS_LOADER, "OS Loader"}, 326 {PLDM_ENTITY_DEVICE_DRIVER, "Device Driver"}, 327 {PLDM_ENTITY_MGMT_CONTROLLER_FW, "Management Controller Firmware"}, 328 {PLDM_ENTITY_SYSTEM_CHASSIS, "System chassis (main enclosure)"}, 329 {PLDM_ENTITY_SUB_CHASSIS, "Sub-chassis"}, 330 {PLDM_ENTITY_DISK_DRIVE_BAY, "Disk Drive Bay"}, 331 {PLDM_ENTITY_PERIPHERAL_BAY, "Peripheral Bay"}, 332 {PLDM_ENTITY_DEVICE_BAY, "Device bay"}, 333 {PLDM_ENTITY_DOOR, "Door"}, 334 {PLDM_ENTITY_ACCESS_PANEL, "Access Panel"}, 335 {PLDM_ENTITY_COVER, "Cover"}, 336 {PLDM_ENTITY_BOARD, "Board"}, 337 {PLDM_ENTITY_CARD, "Card"}, 338 {PLDM_ENTITY_MODULE, "Module"}, 339 {PLDM_ENTITY_SYS_MGMT_MODULE, "System management module"}, 340 {PLDM_ENTITY_SYS_BOARD, "System Board"}, 341 {PLDM_ENTITY_MEMORY_BOARD, "Memory Board"}, 342 {PLDM_ENTITY_MEMORY_MODULE, "Memory Module"}, 343 {PLDM_ENTITY_PROC_MODULE, "Processor Module"}, 344 {PLDM_ENTITY_ADD_IN_CARD, "Add-in Card"}, 345 {PLDM_ENTITY_CHASSIS_FRONT_PANEL_BOARD, 346 "Chassis front panel board(control panel)"}, 347 {PLDM_ENTITY_BACK_PANEL_BOARD, "Back panel board"}, 348 {PLDM_ENTITY_POWER_MGMT, "Power management board"}, 349 {PLDM_ENTITY_POWER_SYS_BOARD, "Power system board"}, 350 {PLDM_ENTITY_DRIVE_BACKPLANE, "Drive backplane"}, 351 {PLDM_ENTITY_SYS_INTERNAL_EXPANSION_BOARD, 352 "System internal expansion board"}, 353 {PLDM_ENTITY_OTHER_SYS_BOARD, "Other system board"}, 354 {PLDM_ENTITY_CHASSIS_BACK_PANEL_BOARD, "Chassis back panel board"}, 355 {PLDM_ENTITY_PROCESSING_BLADE, "Processing blade"}, 356 {PLDM_ENTITY_CONNECTIVITY_SWITCH, "Connectivity switch"}, 357 {PLDM_ENTITY_PROC_MEMORY_MODULE, "Processor/Memory Module"}, 358 {PLDM_ENTITY_IO_MODULE, "I/O Module"}, 359 {PLDM_ENTITY_PROC_IO_MODULE, "Processor I/O Module"}, 360 {PLDM_ENTITY_COOLING_DEVICE, "Cooling device"}, 361 {PLDM_ENTITY_COOLING_SUBSYSTEM, "Cooling subsystem"}, 362 {PLDM_ENTITY_COOLING_UNIT, "Cooling Unit"}, 363 {PLDM_ENTITY_FAN, "Fan"}, 364 {PLDM_ENTITY_PELTIER_COOLING_DEVICE, "Peltier Cooling Device"}, 365 {PLDM_ENTITY_LIQUID_COOLING_DEVICE, "Liquid Cooling Device"}, 366 {PLDM_ENTITY_LIQUID_COOLING_SUBSYSTEM, "Liquid Colling Subsystem"}, 367 {PLDM_ENTITY_OTHER_STORAGE_DEVICE, "Other Storage Device"}, 368 {PLDM_ENTITY_FLOPPY_DRIVE, "Floppy Drive"}, 369 {PLDM_ENTITY_FIXED_DISK_HARD_DRIVE, "Hard Drive"}, 370 {PLDM_ENTITY_CD_DRIVE, "CD Drive"}, 371 {PLDM_ENTITY_CD_DVD_DRIVE, "CD/DVD Drive"}, 372 {PLDM_ENTITY_OTHER_SILICON_STORAGE_DEVICE, 373 "Other Silicon Storage Device"}, 374 {PLDM_ENTITY_SOLID_STATE_SRIVE, "Solid State Drive"}, 375 {PLDM_ENTITY_POWER_SUPPLY, "Power supply"}, 376 {PLDM_ENTITY_BATTERY, "Battery"}, 377 {PLDM_ENTITY_SUPER_CAPACITOR, "Super Capacitor"}, 378 {PLDM_ENTITY_POWER_CONVERTER, "Power Converter"}, 379 {PLDM_ENTITY_DC_DC_CONVERTER, "DC-DC Converter"}, 380 {PLDM_ENTITY_AC_MAINS_POWER_SUPPLY, "AC mains power supply"}, 381 {PLDM_ENTITY_DC_MAINS_POWER_SUPPLY, "DC mains power supply"}, 382 {PLDM_ENTITY_PROC, "Processor"}, 383 {PLDM_ENTITY_CHIPSET_COMPONENT, "Chipset Component"}, 384 {PLDM_ENTITY_MGMT_CONTROLLER, "Management Controller"}, 385 {PLDM_ENTITY_PERIPHERAL_CONTROLLER, "Peripheral Controller"}, 386 {PLDM_ENTITY_SEEPROM, "SEEPROM"}, 387 {PLDM_ENTITY_NVRAM_CHIP, "NVRAM Chip"}, 388 {PLDM_ENTITY_FLASH_MEMORY_CHIP, "FLASH Memory chip"}, 389 {PLDM_ENTITY_MEMORY_CHIP, "Memory Chip"}, 390 {PLDM_ENTITY_MEMORY_CONTROLLER, "Memory Controller"}, 391 {PLDM_ENTITY_NETWORK_CONTROLLER, "Network Controller"}, 392 {PLDM_ENTITY_IO_CONTROLLER, "I/O Controller"}, 393 {PLDM_ENTITY_SOUTH_BRIDGE, "South Bridge"}, 394 {PLDM_ENTITY_REAL_TIME_CLOCK, "Real Time Clock (RTC)"}, 395 {PLDM_ENTITY_FPGA_CPLD_DEVICE, "FPGA/CPLD Configurable Logic Device"}, 396 {PLDM_ENTITY_OTHER_BUS, "Other Bus"}, 397 {PLDM_ENTITY_SYS_BUS, "System Bus"}, 398 {PLDM_ENTITY_I2C_BUS, "I2C Bus"}, 399 {PLDM_ENTITY_SMBUS_BUS, "SMBus Bus"}, 400 {PLDM_ENTITY_SPI_BUS, "SPI Bus"}, 401 {PLDM_ENTITY_PCI_BUS, "PCI Bus"}, 402 {PLDM_ENTITY_PCI_EXPRESS_BUS, "PCI Express Bus"}, 403 {PLDM_ENTITY_PECI_BUS, "PECI Bus"}, 404 {PLDM_ENTITY_LPC_BUS, "LPC Bus"}, 405 {PLDM_ENTITY_USB_BUS, "USB Bus"}, 406 {PLDM_ENTITY_FIREWIRE_BUS, "FireWire Bus"}, 407 {PLDM_ENTITY_SCSI_BUS, "SCSI Bus"}, 408 {PLDM_ENTITY_SATA_SAS_BUS, "SATA/SAS Bus"}, 409 {PLDM_ENTITY_PROC_FRONT_SIDE_BUS, "Processor/Front-side Bus"}, 410 {PLDM_ENTITY_INTER_PROC_BUS, "Inter-processor Bus"}, 411 {PLDM_ENTITY_CONNECTOR, "Connector"}, 412 {PLDM_ENTITY_SLOT, "Slot"}, 413 {PLDM_ENTITY_CABLE, "Cable(electrical or optical)"}, 414 {PLDM_ENTITY_INTERCONNECT, "Interconnect"}, 415 {PLDM_ENTITY_PLUG, "Plug"}, 416 {PLDM_ENTITY_SOCKET, "Socket"}, 417 }; 418 419 const std::map<uint16_t, std::string> stateSet = { 420 {PLDM_STATE_SET_HEALTH_STATE, "Health State"}, 421 {PLDM_STATE_SET_AVAILABILITY, "Availability"}, 422 {PLDM_STATE_SET_PREDICTIVE_CONDITION, "Predictive Condition"}, 423 {PLDM_STATE_SET_REDUNDANCY_STATUS, "Redundancy Status"}, 424 {PLDM_STATE_SET_HEALTH_REDUNDANCY_TREND, "Health/Redundancy Trend"}, 425 {PLDM_STATE_SET_GROUP_RESOURCE_LEVEL, "Group Resource Level"}, 426 {PLDM_STATE_SET_REDUNDANCY_ENTITY_ROLE, "Redundancy Entity Role"}, 427 {PLDM_STATE_SET_OPERATIONAL_STATUS, "Operational Status"}, 428 {PLDM_STATE_SET_OPERATIONAL_STRESS_STATUS, "Operational Stress Status"}, 429 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, "Operational Fault Status"}, 430 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 431 "Operational Running Status"}, 432 {PLDM_STATE_SET_OPERATIONAL_CONNECTION_STATUS, 433 "Operational Connection Status"}, 434 {PLDM_STATE_SET_PRESENCE, "Presence"}, 435 {PLDM_STATE_SET_PERFORMANCE, "Performance"}, 436 {PLDM_STATE_SET_CONFIGURATION_STATE, "Configuration State"}, 437 {PLDM_STATE_SET_CHANGED_CONFIGURATION, "Changed Configuration"}, 438 {PLDM_STATE_SET_IDENTIFY_STATE, "Identify State"}, 439 {PLDM_STATE_SET_VERSION, "Version"}, 440 {PLDM_STATE_SET_ALARM_STATE, "Alarm State"}, 441 {PLDM_STATE_SET_DEVICE_INITIALIZATION, "Device Initialization"}, 442 {PLDM_STATE_SET_THERMAL_TRIP, "Thermal Trip"}, 443 {PLDM_STATE_SET_HEARTBEAT, "Heartbeat"}, 444 {PLDM_STATE_SET_LINK_STATE, "Link State"}, 445 {PLDM_STATE_SET_SMOKE_STATE, "Smoke State"}, 446 {PLDM_STATE_SET_HUMIDITY_STATE, "Humidity State"}, 447 {PLDM_STATE_SET_DOOR_STATE, "Door State"}, 448 {PLDM_STATE_SET_SWITCH_STATE, "Switch State"}, 449 {PLDM_STATE_SET_LOCK_STATE, "Lock State"}, 450 {PLDM_STATE_SET_PHYSICAL_SECURITY, "Physical Security"}, 451 {PLDM_STATE_SET_DOCK_AUTHORIZATION, "Dock Authorization"}, 452 {PLDM_STATE_SET_HW_SECURITY, "Hardware Security"}, 453 {PLDM_STATE_SET_PHYSICAL_COMM_CONNECTION, 454 "Physical Communication Connection"}, 455 {PLDM_STATE_SET_COMM_LEASH_STATUS, "Communication Leash Status"}, 456 {PLDM_STATE_SET_FOREIGN_NW_DETECTION_STATUS, 457 "Foreign Network Detection Status"}, 458 {PLDM_STATE_SET_PASSWORD_PROTECTED_ACCESS_SECURITY, 459 "Password-Protected Access Security"}, 460 {PLDM_STATE_SET_SECURITY_ACCESS_PRIVILEGE_LEVEL, 461 "Security Access –PrivilegeLevel"}, 462 {PLDM_STATE_SET_SESSION_AUDIT, "PLDM Session Audit"}, 463 {PLDM_STATE_SET_SW_TERMINATION_STATUS, "Software Termination Status"}, 464 {PLDM_STATE_SET_STORAGE_MEDIA_ACTIVITY, "Storage Media Activity"}, 465 {PLDM_STATE_SET_BOOT_RESTART_CAUSE, "Boot/Restart Cause"}, 466 {PLDM_STATE_SET_BOOT_RESTART_REQUEST, "Boot/Restart Request"}, 467 {PLDM_STATE_SET_ENTITY_BOOT_STATUS, "Entity Boot Status"}, 468 {PLDM_STATE_SET_BOOT_ERROR_STATUS, "Boot ErrorStatus"}, 469 {PLDM_STATE_SET_BOOT_PROGRESS, "Boot Progress"}, 470 {PLDM_STATE_SET_SYS_FIRMWARE_HANG, "System Firmware Hang"}, 471 {PLDM_STATE_SET_POST_ERRORS, "POST Errors"}, 472 {PLDM_STATE_SET_LOG_FILL_STATUS, "Log Fill Status"}, 473 {PLDM_STATE_SET_LOG_FILTER_STATUS, "Log Filter Status"}, 474 {PLDM_STATE_SET_LOG_TIMESTAMP_CHANGE, "Log Timestamp Change"}, 475 {PLDM_STATE_SET_INTERRUPT_REQUESTED, "Interrupt Requested"}, 476 {PLDM_STATE_SET_INTERRUPT_RECEIVED, "Interrupt Received"}, 477 {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_REQUESTED, 478 "Diagnostic Interrupt Requested"}, 479 {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_RECEIVED, 480 "Diagnostic Interrupt Received"}, 481 {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_REQUESTED, 482 "I/O Channel Check NMI Requested"}, 483 {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_RECEIVED, 484 "I/O Channel Check NMI Received"}, 485 {PLDM_STATE_SET_FATAL_NMI_REQUESTED, "Fatal NMI Requested"}, 486 {PLDM_STATE_SET_FATAL_NMI_RECEIVED, "Fatal NMI Received"}, 487 {PLDM_STATE_SET_SOFTWARE_NMI_REQUESTED, "Software NMI Requested"}, 488 {PLDM_STATE_SET_SOFTWARE_NMI_RECEIVED, "Software NMI Received"}, 489 {PLDM_STATE_SET_SMI_REQUESTED, "SMI Requested"}, 490 {PLDM_STATE_SET_SMI_RECEIVED, "SMI Received"}, 491 {PLDM_STATE_SET_PCI_PERR_REQUESTED, "PCI PERR Requested"}, 492 {PLDM_STATE_SET_PCI_PERR_RECEIVED, "PCI PERR Received"}, 493 {PLDM_STATE_SET_PCI_SERR_REQUESTED, "PCI SERR Requested "}, 494 {PLDM_STATE_SET_PCI_SERR_RECEIVED, "PCI SERR Received"}, 495 {PLDM_STATE_SET_BUS_ERROR_STATUS, "Bus Error Status"}, 496 {PLDM_STATE_SET_WATCHDOG_STATUS, "Watchdog Status"}, 497 {PLDM_STATE_SET_POWER_SUPPLY_STATE, "Power Supply State"}, 498 {PLDM_STATE_SET_DEVICE_POWER_STATE, "Device Power State"}, 499 {PLDM_STATE_SET_ACPI_POWER_STATE, "ACPI Power State"}, 500 {PLDM_STATE_SET_BACKUP_POWER_SOURCE, "Backup Power Source"}, 501 {PLDM_STATE_SET_SYSTEM_POWER_STATE, "System Power State "}, 502 {PLDM_STATE_SET_BATTERY_ACTIVITY, "Battery Activity"}, 503 {PLDM_STATE_SET_BATTERY_STATE, "Battery State"}, 504 {PLDM_STATE_SET_PROC_POWER_STATE, "Processor Power State"}, 505 {PLDM_STATE_SET_POWER_PERFORMANCE_STATE, "Power-Performance State"}, 506 {PLDM_STATE_SET_PROC_ERROR_STATUS, "Processor Error Status"}, 507 {PLDM_STATE_SET_BIST_FAILURE_STATUS, "BIST FailureStatus"}, 508 {PLDM_STATE_SET_IBIST_FAILURE_STATUS, "IBIST FailureStatus"}, 509 {PLDM_STATE_SET_PROC_HANG_IN_POST, "Processor Hang in POST"}, 510 {PLDM_STATE_SET_PROC_STARTUP_FAILURE, "Processor Startup Failure"}, 511 {PLDM_STATE_SET_UNCORRECTABLE_CPU_ERROR, "Uncorrectable CPU Error"}, 512 {PLDM_STATE_SET_MACHINE_CHECK_ERROR, "Machine Check Error"}, 513 {PLDM_STATE_SET_CORRECTED_MACHINE_CHECK, "Corrected Machine Check"}, 514 {PLDM_STATE_SET_CACHE_STATUS, "Cache Status"}, 515 {PLDM_STATE_SET_MEMORY_ERROR_STATUS, "Memory Error Status"}, 516 {PLDM_STATE_SET_REDUNDANT_MEMORY_ACTIVITY_STATUS, 517 "Redundant Memory Activity Status"}, 518 {PLDM_STATE_SET_ERROR_DETECTION_STATUS, "Error Detection Status"}, 519 {PLDM_STATE_SET_STUCK_BIT_STATUS, "Stuck Bit Status"}, 520 {PLDM_STATE_SET_SCRUB_STATUS, "Scrub Status"}, 521 {PLDM_STATE_SET_SLOT_OCCUPANCY, "Slot Occupancy"}, 522 {PLDM_STATE_SET_SLOT_STATE, "Slot State"}, 523 }; 524 525 const std::array<std::string_view, 4> sensorInit = { 526 "noInit", "useInitPDR", "enableSensor", "disableSensor"}; 527 528 const std::array<std::string_view, 4> effecterInit = { 529 "noInit", "useInitPDR", "enableEffecter", "disableEffecter"}; 530 531 const std::map<uint8_t, std::string> pdrType = { 532 {PLDM_TERMINUS_LOCATOR_PDR, "Terminus Locator PDR"}, 533 {PLDM_NUMERIC_SENSOR_PDR, "Numeric Sensor PDR"}, 534 {PLDM_NUMERIC_SENSOR_INITIALIZATION_PDR, 535 "Numeric Sensor Initialization PDR"}, 536 {PLDM_STATE_SENSOR_PDR, "State Sensor PDR"}, 537 {PLDM_STATE_SENSOR_INITIALIZATION_PDR, 538 "State Sensor Initialization PDR"}, 539 {PLDM_SENSOR_AUXILIARY_NAMES_PDR, "Sensor Auxiliary Names PDR"}, 540 {PLDM_OEM_UNIT_PDR, "OEM Unit PDR"}, 541 {PLDM_OEM_STATE_SET_PDR, "OEM State Set PDR"}, 542 {PLDM_NUMERIC_EFFECTER_PDR, "Numeric Effecter PDR"}, 543 {PLDM_NUMERIC_EFFECTER_INITIALIZATION_PDR, 544 "Numeric Effecter Initialization PDR"}, 545 {PLDM_COMPACT_NUMERIC_SENSOR_PDR, "Compact Numeric Sensor PDR"}, 546 {PLDM_STATE_EFFECTER_PDR, "State Effecter PDR"}, 547 {PLDM_STATE_EFFECTER_INITIALIZATION_PDR, 548 "State Effecter Initialization PDR"}, 549 {PLDM_EFFECTER_AUXILIARY_NAMES_PDR, "Effecter Auxiliary Names PDR"}, 550 {PLDM_EFFECTER_OEM_SEMANTIC_PDR, "Effecter OEM Semantic PDR"}, 551 {PLDM_PDR_ENTITY_ASSOCIATION, "Entity Association PDR"}, 552 {PLDM_ENTITY_AUXILIARY_NAMES_PDR, "Entity Auxiliary Names PDR"}, 553 {PLDM_OEM_ENTITY_ID_PDR, "OEM Entity ID PDR"}, 554 {PLDM_INTERRUPT_ASSOCIATION_PDR, "Interrupt Association PDR"}, 555 {PLDM_EVENT_LOG_PDR, "PLDM Event Log PDR"}, 556 {PLDM_PDR_FRU_RECORD_SET, "FRU Record Set PDR"}, 557 {PLDM_OEM_DEVICE_PDR, "OEM Device PDR"}, 558 {PLDM_OEM_PDR, "OEM PDR"}, 559 }; 560 561 static inline const std::map<uint8_t, std::string> setThermalTrip{ 562 {PLDM_STATE_SET_THERMAL_TRIP_STATUS_NORMAL, "Normal"}, 563 {PLDM_STATE_SET_THERMAL_TRIP_STATUS_THERMAL_TRIP, "Thermal Trip"}}; 564 565 static inline const std::map<uint8_t, std::string> setIdentifyState{ 566 {PLDM_STATE_SET_IDENTIFY_STATE_UNASSERTED, "Identify State Unasserted"}, 567 {PLDM_STATE_SET_IDENTIFY_STATE_ASSERTED, "Identify State Asserted"}}; 568 569 static inline const std::map<uint8_t, std::string> setBootProgressState{ 570 {PLDM_STATE_SET_BOOT_PROG_STATE_NOT_ACTIVE, "Boot Not Active"}, 571 {PLDM_STATE_SET_BOOT_PROG_STATE_COMPLETED, "Boot Completed"}, 572 {PLDM_STATE_SET_BOOT_PROG_STATE_MEM_INITIALIZATION, 573 "Memory Initialization"}, 574 {PLDM_STATE_SET_BOOT_PROG_STATE_SEC_PROC_INITIALIZATION, 575 "Secondary Processor(s) Initialization"}, 576 {PLDM_STATE_SET_BOOT_PROG_STATE_PCI_RESORUCE_CONFIG, 577 "PCI Resource Configuration"}, 578 {PLDM_STATE_SET_BOOT_PROG_STATE_STARTING_OP_SYS, 579 "Starting Operating System"}, 580 {PLDM_STATE_SET_BOOT_PROG_STATE_BASE_BOARD_INITIALIZATION, 581 "Baseboard Initialization"}, 582 {PLDM_STATE_SET_BOOT_PROG_STATE_PRIMARY_PROC_INITIALIZATION, 583 "Primary Processor Initialization"}, 584 {PLDM_STATE_SET_BOOT_PROG_STATE_OSSTART, "OSStart"}}; 585 586 static inline const std::map<uint8_t, std::string> setOpFaultStatus{ 587 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_NORMAL, "Normal"}, 588 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_ERROR, "Error"}, 589 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_NON_RECOVERABLE_ERROR, 590 "Non Recoverable Error"}}; 591 592 static inline const std::map<uint8_t, std::string> setSysPowerState{ 593 {PLDM_STATE_SET_SYS_POWER_STATE_OFF_SOFT_GRACEFUL, 594 "Off-Soft Graceful"}}; 595 596 static inline const std::map<uint8_t, std::string> setSWTerminationStatus{ 597 {PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED, 598 "Graceful Restart Requested"}}; 599 600 static inline const std::map<uint8_t, std::string> setAvailability{ 601 {PLDM_STATE_SET_AVAILABILITY_REBOOTING, "Rebooting"}}; 602 603 static inline const std::map<uint8_t, std::string> setHealthState{ 604 {PLDM_STATE_SET_HEALTH_STATE_NORMAL, "Normal"}, 605 {PLDM_STATE_SET_HEALTH_STATE_NON_CRITICAL, "Non-Critical"}, 606 {PLDM_STATE_SET_HEALTH_STATE_CRITICAL, "Critical"}, 607 {PLDM_STATE_SET_HEALTH_STATE_FATAL, "Fatal"}, 608 {PLDM_STATE_SET_HEALTH_STATE_UPPER_NON_CRITICAL, "Upper Non-Critical"}, 609 {PLDM_STATE_SET_HEALTH_STATE_LOWER_NON_CRITICAL, "Lower Non-Critical"}, 610 {PLDM_STATE_SET_HEALTH_STATE_UPPER_CRITICAL, "Upper Critical"}, 611 {PLDM_STATE_SET_HEALTH_STATE_LOWER_CRITICAL, "Lower Critical"}, 612 {PLDM_STATE_SET_HEALTH_STATE_UPPER_FATAL, "Upper Fatal"}, 613 {PLDM_STATE_SET_HEALTH_STATE_LOWER_FATAL, "Lower Fatal"}}; 614 615 static inline const std::map<uint8_t, std::string> 616 setOperationalRunningState{ 617 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STARTING, "Starting"}, 618 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPING, "Stopping"}, 619 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED, "Stopped"}, 620 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE, 621 "In Service"}, 622 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_ABORTED, "Aborted"}, 623 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT, "Dormant"}}; 624 625 static inline const std::map<uint8_t, std::string> setPowerDeviceState{ 626 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_UNKNOWN, "Unknown"}, 627 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_FULLY_ON, "Fully-On"}, 628 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_INTERMEDIATE_1, 629 "Intermediate State-1"}, 630 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_INTERMEDIATE_2, 631 "Intermediate State-2"}, 632 {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_OFF, "Off"}}; 633 634 static inline const std::map<uint16_t, const std::map<uint8_t, std::string>> 635 populatePStateMaps{ 636 {PLDM_STATE_SET_THERMAL_TRIP, setThermalTrip}, 637 {PLDM_STATE_SET_IDENTIFY_STATE, setIdentifyState}, 638 {PLDM_STATE_SET_BOOT_PROGRESS, setBootProgressState}, 639 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, setOpFaultStatus}, 640 {PLDM_STATE_SET_SYSTEM_POWER_STATE, setSysPowerState}, 641 {PLDM_STATE_SET_SW_TERMINATION_STATUS, setSWTerminationStatus}, 642 {PLDM_STATE_SET_AVAILABILITY, setAvailability}, 643 {PLDM_STATE_SET_HEALTH_STATE, setHealthState}, 644 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 645 setOperationalRunningState}, 646 {PLDM_STATE_SET_DEVICE_POWER_STATE, setPowerDeviceState}, 647 }; 648 649 const std::map<std::string, uint8_t> strToPdrType = { 650 {"terminuslocator", PLDM_TERMINUS_LOCATOR_PDR}, 651 {"statesensor", PLDM_STATE_SENSOR_PDR}, 652 {"sensorauxname", PLDM_SENSOR_AUXILIARY_NAMES_PDR}, 653 {"numericeffecter", PLDM_NUMERIC_EFFECTER_PDR}, 654 {"efffecterauxname", PLDM_EFFECTER_AUXILIARY_NAMES_PDR}, 655 {"numericsensor", PLDM_NUMERIC_SENSOR_PDR}, 656 {"compactnumericsensor", PLDM_COMPACT_NUMERIC_SENSOR_PDR}, 657 {"stateeffecter", PLDM_STATE_EFFECTER_PDR}, 658 {"entityassociation", PLDM_PDR_ENTITY_ASSOCIATION}, 659 {"frurecord", PLDM_PDR_FRU_RECORD_SET}, 660 // Add other types 661 }; 662 663 bool isLogicalBitSet(const uint16_t entity_type) 664 { 665 return entity_type & 0x8000; 666 } 667 668 uint16_t getEntityTypeForLogicalEntity(const uint16_t logical_entity_type) 669 { 670 return logical_entity_type & 0x7FFF; 671 } 672 673 std::string getEntityName(pldm::pdr::EntityType type) 674 { 675 uint16_t entityNumber = type; 676 std::string entityName = "[Physical] "; 677 678 if (isLogicalBitSet(type)) 679 { 680 entityName = "[Logical] "; 681 entityNumber = getEntityTypeForLogicalEntity(type); 682 } 683 684 try 685 { 686 return entityName + entityType.at(entityNumber); 687 } 688 catch (const std::out_of_range& e) 689 { 690 auto OemString = 691 std::to_string(static_cast<unsigned>(entityNumber)); 692 if (type >= PLDM_OEM_ENTITY_TYPE_START && 693 type <= PLDM_OEM_ENTITY_TYPE_END) 694 { 695 #ifdef OEM_IBM 696 if (OemIBMEntityType.contains(entityNumber)) 697 { 698 return entityName + OemIBMEntityType.at(entityNumber) + 699 "(OEM)"; 700 } 701 #endif 702 return entityName + OemString + "(OEM)"; 703 } 704 return OemString; 705 } 706 } 707 708 std::string getStateSetName(uint16_t id) 709 { 710 auto typeString = std::to_string(id); 711 try 712 { 713 return stateSet.at(id) + "(" + typeString + ")"; 714 } 715 catch (const std::out_of_range& e) 716 { 717 return typeString; 718 } 719 } 720 721 std::vector<std::string> 722 getStateSetPossibleStateNames(uint16_t stateId, 723 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 = sPrefix + std::to_string(j) + 961 "_nameLanguageTag" + 962 std::to_string(i); 963 std::string entityAuxNameKey = sPrefix + std::to_string(j) + 964 "_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"] = (pdr->has_description_pdr ? true 1126 : 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 = decode_numeric_sensor_pdr_data(data, (size_t)data_length, 1273 &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) : 1621 CommandInterface(type, name, app) 1622 { 1623 app->add_option( 1624 "-i, --id", effecterId, 1625 "A handle that is used to identify and access the effecter") 1626 ->required(); 1627 app->add_option("-c, --count", effecterCount, 1628 "The number of individual sets of effecter information") 1629 ->required(); 1630 app->add_option( 1631 "-d,--data", effecterData, 1632 "Set effecter state data\n" 1633 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...") 1634 ->required(); 1635 } 1636 1637 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1638 { 1639 std::vector<uint8_t> requestMsg( 1640 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES); 1641 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1642 1643 if (effecterCount > maxEffecterCount || 1644 effecterCount < minEffecterCount) 1645 { 1646 std::cerr << "Request Message Error: effecterCount size " 1647 << effecterCount << "is invalid\n"; 1648 auto rc = PLDM_ERROR_INVALID_DATA; 1649 return {rc, requestMsg}; 1650 } 1651 1652 if (effecterData.size() > maxEffecterDataSize) 1653 { 1654 std::cerr << "Request Message Error: effecterData size " 1655 << effecterData.size() << "is invalid\n"; 1656 auto rc = PLDM_ERROR_INVALID_DATA; 1657 return {rc, requestMsg}; 1658 } 1659 1660 auto stateField = parseEffecterData(effecterData, effecterCount); 1661 if (!stateField) 1662 { 1663 std::cerr << "Failed to parse effecter data, effecterCount size " 1664 << effecterCount << "\n"; 1665 auto rc = PLDM_ERROR_INVALID_DATA; 1666 return {rc, requestMsg}; 1667 } 1668 1669 auto rc = encode_set_state_effecter_states_req( 1670 instanceId, effecterId, effecterCount, stateField->data(), request); 1671 return {rc, requestMsg}; 1672 } 1673 1674 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1675 { 1676 uint8_t completionCode = 0; 1677 auto rc = decode_set_state_effecter_states_resp( 1678 responsePtr, payloadLength, &completionCode); 1679 1680 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1681 { 1682 std::cerr << "Response Message Error: " 1683 << "rc=" << rc << ",cc=" << (int)completionCode << "\n"; 1684 return; 1685 } 1686 1687 ordered_json data; 1688 data["Response"] = "SUCCESS"; 1689 pldmtool::helper::DisplayInJson(data); 1690 } 1691 1692 private: 1693 uint16_t effecterId; 1694 uint8_t effecterCount; 1695 std::vector<uint8_t> effecterData; 1696 }; 1697 1698 class SetNumericEffecterValue : public CommandInterface 1699 { 1700 public: 1701 ~SetNumericEffecterValue() = default; 1702 SetNumericEffecterValue() = delete; 1703 SetNumericEffecterValue(const SetNumericEffecterValue&) = delete; 1704 SetNumericEffecterValue(SetNumericEffecterValue&&) = default; 1705 SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete; 1706 SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = delete; 1707 1708 explicit SetNumericEffecterValue(const char* type, const char* name, 1709 CLI::App* app) : 1710 CommandInterface(type, name, app) 1711 { 1712 app->add_option( 1713 "-i, --id", effecterId, 1714 "A handle that is used to identify and access the effecter") 1715 ->required(); 1716 app->add_option("-s, --size", effecterDataSize, 1717 "The bit width and format of the setting value for the " 1718 "effecter. enum value: {uint8, sint8, uint16, sint16, " 1719 "uint32, sint32}\n") 1720 ->required(); 1721 app->add_option("-d,--data", maxEffecterValue, 1722 "The setting value of numeric effecter being " 1723 "requested\n") 1724 ->required(); 1725 } 1726 1727 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1728 { 1729 std::vector<uint8_t> requestMsg( 1730 sizeof(pldm_msg_hdr) + 1731 PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3); 1732 1733 uint8_t* effecterValue = (uint8_t*)&maxEffecterValue; 1734 1735 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1736 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES; 1737 1738 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 || 1739 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) 1740 { 1741 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1; 1742 } 1743 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 || 1744 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) 1745 { 1746 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3; 1747 } 1748 auto rc = encode_set_numeric_effecter_value_req( 1749 0, effecterId, effecterDataSize, effecterValue, request, 1750 payload_length); 1751 1752 return {rc, requestMsg}; 1753 } 1754 1755 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1756 { 1757 uint8_t completionCode = 0; 1758 auto rc = decode_set_numeric_effecter_value_resp( 1759 responsePtr, payloadLength, &completionCode); 1760 1761 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1762 { 1763 std::cerr << "Response Message Error: " 1764 << "rc=" << rc << ",cc=" << (int)completionCode 1765 << std::endl; 1766 return; 1767 } 1768 1769 ordered_json data; 1770 data["Response"] = "SUCCESS"; 1771 pldmtool::helper::DisplayInJson(data); 1772 } 1773 1774 private: 1775 uint16_t effecterId; 1776 uint8_t effecterDataSize; 1777 uint64_t maxEffecterValue; 1778 }; 1779 1780 class GetStateSensorReadings : public CommandInterface 1781 { 1782 public: 1783 ~GetStateSensorReadings() = default; 1784 GetStateSensorReadings() = delete; 1785 GetStateSensorReadings(const GetStateSensorReadings&) = delete; 1786 GetStateSensorReadings(GetStateSensorReadings&&) = default; 1787 GetStateSensorReadings& operator=(const GetStateSensorReadings&) = delete; 1788 GetStateSensorReadings& operator=(GetStateSensorReadings&&) = delete; 1789 1790 explicit GetStateSensorReadings(const char* type, const char* name, 1791 CLI::App* app) : 1792 CommandInterface(type, name, app) 1793 { 1794 app->add_option( 1795 "-i, --sensor_id", sensorId, 1796 "Sensor ID that is used to identify and access the sensor") 1797 ->required(); 1798 app->add_option("-r, --rearm", sensorRearm, 1799 "Each bit location in this field corresponds to a " 1800 "particular sensor") 1801 ->required(); 1802 } 1803 1804 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1805 { 1806 std::vector<uint8_t> requestMsg( 1807 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES); 1808 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1809 1810 uint8_t reserved = 0; 1811 bitfield8_t bf; 1812 bf.byte = sensorRearm; 1813 auto rc = encode_get_state_sensor_readings_req(instanceId, sensorId, bf, 1814 reserved, request); 1815 1816 return {rc, requestMsg}; 1817 } 1818 1819 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1820 { 1821 uint8_t completionCode = 0; 1822 uint8_t compSensorCount = 0; 1823 std::array<get_sensor_state_field, 8> stateField{}; 1824 auto rc = decode_get_state_sensor_readings_resp( 1825 responsePtr, payloadLength, &completionCode, &compSensorCount, 1826 stateField.data()); 1827 1828 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1829 { 1830 std::cerr << "Response Message Error: " 1831 << "rc=" << rc << ",cc=" << (int)completionCode 1832 << std::endl; 1833 return; 1834 } 1835 ordered_json output; 1836 output["compositeSensorCount"] = (int)compSensorCount; 1837 1838 for (size_t i = 0; i < compSensorCount; i++) 1839 { 1840 if (sensorOpState.contains(stateField[i].sensor_op_state)) 1841 { 1842 output.emplace(("sensorOpState[" + std::to_string(i) + "]"), 1843 sensorOpState.at(stateField[i].sensor_op_state)); 1844 } 1845 1846 if (sensorPresState.contains(stateField[i].present_state)) 1847 { 1848 output.emplace(("presentState[" + std::to_string(i) + "]"), 1849 sensorPresState.at(stateField[i].present_state)); 1850 } 1851 1852 if (sensorPresState.contains(stateField[i].previous_state)) 1853 { 1854 output.emplace( 1855 ("previousState[" + std::to_string(i) + "]"), 1856 sensorPresState.at(stateField[i].previous_state)); 1857 } 1858 1859 if (sensorPresState.contains(stateField[i].event_state)) 1860 { 1861 output.emplace(("eventState[" + std::to_string(i) + "]"), 1862 sensorPresState.at(stateField[i].event_state)); 1863 } 1864 } 1865 1866 pldmtool::helper::DisplayInJson(output); 1867 } 1868 1869 private: 1870 uint16_t sensorId; 1871 uint8_t sensorRearm; 1872 }; 1873 1874 class GetSensorReading : public CommandInterface 1875 { 1876 public: 1877 ~GetSensorReading() = default; 1878 GetSensorReading() = delete; 1879 GetSensorReading(const GetSensorReading&) = delete; 1880 GetSensorReading(GetSensorReading&&) = default; 1881 GetSensorReading& operator=(const GetSensorReading&) = delete; 1882 GetSensorReading& operator=(GetSensorReading&&) = delete; 1883 1884 explicit GetSensorReading(const char* type, const char* name, 1885 CLI::App* app) : 1886 CommandInterface(type, name, app) 1887 { 1888 app->add_option( 1889 "-i, --sensor_id", sensorId, 1890 "Sensor ID that is used to identify and access the sensor") 1891 ->required(); 1892 app->add_option("-r, --rearm", rearm, 1893 "Manually re-arm EventState after " 1894 "responding to this request") 1895 ->required(); 1896 } 1897 1898 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1899 { 1900 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 1901 PLDM_GET_SENSOR_READING_REQ_BYTES); 1902 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1903 1904 auto rc = encode_get_sensor_reading_req(instanceId, sensorId, rearm, 1905 request); 1906 1907 return {rc, requestMsg}; 1908 } 1909 1910 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1911 { 1912 uint8_t completionCode = 0; 1913 uint8_t sensorDataSize = 0; 1914 uint8_t sensorOperationalState = 0; 1915 uint8_t sensorEventMessageEnable = 0; 1916 uint8_t presentState = 0; 1917 uint8_t previousState = 0; 1918 uint8_t eventState = 0; 1919 std::array<uint8_t, sizeof(uint32_t)> 1920 presentReading{}; // maximum size for the present Value is uint32 1921 // according to spec DSP0248 1922 1923 auto rc = decode_get_sensor_reading_resp( 1924 responsePtr, payloadLength, &completionCode, &sensorDataSize, 1925 &sensorOperationalState, &sensorEventMessageEnable, &presentState, 1926 &previousState, &eventState, presentReading.data()); 1927 1928 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1929 { 1930 std::cerr << "Response Message Error: " 1931 << "rc=" << rc << ",cc=" << (int)completionCode 1932 << std::endl; 1933 return; 1934 } 1935 1936 ordered_json output; 1937 output["sensorDataSize"] = getSensorState(sensorDataSize, 1938 &sensorDataSz); 1939 output["sensorOperationalState"] = 1940 getSensorState(sensorOperationalState, &sensorOpState); 1941 output["sensorEventMessageEnable"] = 1942 getSensorState(sensorEventMessageEnable, &sensorEventMsgEnable); 1943 output["presentState"] = getSensorState(presentState, &sensorPresState); 1944 output["previousState"] = getSensorState(previousState, 1945 &sensorPresState); 1946 output["eventState"] = getSensorState(eventState, &sensorPresState); 1947 1948 switch (sensorDataSize) 1949 { 1950 case PLDM_SENSOR_DATA_SIZE_UINT8: 1951 { 1952 output["presentReading"] = 1953 *(reinterpret_cast<uint8_t*>(presentReading.data())); 1954 break; 1955 } 1956 case PLDM_SENSOR_DATA_SIZE_SINT8: 1957 { 1958 output["presentReading"] = 1959 *(reinterpret_cast<int8_t*>(presentReading.data())); 1960 break; 1961 } 1962 case PLDM_SENSOR_DATA_SIZE_UINT16: 1963 { 1964 output["presentReading"] = 1965 *(reinterpret_cast<uint16_t*>(presentReading.data())); 1966 break; 1967 } 1968 case PLDM_SENSOR_DATA_SIZE_SINT16: 1969 { 1970 output["presentReading"] = 1971 *(reinterpret_cast<int16_t*>(presentReading.data())); 1972 break; 1973 } 1974 case PLDM_SENSOR_DATA_SIZE_UINT32: 1975 { 1976 output["presentReading"] = 1977 *(reinterpret_cast<uint32_t*>(presentReading.data())); 1978 break; 1979 } 1980 case PLDM_SENSOR_DATA_SIZE_SINT32: 1981 { 1982 output["presentReading"] = 1983 *(reinterpret_cast<int32_t*>(presentReading.data())); 1984 break; 1985 } 1986 default: 1987 { 1988 std::cerr << "Unknown Sensor Data Size : " 1989 << static_cast<int>(sensorDataSize) << std::endl; 1990 break; 1991 } 1992 } 1993 1994 pldmtool::helper::DisplayInJson(output); 1995 } 1996 1997 private: 1998 uint16_t sensorId; 1999 uint8_t rearm; 2000 2001 const std::map<uint8_t, std::string> sensorDataSz = { 2002 {PLDM_SENSOR_DATA_SIZE_UINT8, "uint8"}, 2003 {PLDM_SENSOR_DATA_SIZE_SINT8, "uint8"}, 2004 {PLDM_SENSOR_DATA_SIZE_UINT16, "uint16"}, 2005 {PLDM_SENSOR_DATA_SIZE_SINT16, "uint16"}, 2006 {PLDM_SENSOR_DATA_SIZE_UINT32, "uint32"}, 2007 {PLDM_SENSOR_DATA_SIZE_SINT32, "uint32"}}; 2008 2009 static inline const std::map<uint8_t, std::string> sensorEventMsgEnable{ 2010 {PLDM_NO_EVENT_GENERATION, "Sensor No Event Generation"}, 2011 {PLDM_EVENTS_DISABLED, "Sensor Events Disabled"}, 2012 {PLDM_EVENTS_ENABLED, "Sensor Events Enabled"}, 2013 {PLDM_OP_EVENTS_ONLY_ENABLED, "Sensor Op Events Only Enabled"}, 2014 {PLDM_STATE_EVENTS_ONLY_ENABLED, "Sensor State Events Only Enabled"}}; 2015 2016 std::string getSensorState(uint8_t state, 2017 const std::map<uint8_t, std::string>* cont) 2018 { 2019 auto typeString = std::to_string(state); 2020 try 2021 { 2022 return cont->at(state); 2023 } 2024 catch (const std::out_of_range& e) 2025 { 2026 return typeString; 2027 } 2028 } 2029 }; 2030 2031 class GetStateEffecterStates : public CommandInterface 2032 { 2033 public: 2034 ~GetStateEffecterStates() = default; 2035 GetStateEffecterStates() = delete; 2036 GetStateEffecterStates(const GetStateEffecterStates&) = delete; 2037 GetStateEffecterStates(GetStateEffecterStates&&) = default; 2038 GetStateEffecterStates& operator=(const GetStateEffecterStates&) = delete; 2039 GetStateEffecterStates& operator=(GetStateEffecterStates&&) = delete; 2040 2041 explicit GetStateEffecterStates(const char* type, const char* name, 2042 CLI::App* app) : 2043 CommandInterface(type, name, app) 2044 { 2045 app->add_option( 2046 "-i, --effecter_id", effecter_id, 2047 "Effecter ID that is used to identify and access the effecter") 2048 ->required(); 2049 } 2050 2051 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 2052 { 2053 std::vector<uint8_t> requestMsg( 2054 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES); 2055 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 2056 2057 auto rc = encode_get_state_effecter_states_req( 2058 instanceId, effecter_id, request, 2059 PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES); 2060 2061 return {rc, requestMsg}; 2062 } 2063 2064 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 2065 { 2066 struct pldm_get_state_effecter_states_resp resp; 2067 auto rc = decode_get_state_effecter_states_resp(responsePtr, 2068 payloadLength, &resp); 2069 2070 if (rc || resp.completion_code != PLDM_SUCCESS) 2071 { 2072 std::cerr << "Response Message Error: " 2073 << "rc=" << rc 2074 << ",cc=" << static_cast<int>(resp.completion_code) 2075 << std::endl; 2076 return; 2077 } 2078 ordered_json output; 2079 auto comp_effecter_count = static_cast<int>(resp.comp_effecter_count); 2080 output["compositeEffecterCount"] = comp_effecter_count; 2081 2082 for (auto i : std::views::iota(comp_effecter_count)) 2083 { 2084 output[std::format("effecterOpState[{}])", i)] = 2085 getEffecterOpState(resp.field[i].effecter_op_state); 2086 2087 output[std::format("pendingState[{}]", i)] = 2088 resp.field[i].pending_state; 2089 2090 output[std::format("presentState[{}]", i)] = 2091 resp.field[i].present_state; 2092 } 2093 2094 pldmtool::helper::DisplayInJson(output); 2095 } 2096 2097 private: 2098 uint16_t effecter_id; 2099 }; 2100 2101 class GetNumericEffecterValue : public CommandInterface 2102 { 2103 public: 2104 ~GetNumericEffecterValue() = default; 2105 GetNumericEffecterValue() = delete; 2106 GetNumericEffecterValue(const GetNumericEffecterValue&) = delete; 2107 GetNumericEffecterValue(GetNumericEffecterValue&&) = default; 2108 GetNumericEffecterValue& operator=(const GetNumericEffecterValue&) = delete; 2109 GetNumericEffecterValue& operator=(GetNumericEffecterValue&&) = delete; 2110 2111 explicit GetNumericEffecterValue(const char* type, const char* name, 2112 CLI::App* app) : 2113 CommandInterface(type, name, app) 2114 { 2115 app->add_option( 2116 "-i, --effecter_id", effecterId, 2117 "A handle that is used to identify and access the effecter") 2118 ->required(); 2119 } 2120 2121 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 2122 { 2123 std::vector<uint8_t> requestMsg( 2124 sizeof(pldm_msg_hdr) + PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES); 2125 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 2126 2127 auto rc = encode_get_numeric_effecter_value_req(instanceId, effecterId, 2128 request); 2129 2130 return {rc, requestMsg}; 2131 } 2132 2133 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 2134 { 2135 uint8_t completionCode = 0; 2136 uint8_t effecterDataSize = 0; 2137 uint8_t effecterOperationalState = 0; 2138 std::array<uint8_t, sizeof(uint32_t)> 2139 pendingValue{}; // maximum size for the pending Value is uint32 2140 // according to spec DSP0248 2141 std::array<uint8_t, sizeof(uint32_t)> 2142 presentValue{}; // maximum size for the present Value is uint32 2143 // according to spec DSP0248 2144 2145 auto rc = decode_get_numeric_effecter_value_resp( 2146 responsePtr, payloadLength, &completionCode, &effecterDataSize, 2147 &effecterOperationalState, pendingValue.data(), 2148 presentValue.data()); 2149 2150 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 2151 { 2152 std::cerr << "Response Message Error: " 2153 << "rc=" << rc 2154 << ",cc=" << static_cast<int>(completionCode) 2155 << std::endl; 2156 return; 2157 } 2158 2159 ordered_json output; 2160 output["effecterDataSize"] = static_cast<int>(effecterDataSize); 2161 output["effecterOperationalState"] = 2162 getEffecterOpState(effecterOperationalState); 2163 2164 switch (effecterDataSize) 2165 { 2166 case PLDM_EFFECTER_DATA_SIZE_UINT8: 2167 { 2168 output["pendingValue"] = 2169 *(reinterpret_cast<uint8_t*>(pendingValue.data())); 2170 output["presentValue"] = 2171 *(reinterpret_cast<uint8_t*>(presentValue.data())); 2172 break; 2173 } 2174 case PLDM_EFFECTER_DATA_SIZE_SINT8: 2175 { 2176 output["pendingValue"] = 2177 *(reinterpret_cast<int8_t*>(pendingValue.data())); 2178 output["presentValue"] = 2179 *(reinterpret_cast<int8_t*>(presentValue.data())); 2180 break; 2181 } 2182 case PLDM_EFFECTER_DATA_SIZE_UINT16: 2183 { 2184 output["pendingValue"] = 2185 *(reinterpret_cast<uint16_t*>(pendingValue.data())); 2186 output["presentValue"] = 2187 *(reinterpret_cast<uint16_t*>(presentValue.data())); 2188 break; 2189 } 2190 case PLDM_EFFECTER_DATA_SIZE_SINT16: 2191 { 2192 output["pendingValue"] = 2193 *(reinterpret_cast<int16_t*>(pendingValue.data())); 2194 output["presentValue"] = 2195 *(reinterpret_cast<int16_t*>(presentValue.data())); 2196 break; 2197 } 2198 case PLDM_EFFECTER_DATA_SIZE_UINT32: 2199 { 2200 output["pendingValue"] = 2201 *(reinterpret_cast<uint32_t*>(pendingValue.data())); 2202 output["presentValue"] = 2203 *(reinterpret_cast<uint32_t*>(presentValue.data())); 2204 break; 2205 } 2206 case PLDM_EFFECTER_DATA_SIZE_SINT32: 2207 { 2208 output["pendingValue"] = 2209 *(reinterpret_cast<int32_t*>(pendingValue.data())); 2210 output["presentValue"] = 2211 *(reinterpret_cast<int32_t*>(presentValue.data())); 2212 break; 2213 } 2214 default: 2215 { 2216 std::cerr << "Unknown Effecter Data Size : " 2217 << static_cast<int>(effecterDataSize) << std::endl; 2218 break; 2219 } 2220 } 2221 2222 pldmtool::helper::DisplayInJson(output); 2223 } 2224 2225 private: 2226 uint16_t effecterId; 2227 }; 2228 2229 void registerCommand(CLI::App& app) 2230 { 2231 auto platform = app.add_subcommand("platform", "platform type command"); 2232 platform->require_subcommand(1); 2233 2234 auto getPDR = platform->add_subcommand("GetPDR", 2235 "get platform descriptor records"); 2236 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR)); 2237 2238 auto setStateEffecterStates = platform->add_subcommand( 2239 "SetStateEffecterStates", "set effecter states"); 2240 commands.push_back(std::make_unique<SetStateEffecter>( 2241 "platform", "setStateEffecterStates", setStateEffecterStates)); 2242 2243 auto setNumericEffecterValue = platform->add_subcommand( 2244 "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter"); 2245 commands.push_back(std::make_unique<SetNumericEffecterValue>( 2246 "platform", "setNumericEffecterValue", setNumericEffecterValue)); 2247 2248 auto getStateSensorReadings = platform->add_subcommand( 2249 "GetStateSensorReadings", "get the state sensor readings"); 2250 commands.push_back(std::make_unique<GetStateSensorReadings>( 2251 "platform", "getStateSensorReadings", getStateSensorReadings)); 2252 2253 auto getNumericEffecterValue = platform->add_subcommand( 2254 "GetNumericEffecterValue", "get the numeric effecter value"); 2255 commands.push_back(std::make_unique<GetNumericEffecterValue>( 2256 "platform", "getNumericEffecterValue", getNumericEffecterValue)); 2257 2258 auto getSensorReading = platform->add_subcommand( 2259 "GetSensorReading", "get the numeric sensor reading"); 2260 commands.push_back(std::make_unique<GetSensorReading>( 2261 "platform", "getSensorReading", getSensorReading)); 2262 2263 auto getStateEffecterStates = platform->add_subcommand( 2264 "GetStateEffecterStates", "get the state effecter states"); 2265 commands.push_back(std::make_unique<GetStateEffecterStates>( 2266 "platform", "getStateEffecterStates", getStateEffecterStates)); 2267 } 2268 2269 void parseGetPDROption() 2270 { 2271 for (const auto& command : commands) 2272 { 2273 if (command.get()->getPLDMType() == "platform" && 2274 command.get()->getCommandName() == "getPDR") 2275 { 2276 auto getPDR = dynamic_cast<GetPDR*>(command.get()); 2277 getPDR->parseGetPDROptions(); 2278 } 2279 } 2280 } 2281 2282 } // namespace platform 2283 } // namespace pldmtool 2284