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