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