blob: 6d917fa58d4b3d40cf6b2e4a7e02ac1d7560b861 [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:
83 void printPDR11(uint8_t* data, size_t len)
84 {
85 if (data == NULL || len == 0)
86 {
87 return;
88 }
89
90 struct pldm_state_effecter_pdr* pdr =
91 (struct pldm_state_effecter_pdr*)data;
92 std::cout << "recordHandle: " << pdr->hdr.record_handle << std::endl;
93 std::cout << "PDRHeaderVersion: " << unsigned(pdr->hdr.version)
94 << std::endl;
95 std::cout << "PDRType: " << unsigned(pdr->hdr.type) << std::endl;
96 std::cout << "recordChangeNumber: " << pdr->hdr.record_change_num
97 << std::endl;
98 std::cout << "dataLength: " << pdr->hdr.length << std::endl;
99 std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
100 << std::endl;
101 std::cout << "effecterID: " << pdr->effecter_id << std::endl;
102 std::cout << "entityType: " << pdr->entity_type << std::endl;
103 std::cout << "entityInstanceNumber: " << pdr->entity_instance
104 << std::endl;
105 std::cout << "containerID: " << pdr->container_id << std::endl;
106 std::cout << "effecterSemanticID: " << pdr->effecter_semantic_id
107 << std::endl;
108 std::cout << "effecterInit: " << unsigned(pdr->effecter_init)
109 << std::endl;
110 std::cout << "effecterDescriptionPDR: "
111 << (unsigned(pdr->has_description_pdr) ? "true" : "false")
112 << std::endl;
113 std::cout << "compositeEffecterCount: "
114 << unsigned(pdr->composite_effecter_count) << std::endl;
115
116 for (size_t i = 0; i < pdr->composite_effecter_count; ++i)
117 {
118 struct state_effecter_possible_states* state =
119 (struct state_effecter_possible_states*)pdr->possible_states +
120 i * sizeof(state_effecter_possible_states);
121 std::cout << "stateSetID: " << state->state_set_id << std::endl;
122 std::cout << "possibleStatesSize: "
123 << unsigned(state->possible_states_size) << std::endl;
124 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(state->states);
125 std::cout << "possibleStates: " << unsigned(bf->byte) << std::endl;
126 }
127 }
128
129 void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
130 uint8_t* data, size_t len)
131 {
132 if (data == NULL || len == 0)
133 {
134 return;
135 }
136
137 std::cout << "Parsed Response Msg: " << std::endl;
138 std::cout << "nextRecordHandle: " << nextRecordHndl << std::endl;
139 std::cout << "responseCount: " << respCnt << std::endl;
140
141 struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data;
142 switch (pdr->type)
143 {
144 case PLDM_STATE_EFFECTER_PDR:
145 printPDR11(data, len);
146 break;
147 default:
148 break;
149 }
150 }
151
152 private:
153 uint32_t recordHandle;
154};
155
156class SetStateEffecter : public CommandInterface
157{
158 public:
159 ~SetStateEffecter() = default;
160 SetStateEffecter() = delete;
161 SetStateEffecter(const SetStateEffecter&) = delete;
162 SetStateEffecter(SetStateEffecter&&) = default;
163 SetStateEffecter& operator=(const SetStateEffecter&) = delete;
164 SetStateEffecter& operator=(SetStateEffecter&&) = default;
165
George Liuba4c1fb2020-02-05 14:13:30 +0800166 // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2)
167 static constexpr auto maxEffecterDataSize = 16;
168
169 // compositeEffecterCount(value: 0x01 to 0x08)
170 static constexpr auto minEffecterCount = 1;
171 static constexpr auto maxEffecterCount = 8;
George Liud6649362019-11-27 19:06:51 +0800172 explicit SetStateEffecter(const char* type, const char* name,
173 CLI::App* app) :
174 CommandInterface(type, name, app)
175 {
176 app->add_option(
George Liuba4c1fb2020-02-05 14:13:30 +0800177 "-i, --id", effecterId,
178 "A handle that is used to identify and access the effecter")
179 ->required();
180 app->add_option("-c, --count", effecterCount,
181 "The number of individual sets of effecter information")
182 ->required();
183 app->add_option(
George Liud6649362019-11-27 19:06:51 +0800184 "-d,--data", effecterData,
George Liuba4c1fb2020-02-05 14:13:30 +0800185 "Set effecter state data\n"
186 "eg: requestSet0 effecterState0 noChange1 dummyState1 ...")
187 ->required();
George Liud6649362019-11-27 19:06:51 +0800188 }
189
190 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
191 {
192 std::vector<uint8_t> requestMsg(
193 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES);
194 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
195
George Liuba4c1fb2020-02-05 14:13:30 +0800196 if (effecterCount > maxEffecterCount ||
197 effecterCount < minEffecterCount)
George Liud6649362019-11-27 19:06:51 +0800198 {
George Liuba4c1fb2020-02-05 14:13:30 +0800199 std::cerr << "Request Message Error: effecterCount size "
200 << effecterCount << "is invalid\n";
George Liud6649362019-11-27 19:06:51 +0800201 auto rc = PLDM_ERROR_INVALID_DATA;
202 return {rc, requestMsg};
203 }
204
George Liuba4c1fb2020-02-05 14:13:30 +0800205 if (effecterData.size() > maxEffecterDataSize)
George Liud6649362019-11-27 19:06:51 +0800206 {
George Liuba4c1fb2020-02-05 14:13:30 +0800207 std::cerr << "Request Message Error: effecterData size "
208 << effecterData.size() << "is invalid\n";
209 auto rc = PLDM_ERROR_INVALID_DATA;
210 return {rc, requestMsg};
211 }
212
213 auto stateField = parseEffecterData(effecterData, effecterCount);
214 if (!stateField)
215 {
216 std::cerr << "Failed to parse effecter data, effecterCount size "
217 << effecterCount << "\n";
George Liud6649362019-11-27 19:06:51 +0800218 auto rc = PLDM_ERROR_INVALID_DATA;
219 return {rc, requestMsg};
220 }
221
222 auto rc = encode_set_state_effecter_states_req(
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600223 instanceId, effecterId, effecterCount, stateField->data(), request);
George Liud6649362019-11-27 19:06:51 +0800224 return {rc, requestMsg};
225 }
226
227 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
228 {
229 uint8_t completionCode = 0;
230 auto rc = decode_set_state_effecter_states_resp(
231 responsePtr, payloadLength, &completionCode);
232
233 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
234 {
235 std::cerr << "Response Message Error: "
George Liuba4c1fb2020-02-05 14:13:30 +0800236 << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
George Liud6649362019-11-27 19:06:51 +0800237 return;
238 }
239
240 std::cout << "SetStateEffecterStates: SUCCESS" << std::endl;
241 }
242
243 private:
George Liuba4c1fb2020-02-05 14:13:30 +0800244 uint16_t effecterId;
245 uint8_t effecterCount;
George Liud6649362019-11-27 19:06:51 +0800246 std::vector<uint8_t> effecterData;
247};
248
249void registerCommand(CLI::App& app)
250{
251 auto platform = app.add_subcommand("platform", "platform type command");
252 platform->require_subcommand(1);
253
254 auto getPDR =
255 platform->add_subcommand("GetPDR", "get platform descriptor records");
256 commands.push_back(std::make_unique<GetPDR>("platform", "getPDR", getPDR));
257
258 auto setStateEffecterStates = platform->add_subcommand(
259 "SetStateEffecterStates", "set effecter states");
260 commands.push_back(std::make_unique<SetStateEffecter>(
261 "platform", "setStateEffecterStates", setStateEffecterStates));
262}
263
264} // namespace platform
265} // namespace pldmtool