blob: db5cbed1d3435c76cc30d8f1ecea80214bd5e3ff [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"},
Pavithra Barithayae8beb892020-04-14 23:24:25 -050085 {66, "Memory Module"},
86 {67, "Processor Module"},
Deepak Kodihalli5544ccd2020-03-15 23:36:16 -050087 {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
Deepak Kodihallia556eb22020-04-14 02:29:11 -050094 std::string getEntityName(uint16_t type)
Deepak Kodihalli5544ccd2020-03-15 23:36:16 -050095 {
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, size_t len)
107 {
108 if (data == NULL || len == 0)
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, size_t len)
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 || len == 0)
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
George Liud6649362019-11-27 19:06:51 +0800174 void printPDR11(uint8_t* data, size_t len)
175 {
176 if (data == NULL || len == 0)
177 {
178 return;
179 }
180
181 struct pldm_state_effecter_pdr* pdr =
182 (struct pldm_state_effecter_pdr*)data;
George Liud6649362019-11-27 19:06:51 +0800183 std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
184 << std::endl;
185 std::cout << "effecterID: " << pdr->effecter_id << std::endl;
186 std::cout << "entityType: " << pdr->entity_type << std::endl;
187 std::cout << "entityInstanceNumber: " << pdr->entity_instance
188 << std::endl;
189 std::cout << "containerID: " << pdr->container_id << std::endl;
190 std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
191 << std::endl;
192 std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
193 << std::endl;
194 std::cout << "effecterDescriptionPDR: "
195 << (unsigned(pdr->has_description_pdr) ? "true" : "false")
196 << std::endl;
197 std::cout << "compositeEffecterCount: "
198 << unsigned(pdr->composite_effecter_count) << std::endl;
199
200 for (size_t i = 0; i < pdr->composite_effecter_count; ++i)
201 {
202 struct state_effecter_possible_states* state =
203 (struct state_effecter_possible_states*)pdr->possible_states +
204 i * sizeof(state_effecter_possible_states);
205 std::cout << "stateSetID: " << state->state_set_id << std::endl;
206 std::cout << "possibleStatesSize: "
207 << unsigned(state->possible_states_size) << std::endl;
208 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(state->states);
209 std::cout << "possibleStates: " << unsigned(bf->byte) << std::endl;
210 }
211 }
212
213 void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
214 uint8_t* data, size_t len)
215 {
216 if (data == NULL || len == 0)
217 {
218 return;
219 }
220
George Liud6649362019-11-27 19:06:51 +0800221 std::cout << "nextRecordHandle: " << nextRecordHndl << std::endl;
222 std::cout << "responseCount: " << respCnt << std::endl;
223
224 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data;
Deepak Kodihalli5544ccd2020-03-15 23:36:16 -0500225 std::cout << "recordHandle: " << pdr->record_handle << std::endl;
226 std::cout << "PDRHeaderVersion: " << unsigned(pdr->version)
227 << std::endl;
228 std::cout << "PDRType: " << unsigned(pdr->type) << std::endl;
229 std::cout << "recordChangeNumber: " << pdr->record_change_num
230 << std::endl;
231 std::cout << "dataLength: " << pdr->length << std::endl << std::endl;
232
George Liud6649362019-11-27 19:06:51 +0800233 switch (pdr->type)
234 {
235 case PLDM_STATE_EFFECTER_PDR:
236 printPDR11(data, len);
237 break;
Deepak Kodihalli5544ccd2020-03-15 23:36:16 -0500238 case PLDM_PDR_ENTITY_ASSOCIATION:
239 printPDREntityAssociation(data, len);
240 break;
241 case PLDM_PDR_FRU_RECORD_SET:
242 printPDRFruRecordSet(data, len);
243 break;
George Liud6649362019-11-27 19:06:51 +0800244 default:
245 break;
246 }
247 }
248
249 private:
250 uint32_t recordHandle;
251};
252
253class SetStateEffecter : public CommandInterface
254{
255 public:
256 ~SetStateEffecter() = default;
257 SetStateEffecter() = delete;
258 SetStateEffecter(const SetStateEffecter&) = delete;
259 SetStateEffecter(SetStateEffecter&&) = default;
260 SetStateEffecter& operator=(const SetStateEffecter&) = delete;
261 SetStateEffecter& operator=(SetStateEffecter&&) = default;
262
George Liuba4c1fb2020-02-05 14:13:30 +0800263 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2)
264 static constexpr auto maxEffecterDataSize = 16;
265
266 // compositeEffecterCount(value: 0x01 to 0x08)
267 static constexpr auto minEffecterCount = 1;
268 static constexpr auto maxEffecterCount = 8;
George Liud6649362019-11-27 19:06:51 +0800269 explicit SetStateEffecter(const char* type, const char* name,
270 CLI::App* app) :
271 CommandInterface(type, name, app)
272 {
273 app->add_option(
George Liuba4c1fb2020-02-05 14:13:30 +0800274 "-i, --id", effecterId,
275 "A handle that is used to identify and access the effecter")
276 ->required();
277 app->add_option("-c, --count", effecterCount,
278 "The number of individual sets of effecter information")
279 ->required();
280 app->add_option(
George Liud6649362019-11-27 19:06:51 +0800281 "-d,--data", effecterData,
George Liuba4c1fb2020-02-05 14:13:30 +0800282 "Set effecter state data\n"
283 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...")
284 ->required();
George Liud6649362019-11-27 19:06:51 +0800285 }
286
287 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
288 {
289 std::vector<uint8_t> requestMsg(
290 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES);
291 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
292
George Liuba4c1fb2020-02-05 14:13:30 +0800293 if (effecterCount > maxEffecterCount ||
294 effecterCount < minEffecterCount)
George Liud6649362019-11-27 19:06:51 +0800295 {
George Liuba4c1fb2020-02-05 14:13:30 +0800296 std::cerr << "Request Message Error: effecterCount size "
297 << effecterCount << "is invalid\n";
George Liud6649362019-11-27 19:06:51 +0800298 auto rc = PLDM_ERROR_INVALID_DATA;
299 return {rc, requestMsg};
300 }
301
George Liuba4c1fb2020-02-05 14:13:30 +0800302 if (effecterData.size() > maxEffecterDataSize)
George Liud6649362019-11-27 19:06:51 +0800303 {
George Liuba4c1fb2020-02-05 14:13:30 +0800304 std::cerr << "Request Message Error: effecterData size "
305 << effecterData.size() << "is invalid\n";
306 auto rc = PLDM_ERROR_INVALID_DATA;
307 return {rc, requestMsg};
308 }
309
310 auto stateField = parseEffecterData(effecterData, effecterCount);
311 if (!stateField)
312 {
313 std::cerr << "Failed to parse effecter data, effecterCount size "
314 << effecterCount << "\n";
George Liud6649362019-11-27 19:06:51 +0800315 auto rc = PLDM_ERROR_INVALID_DATA;
316 return {rc, requestMsg};
317 }
318
319 auto rc = encode_set_state_effecter_states_req(
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600320 instanceId, effecterId, effecterCount, stateField->data(), request);
George Liud6649362019-11-27 19:06:51 +0800321 return {rc, requestMsg};
322 }
323
324 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
325 {
326 uint8_t completionCode = 0;
327 auto rc = decode_set_state_effecter_states_resp(
328 responsePtr, payloadLength, &completionCode);
329
330 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
331 {
332 std::cerr << "Response Message Error: "
George Liuba4c1fb2020-02-05 14:13:30 +0800333 << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
George Liud6649362019-11-27 19:06:51 +0800334 return;
335 }
336
337 std::cout << "SetStateEffecterStates: SUCCESS" << std::endl;
338 }
339
340 private:
George Liuba4c1fb2020-02-05 14:13:30 +0800341 uint16_t effecterId;
342 uint8_t effecterCount;
George Liud6649362019-11-27 19:06:51 +0800343 std::vector<uint8_t> effecterData;
344};
345
346void registerCommand(CLI::App& app)
347{
348 auto platform = app.add_subcommand("platform", "platform type command");
349 platform->require_subcommand(1);
350
351 auto getPDR =
352 platform->add_subcommand("GetPDR", "get platform descriptor records");
353 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR));
354
355 auto setStateEffecterStates = platform->add_subcommand(
356 "SetStateEffecterStates", "set effecter states");
357 commands.push_back(std::make_unique<SetStateEffecter>(
358 "platform", "setStateEffecterStates", setStateEffecterStates));
359}
360
361} // namespace platform
362} // namespace pldmtool