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