1 #include "common/types.hpp" 2 #include "pldm_cmd_helper.hpp" 3 4 #include <libpldm/entity.h> 5 #include <libpldm/state_set.h> 6 7 #include <cstddef> 8 #include <map> 9 10 #ifdef OEM_IBM 11 #include "oem/ibm/oem_ibm_state_set.hpp" 12 #endif 13 14 using namespace pldm::utils; 15 16 namespace pldmtool 17 { 18 namespace platform 19 { 20 namespace 21 { 22 using namespace pldmtool::helper; 23 24 static const std::map<uint8_t, std::string> sensorPresState{ 25 {PLDM_SENSOR_UNKNOWN, "Sensor Unknown"}, 26 {PLDM_SENSOR_NORMAL, "Sensor Normal"}, 27 {PLDM_SENSOR_WARNING, "Sensor Warning"}, 28 {PLDM_SENSOR_CRITICAL, "Sensor Critical"}, 29 {PLDM_SENSOR_FATAL, "Sensor Fatal"}, 30 {PLDM_SENSOR_LOWERWARNING, "Sensor Lower Warning"}, 31 {PLDM_SENSOR_LOWERCRITICAL, "Sensor Lower Critical"}, 32 {PLDM_SENSOR_LOWERFATAL, "Sensor Lower Fatal"}, 33 {PLDM_SENSOR_UPPERWARNING, "Sensor Upper Warning"}, 34 {PLDM_SENSOR_UPPERCRITICAL, "Sensor Upper Critical"}, 35 {PLDM_SENSOR_UPPERFATAL, "Sensor Upper Fatal"}}; 36 37 static const std::map<uint8_t, std::string> sensorOpState{ 38 {PLDM_SENSOR_ENABLED, "Sensor Enabled"}, 39 {PLDM_SENSOR_DISABLED, "Sensor Disabled"}, 40 {PLDM_SENSOR_UNAVAILABLE, "Sensor Unavailable"}, 41 {PLDM_SENSOR_STATUSUNKOWN, "Sensor Status Unknown"}, 42 {PLDM_SENSOR_FAILED, "Sensor Failed"}, 43 {PLDM_SENSOR_INITIALIZING, "Sensor Sensor Intializing"}, 44 {PLDM_SENSOR_SHUTTINGDOWN, "Sensor Shutting down"}, 45 {PLDM_SENSOR_INTEST, "Sensor Intest"}}; 46 47 std::vector<std::unique_ptr<CommandInterface>> commands; 48 49 } // namespace 50 51 using ordered_json = nlohmann::ordered_json; 52 53 class GetPDR : public CommandInterface 54 { 55 public: 56 ~GetPDR() = default; 57 GetPDR() = delete; 58 GetPDR(const GetPDR&) = delete; 59 GetPDR(GetPDR&&) = default; 60 GetPDR& operator=(const GetPDR&) = delete; 61 GetPDR& operator=(GetPDR&&) = default; 62 63 using CommandInterface::CommandInterface; 64 65 explicit GetPDR(const char* type, const char* name, CLI::App* app) : 66 CommandInterface(type, name, app) 67 { 68 auto pdrOptionGroup = app->add_option_group( 69 "Required Option", 70 "Retrieve individual PDR, all PDRs, or PDRs of a requested type"); 71 pdrOptionGroup->add_option( 72 "-d,--data", recordHandle, 73 "retrieve individual PDRs from a PDR Repository\n" 74 "eg: The recordHandle value for the PDR to be retrieved and 0 " 75 "means get first PDR in the repository."); 76 pdrRecType = ""; 77 pdrOptionGroup->add_option("-t, --type", pdrRecType, 78 "retrieve all PDRs of the requested type\n" 79 "supported types:\n" 80 "[terminusLocator, stateSensor, " 81 "numericEffecter, stateEffecter, " 82 "EntityAssociation, fruRecord, ... ]"); 83 allPDRs = false; 84 pdrOptionGroup->add_flag("-a, --all", allPDRs, 85 "retrieve all PDRs from a PDR repository"); 86 pdrOptionGroup->require_option(1); 87 } 88 89 void exec() override 90 { 91 if (allPDRs || !pdrRecType.empty()) 92 { 93 if (!pdrRecType.empty()) 94 { 95 std::transform(pdrRecType.begin(), pdrRecType.end(), 96 pdrRecType.begin(), tolower); 97 } 98 99 // start the array 100 std::cout << "[\n"; 101 102 // Retrieve all PDR records starting from the first 103 recordHandle = 0; 104 uint32_t prevRecordHandle = 0; 105 std::map<uint32_t, uint32_t> recordsSeen; 106 do 107 { 108 CommandInterface::exec(); 109 // recordHandle is updated to nextRecord when 110 // CommandInterface::exec() is successful. 111 // In case of any error, return. 112 if (recordHandle == prevRecordHandle) 113 { 114 return; 115 } 116 117 // check for circular references. 118 auto result = recordsSeen.emplace(recordHandle, 119 prevRecordHandle); 120 if (!result.second) 121 { 122 std::cerr 123 << "Record handle " << recordHandle 124 << " has multiple references: " << result.first->second 125 << ", " << prevRecordHandle << "\n"; 126 return; 127 } 128 prevRecordHandle = recordHandle; 129 130 if (recordHandle != 0) 131 { 132 // close the array 133 std::cout << ","; 134 } 135 } while (recordHandle != 0); 136 137 // close the array 138 std::cout << "]\n"; 139 } 140 else 141 { 142 CommandInterface::exec(); 143 } 144 } 145 146 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 147 { 148 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 149 PLDM_GET_PDR_REQ_BYTES); 150 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 151 152 auto rc = encode_get_pdr_req(instanceId, recordHandle, 0, 153 PLDM_GET_FIRSTPART, UINT16_MAX, 0, request, 154 PLDM_GET_PDR_REQ_BYTES); 155 return {rc, requestMsg}; 156 } 157 158 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 159 { 160 uint8_t completionCode = 0; 161 uint8_t recordData[UINT16_MAX] = {0}; 162 uint32_t nextRecordHndl = 0; 163 uint32_t nextDataTransferHndl = 0; 164 uint8_t transferFlag = 0; 165 uint16_t respCnt = 0; 166 uint8_t transferCRC = 0; 167 168 auto rc = decode_get_pdr_resp( 169 responsePtr, payloadLength, &completionCode, &nextRecordHndl, 170 &nextDataTransferHndl, &transferFlag, &respCnt, recordData, 171 sizeof(recordData), &transferCRC); 172 173 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 174 { 175 std::cerr << "Response Message Error: " 176 << "rc=" << rc << ",cc=" << (int)completionCode 177 << std::endl; 178 return; 179 } 180 181 printPDRMsg(nextRecordHndl, respCnt, recordData); 182 recordHandle = nextRecordHndl; 183 } 184 185 private: 186 const std::map<pldm::pdr::EntityType, std::string> entityType = { 187 {PLDM_ENTITY_UNSPECIFIED, "Unspecified"}, 188 {PLDM_ENTITY_OTHER, "Other"}, 189 {PLDM_ENTITY_NETWORK, "Network"}, 190 {PLDM_ENTITY_GROUP, "Group"}, 191 {PLDM_ENTITY_REMOTE_MGMT_COMM_DEVICE, 192 "Remote Management Communication Device"}, 193 {PLDM_ENTITY_EXTERNAL_ENVIRONMENT, "External Environment"}, 194 {PLDM_ENTITY_COMM_CHANNEL, " Communication Channel"}, 195 {PLDM_ENTITY_TERMINUS, "PLDM Terminus"}, 196 {PLDM_ENTITY_PLATFORM_EVENT_LOG, " Platform Event Log"}, 197 {PLDM_ENTITY_KEYPAD, "keypad"}, 198 {PLDM_ENTITY_SWITCH, "Switch"}, 199 {PLDM_ENTITY_PUSHBUTTON, "Pushbutton"}, 200 {PLDM_ENTITY_DISPLAY, "Display"}, 201 {PLDM_ENTITY_INDICATOR, "Indicator"}, 202 {PLDM_ENTITY_SYS_MGMT_SW, "System Management Software"}, 203 {PLDM_ENTITY_SYS_FIRMWARE, "System Firmware"}, 204 {PLDM_ENTITY_OPERATING_SYS, "Operating System"}, 205 {PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER, "Virtual Machine Manager"}, 206 {PLDM_ENTITY_OS_LOADER, "OS Loader"}, 207 {PLDM_ENTITY_DEVICE_DRIVER, "Device Driver"}, 208 {PLDM_ENTITY_MGMT_CONTROLLER_FW, "Management Controller Firmware"}, 209 {PLDM_ENTITY_SYSTEM_CHASSIS, "System chassis (main enclosure)"}, 210 {PLDM_ENTITY_SUB_CHASSIS, "Sub-chassis"}, 211 {PLDM_ENTITY_DISK_DRIVE_BAY, "Disk Drive Bay"}, 212 {PLDM_ENTITY_PERIPHERAL_BAY, "Peripheral Bay"}, 213 {PLDM_ENTITY_DEVICE_BAY, "Device bay"}, 214 {PLDM_ENTITY_DOOR, "Door"}, 215 {PLDM_ENTITY_ACCESS_PANEL, "Access Panel"}, 216 {PLDM_ENTITY_COVER, "Cover"}, 217 {PLDM_ENTITY_BOARD, "Board"}, 218 {PLDM_ENTITY_CARD, "Card"}, 219 {PLDM_ENTITY_MODULE, "Module"}, 220 {PLDM_ENTITY_SYS_MGMT_MODULE, "System management module"}, 221 {PLDM_ENTITY_SYS_BOARD, "System Board"}, 222 {PLDM_ENTITY_MEMORY_BOARD, "Memory Board"}, 223 {PLDM_ENTITY_MEMORY_MODULE, "Memory Module"}, 224 {PLDM_ENTITY_PROC_MODULE, "Processor Module"}, 225 {PLDM_ENTITY_ADD_IN_CARD, "Add-in Card"}, 226 {PLDM_ENTITY_CHASSIS_FRONT_PANEL_BOARD, 227 "Chassis front panel board(control panel)"}, 228 {PLDM_ENTITY_BACK_PANEL_BOARD, "Back panel board"}, 229 {PLDM_ENTITY_POWER_MGMT, "Power management board"}, 230 {PLDM_ENTITY_POWER_SYS_BOARD, "Power system board"}, 231 {PLDM_ENTITY_DRIVE_BACKPLANE, "Drive backplane"}, 232 {PLDM_ENTITY_SYS_INTERNAL_EXPANSION_BOARD, 233 "System internal expansion board"}, 234 {PLDM_ENTITY_OTHER_SYS_BOARD, "Other system board"}, 235 {PLDM_ENTITY_CHASSIS_BACK_PANEL_BOARD, "Chassis back panel board"}, 236 {PLDM_ENTITY_PROCESSING_BLADE, "Processing blade"}, 237 {PLDM_ENTITY_CONNECTIVITY_SWITCH, "Connectivity switch"}, 238 {PLDM_ENTITY_PROC_MEMORY_MODULE, "Processor/Memory Module"}, 239 {PLDM_ENTITY_IO_MODULE, "I/O Module"}, 240 {PLDM_ENTITY_PROC_IO_MODULE, "Processor I/O Module"}, 241 {PLDM_ENTITY_COOLING_DEVICE, "Cooling device"}, 242 {PLDM_ENTITY_COOLING_SUBSYSTEM, "Cooling subsystem"}, 243 {PLDM_ENTITY_COOLING_UNIT, "Cooling Unit"}, 244 {PLDM_ENTITY_FAN, "Fan"}, 245 {PLDM_ENTITY_PELTIER_COOLING_DEVICE, "Peltier Cooling Device"}, 246 {PLDM_ENTITY_LIQUID_COOLING_DEVICE, "Liquid Cooling Device"}, 247 {PLDM_ENTITY_LIQUID_COOLING_SUBSYSTEM, "Liquid Colling Subsystem"}, 248 {PLDM_ENTITY_OTHER_STORAGE_DEVICE, "Other Storage Device"}, 249 {PLDM_ENTITY_FLOPPY_DRIVE, "Floppy Drive"}, 250 {PLDM_ENTITY_FIXED_DISK_HARD_DRIVE, "Hard Drive"}, 251 {PLDM_ENTITY_CD_DRIVE, "CD Drive"}, 252 {PLDM_ENTITY_CD_DVD_DRIVE, "CD/DVD Drive"}, 253 {PLDM_ENTITY_OTHER_SILICON_STORAGE_DEVICE, 254 "Other Silicon Storage Device"}, 255 {PLDM_ENTITY_SOLID_STATE_SRIVE, "Solid State Drive"}, 256 {PLDM_ENTITY_POWER_SUPPLY, "Power supply"}, 257 {PLDM_ENTITY_BATTERY, "Battery"}, 258 {PLDM_ENTITY_SUPER_CAPACITOR, "Super Capacitor"}, 259 {PLDM_ENTITY_POWER_CONVERTER, "Power Converter"}, 260 {PLDM_ENTITY_DC_DC_CONVERTER, "DC-DC Converter"}, 261 {PLDM_ENTITY_AC_MAINS_POWER_SUPPLY, "AC mains power supply"}, 262 {PLDM_ENTITY_DC_MAINS_POWER_SUPPLY, "DC mains power supply"}, 263 {PLDM_ENTITY_PROC, "Processor"}, 264 {PLDM_ENTITY_CHIPSET_COMPONENT, "Chipset Component"}, 265 {PLDM_ENTITY_MGMT_CONTROLLER, "Management Controller"}, 266 {PLDM_ENTITY_PERIPHERAL_CONTROLLER, "Peripheral Controller"}, 267 {PLDM_ENTITY_SEEPROM, "SEEPROM"}, 268 {PLDM_ENTITY_NVRAM_CHIP, "NVRAM Chip"}, 269 {PLDM_ENTITY_FLASH_MEMORY_CHIP, "FLASH Memory chip"}, 270 {PLDM_ENTITY_MEMORY_CHIP, "Memory Chip"}, 271 {PLDM_ENTITY_MEMORY_CONTROLLER, "Memory Controller"}, 272 {PLDM_ENTITY_NETWORK_CONTROLLER, "Network Controller"}, 273 {PLDM_ENTITY_IO_CONTROLLER, "I/O Controller"}, 274 {PLDM_ENTITY_SOUTH_BRIDGE, "South Bridge"}, 275 {PLDM_ENTITY_REAL_TIME_CLOCK, "Real Time Clock (RTC)"}, 276 {PLDM_ENTITY_FPGA_CPLD_DEVICE, "FPGA/CPLD Configurable Logic Device"}, 277 {PLDM_ENTITY_OTHER_BUS, "Other Bus"}, 278 {PLDM_ENTITY_SYS_BUS, "System Bus"}, 279 {PLDM_ENTITY_I2C_BUS, "I2C Bus"}, 280 {PLDM_ENTITY_SMBUS_BUS, "SMBus Bus"}, 281 {PLDM_ENTITY_SPI_BUS, "SPI Bus"}, 282 {PLDM_ENTITY_PCI_BUS, "PCI Bus"}, 283 {PLDM_ENTITY_PCI_EXPRESS_BUS, "PCI Express Bus"}, 284 {PLDM_ENTITY_PECI_BUS, "PECI Bus"}, 285 {PLDM_ENTITY_LPC_BUS, "LPC Bus"}, 286 {PLDM_ENTITY_USB_BUS, "USB Bus"}, 287 {PLDM_ENTITY_FIREWIRE_BUS, "FireWire Bus"}, 288 {PLDM_ENTITY_SCSI_BUS, "SCSI Bus"}, 289 {PLDM_ENTITY_SATA_SAS_BUS, "SATA/SAS Bus"}, 290 {PLDM_ENTITY_PROC_FRONT_SIDE_BUS, "Processor/Front-side Bus"}, 291 {PLDM_ENTITY_INTER_PROC_BUS, "Inter-processor Bus"}, 292 {PLDM_ENTITY_CONNECTOR, "Connector"}, 293 {PLDM_ENTITY_SLOT, "Slot"}, 294 {PLDM_ENTITY_CABLE, "Cable(electrical or optical)"}, 295 {PLDM_ENTITY_INTERCONNECT, "Interconnect"}, 296 {PLDM_ENTITY_PLUG, "Plug"}, 297 {PLDM_ENTITY_SOCKET, "Socket"}, 298 }; 299 300 const std::map<uint16_t, std::string> stateSet = { 301 {PLDM_STATE_SET_HEALTH_STATE, "Health State"}, 302 {PLDM_STATE_SET_AVAILABILITY, "Availability"}, 303 {PLDM_STATE_SET_PREDICTIVE_CONDITION, "Predictive Condition"}, 304 {PLDM_STATE_SET_REDUNDANCY_STATUS, "Redundancy Status"}, 305 {PLDM_STATE_SET_HEALTH_REDUNDANCY_TREND, "Health/Redundancy Trend"}, 306 {PLDM_STATE_SET_GROUP_RESOURCE_LEVEL, "Group Resource Level"}, 307 {PLDM_STATE_SET_REDUNDANCY_ENTITY_ROLE, "Redundancy Entity Role"}, 308 {PLDM_STATE_SET_OPERATIONAL_STATUS, "Operational Status"}, 309 {PLDM_STATE_SET_OPERATIONAL_STRESS_STATUS, "Operational Stress Status"}, 310 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, "Operational Fault Status"}, 311 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 312 "Operational Running Status"}, 313 {PLDM_STATE_SET_OPERATIONAL_CONNECTION_STATUS, 314 "Operational Connection Status"}, 315 {PLDM_STATE_SET_PRESENCE, "Presence"}, 316 {PLDM_STATE_SET_PERFORMANCE, "Performance"}, 317 {PLDM_STATE_SET_CONFIGURATION_STATE, "Configuration State"}, 318 {PLDM_STATE_SET_CHANGED_CONFIGURATION, "Changed Configuration"}, 319 {PLDM_STATE_SET_IDENTIFY_STATE, "Identify State"}, 320 {PLDM_STATE_SET_VERSION, "Version"}, 321 {PLDM_STATE_SET_ALARM_STATE, "Alarm State"}, 322 {PLDM_STATE_SET_DEVICE_INITIALIZATION, "Device Initialization"}, 323 {PLDM_STATE_SET_THERMAL_TRIP, "Thermal Trip"}, 324 {PLDM_STATE_SET_HEARTBEAT, "Heartbeat"}, 325 {PLDM_STATE_SET_LINK_STATE, "Link State"}, 326 {PLDM_STATE_SET_SMOKE_STATE, "Smoke State"}, 327 {PLDM_STATE_SET_HUMIDITY_STATE, "Humidity State"}, 328 {PLDM_STATE_SET_DOOR_STATE, "Door State"}, 329 {PLDM_STATE_SET_SWITCH_STATE, "Switch State"}, 330 {PLDM_STATE_SET_LOCK_STATE, "Lock State"}, 331 {PLDM_STATE_SET_PHYSICAL_SECURITY, "Physical Security"}, 332 {PLDM_STATE_SET_DOCK_AUTHORIZATION, "Dock Authorization"}, 333 {PLDM_STATE_SET_HW_SECURITY, "Hardware Security"}, 334 {PLDM_STATE_SET_PHYSICAL_COMM_CONNECTION, 335 "Physical Communication Connection"}, 336 {PLDM_STATE_SET_COMM_LEASH_STATUS, "Communication Leash Status"}, 337 {PLDM_STATE_SET_FOREIGN_NW_DETECTION_STATUS, 338 "Foreign Network Detection Status"}, 339 {PLDM_STATE_SET_PASSWORD_PROTECTED_ACCESS_SECURITY, 340 "Password-Protected Access Security"}, 341 {PLDM_STATE_SET_SECURITY_ACCESS_PRIVILEGE_LEVEL, 342 "Security Access –PrivilegeLevel"}, 343 {PLDM_STATE_SET_SESSION_AUDIT, "PLDM Session Audit"}, 344 {PLDM_STATE_SET_SW_TERMINATION_STATUS, "Software Termination Status"}, 345 {PLDM_STATE_SET_STORAGE_MEDIA_ACTIVITY, "Storage Media Activity"}, 346 {PLDM_STATE_SET_BOOT_RESTART_CAUSE, "Boot/Restart Cause"}, 347 {PLDM_STATE_SET_BOOT_RESTART_REQUEST, "Boot/Restart Request"}, 348 {PLDM_STATE_SET_ENTITY_BOOT_STATUS, "Entity Boot Status"}, 349 {PLDM_STATE_SET_BOOT_ERROR_STATUS, "Boot ErrorStatus"}, 350 {PLDM_STATE_SET_BOOT_PROGRESS, "Boot Progress"}, 351 {PLDM_STATE_SET_SYS_FIRMWARE_HANG, "System Firmware Hang"}, 352 {PLDM_STATE_SET_POST_ERRORS, "POST Errors"}, 353 {PLDM_STATE_SET_LOG_FILL_STATUS, "Log Fill Status"}, 354 {PLDM_STATE_SET_LOG_FILTER_STATUS, "Log Filter Status"}, 355 {PLDM_STATE_SET_LOG_TIMESTAMP_CHANGE, "Log Timestamp Change"}, 356 {PLDM_STATE_SET_INTERRUPT_REQUESTED, "Interrupt Requested"}, 357 {PLDM_STATE_SET_INTERRUPT_RECEIVED, "Interrupt Received"}, 358 {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_REQUESTED, 359 "Diagnostic Interrupt Requested"}, 360 {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_RECEIVED, 361 "Diagnostic Interrupt Received"}, 362 {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_REQUESTED, 363 "I/O Channel Check NMI Requested"}, 364 {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_RECEIVED, 365 "I/O Channel Check NMI Received"}, 366 {PLDM_STATE_SET_FATAL_NMI_REQUESTED, "Fatal NMI Requested"}, 367 {PLDM_STATE_SET_FATAL_NMI_RECEIVED, "Fatal NMI Received"}, 368 {PLDM_STATE_SET_SOFTWARE_NMI_REQUESTED, "Software NMI Requested"}, 369 {PLDM_STATE_SET_SOFTWARE_NMI_RECEIVED, "Software NMI Received"}, 370 {PLDM_STATE_SET_SMI_REQUESTED, "SMI Requested"}, 371 {PLDM_STATE_SET_SMI_RECEIVED, "SMI Received"}, 372 {PLDM_STATE_SET_PCI_PERR_REQUESTED, "PCI PERR Requested"}, 373 {PLDM_STATE_SET_PCI_PERR_RECEIVED, "PCI PERR Received"}, 374 {PLDM_STATE_SET_PCI_SERR_REQUESTED, "PCI SERR Requested "}, 375 {PLDM_STATE_SET_PCI_SERR_RECEIVED, "PCI SERR Received"}, 376 {PLDM_STATE_SET_BUS_ERROR_STATUS, "Bus Error Status"}, 377 {PLDM_STATE_SET_WATCHDOG_STATUS, "Watchdog Status"}, 378 {PLDM_STATE_SET_POWER_SUPPLY_STATE, "Power Supply State"}, 379 {PLDM_STATE_SET_DEVICE_POWER_STATE, "Device Power State"}, 380 {PLDM_STATE_SET_ACPI_POWER_STATE, "ACPI Power State"}, 381 {PLDM_STATE_SET_BACKUP_POWER_SOURCE, "Backup Power Source"}, 382 {PLDM_STATE_SET_SYSTEM_POWER_STATE, "System Power State "}, 383 {PLDM_STATE_SET_BATTERY_ACTIVITY, "Battery Activity"}, 384 {PLDM_STATE_SET_BATTERY_STATE, "Battery State"}, 385 {PLDM_STATE_SET_PROC_POWER_STATE, "Processor Power State"}, 386 {PLDM_STATE_SET_POWER_PERFORMANCE_STATE, "Power-Performance State"}, 387 {PLDM_STATE_SET_PROC_ERROR_STATUS, "Processor Error Status"}, 388 {PLDM_STATE_SET_BIST_FAILURE_STATUS, "BIST FailureStatus"}, 389 {PLDM_STATE_SET_IBIST_FAILURE_STATUS, "IBIST FailureStatus"}, 390 {PLDM_STATE_SET_PROC_HANG_IN_POST, "Processor Hang in POST"}, 391 {PLDM_STATE_SET_PROC_STARTUP_FAILURE, "Processor Startup Failure"}, 392 {PLDM_STATE_SET_UNCORRECTABLE_CPU_ERROR, "Uncorrectable CPU Error"}, 393 {PLDM_STATE_SET_MACHINE_CHECK_ERROR, "Machine Check Error"}, 394 {PLDM_STATE_SET_CORRECTED_MACHINE_CHECK, "Corrected Machine Check"}, 395 {PLDM_STATE_SET_CACHE_STATUS, "Cache Status"}, 396 {PLDM_STATE_SET_MEMORY_ERROR_STATUS, "Memory Error Status"}, 397 {PLDM_STATE_SET_REDUNDANT_MEMORY_ACTIVITY_STATUS, 398 "Redundant Memory Activity Status"}, 399 {PLDM_STATE_SET_ERROR_DETECTION_STATUS, "Error Detection Status"}, 400 {PLDM_STATE_SET_STUCK_BIT_STATUS, "Stuck Bit Status"}, 401 {PLDM_STATE_SET_SCRUB_STATUS, "Scrub Status"}, 402 {PLDM_STATE_SET_SLOT_OCCUPANCY, "Slot Occupancy"}, 403 {PLDM_STATE_SET_SLOT_STATE, "Slot State"}, 404 }; 405 406 const std::array<std::string_view, 4> sensorInit = { 407 "noInit", "useInitPDR", "enableSensor", "disableSensor"}; 408 409 const std::array<std::string_view, 4> effecterInit = { 410 "noInit", "useInitPDR", "enableEffecter", "disableEffecter"}; 411 412 const std::map<uint8_t, std::string> pdrType = { 413 {PLDM_TERMINUS_LOCATOR_PDR, "Terminus Locator PDR"}, 414 {PLDM_NUMERIC_SENSOR_PDR, "Numeric Sensor PDR"}, 415 {PLDM_NUMERIC_SENSOR_INITIALIZATION_PDR, 416 "Numeric Sensor Initialization PDR"}, 417 {PLDM_STATE_SENSOR_PDR, "State Sensor PDR"}, 418 {PLDM_STATE_SENSOR_INITIALIZATION_PDR, 419 "State Sensor Initialization PDR"}, 420 {PLDM_SENSOR_AUXILIARY_NAMES_PDR, "Sensor Auxiliary Names PDR"}, 421 {PLDM_OEM_UNIT_PDR, "OEM Unit PDR"}, 422 {PLDM_OEM_STATE_SET_PDR, "OEM State Set PDR"}, 423 {PLDM_NUMERIC_EFFECTER_PDR, "Numeric Effecter PDR"}, 424 {PLDM_NUMERIC_EFFECTER_INITIALIZATION_PDR, 425 "Numeric Effecter Initialization PDR"}, 426 {PLDM_STATE_EFFECTER_PDR, "State Effecter PDR"}, 427 {PLDM_STATE_EFFECTER_INITIALIZATION_PDR, 428 "State Effecter Initialization PDR"}, 429 {PLDM_EFFECTER_AUXILIARY_NAMES_PDR, "Effecter Auxiliary Names PDR"}, 430 {PLDM_EFFECTER_OEM_SEMANTIC_PDR, "Effecter OEM Semantic PDR"}, 431 {PLDM_PDR_ENTITY_ASSOCIATION, "Entity Association PDR"}, 432 {PLDM_ENTITY_AUXILIARY_NAMES_PDR, "Entity Auxiliary Names PDR"}, 433 {PLDM_OEM_ENTITY_ID_PDR, "OEM Entity ID PDR"}, 434 {PLDM_INTERRUPT_ASSOCIATION_PDR, "Interrupt Association PDR"}, 435 {PLDM_EVENT_LOG_PDR, "PLDM Event Log PDR"}, 436 {PLDM_PDR_FRU_RECORD_SET, "FRU Record Set PDR"}, 437 {PLDM_OEM_DEVICE_PDR, "OEM Device PDR"}, 438 {PLDM_OEM_PDR, "OEM PDR"}, 439 }; 440 441 static inline const std::map<uint8_t, std::string> setThermalTrip{ 442 {PLDM_STATE_SET_THERMAL_TRIP_STATUS_NORMAL, "Normal"}, 443 {PLDM_STATE_SET_THERMAL_TRIP_STATUS_THERMAL_TRIP, "Thermal Trip"}}; 444 445 static inline const std::map<uint8_t, std::string> setIdentifyState{ 446 {PLDM_STATE_SET_IDENTIFY_STATE_UNASSERTED, "Identify State Unasserted"}, 447 {PLDM_STATE_SET_IDENTIFY_STATE_ASSERTED, "Identify State Asserted"}}; 448 449 static inline const std::map<uint8_t, std::string> setBootProgressState{ 450 {PLDM_STATE_SET_BOOT_PROG_STATE_NOT_ACTIVE, "Boot Not Active"}, 451 {PLDM_STATE_SET_BOOT_PROG_STATE_COMPLETED, "Boot Completed"}, 452 {PLDM_STATE_SET_BOOT_PROG_STATE_MEM_INITIALIZATION, 453 "Memory Initialization"}, 454 {PLDM_STATE_SET_BOOT_PROG_STATE_SEC_PROC_INITIALIZATION, 455 "Secondary Processor(s) Initialization"}, 456 {PLDM_STATE_SET_BOOT_PROG_STATE_PCI_RESORUCE_CONFIG, 457 "PCI Resource Configuration"}, 458 {PLDM_STATE_SET_BOOT_PROG_STATE_STARTING_OP_SYS, 459 "Starting Operating System"}, 460 {PLDM_STATE_SET_BOOT_PROG_STATE_BASE_BOARD_INITIALIZATION, 461 "Baseboard Initialization"}, 462 {PLDM_STATE_SET_BOOT_PROG_STATE_PRIMARY_PROC_INITIALIZATION, 463 "Primary Processor Initialization"}, 464 {PLDM_STATE_SET_BOOT_PROG_STATE_OSSTART, "OSStart"}}; 465 466 static inline const std::map<uint8_t, std::string> setOpFaultStatus{ 467 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_NORMAL, "Normal"}, 468 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_STRESSED, "Stressed"}}; 469 470 static inline const std::map<uint8_t, std::string> setSysPowerState{ 471 {PLDM_STATE_SET_SYS_POWER_STATE_OFF_SOFT_GRACEFUL, 472 "Off-Soft Graceful"}}; 473 474 static inline const std::map<uint8_t, std::string> setSWTerminationStatus{ 475 {PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED, 476 "Graceful Restart Requested"}}; 477 478 static inline const std::map<uint8_t, std::string> setAvailability{ 479 {PLDM_STATE_SET_AVAILABILITY_REBOOTING, "Rebooting"}}; 480 481 static inline const std::map<uint8_t, std::string> setHealthState{ 482 {PLDM_STATE_SET_HEALTH_STATE_NORMAL, "Normal"}, 483 {PLDM_STATE_SET_HEALTH_STATE_NON_CRITICAL, "Non-Critical"}, 484 {PLDM_STATE_SET_HEALTH_STATE_CRITICAL, "Critical"}, 485 {PLDM_STATE_SET_HEALTH_STATE_FATAL, "Fatal"}, 486 {PLDM_STATE_SET_HEALTH_STATE_UPPER_NON_CRITICAL, "Upper Non-Critical"}, 487 {PLDM_STATE_SET_HEALTH_STATE_LOWER_NON_CRITICAL, "Lower Non-Critical"}, 488 {PLDM_STATE_SET_HEALTH_STATE_UPPER_CRITICAL, "Upper Critical"}, 489 {PLDM_STATE_SET_HEALTH_STATE_LOWER_CRITICAL, "Lower Critical"}, 490 {PLDM_STATE_SET_HEALTH_STATE_UPPER_FATAL, "Upper Fatal"}, 491 {PLDM_STATE_SET_HEALTH_STATE_LOWER_FATAL, "Lower Fatal"}}; 492 493 static inline const std::map<uint8_t, std::string> 494 setOperationalRunningState{ 495 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STARTING, "Starting"}, 496 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPING, "Stopping"}, 497 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED, "Stopped"}, 498 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE, 499 "In Service"}, 500 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_ABORTED, "Aborted"}, 501 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT, "Dormant"}}; 502 503 static inline const std::map<uint16_t, const std::map<uint8_t, std::string>> 504 populatePStateMaps{ 505 {PLDM_STATE_SET_THERMAL_TRIP, setThermalTrip}, 506 {PLDM_STATE_SET_IDENTIFY_STATE, setIdentifyState}, 507 {PLDM_STATE_SET_BOOT_PROGRESS, setBootProgressState}, 508 {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, setOpFaultStatus}, 509 {PLDM_STATE_SET_SYSTEM_POWER_STATE, setSysPowerState}, 510 {PLDM_STATE_SET_SW_TERMINATION_STATUS, setSWTerminationStatus}, 511 {PLDM_STATE_SET_AVAILABILITY, setAvailability}, 512 {PLDM_STATE_SET_HEALTH_STATE, setHealthState}, 513 {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 514 setOperationalRunningState}, 515 }; 516 517 const std::map<std::string, uint8_t> strToPdrType = { 518 {"terminuslocator", PLDM_TERMINUS_LOCATOR_PDR}, 519 {"statesensor", PLDM_STATE_SENSOR_PDR}, 520 {"numericeffecter", PLDM_NUMERIC_EFFECTER_PDR}, 521 {"stateeffecter", PLDM_STATE_EFFECTER_PDR}, 522 {"entityassociation", PLDM_PDR_ENTITY_ASSOCIATION}, 523 {"frurecord", PLDM_PDR_FRU_RECORD_SET}, 524 // Add other types 525 }; 526 527 bool isLogicalBitSet(const uint16_t entity_type) 528 { 529 return entity_type & 0x8000; 530 } 531 532 uint16_t getEntityTypeForLogicalEntity(const uint16_t logical_entity_type) 533 { 534 return logical_entity_type & 0x7FFF; 535 } 536 537 std::string getEntityName(pldm::pdr::EntityType type) 538 { 539 uint16_t entityNumber = type; 540 std::string entityName = "[Physical] "; 541 542 if (isLogicalBitSet(type)) 543 { 544 entityName = "[Logical] "; 545 entityNumber = getEntityTypeForLogicalEntity(type); 546 } 547 548 try 549 { 550 return entityName + entityType.at(entityNumber); 551 } 552 catch (const std::out_of_range& e) 553 { 554 auto OemString = 555 std::to_string(static_cast<unsigned>(entityNumber)); 556 if (type >= PLDM_OEM_ENTITY_TYPE_START && 557 type <= PLDM_OEM_ENTITY_TYPE_END) 558 { 559 #ifdef OEM_IBM 560 if (OemIBMEntityType.contains(entityNumber)) 561 { 562 return entityName + OemIBMEntityType.at(entityNumber) + 563 "(OEM)"; 564 } 565 #endif 566 return entityName + OemString + "(OEM)"; 567 } 568 return OemString; 569 } 570 } 571 572 std::string getStateSetName(uint16_t id) 573 { 574 auto typeString = std::to_string(id); 575 try 576 { 577 return stateSet.at(id) + "(" + typeString + ")"; 578 } 579 catch (const std::out_of_range& e) 580 { 581 return typeString; 582 } 583 } 584 585 std::vector<std::string> 586 getStateSetPossibleStateNames(uint16_t stateId, 587 const std::vector<uint8_t>& value) 588 { 589 std::vector<std::string> data{}; 590 std::map<uint8_t, std::string> stateNameMaps; 591 592 for (auto& s : value) 593 { 594 std::map<uint8_t, std::string> stateNameMaps; 595 auto pstr = std::to_string(s); 596 597 #ifdef OEM_IBM 598 if (stateId >= PLDM_OEM_STATE_SET_ID_START && 599 stateId < PLDM_OEM_STATE_SET_ID_END) 600 { 601 if (populateOemIBMStateMaps.contains(stateId)) 602 { 603 const std::map<uint8_t, std::string> stateNames = 604 populateOemIBMStateMaps.at(stateId); 605 stateNameMaps.insert(stateNames.begin(), stateNames.end()); 606 } 607 } 608 #endif 609 if (populatePStateMaps.contains(stateId)) 610 { 611 const std::map<uint8_t, std::string> stateNames = 612 populatePStateMaps.at(stateId); 613 stateNameMaps.insert(stateNames.begin(), stateNames.end()); 614 } 615 if (stateNameMaps.contains(s)) 616 { 617 data.push_back(stateNameMaps.at(s) + "(" + pstr + ")"); 618 } 619 else 620 { 621 data.push_back(pstr); 622 } 623 } 624 return data; 625 } 626 627 std::string getPDRType(uint8_t type) 628 { 629 auto typeString = std::to_string(type); 630 try 631 { 632 return pdrType.at(type); 633 } 634 catch (const std::out_of_range& e) 635 { 636 return typeString; 637 } 638 } 639 640 void printCommonPDRHeader(const pldm_pdr_hdr* hdr, ordered_json& output) 641 { 642 output["recordHandle"] = hdr->record_handle; 643 output["PDRHeaderVersion"] = unsigned(hdr->version); 644 output["PDRType"] = getPDRType(hdr->type); 645 output["recordChangeNumber"] = hdr->record_change_num; 646 output["dataLength"] = hdr->length; 647 } 648 649 std::vector<uint8_t> printPossibleStates(uint8_t possibleStatesSize, 650 const bitfield8_t* states) 651 { 652 uint8_t possibleStatesPos{}; 653 std::vector<uint8_t> data{}; 654 auto printStates = [&possibleStatesPos, &data](const bitfield8_t& val) { 655 std::stringstream pstates; 656 for (int i = 0; i < CHAR_BIT; i++) 657 { 658 if (val.byte & (1 << i)) 659 { 660 pstates << (possibleStatesPos * CHAR_BIT + i); 661 data.push_back( 662 static_cast<uint8_t>(std::stoi(pstates.str()))); 663 pstates.str(""); 664 } 665 } 666 possibleStatesPos++; 667 }; 668 std::for_each(states, states + possibleStatesSize, printStates); 669 return data; 670 } 671 672 void printStateSensorPDR(const uint8_t* data, ordered_json& output) 673 { 674 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(data); 675 output["PLDMTerminusHandle"] = pdr->terminus_handle; 676 output["sensorID"] = pdr->sensor_id; 677 output["entityType"] = getEntityName(pdr->entity_type); 678 output["entityInstanceNumber"] = pdr->entity_instance; 679 output["containerID"] = pdr->container_id; 680 output["sensorInit"] = sensorInit[pdr->sensor_init]; 681 output["sensorAuxiliaryNamesPDR"] = 682 (pdr->sensor_auxiliary_names_pdr ? true : false); 683 output["compositeSensorCount"] = unsigned(pdr->composite_sensor_count); 684 685 auto statesPtr = pdr->possible_states; 686 auto compCount = pdr->composite_sensor_count; 687 688 while (compCount--) 689 { 690 auto state = reinterpret_cast<const state_sensor_possible_states*>( 691 statesPtr); 692 output.emplace(("stateSetID[" + std::to_string(compCount) + "]"), 693 getStateSetName(state->state_set_id)); 694 output.emplace( 695 ("possibleStatesSize[" + std::to_string(compCount) + "]"), 696 state->possible_states_size); 697 output.emplace( 698 ("possibleStates[" + std::to_string(compCount) + "]"), 699 getStateSetPossibleStateNames( 700 state->state_set_id, 701 printPossibleStates(state->possible_states_size, 702 state->states))); 703 704 if (compCount) 705 { 706 statesPtr += sizeof(state_sensor_possible_states) + 707 state->possible_states_size - 1; 708 } 709 } 710 } 711 712 void printPDRFruRecordSet(uint8_t* data, ordered_json& output) 713 { 714 if (data == NULL) 715 { 716 return; 717 } 718 719 data += sizeof(pldm_pdr_hdr); 720 pldm_pdr_fru_record_set* pdr = 721 reinterpret_cast<pldm_pdr_fru_record_set*>(data); 722 if (!pdr) 723 { 724 std::cerr << "Failed to get the FRU record set PDR" << std::endl; 725 return; 726 } 727 728 output["PLDMTerminusHandle"] = unsigned(pdr->terminus_handle); 729 output["FRURecordSetIdentifier"] = unsigned(pdr->fru_rsi); 730 output["entityType"] = getEntityName(pdr->entity_type); 731 output["entityInstanceNumber"] = unsigned(pdr->entity_instance_num); 732 output["containerID"] = unsigned(pdr->container_id); 733 } 734 735 void printPDREntityAssociation(uint8_t* data, ordered_json& output) 736 { 737 const std::map<uint8_t, const char*> assocationType = { 738 {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"}, 739 {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"}, 740 }; 741 742 if (data == NULL) 743 { 744 return; 745 } 746 747 data += sizeof(pldm_pdr_hdr); 748 pldm_pdr_entity_association* pdr = 749 reinterpret_cast<pldm_pdr_entity_association*>(data); 750 if (!pdr) 751 { 752 std::cerr << "Failed to get the PDR eneity association" 753 << std::endl; 754 return; 755 } 756 757 output["containerID"] = int(pdr->container_id); 758 if (assocationType.contains(pdr->association_type)) 759 { 760 output["associationType"] = 761 assocationType.at(pdr->association_type); 762 } 763 else 764 { 765 std::cout << "Get associationType failed.\n"; 766 } 767 output["containerEntityType"] = 768 getEntityName(pdr->container.entity_type); 769 output["containerEntityInstanceNumber"] = 770 int(pdr->container.entity_instance_num); 771 output["containerEntityContainerID"] = 772 int(pdr->container.entity_container_id); 773 output["containedEntityCount"] = 774 static_cast<unsigned>(pdr->num_children); 775 776 auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]); 777 for (int i = 0; i < pdr->num_children; ++i) 778 { 779 output.emplace("containedEntityType[" + std::to_string(i + 1) + "]", 780 getEntityName(child->entity_type)); 781 output.emplace("containedEntityInstanceNumber[" + 782 std::to_string(i + 1) + "]", 783 unsigned(child->entity_instance_num)); 784 output.emplace("containedEntityContainerID[" + 785 std::to_string(i + 1) + "]", 786 unsigned(child->entity_container_id)); 787 788 ++child; 789 } 790 } 791 792 void printNumericEffecterPDR(uint8_t* data, ordered_json& output) 793 { 794 struct pldm_numeric_effecter_value_pdr* pdr = 795 (struct pldm_numeric_effecter_value_pdr*)data; 796 if (!pdr) 797 { 798 std::cerr << "Failed to get numeric effecter PDR" << std::endl; 799 return; 800 } 801 802 output["PLDMTerminusHandle"] = int(pdr->terminus_handle); 803 output["effecterID"] = int(pdr->effecter_id); 804 output["entityType"] = int(pdr->entity_type); 805 output["entityInstanceNumber"] = int(pdr->entity_instance); 806 output["containerID"] = int(pdr->container_id); 807 output["effecterSemanticID"] = int(pdr->effecter_semantic_id); 808 output["effecterInit"] = unsigned(pdr->effecter_init); 809 output["effecterAuxiliaryNames"] = 810 (unsigned(pdr->effecter_auxiliary_names) ? true : false); 811 output["baseUnit"] = unsigned(pdr->base_unit); 812 output["unitModifier"] = unsigned(pdr->unit_modifier); 813 output["rateUnit"] = unsigned(pdr->rate_unit); 814 output["baseOEMUnitHandle"] = unsigned(pdr->base_oem_unit_handle); 815 output["auxUnit"] = unsigned(pdr->aux_unit); 816 output["auxUnitModifier"] = unsigned(pdr->aux_unit_modifier); 817 output["auxrateUnit"] = unsigned(pdr->aux_rate_unit); 818 output["auxOEMUnitHandle"] = unsigned(pdr->aux_oem_unit_handle); 819 output["isLinear"] = (unsigned(pdr->is_linear) ? true : false); 820 output["effecterDataSize"] = unsigned(pdr->effecter_data_size); 821 output["resolution"] = unsigned(pdr->resolution); 822 output["offset"] = unsigned(pdr->offset); 823 output["accuracy"] = unsigned(pdr->accuracy); 824 output["plusTolerance"] = unsigned(pdr->plus_tolerance); 825 output["minusTolerance"] = unsigned(pdr->minus_tolerance); 826 output["stateTransitionInterval"] = 827 unsigned(pdr->state_transition_interval); 828 output["TransitionInterval"] = unsigned(pdr->transition_interval); 829 830 switch (pdr->effecter_data_size) 831 { 832 case PLDM_EFFECTER_DATA_SIZE_UINT8: 833 output["maxSettable"] = unsigned(pdr->max_settable.value_u8); 834 output["minSettable"] = unsigned(pdr->min_settable.value_u8); 835 break; 836 case PLDM_EFFECTER_DATA_SIZE_SINT8: 837 output["maxSettable"] = unsigned(pdr->max_settable.value_s8); 838 output["minSettable"] = unsigned(pdr->min_settable.value_s8); 839 break; 840 case PLDM_EFFECTER_DATA_SIZE_UINT16: 841 output["maxSettable"] = unsigned(pdr->max_settable.value_u16); 842 output["minSettable"] = unsigned(pdr->min_settable.value_u16); 843 break; 844 case PLDM_EFFECTER_DATA_SIZE_SINT16: 845 output["maxSettable"] = unsigned(pdr->max_settable.value_s16); 846 output["minSettable"] = unsigned(pdr->min_settable.value_s16); 847 break; 848 case PLDM_EFFECTER_DATA_SIZE_UINT32: 849 output["maxSettable"] = unsigned(pdr->max_settable.value_u32); 850 output["minSettable"] = unsigned(pdr->min_settable.value_u32); 851 break; 852 case PLDM_EFFECTER_DATA_SIZE_SINT32: 853 output["maxSettable"] = unsigned(pdr->max_settable.value_s32); 854 output["minSettable"] = unsigned(pdr->min_settable.value_s32); 855 break; 856 default: 857 break; 858 } 859 860 output["rangeFieldFormat"] = unsigned(pdr->range_field_format); 861 output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte); 862 863 switch (pdr->range_field_format) 864 { 865 case PLDM_RANGE_FIELD_FORMAT_UINT8: 866 output["nominalValue"] = unsigned(pdr->nominal_value.value_u8); 867 output["normalMax"] = unsigned(pdr->normal_max.value_u8); 868 output["normalMin"] = unsigned(pdr->normal_min.value_u8); 869 output["ratedMax"] = unsigned(pdr->rated_max.value_u8); 870 output["ratedMin"] = unsigned(pdr->rated_min.value_u8); 871 break; 872 case PLDM_RANGE_FIELD_FORMAT_SINT8: 873 output["nominalValue"] = unsigned(pdr->nominal_value.value_s8); 874 output["normalMax"] = unsigned(pdr->normal_max.value_s8); 875 output["normalMin"] = unsigned(pdr->normal_min.value_s8); 876 output["ratedMax"] = unsigned(pdr->rated_max.value_s8); 877 output["ratedMin"] = unsigned(pdr->rated_min.value_s8); 878 break; 879 case PLDM_RANGE_FIELD_FORMAT_UINT16: 880 output["nominalValue"] = unsigned(pdr->nominal_value.value_u16); 881 output["normalMax"] = unsigned(pdr->normal_max.value_u16); 882 output["normalMin"] = unsigned(pdr->normal_min.value_u16); 883 output["ratedMax"] = unsigned(pdr->rated_max.value_u16); 884 output["ratedMin"] = unsigned(pdr->rated_min.value_u16); 885 break; 886 case PLDM_RANGE_FIELD_FORMAT_SINT16: 887 output["nominalValue"] = unsigned(pdr->nominal_value.value_s16); 888 output["normalMax"] = unsigned(pdr->normal_max.value_s16); 889 output["normalMin"] = unsigned(pdr->normal_min.value_s16); 890 output["ratedMax"] = unsigned(pdr->rated_max.value_s16); 891 output["ratedMin"] = unsigned(pdr->rated_min.value_s16); 892 break; 893 case PLDM_RANGE_FIELD_FORMAT_UINT32: 894 output["nominalValue"] = unsigned(pdr->nominal_value.value_u32); 895 output["normalMax"] = unsigned(pdr->normal_max.value_u32); 896 output["normalMin"] = unsigned(pdr->normal_min.value_u32); 897 output["ratedMax"] = unsigned(pdr->rated_max.value_u32); 898 output["ratedMin"] = unsigned(pdr->rated_min.value_u32); 899 break; 900 case PLDM_RANGE_FIELD_FORMAT_SINT32: 901 output["nominalValue"] = unsigned(pdr->nominal_value.value_s32); 902 output["normalMax"] = unsigned(pdr->normal_max.value_s32); 903 output["normalMin"] = unsigned(pdr->normal_min.value_s32); 904 output["ratedMax"] = unsigned(pdr->rated_max.value_s32); 905 output["ratedMin"] = unsigned(pdr->rated_min.value_s32); 906 break; 907 case PLDM_RANGE_FIELD_FORMAT_REAL32: 908 output["nominalValue"] = unsigned(pdr->nominal_value.value_f32); 909 output["normalMax"] = unsigned(pdr->normal_max.value_f32); 910 output["normalMin"] = unsigned(pdr->normal_min.value_f32); 911 output["ratedMax"] = unsigned(pdr->rated_max.value_f32); 912 output["ratedMin"] = unsigned(pdr->rated_min.value_f32); 913 break; 914 default: 915 break; 916 } 917 } 918 919 void printStateEffecterPDR(const uint8_t* data, ordered_json& output) 920 { 921 auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(data); 922 923 output["PLDMTerminusHandle"] = pdr->terminus_handle; 924 output["effecterID"] = pdr->effecter_id; 925 output["entityType"] = getEntityName(pdr->entity_type); 926 output["entityInstanceNumber"] = pdr->entity_instance; 927 output["containerID"] = pdr->container_id; 928 output["effecterSemanticID"] = pdr->effecter_semantic_id; 929 output["effecterInit"] = effecterInit[pdr->effecter_init]; 930 output["effecterDescriptionPDR"] = (pdr->has_description_pdr ? true 931 : false); 932 output["compositeEffecterCount"] = 933 unsigned(pdr->composite_effecter_count); 934 935 auto statesPtr = pdr->possible_states; 936 auto compEffCount = pdr->composite_effecter_count; 937 938 while (compEffCount--) 939 { 940 auto state = 941 reinterpret_cast<const state_effecter_possible_states*>( 942 statesPtr); 943 output.emplace(("stateSetID[" + std::to_string(compEffCount) + "]"), 944 getStateSetName(state->state_set_id)); 945 output.emplace( 946 ("possibleStatesSize[" + std::to_string(compEffCount) + "]"), 947 state->possible_states_size); 948 output.emplace( 949 ("possibleStates[" + std::to_string(compEffCount) + "]"), 950 getStateSetPossibleStateNames( 951 state->state_set_id, 952 printPossibleStates(state->possible_states_size, 953 state->states))); 954 955 if (compEffCount) 956 { 957 statesPtr += sizeof(state_effecter_possible_states) + 958 state->possible_states_size - 1; 959 } 960 } 961 } 962 963 void printTerminusLocatorPDR(const uint8_t* data, ordered_json& output) 964 { 965 const std::array<std::string_view, 4> terminusLocatorType = { 966 "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"}; 967 968 auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data); 969 970 output["PLDMTerminusHandle"] = pdr->terminus_handle; 971 output["validity"] = (pdr->validity ? "valid" : "notValid"); 972 output["TID"] = unsigned(pdr->tid); 973 output["containerID"] = pdr->container_id; 974 output["terminusLocatorType"] = 975 terminusLocatorType[pdr->terminus_locator_type]; 976 output["terminusLocatorValueSize"] = 977 unsigned(pdr->terminus_locator_value_size); 978 979 if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID) 980 { 981 auto locatorValue = 982 reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>( 983 pdr->terminus_locator_value); 984 output["EID"] = unsigned(locatorValue->eid); 985 } 986 } 987 988 void printPDRMsg(uint32_t& nextRecordHndl, const uint16_t respCnt, 989 uint8_t* data) 990 { 991 if (data == NULL) 992 { 993 std::cerr << "Failed to get PDR message" << std::endl; 994 return; 995 } 996 997 ordered_json output; 998 output["nextRecordHandle"] = nextRecordHndl; 999 output["responseCount"] = respCnt; 1000 1001 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; 1002 if (!pdr) 1003 { 1004 return; 1005 } 1006 1007 if (!pdrRecType.empty()) 1008 { 1009 // Need to return if the requested PDR type 1010 // is not supported 1011 if (!strToPdrType.contains(pdrRecType)) 1012 { 1013 std::cerr << "PDR type '" << pdrRecType 1014 << "' is not supported or invalid\n"; 1015 // PDR type not supported, setting next record handle to 0 1016 // to avoid looping through all PDR records 1017 nextRecordHndl = 0; 1018 return; 1019 } 1020 1021 // Do not print PDR record if the current record 1022 // PDR type does not match with requested type 1023 if (pdr->type != strToPdrType.at(pdrRecType)) 1024 { 1025 return; 1026 } 1027 } 1028 1029 printCommonPDRHeader(pdr, output); 1030 1031 switch (pdr->type) 1032 { 1033 case PLDM_TERMINUS_LOCATOR_PDR: 1034 printTerminusLocatorPDR(data, output); 1035 break; 1036 case PLDM_STATE_SENSOR_PDR: 1037 printStateSensorPDR(data, output); 1038 break; 1039 case PLDM_NUMERIC_EFFECTER_PDR: 1040 printNumericEffecterPDR(data, output); 1041 break; 1042 case PLDM_STATE_EFFECTER_PDR: 1043 printStateEffecterPDR(data, output); 1044 break; 1045 case PLDM_PDR_ENTITY_ASSOCIATION: 1046 printPDREntityAssociation(data, output); 1047 break; 1048 case PLDM_PDR_FRU_RECORD_SET: 1049 printPDRFruRecordSet(data, output); 1050 break; 1051 default: 1052 break; 1053 } 1054 pldmtool::helper::DisplayInJson(output); 1055 } 1056 1057 private: 1058 uint32_t recordHandle; 1059 bool allPDRs; 1060 std::string pdrRecType; 1061 }; 1062 1063 class SetStateEffecter : public CommandInterface 1064 { 1065 public: 1066 ~SetStateEffecter() = default; 1067 SetStateEffecter() = delete; 1068 SetStateEffecter(const SetStateEffecter&) = delete; 1069 SetStateEffecter(SetStateEffecter&&) = default; 1070 SetStateEffecter& operator=(const SetStateEffecter&) = delete; 1071 SetStateEffecter& operator=(SetStateEffecter&&) = default; 1072 1073 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2) 1074 static constexpr auto maxEffecterDataSize = 16; 1075 1076 // compositeEffecterCount(value: 0x01 to 0x08) 1077 static constexpr auto minEffecterCount = 1; 1078 static constexpr auto maxEffecterCount = 8; 1079 explicit SetStateEffecter(const char* type, const char* name, 1080 CLI::App* app) : 1081 CommandInterface(type, name, app) 1082 { 1083 app->add_option( 1084 "-i, --id", effecterId, 1085 "A handle that is used to identify and access the effecter") 1086 ->required(); 1087 app->add_option("-c, --count", effecterCount, 1088 "The number of individual sets of effecter information") 1089 ->required(); 1090 app->add_option( 1091 "-d,--data", effecterData, 1092 "Set effecter state data\n" 1093 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...") 1094 ->required(); 1095 } 1096 1097 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1098 { 1099 std::vector<uint8_t> requestMsg( 1100 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES); 1101 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1102 1103 if (effecterCount > maxEffecterCount || 1104 effecterCount < minEffecterCount) 1105 { 1106 std::cerr << "Request Message Error: effecterCount size " 1107 << effecterCount << "is invalid\n"; 1108 auto rc = PLDM_ERROR_INVALID_DATA; 1109 return {rc, requestMsg}; 1110 } 1111 1112 if (effecterData.size() > maxEffecterDataSize) 1113 { 1114 std::cerr << "Request Message Error: effecterData size " 1115 << effecterData.size() << "is invalid\n"; 1116 auto rc = PLDM_ERROR_INVALID_DATA; 1117 return {rc, requestMsg}; 1118 } 1119 1120 auto stateField = parseEffecterData(effecterData, effecterCount); 1121 if (!stateField) 1122 { 1123 std::cerr << "Failed to parse effecter data, effecterCount size " 1124 << effecterCount << "\n"; 1125 auto rc = PLDM_ERROR_INVALID_DATA; 1126 return {rc, requestMsg}; 1127 } 1128 1129 auto rc = encode_set_state_effecter_states_req( 1130 instanceId, effecterId, effecterCount, stateField->data(), request); 1131 return {rc, requestMsg}; 1132 } 1133 1134 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1135 { 1136 uint8_t completionCode = 0; 1137 auto rc = decode_set_state_effecter_states_resp( 1138 responsePtr, payloadLength, &completionCode); 1139 1140 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1141 { 1142 std::cerr << "Response Message Error: " 1143 << "rc=" << rc << ",cc=" << (int)completionCode << "\n"; 1144 return; 1145 } 1146 1147 ordered_json data; 1148 data["Response"] = "SUCCESS"; 1149 pldmtool::helper::DisplayInJson(data); 1150 } 1151 1152 private: 1153 uint16_t effecterId; 1154 uint8_t effecterCount; 1155 std::vector<uint8_t> effecterData; 1156 }; 1157 1158 class SetNumericEffecterValue : public CommandInterface 1159 { 1160 public: 1161 ~SetNumericEffecterValue() = default; 1162 SetNumericEffecterValue() = delete; 1163 SetNumericEffecterValue(const SetNumericEffecterValue&) = delete; 1164 SetNumericEffecterValue(SetNumericEffecterValue&&) = default; 1165 SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete; 1166 SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = default; 1167 1168 explicit SetNumericEffecterValue(const char* type, const char* name, 1169 CLI::App* app) : 1170 CommandInterface(type, name, app) 1171 { 1172 app->add_option( 1173 "-i, --id", effecterId, 1174 "A handle that is used to identify and access the effecter") 1175 ->required(); 1176 app->add_option("-s, --size", effecterDataSize, 1177 "The bit width and format of the setting value for the " 1178 "effecter. enum value: {uint8, sint8, uint16, sint16, " 1179 "uint32, sint32}\n") 1180 ->required(); 1181 app->add_option("-d,--data", maxEffecterValue, 1182 "The setting value of numeric effecter being " 1183 "requested\n") 1184 ->required(); 1185 } 1186 1187 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1188 { 1189 std::vector<uint8_t> requestMsg( 1190 sizeof(pldm_msg_hdr) + 1191 PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3); 1192 1193 uint8_t* effecterValue = (uint8_t*)&maxEffecterValue; 1194 1195 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1196 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES; 1197 1198 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 || 1199 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) 1200 { 1201 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1; 1202 } 1203 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 || 1204 effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) 1205 { 1206 payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3; 1207 } 1208 auto rc = encode_set_numeric_effecter_value_req( 1209 0, effecterId, effecterDataSize, effecterValue, request, 1210 payload_length); 1211 1212 return {rc, requestMsg}; 1213 } 1214 1215 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1216 { 1217 uint8_t completionCode = 0; 1218 auto rc = decode_set_numeric_effecter_value_resp( 1219 responsePtr, payloadLength, &completionCode); 1220 1221 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1222 { 1223 std::cerr << "Response Message Error: " 1224 << "rc=" << rc << ",cc=" << (int)completionCode 1225 << std::endl; 1226 return; 1227 } 1228 1229 ordered_json data; 1230 data["Response"] = "SUCCESS"; 1231 pldmtool::helper::DisplayInJson(data); 1232 } 1233 1234 private: 1235 uint16_t effecterId; 1236 uint8_t effecterDataSize; 1237 uint64_t maxEffecterValue; 1238 }; 1239 1240 class GetStateSensorReadings : public CommandInterface 1241 { 1242 public: 1243 ~GetStateSensorReadings() = default; 1244 GetStateSensorReadings() = delete; 1245 GetStateSensorReadings(const GetStateSensorReadings&) = delete; 1246 GetStateSensorReadings(GetStateSensorReadings&&) = default; 1247 GetStateSensorReadings& operator=(const GetStateSensorReadings&) = delete; 1248 GetStateSensorReadings& operator=(GetStateSensorReadings&&) = default; 1249 1250 explicit GetStateSensorReadings(const char* type, const char* name, 1251 CLI::App* app) : 1252 CommandInterface(type, name, app) 1253 { 1254 app->add_option( 1255 "-i, --sensor_id", sensorId, 1256 "Sensor ID that is used to identify and access the sensor") 1257 ->required(); 1258 app->add_option("-r, --rearm", sensorRearm, 1259 "Each bit location in this field corresponds to a " 1260 "particular sensor") 1261 ->required(); 1262 } 1263 1264 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 1265 { 1266 std::vector<uint8_t> requestMsg( 1267 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES); 1268 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 1269 1270 uint8_t reserved = 0; 1271 bitfield8_t bf; 1272 bf.byte = sensorRearm; 1273 auto rc = encode_get_state_sensor_readings_req(instanceId, sensorId, bf, 1274 reserved, request); 1275 1276 return {rc, requestMsg}; 1277 } 1278 1279 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 1280 { 1281 uint8_t completionCode = 0; 1282 uint8_t compSensorCount = 0; 1283 std::array<get_sensor_state_field, 8> stateField{}; 1284 auto rc = decode_get_state_sensor_readings_resp( 1285 responsePtr, payloadLength, &completionCode, &compSensorCount, 1286 stateField.data()); 1287 1288 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 1289 { 1290 std::cerr << "Response Message Error: " 1291 << "rc=" << rc << ",cc=" << (int)completionCode 1292 << std::endl; 1293 return; 1294 } 1295 ordered_json output; 1296 output["compositeSensorCount"] = (int)compSensorCount; 1297 1298 for (size_t i = 0; i < compSensorCount; i++) 1299 { 1300 if (sensorOpState.contains(stateField[i].sensor_op_state)) 1301 { 1302 output.emplace(("sensorOpState[" + std::to_string(i) + "]"), 1303 sensorOpState.at(stateField[i].sensor_op_state)); 1304 } 1305 1306 if (sensorPresState.contains(stateField[i].present_state)) 1307 { 1308 output.emplace(("presentState[" + std::to_string(i) + "]"), 1309 sensorPresState.at(stateField[i].present_state)); 1310 } 1311 1312 if (sensorPresState.contains(stateField[i].previous_state)) 1313 { 1314 output.emplace( 1315 ("previousState[" + std::to_string(i) + "]"), 1316 sensorPresState.at(stateField[i].previous_state)); 1317 } 1318 1319 if (sensorPresState.contains(stateField[i].event_state)) 1320 { 1321 output.emplace(("eventState[" + std::to_string(i) + "]"), 1322 sensorPresState.at(stateField[i].event_state)); 1323 } 1324 } 1325 1326 pldmtool::helper::DisplayInJson(output); 1327 } 1328 1329 private: 1330 uint16_t sensorId; 1331 uint8_t sensorRearm; 1332 }; 1333 1334 void registerCommand(CLI::App& app) 1335 { 1336 auto platform = app.add_subcommand("platform", "platform type command"); 1337 platform->require_subcommand(1); 1338 1339 auto getPDR = platform->add_subcommand("GetPDR", 1340 "get platform descriptor records"); 1341 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR)); 1342 1343 auto setStateEffecterStates = platform->add_subcommand( 1344 "SetStateEffecterStates", "set effecter states"); 1345 commands.push_back(std::make_unique<SetStateEffecter>( 1346 "platform", "setStateEffecterStates", setStateEffecterStates)); 1347 1348 auto setNumericEffecterValue = platform->add_subcommand( 1349 "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter"); 1350 commands.push_back(std::make_unique<SetNumericEffecterValue>( 1351 "platform", "setNumericEffecterValue", setNumericEffecterValue)); 1352 1353 auto getStateSensorReadings = platform->add_subcommand( 1354 "GetStateSensorReadings", "get the state sensor readings"); 1355 commands.push_back(std::make_unique<GetStateSensorReadings>( 1356 "platform", "getStateSensorReadings", getStateSensorReadings)); 1357 } 1358 1359 } // namespace platform 1360 } // namespace pldmtool 1361