blob: ba94f4ec44ac930a799388620ca27d3ea8f1a3a5 [file] [log] [blame]
Sampa Misra854e61f2019-08-22 04:36:47 -05001#include "config.h"
2
3#include "file_io_type_pel.hpp"
4
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05005#include "common/utils.hpp"
Sampa Misra854e61f2019-08-22 04:36:47 -05006#include "xyz/openbmc_project/Common/error.hpp"
7
George Liuc453e162022-12-21 17:16:23 +08008#include <libpldm/base.h>
9#include <libpldm/file_io.h>
Sampa Misra854e61f2019-08-22 04:36:47 -050010#include <stdint.h>
11#include <systemd/sd-bus.h>
12#include <unistd.h>
13
Riya Dixit49cfb132023-03-02 04:26:53 -060014#include <phosphor-logging/lg2.hpp>
George Liu6492f522020-06-16 10:34:05 +080015#include <sdbusplus/server.hpp>
16#include <xyz/openbmc_project/Logging/Entry/server.hpp>
17
Sampa Misra854e61f2019-08-22 04:36:47 -050018#include <exception>
19#include <filesystem>
Matt Spinler39d8c7a2020-03-05 11:28:59 -060020#include <fstream>
Sampa Misraaa8ae722019-12-12 03:20:40 -060021#include <iostream>
Sampa Misra854e61f2019-08-22 04:36:47 -050022#include <vector>
Sampa Misra854e61f2019-08-22 04:36:47 -050023
Riya Dixit49cfb132023-03-02 04:26:53 -060024PHOSPHOR_LOG2_USING;
25
Sampa Misra854e61f2019-08-22 04:36:47 -050026namespace pldm
27{
28namespace responder
29{
Matt Spinler39d8c7a2020-03-05 11:28:59 -060030using namespace sdbusplus::xyz::openbmc_project::Logging::server;
31
32namespace detail
33{
Matt Spinler39d8c7a2020-03-05 11:28:59 -060034/**
35 * @brief Finds the Entry::Level value for the severity of the PEL
36 * passed in.
37 *
38 * The severity byte is at offset 10 in the User Header section,
39 * which is always after the 48 byte Private Header section.
40 *
41 * @param[in] pelFileName - The file containing the PEL
42 *
43 * @return Entry::Level - The severity value for the Entry
44 */
45Entry::Level getEntryLevelFromPEL(const std::string& pelFileName)
46{
47 const std::map<uint8_t, Entry::Level> severityMap{
48 {0x00, Entry::Level::Informational}, // Informational event
49 {0x10, Entry::Level::Warning}, // Recoverable error
50 {0x20, Entry::Level::Warning}, // Predictive error
51 {0x40, Entry::Level::Error}, // Unrecoverable error
52 {0x50, Entry::Level::Error}, // Critical error
53 {0x60, Entry::Level::Error}, // Error from a diagnostic test
54 {0x70, Entry::Level::Warning} // Recoverable symptom
55 };
56
57 const size_t severityOffset = 0x3A;
58
59 size_t size = 0;
60 if (fs::exists(pelFileName))
61 {
62 size = fs::file_size(pelFileName);
63 }
64
65 if (size > severityOffset)
66 {
67 std::ifstream pel{pelFileName};
68 if (pel.good())
69 {
70 pel.seekg(severityOffset);
71
72 uint8_t sev;
73 pel.read(reinterpret_cast<char*>(&sev), 1);
74
75 // Get the type
76 sev = sev & 0xF0;
77
78 auto entry = severityMap.find(sev);
79 if (entry != severityMap.end())
80 {
81 return entry->second;
82 }
83 }
84 else
85 {
Riya Dixit49cfb132023-03-02 04:26:53 -060086 error("Unable to open PEL file {PEL_FILE_NAME}", "PEL_FILE_NAME",
87 pelFileName);
Matt Spinler39d8c7a2020-03-05 11:28:59 -060088 }
89 }
90
91 return Entry::Level::Error;
92}
93} // namespace detail
94
Deepak Kodihalli15211b42019-12-14 02:24:49 -060095int PelHandler::readIntoMemory(uint32_t offset, uint32_t& length,
Sampa Misra69508502020-09-08 00:08:21 -050096 uint64_t address,
97 oem_platform::Handler* /*oemPlatformHandler*/)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060098{
Deepak Kodihalli15211b42019-12-14 02:24:49 -060099 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
100 static constexpr auto logInterface = "org.open_power.Logging.PEL";
101
George Liu0e02c322020-01-01 09:41:51 +0800102 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600103
104 try
105 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500106 auto service = pldm::utils::DBusHandler().getService(logObjPath,
107 logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600108 auto method = bus.new_method_call(service.c_str(), logObjPath,
109 logInterface, "GetPEL");
110 method.append(fileHandle);
vkaverap@in.ibm.com9138c202023-05-19 07:50:47 -0500111 auto reply = bus.call(
112 method,
113 std::chrono::duration_cast<microsec>(sec(DBUS_TIMEOUT)).count());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600114 sdbusplus::message::unix_fd fd{};
115 reply.read(fd);
116 auto rc = transferFileData(fd, true, offset, length, address);
117 return rc;
118 }
119 catch (const std::exception& e)
120 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600121 error(
122 "GetPEL D-Bus call failed, PEL id = 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
123 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600124 return PLDM_ERROR;
125 }
126
127 return PLDM_SUCCESS;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600128}
129
Sampa Misra69508502020-09-08 00:08:21 -0500130int PelHandler::read(uint32_t offset, uint32_t& length, Response& response,
131 oem_platform::Handler* /*oemPlatformHandler*/)
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600132{
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600133 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
134 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800135 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600136
137 try
138 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500139 auto service = pldm::utils::DBusHandler().getService(logObjPath,
140 logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600141 auto method = bus.new_method_call(service.c_str(), logObjPath,
142 logInterface, "GetPEL");
143 method.append(fileHandle);
vkaverap@in.ibm.com9138c202023-05-19 07:50:47 -0500144 auto reply = bus.call(
145 method,
146 std::chrono::duration_cast<microsec>(sec(DBUS_TIMEOUT)).count());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600147 sdbusplus::message::unix_fd fd{};
148 reply.read(fd);
Pavithraba0738b2020-01-29 08:47:51 -0600149
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600150 off_t fileSize = lseek(fd, 0, SEEK_END);
151 if (fileSize == -1)
152 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600153 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600154 return PLDM_ERROR;
155 }
156 if (offset >= fileSize)
157 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600158 error(
159 "Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}",
160 "OFFSET", offset, "FILE_SIZE", fileSize);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600161 return PLDM_DATA_OUT_OF_RANGE;
162 }
163 if (offset + length > fileSize)
164 {
165 length = fileSize - offset;
166 }
167 auto rc = lseek(fd, offset, SEEK_SET);
168 if (rc == -1)
169 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600170 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600171 return PLDM_ERROR;
172 }
173 size_t currSize = response.size();
174 response.resize(currSize + length);
175 auto filePos = reinterpret_cast<char*>(response.data());
176 filePos += currSize;
177 rc = ::read(fd, filePos, length);
178 if (rc == -1)
179 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600180 error("file read failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600181 return PLDM_ERROR;
182 }
183 if (rc != length)
184 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600185 error(
186 "mismatch between number of characters to read and the length read, LENGTH={LEN} COUNT={CNT}",
187 "LEN", length, "CNT", rc);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600188 return PLDM_ERROR;
189 }
190 }
191 catch (const std::exception& e)
192 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600193 error(
194 "GetPEL D-Bus call failed on PEL ID 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
195 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600196 return PLDM_ERROR;
197 }
198 return PLDM_SUCCESS;
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600199}
200
Sampa Misra854e61f2019-08-22 04:36:47 -0500201int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
Sampa Misra69508502020-09-08 00:08:21 -0500202 uint64_t address,
203 oem_platform::Handler* /*oemPlatformHandler*/)
Sampa Misra854e61f2019-08-22 04:36:47 -0500204{
Sampa Misraf5087a42019-12-03 04:51:36 -0600205 char tmpFile[] = "/tmp/pel.XXXXXX";
206 int fd = mkstemp(tmpFile);
207 if (fd == -1)
208 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600209 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
Sampa Misraf5087a42019-12-03 04:51:36 -0600210 return PLDM_ERROR;
211 }
212 close(fd);
213 fs::path path(tmpFile);
Sampa Misra854e61f2019-08-22 04:36:47 -0500214
215 auto rc = transferFileData(path, false, offset, length, address);
216 if (rc == PLDM_SUCCESS)
217 {
218 rc = storePel(path.string());
219 }
Sampa Misra854e61f2019-08-22 04:36:47 -0500220 return rc;
221}
222
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600223int PelHandler::fileAck(uint8_t /*fileStatus*/)
224{
225 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
226 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800227 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600228
229 try
230 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500231 auto service = pldm::utils::DBusHandler().getService(logObjPath,
232 logInterface);
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600233 auto method = bus.new_method_call(service.c_str(), logObjPath,
234 logInterface, "HostAck");
235 method.append(fileHandle);
236 bus.call_noreply(method);
237 }
238 catch (const std::exception& e)
239 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600240 error(
241 "HostAck D-Bus call failed on PEL ID 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
242 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600243 return PLDM_ERROR;
244 }
245
246 return PLDM_SUCCESS;
247}
248
Sampa Misra854e61f2019-08-22 04:36:47 -0500249int PelHandler::storePel(std::string&& pelFileName)
250{
251 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
252 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
253
George Liu0e02c322020-01-01 09:41:51 +0800254 auto& bus = pldm::utils::DBusHandler::getBus();
Sampa Misra854e61f2019-08-22 04:36:47 -0500255
256 try
257 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500258 auto service = pldm::utils::DBusHandler().getService(logObjPath,
259 logInterface);
Sampa Misra854e61f2019-08-22 04:36:47 -0500260 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
261 std::map<std::string, std::string> addlData{};
Sampa Misra854e61f2019-08-22 04:36:47 -0500262 auto severity =
263 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Matt Spinler39d8c7a2020-03-05 11:28:59 -0600264 detail::getEntryLevelFromPEL(pelFileName));
265 addlData.emplace("RAWPEL", std::move(pelFileName));
Sampa Misra854e61f2019-08-22 04:36:47 -0500266
267 auto method = bus.new_method_call(service.c_str(), logObjPath,
268 logInterface, "Create");
269 method.append("xyz.openbmc_project.Host.Error.Event", severity,
270 addlData);
271 bus.call_noreply(method);
272 }
273 catch (const std::exception& e)
274 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600275 error("failed to make a d-bus call to PEL daemon, ERROR={ERR_EXCEP}",
276 "ERR_EXCEP", e.what());
Sampa Misra854e61f2019-08-22 04:36:47 -0500277 return PLDM_ERROR;
278 }
279
280 return PLDM_SUCCESS;
281}
282
George Liud37b4952021-06-28 15:14:29 +0800283int PelHandler::write(const char* buffer, uint32_t offset, uint32_t& length,
284 oem_platform::Handler* /*oemPlatformHandler*/)
285{
286 int rc = PLDM_SUCCESS;
287
288 if (offset > 0)
289 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600290 error("Offset is non zero");
George Liud37b4952021-06-28 15:14:29 +0800291 return PLDM_ERROR;
292 }
293
294 char tmpFile[] = "/tmp/pel.XXXXXX";
295 auto fd = mkstemp(tmpFile);
296 if (fd == -1)
297 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600298 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
George Liud37b4952021-06-28 15:14:29 +0800299 return PLDM_ERROR;
300 }
301
302 size_t written = 0;
303 do
304 {
305 if ((rc = ::write(fd, buffer, length - written)) == -1)
306 {
307 break;
308 }
309 written += rc;
310 buffer += rc;
311 } while (rc && written < length);
312 close(fd);
313
314 if (rc == -1)
315 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600316 error("file write failed, ERROR={ERR}, LENGTH={LEN}, OFFSET={OFFSET}",
317 "ERR", errno, "LEN", length, "OFFSET", offset);
George Liud37b4952021-06-28 15:14:29 +0800318 fs::remove(tmpFile);
319 return PLDM_ERROR;
320 }
321
322 if (written == length)
323 {
324 fs::path path(tmpFile);
325 rc = storePel(path.string());
326 if (rc != PLDM_SUCCESS)
327 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600328 error("save PEL failed, ERROR = {RC} tmpFile = {TMP_FILE}", "RC",
329 rc, "TMP_FILE", tmpFile);
George Liud37b4952021-06-28 15:14:29 +0800330 }
331 }
332
333 return rc;
334}
335
Sampa Misra854e61f2019-08-22 04:36:47 -0500336} // namespace responder
337} // namespace pldm