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