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         {PLDM_STATE_SET_SYSTEM_POWER_STATE, "System Power State"},
114     };
115 
116     const std::array<std::string_view, 4> sensorInit = {
117         "noInit", "useInitPDR", "enableSensor", "disableSensor"};
118 
119     const std::array<std::string_view, 4> effecterInit = {
120         "noInit", "useInitPDR", "enableEffecter", "disableEffecter"};
121 
122     const std::map<uint8_t, std::string> pdrType = {
123         {PLDM_TERMINUS_LOCATOR_PDR, "Terminus Locator PDR"},
124         {PLDM_NUMERIC_SENSOR_PDR, "Numeric Sensor PDR"},
125         {PLDM_NUMERIC_SENSOR_INITIALIZATION_PDR,
126          "Numeric Sensor Initialization PDR"},
127         {PLDM_STATE_SENSOR_PDR, "State Sensor PDR"},
128         {PLDM_STATE_SENSOR_INITIALIZATION_PDR,
129          "State Sensor Initialization PDR"},
130         {PLDM_SENSOR_AUXILIARY_NAMES_PDR, "Sensor Auxiliary Names PDR"},
131         {PLDM_OEM_UNIT_PDR, "OEM Unit PDR"},
132         {PLDM_OEM_STATE_SET_PDR, "OEM State Set PDR"},
133         {PLDM_NUMERIC_EFFECTER_PDR, "Numeric Effecter PDR"},
134         {PLDM_NUMERIC_EFFECTER_INITIALIZATION_PDR,
135          "Numeric Effecter Initialization PDR"},
136         {PLDM_STATE_EFFECTER_PDR, "State Effecter PDR"},
137         {PLDM_STATE_EFFECTER_INITIALIZATION_PDR,
138          "State Effecter Initialization PDR"},
139         {PLDM_EFFECTER_AUXILIARY_NAMES_PDR, "Effecter Auxiliary Names PDR"},
140         {PLDM_EFFECTER_OEM_SEMANTIC_PDR, "Effecter OEM Semantic PDR"},
141         {PLDM_PDR_ENTITY_ASSOCIATION, "Entity Association PDR"},
142         {PLDM_ENTITY_AUXILIARY_NAMES_PDR, "Entity Auxiliary Names PDR"},
143         {PLDM_OEM_ENTITY_ID_PDR, "OEM Entity ID PDR"},
144         {PLDM_INTERRUPT_ASSOCIATION_PDR, "Interrupt Association PDR"},
145         {PLDM_EVENT_LOG_PDR, "PLDM Event Log PDR"},
146         {PLDM_PDR_FRU_RECORD_SET, "FRU Record Set PDR"},
147         {PLDM_OEM_DEVICE_PDR, "OEM Device PDR"},
148         {PLDM_OEM_PDR, "OEM PDR"},
149     };
150 
151     std::string getEntityName(pldm::pdr::EntityType type)
152     {
153         try
154         {
155             return entityType.at(type);
156         }
157         catch (const std::out_of_range& e)
158         {
159             return std::to_string(static_cast<unsigned>(type)) + "(OEM)";
160         }
161     }
162 
163     std::string getStateSetName(uint16_t id)
164     {
165         auto typeString = std::to_string(id);
166         try
167         {
168             return stateSet.at(id) + "(" + typeString + ")";
169         }
170         catch (const std::out_of_range& e)
171         {
172             return typeString;
173         }
174     }
175 
176     std::string getPDRType(uint8_t type)
177     {
178         auto typeString = std::to_string(type);
179         try
180         {
181             return pdrType.at(type) + "(" + typeString + ")";
182         }
183         catch (const std::out_of_range& e)
184         {
185             return typeString;
186         }
187     }
188 
189     void printCommonPDRHeader(const pldm_pdr_hdr* hdr)
190     {
191         std::cout << "recordHandle: " << hdr->record_handle << std::endl;
192         std::cout << "PDRHeaderVersion: " << unsigned(hdr->version)
193                   << std::endl;
194         std::cout << "PDRType: " << getPDRType(hdr->type) << std::endl;
195         std::cout << "recordChangeNumber: " << hdr->record_change_num
196                   << std::endl;
197         std::cout << "dataLength: " << hdr->length << std::endl << std::endl;
198     }
199 
200     void printPossibleStates(uint8_t possibleStatesSize,
201                              const bitfield8_t* states)
202     {
203         uint8_t possibleStatesPos{};
204         auto printStates = [&possibleStatesPos](const bitfield8_t& val) {
205             for (int i = 0; i < CHAR_BIT; i++)
206             {
207                 if (val.byte & (1 << i))
208                 {
209                     std::cout << " " << (possibleStatesPos * CHAR_BIT + i);
210                 }
211             }
212             possibleStatesPos++;
213         };
214         std::for_each(states, states + possibleStatesSize, printStates);
215     }
216 
217     void printStateSensorPDR(const uint8_t* data)
218     {
219         auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(data);
220 
221         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
222                   << std::endl;
223         std::cout << "sensorID: " << pdr->sensor_id << std::endl;
224         std::cout << "entityType: " << getEntityName(pdr->entity_type)
225                   << std::endl;
226         std::cout << "entityInstanceNumber: " << pdr->entity_instance
227                   << std::endl;
228         std::cout << "containerID: " << pdr->container_id << std::endl;
229         std::cout << "sensorInit: " << sensorInit[pdr->sensor_init]
230                   << std::endl;
231         std::cout << "sensorAuxiliaryNamesPDR: "
232                   << (pdr->sensor_auxiliary_names_pdr ? "true" : "false")
233                   << std::endl;
234         std::cout << "compositeSensorCount: "
235                   << unsigned(pdr->composite_sensor_count) << std::endl;
236 
237         auto statesPtr = pdr->possible_states;
238         auto compositeSensorCount = pdr->composite_sensor_count;
239 
240         while (compositeSensorCount--)
241         {
242             auto state = reinterpret_cast<const state_sensor_possible_states*>(
243                 statesPtr);
244             std::cout << "stateSetID: " << getStateSetName(state->state_set_id)
245                       << std::endl;
246             std::cout << "possibleStatesSize: "
247                       << unsigned(state->possible_states_size) << std::endl;
248             std::cout << "possibleStates:";
249             printPossibleStates(state->possible_states_size, state->states);
250             std::cout << std::endl;
251 
252             if (compositeSensorCount)
253             {
254                 statesPtr += sizeof(state_sensor_possible_states) +
255                              state->possible_states_size - 1;
256             }
257         }
258     }
259 
260     void printPDRFruRecordSet(uint8_t* data)
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         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
272                   << std::endl;
273         std::cout << "FRURecordSetIdentifier: " << pdr->fru_rsi << std::endl;
274         std::cout << "entityType: " << getEntityName(pdr->entity_type)
275                   << std::endl;
276         std::cout << "entityInstanceNumber: " << pdr->entity_instance_num
277                   << std::endl;
278         std::cout << "containerID: " << pdr->container_id << std::endl;
279     }
280 
281     void printPDREntityAssociation(uint8_t* data)
282     {
283         const std::map<uint8_t, const char*> assocationType = {
284             {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"},
285             {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"},
286         };
287 
288         if (data == NULL)
289         {
290             return;
291         }
292 
293         data += sizeof(pldm_pdr_hdr);
294         pldm_pdr_entity_association* pdr =
295             reinterpret_cast<pldm_pdr_entity_association*>(data);
296 
297         std::cout << "containerID: " << pdr->container_id << std::endl;
298         std::cout << "associationType: "
299                   << assocationType.at(pdr->association_type) << std::endl
300                   << std::endl;
301 
302         std::cout << "containerEntityType: "
303                   << getEntityName(pdr->container.entity_type) << std::endl;
304         std::cout << "containerEntityInstanceNumber: "
305                   << pdr->container.entity_instance_num << std::endl;
306         std::cout << "containerEntityContainerID: "
307                   << pdr->container.entity_container_id << std::endl;
308 
309         std::cout << "containedEntityCount: "
310                   << static_cast<unsigned>(pdr->num_children) << std::endl
311                   << std::endl;
312 
313         auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]);
314         for (int i = 0; i < pdr->num_children; ++i)
315         {
316             std::cout << "containedEntityType[" << i + 1
317                       << "]: " << getEntityName(child->entity_type)
318                       << std::endl;
319             std::cout << "containedEntityInstanceNumber[" << i + 1
320                       << "]: " << child->entity_instance_num << std::endl;
321             std::cout << "containedEntityContainerID[" << i + 1
322                       << "]: " << child->entity_container_id << std::endl
323                       << std::endl;
324             ++child;
325         }
326     }
327 
328     void printNumericEffecterPDR(uint8_t* data)
329     {
330         struct pldm_numeric_effecter_value_pdr* pdr =
331             (struct pldm_numeric_effecter_value_pdr*)data;
332         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
333                   << std::endl;
334         std::cout << "effecterID: " << pdr->effecter_id << std::endl;
335         std::cout << "entityType: " << pdr->entity_type << std::endl;
336         std::cout << "entityInstanceNumber: " << pdr->entity_instance
337                   << std::endl;
338         std::cout << "containerID: " << pdr->container_id << std::endl;
339         std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
340                   << std::endl;
341         std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
342                   << std::endl;
343         std::cout << "effecterAuxiliaryNames: "
344                   << (unsigned(pdr->effecter_auxiliary_names) ? "true"
345                                                               : "false")
346                   << std::endl;
347         std::cout << "baseUnit: " << unsigned(pdr->base_unit) << std::endl;
348         std::cout << "unitModifier: " << unsigned(pdr->unit_modifier)
349                   << std::endl;
350         std::cout << "rateUnit: " << unsigned(pdr->rate_unit) << std::endl;
351         std::cout << "baseOEMUnitHandle: "
352                   << unsigned(pdr->base_oem_unit_handle) << std::endl;
353         std::cout << "auxUnit: " << unsigned(pdr->aux_unit) << std::endl;
354         std::cout << "auxUnitModifier: " << unsigned(pdr->aux_unit_modifier)
355                   << std::endl;
356         std::cout << "auxrateUnit: " << unsigned(pdr->aux_rate_unit)
357                   << std::endl;
358         std::cout << "auxOEMUnitHandle: " << unsigned(pdr->aux_oem_unit_handle)
359                   << std::endl;
360         std::cout << "isLinear: "
361                   << (unsigned(pdr->is_linear) ? "true" : "false") << std::endl;
362         std::cout << "effecterDataSize: " << unsigned(pdr->effecter_data_size)
363                   << std::endl;
364         std::cout << "resolution: " << pdr->resolution << std::endl;
365         std::cout << "offset: " << pdr->offset << std::endl;
366         std::cout << "accuracy: " << pdr->accuracy << std::endl;
367         std::cout << "plusTolerance: " << unsigned(pdr->plus_tolerance)
368                   << std::endl;
369         std::cout << "minusTolerance: " << unsigned(pdr->minus_tolerance)
370                   << std::endl;
371         std::cout << "stateTransitionInterval: "
372                   << pdr->state_transition_interval << std::endl;
373         std::cout << "TransitionInterval: " << pdr->transition_interval
374                   << std::endl;
375         switch (pdr->effecter_data_size)
376         {
377             case PLDM_EFFECTER_DATA_SIZE_UINT8:
378                 std::cout << "maxSettable: "
379                           << unsigned(pdr->max_set_table.value_u8) << std::endl;
380                 std::cout << "minSettable: "
381                           << unsigned(pdr->min_set_table.value_u8) << std::endl;
382                 break;
383             case PLDM_EFFECTER_DATA_SIZE_SINT8:
384                 std::cout << "maxSettable: "
385                           << unsigned(pdr->max_set_table.value_s8) << std::endl;
386                 std::cout << "minSettable: "
387                           << unsigned(pdr->min_set_table.value_s8) << std::endl;
388                 break;
389             case PLDM_EFFECTER_DATA_SIZE_UINT16:
390                 std::cout << "maxSettable: " << pdr->max_set_table.value_u16
391                           << std::endl;
392                 std::cout << "minSettable: " << pdr->min_set_table.value_u16
393                           << std::endl;
394                 break;
395             case PLDM_EFFECTER_DATA_SIZE_SINT16:
396                 std::cout << "maxSettable: " << pdr->max_set_table.value_s16
397                           << std::endl;
398                 std::cout << "minSettable: " << pdr->min_set_table.value_s16
399                           << std::endl;
400                 break;
401             case PLDM_EFFECTER_DATA_SIZE_UINT32:
402                 std::cout << "maxSettable: " << pdr->max_set_table.value_u32
403                           << std::endl;
404                 std::cout << "minSettable: " << pdr->min_set_table.value_u32
405                           << std::endl;
406                 break;
407             case PLDM_EFFECTER_DATA_SIZE_SINT32:
408                 std::cout << "maxSettable: " << pdr->max_set_table.value_s32
409                           << std::endl;
410                 std::cout << "minSettable: " << pdr->min_set_table.value_s32
411                           << std::endl;
412                 break;
413             default:
414                 break;
415         }
416         std::cout << "rangeFieldFormat: " << unsigned(pdr->range_field_format)
417                   << std::endl;
418         std::cout << "rangeFieldSupport: "
419                   << unsigned(pdr->range_field_support.byte) << std::endl;
420         switch (pdr->range_field_format)
421         {
422             case PLDM_RANGE_FIELD_FORMAT_UINT8:
423                 std::cout << "nominalValue: "
424                           << unsigned(pdr->nominal_value.value_u8) << std::endl;
425                 std::cout << "normalMax: " << unsigned(pdr->normal_max.value_u8)
426                           << std::endl;
427                 std::cout << "normalMin: " << unsigned(pdr->normal_min.value_u8)
428                           << std::endl;
429                 std::cout << "ratedMax: " << unsigned(pdr->rated_max.value_u8)
430                           << std::endl;
431                 std::cout << "ratedMin: " << unsigned(pdr->rated_min.value_u8)
432                           << std::endl;
433                 break;
434             case PLDM_RANGE_FIELD_FORMAT_SINT8:
435                 std::cout << "nominalValue: "
436                           << unsigned(pdr->nominal_value.value_s8) << std::endl;
437                 std::cout << "normalMax: " << unsigned(pdr->normal_max.value_s8)
438                           << std::endl;
439                 std::cout << "normalMin: " << unsigned(pdr->normal_min.value_s8)
440                           << std::endl;
441                 std::cout << "ratedMax: " << unsigned(pdr->rated_max.value_s8)
442                           << std::endl;
443                 std::cout << "ratedMin: " << unsigned(pdr->rated_min.value_s8)
444                           << std::endl;
445                 break;
446             case PLDM_RANGE_FIELD_FORMAT_UINT16:
447                 std::cout << "nominalValue: " << pdr->nominal_value.value_u16
448                           << std::endl;
449                 std::cout << "normalMax: " << pdr->normal_max.value_u16
450                           << std::endl;
451                 std::cout << "normalMin: " << pdr->normal_min.value_u16
452                           << std::endl;
453                 std::cout << "ratedMax: " << pdr->rated_max.value_u16
454                           << std::endl;
455                 std::cout << "ratedMin: " << pdr->rated_min.value_u16
456                           << std::endl;
457                 break;
458             case PLDM_RANGE_FIELD_FORMAT_SINT16:
459                 std::cout << "nominalValue: " << pdr->nominal_value.value_s16
460                           << std::endl;
461                 std::cout << "normalMax: " << pdr->normal_max.value_s16
462                           << std::endl;
463                 std::cout << "normalMin: " << pdr->normal_min.value_s16
464                           << std::endl;
465                 std::cout << "ratedMax: " << pdr->rated_max.value_s16
466                           << std::endl;
467                 std::cout << "ratedMin: " << pdr->rated_min.value_s16
468                           << std::endl;
469                 break;
470             case PLDM_RANGE_FIELD_FORMAT_UINT32:
471                 std::cout << "nominalValue: " << pdr->nominal_value.value_u32
472                           << std::endl;
473                 std::cout << "normalMax: " << pdr->normal_max.value_u32
474                           << std::endl;
475                 std::cout << "normalMin: " << pdr->normal_min.value_u32
476                           << std::endl;
477                 std::cout << "ratedMax: " << pdr->rated_max.value_u32
478                           << std::endl;
479                 std::cout << "ratedMin: " << pdr->rated_min.value_u32
480                           << std::endl;
481                 break;
482             case PLDM_RANGE_FIELD_FORMAT_SINT32:
483                 std::cout << "nominalValue: " << pdr->nominal_value.value_s32
484                           << std::endl;
485                 std::cout << "normalMax: " << pdr->normal_max.value_s32
486                           << std::endl;
487                 std::cout << "normalMin: " << pdr->normal_min.value_s32
488                           << std::endl;
489                 std::cout << "ratedMax: " << pdr->rated_max.value_s32
490                           << std::endl;
491                 std::cout << "ratedMin: " << pdr->rated_min.value_s32
492                           << std::endl;
493                 break;
494             case PLDM_RANGE_FIELD_FORMAT_REAL32:
495                 std::cout << "nominalValue: " << pdr->nominal_value.value_f32
496                           << std::endl;
497                 std::cout << "normalMax: " << pdr->normal_max.value_f32
498                           << std::endl;
499                 std::cout << "normalMin: " << pdr->normal_min.value_f32
500                           << std::endl;
501                 std::cout << "ratedMax: " << pdr->rated_max.value_f32
502                           << std::endl;
503                 std::cout << "ratedMin: " << pdr->rated_min.value_f32
504                           << std::endl;
505                 break;
506             default:
507                 break;
508         }
509     }
510 
511     void printStateEffecterPDR(const uint8_t* data)
512     {
513         auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(data);
514 
515         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
516                   << std::endl;
517         std::cout << "effecterID: " << pdr->effecter_id << std::endl;
518         std::cout << "entityType: " << getEntityName(pdr->entity_type)
519                   << std::endl;
520         std::cout << "entityInstanceNumber: " << pdr->entity_instance
521                   << std::endl;
522         std::cout << "containerID: " << pdr->container_id << std::endl;
523         std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
524                   << std::endl;
525         std::cout << "effecterInit: " << effecterInit[pdr->effecter_init]
526                   << std::endl;
527         std::cout << "effecterDescriptionPDR: "
528                   << (pdr->has_description_pdr ? "true" : "false") << std::endl;
529         std::cout << "compositeEffecterCount: "
530                   << unsigned(pdr->composite_effecter_count) << std::endl;
531 
532         auto statesPtr = pdr->possible_states;
533         auto compositeEffecterCount = pdr->composite_effecter_count;
534 
535         while (compositeEffecterCount--)
536         {
537             auto state =
538                 reinterpret_cast<const state_effecter_possible_states*>(
539                     statesPtr);
540             std::cout << "stateSetID: " << getStateSetName(state->state_set_id)
541                       << std::endl;
542             std::cout << "possibleStatesSize: "
543                       << unsigned(state->possible_states_size) << std::endl;
544             std::cout << "possibleStates:";
545             printPossibleStates(state->possible_states_size, state->states);
546             std::cout << std::endl;
547 
548             if (compositeEffecterCount)
549             {
550                 statesPtr += sizeof(state_effecter_possible_states) +
551                              state->possible_states_size - 1;
552             }
553         }
554     }
555 
556     void printTerminusLocatorPDR(const uint8_t* data)
557     {
558         const std::array<std::string_view, 4> terminusLocatorType = {
559             "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"};
560 
561         auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data);
562 
563         std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
564                   << std::endl;
565         std::cout << "validity: " << (pdr->validity ? "valid" : "notValid")
566                   << std::endl;
567         std::cout << "TID: " << unsigned(pdr->tid) << std::endl;
568         std::cout << "containerID: " << pdr->container_id << std::endl;
569         std::cout << "terminusLocatorType: "
570                   << terminusLocatorType[pdr->terminus_locator_type]
571                   << std::endl;
572         std::cout << "terminusLocatorValueSize: "
573                   << unsigned(pdr->terminus_locator_value_size) << std::endl;
574 
575         if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
576         {
577             auto locatorValue =
578                 reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
579                     pdr->terminus_locator_value);
580             std::cout << "EID: " << unsigned(locatorValue->eid) << std::endl;
581         }
582     }
583 
584     void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
585                      uint8_t* data)
586     {
587         if (data == NULL)
588         {
589             return;
590         }
591 
592         std::cout << "nextRecordHandle: " << nextRecordHndl << std::endl;
593         std::cout << "responseCount: " << respCnt << std::endl;
594 
595         struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data;
596         printCommonPDRHeader(pdr);
597         switch (pdr->type)
598         {
599             case PLDM_TERMINUS_LOCATOR_PDR:
600                 printTerminusLocatorPDR(data);
601                 break;
602             case PLDM_STATE_SENSOR_PDR:
603                 printStateSensorPDR(data);
604                 break;
605             case PLDM_NUMERIC_EFFECTER_PDR:
606                 printNumericEffecterPDR(data);
607                 break;
608             case PLDM_STATE_EFFECTER_PDR:
609                 printStateEffecterPDR(data);
610                 break;
611             case PLDM_PDR_ENTITY_ASSOCIATION:
612                 printPDREntityAssociation(data);
613                 break;
614             case PLDM_PDR_FRU_RECORD_SET:
615                 printPDRFruRecordSet(data);
616                 break;
617             default:
618                 break;
619         }
620     }
621 
622   private:
623     uint32_t recordHandle;
624 };
625 
626 class SetStateEffecter : public CommandInterface
627 {
628   public:
629     ~SetStateEffecter() = default;
630     SetStateEffecter() = delete;
631     SetStateEffecter(const SetStateEffecter&) = delete;
632     SetStateEffecter(SetStateEffecter&&) = default;
633     SetStateEffecter& operator=(const SetStateEffecter&) = delete;
634     SetStateEffecter& operator=(SetStateEffecter&&) = default;
635 
636     // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2)
637     static constexpr auto maxEffecterDataSize = 16;
638 
639     // compositeEffecterCount(value: 0x01 to 0x08)
640     static constexpr auto minEffecterCount = 1;
641     static constexpr auto maxEffecterCount = 8;
642     explicit SetStateEffecter(const char* type, const char* name,
643                               CLI::App* app) :
644         CommandInterface(type, name, app)
645     {
646         app->add_option(
647                "-i, --id", effecterId,
648                "A handle that is used to identify and access the effecter")
649             ->required();
650         app->add_option("-c, --count", effecterCount,
651                         "The number of individual sets of effecter information")
652             ->required();
653         app->add_option(
654                "-d,--data", effecterData,
655                "Set effecter state data\n"
656                "eg: requestSet0 effecterState0 noChange1 dummyState1 ...")
657             ->required();
658     }
659 
660     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
661     {
662         std::vector<uint8_t> requestMsg(
663             sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES);
664         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
665 
666         if (effecterCount > maxEffecterCount ||
667             effecterCount < minEffecterCount)
668         {
669             std::cerr << "Request Message Error: effecterCount size "
670                       << effecterCount << "is invalid\n";
671             auto rc = PLDM_ERROR_INVALID_DATA;
672             return {rc, requestMsg};
673         }
674 
675         if (effecterData.size() > maxEffecterDataSize)
676         {
677             std::cerr << "Request Message Error: effecterData size "
678                       << effecterData.size() << "is invalid\n";
679             auto rc = PLDM_ERROR_INVALID_DATA;
680             return {rc, requestMsg};
681         }
682 
683         auto stateField = parseEffecterData(effecterData, effecterCount);
684         if (!stateField)
685         {
686             std::cerr << "Failed to parse effecter data, effecterCount size "
687                       << effecterCount << "\n";
688             auto rc = PLDM_ERROR_INVALID_DATA;
689             return {rc, requestMsg};
690         }
691 
692         auto rc = encode_set_state_effecter_states_req(
693             instanceId, effecterId, effecterCount, stateField->data(), request);
694         return {rc, requestMsg};
695     }
696 
697     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
698     {
699         uint8_t completionCode = 0;
700         auto rc = decode_set_state_effecter_states_resp(
701             responsePtr, payloadLength, &completionCode);
702 
703         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
704         {
705             std::cerr << "Response Message Error: "
706                       << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
707             return;
708         }
709 
710         std::cout << "SetStateEffecterStates: SUCCESS" << std::endl;
711     }
712 
713   private:
714     uint16_t effecterId;
715     uint8_t effecterCount;
716     std::vector<uint8_t> effecterData;
717 };
718 
719 class SetNumericEffecterValue : public CommandInterface
720 {
721   public:
722     ~SetNumericEffecterValue() = default;
723     SetNumericEffecterValue() = delete;
724     SetNumericEffecterValue(const SetNumericEffecterValue&) = delete;
725     SetNumericEffecterValue(SetNumericEffecterValue&&) = default;
726     SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete;
727     SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = default;
728 
729     explicit SetNumericEffecterValue(const char* type, const char* name,
730                                      CLI::App* app) :
731         CommandInterface(type, name, app)
732     {
733         app->add_option(
734                "-i, --id", effecterId,
735                "A handle that is used to identify and access the effecter")
736             ->required();
737         app->add_option("-s, --size", effecterDataSize,
738                         "The bit width and format of the setting value for the "
739                         "effecter. enum value: {uint8, sint8, uint16, sint16, "
740                         "uint32, sint32}\n")
741             ->required();
742         app->add_option("-d,--data", maxEffecterValue,
743                         "The setting value of numeric effecter being "
744                         "requested\n")
745             ->required();
746     }
747 
748     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
749     {
750         std::vector<uint8_t> requestMsg(
751             sizeof(pldm_msg_hdr) +
752             PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3);
753 
754         uint8_t* effecterValue = (uint8_t*)&maxEffecterValue;
755 
756         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
757         size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES;
758 
759         if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
760             effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
761         {
762             payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1;
763         }
764         if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
765             effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
766         {
767             payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3;
768         }
769         auto rc = encode_set_numeric_effecter_value_req(
770             0, effecterId, effecterDataSize, effecterValue, request,
771             payload_length);
772 
773         return {rc, requestMsg};
774     }
775 
776     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
777     {
778         uint8_t completionCode = 0;
779         auto rc = decode_set_numeric_effecter_value_resp(
780             responsePtr, payloadLength, &completionCode);
781 
782         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
783         {
784             std::cerr << "Response Message Error: "
785                       << "rc=" << rc << ",cc=" << (int)completionCode
786                       << std::endl;
787             return;
788         }
789 
790         std::cout << "SetNumericEffecterValue: SUCCESS" << std::endl;
791     }
792 
793   private:
794     uint16_t effecterId;
795     uint8_t effecterDataSize;
796     uint64_t maxEffecterValue;
797 };
798 
799 void registerCommand(CLI::App& app)
800 {
801     auto platform = app.add_subcommand("platform", "platform type command");
802     platform->require_subcommand(1);
803 
804     auto getPDR =
805         platform->add_subcommand("GetPDR", "get platform descriptor records");
806     commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR));
807 
808     auto setStateEffecterStates = platform->add_subcommand(
809         "SetStateEffecterStates", "set effecter states");
810     commands.push_back(std::make_unique<SetStateEffecter>(
811         "platform", "setStateEffecterStates", setStateEffecterStates));
812 
813     auto setNumericEffecterValue = platform->add_subcommand(
814         "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter");
815     commands.push_back(std::make_unique<SetNumericEffecterValue>(
816         "platform", "setNumericEffecterValue", setNumericEffecterValue));
817 }
818 
819 } // namespace platform
820 } // namespace pldmtool
821