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