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