xref: /openbmc/pldm/pldmtool/oem/ibm/pldm_oem_ibm.cpp (revision 96a3a048)
1 #include "pldm_oem_ibm.hpp"
2 
3 #include "oem/ibm/libpldm/file_io.h"
4 #include "oem/ibm/libpldm/host.h"
5 #include "pldm_types.h"
6 
7 #include "../../pldm_cmd_helper.hpp"
8 
9 #include <endian.h>
10 
11 #include <iostream>
12 #include <string>
13 namespace pldmtool
14 {
15 
16 namespace oem_ibm
17 {
18 namespace
19 {
20 
21 using namespace pldmtool::helper;
22 
23 std::vector<std::unique_ptr<CommandInterface>> commands;
24 
25 const std::map<const char*, pldm_fileio_table_type> pldmFileIOTableTypes{
26     {"AttributeTable", PLDM_FILE_ATTRIBUTE_TABLE},
27 };
28 
29 constexpr uint8_t CHKSUM_PADDING = 8;
30 
31 } // namespace
32 
33 class GetAlertStatus : public CommandInterface
34 {
35   public:
36     ~GetAlertStatus() = default;
37     GetAlertStatus() = delete;
38     GetAlertStatus(const GetAlertStatus&) = delete;
39     GetAlertStatus(GetAlertStatus&&) = default;
40     GetAlertStatus& operator=(const GetAlertStatus&) = delete;
41     GetAlertStatus& operator=(GetAlertStatus&&) = default;
42 
43     explicit GetAlertStatus(const char* type, const char* name, CLI::App* app) :
44         CommandInterface(type, name, app)
45     {
46         app->add_option(
47                "-i, --id", versionId,
48                "Version of the command/response format. 0x00 for this format")
49             ->required();
50     }
51 
52     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
53     {
54         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
55                                         PLDM_GET_ALERT_STATUS_REQ_BYTES);
56         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
57 
58         auto rc = encode_get_alert_status_req(instanceId, versionId, request,
59                                               PLDM_GET_ALERT_STATUS_REQ_BYTES);
60         return {rc, requestMsg};
61     }
62 
63     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
64     {
65         uint8_t completionCode = 0;
66         uint32_t rack_entry = 0;
67         uint32_t pri_cec_node = 0;
68         auto rc = decode_get_alert_status_resp(responsePtr, payloadLength,
69                                                &completionCode, &rack_entry,
70                                                &pri_cec_node);
71 
72         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
73         {
74             std::cerr << "Response Message Error: "
75                       << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
76             return;
77         }
78 
79         std::stringstream re;
80         std::stringstream pcn;
81         ordered_json data;
82         re << "0x" << std::setfill('0') << std::setw(8) << std::hex
83            << (int)rack_entry;
84         pcn << "0x" << std::setfill('0') << std::setw(8) << std::hex
85             << (int)pri_cec_node;
86         data["rack entry"] = re.str();
87         data["pri cec node"] = pcn.str();
88         pldmtool::helper::DisplayInJson(data);
89     }
90 
91   private:
92     uint8_t versionId;
93 };
94 
95 class GetFileTable : public CommandInterface
96 {
97   public:
98     ~GetFileTable() = default;
99     GetFileTable() = delete;
100     GetFileTable(const GetFileTable&) = delete;
101     GetFileTable(GetFileTable&&) = default;
102     GetFileTable& operator=(const GetFileTable&) = delete;
103     GetFileTable& operator=(GetFileTable&&) = default;
104 
105     using CommandInterface::CommandInterface;
106 
107     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
108     {
109 
110         return {PLDM_ERROR, {}};
111     }
112 
113     void parseResponseMsg(pldm_msg*, size_t) override
114     {}
115     void exec()
116     {
117         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
118                                         PLDM_GET_FILE_TABLE_REQ_BYTES);
119 
120         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
121 
122         auto rc = encode_get_file_table_req(instanceId, 0, PLDM_GET_FIRSTPART,
123                                             0, request);
124         if (rc != PLDM_SUCCESS)
125         {
126             std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl;
127             return;
128         }
129 
130         std::vector<uint8_t> responseMsg;
131         rc = pldmSendRecv(requestMsg, responseMsg);
132         if (rc != PLDM_SUCCESS)
133         {
134             std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl;
135             return;
136         }
137 
138         uint8_t cc = 0;
139         uint8_t transferFlag = 0;
140         uint32_t nextTransferHandle = 0;
141         size_t fileTableDataLength = 0;
142         uint8_t table_data_start_offset;
143         auto responsePtr =
144             reinterpret_cast<struct pldm_msg*>(responseMsg.data());
145         auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr);
146 
147         rc = decode_get_file_table_resp(
148             responsePtr, payloadLength, &cc, &nextTransferHandle, &transferFlag,
149             &table_data_start_offset, &fileTableDataLength);
150 
151         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
152         {
153             std::cerr << "Response Message Error: "
154                       << ", rc=" << rc << ", cc=" << (int)cc << std::endl;
155             return;
156         }
157 
158         auto tableData = reinterpret_cast<uint8_t*>((responsePtr->payload) +
159                                                     table_data_start_offset);
160         printFileAttrTable(tableData, fileTableDataLength);
161     }
162 
163     void printFileAttrTable(uint8_t* data, size_t length)
164     {
165         if (data == NULL || length == 0)
166         {
167             return;
168         }
169 
170         auto startptr = data;
171         auto endptr = startptr + length - CHKSUM_PADDING;
172         ordered_json kwVal;
173 
174         while (startptr < endptr)
175         {
176             ordered_json fdata;
177             auto filetableData =
178                 reinterpret_cast<pldm_file_attr_table_entry*>(startptr);
179             fdata["FileHandle"] = std::to_string(filetableData->file_handle);
180             startptr += sizeof(filetableData->file_handle);
181 
182             auto nameLength = filetableData->file_name_length;
183             fdata["FileNameLength"] = nameLength;
184             startptr += sizeof(filetableData->file_name_length);
185 
186             fdata["FileName"] = (std::string(
187                 reinterpret_cast<char const*>(startptr), nameLength));
188             startptr += nameLength;
189 
190             auto fileSize = *(reinterpret_cast<uint32_t*>(startptr));
191             fdata["FileSize"] = le32toh(fileSize);
192             startptr += sizeof(fileSize);
193 
194             auto fileTraits =
195                 (*(reinterpret_cast<bitfield32_t*>(startptr))).value;
196             fdata["FileTraits"] = le32toh(fileTraits);
197             startptr += sizeof(fileTraits);
198             kwVal.emplace_back(fdata);
199         }
200         pldmtool::helper::DisplayInJson(kwVal);
201     }
202 };
203 
204 void registerCommand(CLI::App& app)
205 {
206     auto oem_ibm = app.add_subcommand("oem-ibm", "oem type command");
207     oem_ibm->require_subcommand(1);
208 
209     auto getAlertStatus = oem_ibm->add_subcommand(
210         "GetAlertStatus", "get alert status descriptor");
211     commands.push_back(std::make_unique<GetAlertStatus>(
212         "oem_ibm", "getAlertStatus", getAlertStatus));
213 
214     auto getFileTable =
215         oem_ibm->add_subcommand("GetFileTable", "get file table");
216 
217     commands.push_back(std::make_unique<GetFileTable>("oem_ibm", "getFileTable",
218                                                       getFileTable));
219 }
220 } // namespace oem_ibm
221 } // namespace pldmtool
222