blob: e256bc8d9354d6d3451dca20129811a751544086 [file] [log] [blame]
Jayashankar Padathdb124362021-01-28 21:12:34 -06001#include "dbus_to_file_handler.hpp"
2
3#include "libpldm/requester/pldm.h"
4#include "oem/ibm/libpldm/file_io.h"
5
6#include "common/utils.hpp"
7
8namespace pldm
9{
10namespace requester
11{
12namespace oem_ibm
13{
14
15using namespace pldm::utils;
16using namespace sdbusplus::bus::match::rules;
17
18static constexpr auto resDumpObjPath =
19 "/xyz/openbmc_project/dump/resource/entry";
20static constexpr auto resDumpEntry = "com.ibm.Dump.Entry.Resource";
21static constexpr auto resDumpProgressIntf =
22 "xyz.openbmc_project.Common.Progress";
23static constexpr auto resDumpStatus =
24 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed";
25
26DbusToFileHandler::DbusToFileHandler(
27 int mctp_fd, uint8_t mctp_eid, dbus_api::Requester* requester,
28 sdbusplus::message::object_path resDumpCurrentObjPath) :
29 mctp_fd(mctp_fd),
30 mctp_eid(mctp_eid), requester(requester),
31 resDumpCurrentObjPath(resDumpCurrentObjPath)
32{}
33
34void DbusToFileHandler::sendNewFileAvailableCmd(uint64_t fileSize)
35{
36 if (requester == NULL)
37 {
38 std::cerr << "Failed to send resource dump parameters as requester is "
39 "not set";
40 pldm::utils::reportError(
41 "xyz.openbmc_project.bmc.pldm.InternalFailure");
42 return;
43 }
44 auto instanceId = requester->getInstanceId(mctp_eid);
45 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
46 PLDM_NEW_FILE_REQ_BYTES + fileSize);
47 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
48 // Need to revisit this logic at the time of multiple resource dump support
49 uint32_t fileHandle = 1;
50
51 auto rc =
52 encode_new_file_req(instanceId, PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS,
53 fileHandle, fileSize, request);
54 if (rc != PLDM_SUCCESS)
55 {
56 requester->markFree(mctp_eid, instanceId);
57 std::cerr << "Failed to encode_new_file_req, rc = " << rc << std::endl;
58 return;
59 }
60
61 uint8_t* responseMsg = nullptr;
62 size_t responseMsgSize{};
63
64 auto requesterRc =
65 pldm_send_recv(mctp_eid, mctp_fd, requestMsg.data(), requestMsg.size(),
66 &responseMsg, &responseMsgSize);
67
68 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg,
69 std::free};
70
71 requester->markFree(mctp_eid, instanceId);
72 bool isDecodeNewFileRespFailed = false;
73 if (requesterRc != PLDM_REQUESTER_SUCCESS)
74 {
75 std::cerr << "Failed to send resource dump parameters, rc = "
76 << requesterRc << std::endl;
77 }
78 else
79 {
80 uint8_t completionCode{};
81 auto responsePtr =
82 reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get());
83
84 rc = decode_new_file_resp(responsePtr, PLDM_NEW_FILE_RESP_BYTES,
85 &completionCode);
86
87 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
88 {
89 std::cerr << "Failed to decode_new_file_resp: "
90 << "rc=" << rc
91 << ", cc=" << static_cast<unsigned>(completionCode)
92 << std::endl;
93 isDecodeNewFileRespFailed = true;
94 }
95 }
96
97 if ((requesterRc != PLDM_REQUESTER_SUCCESS) || (isDecodeNewFileRespFailed))
98 {
99 pldm::utils::reportError(
100 "xyz.openbmc_project.bmc.pldm.InternalFailure");
101
102 PropertyValue value{resDumpStatus};
103 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf,
104 "Status", "string"};
105 try
106 {
107 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
108 }
109 catch (const std::exception& e)
110 {
111 std::cerr << "failed to set resource dump operation status, "
112 "ERROR="
113 << e.what() << "\n";
114 }
115 }
116}
117
118void DbusToFileHandler::processNewResourceDump(
119 const std::string& vspString, const std::string& resDumpReqPass)
120{
121 // This needs special handling in later point of time. Resource dump without
122 // the vsp string is supposed to be a non-disruptive system dump.
123 if (vspString.empty())
124 {
125 std::cerr << "Empty vsp string"
126 << "\n";
127 PropertyValue value{resDumpStatus};
128 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf,
129 "Status", "string"};
130 try
131 {
132 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
133 }
134 catch (const std::exception& e)
135 {
136 std::cerr << "failed to set resource dump operation status, "
137 "ERROR="
138 << e.what() << "\n";
139 }
140 return;
141 }
142
143 namespace fs = std::filesystem;
144 const fs::path resDumpDirPath = "/var/lib/pldm/resourcedump";
145
146 if (!fs::exists(resDumpDirPath))
147 {
148 fs::create_directories(resDumpDirPath);
149 }
150
151 // Need to reconsider this logic to set the value as "1" when we have the
152 // support to handle multiple resource dumps
153 fs::path resDumpFilePath = resDumpDirPath / "1";
154
155 std::ofstream fileHandle;
156 fileHandle.open(resDumpFilePath, std::ios::out | std::ofstream::binary);
157
158 if (!fileHandle)
159 {
160 std::cerr << "resource dump file open error: " << resDumpFilePath
161 << "\n";
162 PropertyValue value{resDumpStatus};
163 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf,
164 "Status", "string"};
165 try
166 {
167 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
168 }
169 catch (const std::exception& e)
170 {
171 std::cerr << "failed to set resource dump operation status, "
172 "ERROR="
173 << e.what() << "\n";
174 }
175 return;
176 }
177
178 // Fill up the file with resource dump parameters and respective sizes
179 auto fileFunc = [&fileHandle](auto& paramBuf) {
180 uint32_t paramSize = paramBuf.size();
181 fileHandle.write((char*)&paramSize, sizeof(paramSize));
182 fileHandle << paramBuf;
183 };
184 fileFunc(vspString);
185 fileFunc(resDumpReqPass);
186
187 fileHandle.close();
188 size_t fileSize = fs::file_size(resDumpFilePath);
189
190 sendNewFileAvailableCmd(fileSize);
191}
192
Varsha Kaverappa219ace92021-04-01 02:50:11 -0500193void DbusToFileHandler::newCsrFileAvailable(const std::string& csr,
194 const std::string fileHandle)
195{
196 namespace fs = std::filesystem;
197 std::string dirPath = "/var/lib/ibm/bmcweb";
198 const fs::path certDirPath = dirPath;
199
200 if (!fs::exists(certDirPath))
201 {
202 fs::create_directories(certDirPath);
203 fs::permissions(certDirPath,
204 fs::perms::others_read | fs::perms::owner_write);
205 }
206
207 fs::path certFilePath = certDirPath / ("CSR_" + fileHandle);
208 std::ofstream certFile;
209
210 certFile.open(certFilePath, std::ios::out | std::ofstream::binary);
211
212 if (!certFile)
213 {
214 std::cerr << "cert file open error: " << certFilePath << "\n";
215 return;
216 }
217
218 // Add csr to file
219 certFile << csr << std::endl;
220
221 certFile.close();
222 uint32_t fileSize = fs::file_size(certFilePath);
223
224 newFileAvailableSendToHost(fileSize, (uint32_t)stoi(fileHandle),
225 PLDM_FILE_TYPE_CERT_SIGNING_REQUEST);
226}
227
228void DbusToFileHandler::newFileAvailableSendToHost(const uint32_t fileSize,
229 const uint32_t fileHandle,
230 const uint16_t type)
231{
232 if (requester == NULL)
233 {
234 std::cerr << "Failed to send csr to host.";
235 pldm::utils::reportError(
236 "xyz.openbmc_project.bmc.pldm.InternalFailure");
237 return;
238 }
239 auto instanceId = requester->getInstanceId(mctp_eid);
240 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
241 PLDM_NEW_FILE_REQ_BYTES);
242 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
243
244 auto rc =
245 encode_new_file_req(instanceId, type, fileHandle, fileSize, request);
246 if (rc != PLDM_SUCCESS)
247 {
248 requester->markFree(mctp_eid, instanceId);
249 std::cerr << "Failed to encode_new_file_req, rc = " << rc << std::endl;
250 return;
251 }
252
253 uint8_t* responseMsg = nullptr;
254 size_t responseMsgSize{};
255
256 auto requesterRc =
257 pldm_send_recv(mctp_eid, mctp_fd, requestMsg.data(), requestMsg.size(),
258 &responseMsg, &responseMsgSize);
259
260 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg,
261 std::free};
262
263 requester->markFree(mctp_eid, instanceId);
264 bool isDecodeNewFileRespFailed = false;
265 if (requesterRc != PLDM_REQUESTER_SUCCESS)
266 {
267 std::cerr << "Failed to send file to host, rc = " << requesterRc
268 << std::endl;
269 }
270 else
271 {
272 uint8_t completionCode{};
273 auto responsePtr =
274 reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get());
275
276 rc = decode_new_file_resp(responsePtr, PLDM_NEW_FILE_RESP_BYTES,
277 &completionCode);
278
279 std::vector<uint8_t> responseMsgVec;
280 responseMsgVec.resize(responseMsgSize);
281 memcpy(responseMsgVec.data(), responseMsg, responseMsgVec.size());
282
283 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
284 {
285 std::cerr << "Failed to decode_new_file_resp: "
286 << "rc=" << rc
287 << ", cc=" << static_cast<unsigned>(completionCode)
288 << std::endl;
289 isDecodeNewFileRespFailed = true;
290 }
291 }
292 if ((requesterRc != PLDM_REQUESTER_SUCCESS) || (isDecodeNewFileRespFailed))
293 {
294 pldm::utils::reportError(
295 "xyz.openbmc_project.bmc.pldm.InternalFailure");
296 }
297}
298
Jayashankar Padathdb124362021-01-28 21:12:34 -0600299} // namespace oem_ibm
300} // namespace requester
301} // namespace pldm