blob: 458697ba4a6694d32f54913eb1270ef9a23de633 [file] [log] [blame]
Sampa Misra854e61f2019-08-22 04:36:47 -05001#include "file_io_type_pel.hpp"
2
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05003#include "common/utils.hpp"
Sampa Misra854e61f2019-08-22 04:36:47 -05004#include "xyz/openbmc_project/Common/error.hpp"
5
George Liuc453e162022-12-21 17:16:23 +08006#include <libpldm/base.h>
Andrew Jeffery21f128d2024-01-15 15:34:26 +10307#include <libpldm/oem/ibm/file_io.h>
Sampa Misra854e61f2019-08-22 04:36:47 -05008#include <stdint.h>
9#include <systemd/sd-bus.h>
10#include <unistd.h>
11
Matt Spinlerc180bc82023-09-12 09:29:54 -050012#include <org/open_power/Logging/PEL/server.hpp>
Riya Dixit49cfb132023-03-02 04:26:53 -060013#include <phosphor-logging/lg2.hpp>
George Liu6492f522020-06-16 10:34:05 +080014#include <sdbusplus/server.hpp>
15#include <xyz/openbmc_project/Logging/Entry/server.hpp>
16
Sampa Misra854e61f2019-08-22 04:36:47 -050017#include <exception>
18#include <filesystem>
Matt Spinler39d8c7a2020-03-05 11:28:59 -060019#include <fstream>
Sampa Misra854e61f2019-08-22 04:36:47 -050020#include <vector>
Sampa Misra854e61f2019-08-22 04:36:47 -050021
Riya Dixit49cfb132023-03-02 04:26:53 -060022PHOSPHOR_LOG2_USING;
23
Sampa Misra854e61f2019-08-22 04:36:47 -050024namespace pldm
25{
26namespace responder
27{
Matt Spinler39d8c7a2020-03-05 11:28:59 -060028using namespace sdbusplus::xyz::openbmc_project::Logging::server;
Matt Spinlerc180bc82023-09-12 09:29:54 -050029using namespace sdbusplus::org::open_power::Logging::server;
Matt Spinler39d8c7a2020-03-05 11:28:59 -060030
31namespace detail
32{
Matt Spinler39d8c7a2020-03-05 11:28:59 -060033/**
34 * @brief Finds the Entry::Level value for the severity of the PEL
35 * passed in.
36 *
37 * The severity byte is at offset 10 in the User Header section,
38 * which is always after the 48 byte Private Header section.
39 *
40 * @param[in] pelFileName - The file containing the PEL
41 *
42 * @return Entry::Level - The severity value for the Entry
43 */
44Entry::Level getEntryLevelFromPEL(const std::string& pelFileName)
45{
46 const std::map<uint8_t, Entry::Level> severityMap{
47 {0x00, Entry::Level::Informational}, // Informational event
48 {0x10, Entry::Level::Warning}, // Recoverable error
49 {0x20, Entry::Level::Warning}, // Predictive error
50 {0x40, Entry::Level::Error}, // Unrecoverable error
51 {0x50, Entry::Level::Error}, // Critical error
52 {0x60, Entry::Level::Error}, // Error from a diagnostic test
53 {0x70, Entry::Level::Warning} // Recoverable symptom
54 };
55
56 const size_t severityOffset = 0x3A;
57
58 size_t size = 0;
59 if (fs::exists(pelFileName))
60 {
61 size = fs::file_size(pelFileName);
62 }
63
64 if (size > severityOffset)
65 {
66 std::ifstream pel{pelFileName};
67 if (pel.good())
68 {
69 pel.seekg(severityOffset);
70
71 uint8_t sev;
72 pel.read(reinterpret_cast<char*>(&sev), 1);
73
74 // Get the type
75 sev = sev & 0xF0;
76
77 auto entry = severityMap.find(sev);
78 if (entry != severityMap.end())
79 {
80 return entry->second;
81 }
82 }
83 else
84 {
Riya Dixit49cfb132023-03-02 04:26:53 -060085 error("Unable to open PEL file {PEL_FILE_NAME}", "PEL_FILE_NAME",
86 pelFileName);
Matt Spinler39d8c7a2020-03-05 11:28:59 -060087 }
88 }
89
90 return Entry::Level::Error;
91}
92} // namespace detail
93
Deepak Kodihalli15211b42019-12-14 02:24:49 -060094int PelHandler::readIntoMemory(uint32_t offset, uint32_t& length,
Sampa Misra69508502020-09-08 00:08:21 -050095 uint64_t address,
96 oem_platform::Handler* /*oemPlatformHandler*/)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060097{
Deepak Kodihalli15211b42019-12-14 02:24:49 -060098 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
99 static constexpr auto logInterface = "org.open_power.Logging.PEL";
100
George Liu0e02c322020-01-01 09:41:51 +0800101 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600102
103 try
104 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500105 auto service = pldm::utils::DBusHandler().getService(logObjPath,
106 logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600107 auto method = bus.new_method_call(service.c_str(), logObjPath,
108 logInterface, "GetPEL");
109 method.append(fileHandle);
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500110 auto reply = bus.call(method, dbusTimeout);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600111 sdbusplus::message::unix_fd fd{};
112 reply.read(fd);
113 auto rc = transferFileData(fd, true, offset, length, address);
114 return rc;
115 }
116 catch (const std::exception& e)
117 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600118 error(
119 "GetPEL D-Bus call failed, PEL id = 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
120 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600121 return PLDM_ERROR;
122 }
123
124 return PLDM_SUCCESS;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600125}
126
Sampa Misra69508502020-09-08 00:08:21 -0500127int PelHandler::read(uint32_t offset, uint32_t& length, Response& response,
128 oem_platform::Handler* /*oemPlatformHandler*/)
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600129{
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600130 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
131 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800132 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600133
134 try
135 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500136 auto service = pldm::utils::DBusHandler().getService(logObjPath,
137 logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600138 auto method = bus.new_method_call(service.c_str(), logObjPath,
139 logInterface, "GetPEL");
140 method.append(fileHandle);
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500141 auto reply = bus.call(method, dbusTimeout);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600142 sdbusplus::message::unix_fd fd{};
143 reply.read(fd);
Pavithraba0738b2020-01-29 08:47:51 -0600144
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600145 off_t fileSize = lseek(fd, 0, SEEK_END);
146 if (fileSize == -1)
147 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600148 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600149 return PLDM_ERROR;
150 }
151 if (offset >= fileSize)
152 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600153 error(
Sagar Srinivas82257922023-07-10 08:12:22 -0500154 "Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE} FILE_HANDLE{FILE_HANDLE}",
155 "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE",
156 fileHandle);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600157 return PLDM_DATA_OUT_OF_RANGE;
158 }
159 if (offset + length > fileSize)
160 {
161 length = fileSize - offset;
162 }
163 auto rc = lseek(fd, offset, SEEK_SET);
164 if (rc == -1)
165 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600166 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600167 return PLDM_ERROR;
168 }
169 size_t currSize = response.size();
170 response.resize(currSize + length);
171 auto filePos = reinterpret_cast<char*>(response.data());
172 filePos += currSize;
173 rc = ::read(fd, filePos, length);
174 if (rc == -1)
175 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600176 error("file read failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600177 return PLDM_ERROR;
178 }
179 if (rc != length)
180 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600181 error(
182 "mismatch between number of characters to read and the length read, LENGTH={LEN} COUNT={CNT}",
183 "LEN", length, "CNT", rc);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600184 return PLDM_ERROR;
185 }
186 }
187 catch (const std::exception& e)
188 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600189 error(
190 "GetPEL D-Bus call failed on PEL ID 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
191 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600192 return PLDM_ERROR;
193 }
194 return PLDM_SUCCESS;
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600195}
196
Sampa Misra854e61f2019-08-22 04:36:47 -0500197int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
Sampa Misra69508502020-09-08 00:08:21 -0500198 uint64_t address,
199 oem_platform::Handler* /*oemPlatformHandler*/)
Sampa Misra854e61f2019-08-22 04:36:47 -0500200{
Sampa Misraf5087a42019-12-03 04:51:36 -0600201 char tmpFile[] = "/tmp/pel.XXXXXX";
202 int fd = mkstemp(tmpFile);
203 if (fd == -1)
204 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600205 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
Sampa Misraf5087a42019-12-03 04:51:36 -0600206 return PLDM_ERROR;
207 }
208 close(fd);
209 fs::path path(tmpFile);
Sampa Misra854e61f2019-08-22 04:36:47 -0500210
211 auto rc = transferFileData(path, false, offset, length, address);
212 if (rc == PLDM_SUCCESS)
213 {
214 rc = storePel(path.string());
215 }
Sampa Misra854e61f2019-08-22 04:36:47 -0500216 return rc;
217}
218
Matt Spinlerc180bc82023-09-12 09:29:54 -0500219int PelHandler::fileAck(uint8_t fileStatus)
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600220{
221 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
222 static constexpr auto logInterface = "org.open_power.Logging.PEL";
Matt Spinlerc180bc82023-09-12 09:29:54 -0500223 static std::string service;
George Liu0e02c322020-01-01 09:41:51 +0800224 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600225
Matt Spinlerc180bc82023-09-12 09:29:54 -0500226 if (service.empty())
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600227 {
Matt Spinlerc180bc82023-09-12 09:29:54 -0500228 try
229 {
230 service = pldm::utils::DBusHandler().getService(logObjPath,
231 logInterface);
232 }
233 catch (const sdbusplus::exception_t& e)
234 {
235 error("Mapper call failed when trying to find logging service "
236 "to ack PEL ID {FILE_HANDLE} error = {ERR_EXCEP}",
237 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e);
238 return PLDM_ERROR;
239 }
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600240 }
Matt Spinlerc180bc82023-09-12 09:29:54 -0500241
242 if (fileStatus == PLDM_SUCCESS)
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600243 {
Matt Spinlerc180bc82023-09-12 09:29:54 -0500244 try
245 {
246 auto method = bus.new_method_call(service.c_str(), logObjPath,
247 logInterface, "HostAck");
248 method.append(fileHandle);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000249 bus.call_noreply(method, dbusTimeout);
Matt Spinlerc180bc82023-09-12 09:29:54 -0500250 }
251 catch (const std::exception& e)
252 {
253 error(
254 "HostAck D-Bus call failed on PEL ID {FILE_HANDLE}, error = {ERR_EXCEP}",
255 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e);
256 return PLDM_ERROR;
257 }
258 }
259 else
260 {
261 PEL::RejectionReason reason{};
262 if (fileStatus == PLDM_FULL_FILE_DISCARDED)
263 {
264 reason = PEL::RejectionReason::HostFull;
265 }
266 else if (fileStatus == PLDM_ERROR_FILE_DISCARDED)
267 {
268 reason = PEL::RejectionReason::BadPEL;
269 }
270 else
271 {
272 error(
273 "Invalid file status {STATUS} in PEL file ack response for PEL {FILE_HANDLE}",
274 "STATUS", lg2::hex, fileStatus, "FILE_HANDLE", lg2::hex,
275 fileHandle);
276 return PLDM_ERROR;
277 }
278
279 try
280 {
281 auto method = bus.new_method_call(service.c_str(), logObjPath,
282 logInterface, "HostReject");
283 method.append(fileHandle, reason);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000284 bus.call_noreply(method, dbusTimeout);
Matt Spinlerc180bc82023-09-12 09:29:54 -0500285 }
286 catch (const std::exception& e)
287 {
288 error("HostReject D-Bus call failed on PEL ID {FILE_HANDLE}, "
289 "error = {ERR_EXCEP}, status = {STATUS}",
290 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e, "STATUS",
291 lg2::hex, fileStatus);
292 return PLDM_ERROR;
293 }
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600294 }
295
296 return PLDM_SUCCESS;
297}
298
Sampa Misra854e61f2019-08-22 04:36:47 -0500299int PelHandler::storePel(std::string&& pelFileName)
300{
301 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
302 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
303
George Liu0e02c322020-01-01 09:41:51 +0800304 auto& bus = pldm::utils::DBusHandler::getBus();
Sampa Misra854e61f2019-08-22 04:36:47 -0500305
306 try
307 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500308 auto service = pldm::utils::DBusHandler().getService(logObjPath,
309 logInterface);
Sampa Misra854e61f2019-08-22 04:36:47 -0500310 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
311 std::map<std::string, std::string> addlData{};
Sampa Misra854e61f2019-08-22 04:36:47 -0500312 auto severity =
313 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Matt Spinler39d8c7a2020-03-05 11:28:59 -0600314 detail::getEntryLevelFromPEL(pelFileName));
315 addlData.emplace("RAWPEL", std::move(pelFileName));
Sampa Misra854e61f2019-08-22 04:36:47 -0500316
317 auto method = bus.new_method_call(service.c_str(), logObjPath,
318 logInterface, "Create");
319 method.append("xyz.openbmc_project.Host.Error.Event", severity,
320 addlData);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000321 bus.call_noreply(method, dbusTimeout);
Sampa Misra854e61f2019-08-22 04:36:47 -0500322 }
323 catch (const std::exception& e)
324 {
Sagar Srinivas90403472023-08-21 06:08:55 -0500325 error(
326 "failed to make a d-bus call to PEL daemon, PEL_FILE_NAME={PEL_FILE_NAME), ERROR={ERR_EXCEP}",
327 "PEL_FILE_NAME", pelFileName, "ERR_EXCEP", e.what());
Sampa Misra854e61f2019-08-22 04:36:47 -0500328 return PLDM_ERROR;
329 }
330
331 return PLDM_SUCCESS;
332}
333
George Liud37b4952021-06-28 15:14:29 +0800334int PelHandler::write(const char* buffer, uint32_t offset, uint32_t& length,
335 oem_platform::Handler* /*oemPlatformHandler*/)
336{
337 int rc = PLDM_SUCCESS;
338
339 if (offset > 0)
340 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600341 error("Offset is non zero");
George Liud37b4952021-06-28 15:14:29 +0800342 return PLDM_ERROR;
343 }
344
345 char tmpFile[] = "/tmp/pel.XXXXXX";
346 auto fd = mkstemp(tmpFile);
347 if (fd == -1)
348 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600349 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
George Liud37b4952021-06-28 15:14:29 +0800350 return PLDM_ERROR;
351 }
352
353 size_t written = 0;
354 do
355 {
356 if ((rc = ::write(fd, buffer, length - written)) == -1)
357 {
358 break;
359 }
360 written += rc;
361 buffer += rc;
362 } while (rc && written < length);
363 close(fd);
364
365 if (rc == -1)
366 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600367 error("file write failed, ERROR={ERR}, LENGTH={LEN}, OFFSET={OFFSET}",
368 "ERR", errno, "LEN", length, "OFFSET", offset);
George Liud37b4952021-06-28 15:14:29 +0800369 fs::remove(tmpFile);
370 return PLDM_ERROR;
371 }
372
373 if (written == length)
374 {
375 fs::path path(tmpFile);
376 rc = storePel(path.string());
377 if (rc != PLDM_SUCCESS)
378 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600379 error("save PEL failed, ERROR = {RC} tmpFile = {TMP_FILE}", "RC",
380 rc, "TMP_FILE", tmpFile);
George Liud37b4952021-06-28 15:14:29 +0800381 }
382 }
383
384 return rc;
385}
386
Sampa Misra854e61f2019-08-22 04:36:47 -0500387} // namespace responder
388} // namespace pldm