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