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