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