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