blob: ef21c0122419cc83d8ba5a8fcb1e19dae24bae05 [file] [log] [blame]
Sampa Misra854e61f2019-08-22 04:36:47 -05001#include "config.h"
2
3#include "file_io_type_pel.hpp"
4
George Liu6492f522020-06-16 10:34:05 +08005#include "libpldm/base.h"
6#include "oem/ibm/libpldm/file_io.h"
7
George Liu83409572019-12-24 18:42:54 +08008#include "utils.hpp"
Sampa Misra854e61f2019-08-22 04:36:47 -05009#include "xyz/openbmc_project/Common/error.hpp"
10
11#include <stdint.h>
12#include <systemd/sd-bus.h>
13#include <unistd.h>
14
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
24namespace pldm
25{
26namespace responder
27{
28
Matt Spinler39d8c7a2020-03-05 11:28:59 -060029using namespace sdbusplus::xyz::openbmc_project::Logging::server;
30
31namespace detail
32{
33
34/**
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 {
86 std::cerr << "Unable to open PEL file " << pelFileName << "\n";
87 }
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,
95 uint64_t address)
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 {
George Liu0e02c322020-01-01 09:41:51 +0800104 auto service =
105 pldm::utils::DBusHandler().getService(logObjPath, 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);
109 auto reply = bus.call(method);
110 sdbusplus::message::unix_fd fd{};
111 reply.read(fd);
112 auto rc = transferFileData(fd, true, offset, length, address);
113 return rc;
114 }
115 catch (const std::exception& e)
116 {
117 std::cerr << "GetPEL D-Bus call failed, PEL id = " << fileHandle
118 << ", error = " << e.what() << "\n";
119 return PLDM_ERROR;
120 }
121
122 return PLDM_SUCCESS;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600123}
124
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600125int PelHandler::read(uint32_t offset, uint32_t& length, Response& response)
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600126{
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600127 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
128 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800129 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600130
131 try
132 {
George Liu0e02c322020-01-01 09:41:51 +0800133 auto service =
134 pldm::utils::DBusHandler().getService(logObjPath, logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600135 auto method = bus.new_method_call(service.c_str(), logObjPath,
136 logInterface, "GetPEL");
137 method.append(fileHandle);
138 auto reply = bus.call(method);
139 sdbusplus::message::unix_fd fd{};
140 reply.read(fd);
Pavithraba0738b2020-01-29 08:47:51 -0600141
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600142 off_t fileSize = lseek(fd, 0, SEEK_END);
143 if (fileSize == -1)
144 {
145 std::cerr << "file seek failed";
146 return PLDM_ERROR;
147 }
148 if (offset >= fileSize)
149 {
150 std::cerr << "Offset exceeds file size, OFFSET=" << offset
151 << " FILE_SIZE=" << fileSize << std::endl;
152 return PLDM_DATA_OUT_OF_RANGE;
153 }
154 if (offset + length > fileSize)
155 {
156 length = fileSize - offset;
157 }
158 auto rc = lseek(fd, offset, SEEK_SET);
159 if (rc == -1)
160 {
161 std::cerr << "file seek failed";
162 return PLDM_ERROR;
163 }
164 size_t currSize = response.size();
165 response.resize(currSize + length);
166 auto filePos = reinterpret_cast<char*>(response.data());
167 filePos += currSize;
168 rc = ::read(fd, filePos, length);
169 if (rc == -1)
170 {
171 std::cerr << "file read failed";
172 return PLDM_ERROR;
173 }
174 if (rc != length)
175 {
176 std::cerr << "mismatch between number of characters to read and "
177 << "the length read, LENGTH=" << length << " COUNT=" << rc
178 << std::endl;
179 return PLDM_ERROR;
180 }
181 }
182 catch (const std::exception& e)
183 {
184 std::cerr << "GetPEL D-Bus call failed";
185 return PLDM_ERROR;
186 }
187 return PLDM_SUCCESS;
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600188}
189
Sampa Misra854e61f2019-08-22 04:36:47 -0500190int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
191 uint64_t address)
192{
Sampa Misraf5087a42019-12-03 04:51:36 -0600193 char tmpFile[] = "/tmp/pel.XXXXXX";
194 int fd = mkstemp(tmpFile);
195 if (fd == -1)
196 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600197 std::cerr << "failed to create a temporary pel, ERROR=" << errno
198 << "\n";
Sampa Misraf5087a42019-12-03 04:51:36 -0600199 return PLDM_ERROR;
200 }
201 close(fd);
202 fs::path path(tmpFile);
Sampa Misra854e61f2019-08-22 04:36:47 -0500203
204 auto rc = transferFileData(path, false, offset, length, address);
205 if (rc == PLDM_SUCCESS)
206 {
207 rc = storePel(path.string());
208 }
209 fs::remove(path);
210 return rc;
211}
212
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600213int PelHandler::fileAck(uint8_t /*fileStatus*/)
214{
215 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
216 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800217 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600218
219 try
220 {
George Liu0e02c322020-01-01 09:41:51 +0800221 auto service =
222 pldm::utils::DBusHandler().getService(logObjPath, logInterface);
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600223 auto method = bus.new_method_call(service.c_str(), logObjPath,
224 logInterface, "HostAck");
225 method.append(fileHandle);
226 bus.call_noreply(method);
227 }
228 catch (const std::exception& e)
229 {
230 std::cerr << "HostAck D-Bus call failed";
231 return PLDM_ERROR;
232 }
233
234 return PLDM_SUCCESS;
235}
236
Sampa Misra854e61f2019-08-22 04:36:47 -0500237int PelHandler::storePel(std::string&& pelFileName)
238{
239 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
240 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
241
George Liu0e02c322020-01-01 09:41:51 +0800242 auto& bus = pldm::utils::DBusHandler::getBus();
Sampa Misra854e61f2019-08-22 04:36:47 -0500243
244 try
245 {
George Liu0e02c322020-01-01 09:41:51 +0800246 auto service =
247 pldm::utils::DBusHandler().getService(logObjPath, logInterface);
Sampa Misra854e61f2019-08-22 04:36:47 -0500248 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
249 std::map<std::string, std::string> addlData{};
Sampa Misra854e61f2019-08-22 04:36:47 -0500250 auto severity =
251 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Matt Spinler39d8c7a2020-03-05 11:28:59 -0600252 detail::getEntryLevelFromPEL(pelFileName));
253 addlData.emplace("RAWPEL", std::move(pelFileName));
Sampa Misra854e61f2019-08-22 04:36:47 -0500254
255 auto method = bus.new_method_call(service.c_str(), logObjPath,
256 logInterface, "Create");
257 method.append("xyz.openbmc_project.Host.Error.Event", severity,
258 addlData);
259 bus.call_noreply(method);
260 }
261 catch (const std::exception& e)
262 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600263 std::cerr << "failed to make a d-bus call to PEL daemon, ERROR="
264 << e.what() << "\n";
Sampa Misra854e61f2019-08-22 04:36:47 -0500265 return PLDM_ERROR;
266 }
267
268 return PLDM_SUCCESS;
269}
270
271} // namespace responder
272} // namespace pldm