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