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 case PLDM_EFFECTER_AUXILIARY_NAMES_PDR: 1564 printAuxNamePDR(data, output); 1565 break; 1566 case PLDM_STATE_EFFECTER_PDR: 1567 printStateEffecterPDR(data, output); 1568 break; 1569 case PLDM_PDR_ENTITY_ASSOCIATION: 1570 printPDREntityAssociation(data, output); 1571 break; 1572 case PLDM_PDR_FRU_RECORD_SET: 1573 printPDRFruRecordSet(data, output); 1574 break; 1575 case PLDM_COMPACT_NUMERIC_SENSOR_PDR: 1576 printCompactNumericSensorPDR(data, output); 1577 break; 1578 default: 1579 break; 1580 } 1581 pldmtool::helper::DisplayInJson(output); 1582 } 1583 1584 private: 1585 bool optTIDSet = false; 1586 uint32_t recordHandle; 1587 bool allPDRs; 1588 std::string pdrRecType; 1589 std::optional<uint8_t> pdrTerminus; 1590 std::optional<uint16_t> terminusHandle; 1591 bool handleFound = false; 1592 CLI::Option* getPDRGroupOption = nullptr; 1593 uint32_t dataTransferHandle; 1594 uint8_t operationFlag; 1595 uint16_t requestCount; 1596 uint16_t recordChangeNumber; 1597 std::vector<uint8_t> recordData; 1598 bool nextPartRequired; 1599 }; 1600 1601 class SetStateEffecter : public CommandInterface 1602 { 1603 public: 1604 ~SetStateEffecter() = default; 1605 SetStateEffecter() = delete; 1606 SetStateEffecter(const SetStateEffecter&) = delete; 1607 SetStateEffecter(SetStateEffecter&&) = default; 1608 SetStateEffecter& operator=(const SetStateEffecter&) = delete; 1609 SetStateEffecter& operator=(SetStateEffecter&&) = delete; 1610 1611 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2) 1612 static constexpr auto maxEffecterDataSize = 16; 1613 1614 // compositeEffecterCount(value: 0x01 to 0x08) 1615 static constexpr auto minEffecterCount = 1; 1616 static constexpr auto maxEffecterCount = 8; 1617 explicit SetStateEffecter(const char* type, const char* name, 1618 CLI::App* app) : CommandInterface(type, name, app) 1619 { 1620 app->add_option( 1621 "-i, --id", effecterId, 1622 "A handle that is used to identify and access the effecter") 1623 ->required(); 1624 app->add_option("-c, --count", effecterCount, 1625 "The number of individual sets of effecter information") 1626 ->required(); 1627 app->add_option( 1628 "-d,--data", effecterData, 1629 "Set effecter state data\n" 1630 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...") 1631 ->required(); 1632 } 1633 1634 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1635 { 1636 std::vector<uint8_t> requestMsg( 1637 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES); 1638 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1639 1640 if (effecterCount > maxEffecterCount || 1641 effecterCount < minEffecterCount) 1642 { 1643 std::cerr << "Request Message Error: effecterCount size " 1644 << effecterCount << "is invalid\n"; 1645 auto rc = PLDM_ERROR_INVALID_DATA; 1646 return {rc, requestMsg}; 1647 } 1648 1649 if (effecterData.size() > maxEffecterDataSize) 1650 { 1651 std::cerr << "Request Message Error: effecterData size " 1652 << effecterData.size() << "is invalid\n"; 1653 auto rc = PLDM_ERROR_INVALID_DATA; 1654 return {rc, requestMsg}; 1655 } 1656 1657 auto stateField = parseEffecterData(effecterData, effecterCount); 1658 if (!stateField) 1659 { 1660 std::cerr << "Failed to parse effecter data, effecterCount size " 1661 << effecterCount << "\n"; 1662 auto rc = PLDM_ERROR_INVALID_DATA; 1663 return {rc, requestMsg}; 1664 } 1665 1666 auto rc = encode_set_state_effecter_states_req( 1667 instanceId, effecterId, effecterCount, stateField->data(), request); 1668 return {rc, requestMsg}; 1669 } 1670 1671 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1672 { 1673 uint8_t completionCode = 0; 1674 auto rc = decode_set_state_effecter_states_resp( 1675 responsePtr, payloadLength, &completionCode); 1676 1677 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1678 { 1679 std::cerr << "Response Message Error: " 1680 << "rc=" << rc << ",cc=" << (int)completionCode << "\n"; 1681 return; 1682 } 1683 1684 ordered_json data; 1685 data["Response"] = "SUCCESS"; 1686 pldmtool::helper::DisplayInJson(data); 1687 } 1688 1689 private: 1690 uint16_t effecterId; 1691 uint8_t effecterCount; 1692 std::vector<uint8_t> effecterData; 1693 }; 1694 1695 class SetNumericEffecterValue : public CommandInterface 1696 { 1697 public: 1698 ~SetNumericEffecterValue() = default; 1699 SetNumericEffecterValue() = delete; 1700 SetNumericEffecterValue(const SetNumericEffecterValue&) = delete; 1701 SetNumericEffecterValue(SetNumericEffecterValue&&) = default; 1702 SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete; 1703 SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = delete; 1704 1705 explicit SetNumericEffecterValue(const char* type, const char* name, 1706 CLI::App* app) : 1707 CommandInterface(type, name, app) 1708 { 1709 app->add_option( 1710 "-i, --id", effecterId, 1711 "A handle that is used to identify and access the effecter") 1712 ->required(); 1713 app->add_option("-s, --size", effecterDataSize, 1714 "The bit width and format of the setting value for the " 1715 "effecter. enum value: {uint8, sint8, uint16, sint16, " 1716 "uint32, sint32}\n") 1717 ->required(); 1718 app->add_option("-d,--data", maxEffecterValue, 1719 "The setting value of numeric effecter being " 1720 "requested\n") 1721 ->required(); 1722 } 1723 1724 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1725 { 1726 std::vector<uint8_t> requestMsg( 1727 sizeof(pldm_msg_hdr) + 1728 PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3); 1729 1730 uint8_t* effecterValue = (uint8_t*)&maxEffecterValue; 1731 1732 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1733 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES; 1734 1735 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 || 1736 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) 1737 { 1738 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1; 1739 } 1740 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 || 1741 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) 1742 { 1743 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3; 1744 } 1745 auto rc = encode_set_numeric_effecter_value_req( 1746 0, effecterId, effecterDataSize, effecterValue, request, 1747 payload_length); 1748 1749 return {rc, requestMsg}; 1750 } 1751 1752 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1753 { 1754 uint8_t completionCode = 0; 1755 auto rc = decode_set_numeric_effecter_value_resp( 1756 responsePtr, payloadLength, &completionCode); 1757 1758 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1759 { 1760 std::cerr << "Response Message Error: " 1761 << "rc=" << rc << ",cc=" << (int)completionCode 1762 << std::endl; 1763 return; 1764 } 1765 1766 ordered_json data; 1767 data["Response"] = "SUCCESS"; 1768 pldmtool::helper::DisplayInJson(data); 1769 } 1770 1771 private: 1772 uint16_t effecterId; 1773 uint8_t effecterDataSize; 1774 uint64_t maxEffecterValue; 1775 }; 1776 1777 class GetStateSensorReadings : public CommandInterface 1778 { 1779 public: 1780 ~GetStateSensorReadings() = default; 1781 GetStateSensorReadings() = delete; 1782 GetStateSensorReadings(const GetStateSensorReadings&) = delete; 1783 GetStateSensorReadings(GetStateSensorReadings&&) = default; 1784 GetStateSensorReadings& operator=(const GetStateSensorReadings&) = delete; 1785 GetStateSensorReadings& operator=(GetStateSensorReadings&&) = delete; 1786 1787 explicit GetStateSensorReadings(const char* type, const char* name, 1788 CLI::App* app) : 1789 CommandInterface(type, name, app) 1790 { 1791 app->add_option( 1792 "-i, --sensor_id", sensorId, 1793 "Sensor ID that is used to identify and access the sensor") 1794 ->required(); 1795 app->add_option("-r, --rearm", sensorRearm, 1796 "Each bit location in this field corresponds to a " 1797 "particular sensor") 1798 ->required(); 1799 } 1800 1801 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1802 { 1803 std::vector<uint8_t> requestMsg( 1804 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES); 1805 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1806 1807 uint8_t reserved = 0; 1808 bitfield8_t bf; 1809 bf.byte = sensorRearm; 1810 auto rc = encode_get_state_sensor_readings_req(instanceId, sensorId, bf, 1811 reserved, request); 1812 1813 return {rc, requestMsg}; 1814 } 1815 1816 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1817 { 1818 uint8_t completionCode = 0; 1819 uint8_t compSensorCount = 0; 1820 std::array<get_sensor_state_field, 8> stateField{}; 1821 auto rc = decode_get_state_sensor_readings_resp( 1822 responsePtr, payloadLength, &completionCode, &compSensorCount, 1823 stateField.data()); 1824 1825 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1826 { 1827 std::cerr << "Response Message Error: " 1828 << "rc=" << rc << ",cc=" << (int)completionCode 1829 << std::endl; 1830 return; 1831 } 1832 ordered_json output; 1833 output["compositeSensorCount"] = (int)compSensorCount; 1834 1835 for (size_t i = 0; i < compSensorCount; i++) 1836 { 1837 if (sensorOpState.contains(stateField[i].sensor_op_state)) 1838 { 1839 output.emplace(("sensorOpState[" + std::to_string(i) + "]"), 1840 sensorOpState.at(stateField[i].sensor_op_state)); 1841 } 1842 1843 if (sensorPresState.contains(stateField[i].present_state)) 1844 { 1845 output.emplace(("presentState[" + std::to_string(i) + "]"), 1846 sensorPresState.at(stateField[i].present_state)); 1847 } 1848 1849 if (sensorPresState.contains(stateField[i].previous_state)) 1850 { 1851 output.emplace( 1852 ("previousState[" + std::to_string(i) + "]"), 1853 sensorPresState.at(stateField[i].previous_state)); 1854 } 1855 1856 if (sensorPresState.contains(stateField[i].event_state)) 1857 { 1858 output.emplace(("eventState[" + std::to_string(i) + "]"), 1859 sensorPresState.at(stateField[i].event_state)); 1860 } 1861 } 1862 1863 pldmtool::helper::DisplayInJson(output); 1864 } 1865 1866 private: 1867 uint16_t sensorId; 1868 uint8_t sensorRearm; 1869 }; 1870 1871 class GetSensorReading : public CommandInterface 1872 { 1873 public: 1874 ~GetSensorReading() = default; 1875 GetSensorReading() = delete; 1876 GetSensorReading(const GetSensorReading&) = delete; 1877 GetSensorReading(GetSensorReading&&) = default; 1878 GetSensorReading& operator=(const GetSensorReading&) = delete; 1879 GetSensorReading& operator=(GetSensorReading&&) = delete; 1880 1881 explicit GetSensorReading(const char* type, const char* name, 1882 CLI::App* app) : CommandInterface(type, name, app) 1883 { 1884 app->add_option( 1885 "-i, --sensor_id", sensorId, 1886 "Sensor ID that is used to identify and access the sensor") 1887 ->required(); 1888 app->add_option("-r, --rearm", rearm, 1889 "Manually re-arm EventState after " 1890 "responding to this request") 1891 ->required(); 1892 } 1893 1894 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1895 { 1896 std::vector<uint8_t> requestMsg( 1897 sizeof(pldm_msg_hdr) + PLDM_GET_SENSOR_READING_REQ_BYTES); 1898 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1899 1900 auto rc = 1901 encode_get_sensor_reading_req(instanceId, sensorId, rearm, request); 1902 1903 return {rc, requestMsg}; 1904 } 1905 1906 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1907 { 1908 uint8_t completionCode = 0; 1909 uint8_t sensorDataSize = 0; 1910 uint8_t sensorOperationalState = 0; 1911 uint8_t sensorEventMessageEnable = 0; 1912 uint8_t presentState = 0; 1913 uint8_t previousState = 0; 1914 uint8_t eventState = 0; 1915 std::array<uint8_t, sizeof(uint32_t)> 1916 presentReading{}; // maximum size for the present Value is uint32 1917 // according to spec DSP0248 1918 1919 auto rc = decode_get_sensor_reading_resp( 1920 responsePtr, payloadLength, &completionCode, &sensorDataSize, 1921 &sensorOperationalState, &sensorEventMessageEnable, &presentState, 1922 &previousState, &eventState, presentReading.data()); 1923 1924 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1925 { 1926 std::cerr << "Response Message Error: " 1927 << "rc=" << rc << ",cc=" << (int)completionCode 1928 << std::endl; 1929 return; 1930 } 1931 1932 ordered_json output; 1933 output["sensorDataSize"] = 1934 getSensorState(sensorDataSize, &sensorDataSz); 1935 output["sensorOperationalState"] = 1936 getSensorState(sensorOperationalState, &sensorOpState); 1937 output["sensorEventMessageEnable"] = 1938 getSensorState(sensorEventMessageEnable, &sensorEventMsgEnable); 1939 output["presentState"] = getSensorState(presentState, &sensorPresState); 1940 output["previousState"] = 1941 getSensorState(previousState, &sensorPresState); 1942 output["eventState"] = getSensorState(eventState, &sensorPresState); 1943 1944 switch (sensorDataSize) 1945 { 1946 case PLDM_SENSOR_DATA_SIZE_UINT8: 1947 { 1948 output["presentReading"] = 1949 *(reinterpret_cast<uint8_t*>(presentReading.data())); 1950 break; 1951 } 1952 case PLDM_SENSOR_DATA_SIZE_SINT8: 1953 { 1954 output["presentReading"] = 1955 *(reinterpret_cast<int8_t*>(presentReading.data())); 1956 break; 1957 } 1958 case PLDM_SENSOR_DATA_SIZE_UINT16: 1959 { 1960 output["presentReading"] = 1961 *(reinterpret_cast<uint16_t*>(presentReading.data())); 1962 break; 1963 } 1964 case PLDM_SENSOR_DATA_SIZE_SINT16: 1965 { 1966 output["presentReading"] = 1967 *(reinterpret_cast<int16_t*>(presentReading.data())); 1968 break; 1969 } 1970 case PLDM_SENSOR_DATA_SIZE_UINT32: 1971 { 1972 output["presentReading"] = 1973 *(reinterpret_cast<uint32_t*>(presentReading.data())); 1974 break; 1975 } 1976 case PLDM_SENSOR_DATA_SIZE_SINT32: 1977 { 1978 output["presentReading"] = 1979 *(reinterpret_cast<int32_t*>(presentReading.data())); 1980 break; 1981 } 1982 default: 1983 { 1984 std::cerr << "Unknown Sensor Data Size : " 1985 << static_cast<int>(sensorDataSize) << std::endl; 1986 break; 1987 } 1988 } 1989 1990 pldmtool::helper::DisplayInJson(output); 1991 } 1992 1993 private: 1994 uint16_t sensorId; 1995 uint8_t rearm; 1996 1997 const std::map<uint8_t, std::string> sensorDataSz = { 1998 {PLDM_SENSOR_DATA_SIZE_UINT8, "uint8"}, 1999 {PLDM_SENSOR_DATA_SIZE_SINT8, "uint8"}, 2000 {PLDM_SENSOR_DATA_SIZE_UINT16, "uint16"}, 2001 {PLDM_SENSOR_DATA_SIZE_SINT16, "uint16"}, 2002 {PLDM_SENSOR_DATA_SIZE_UINT32, "uint32"}, 2003 {PLDM_SENSOR_DATA_SIZE_SINT32, "uint32"}}; 2004 2005 static inline const std::map<uint8_t, std::string> sensorEventMsgEnable{ 2006 {PLDM_NO_EVENT_GENERATION, "Sensor No Event Generation"}, 2007 {PLDM_EVENTS_DISABLED, "Sensor Events Disabled"}, 2008 {PLDM_EVENTS_ENABLED, "Sensor Events Enabled"}, 2009 {PLDM_OP_EVENTS_ONLY_ENABLED, "Sensor Op Events Only Enabled"}, 2010 {PLDM_STATE_EVENTS_ONLY_ENABLED, "Sensor State Events Only Enabled"}}; 2011 2012 std::string getSensorState(uint8_t state, 2013 const std::map<uint8_t, std::string>* cont) 2014 { 2015 auto typeString = std::to_string(state); 2016 try 2017 { 2018 return cont->at(state); 2019 } 2020 catch (const std::out_of_range& e) 2021 { 2022 return typeString; 2023 } 2024 } 2025 }; 2026 2027 class GetStateEffecterStates : public CommandInterface 2028 { 2029 public: 2030 ~GetStateEffecterStates() = default; 2031 GetStateEffecterStates() = delete; 2032 GetStateEffecterStates(const GetStateEffecterStates&) = delete; 2033 GetStateEffecterStates(GetStateEffecterStates&&) = default; 2034 GetStateEffecterStates& operator=(const GetStateEffecterStates&) = delete; 2035 GetStateEffecterStates& operator=(GetStateEffecterStates&&) = delete; 2036 2037 explicit GetStateEffecterStates(const char* type, const char* name, 2038 CLI::App* app) : 2039 CommandInterface(type, name, app) 2040 { 2041 app->add_option( 2042 "-i, --effecter_id", effecter_id, 2043 "Effecter ID that is used to identify and access the effecter") 2044 ->required(); 2045 } 2046 2047 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 2048 { 2049 std::vector<uint8_t> requestMsg( 2050 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES); 2051 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 2052 2053 auto rc = encode_get_state_effecter_states_req( 2054 instanceId, effecter_id, request, 2055 PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES); 2056 2057 return {rc, requestMsg}; 2058 } 2059 2060 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 2061 { 2062 struct pldm_get_state_effecter_states_resp resp; 2063 auto rc = decode_get_state_effecter_states_resp(responsePtr, 2064 payloadLength, &resp); 2065 2066 if (rc || resp.completion_code != PLDM_SUCCESS) 2067 { 2068 std::cerr << "Response Message Error: " 2069 << "rc=" << rc << ",cc=" 2070 << static_cast<int>(resp.completion_code) << std::endl; 2071 return; 2072 } 2073 ordered_json output; 2074 auto comp_effecter_count = static_cast<int>(resp.comp_effecter_count); 2075 output["compositeEffecterCount"] = comp_effecter_count; 2076 2077 for (auto i : std::views::iota(0, comp_effecter_count)) 2078 { 2079 output[std::format("effecterOpState[{}])", i)] = 2080 getEffecterOpState(resp.field[i].effecter_op_state); 2081 2082 output[std::format("pendingState[{}]", i)] = 2083 resp.field[i].pending_state; 2084 2085 output[std::format("presentState[{}]", i)] = 2086 resp.field[i].present_state; 2087 } 2088 2089 pldmtool::helper::DisplayInJson(output); 2090 } 2091 2092 private: 2093 uint16_t effecter_id; 2094 }; 2095 2096 class GetNumericEffecterValue : public CommandInterface 2097 { 2098 public: 2099 ~GetNumericEffecterValue() = default; 2100 GetNumericEffecterValue() = delete; 2101 GetNumericEffecterValue(const GetNumericEffecterValue&) = delete; 2102 GetNumericEffecterValue(GetNumericEffecterValue&&) = default; 2103 GetNumericEffecterValue& operator=(const GetNumericEffecterValue&) = delete; 2104 GetNumericEffecterValue& operator=(GetNumericEffecterValue&&) = delete; 2105 2106 explicit GetNumericEffecterValue(const char* type, const char* name, 2107 CLI::App* app) : 2108 CommandInterface(type, name, app) 2109 { 2110 app->add_option( 2111 "-i, --effecter_id", effecterId, 2112 "A handle that is used to identify and access the effecter") 2113 ->required(); 2114 } 2115 2116 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 2117 { 2118 std::vector<uint8_t> requestMsg( 2119 sizeof(pldm_msg_hdr) + PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES); 2120 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 2121 2122 auto rc = encode_get_numeric_effecter_value_req(instanceId, effecterId, 2123 request); 2124 2125 return {rc, requestMsg}; 2126 } 2127 2128 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 2129 { 2130 uint8_t completionCode = 0; 2131 uint8_t effecterDataSize = 0; 2132 uint8_t effecterOperationalState = 0; 2133 std::array<uint8_t, sizeof(uint32_t)> 2134 pendingValue{}; // maximum size for the pending Value is uint32 2135 // according to spec DSP0248 2136 std::array<uint8_t, sizeof(uint32_t)> 2137 presentValue{}; // maximum size for the present Value is uint32 2138 // according to spec DSP0248 2139 2140 auto rc = decode_get_numeric_effecter_value_resp( 2141 responsePtr, payloadLength, &completionCode, &effecterDataSize, 2142 &effecterOperationalState, pendingValue.data(), 2143 presentValue.data()); 2144 2145 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 2146 { 2147 std::cerr << "Response Message Error: " 2148 << "rc=" << rc << ",cc=" 2149 << static_cast<int>(completionCode) << std::endl; 2150 return; 2151 } 2152 2153 ordered_json output; 2154 output["effecterDataSize"] = static_cast<int>(effecterDataSize); 2155 output["effecterOperationalState"] = 2156 getEffecterOpState(effecterOperationalState); 2157 2158 switch (effecterDataSize) 2159 { 2160 case PLDM_EFFECTER_DATA_SIZE_UINT8: 2161 { 2162 output["pendingValue"] = 2163 *(reinterpret_cast<uint8_t*>(pendingValue.data())); 2164 output["presentValue"] = 2165 *(reinterpret_cast<uint8_t*>(presentValue.data())); 2166 break; 2167 } 2168 case PLDM_EFFECTER_DATA_SIZE_SINT8: 2169 { 2170 output["pendingValue"] = 2171 *(reinterpret_cast<int8_t*>(pendingValue.data())); 2172 output["presentValue"] = 2173 *(reinterpret_cast<int8_t*>(presentValue.data())); 2174 break; 2175 } 2176 case PLDM_EFFECTER_DATA_SIZE_UINT16: 2177 { 2178 output["pendingValue"] = 2179 *(reinterpret_cast<uint16_t*>(pendingValue.data())); 2180 output["presentValue"] = 2181 *(reinterpret_cast<uint16_t*>(presentValue.data())); 2182 break; 2183 } 2184 case PLDM_EFFECTER_DATA_SIZE_SINT16: 2185 { 2186 output["pendingValue"] = 2187 *(reinterpret_cast<int16_t*>(pendingValue.data())); 2188 output["presentValue"] = 2189 *(reinterpret_cast<int16_t*>(presentValue.data())); 2190 break; 2191 } 2192 case PLDM_EFFECTER_DATA_SIZE_UINT32: 2193 { 2194 output["pendingValue"] = 2195 *(reinterpret_cast<uint32_t*>(pendingValue.data())); 2196 output["presentValue"] = 2197 *(reinterpret_cast<uint32_t*>(presentValue.data())); 2198 break; 2199 } 2200 case PLDM_EFFECTER_DATA_SIZE_SINT32: 2201 { 2202 output["pendingValue"] = 2203 *(reinterpret_cast<int32_t*>(pendingValue.data())); 2204 output["presentValue"] = 2205 *(reinterpret_cast<int32_t*>(presentValue.data())); 2206 break; 2207 } 2208 default: 2209 { 2210 std::cerr << "Unknown Effecter Data Size : " 2211 << static_cast<int>(effecterDataSize) << std::endl; 2212 break; 2213 } 2214 } 2215 2216 pldmtool::helper::DisplayInJson(output); 2217 } 2218 2219 private: 2220 uint16_t effecterId; 2221 }; 2222 2223 void registerCommand(CLI::App& app) 2224 { 2225 auto platform = app.add_subcommand("platform", "platform type command"); 2226 platform->require_subcommand(1); 2227 2228 auto getPDR = 2229 platform->add_subcommand("GetPDR", "get platform descriptor records"); 2230 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR)); 2231 2232 auto setStateEffecterStates = platform->add_subcommand( 2233 "SetStateEffecterStates", "set effecter states"); 2234 commands.push_back(std::make_unique<SetStateEffecter>( 2235 "platform", "setStateEffecterStates", setStateEffecterStates)); 2236 2237 auto setNumericEffecterValue = platform->add_subcommand( 2238 "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter"); 2239 commands.push_back(std::make_unique<SetNumericEffecterValue>( 2240 "platform", "setNumericEffecterValue", setNumericEffecterValue)); 2241 2242 auto getStateSensorReadings = platform->add_subcommand( 2243 "GetStateSensorReadings", "get the state sensor readings"); 2244 commands.push_back(std::make_unique<GetStateSensorReadings>( 2245 "platform", "getStateSensorReadings", getStateSensorReadings)); 2246 2247 auto getNumericEffecterValue = platform->add_subcommand( 2248 "GetNumericEffecterValue", "get the numeric effecter value"); 2249 commands.push_back(std::make_unique<GetNumericEffecterValue>( 2250 "platform", "getNumericEffecterValue", getNumericEffecterValue)); 2251 2252 auto getSensorReading = platform->add_subcommand( 2253 "GetSensorReading", "get the numeric sensor reading"); 2254 commands.push_back(std::make_unique<GetSensorReading>( 2255 "platform", "getSensorReading", getSensorReading)); 2256 2257 auto getStateEffecterStates = platform->add_subcommand( 2258 "GetStateEffecterStates", "get the state effecter states"); 2259 commands.push_back(std::make_unique<GetStateEffecterStates>( 2260 "platform", "getStateEffecterStates", getStateEffecterStates)); 2261 } 2262 2263 void parseGetPDROption() 2264 { 2265 for (const auto& command : commands) 2266 { 2267 if (command.get()->getPLDMType() == "platform" && 2268 command.get()->getCommandName() == "getPDR") 2269 { 2270 auto getPDR = dynamic_cast<GetPDR*>(command.get()); 2271 getPDR->parseGetPDROptions(); 2272 } 2273 } 2274 } 2275 2276 } // namespace platform 2277 } // namespace pldmtool 2278