blob: 8374abf993348a81e5872152fcd9a9d37cb34af5 [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
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
23namespace pldm
24{
25namespace responder
26{
27
Matt Spinler39d8c7a2020-03-05 11:28:59 -060028using namespace sdbusplus::xyz::openbmc_project::Logging::server;
29
30namespace detail
31{
32
33/**
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 {
85 std::cerr << "Unable to open PEL file " << pelFileName << "\n";
86 }
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 {
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 {
Matt Spinler72bf78e2021-09-24 13:46:13 -0500117 std::cerr << "GetPEL D-Bus call failed, PEL id = 0x" << std::hex
118 << fileHandle << ", error = " << e.what() << "\n";
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600119 return PLDM_ERROR;
120 }
121
122 return PLDM_SUCCESS;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600123}
124
Sampa Misra69508502020-09-08 00:08:21 -0500125int PelHandler::read(uint32_t offset, uint32_t& length, Response& response,
126 oem_platform::Handler* /*oemPlatformHandler*/)
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600127{
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600128 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
129 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800130 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600131
132 try
133 {
George Liu0e02c322020-01-01 09:41:51 +0800134 auto service =
135 pldm::utils::DBusHandler().getService(logObjPath, logInterface);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600136 auto method = bus.new_method_call(service.c_str(), logObjPath,
137 logInterface, "GetPEL");
138 method.append(fileHandle);
139 auto reply = bus.call(method);
140 sdbusplus::message::unix_fd fd{};
141 reply.read(fd);
Pavithraba0738b2020-01-29 08:47:51 -0600142
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600143 off_t fileSize = lseek(fd, 0, SEEK_END);
144 if (fileSize == -1)
145 {
146 std::cerr << "file seek failed";
147 return PLDM_ERROR;
148 }
149 if (offset >= fileSize)
150 {
151 std::cerr << "Offset exceeds file size, OFFSET=" << offset
152 << " FILE_SIZE=" << fileSize << std::endl;
153 return PLDM_DATA_OUT_OF_RANGE;
154 }
155 if (offset + length > fileSize)
156 {
157 length = fileSize - offset;
158 }
159 auto rc = lseek(fd, offset, SEEK_SET);
160 if (rc == -1)
161 {
162 std::cerr << "file seek failed";
163 return PLDM_ERROR;
164 }
165 size_t currSize = response.size();
166 response.resize(currSize + length);
167 auto filePos = reinterpret_cast<char*>(response.data());
168 filePos += currSize;
169 rc = ::read(fd, filePos, length);
170 if (rc == -1)
171 {
172 std::cerr << "file read failed";
173 return PLDM_ERROR;
174 }
175 if (rc != length)
176 {
177 std::cerr << "mismatch between number of characters to read and "
178 << "the length read, LENGTH=" << length << " COUNT=" << rc
179 << std::endl;
180 return PLDM_ERROR;
181 }
182 }
183 catch (const std::exception& e)
184 {
Matt Spinler72bf78e2021-09-24 13:46:13 -0500185 std::cerr << "GetPEL D-Bus call failed on PEL ID 0x" << std::hex
186 << fileHandle << ", error = " << e.what() << "\n";
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600187 return PLDM_ERROR;
188 }
189 return PLDM_SUCCESS;
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600190}
191
Sampa Misra854e61f2019-08-22 04:36:47 -0500192int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
Sampa Misra69508502020-09-08 00:08:21 -0500193 uint64_t address,
194 oem_platform::Handler* /*oemPlatformHandler*/)
Sampa Misra854e61f2019-08-22 04:36:47 -0500195{
Sampa Misraf5087a42019-12-03 04:51:36 -0600196 char tmpFile[] = "/tmp/pel.XXXXXX";
197 int fd = mkstemp(tmpFile);
198 if (fd == -1)
199 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600200 std::cerr << "failed to create a temporary pel, ERROR=" << errno
201 << "\n";
Sampa Misraf5087a42019-12-03 04:51:36 -0600202 return PLDM_ERROR;
203 }
204 close(fd);
205 fs::path path(tmpFile);
Sampa Misra854e61f2019-08-22 04:36:47 -0500206
207 auto rc = transferFileData(path, false, offset, length, address);
208 if (rc == PLDM_SUCCESS)
209 {
210 rc = storePel(path.string());
211 }
Sampa Misra854e61f2019-08-22 04:36:47 -0500212 return rc;
213}
214
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600215int PelHandler::fileAck(uint8_t /*fileStatus*/)
216{
217 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
218 static constexpr auto logInterface = "org.open_power.Logging.PEL";
George Liu0e02c322020-01-01 09:41:51 +0800219 auto& bus = pldm::utils::DBusHandler::getBus();
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600220
221 try
222 {
George Liu0e02c322020-01-01 09:41:51 +0800223 auto service =
224 pldm::utils::DBusHandler().getService(logObjPath, logInterface);
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600225 auto method = bus.new_method_call(service.c_str(), logObjPath,
226 logInterface, "HostAck");
227 method.append(fileHandle);
228 bus.call_noreply(method);
229 }
230 catch (const std::exception& e)
231 {
Matt Spinler72bf78e2021-09-24 13:46:13 -0500232 std::cerr << "HostAck D-Bus call failed on PEL ID 0x" << std::hex
233 << fileHandle << ", error = " << e.what() << "\n";
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600234 return PLDM_ERROR;
235 }
236
237 return PLDM_SUCCESS;
238}
239
Sampa Misra854e61f2019-08-22 04:36:47 -0500240int PelHandler::storePel(std::string&& pelFileName)
241{
242 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
243 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
244
George Liu0e02c322020-01-01 09:41:51 +0800245 auto& bus = pldm::utils::DBusHandler::getBus();
Sampa Misra854e61f2019-08-22 04:36:47 -0500246
247 try
248 {
George Liu0e02c322020-01-01 09:41:51 +0800249 auto service =
250 pldm::utils::DBusHandler().getService(logObjPath, logInterface);
Sampa Misra854e61f2019-08-22 04:36:47 -0500251 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
252 std::map<std::string, std::string> addlData{};
Sampa Misra854e61f2019-08-22 04:36:47 -0500253 auto severity =
254 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Matt Spinler39d8c7a2020-03-05 11:28:59 -0600255 detail::getEntryLevelFromPEL(pelFileName));
256 addlData.emplace("RAWPEL", std::move(pelFileName));
Sampa Misra854e61f2019-08-22 04:36:47 -0500257
258 auto method = bus.new_method_call(service.c_str(), logObjPath,
259 logInterface, "Create");
260 method.append("xyz.openbmc_project.Host.Error.Event", severity,
261 addlData);
262 bus.call_noreply(method);
263 }
264 catch (const std::exception& e)
265 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600266 std::cerr << "failed to make a d-bus call to PEL daemon, ERROR="
267 << e.what() << "\n";
Sampa Misra854e61f2019-08-22 04:36:47 -0500268 return PLDM_ERROR;
269 }
270
271 return PLDM_SUCCESS;
272}
273
George Liud37b4952021-06-28 15:14:29 +0800274int PelHandler::write(const char* buffer, uint32_t offset, uint32_t& length,
275 oem_platform::Handler* /*oemPlatformHandler*/)
276{
277 int rc = PLDM_SUCCESS;
278
279 if (offset > 0)
280 {
281 std::cerr << "Offset is non zero \n";
282 return PLDM_ERROR;
283 }
284
285 char tmpFile[] = "/tmp/pel.XXXXXX";
286 auto fd = mkstemp(tmpFile);
287 if (fd == -1)
288 {
289 std::cerr << "failed to create a temporary pel, ERROR=" << errno
290 << "\n";
291 return PLDM_ERROR;
292 }
293
294 size_t written = 0;
295 do
296 {
297 if ((rc = ::write(fd, buffer, length - written)) == -1)
298 {
299 break;
300 }
301 written += rc;
302 buffer += rc;
303 } while (rc && written < length);
304 close(fd);
305
306 if (rc == -1)
307 {
308 std::cerr << "file write failed, ERROR=" << errno
309 << ", LENGTH=" << length << ", OFFSET=" << offset << "\n";
310 fs::remove(tmpFile);
311 return PLDM_ERROR;
312 }
313
314 if (written == length)
315 {
316 fs::path path(tmpFile);
317 rc = storePel(path.string());
318 if (rc != PLDM_SUCCESS)
319 {
320 std::cerr << "save PEL failed, ERROR = " << rc
321 << "tmpFile = " << tmpFile << "\n";
322 }
323 }
324
325 return rc;
326}
327
Sampa Misra854e61f2019-08-22 04:36:47 -0500328} // namespace responder
329} // namespace pldm