1 #include "pldm_cmd_helper.hpp"
2 
3 namespace pldmtool
4 {
5 
6 namespace platform
7 {
8 
9 namespace
10 {
11 
12 using namespace pldmtool::helper;
13 std::vector<std::unique_ptr<CommandInterface>> commands;
14 
15 } // namespace
16 
17 class GetPDR : public CommandInterface
18 {
19   public:
20     ~GetPDR() = default;
21     GetPDR() = delete;
22     GetPDR(const GetPDR&) = delete;
23     GetPDR(GetPDR&&) = default;
24     GetPDR& operator=(const GetPDR&) = delete;
25     GetPDR& operator=(GetPDR&&) = default;
26 
27     using CommandInterface::CommandInterface;
28 
29     // The maximum number of record bytes requested to be returned in the
30     // response to this instance of the GetPDR command.
31     static constexpr uint16_t requestCount = 128;
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 = encode_get_pdr_req(instanceId, recordHandle, 0,
51                                      PLDM_GET_FIRSTPART, requestCount, 0,
52                                      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[65535] = {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<uint16_t, std::string> entityType = {
84         {64, "System Board"},
85         {66, "Memory Module"},
86         {67, "Processor Module"},
87         {137, "Management Controller"},
88         {69, "Chassis front panel board (control panel)"},
89         {123, "Power converter"},
90         {45, "System chassis (main enclosure)"},
91         {11521, "System (logical)"},
92     };
93 
94     std::string getEntityName(uint16_t type)
95     {
96         try
97         {
98             return entityType.at(type);
99         }
100         catch (const std::out_of_range& e)
101         {
102             return std::to_string(static_cast<unsigned>(type)) + "(OEM)";
103         }
104     }
105 
106     void printPDRFruRecordSet(uint8_t* data)
107     {
108         if (data == NULL)
109         {
110             return;
111         }
112 
113         data += sizeof(pldm_pdr_hdr);
114         pldm_pdr_fru_record_set* pdr =
115             reinterpret_cast<pldm_pdr_fru_record_set*>(data);
116 
117         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
118                   << std::endl;
119         std::cout << "FRURecordSetIdentifier: " << pdr->fru_rsi << std::endl;
120         std::cout << "entityType: " << getEntityName(pdr->entity_type)
121                   << std::endl;
122         std::cout << "entityInstanceNumber: " << pdr->entity_instance_num
123                   << std::endl;
124         std::cout << "containerID: " << pdr->container_id << std::endl;
125     }
126 
127     void printPDREntityAssociation(uint8_t* data)
128     {
129         const std::map<uint8_t, const char*> assocationType = {
130             {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"},
131             {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"},
132         };
133 
134         if (data == NULL)
135         {
136             return;
137         }
138 
139         data += sizeof(pldm_pdr_hdr);
140         pldm_pdr_entity_association* pdr =
141             reinterpret_cast<pldm_pdr_entity_association*>(data);
142 
143         std::cout << "containerID: " << pdr->container_id << std::endl;
144         std::cout << "associationType: "
145                   << assocationType.at(pdr->association_type) << std::endl
146                   << std::endl;
147 
148         std::cout << "containerEntityType: "
149                   << getEntityName(pdr->container.entity_type) << std::endl;
150         std::cout << "containerEntityInstanceNumber: "
151                   << pdr->container.entity_instance_num << std::endl;
152         std::cout << "containerEntityContainerID: "
153                   << pdr->container.entity_container_id << std::endl;
154 
155         std::cout << "containedEntityCount: "
156                   << static_cast<unsigned>(pdr->num_children) << std::endl
157                   << std::endl;
158 
159         auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]);
160         for (int i = 0; i < pdr->num_children; ++i)
161         {
162             std::cout << "containedEntityType[" << i + 1
163                       << "]: " << getEntityName(child->entity_type)
164                       << std::endl;
165             std::cout << "containedEntityInstanceNumber[" << i + 1
166                       << "]: " << child->entity_instance_num << std::endl;
167             std::cout << "containedEntityContainerID[" << i + 1
168                       << "]: " << child->entity_container_id << std::endl
169                       << std::endl;
170             ++child;
171         }
172     }
173 
174     void printEffecterHdrPDR(pldm_pdr_hdr* hdr)
175     {
176         std::cout << "recordHandle: " << hdr->record_handle << std::endl;
177         std::cout << "PDRHeaderVersion: " << unsigned(hdr->version)
178                   << std::endl;
179         std::cout << "PDRType: " << unsigned(hdr->type) << std::endl;
180         std::cout << "recordChangeNumber: " << hdr->record_change_num
181                   << std::endl;
182         std::cout << "dataLength: " << hdr->length << std::endl;
183     }
184 
185     void printNumericEffecterPDR(uint8_t* data)
186     {
187         struct pldm_numeric_effecter_value_pdr* pdr =
188             (struct pldm_numeric_effecter_value_pdr*)data;
189         printEffecterHdrPDR(&pdr->hdr);
190         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
191                   << std::endl;
192         std::cout << "effecterID: " << pdr->effecter_id << std::endl;
193         std::cout << "entityType: " << pdr->entity_type << std::endl;
194         std::cout << "entityInstanceNumber: " << pdr->entity_instance
195                   << std::endl;
196         std::cout << "containerID: " << pdr->container_id << std::endl;
197         std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
198                   << std::endl;
199         std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
200                   << std::endl;
201         std::cout << "effecterAuxiliaryNames: "
202                   << (unsigned(pdr->effecter_auxiliary_names) ? "true"
203                                                               : "false")
204                   << std::endl;
205         std::cout << "baseUnit: " << unsigned(pdr->base_unit) << std::endl;
206         std::cout << "unitModifier: " << unsigned(pdr->unit_modifier)
207                   << std::endl;
208         std::cout << "rateUnit: " << unsigned(pdr->rate_unit) << std::endl;
209         std::cout << "baseOEMUnitHandle: "
210                   << unsigned(pdr->base_oem_unit_handle) << std::endl;
211         std::cout << "auxUnit: " << unsigned(pdr->aux_unit) << std::endl;
212         std::cout << "auxUnitModifier: " << unsigned(pdr->aux_unit_modifier)
213                   << std::endl;
214         std::cout << "auxrateUnit: " << unsigned(pdr->aux_rate_unit)
215                   << std::endl;
216         std::cout << "auxOEMUnitHandle: " << unsigned(pdr->aux_oem_unit_handle)
217                   << std::endl;
218         std::cout << "isLinear: "
219                   << (unsigned(pdr->is_linear) ? "true" : "false") << std::endl;
220         std::cout << "effecterDataSize: " << unsigned(pdr->effecter_data_size)
221                   << std::endl;
222         std::cout << "resolution: " << pdr->resolution << std::endl;
223         std::cout << "offset: " << pdr->offset << std::endl;
224         std::cout << "accuracy: " << pdr->accuracy << std::endl;
225         std::cout << "plusTolerance: " << unsigned(pdr->plus_tolerance)
226                   << std::endl;
227         std::cout << "minusTolerance: " << unsigned(pdr->minus_tolerance)
228                   << std::endl;
229         std::cout << "stateTransitionInterval: "
230                   << pdr->state_transition_interval << std::endl;
231         std::cout << "TransitionInterval: " << pdr->transition_interval
232                   << std::endl;
233         switch (pdr->effecter_data_size)
234         {
235             case PLDM_EFFECTER_DATA_SIZE_UINT8:
236                 std::cout << "maxSettable: "
237                           << unsigned(pdr->max_set_table.value_u8) << std::endl;
238                 std::cout << "minSettable: "
239                           << unsigned(pdr->min_set_table.value_u8) << std::endl;
240                 break;
241             case PLDM_EFFECTER_DATA_SIZE_SINT8:
242                 std::cout << "maxSettable: "
243                           << unsigned(pdr->max_set_table.value_s8) << std::endl;
244                 std::cout << "minSettable: "
245                           << unsigned(pdr->min_set_table.value_s8) << std::endl;
246                 break;
247             case PLDM_EFFECTER_DATA_SIZE_UINT16:
248                 std::cout << "maxSettable: " << pdr->max_set_table.value_u16
249                           << std::endl;
250                 std::cout << "minSettable: " << pdr->min_set_table.value_u16
251                           << std::endl;
252                 break;
253             case PLDM_EFFECTER_DATA_SIZE_SINT16:
254                 std::cout << "maxSettable: " << pdr->max_set_table.value_s16
255                           << std::endl;
256                 std::cout << "minSettable: " << pdr->min_set_table.value_s16
257                           << std::endl;
258                 break;
259             case PLDM_EFFECTER_DATA_SIZE_UINT32:
260                 std::cout << "maxSettable: " << pdr->max_set_table.value_u32
261                           << std::endl;
262                 std::cout << "minSettable: " << pdr->min_set_table.value_u32
263                           << std::endl;
264                 break;
265             case PLDM_EFFECTER_DATA_SIZE_SINT32:
266                 std::cout << "maxSettable: " << pdr->max_set_table.value_s32
267                           << std::endl;
268                 std::cout << "minSettable: " << pdr->min_set_table.value_s32
269                           << std::endl;
270                 break;
271             default:
272                 break;
273         }
274         std::cout << "rangeFieldFormat: " << unsigned(pdr->range_field_format)
275                   << std::endl;
276         std::cout << "rangeFieldSupport: "
277                   << unsigned(pdr->range_field_support.byte) << std::endl;
278         switch (pdr->range_field_format)
279         {
280             case PLDM_RANGE_FIELD_FORMAT_UINT8:
281                 std::cout << "nominalValue: "
282                           << unsigned(pdr->nominal_value.value_u8) << std::endl;
283                 std::cout << "normalMax: " << unsigned(pdr->normal_max.value_u8)
284                           << std::endl;
285                 std::cout << "normalMin: " << unsigned(pdr->normal_min.value_u8)
286                           << std::endl;
287                 std::cout << "ratedMax: " << unsigned(pdr->rated_max.value_u8)
288                           << std::endl;
289                 std::cout << "ratedMin: " << unsigned(pdr->rated_min.value_u8)
290                           << std::endl;
291                 break;
292             case PLDM_RANGE_FIELD_FORMAT_SINT8:
293                 std::cout << "nominalValue: "
294                           << unsigned(pdr->nominal_value.value_s8) << std::endl;
295                 std::cout << "normalMax: " << unsigned(pdr->normal_max.value_s8)
296                           << std::endl;
297                 std::cout << "normalMin: " << unsigned(pdr->normal_min.value_s8)
298                           << std::endl;
299                 std::cout << "ratedMax: " << unsigned(pdr->rated_max.value_s8)
300                           << std::endl;
301                 std::cout << "ratedMin: " << unsigned(pdr->rated_min.value_s8)
302                           << std::endl;
303                 break;
304             case PLDM_RANGE_FIELD_FORMAT_UINT16:
305                 std::cout << "nominalValue: " << pdr->nominal_value.value_u16
306                           << std::endl;
307                 std::cout << "normalMax: " << pdr->normal_max.value_u16
308                           << std::endl;
309                 std::cout << "normalMin: " << pdr->normal_min.value_u16
310                           << std::endl;
311                 std::cout << "ratedMax: " << pdr->rated_max.value_u16
312                           << std::endl;
313                 std::cout << "ratedMin: " << pdr->rated_min.value_u16
314                           << std::endl;
315                 break;
316             case PLDM_RANGE_FIELD_FORMAT_SINT16:
317                 std::cout << "nominalValue: " << pdr->nominal_value.value_s16
318                           << std::endl;
319                 std::cout << "normalMax: " << pdr->normal_max.value_s16
320                           << std::endl;
321                 std::cout << "normalMin: " << pdr->normal_min.value_s16
322                           << std::endl;
323                 std::cout << "ratedMax: " << pdr->rated_max.value_s16
324                           << std::endl;
325                 std::cout << "ratedMin: " << pdr->rated_min.value_s16
326                           << std::endl;
327                 break;
328             case PLDM_RANGE_FIELD_FORMAT_UINT32:
329                 std::cout << "nominalValue: " << pdr->nominal_value.value_u32
330                           << std::endl;
331                 std::cout << "normalMax: " << pdr->normal_max.value_u32
332                           << std::endl;
333                 std::cout << "normalMin: " << pdr->normal_min.value_u32
334                           << std::endl;
335                 std::cout << "ratedMax: " << pdr->rated_max.value_u32
336                           << std::endl;
337                 std::cout << "ratedMin: " << pdr->rated_min.value_u32
338                           << std::endl;
339                 break;
340             case PLDM_RANGE_FIELD_FORMAT_SINT32:
341                 std::cout << "nominalValue: " << pdr->nominal_value.value_s32
342                           << std::endl;
343                 std::cout << "normalMax: " << pdr->normal_max.value_s32
344                           << std::endl;
345                 std::cout << "normalMin: " << pdr->normal_min.value_s32
346                           << std::endl;
347                 std::cout << "ratedMax: " << pdr->rated_max.value_s32
348                           << std::endl;
349                 std::cout << "ratedMin: " << pdr->rated_min.value_s32
350                           << std::endl;
351                 break;
352             case PLDM_RANGE_FIELD_FORMAT_REAL32:
353                 std::cout << "nominalValue: " << pdr->nominal_value.value_f32
354                           << std::endl;
355                 std::cout << "normalMax: " << pdr->normal_max.value_f32
356                           << std::endl;
357                 std::cout << "normalMin: " << pdr->normal_min.value_f32
358                           << std::endl;
359                 std::cout << "ratedMax: " << pdr->rated_max.value_f32
360                           << std::endl;
361                 std::cout << "ratedMin: " << pdr->rated_min.value_f32
362                           << std::endl;
363                 break;
364             default:
365                 break;
366         }
367     }
368 
369     void printStateEffecterPDR(uint8_t* data)
370     {
371         if (data == NULL)
372         {
373             return;
374         }
375 
376         struct pldm_state_effecter_pdr* pdr =
377             (struct pldm_state_effecter_pdr*)data;
378         printEffecterHdrPDR(&pdr->hdr);
379 
380         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
381                   << std::endl;
382         std::cout << "effecterID: " << pdr->effecter_id << std::endl;
383         std::cout << "entityType: " << pdr->entity_type << std::endl;
384         std::cout << "entityInstanceNumber: " << pdr->entity_instance
385                   << std::endl;
386         std::cout << "containerID: " << pdr->container_id << std::endl;
387         std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
388                   << std::endl;
389         std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
390                   << std::endl;
391         std::cout << "effecterDescriptionPDR: "
392                   << (unsigned(pdr->has_description_pdr) ? "true" : "false")
393                   << std::endl;
394         std::cout << "compositeEffecterCount: "
395                   << unsigned(pdr->composite_effecter_count) << std::endl;
396 
397         for (size_t i = 0; i < pdr->composite_effecter_count; ++i)
398         {
399             struct state_effecter_possible_states* state =
400                 (struct state_effecter_possible_states*)pdr->possible_states +
401                 i * sizeof(state_effecter_possible_states);
402             std::cout << "stateSetID: " << state->state_set_id << std::endl;
403             std::cout << "possibleStatesSize: "
404                       << unsigned(state->possible_states_size) << std::endl;
405             bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(state->states);
406             std::cout << "possibleStates: " << unsigned(bf->byte) << std::endl;
407         }
408     }
409 
410     void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
411                      uint8_t* data)
412     {
413         if (data == NULL)
414         {
415             return;
416         }
417 
418         std::cout << "nextRecordHandle: " << nextRecordHndl << std::endl;
419         std::cout << "responseCount: " << respCnt << std::endl;
420 
421         struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data;
422         std::cout << "recordHandle: " << pdr->record_handle << std::endl;
423         std::cout << "PDRHeaderVersion: " << unsigned(pdr->version)
424                   << std::endl;
425         std::cout << "PDRType: " << unsigned(pdr->type) << std::endl;
426         std::cout << "recordChangeNumber: " << pdr->record_change_num
427                   << std::endl;
428         std::cout << "dataLength: " << pdr->length << std::endl << std::endl;
429 
430         switch (pdr->type)
431         {
432             case PLDM_NUMERIC_EFFECTER_PDR:
433                 printNumericEffecterPDR(data);
434                 break;
435             case PLDM_STATE_EFFECTER_PDR:
436                 printStateEffecterPDR(data);
437                 break;
438             case PLDM_PDR_ENTITY_ASSOCIATION:
439                 printPDREntityAssociation(data);
440                 break;
441             case PLDM_PDR_FRU_RECORD_SET:
442                 printPDRFruRecordSet(data);
443                 break;
444             default:
445                 break;
446         }
447     }
448 
449   private:
450     uint32_t recordHandle;
451 };
452 
453 class SetStateEffecter : public CommandInterface
454 {
455   public:
456     ~SetStateEffecter() = default;
457     SetStateEffecter() = delete;
458     SetStateEffecter(const SetStateEffecter&) = delete;
459     SetStateEffecter(SetStateEffecter&&) = default;
460     SetStateEffecter& operator=(const SetStateEffecter&) = delete;
461     SetStateEffecter& operator=(SetStateEffecter&&) = default;
462 
463     // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2)
464     static constexpr auto maxEffecterDataSize = 16;
465 
466     // compositeEffecterCount(value: 0x01 to 0x08)
467     static constexpr auto minEffecterCount = 1;
468     static constexpr auto maxEffecterCount = 8;
469     explicit SetStateEffecter(const char* type, const char* name,
470                               CLI::App* app) :
471         CommandInterface(type, name, app)
472     {
473         app->add_option(
474                "-i, --id", effecterId,
475                "A handle that is used to identify and access the effecter")
476             ->required();
477         app->add_option("-c, --count", effecterCount,
478                         "The number of individual sets of effecter information")
479             ->required();
480         app->add_option(
481                "-d,--data", effecterData,
482                "Set effecter state data\n"
483                "eg: requestSet0 effecterState0 noChange1 dummyState1 ...")
484             ->required();
485     }
486 
487     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
488     {
489         std::vector<uint8_t> requestMsg(
490             sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES);
491         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
492 
493         if (effecterCount > maxEffecterCount ||
494             effecterCount < minEffecterCount)
495         {
496             std::cerr << "Request Message Error: effecterCount size "
497                       << effecterCount << "is invalid\n";
498             auto rc = PLDM_ERROR_INVALID_DATA;
499             return {rc, requestMsg};
500         }
501 
502         if (effecterData.size() > maxEffecterDataSize)
503         {
504             std::cerr << "Request Message Error: effecterData size "
505                       << effecterData.size() << "is invalid\n";
506             auto rc = PLDM_ERROR_INVALID_DATA;
507             return {rc, requestMsg};
508         }
509 
510         auto stateField = parseEffecterData(effecterData, effecterCount);
511         if (!stateField)
512         {
513             std::cerr << "Failed to parse effecter data, effecterCount size "
514                       << effecterCount << "\n";
515             auto rc = PLDM_ERROR_INVALID_DATA;
516             return {rc, requestMsg};
517         }
518 
519         auto rc = encode_set_state_effecter_states_req(
520             instanceId, effecterId, effecterCount, stateField->data(), request);
521         return {rc, requestMsg};
522     }
523 
524     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
525     {
526         uint8_t completionCode = 0;
527         auto rc = decode_set_state_effecter_states_resp(
528             responsePtr, payloadLength, &completionCode);
529 
530         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
531         {
532             std::cerr << "Response Message Error: "
533                       << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
534             return;
535         }
536 
537         std::cout << "SetStateEffecterStates: SUCCESS" << std::endl;
538     }
539 
540   private:
541     uint16_t effecterId;
542     uint8_t effecterCount;
543     std::vector<uint8_t> effecterData;
544 };
545 
546 class SetNumericEffecterValue : public CommandInterface
547 {
548   public:
549     ~SetNumericEffecterValue() = default;
550     SetNumericEffecterValue() = delete;
551     SetNumericEffecterValue(const SetNumericEffecterValue&) = delete;
552     SetNumericEffecterValue(SetNumericEffecterValue&&) = default;
553     SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete;
554     SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = default;
555 
556     explicit SetNumericEffecterValue(const char* type, const char* name,
557                                      CLI::App* app) :
558         CommandInterface(type, name, app)
559     {
560         app->add_option(
561                "-i, --id", effecterId,
562                "A handle that is used to identify and access the effecter")
563             ->required();
564         app->add_option("-s, --size", effecterDataSize,
565                         "The bit width and format of the setting value for the "
566                         "effecter. enum value: {uint8, sint8, uint16, sint16, "
567                         "uint32, sint32}\n")
568             ->required();
569         app->add_option("-d,--data", maxEffecterValue,
570                         "The setting value of numeric effecter being "
571                         "requested\n")
572             ->required();
573     }
574 
575     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
576     {
577         std::vector<uint8_t> requestMsg(
578             sizeof(pldm_msg_hdr) +
579             PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3);
580 
581         uint8_t* effecterValue = (uint8_t*)&maxEffecterValue;
582 
583         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
584         size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES;
585 
586         if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
587             effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
588         {
589             payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1;
590         }
591         if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
592             effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
593         {
594             payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3;
595         }
596         auto rc = encode_set_numeric_effecter_value_req(
597             0, effecterId, effecterDataSize, effecterValue, request,
598             payload_length);
599 
600         return {rc, requestMsg};
601     }
602 
603     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
604     {
605         uint8_t completionCode = 0;
606         auto rc = decode_set_numeric_effecter_value_resp(
607             responsePtr, payloadLength, &completionCode);
608 
609         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
610         {
611             std::cerr << "Response Message Error: "
612                       << "rc=" << rc << ",cc=" << (int)completionCode
613                       << std::endl;
614             return;
615         }
616 
617         std::cout << "SetNumericEffecterValue: SUCCESS" << std::endl;
618     }
619 
620   private:
621     uint16_t effecterId;
622     uint8_t effecterDataSize;
623     uint64_t maxEffecterValue;
624 };
625 
626 void registerCommand(CLI::App& app)
627 {
628     auto platform = app.add_subcommand("platform", "platform type command");
629     platform->require_subcommand(1);
630 
631     auto getPDR =
632         platform->add_subcommand("GetPDR", "get platform descriptor records");
633     commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR));
634 
635     auto setStateEffecterStates = platform->add_subcommand(
636         "SetStateEffecterStates", "set effecter states");
637     commands.push_back(std::make_unique<SetStateEffecter>(
638         "platform", "setStateEffecterStates", setStateEffecterStates));
639 
640     auto setNumericEffecterValue = platform->add_subcommand(
641         "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter");
642     commands.push_back(std::make_unique<SetNumericEffecterValue>(
643         "platform", "setNumericEffecterValue", setNumericEffecterValue));
644 }
645 
646 } // namespace platform
647 } // namespace pldmtool
648