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