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