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