blob: 95ee7ae33218b1d44da9c8bdf6f2b66cbfad818e [file] [log] [blame]
Brad Bishopf6783cd2020-10-27 19:25:09 -04001#include "create_pel.hpp"
2
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -06003#include "attributes_info.H"
4
Jayanth Othayothc4831812021-06-08 01:33:40 -05005#include "util.hpp"
6
Brad Bishopf6783cd2020-10-27 19:25:09 -04007#include <fcntl.h>
8#include <fmt/format.h>
9#include <libekb.H>
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -060010#include <libphal.H>
Brad Bishopf6783cd2020-10-27 19:25:09 -040011#include <unistd.h>
12
Brad Bishop5e5d4452020-10-27 19:46:13 -040013#include <phosphor-logging/elog.hpp>
14#include <xyz/openbmc_project/Logging/Create/server.hpp>
15#include <xyz/openbmc_project/Logging/Entry/server.hpp>
16
Brad Bishopf6783cd2020-10-27 19:25:09 -040017#include <cerrno>
18#include <cstdio>
19#include <cstdlib>
20#include <cstring>
21#include <map>
Brad Bishopf6783cd2020-10-27 19:25:09 -040022#include <stdexcept>
23#include <string>
24#include <tuple>
25#include <vector>
Brad Bishopf6783cd2020-10-27 19:25:09 -040026
27namespace openpower
28{
29using namespace phosphor::logging;
30
Brad Bishopf6783cd2020-10-27 19:25:09 -040031namespace pel
32{
Andrew Geissler61febf02021-06-22 17:19:32 -050033
34constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
35constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
Jayanth Othayothfe37aea2021-10-07 04:41:26 -050036constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";
Andrew Geissler61febf02021-06-22 17:19:32 -050037
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -060038/**
39 * @brief get SBE special callout information
40 *
41 * This function add the special sbe callout in the user provided
42 * json callout list. includes BMC0002 procedure callout with
43 * high priority and processor callout with medium priority.
44 *
45 * @param[in] procTarget - pdbg processor target
46 * @param[out] jsonCalloutDataList - reference to json callout list
47 */
48static void getSBECallout(struct pdbg_target* procTarget,
49 json& jsonCalloutDataList)
50{
51 using namespace openpower::phal::pdbg;
52
53 json jsonProcedCallout;
54
55 // Add procedure callout
56 jsonProcedCallout["Procedure"] = "BMC0002";
57 jsonProcedCallout["Priority"] = "H";
58 jsonCalloutDataList.emplace_back(std::move(jsonProcedCallout));
59 try
60 {
61 ATTR_LOCATION_CODE_Type locationCode;
62 // Initialize with default data.
63 memset(&locationCode, '\0', sizeof(locationCode));
64 // Get location code information
65 openpower::phal::pdbg::getLocationCode(procTarget, locationCode);
66 json jsonProcCallout;
67 jsonProcCallout["LocationCode"] = locationCode;
68 jsonProcCallout["Deconfigured"] = false;
69 jsonProcCallout["Guarded"] = false;
70 jsonProcCallout["Priority"] = "M";
71 jsonCalloutDataList.emplace_back(std::move(jsonProcCallout));
72 }
73 catch (const std::exception& e)
74 {
75 log<level::ERR>(fmt::format("getLocationCode({}): Exception({})",
76 pdbg_target_path(procTarget), e.what())
77 .c_str());
78 }
79}
80
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -060081void createErrorPEL(const std::string& event, const json& calloutData,
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -050082 const FFDCData& ffdcData, const Severity severity)
Brad Bishopf6783cd2020-10-27 19:25:09 -040083{
Brad Bishopf6783cd2020-10-27 19:25:09 -040084 std::map<std::string, std::string> additionalData;
85 auto bus = sdbusplus::bus::new_default();
86 additionalData.emplace("_PID", std::to_string(getpid()));
87 for (auto& data : ffdcData)
88 {
89 additionalData.emplace(data);
90 }
91
92 try
93 {
94 FFDCFile ffdcFile(calloutData);
95
96 std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging::
97 server::Create::FFDCFormat,
98 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
99 pelCalloutInfo;
100
101 pelCalloutInfo.push_back(
102 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
103 Create::FFDCFormat::JSON,
104 static_cast<uint8_t>(0xCA),
105 static_cast<uint8_t>(0x01), ffdcFile.getFileFD()));
106
Patrick Williams00dd33e2023-05-10 07:50:37 -0500107 std::string service = util::getService(bus, loggingObjectPath,
108 loggingInterface);
109 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
110 loggingInterface,
111 "CreateWithFFDCFiles");
Brad Bishopf6783cd2020-10-27 19:25:09 -0400112 auto level =
113 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500114 severity);
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -0600115 method.append(event, level, additionalData, pelCalloutInfo);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400116 auto resp = bus.call(method);
117 }
Patrick Williamsaaea6862022-07-22 19:26:54 -0500118 catch (const sdbusplus::exception_t& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400119 {
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -0600120 log<level::ERR>(
121 fmt::format("D-Bus call exception",
122 "OBJPATH={}, INTERFACE={}, event={}, EXCEPTION={}",
123 loggingObjectPath, loggingInterface, event, e.what())
124 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -0400125 throw std::runtime_error(
126 "Error in invoking D-Bus logging create interface");
127 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500128 catch (const std::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400129 {
130 throw e;
131 }
132}
133
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500134uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -0600135 const FFDCData& ffdcData,
136 struct pdbg_target* procTarget,
137 const Severity severity)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500138{
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500139 uint32_t plid = 0;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500140 std::map<std::string, std::string> additionalData;
141 auto bus = sdbusplus::bus::new_default();
142
143 additionalData.emplace("_PID", std::to_string(getpid()));
144 additionalData.emplace("SBE_ERR_MSG", sbeError.what());
145
146 for (auto& data : ffdcData)
147 {
148 additionalData.emplace(data);
149 }
150
151 std::vector<std::tuple<
152 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
153 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
154 pelFFDCInfo;
155
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500156 // get SBE ffdc file descriptor
157 auto fd = sbeError.getFd();
158
159 // Negative fd value indicates error case or invalid file
160 // No need of special processing , just log error with additional ffdc.
161 if (fd > 0)
162 {
163 // Refer phosphor-logging/extensions/openpower-pels/README.md section
164 // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
165 // for details of related to createPEL with SBE FFDC information
166 // usin g CreateWithFFDCFiles api.
167 pelFFDCInfo.push_back(
168 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
169 Create::FFDCFormat::Custom,
170 static_cast<uint8_t>(0xCB),
171 static_cast<uint8_t>(0x01), sbeError.getFd()));
172 }
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -0600173
174 // Workaround : currently sbe_extract_rc hwp procedure based callout
175 // handling is not available. openbmc issue #2917
176 // As per discussion with RAS team adding additional callout for
177 // SBE timeout error case, till this hwp based error handling in place.
178 // Note: PEL needs ffdcFile file till pel creation. This is forced to
179 // define ffdcFile function level scope.
180 std::unique_ptr<FFDCFile> FFDCFilePtr;
181 try
182 {
Jayanth Othayoth8e93c1c2022-06-02 08:59:08 -0500183 if ((event == "org.open_power.Processor.Error.SbeBootTimeout") &&
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -0600184 (severity == Severity::Error))
185 {
186 json jsonCalloutDataList;
187 jsonCalloutDataList = json::array();
188 getSBECallout(procTarget, jsonCalloutDataList);
189 FFDCFilePtr = std::make_unique<FFDCFile>(jsonCalloutDataList);
190 pelFFDCInfo.push_back(std::make_tuple(
191 sdbusplus::xyz::openbmc_project::Logging::server::Create::
192 FFDCFormat::JSON,
193 static_cast<uint8_t>(0xCA), static_cast<uint8_t>(0x01),
194 FFDCFilePtr->getFileFD()));
195 }
196 }
197 catch (const std::exception& e)
198 {
199 log<level::ERR>(
200 fmt::format("Skipping SBE special callout due to Exception({})",
201 e.what())
202 .c_str());
203 }
204
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500205 try
206 {
Patrick Williams00dd33e2023-05-10 07:50:37 -0500207 std::string service = util::getService(bus, loggingObjectPath,
208 opLoggingInterface);
209 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
210 opLoggingInterface,
211 "CreatePELWithFFDCFiles");
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500212 auto level =
213 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Marri Devender Rao2b30dea2021-12-17 02:38:30 -0600214 severity);
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500215 method.append(event, level, additionalData, pelFFDCInfo);
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500216 auto response = bus.call(method);
217
218 // reply will be tuple containing bmc log id, platform log id
219 std::tuple<uint32_t, uint32_t> reply = {0, 0};
220
221 // parse dbus response into reply
222 response.read(reply);
223 plid = std::get<1>(reply); // platform log id is tuple "second"
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500224 }
Patrick Williamsaaea6862022-07-22 19:26:54 -0500225 catch (const sdbusplus::exception_t& e)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500226 {
227 log<level::ERR>(fmt::format("D-Bus call exception",
228 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
229 loggingObjectPath, loggingInterface,
230 e.what())
231 .c_str());
232 throw std::runtime_error(
233 "Error in invoking D-Bus logging create interface");
234 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500235 catch (const std::exception& e)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500236 {
237 throw e;
238 }
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500239 return plid;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500240}
241
Matt Spinlerbe14ec22023-03-24 15:59:48 -0500242void createPEL(const std::string& event, const FFDCData& ffdcData,
243 const Severity severity)
Andrew Geissler61febf02021-06-22 17:19:32 -0500244{
245 std::map<std::string, std::string> additionalData;
246 auto bus = sdbusplus::bus::new_default();
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500247
Andrew Geissler61febf02021-06-22 17:19:32 -0500248 additionalData.emplace("_PID", std::to_string(getpid()));
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500249 for (auto& data : ffdcData)
250 {
251 additionalData.emplace(data);
252 }
Andrew Geissler61febf02021-06-22 17:19:32 -0500253
254 try
255 {
Patrick Williams00dd33e2023-05-10 07:50:37 -0500256 std::string service = util::getService(bus, loggingObjectPath,
257 loggingInterface);
Andrew Geissler61febf02021-06-22 17:19:32 -0500258 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
259 loggingInterface, "Create");
260 auto level =
261 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Matt Spinlerbe14ec22023-03-24 15:59:48 -0500262 severity);
Jayanth Othayothac95c562021-07-16 05:56:04 -0500263 method.append(event, level, additionalData);
Andrew Geissler61febf02021-06-22 17:19:32 -0500264 auto resp = bus.call(method);
265 }
Patrick Williamsaaea6862022-07-22 19:26:54 -0500266 catch (const sdbusplus::exception_t& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500267 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500268 log<level::ERR>(fmt::format("sdbusplus D-Bus call exception",
269 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
270 loggingObjectPath, loggingInterface,
271 e.what())
272 .c_str());
273 ;
Andrew Geissler61febf02021-06-22 17:19:32 -0500274
275 throw std::runtime_error(
276 "Error in invoking D-Bus logging create interface");
277 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500278 catch (const std::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500279 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500280 log<level::ERR>(
281 fmt::format("D-bus call exception", "EXCEPTION={}", e.what())
282 .c_str());
Andrew Geissler61febf02021-06-22 17:19:32 -0500283 throw e;
284 }
285}
286
Brad Bishopf6783cd2020-10-27 19:25:09 -0400287FFDCFile::FFDCFile(const json& pHALCalloutData) :
288 calloutData(pHALCalloutData.dump()),
289 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
290{
291 prepareFFDCFile();
292}
293
294FFDCFile::~FFDCFile()
295{
296 removeCalloutFile();
297}
298
299int FFDCFile::getFileFD() const
300{
301 return fileFD;
302}
303
304void FFDCFile::prepareFFDCFile()
305{
306 createCalloutFile();
307 writeCalloutData();
308 setCalloutFileSeekPos();
309}
310
311void FFDCFile::createCalloutFile()
312{
313 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
314
315 if (fileFD == -1)
316 {
317 log<level::ERR>(fmt::format("Failed to create phalPELCallouts "
318 "file({}), errorno({}) and errormsg({})",
319 calloutFile, errno, strerror(errno))
320 .c_str());
321 throw std::runtime_error("Failed to create phalPELCallouts file");
322 }
323}
324
325void FFDCFile::writeCalloutData()
326{
327 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
328
329 if (rc == -1)
330 {
331 log<level::ERR>(fmt::format("Failed to write phaPELCallout info "
332 "in file({}), errorno({}), errormsg({})",
333 calloutFile, errno, strerror(errno))
334 .c_str());
335 throw std::runtime_error("Failed to write phalPELCallouts info");
336 }
337 else if (rc != static_cast<ssize_t>(calloutData.size()))
338 {
339 log<level::WARNING>(fmt::format("Could not write all phal callout "
340 "info in file({}), written byte({}) "
341 "and total byte({})",
342 calloutFile, rc, calloutData.size())
343 .c_str());
344 }
345}
346
347void FFDCFile::setCalloutFileSeekPos()
348{
349 int rc = lseek(fileFD, 0, SEEK_SET);
350
351 if (rc == -1)
352 {
353 log<level::ERR>(fmt::format("Failed to set SEEK_SET for "
354 "phalPELCallouts in file({}), errorno({}) "
355 "and errormsg({})",
356 calloutFile, errno, strerror(errno))
357 .c_str());
358 throw std::runtime_error(
359 "Failed to set SEEK_SET for phalPELCallouts file");
360 }
361}
362
363void FFDCFile::removeCalloutFile()
364{
365 close(fileFD);
366 std::remove(calloutFile.c_str());
367}
368
369} // namespace pel
370} // namespace openpower