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 std::vector<std::unique_ptr<CommandInterface>> commands;
18 
19 } // namespace
20 
21 using ordered_json = nlohmann::ordered_json;
22 
23 class GetPDR : public CommandInterface
24 {
25   public:
26     ~GetPDR() = default;
27     GetPDR() = delete;
28     GetPDR(const GetPDR&) = delete;
29     GetPDR(GetPDR&&) = default;
30     GetPDR& operator=(const GetPDR&) = delete;
31     GetPDR& operator=(GetPDR&&) = default;
32 
33     using CommandInterface::CommandInterface;
34 
35     explicit GetPDR(const char* type, const char* name, CLI::App* app) :
36         CommandInterface(type, name, app)
37     {
38         app->add_option(
39                "-d,--data", recordHandle,
40                "retrieve individual PDRs from a PDR Repository\n"
41                "eg: The recordHandle value for the PDR to be retrieved and 0 "
42                "means get first PDR in the repository.")
43             ->required();
44     }
45 
46     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
47     {
48         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
49                                         PLDM_GET_PDR_REQ_BYTES);
50         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
51 
52         auto rc =
53             encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
54                                UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
55         return {rc, requestMsg};
56     }
57 
58     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
59     {
60         uint8_t completionCode = 0;
61         uint8_t recordData[UINT16_MAX] = {0};
62         uint32_t nextRecordHndl = 0;
63         uint32_t nextDataTransferHndl = 0;
64         uint8_t transferFlag = 0;
65         uint16_t respCnt = 0;
66         uint8_t transferCRC = 0;
67 
68         auto rc = decode_get_pdr_resp(
69             responsePtr, payloadLength, &completionCode, &nextRecordHndl,
70             &nextDataTransferHndl, &transferFlag, &respCnt, recordData,
71             sizeof(recordData), &transferCRC);
72 
73         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
74         {
75             std::cerr << "Response Message Error: "
76                       << "rc=" << rc << ",cc=" << (int)completionCode
77                       << std::endl;
78             return;
79         }
80 
81         printPDRMsg(nextRecordHndl, respCnt, recordData);
82     }
83 
84   private:
85     const std::map<pldm::pdr::EntityType, std::string> entityType = {
86         {PLDM_ENTITY_COMM_CHANNEL, "Communication Channel"},
87         {PLDM_ENTITY_SYS_FIRMWARE, "System Firmware"},
88         {PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER, "Virtual Machine Manager"},
89         {PLDM_ENTITY_SYSTEM_CHASSIS, "System chassis (main enclosure)"},
90         {PLDM_ENTITY_SYS_BOARD, "System Board"},
91         {PLDM_ENTITY_MEMORY_MODULE, "Memory Module"},
92         {PLDM_ENTITY_PROC_MODULE, "Processor Module"},
93         {PLDM_ENTITY_CHASSIS_FRONT_PANEL_BOARD,
94          "Chassis front panel board (control panel)"},
95         {PLDM_ENTITY_POWER_CONVERTER, "Power converter"},
96         {PLDM_ENTITY_PROC, "Processor"},
97         {PLDM_ENTITY_MGMT_CONTROLLER, "Management Controller"},
98         {PLDM_ENTITY_CONNECTOR, "Connector"},
99         {PLDM_ENTITY_POWER_SUPPLY, "Power Supply"},
100         {11521, "System (logical)"},
101     };
102 
103     const std::map<uint16_t, std::string> stateSet = {
104         {PLDM_STATE_SET_HEALTH_STATE, "Health State"},
105         {PLDM_STATE_SET_AVAILABILITY, "Availability"},
106         {PLDM_STATE_SET_OPERATIONAL_STATUS, "Operational Status"},
107         {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
108          "Operational Running Status"},
109         {PLDM_STATE_SET_PRESENCE, "Presence"},
110         {PLDM_STATE_SET_CONFIGURATION_STATE, "Configuration State"},
111         {PLDM_STATE_SET_LINK_STATE, "Link State"},
112         {PLDM_STATE_SET_SW_TERMINATION_STATUS, "Software Termination Status"},
113         {PLDM_STATE_SET_BOOT_RESTART_CAUSE, "Boot/Restart Cause"},
114         {PLDM_STATE_SET_BOOT_PROGRESS, "Boot Progress"},
115         {PLDM_STATE_SET_SYSTEM_POWER_STATE, "System Power State"},
116     };
117 
118     const std::array<std::string_view, 4> sensorInit = {
119         "noInit", "useInitPDR", "enableSensor", "disableSensor"};
120 
121     const std::array<std::string_view, 4> effecterInit = {
122         "noInit", "useInitPDR", "enableEffecter", "disableEffecter"};
123 
124     const std::map<uint8_t, std::string> pdrType = {
125         {PLDM_TERMINUS_LOCATOR_PDR, "Terminus Locator PDR"},
126         {PLDM_NUMERIC_SENSOR_PDR, "Numeric Sensor PDR"},
127         {PLDM_NUMERIC_SENSOR_INITIALIZATION_PDR,
128          "Numeric Sensor Initialization PDR"},
129         {PLDM_STATE_SENSOR_PDR, "State Sensor PDR"},
130         {PLDM_STATE_SENSOR_INITIALIZATION_PDR,
131          "State Sensor Initialization PDR"},
132         {PLDM_SENSOR_AUXILIARY_NAMES_PDR, "Sensor Auxiliary Names PDR"},
133         {PLDM_OEM_UNIT_PDR, "OEM Unit PDR"},
134         {PLDM_OEM_STATE_SET_PDR, "OEM State Set PDR"},
135         {PLDM_NUMERIC_EFFECTER_PDR, "Numeric Effecter PDR"},
136         {PLDM_NUMERIC_EFFECTER_INITIALIZATION_PDR,
137          "Numeric Effecter Initialization PDR"},
138         {PLDM_STATE_EFFECTER_PDR, "State Effecter PDR"},
139         {PLDM_STATE_EFFECTER_INITIALIZATION_PDR,
140          "State Effecter Initialization PDR"},
141         {PLDM_EFFECTER_AUXILIARY_NAMES_PDR, "Effecter Auxiliary Names PDR"},
142         {PLDM_EFFECTER_OEM_SEMANTIC_PDR, "Effecter OEM Semantic PDR"},
143         {PLDM_PDR_ENTITY_ASSOCIATION, "Entity Association PDR"},
144         {PLDM_ENTITY_AUXILIARY_NAMES_PDR, "Entity Auxiliary Names PDR"},
145         {PLDM_OEM_ENTITY_ID_PDR, "OEM Entity ID PDR"},
146         {PLDM_INTERRUPT_ASSOCIATION_PDR, "Interrupt Association PDR"},
147         {PLDM_EVENT_LOG_PDR, "PLDM Event Log PDR"},
148         {PLDM_PDR_FRU_RECORD_SET, "FRU Record Set PDR"},
149         {PLDM_OEM_DEVICE_PDR, "OEM Device PDR"},
150         {PLDM_OEM_PDR, "OEM PDR"},
151     };
152 
153     std::string getEntityName(pldm::pdr::EntityType type)
154     {
155         try
156         {
157             return entityType.at(type);
158         }
159         catch (const std::out_of_range& e)
160         {
161             return std::to_string(static_cast<unsigned>(type)) + "(OEM)";
162         }
163     }
164 
165     std::string getStateSetName(uint16_t id)
166     {
167         auto typeString = std::to_string(id);
168         try
169         {
170             return stateSet.at(id) + "(" + typeString + ")";
171         }
172         catch (const std::out_of_range& e)
173         {
174             return typeString;
175         }
176     }
177 
178     std::string getPDRType(uint8_t type)
179     {
180         auto typeString = std::to_string(type);
181         try
182         {
183             return pdrType.at(type);
184         }
185         catch (const std::out_of_range& e)
186         {
187             return typeString;
188         }
189     }
190 
191     void printCommonPDRHeader(const pldm_pdr_hdr* hdr, ordered_json& output)
192     {
193         output["recordHandle"] = hdr->record_handle;
194         output["PDRHeaderVersion"] = unsigned(hdr->version);
195         output["PDRType"] = getPDRType(hdr->type);
196         output["recordChangeNumber"] = hdr->record_change_num;
197         output["dataLength"] = hdr->length;
198     }
199 
200     std::string printPossibleStates(uint8_t possibleStatesSize,
201                                     const bitfield8_t* states)
202     {
203         uint8_t possibleStatesPos{};
204         std::string data;
205         auto printStates = [&possibleStatesPos, &data](const bitfield8_t& val) {
206             std::stringstream pstates;
207             for (int i = 0; i < CHAR_BIT; i++)
208             {
209                 if (val.byte & (1 << i))
210                 {
211                     pstates << " " << (possibleStatesPos * CHAR_BIT + i);
212                     data.append(pstates.str());
213                     pstates.str("");
214                 }
215             }
216             possibleStatesPos++;
217         };
218         std::for_each(states, states + possibleStatesSize, printStates);
219         return data;
220     }
221 
222     void printStateSensorPDR(const uint8_t* data, ordered_json& output)
223     {
224         auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(data);
225         output["PLDMTerminusHandle"] = pdr->terminus_handle;
226         output["sensorID"] = pdr->sensor_id;
227         output["entityType"] = getEntityName(pdr->entity_type);
228         output["entityInstanceNumber"] = pdr->entity_instance;
229         output["containerID"] = pdr->container_id;
230         output["sensorInit"] = sensorInit[pdr->sensor_init];
231         output["sensorAuxiliaryNamesPDR"] =
232             (pdr->sensor_auxiliary_names_pdr ? true : false);
233         output["compositeSensorCount"] = unsigned(pdr->composite_sensor_count);
234 
235         auto statesPtr = pdr->possible_states;
236         auto compCount = pdr->composite_sensor_count;
237 
238         while (compCount--)
239         {
240             auto state = reinterpret_cast<const state_sensor_possible_states*>(
241                 statesPtr);
242             output.emplace(("stateSetID[" + std::to_string(compCount) + "]"),
243                            getStateSetName(state->state_set_id));
244             output.emplace(
245                 ("possibleStatesSize[" + std::to_string(compCount) + "]"),
246                 state->possible_states_size);
247             output.emplace(
248                 ("possibleStates[" + std::to_string(compCount) + "]"),
249                 printPossibleStates(state->possible_states_size,
250                                     state->states));
251 
252             if (compCount)
253             {
254                 statesPtr += sizeof(state_sensor_possible_states) +
255                              state->possible_states_size - 1;
256             }
257         }
258     }
259 
260     void printPDRFruRecordSet(uint8_t* data, ordered_json& output)
261     {
262         if (data == NULL)
263         {
264             return;
265         }
266 
267         data += sizeof(pldm_pdr_hdr);
268         pldm_pdr_fru_record_set* pdr =
269             reinterpret_cast<pldm_pdr_fru_record_set*>(data);
270 
271         output["PLDMTerminusHandle"] = unsigned(pdr->terminus_handle);
272         output["FRURecordSetIdentifier"] = unsigned(pdr->fru_rsi);
273         output["entityType"] = getEntityName(pdr->entity_type);
274         output["entityInstanceNumber"] = unsigned(pdr->entity_instance_num);
275         output["containerID"] = unsigned(pdr->container_id);
276     }
277 
278     void printPDREntityAssociation(uint8_t* data, ordered_json& output)
279     {
280         const std::map<uint8_t, const char*> assocationType = {
281             {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"},
282             {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"},
283         };
284 
285         if (data == NULL)
286         {
287             return;
288         }
289 
290         data += sizeof(pldm_pdr_hdr);
291         pldm_pdr_entity_association* pdr =
292             reinterpret_cast<pldm_pdr_entity_association*>(data);
293 
294         output["containerID"] = int(pdr->container_id);
295         output["associationType"] = assocationType.at(pdr->association_type);
296         output["containerEntityType"] =
297             getEntityName(pdr->container.entity_type);
298         output["containerEntityInstanceNumber"] =
299             int(pdr->container.entity_instance_num);
300         output["containerEntityContainerID"] =
301             int(pdr->container.entity_container_id);
302         output["containedEntityCount"] =
303             static_cast<unsigned>(pdr->num_children);
304 
305         auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]);
306         for (int i = 0; i < pdr->num_children; ++i)
307         {
308             output.emplace("containedEntityType[" + std::to_string(i + 1) + "]",
309                            getEntityName(child->entity_type));
310             output.emplace("containedEntityInstanceNumber[" +
311                                std::to_string(i + 1) + "]",
312                            unsigned(child->entity_instance_num));
313             output.emplace("containedEntityContainerID[" +
314                                std::to_string(i + 1) + "]",
315                            unsigned(child->entity_container_id));
316 
317             ++child;
318         }
319     }
320 
321     void printNumericEffecterPDR(uint8_t* data, ordered_json& output)
322     {
323         struct pldm_numeric_effecter_value_pdr* pdr =
324             (struct pldm_numeric_effecter_value_pdr*)data;
325 
326         output["PLDMTerminusHandle"] = int(pdr->terminus_handle);
327         output["effecterID"] = int(pdr->effecter_id);
328         output["entityType"] = int(pdr->entity_type);
329         output["entityInstanceNumber"] = int(pdr->entity_instance);
330         output["containerID"] = int(pdr->container_id);
331         output["effecterSemanticID"] = int(pdr->effecter_semantic_id);
332         output["effecterInit"] = unsigned(pdr->effecter_init);
333         output["effecterAuxiliaryNames"] =
334             (unsigned(pdr->effecter_auxiliary_names) ? true : false);
335         output["baseUnit"] = unsigned(pdr->base_unit);
336         output["unitModifier"] = unsigned(pdr->unit_modifier);
337         output["rateUnit"] = unsigned(pdr->rate_unit);
338         output["baseOEMUnitHandle"] = unsigned(pdr->base_oem_unit_handle);
339         output["auxUnit"] = unsigned(pdr->aux_unit);
340         output["auxUnitModifier"] = unsigned(pdr->aux_unit_modifier);
341         output["auxrateUnit"] = unsigned(pdr->aux_rate_unit);
342         output["auxOEMUnitHandle"] = unsigned(pdr->aux_oem_unit_handle);
343         output["isLinear"] = (unsigned(pdr->is_linear) ? true : false);
344         output["effecterDataSize"] = unsigned(pdr->effecter_data_size);
345         output["resolution"] = unsigned(pdr->resolution);
346         output["offset"] = unsigned(pdr->offset);
347         output["accuracy"] = unsigned(pdr->accuracy);
348         output["plusTolerance"] = unsigned(pdr->plus_tolerance);
349         output["minusTolerance"] = unsigned(pdr->minus_tolerance);
350         output["stateTransitionInterval"] =
351             unsigned(pdr->state_transition_interval);
352         output["TransitionInterval"] = unsigned(pdr->transition_interval);
353 
354         switch (pdr->effecter_data_size)
355         {
356             case PLDM_EFFECTER_DATA_SIZE_UINT8:
357                 output["maxSettable"] = unsigned(pdr->max_set_table.value_u8);
358                 output["minSettable"] = unsigned(pdr->min_set_table.value_u8);
359                 break;
360             case PLDM_EFFECTER_DATA_SIZE_SINT8:
361                 output["maxSettable"] = unsigned(pdr->max_set_table.value_s8);
362                 output["minSettable"] = unsigned(pdr->min_set_table.value_s8);
363                 break;
364             case PLDM_EFFECTER_DATA_SIZE_UINT16:
365                 output["maxSettable"] = unsigned(pdr->max_set_table.value_u16);
366                 output["minSettable"] = unsigned(pdr->min_set_table.value_u16);
367                 break;
368             case PLDM_EFFECTER_DATA_SIZE_SINT16:
369                 output["maxSettable"] = unsigned(pdr->max_set_table.value_s16);
370                 output["minSettable"] = unsigned(pdr->min_set_table.value_s16);
371                 break;
372             case PLDM_EFFECTER_DATA_SIZE_UINT32:
373                 output["maxSettable"] = unsigned(pdr->max_set_table.value_u32);
374                 output["minSettable"] = unsigned(pdr->min_set_table.value_u32);
375                 break;
376             case PLDM_EFFECTER_DATA_SIZE_SINT32:
377                 output["maxSettable"] = unsigned(pdr->max_set_table.value_s32);
378                 output["minSettable"] = unsigned(pdr->min_set_table.value_s32);
379                 break;
380             default:
381                 break;
382         }
383 
384         output["rangeFieldFormat"] = unsigned(pdr->range_field_format);
385         output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte);
386 
387         switch (pdr->range_field_format)
388         {
389             case PLDM_RANGE_FIELD_FORMAT_UINT8:
390                 output["nominalValue"] = unsigned(pdr->nominal_value.value_u8);
391                 output["normalMax"] = unsigned(pdr->normal_max.value_u8);
392                 output["normalMin"] = unsigned(pdr->normal_min.value_u8);
393                 output["ratedMax"] = unsigned(pdr->rated_max.value_u8);
394                 output["ratedMin"] = unsigned(pdr->rated_min.value_u8);
395                 break;
396             case PLDM_RANGE_FIELD_FORMAT_SINT8:
397                 output["nominalValue"] = unsigned(pdr->nominal_value.value_s8);
398                 output["normalMax"] = unsigned(pdr->normal_max.value_s8);
399                 output["normalMin"] = unsigned(pdr->normal_min.value_s8);
400                 output["ratedMax"] = unsigned(pdr->rated_max.value_s8);
401                 output["ratedMin"] = unsigned(pdr->rated_min.value_s8);
402                 break;
403             case PLDM_RANGE_FIELD_FORMAT_UINT16:
404                 output["nominalValue"] = unsigned(pdr->nominal_value.value_u16);
405                 output["normalMax"] = unsigned(pdr->normal_max.value_u16);
406                 output["normalMin"] = unsigned(pdr->normal_min.value_u16);
407                 output["ratedMax"] = unsigned(pdr->rated_max.value_u16);
408                 output["ratedMin"] = unsigned(pdr->rated_min.value_u16);
409                 break;
410             case PLDM_RANGE_FIELD_FORMAT_SINT16:
411                 output["nominalValue"] = unsigned(pdr->nominal_value.value_s16);
412                 output["normalMax"] = unsigned(pdr->normal_max.value_s16);
413                 output["normalMin"] = unsigned(pdr->normal_min.value_s16);
414                 output["ratedMax"] = unsigned(pdr->rated_max.value_s16);
415                 output["ratedMin"] = unsigned(pdr->rated_min.value_s16);
416                 break;
417             case PLDM_RANGE_FIELD_FORMAT_UINT32:
418                 output["nominalValue"] = unsigned(pdr->nominal_value.value_u32);
419                 output["normalMax"] = unsigned(pdr->normal_max.value_u32);
420                 output["normalMin"] = unsigned(pdr->normal_min.value_u32);
421                 output["ratedMax"] = unsigned(pdr->rated_max.value_u32);
422                 output["ratedMin"] = unsigned(pdr->rated_min.value_u32);
423                 break;
424             case PLDM_RANGE_FIELD_FORMAT_SINT32:
425                 output["nominalValue"] = unsigned(pdr->nominal_value.value_s32);
426                 output["normalMax"] = unsigned(pdr->normal_max.value_s32);
427                 output["normalMin"] = unsigned(pdr->normal_min.value_s32);
428                 output["ratedMax"] = unsigned(pdr->rated_max.value_s32);
429                 output["ratedMin"] = unsigned(pdr->rated_min.value_s32);
430                 break;
431             case PLDM_RANGE_FIELD_FORMAT_REAL32:
432                 output["nominalValue"] = unsigned(pdr->nominal_value.value_f32);
433                 output["normalMax"] = unsigned(pdr->normal_max.value_f32);
434                 output["normalMin"] = unsigned(pdr->normal_min.value_f32);
435                 output["ratedMax"] = unsigned(pdr->rated_max.value_f32);
436                 output["ratedMin"] = unsigned(pdr->rated_min.value_f32);
437                 break;
438             default:
439                 break;
440         }
441     }
442 
443     void printStateEffecterPDR(const uint8_t* data, ordered_json& output)
444     {
445         auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(data);
446 
447         output["PLDMTerminusHandle"] = pdr->terminus_handle;
448         output["effecterID"] = pdr->effecter_id;
449         output["entityType"] = getEntityName(pdr->entity_type);
450         output["entityInstanceNumber"] = pdr->entity_instance;
451         output["containerID"] = pdr->container_id;
452         output["effecterSemanticID"] = pdr->effecter_semantic_id;
453         output["effecterInit"] = effecterInit[pdr->effecter_init];
454         output["effecterDescriptionPDR"] =
455             (pdr->has_description_pdr ? true : false);
456         output["compositeEffecterCount"] =
457             unsigned(pdr->composite_effecter_count);
458 
459         auto statesPtr = pdr->possible_states;
460         auto compEffCount = pdr->composite_effecter_count;
461 
462         while (compEffCount--)
463         {
464             auto state =
465                 reinterpret_cast<const state_effecter_possible_states*>(
466                     statesPtr);
467             output.emplace(("stateSetID[" + std::to_string(compEffCount) + "]"),
468                            getStateSetName(state->state_set_id));
469             output.emplace(
470                 ("possibleStatesSize[" + std::to_string(compEffCount) + "]"),
471                 state->possible_states_size);
472             output.emplace(
473                 ("possibleStates[" + std::to_string(compEffCount) + "]"),
474                 printPossibleStates(state->possible_states_size,
475                                     state->states));
476 
477             if (compEffCount)
478             {
479                 statesPtr += sizeof(state_effecter_possible_states) +
480                              state->possible_states_size - 1;
481             }
482         }
483     }
484 
485     void printTerminusLocatorPDR(const uint8_t* data, ordered_json& output)
486     {
487         const std::array<std::string_view, 4> terminusLocatorType = {
488             "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"};
489 
490         auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data);
491 
492         output["PLDMTerminusHandle"] = pdr->terminus_handle;
493         output["validity"] = (pdr->validity ? "valid" : "notValid");
494         output["TID"] = unsigned(pdr->tid);
495         output["containerID"] = pdr->container_id;
496         output["terminusLocatorType"] =
497             terminusLocatorType[pdr->terminus_locator_type];
498         output["terminusLocatorValueSize"] =
499             unsigned(pdr->terminus_locator_value_size);
500 
501         if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
502         {
503             auto locatorValue =
504                 reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
505                     pdr->terminus_locator_value);
506             output["EID"] = unsigned(locatorValue->eid);
507         }
508     }
509 
510     void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
511                      uint8_t* data)
512     {
513         if (data == NULL)
514         {
515             return;
516         }
517 
518         ordered_json output;
519         output["nextRecordHandle"] = nextRecordHndl;
520         output["responseCount"] = respCnt;
521 
522         struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data;
523         printCommonPDRHeader(pdr, output);
524 
525         switch (pdr->type)
526         {
527             case PLDM_TERMINUS_LOCATOR_PDR:
528                 printTerminusLocatorPDR(data, output);
529                 break;
530             case PLDM_STATE_SENSOR_PDR:
531                 printStateSensorPDR(data, output);
532                 break;
533             case PLDM_NUMERIC_EFFECTER_PDR:
534                 printNumericEffecterPDR(data, output);
535                 break;
536             case PLDM_STATE_EFFECTER_PDR:
537                 printStateEffecterPDR(data, output);
538                 break;
539             case PLDM_PDR_ENTITY_ASSOCIATION:
540                 printPDREntityAssociation(data, output);
541                 break;
542             case PLDM_PDR_FRU_RECORD_SET:
543                 printPDRFruRecordSet(data, output);
544                 break;
545             default:
546                 break;
547         }
548         pldmtool::helper::DisplayInJson(output);
549     }
550 
551   private:
552     uint32_t recordHandle;
553 };
554 
555 class SetStateEffecter : public CommandInterface
556 {
557   public:
558     ~SetStateEffecter() = default;
559     SetStateEffecter() = delete;
560     SetStateEffecter(const SetStateEffecter&) = delete;
561     SetStateEffecter(SetStateEffecter&&) = default;
562     SetStateEffecter& operator=(const SetStateEffecter&) = delete;
563     SetStateEffecter& operator=(SetStateEffecter&&) = default;
564 
565     // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2)
566     static constexpr auto maxEffecterDataSize = 16;
567 
568     // compositeEffecterCount(value: 0x01 to 0x08)
569     static constexpr auto minEffecterCount = 1;
570     static constexpr auto maxEffecterCount = 8;
571     explicit SetStateEffecter(const char* type, const char* name,
572                               CLI::App* app) :
573         CommandInterface(type, name, app)
574     {
575         app->add_option(
576                "-i, --id", effecterId,
577                "A handle that is used to identify and access the effecter")
578             ->required();
579         app->add_option("-c, --count", effecterCount,
580                         "The number of individual sets of effecter information")
581             ->required();
582         app->add_option(
583                "-d,--data", effecterData,
584                "Set effecter state data\n"
585                "eg: requestSet0 effecterState0 noChange1 dummyState1 ...")
586             ->required();
587     }
588 
589     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
590     {
591         std::vector<uint8_t> requestMsg(
592             sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES);
593         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
594 
595         if (effecterCount > maxEffecterCount ||
596             effecterCount < minEffecterCount)
597         {
598             std::cerr << "Request Message Error: effecterCount size "
599                       << effecterCount << "is invalid\n";
600             auto rc = PLDM_ERROR_INVALID_DATA;
601             return {rc, requestMsg};
602         }
603 
604         if (effecterData.size() > maxEffecterDataSize)
605         {
606             std::cerr << "Request Message Error: effecterData size "
607                       << effecterData.size() << "is invalid\n";
608             auto rc = PLDM_ERROR_INVALID_DATA;
609             return {rc, requestMsg};
610         }
611 
612         auto stateField = parseEffecterData(effecterData, effecterCount);
613         if (!stateField)
614         {
615             std::cerr << "Failed to parse effecter data, effecterCount size "
616                       << effecterCount << "\n";
617             auto rc = PLDM_ERROR_INVALID_DATA;
618             return {rc, requestMsg};
619         }
620 
621         auto rc = encode_set_state_effecter_states_req(
622             instanceId, effecterId, effecterCount, stateField->data(), request);
623         return {rc, requestMsg};
624     }
625 
626     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
627     {
628         uint8_t completionCode = 0;
629         auto rc = decode_set_state_effecter_states_resp(
630             responsePtr, payloadLength, &completionCode);
631 
632         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
633         {
634             std::cerr << "Response Message Error: "
635                       << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
636             return;
637         }
638 
639         ordered_json data;
640         data["Response"] = "SUCCESS";
641         pldmtool::helper::DisplayInJson(data);
642     }
643 
644   private:
645     uint16_t effecterId;
646     uint8_t effecterCount;
647     std::vector<uint8_t> effecterData;
648 };
649 
650 class SetNumericEffecterValue : public CommandInterface
651 {
652   public:
653     ~SetNumericEffecterValue() = default;
654     SetNumericEffecterValue() = delete;
655     SetNumericEffecterValue(const SetNumericEffecterValue&) = delete;
656     SetNumericEffecterValue(SetNumericEffecterValue&&) = default;
657     SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete;
658     SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = default;
659 
660     explicit SetNumericEffecterValue(const char* type, const char* name,
661                                      CLI::App* app) :
662         CommandInterface(type, name, app)
663     {
664         app->add_option(
665                "-i, --id", effecterId,
666                "A handle that is used to identify and access the effecter")
667             ->required();
668         app->add_option("-s, --size", effecterDataSize,
669                         "The bit width and format of the setting value for the "
670                         "effecter. enum value: {uint8, sint8, uint16, sint16, "
671                         "uint32, sint32}\n")
672             ->required();
673         app->add_option("-d,--data", maxEffecterValue,
674                         "The setting value of numeric effecter being "
675                         "requested\n")
676             ->required();
677     }
678 
679     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
680     {
681         std::vector<uint8_t> requestMsg(
682             sizeof(pldm_msg_hdr) +
683             PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3);
684 
685         uint8_t* effecterValue = (uint8_t*)&maxEffecterValue;
686 
687         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
688         size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES;
689 
690         if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
691             effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
692         {
693             payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1;
694         }
695         if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
696             effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
697         {
698             payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3;
699         }
700         auto rc = encode_set_numeric_effecter_value_req(
701             0, effecterId, effecterDataSize, effecterValue, request,
702             payload_length);
703 
704         return {rc, requestMsg};
705     }
706 
707     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
708     {
709         uint8_t completionCode = 0;
710         auto rc = decode_set_numeric_effecter_value_resp(
711             responsePtr, payloadLength, &completionCode);
712 
713         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
714         {
715             std::cerr << "Response Message Error: "
716                       << "rc=" << rc << ",cc=" << (int)completionCode
717                       << std::endl;
718             return;
719         }
720 
721         ordered_json data;
722         data["Response"] = "SUCCESS";
723         pldmtool::helper::DisplayInJson(data);
724     }
725 
726   private:
727     uint16_t effecterId;
728     uint8_t effecterDataSize;
729     uint64_t maxEffecterValue;
730 };
731 
732 void registerCommand(CLI::App& app)
733 {
734     auto platform = app.add_subcommand("platform", "platform type command");
735     platform->require_subcommand(1);
736 
737     auto getPDR =
738         platform->add_subcommand("GetPDR", "get platform descriptor records");
739     commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR));
740 
741     auto setStateEffecterStates = platform->add_subcommand(
742         "SetStateEffecterStates", "set effecter states");
743     commands.push_back(std::make_unique<SetStateEffecter>(
744         "platform", "setStateEffecterStates", setStateEffecterStates));
745 
746     auto setNumericEffecterValue = platform->add_subcommand(
747         "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter");
748     commands.push_back(std::make_unique<SetNumericEffecterValue>(
749         "platform", "setNumericEffecterValue", setNumericEffecterValue));
750 }
751 
752 } // namespace platform
753 } // namespace pldmtool
754