blob: 6ad5ee237ffa864acc2eace570bb8ddc26be7be5 [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>
7#include <libpldm/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
Riya Dixit49cfb132023-03-02 04:26:53 -060012#include <phosphor-logging/lg2.hpp>
George Liu6492f522020-06-16 10:34:05 +080013#include <sdbusplus/server.hpp>
14#include <xyz/openbmc_project/Logging/Entry/server.hpp>
15
Sampa Misra854e61f2019-08-22 04:36:47 -050016#include <exception>
17#include <filesystem>
Matt Spinler39d8c7a2020-03-05 11:28:59 -060018#include <fstream>
Sampa Misraaa8ae722019-12-12 03:20:40 -060019#include <iostream>
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;
29
30namespace detail
31{
Matt Spinler39d8c7a2020-03-05 11:28:59 -060032/**
33 * @brief Finds the Entry::Level value for the severity of the PEL
34 * passed in.
35 *
36 * The severity byte is at offset 10 in the User Header section,
37 * which is always after the 48 byte Private Header section.
38 *
39 * @param[in] pelFileName - The file containing the PEL
40 *
41 * @return Entry::Level - The severity value for the Entry
42 */
43Entry::Level getEntryLevelFromPEL(const std::string& pelFileName)
44{
45 const std::map<uint8_t, Entry::Level> severityMap{
46 {0x00, Entry::Level::Informational}, // Informational event
47 {0x10, Entry::Level::Warning}, // Recoverable error
48 {0x20, Entry::Level::Warning}, // Predictive error
49 {0x40, Entry::Level::Error}, // Unrecoverable error
50 {0x50, Entry::Level::Error}, // Critical error
51 {0x60, Entry::Level::Error}, // Error from a diagnostic test
52 {0x70, Entry::Level::Warning} // Recoverable symptom
53 };
54
55 const size_t severityOffset = 0x3A;
56
57 size_t size = 0;
58 if (fs::exists(pelFileName))
59 {
60 size = fs::file_size(pelFileName);
61 }
62
63 if (size > severityOffset)
64 {
65 std::ifstream pel{pelFileName};
66 if (pel.good())
67 {
68 pel.seekg(severityOffset);
69
70 uint8_t sev;
71 pel.read(reinterpret_cast<char*>(&sev), 1);
72
73 // Get the type
74 sev = sev & 0xF0;
75
76 auto entry = severityMap.find(sev);
77 if (entry != severityMap.end())
78 {
79 return entry->second;
80 }
81 }
82 else
83 {
Riya Dixit49cfb132023-03-02 04:26:53 -060084 error("Unable to open PEL file {PEL_FILE_NAME}", "PEL_FILE_NAME",
85 pelFileName);
Matt Spinler39d8c7a2020-03-05 11:28:59 -060086 }
87 }
88
89 return Entry::Level::Error;
90}
91} // namespace detail
92
Deepak Kodihalli15211b42019-12-14 02:24:49 -060093int PelHandler::readIntoMemory(uint32_t offset, uint32_t& length,
Sampa Misra69508502020-09-08 00:08:21 -050094 uint64_t address,
95 oem_platform::Handler* /*oemPlatformHandler*/)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060096{
Deepak Kodihalli15211b42019-12-14 02:24:49 -060097 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
98 static constexpr auto logInterface = "org.open_power.Logging.PEL";
99
George Liu0e02c322020-01-01 09:41:51 +0800100 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600101
102 try
103 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500104 auto service = pldm::utils::DBusHandler().getService(logObjPath,
105 logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600106 auto method = bus.new_method_call(service.c_str(), logObjPath,
107 logInterface, "GetPEL");
108 method.append(fileHandle);
vkaverap@in.ibm.com9138c202023-05-19 07:50:47 -0500109 auto reply = bus.call(
110 method,
111 std::chrono::duration_cast<microsec>(sec(DBUS_TIMEOUT)).count());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600112 sdbusplus::message::unix_fd fd{};
113 reply.read(fd);
114 auto rc = transferFileData(fd, true, offset, length, address);
115 return rc;
116 }
117 catch (const std::exception& e)
118 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600119 error(
120 "GetPEL D-Bus call failed, PEL id = 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
121 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600122 return PLDM_ERROR;
123 }
124
125 return PLDM_SUCCESS;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600126}
127
Sampa Misra69508502020-09-08 00:08:21 -0500128int PelHandler::read(uint32_t offset, uint32_t& length, Response& response,
129 oem_platform::Handler* /*oemPlatformHandler*/)
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600130{
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600131 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
132 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800133 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600134
135 try
136 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500137 auto service = pldm::utils::DBusHandler().getService(logObjPath,
138 logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600139 auto method = bus.new_method_call(service.c_str(), logObjPath,
140 logInterface, "GetPEL");
141 method.append(fileHandle);
vkaverap@in.ibm.com9138c202023-05-19 07:50:47 -0500142 auto reply = bus.call(
143 method,
144 std::chrono::duration_cast<microsec>(sec(DBUS_TIMEOUT)).count());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600145 sdbusplus::message::unix_fd fd{};
146 reply.read(fd);
Pavithraba0738b2020-01-29 08:47:51 -0600147
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600148 off_t fileSize = lseek(fd, 0, SEEK_END);
149 if (fileSize == -1)
150 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600151 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600152 return PLDM_ERROR;
153 }
154 if (offset >= fileSize)
155 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600156 error(
Sagar Srinivas82257922023-07-10 08:12:22 -0500157 "Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE} FILE_HANDLE{FILE_HANDLE}",
158 "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE",
159 fileHandle);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600160 return PLDM_DATA_OUT_OF_RANGE;
161 }
162 if (offset + length > fileSize)
163 {
164 length = fileSize - offset;
165 }
166 auto rc = lseek(fd, offset, SEEK_SET);
167 if (rc == -1)
168 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600169 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600170 return PLDM_ERROR;
171 }
172 size_t currSize = response.size();
173 response.resize(currSize + length);
174 auto filePos = reinterpret_cast<char*>(response.data());
175 filePos += currSize;
176 rc = ::read(fd, filePos, length);
177 if (rc == -1)
178 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600179 error("file read failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600180 return PLDM_ERROR;
181 }
182 if (rc != length)
183 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600184 error(
185 "mismatch between number of characters to read and the length read, LENGTH={LEN} COUNT={CNT}",
186 "LEN", length, "CNT", rc);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600187 return PLDM_ERROR;
188 }
189 }
190 catch (const std::exception& e)
191 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600192 error(
193 "GetPEL D-Bus call failed on PEL ID 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
194 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600195 return PLDM_ERROR;
196 }
197 return PLDM_SUCCESS;
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600198}
199
Sampa Misra854e61f2019-08-22 04:36:47 -0500200int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
Sampa Misra69508502020-09-08 00:08:21 -0500201 uint64_t address,
202 oem_platform::Handler* /*oemPlatformHandler*/)
Sampa Misra854e61f2019-08-22 04:36:47 -0500203{
Sampa Misraf5087a42019-12-03 04:51:36 -0600204 char tmpFile[] = "/tmp/pel.XXXXXX";
205 int fd = mkstemp(tmpFile);
206 if (fd == -1)
207 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600208 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
Sampa Misraf5087a42019-12-03 04:51:36 -0600209 return PLDM_ERROR;
210 }
211 close(fd);
212 fs::path path(tmpFile);
Sampa Misra854e61f2019-08-22 04:36:47 -0500213
214 auto rc = transferFileData(path, false, offset, length, address);
215 if (rc == PLDM_SUCCESS)
216 {
217 rc = storePel(path.string());
218 }
Sampa Misra854e61f2019-08-22 04:36:47 -0500219 return rc;
220}
221
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600222int PelHandler::fileAck(uint8_t /*fileStatus*/)
223{
224 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
225 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800226 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600227
228 try
229 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500230 auto service = pldm::utils::DBusHandler().getService(logObjPath,
231 logInterface);
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600232 auto method = bus.new_method_call(service.c_str(), logObjPath,
233 logInterface, "HostAck");
234 method.append(fileHandle);
235 bus.call_noreply(method);
236 }
237 catch (const std::exception& e)
238 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600239 error(
240 "HostAck D-Bus call failed on PEL ID 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
241 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600242 return PLDM_ERROR;
243 }
244
245 return PLDM_SUCCESS;
246}
247
Sampa Misra854e61f2019-08-22 04:36:47 -0500248int PelHandler::storePel(std::string&& pelFileName)
249{
250 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
251 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
252
George Liu0e02c322020-01-01 09:41:51 +0800253 auto& bus = pldm::utils::DBusHandler::getBus();
Sampa Misra854e61f2019-08-22 04:36:47 -0500254
255 try
256 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500257 auto service = pldm::utils::DBusHandler().getService(logObjPath,
258 logInterface);
Sampa Misra854e61f2019-08-22 04:36:47 -0500259 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
260 std::map<std::string, std::string> addlData{};
Sampa Misra854e61f2019-08-22 04:36:47 -0500261 auto severity =
262 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Matt Spinler39d8c7a2020-03-05 11:28:59 -0600263 detail::getEntryLevelFromPEL(pelFileName));
264 addlData.emplace("RAWPEL", std::move(pelFileName));
Sampa Misra854e61f2019-08-22 04:36:47 -0500265
266 auto method = bus.new_method_call(service.c_str(), logObjPath,
267 logInterface, "Create");
268 method.append("xyz.openbmc_project.Host.Error.Event", severity,
269 addlData);
270 bus.call_noreply(method);
271 }
272 catch (const std::exception& e)
273 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600274 error("failed to make a d-bus call to PEL daemon, ERROR={ERR_EXCEP}",
275 "ERR_EXCEP", e.what());
Sampa Misra854e61f2019-08-22 04:36:47 -0500276 return PLDM_ERROR;
277 }
278
279 return PLDM_SUCCESS;
280}
281
George Liud37b4952021-06-28 15:14:29 +0800282int PelHandler::write(const char* buffer, uint32_t offset, uint32_t& length,
283 oem_platform::Handler* /*oemPlatformHandler*/)
284{
285 int rc = PLDM_SUCCESS;
286
287 if (offset > 0)
288 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600289 error("Offset is non zero");
George Liud37b4952021-06-28 15:14:29 +0800290 return PLDM_ERROR;
291 }
292
293 char tmpFile[] = "/tmp/pel.XXXXXX";
294 auto fd = mkstemp(tmpFile);
295 if (fd == -1)
296 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600297 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
George Liud37b4952021-06-28 15:14:29 +0800298 return PLDM_ERROR;
299 }
300
301 size_t written = 0;
302 do
303 {
304 if ((rc = ::write(fd, buffer, length - written)) == -1)
305 {
306 break;
307 }
308 written += rc;
309 buffer += rc;
310 } while (rc && written < length);
311 close(fd);
312
313 if (rc == -1)
314 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600315 error("file write failed, ERROR={ERR}, LENGTH={LEN}, OFFSET={OFFSET}",
316 "ERR", errno, "LEN", length, "OFFSET", offset);
George Liud37b4952021-06-28 15:14:29 +0800317 fs::remove(tmpFile);
318 return PLDM_ERROR;
319 }
320
321 if (written == length)
322 {
323 fs::path path(tmpFile);
324 rc = storePel(path.string());
325 if (rc != PLDM_SUCCESS)
326 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600327 error("save PEL failed, ERROR = {RC} tmpFile = {TMP_FILE}", "RC",
328 rc, "TMP_FILE", tmpFile);
George Liud37b4952021-06-28 15:14:29 +0800329 }
330 }
331
332 return rc;
333}
334
Sampa Misra854e61f2019-08-22 04:36:47 -0500335} // namespace responder
336} // namespace pldm