1 #include "pldm_base_cmd.hpp"
2
3 #include "pldm_cmd_helper.hpp"
4
5 #include <libpldm/utils.h>
6
7 #ifdef OEM_IBM
8 #include <libpldm/oem/ibm/file_io.h>
9 #include <libpldm/oem/ibm/host.h>
10 #endif
11
12 #include <string>
13
14 namespace pldmtool
15 {
16
17 namespace base
18 {
19
20 namespace
21 {
22
23 using namespace pldmtool::helper;
24
25 std::vector<std::unique_ptr<CommandInterface>> commands;
26 const std::map<const char*, pldm_supported_types> pldmTypes{
27 {"base", PLDM_BASE}, {"platform", PLDM_PLATFORM},
28 {"bios", PLDM_BIOS}, {"fru", PLDM_FRU},
29 #ifdef OEM_IBM
30 {"oem-ibm", PLDM_OEM},
31 #endif
32 };
33
34 const std::map<const char*, pldm_supported_commands> pldmBaseCmds{
35 {"SetTID", PLDM_SET_TID},
36 {"GetTID", PLDM_GET_TID},
37 {"GetPLDMVersion", PLDM_GET_PLDM_VERSION},
38 {"GetPLDMTypes", PLDM_GET_PLDM_TYPES},
39 {"GetPLDMCommands", PLDM_GET_PLDM_COMMANDS},
40 {"SelectPLDMVersion", PLDM_SELECT_PLDM_VERSION},
41 {"NegotiateTransferParameters", PLDM_NEGOTIATE_TRANSFER_PARAMETERS},
42 {"MultipartSend", PLDM_MULTIPART_SEND},
43 {"MultipartReceive", PLDM_MULTIPART_RECEIVE},
44 {"GetMultipartTransferSupport", PLDM_GET_MULTIPART_TRANSFER_SUPPORT}};
45
46 const std::map<const char*, pldm_bios_commands> pldmBiosCmds{
47 {"GetBIOSTable", PLDM_GET_BIOS_TABLE},
48 {"SetBIOSTable", PLDM_SET_BIOS_TABLE},
49 {"SetBIOSAttributeCurrentValue", PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE},
50 {"GetBIOSAttributeCurrentValueByHandle",
51 PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE},
52 {"GetDateTime", PLDM_GET_DATE_TIME},
53 {"SetDateTime", PLDM_SET_DATE_TIME}};
54
55 const std::map<const char*, pldm_platform_commands> pldmPlatformCmds{
56 {"GetTerminusUID", PLDM_GET_TERMINUS_UID},
57 {"SetEventReceiver", PLDM_SET_EVENT_RECEIVER},
58 {"GetEventReceiver", PLDM_GET_EVENT_RECEIVER},
59 {"PlatformEventMessage", PLDM_PLATFORM_EVENT_MESSAGE},
60 {"PollForPlatformEventMessage", PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE},
61 {"EventMessageSupported", PLDM_EVENT_MESSAGE_SUPPORTED},
62 {"EventMessageBufferSize", PLDM_EVENT_MESSAGE_BUFFER_SIZE},
63 {"SetNumericSensorEnable", PLDM_SET_NUMERIC_SENSOR_ENABLE},
64 {"GetSensorReading", PLDM_GET_SENSOR_READING},
65 {"GetSensorThresholds", PLDM_GET_SENSOR_THRESHOLDS},
66 {"SetSensorThresholds", PLDM_SET_SENSOR_THRESHOLDS},
67 {"RestoreSensorThresholds", PLDM_RESTORE_SENSOR_THRESHOLDS},
68 {"GetSensorHysteresis", PLDM_GET_SENSOR_HYSTERESIS},
69 {"SetSensorHysteresis", PLDM_SET_SENSOR_HYSTERESIS},
70 {"InitNumericSensor", PLDM_INIT_NUMERIC_SENSOR},
71 {"SetStateSensorEnables", PLDM_SET_STATE_SENSOR_ENABLES},
72 {"GetStateSensorReadings", PLDM_GET_STATE_SENSOR_READINGS},
73 {"InitStateSensor", PLDM_INIT_STATE_SENSOR},
74 {"SetNumericEffecterEnable", PLDM_SET_NUMERIC_EFFECTER_ENABLE},
75 {"SetNumericEffecterValue", PLDM_SET_NUMERIC_EFFECTER_VALUE},
76 {"GetNumericEffecterValue", PLDM_GET_NUMERIC_EFFECTER_VALUE},
77 {"SetStateEffecterEnables", PLDM_SET_STATE_EFFECTER_ENABLES},
78 {"SetStateEffecterStates", PLDM_SET_STATE_EFFECTER_STATES},
79 {"GetStateEffecterStates", PLDM_GET_STATE_EFFECTER_STATES},
80 {"GetPLDMEventLogInfo", PLDM_GET_PLDM_EVENT_LOG_INFO},
81 {"EnablePLDMEventLogging", PLDM_ENABLE_PLDM_EVENT_LOGGING},
82 {"ClearPLDMEventLog", PLDM_CLEAR_PLDM_EVENT_LOG},
83 {"GetPLDMEventLogTimestamp", PLDM_GET_PLDM_EVENT_LOG_TIMESTAMP},
84 {"SetPLDMEventLogTimestamp", PLDM_SET_PLDM_EVENT_LOG_TIMESTAMP},
85 {"ReadPLDMEventLog", PLDM_READ_PLDM_EVENT_LOG},
86 {"GetPLDMEventLogPolicyInfo", PLDM_GET_PLDM_EVENT_LOG_POLICY_INFO},
87 {"SetPLDMEventLogPolicy", PLDM_SET_PLDM_EVENT_LOG_POLICY},
88 {"FindPLDMEventLogEntry", PLDM_FIND_PLDM_EVENT_LOG_ENTRY},
89 {"GetPDRRepositoryInfo", PLDM_GET_PDR_REPOSITORY_INFO},
90 {"GetPDR", PLDM_GET_PDR},
91 {"FindPDR", PLDM_FIND_PDR},
92 {"RunInitAgent", PLDM_RUN_INIT_AGENT},
93 {"GetPDRRepositorySignature", PLDM_GET_PDR_REPOSITORY_SIGNATURE}};
94
95 const std::map<const char*, pldm_fru_commands> pldmFruCmds{
96 {"GetFRURecordTableMetadata", PLDM_GET_FRU_RECORD_TABLE_METADATA},
97 {"GetFRURecordTable", PLDM_GET_FRU_RECORD_TABLE},
98 {"GetFRURecordByOption", PLDM_GET_FRU_RECORD_BY_OPTION}};
99
100 #ifdef OEM_IBM
101 const std::map<const char*, pldm_host_commands> pldmIBMHostCmds{
102 {"GetAlertStatus", PLDM_HOST_GET_ALERT_STATUS}};
103
104 const std::map<const char*, pldm_fileio_commands> pldmIBMFileIOCmds{
105 {"GetFileTable", PLDM_GET_FILE_TABLE},
106 {"ReadFile", PLDM_READ_FILE},
107 {"WriteFile", PLDM_WRITE_FILE},
108 {"ReadFileInToMemory", PLDM_READ_FILE_INTO_MEMORY},
109 {"WriteFileFromMemory", PLDM_WRITE_FILE_FROM_MEMORY},
110 {"ReadFileByTypeIntoMemory", PLDM_READ_FILE_BY_TYPE_INTO_MEMORY},
111 {"WriteFileByTypeFromMemory", PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY},
112 {"NewFileAvailable", PLDM_NEW_FILE_AVAILABLE},
113 {"ReadFileByType", PLDM_READ_FILE_BY_TYPE},
114 {"WriteFileByType", PLDM_WRITE_FILE_BY_TYPE},
115 {"FileAck", PLDM_FILE_ACK}};
116 #endif
117
118 } // namespace
119
120 class GetPLDMTypes : public CommandInterface
121 {
122 public:
123 ~GetPLDMTypes() = default;
124 GetPLDMTypes() = delete;
125 GetPLDMTypes(const GetPLDMTypes&) = delete;
126 GetPLDMTypes(GetPLDMTypes&&) = default;
127 GetPLDMTypes& operator=(const GetPLDMTypes&) = delete;
128 GetPLDMTypes& operator=(GetPLDMTypes&&) = delete;
129
130 using CommandInterface::CommandInterface;
131
createRequestMsg()132 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
133 {
134 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
135 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
136 auto rc = encode_get_types_req(instanceId, request);
137 return {rc, requestMsg};
138 }
139
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)140 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
141 {
142 uint8_t cc = 0;
143 std::vector<bitfield8_t> types(8);
144 auto rc = decode_get_types_resp(responsePtr, payloadLength, &cc,
145 types.data());
146 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
147 {
148 std::cerr << "Response Message Error: "
149 << "rc=" << rc << ",cc=" << (int)cc << "\n";
150 return;
151 }
152
153 printPldmTypes(types);
154 }
155
156 private:
printPldmTypes(std::vector<bitfield8_t> & types)157 void printPldmTypes(std::vector<bitfield8_t>& types)
158 {
159 ordered_json data;
160 ordered_json jarray;
161 for (int i = 0; i < PLDM_MAX_TYPES; i++)
162 {
163 bitfield8_t b = types[i / 8];
164 if (b.byte & (1 << i % 8))
165 {
166 auto it = std::find_if(
167 pldmTypes.begin(), pldmTypes.end(),
168 [i](const auto& typePair) { return typePair.second == i; });
169 if (it != pldmTypes.end())
170 {
171 jarray["PLDM Type"] = it->first;
172 jarray["PLDM Type Code"] = i;
173 data.emplace_back(jarray);
174 }
175 }
176 }
177 pldmtool::helper::DisplayInJson(data);
178 }
179 };
180
181 class GetPLDMVersion : public CommandInterface
182 {
183 public:
184 ~GetPLDMVersion() = default;
185 GetPLDMVersion() = delete;
186 GetPLDMVersion(const GetPLDMVersion&) = delete;
187 GetPLDMVersion(GetPLDMVersion&&) = default;
188 GetPLDMVersion& operator=(const GetPLDMVersion&) = delete;
189 GetPLDMVersion& operator=(GetPLDMVersion&&) = delete;
190
GetPLDMVersion(const char * type,const char * name,CLI::App * app)191 explicit GetPLDMVersion(const char* type, const char* name, CLI::App* app) :
192 CommandInterface(type, name, app)
193 {
194 app->add_option("-t,--type", pldmType, "pldm supported type")
195 ->required()
196 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case));
197 }
createRequestMsg()198 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
199 {
200 std::vector<uint8_t> requestMsg(
201 sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES);
202 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
203
204 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
205 pldmType, request);
206 return {rc, requestMsg};
207 }
208
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)209 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
210 {
211 uint8_t cc = 0, transferFlag = 0;
212 uint32_t transferHandle = 0;
213 ver32_t version;
214 auto rc =
215 decode_get_version_resp(responsePtr, payloadLength, &cc,
216 &transferHandle, &transferFlag, &version);
217 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
218 {
219 std::cerr << "Response Message Error: "
220 << "rc=" << rc << ",cc=" << (int)cc << "\n";
221 return;
222 }
223 char buffer[16] = {0};
224 ver2str(&version, buffer, sizeof(buffer));
225 ordered_json data;
226 auto it = std::find_if(
227 pldmTypes.begin(), pldmTypes.end(),
228 [&](const auto& typePair) { return typePair.second == pldmType; });
229
230 if (it != pldmTypes.end())
231 {
232 data["Response"] = buffer;
233 }
234 pldmtool::helper::DisplayInJson(data);
235 }
236
237 private:
238 pldm_supported_types pldmType;
239 };
240
241 class GetTID : public CommandInterface
242 {
243 public:
244 ~GetTID() = default;
245 GetTID() = delete;
246 GetTID(const GetTID&) = delete;
247 GetTID(GetTID&&) = default;
248 GetTID& operator=(const GetTID&) = delete;
249 GetTID& operator=(GetTID&&) = delete;
250
251 using CommandInterface::CommandInterface;
252
createRequestMsg()253 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
254 {
255 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
256 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
257 auto rc = encode_get_tid_req(instanceId, request);
258 return {rc, requestMsg};
259 }
260
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)261 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
262 {
263 uint8_t cc = 0;
264 uint8_t tid = 0;
265 std::vector<bitfield8_t> types(8);
266 auto rc = decode_get_tid_resp(responsePtr, payloadLength, &cc, &tid);
267 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
268 {
269 std::cerr << "Response Message Error: "
270 << "rc=" << rc << ",cc=" << (int)cc << "\n";
271 return;
272 }
273 ordered_json data;
274 data["Response"] = static_cast<uint32_t>(tid);
275 pldmtool::helper::DisplayInJson(data);
276 }
277 };
278
279 class GetPLDMCommands : public CommandInterface
280 {
281 public:
282 ~GetPLDMCommands() = default;
283 GetPLDMCommands() = delete;
284 GetPLDMCommands(const GetPLDMCommands&) = delete;
285 GetPLDMCommands(GetPLDMCommands&&) = default;
286 GetPLDMCommands& operator=(const GetPLDMCommands&) = delete;
287 GetPLDMCommands& operator=(GetPLDMCommands&&) = delete;
288
GetPLDMCommands(const char * type,const char * name,CLI::App * app)289 explicit GetPLDMCommands(const char* type, const char* name,
290 CLI::App* app) : CommandInterface(type, name, app)
291 {
292 app->add_option("-t,--type", pldmType, "pldm supported type")
293 ->required()
294 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case));
295 app->add_option(
296 "-d,--data", inputVersion,
297 "Set PLDM type version. Which is got from GetPLDMVersion\n"
298 "eg: version 1.1.0 then data will be `0xf1 0xf1 0xf0 0x00`");
299 }
300
createRequestMsg()301 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
302 {
303 std::vector<uint8_t> requestMsg(
304 sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES);
305 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
306 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
307 if (inputVersion.size() != 0)
308 {
309 if (inputVersion.size() != 4)
310 {
311 std::cerr << "Invalid version format. "
312 << "\n";
313 }
314 else
315 {
316 version.major = inputVersion[3];
317 version.minor = inputVersion[2];
318 version.update = inputVersion[1];
319 version.alpha = inputVersion[0];
320 }
321 }
322 auto rc =
323 encode_get_commands_req(instanceId, pldmType, version, request);
324 return {rc, requestMsg};
325 }
326
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)327 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
328 {
329 uint8_t cc = 0;
330 std::vector<bitfield8_t> cmdTypes(32);
331 auto rc = decode_get_commands_resp(responsePtr, payloadLength, &cc,
332 cmdTypes.data());
333 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
334 {
335 std::cerr << "Response Message Error: "
336 << "rc=" << rc << ",cc=" << (int)cc << "\n";
337 return;
338 }
339 printPldmCommands(cmdTypes, pldmType);
340 }
341
342 private:
343 pldm_supported_types pldmType;
344 std::vector<uint8_t> inputVersion;
345
346 template <typename CommandMap>
printCommand(CommandMap & commandMap,int i,ordered_json & jarray)347 void printCommand(CommandMap& commandMap, int i, ordered_json& jarray)
348 {
349 auto it = std::find_if(
350 commandMap.begin(), commandMap.end(),
351 [i](const auto& typePair) { return typePair.second == i; });
352 if (it != commandMap.end())
353 {
354 jarray["PLDM Command Code"] = i;
355 jarray["PLDM Command"] = it->first;
356 }
357 }
358
printPldmCommands(std::vector<bitfield8_t> & cmdTypes,pldm_supported_types pldmType)359 void printPldmCommands(std::vector<bitfield8_t>& cmdTypes,
360 pldm_supported_types pldmType)
361 {
362 ordered_json output;
363 for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++)
364 {
365 ordered_json cmdinfo;
366 bitfield8_t b = cmdTypes[i / 8];
367 if (b.byte & (1 << i % 8))
368 {
369 switch (pldmType)
370 {
371 case PLDM_BASE:
372 printCommand(pldmBaseCmds, i, cmdinfo);
373 break;
374 case PLDM_PLATFORM:
375 printCommand(pldmPlatformCmds, i, cmdinfo);
376 break;
377 case PLDM_BIOS:
378 printCommand(pldmBiosCmds, i, cmdinfo);
379 break;
380 case PLDM_FRU:
381 printCommand(pldmFruCmds, i, cmdinfo);
382 break;
383 case PLDM_OEM:
384 #ifdef OEM_IBM
385 printCommand(pldmIBMHostCmds, i, cmdinfo);
386 printCommand(pldmIBMFileIOCmds, i, cmdinfo);
387 #endif
388 break;
389 default:
390 break;
391 }
392 output.emplace_back(cmdinfo);
393 }
394 }
395 pldmtool::helper::DisplayInJson(output);
396 }
397 };
398
registerCommand(CLI::App & app)399 void registerCommand(CLI::App& app)
400 {
401 auto base = app.add_subcommand("base", "base type command");
402 base->require_subcommand(1);
403
404 auto getPLDMTypes =
405 base->add_subcommand("GetPLDMTypes", "get pldm supported types");
406 commands.push_back(
407 std::make_unique<GetPLDMTypes>("base", "GetPLDMTypes", getPLDMTypes));
408
409 auto getPLDMVersion =
410 base->add_subcommand("GetPLDMVersion", "get version of a certain type");
411 commands.push_back(std::make_unique<GetPLDMVersion>(
412 "base", "GetPLDMVersion", getPLDMVersion));
413
414 auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)");
415 commands.push_back(std::make_unique<GetTID>("base", "GetTID", getPLDMTID));
416
417 auto getPLDMCommands = base->add_subcommand(
418 "GetPLDMCommands", "get supported commands of pldm type");
419 commands.push_back(std::make_unique<GetPLDMCommands>(
420 "base", "GetPLDMCommands", getPLDMCommands));
421 }
422
423 } // namespace base
424 } // namespace pldmtool
425