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