blob: 07cd07a2dea87bf5f7727a45b6e547dd1d0e1d45 [file] [log] [blame]
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -05001#include "create_pel.hpp"
2
3#include "dump_utils.hpp"
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -05004#include "sbe_consts.hpp"
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -05005
6#include <fcntl.h>
7#include <libekb.H>
8#include <unistd.h>
9
10#include <phosphor-logging/elog.hpp>
11#include <phosphor-logging/lg2.hpp>
12#include <xyz/openbmc_project/Logging/Create/server.hpp>
13#include <xyz/openbmc_project/Logging/Entry/server.hpp>
14
15#include <cerrno>
16#include <cstdio>
17#include <cstdlib>
18#include <cstring>
19#include <format>
20#include <map>
21#include <stdexcept>
22#include <string>
23#include <tuple>
24#include <vector>
25
26namespace openpower::dump::pel
27{
28
29using namespace phosphor::logging;
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -050030using namespace openpower::dump::SBE;
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050031constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
32constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
33constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";
SwethaParasaed53dc72025-01-24 01:07:01 -060034constexpr auto entryInterface = "xyz.openbmc_project.Logging.Entry";
35constexpr auto opEntryInterface = "org.open_power.Logging.PEL.Entry";
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050036
37uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -050038 const FFDCData& ffdcData, const Severity severity,
39 const std::optional<PELFFDCInfo>& pelFFDCInfoOpt)
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050040{
41 uint32_t plid = 0;
42 std::unordered_map<std::string, std::string> additionalData = {
43 {"_PID", std::to_string(getpid())}, {"SBE_ERR_MSG", sbeError.what()}};
44 auto bus = sdbusplus::bus::new_default();
45
46 additionalData.emplace("_PID", std::to_string(getpid()));
47 additionalData.emplace("SBE_ERR_MSG", sbeError.what());
48
49 for (auto& data : ffdcData)
50 {
51 additionalData.emplace(data);
52 }
53
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -050054 PELFFDCInfo pelFFDCInfo;
55 if (pelFFDCInfoOpt)
56 {
57 pelFFDCInfo = *pelFFDCInfoOpt;
58 }
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050059
60 // Negative fd value indicates error case or invalid file
61 // No need of special processing , just log error with additional ffdc.
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -050062 else if (sbeError.getFd() > 0)
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050063 {
64 // Refer phosphor-logging/extensions/openpower-pels/README.md section
65 // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
66 // for details of related to createPEL with SBE FFDC information
Manojkiran Edaeb462522024-06-17 11:05:27 +053067 // using CreateWithFFDCFiles api.
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -050068 pelFFDCInfo.emplace_back(std::make_tuple(
69 sdbusplus::xyz::openbmc_project::Logging::server::Create::
70 FFDCFormat::Custom,
71 FFDC_FORMAT_SUBTYPE, FFDC_FORMAT_VERSION, sbeError.getFd()));
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050072 }
73 try
74 {
Patrick Williams540521e2024-08-16 15:20:03 -040075 auto service =
76 util::getService(bus, opLoggingInterface, loggingObjectPath);
77 auto method =
78 bus.new_method_call(service.c_str(), loggingObjectPath,
79 opLoggingInterface, "CreatePELWithFFDCFiles");
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050080 auto level =
81 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Dhruvaraj Subhashchandranf9f65b82022-10-13 06:46:43 -050082 severity);
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050083 method.append(event, level, additionalData, pelFFDCInfo);
84 auto response = bus.call(method);
85
86 // reply will be tuple containing bmc log id, platform log id
87 std::tuple<uint32_t, uint32_t> reply = {0, 0};
88
89 // parse dbus response into reply
90 response.read(reply);
SwethaParasaed53dc72025-01-24 01:07:01 -060091 plid = std::get<0>(reply); // dbus entry id is tuple "first"
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050092 }
Patrick Williams9ae780d2024-04-26 02:34:31 -050093 catch (const sdbusplus::exception_t& e)
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050094 {
95 lg2::error(
96 "D-Bus call exception OBJPATH={OBJPATH}, INTERFACE={INTERFACE}, "
97 "EXCEPTION={ERROR}",
98 "OBJPATH", loggingObjectPath, "INTERFACE", loggingInterface,
99 "ERROR", e);
100
101 throw;
102 }
103 catch (const std::exception& e)
104 {
105 throw;
106 }
107
108 return plid;
109}
110
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -0500111openpower::dump::pel::Severity convertSeverityToEnum(uint8_t severity)
112{
113 switch (severity)
114 {
115 case openpower::phal::FAPI2_ERRL_SEV_RECOVERED:
116 return openpower::dump::pel::Severity::Informational;
117 case openpower::phal::FAPI2_ERRL_SEV_PREDICTIVE:
118 return openpower::dump::pel::Severity::Warning;
119 case openpower::phal::FAPI2_ERRL_SEV_UNRECOVERABLE:
120 return openpower::dump::pel::Severity::Error;
121 default:
122 return openpower::dump::pel::Severity::Error;
123 }
124}
125
SwethaParasaed53dc72025-01-24 01:07:01 -0600126std::vector<uint32_t> processFFDCPackets(
127 const openpower::phal::sbeError_t& sbeError, const std::string& event,
128 openpower::dump::pel::FFDCData& pelAdditionalData)
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -0500129{
130 const auto& ffdcFileList = sbeError.getFfdcFileList();
SwethaParasaed53dc72025-01-24 01:07:01 -0600131 std::vector<uint32_t> logIdList;
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -0500132 for (const auto& [slid, ffdcTuple] : ffdcFileList)
133 {
134 uint8_t severity;
135 int fd;
136 std::filesystem::path path;
137 std::tie(severity, fd, path) = ffdcTuple;
138
139 Severity logSeverity = convertSeverityToEnum(severity);
140
Dhruvaraj Subhashchandranef646042024-05-03 09:25:03 -0500141 if (logSeverity != openpower::dump::pel::Severity::Informational)
142 {
143 lg2::info(
144 "Changing severity from {SEV_ORIG} to informational in the "
145 "dumping path",
146 "SEV_ORIG", logSeverity);
147 logSeverity = openpower::dump::pel::Severity::Informational;
148 }
149
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -0500150 PELFFDCInfo pelFFDCInfo;
151 pelFFDCInfo.emplace_back(
152 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
153 Create::FFDCFormat::Custom,
154 FFDC_FORMAT_SUBTYPE, FFDC_FORMAT_VERSION, fd));
155
156 auto logId = openpower::dump::pel::createSbeErrorPEL(
157 event, sbeError, pelAdditionalData, logSeverity);
158 lg2::info("Logged PEL {PELID} for SLID {SLID}", "PELID", logId, "SLID",
159 slid);
SwethaParasaed53dc72025-01-24 01:07:01 -0600160 logIdList.push_back(logId);
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -0500161 }
SwethaParasaed53dc72025-01-24 01:07:01 -0600162 return logIdList;
163}
164
165std::tuple<uint32_t, std::string> getLogInfo(uint32_t logId)
166{
167 uint32_t pelId;
168 std::string src;
169 try
170 {
171 auto bus = sdbusplus::bus::new_default();
172 const auto loggingEntryObjectPath =
173 std::string(loggingObjectPath) + "/entry/" + std::to_string(logId);
174 auto service =
175 util::getService(bus, entryInterface, loggingEntryObjectPath);
176 auto method =
177 bus.new_method_call(service.c_str(), loggingEntryObjectPath.c_str(),
178 "org.freedesktop.DBus.Properties", "Get");
179 method.append(opEntryInterface);
180 method.append("PlatformLogID");
181 auto response = bus.call(method);
182 std::variant<uint32_t, std::string> v;
183 response.read(v);
184 pelId = std::get<uint32_t>(v);
185 method =
186 bus.new_method_call(service.c_str(), loggingEntryObjectPath.c_str(),
187 "org.freedesktop.DBus.Properties", "Get");
188 method.append(entryInterface);
189 method.append("EventId");
190 response = bus.call(method);
191 response.read(v);
192 std::istringstream iss(std::get<std::string>(v));
193 iss >> src;
194 }
Patrick Williams535dfb22025-04-16 02:37:23 -0400195 catch (const sdbusplus::exception_t& e)
SwethaParasaed53dc72025-01-24 01:07:01 -0600196 {
197 lg2::error("D-Bus call exception "
198 "EXCEPTION={ERROR}",
199 "ERROR", e);
200 throw;
201 }
202 catch (const std::exception& e)
203 {
204 throw;
205 }
206
207 return std::tuple<uint32_t, std::string>(pelId, src);
Dhruvaraj Subhashchandranf2298892024-04-21 04:42:55 -0500208}
209
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500210FFDCFile::FFDCFile(const json& pHALCalloutData) :
211 calloutData(pHALCalloutData.dump()),
212 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
213{
214 prepareFFDCFile();
215}
216
217FFDCFile::~FFDCFile()
218{
219 removeCalloutFile();
220}
221
222int FFDCFile::getFileFD() const
223{
224 return fileFD;
225}
226
227void FFDCFile::prepareFFDCFile()
228{
229 createCalloutFile();
230 writeCalloutData();
231 setCalloutFileSeekPos();
232}
233
234void FFDCFile::createCalloutFile()
235{
236 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
237
238 if (fileFD == -1)
239 {
240 lg2::error("Failed to create phalPELCallouts file({FILE}), "
241 "errorno({ERRNO}) and errormsg({ERRORMSG})",
242 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
243 strerror(errno));
244 throw std::runtime_error("Failed to create phalPELCallouts file");
245 }
246}
247
248void FFDCFile::writeCalloutData()
249{
250 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
251
252 if (rc == -1)
253 {
254 lg2::error("Failed to write phaPELCallout info in file({FILE}), "
255 "errorno({ERRNO}), errormsg({ERRORMSG})",
256 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
257 strerror(errno));
258 throw std::runtime_error("Failed to write phalPELCallouts info");
259 }
260 else if (rc != static_cast<ssize_t>(calloutData.size()))
261 {
262 lg2::warning("Could not write all phal callout info in file({FILE}), "
263 "written byte({WRITTEN}), total byte({TOTAL})",
264 "FILE", calloutFile, "WRITTEN", rc, "TOTAL",
265 calloutData.size());
266 }
267}
268
269void FFDCFile::setCalloutFileSeekPos()
270{
271 int rc = lseek(fileFD, 0, SEEK_SET);
272
273 if (rc == -1)
274 {
275 lg2::error("Failed to set SEEK_SET for phalPELCallouts in "
276 "file({FILE}), errorno({ERRNO}), errormsg({ERRORMSG})",
277 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
278 strerror(errno));
279
280 throw std::runtime_error(
281 "Failed to set SEEK_SET for phalPELCallouts file");
282 }
283}
284
285void FFDCFile::removeCalloutFile()
286{
287 close(fileFD);
288 std::remove(calloutFile.c_str());
289}
290
291} // namespace openpower::dump::pel