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