blob: d3ca8f71a07407321f293c60233d9d40b594d84b [file] [log] [blame]
George Liud6649362019-11-27 19:06:51 +08001#include "pldm_cmd_helper.hpp"
2
George Liud6649362019-11-27 19:06:51 +08003namespace pldmtool
4{
5
6namespace platform
7{
8
9namespace
10{
11
12using namespace pldmtool::helper;
13std::vector<std::unique_ptr<CommandInterface>> commands;
14
15} // namespace
16
17class 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
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -060050 auto rc = encode_get_pdr_req(instanceId, recordHandle, 0,
George Liud6649362019-11-27 19:06:51 +080051 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[255] = {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, sizeof(recordData));
80 }
81
82 private:
Deepak Kodihalli5544ccd2020-03-15 23:36:16 -050083 const std::map<uint16_t, std::string> entityType = {
84 {64, "System Board"},
85 {137, "Management Controller"},
86 {69, "Chassis front panel board (control panel)"},
87 {123, "Power converter"},
88 {45, "System chassis (main enclosure)"},
89 {11521, "System (logical)"},
90 };
91
92 std::string getEntityName(uint8_t type)
93 {
94 try
95 {
96 return entityType.at(type);
97 }
98 catch (const std::out_of_range& e)
99 {
100 return std::to_string(static_cast<unsigned>(type)) + "(OEM)";
101 }
102 }
103
104 void printPDRFruRecordSet(uint8_t* data, size_t len)
105 {
106 if (data == NULL || len == 0)
107 {
108 return;
109 }
110
111 data += sizeof(pldm_pdr_hdr);
112 pldm_pdr_fru_record_set* pdr =
113 reinterpret_cast<pldm_pdr_fru_record_set*>(data);
114
115 std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
116 << std::endl;
117 std::cout << "FRURecordSetIdentifier: " << pdr->fru_rsi << std::endl;
118 std::cout << "entityType: " << getEntityName(pdr->entity_type)
119 << std::endl;
120 std::cout << "entityInstanceNumber: " << pdr->entity_instance_num
121 << std::endl;
122 std::cout << "containerID: " << pdr->container_id << std::endl;
123 }
124
125 void printPDREntityAssociation(uint8_t* data, size_t len)
126 {
127 const std::map<uint8_t, const char*> assocationType = {
128 {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"},
129 {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"},
130 };
131
132 if (data == NULL || len == 0)
133 {
134 return;
135 }
136
137 data += sizeof(pldm_pdr_hdr);
138 pldm_pdr_entity_association* pdr =
139 reinterpret_cast<pldm_pdr_entity_association*>(data);
140
141 std::cout << "containerID: " << pdr->container_id << std::endl;
142 std::cout << "associationType: "
143 << assocationType.at(pdr->association_type) << std::endl
144 << std::endl;
145
146 std::cout << "containerEntityType: "
147 << getEntityName(pdr->container.entity_type) << std::endl;
148 std::cout << "containerEntityInstanceNumber: "
149 << pdr->container.entity_instance_num << std::endl;
150 std::cout << "containerEntityContainerID: "
151 << pdr->container.entity_container_id << std::endl;
152
153 std::cout << "containedEntityCount: "
154 << static_cast<unsigned>(pdr->num_children) << std::endl
155 << std::endl;
156
157 auto child = reinterpret_cast<pldm_entity*>(&pdr->children[0]);
158 for (int i = 0; i < pdr->num_children; ++i)
159 {
160 std::cout << "containedEntityType[" << i + 1
161 << "]: " << getEntityName(child->entity_type)
162 << std::endl;
163 std::cout << "containedEntityInstanceNumber[" << i + 1
164 << "]: " << child->entity_instance_num << std::endl;
165 std::cout << "containedEntityContainerID[" << i + 1
166 << "]: " << child->entity_container_id << std::endl
167 << std::endl;
168 ++child;
169 }
170 }
171
George Liud6649362019-11-27 19:06:51 +0800172 void printPDR11(uint8_t* data, size_t len)
173 {
174 if (data == NULL || len == 0)
175 {
176 return;
177 }
178
179 struct pldm_state_effecter_pdr* pdr =
180 (struct pldm_state_effecter_pdr*)data;
George Liud6649362019-11-27 19:06:51 +0800181 std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
182 << std::endl;
183 std::cout << "effecterID: " << pdr->effecter_id << std::endl;
184 std::cout << "entityType: " << pdr->entity_type << std::endl;
185 std::cout << "entityInstanceNumber: " << pdr->entity_instance
186 << std::endl;
187 std::cout << "containerID: " << pdr->container_id << std::endl;
188 std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
189 << std::endl;
190 std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
191 << std::endl;
192 std::cout << "effecterDescriptionPDR: "
193 << (unsigned(pdr->has_description_pdr) ? "true" : "false")
194 << std::endl;
195 std::cout << "compositeEffecterCount: "
196 << unsigned(pdr->composite_effecter_count) << std::endl;
197
198 for (size_t i = 0; i < pdr->composite_effecter_count; ++i)
199 {
200 struct state_effecter_possible_states* state =
201 (struct state_effecter_possible_states*)pdr->possible_states +
202 i * sizeof(state_effecter_possible_states);
203 std::cout << "stateSetID: " << state->state_set_id << std::endl;
204 std::cout << "possibleStatesSize: "
205 << unsigned(state->possible_states_size) << std::endl;
206 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(state->states);
207 std::cout << "possibleStates: " << unsigned(bf->byte) << std::endl;
208 }
209 }
210
211 void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
212 uint8_t* data, size_t len)
213 {
214 if (data == NULL || len == 0)
215 {
216 return;
217 }
218
George Liud6649362019-11-27 19:06:51 +0800219 std::cout << "nextRecordHandle: " << nextRecordHndl << std::endl;
220 std::cout << "responseCount: " << respCnt << std::endl;
221
222 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data;
Deepak Kodihalli5544ccd2020-03-15 23:36:16 -0500223 std::cout << "recordHandle: " << pdr->record_handle << std::endl;
224 std::cout << "PDRHeaderVersion: " << unsigned(pdr->version)
225 << std::endl;
226 std::cout << "PDRType: " << unsigned(pdr->type) << std::endl;
227 std::cout << "recordChangeNumber: " << pdr->record_change_num
228 << std::endl;
229 std::cout << "dataLength: " << pdr->length << std::endl << std::endl;
230
George Liud6649362019-11-27 19:06:51 +0800231 switch (pdr->type)
232 {
233 case PLDM_STATE_EFFECTER_PDR:
234 printPDR11(data, len);
235 break;
Deepak Kodihalli5544ccd2020-03-15 23:36:16 -0500236 case PLDM_PDR_ENTITY_ASSOCIATION:
237 printPDREntityAssociation(data, len);
238 break;
239 case PLDM_PDR_FRU_RECORD_SET:
240 printPDRFruRecordSet(data, len);
241 break;
George Liud6649362019-11-27 19:06:51 +0800242 default:
243 break;
244 }
245 }
246
247 private:
248 uint32_t recordHandle;
249};
250
251class SetStateEffecter : public CommandInterface
252{
253 public:
254 ~SetStateEffecter() = default;
255 SetStateEffecter() = delete;
256 SetStateEffecter(const SetStateEffecter&) = delete;
257 SetStateEffecter(SetStateEffecter&&) = default;
258 SetStateEffecter& operator=(const SetStateEffecter&) = delete;
259 SetStateEffecter& operator=(SetStateEffecter&&) = default;
260
George Liuba4c1fb2020-02-05 14:13:30 +0800261 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2)
262 static constexpr auto maxEffecterDataSize = 16;
263
264 // compositeEffecterCount(value: 0x01 to 0x08)
265 static constexpr auto minEffecterCount = 1;
266 static constexpr auto maxEffecterCount = 8;
George Liud6649362019-11-27 19:06:51 +0800267 explicit SetStateEffecter(const char* type, const char* name,
268 CLI::App* app) :
269 CommandInterface(type, name, app)
270 {
271 app->add_option(
George Liuba4c1fb2020-02-05 14:13:30 +0800272 "-i, --id", effecterId,
273 "A handle that is used to identify and access the effecter")
274 ->required();
275 app->add_option("-c, --count", effecterCount,
276 "The number of individual sets of effecter information")
277 ->required();
278 app->add_option(
George Liud6649362019-11-27 19:06:51 +0800279 "-d,--data", effecterData,
George Liuba4c1fb2020-02-05 14:13:30 +0800280 "Set effecter state data\n"
281 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...")
282 ->required();
George Liud6649362019-11-27 19:06:51 +0800283 }
284
285 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
286 {
287 std::vector<uint8_t> requestMsg(
288 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES);
289 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
290
George Liuba4c1fb2020-02-05 14:13:30 +0800291 if (effecterCount > maxEffecterCount ||
292 effecterCount < minEffecterCount)
George Liud6649362019-11-27 19:06:51 +0800293 {
George Liuba4c1fb2020-02-05 14:13:30 +0800294 std::cerr << "Request Message Error: effecterCount size "
295 << effecterCount << "is invalid\n";
George Liud6649362019-11-27 19:06:51 +0800296 auto rc = PLDM_ERROR_INVALID_DATA;
297 return {rc, requestMsg};
298 }
299
George Liuba4c1fb2020-02-05 14:13:30 +0800300 if (effecterData.size() > maxEffecterDataSize)
George Liud6649362019-11-27 19:06:51 +0800301 {
George Liuba4c1fb2020-02-05 14:13:30 +0800302 std::cerr << "Request Message Error: effecterData size "
303 << effecterData.size() << "is invalid\n";
304 auto rc = PLDM_ERROR_INVALID_DATA;
305 return {rc, requestMsg};
306 }
307
308 auto stateField = parseEffecterData(effecterData, effecterCount);
309 if (!stateField)
310 {
311 std::cerr << "Failed to parse effecter data, effecterCount size "
312 << effecterCount << "\n";
George Liud6649362019-11-27 19:06:51 +0800313 auto rc = PLDM_ERROR_INVALID_DATA;
314 return {rc, requestMsg};
315 }
316
317 auto rc = encode_set_state_effecter_states_req(
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600318 instanceId, effecterId, effecterCount, stateField->data(), request);
George Liud6649362019-11-27 19:06:51 +0800319 return {rc, requestMsg};
320 }
321
322 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
323 {
324 uint8_t completionCode = 0;
325 auto rc = decode_set_state_effecter_states_resp(
326 responsePtr, payloadLength, &completionCode);
327
328 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
329 {
330 std::cerr << "Response Message Error: "
George Liuba4c1fb2020-02-05 14:13:30 +0800331 << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
George Liud6649362019-11-27 19:06:51 +0800332 return;
333 }
334
335 std::cout << "SetStateEffecterStates: SUCCESS" << std::endl;
336 }
337
338 private:
George Liuba4c1fb2020-02-05 14:13:30 +0800339 uint16_t effecterId;
340 uint8_t effecterCount;
George Liud6649362019-11-27 19:06:51 +0800341 std::vector<uint8_t> effecterData;
342};
343
344void registerCommand(CLI::App& app)
345{
346 auto platform = app.add_subcommand("platform", "platform type command");
347 platform->require_subcommand(1);
348
349 auto getPDR =
350 platform->add_subcommand("GetPDR", "get platform descriptor records");
351 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR));
352
353 auto setStateEffecterStates = platform->add_subcommand(
354 "SetStateEffecterStates", "set effecter states");
355 commands.push_back(std::make_unique<SetStateEffecter>(
356 "platform", "setStateEffecterStates", setStateEffecterStates));
357}
358
359} // namespace platform
360} // namespace pldmtool