blob: 3e33cc60744eca964a974c11dc8ad00f7628727d [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
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 Misraaa8ae722019-12-12 03:20:40 -060020#include <iostream>
Sampa Misra854e61f2019-08-22 04:36:47 -050021#include <vector>
Sampa Misra854e61f2019-08-22 04:36:47 -050022
Riya Dixit49cfb132023-03-02 04:26:53 -060023PHOSPHOR_LOG2_USING;
24
Sampa Misra854e61f2019-08-22 04:36:47 -050025namespace pldm
26{
27namespace responder
28{
Matt Spinler39d8c7a2020-03-05 11:28:59 -060029using namespace sdbusplus::xyz::openbmc_project::Logging::server;
Matt Spinlerc180bc82023-09-12 09:29:54 -050030using namespace sdbusplus::org::open_power::Logging::server;
Matt Spinler39d8c7a2020-03-05 11:28:59 -060031
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.com91a092f2023-09-18 23:39:44 -0500111 auto reply = bus.call(method, dbusTimeout);
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.com91a092f2023-09-18 23:39:44 -0500142 auto reply = bus.call(method, dbusTimeout);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600143 sdbusplus::message::unix_fd fd{};
144 reply.read(fd);
Pavithraba0738b2020-01-29 08:47:51 -0600145
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600146 off_t fileSize = lseek(fd, 0, SEEK_END);
147 if (fileSize == -1)
148 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600149 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600150 return PLDM_ERROR;
151 }
152 if (offset >= fileSize)
153 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600154 error(
Sagar Srinivas82257922023-07-10 08:12:22 -0500155 "Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE} FILE_HANDLE{FILE_HANDLE}",
156 "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE",
157 fileHandle);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600158 return PLDM_DATA_OUT_OF_RANGE;
159 }
160 if (offset + length > fileSize)
161 {
162 length = fileSize - offset;
163 }
164 auto rc = lseek(fd, offset, SEEK_SET);
165 if (rc == -1)
166 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600167 error("file seek failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600168 return PLDM_ERROR;
169 }
170 size_t currSize = response.size();
171 response.resize(currSize + length);
172 auto filePos = reinterpret_cast<char*>(response.data());
173 filePos += currSize;
174 rc = ::read(fd, filePos, length);
175 if (rc == -1)
176 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600177 error("file read failed");
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600178 return PLDM_ERROR;
179 }
180 if (rc != length)
181 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600182 error(
183 "mismatch between number of characters to read and the length read, LENGTH={LEN} COUNT={CNT}",
184 "LEN", length, "CNT", rc);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600185 return PLDM_ERROR;
186 }
187 }
188 catch (const std::exception& e)
189 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600190 error(
191 "GetPEL D-Bus call failed on PEL ID 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
192 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600193 return PLDM_ERROR;
194 }
195 return PLDM_SUCCESS;
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600196}
197
Sampa Misra854e61f2019-08-22 04:36:47 -0500198int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
Sampa Misra69508502020-09-08 00:08:21 -0500199 uint64_t address,
200 oem_platform::Handler* /*oemPlatformHandler*/)
Sampa Misra854e61f2019-08-22 04:36:47 -0500201{
Sampa Misraf5087a42019-12-03 04:51:36 -0600202 char tmpFile[] = "/tmp/pel.XXXXXX";
203 int fd = mkstemp(tmpFile);
204 if (fd == -1)
205 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600206 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
Sampa Misraf5087a42019-12-03 04:51:36 -0600207 return PLDM_ERROR;
208 }
209 close(fd);
210 fs::path path(tmpFile);
Sampa Misra854e61f2019-08-22 04:36:47 -0500211
212 auto rc = transferFileData(path, false, offset, length, address);
213 if (rc == PLDM_SUCCESS)
214 {
215 rc = storePel(path.string());
216 }
Sampa Misra854e61f2019-08-22 04:36:47 -0500217 return rc;
218}
219
Matt Spinlerc180bc82023-09-12 09:29:54 -0500220int PelHandler::fileAck(uint8_t fileStatus)
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600221{
222 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
223 static constexpr auto logInterface = "org.open_power.Logging.PEL";
Matt Spinlerc180bc82023-09-12 09:29:54 -0500224 static std::string service;
George Liu0e02c322020-01-01 09:41:51 +0800225 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600226
Matt Spinlerc180bc82023-09-12 09:29:54 -0500227 if (service.empty())
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600228 {
Matt Spinlerc180bc82023-09-12 09:29:54 -0500229 try
230 {
231 service = pldm::utils::DBusHandler().getService(logObjPath,
232 logInterface);
233 }
234 catch (const sdbusplus::exception_t& e)
235 {
236 error("Mapper call failed when trying to find logging service "
237 "to ack PEL ID {FILE_HANDLE} error = {ERR_EXCEP}",
238 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e);
239 return PLDM_ERROR;
240 }
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600241 }
Matt Spinlerc180bc82023-09-12 09:29:54 -0500242
243 if (fileStatus == PLDM_SUCCESS)
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600244 {
Matt Spinlerc180bc82023-09-12 09:29:54 -0500245 try
246 {
247 auto method = bus.new_method_call(service.c_str(), logObjPath,
248 logInterface, "HostAck");
249 method.append(fileHandle);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000250 bus.call_noreply(method, dbusTimeout);
Matt Spinlerc180bc82023-09-12 09:29:54 -0500251 }
252 catch (const std::exception& e)
253 {
254 error(
255 "HostAck D-Bus call failed on PEL ID {FILE_HANDLE}, error = {ERR_EXCEP}",
256 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e);
257 return PLDM_ERROR;
258 }
259 }
260 else
261 {
262 PEL::RejectionReason reason{};
263 if (fileStatus == PLDM_FULL_FILE_DISCARDED)
264 {
265 reason = PEL::RejectionReason::HostFull;
266 }
267 else if (fileStatus == PLDM_ERROR_FILE_DISCARDED)
268 {
269 reason = PEL::RejectionReason::BadPEL;
270 }
271 else
272 {
273 error(
274 "Invalid file status {STATUS} in PEL file ack response for PEL {FILE_HANDLE}",
275 "STATUS", lg2::hex, fileStatus, "FILE_HANDLE", lg2::hex,
276 fileHandle);
277 return PLDM_ERROR;
278 }
279
280 try
281 {
282 auto method = bus.new_method_call(service.c_str(), logObjPath,
283 logInterface, "HostReject");
284 method.append(fileHandle, reason);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000285 bus.call_noreply(method, dbusTimeout);
Matt Spinlerc180bc82023-09-12 09:29:54 -0500286 }
287 catch (const std::exception& e)
288 {
289 error("HostReject D-Bus call failed on PEL ID {FILE_HANDLE}, "
290 "error = {ERR_EXCEP}, status = {STATUS}",
291 "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e, "STATUS",
292 lg2::hex, fileStatus);
293 return PLDM_ERROR;
294 }
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600295 }
296
297 return PLDM_SUCCESS;
298}
299
Sampa Misra854e61f2019-08-22 04:36:47 -0500300int PelHandler::storePel(std::string&& pelFileName)
301{
302 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
303 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
304
George Liu0e02c322020-01-01 09:41:51 +0800305 auto& bus = pldm::utils::DBusHandler::getBus();
Sampa Misra854e61f2019-08-22 04:36:47 -0500306
307 try
308 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500309 auto service = pldm::utils::DBusHandler().getService(logObjPath,
310 logInterface);
Sampa Misra854e61f2019-08-22 04:36:47 -0500311 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
312 std::map<std::string, std::string> addlData{};
Sampa Misra854e61f2019-08-22 04:36:47 -0500313 auto severity =
314 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Matt Spinler39d8c7a2020-03-05 11:28:59 -0600315 detail::getEntryLevelFromPEL(pelFileName));
316 addlData.emplace("RAWPEL", std::move(pelFileName));
Sampa Misra854e61f2019-08-22 04:36:47 -0500317
318 auto method = bus.new_method_call(service.c_str(), logObjPath,
319 logInterface, "Create");
320 method.append("xyz.openbmc_project.Host.Error.Event", severity,
321 addlData);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000322 bus.call_noreply(method, dbusTimeout);
Sampa Misra854e61f2019-08-22 04:36:47 -0500323 }
324 catch (const std::exception& e)
325 {
Sagar Srinivas90403472023-08-21 06:08:55 -0500326 error(
327 "failed to make a d-bus call to PEL daemon, PEL_FILE_NAME={PEL_FILE_NAME), ERROR={ERR_EXCEP}",
328 "PEL_FILE_NAME", pelFileName, "ERR_EXCEP", e.what());
Sampa Misra854e61f2019-08-22 04:36:47 -0500329 return PLDM_ERROR;
330 }
331
332 return PLDM_SUCCESS;
333}
334
George Liud37b4952021-06-28 15:14:29 +0800335int PelHandler::write(const char* buffer, uint32_t offset, uint32_t& length,
336 oem_platform::Handler* /*oemPlatformHandler*/)
337{
338 int rc = PLDM_SUCCESS;
339
340 if (offset > 0)
341 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600342 error("Offset is non zero");
George Liud37b4952021-06-28 15:14:29 +0800343 return PLDM_ERROR;
344 }
345
346 char tmpFile[] = "/tmp/pel.XXXXXX";
347 auto fd = mkstemp(tmpFile);
348 if (fd == -1)
349 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600350 error("failed to create a temporary pel, ERROR={ERR}", "ERR", errno);
George Liud37b4952021-06-28 15:14:29 +0800351 return PLDM_ERROR;
352 }
353
354 size_t written = 0;
355 do
356 {
357 if ((rc = ::write(fd, buffer, length - written)) == -1)
358 {
359 break;
360 }
361 written += rc;
362 buffer += rc;
363 } while (rc && written < length);
364 close(fd);
365
366 if (rc == -1)
367 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600368 error("file write failed, ERROR={ERR}, LENGTH={LEN}, OFFSET={OFFSET}",
369 "ERR", errno, "LEN", length, "OFFSET", offset);
George Liud37b4952021-06-28 15:14:29 +0800370 fs::remove(tmpFile);
371 return PLDM_ERROR;
372 }
373
374 if (written == length)
375 {
376 fs::path path(tmpFile);
377 rc = storePel(path.string());
378 if (rc != PLDM_SUCCESS)
379 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600380 error("save PEL failed, ERROR = {RC} tmpFile = {TMP_FILE}", "RC",
381 rc, "TMP_FILE", tmpFile);
George Liud37b4952021-06-28 15:14:29 +0800382 }
383 }
384
385 return rc;
386}
387
Sampa Misra854e61f2019-08-22 04:36:47 -0500388} // namespace responder
389} // namespace pldm