blob: 8638d5ca22a8bdd83f068382350083a3058243d3 [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,
82 const FFDCData& ffdcData)
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
Brad Bishopf6783cd2020-10-27 19:25:09 -0400107 std::string service =
108 util::getService(bus, loggingObjectPath, loggingInterface);
109 auto method =
110 bus.new_method_call(service.c_str(), loggingObjectPath,
111 loggingInterface, "CreateWithFFDCFiles");
112 auto level =
113 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
114 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
115 Error);
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -0600116 method.append(event, level, additionalData, pelCalloutInfo);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400117 auto resp = bus.call(method);
118 }
Patrick Williams2246cca2021-09-02 09:32:52 -0500119 catch (const sdbusplus::exception::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400120 {
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -0600121 log<level::ERR>(
122 fmt::format("D-Bus call exception",
123 "OBJPATH={}, INTERFACE={}, event={}, EXCEPTION={}",
124 loggingObjectPath, loggingInterface, event, e.what())
125 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -0400126 throw std::runtime_error(
127 "Error in invoking D-Bus logging create interface");
128 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500129 catch (const std::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400130 {
131 throw e;
132 }
133}
134
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500135uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -0600136 const FFDCData& ffdcData,
137 struct pdbg_target* procTarget,
138 const Severity severity)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500139{
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500140 uint32_t plid = 0;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500141 std::map<std::string, std::string> additionalData;
142 auto bus = sdbusplus::bus::new_default();
143
144 additionalData.emplace("_PID", std::to_string(getpid()));
145 additionalData.emplace("SBE_ERR_MSG", sbeError.what());
146
147 for (auto& data : ffdcData)
148 {
149 additionalData.emplace(data);
150 }
151
152 std::vector<std::tuple<
153 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
154 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
155 pelFFDCInfo;
156
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500157 // get SBE ffdc file descriptor
158 auto fd = sbeError.getFd();
159
160 // Negative fd value indicates error case or invalid file
161 // No need of special processing , just log error with additional ffdc.
162 if (fd > 0)
163 {
164 // Refer phosphor-logging/extensions/openpower-pels/README.md section
165 // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
166 // for details of related to createPEL with SBE FFDC information
167 // usin g CreateWithFFDCFiles api.
168 pelFFDCInfo.push_back(
169 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
170 Create::FFDCFormat::Custom,
171 static_cast<uint8_t>(0xCB),
172 static_cast<uint8_t>(0x01), sbeError.getFd()));
173 }
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -0600174
175 // Workaround : currently sbe_extract_rc hwp procedure based callout
176 // handling is not available. openbmc issue #2917
177 // As per discussion with RAS team adding additional callout for
178 // SBE timeout error case, till this hwp based error handling in place.
179 // Note: PEL needs ffdcFile file till pel creation. This is forced to
180 // define ffdcFile function level scope.
181 std::unique_ptr<FFDCFile> FFDCFilePtr;
182 try
183 {
184 if ((event == "org.open_power.Processor.Error.SbeBootTimeout") &&
185 (severity == Severity::Error))
186 {
187 json jsonCalloutDataList;
188 jsonCalloutDataList = json::array();
189 getSBECallout(procTarget, jsonCalloutDataList);
190 FFDCFilePtr = std::make_unique<FFDCFile>(jsonCalloutDataList);
191 pelFFDCInfo.push_back(std::make_tuple(
192 sdbusplus::xyz::openbmc_project::Logging::server::Create::
193 FFDCFormat::JSON,
194 static_cast<uint8_t>(0xCA), static_cast<uint8_t>(0x01),
195 FFDCFilePtr->getFileFD()));
196 }
197 }
198 catch (const std::exception& e)
199 {
200 log<level::ERR>(
201 fmt::format("Skipping SBE special callout due to Exception({})",
202 e.what())
203 .c_str());
204 }
205
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500206 try
207 {
208 std::string service =
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500209 util::getService(bus, loggingObjectPath, opLoggingInterface);
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500210 auto method =
211 bus.new_method_call(service.c_str(), loggingObjectPath,
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500212 opLoggingInterface, "CreatePELWithFFDCFiles");
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500213 auto level =
214 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Marri Devender Rao2b30dea2021-12-17 02:38:30 -0600215 severity);
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500216 method.append(event, level, additionalData, pelFFDCInfo);
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500217 auto response = bus.call(method);
218
219 // reply will be tuple containing bmc log id, platform log id
220 std::tuple<uint32_t, uint32_t> reply = {0, 0};
221
222 // parse dbus response into reply
223 response.read(reply);
224 plid = std::get<1>(reply); // platform log id is tuple "second"
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500225 }
226 catch (const sdbusplus::exception::exception& e)
227 {
228 log<level::ERR>(fmt::format("D-Bus call exception",
229 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
230 loggingObjectPath, loggingInterface,
231 e.what())
232 .c_str());
233 throw std::runtime_error(
234 "Error in invoking D-Bus logging create interface");
235 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500236 catch (const std::exception& e)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500237 {
238 throw e;
239 }
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500240 return plid;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500241}
242
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500243void createPEL(const std::string& event, const FFDCData& ffdcData)
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 {
Andrew Geissler61febf02021-06-22 17:19:32 -0500256 std::string service =
257 util::getService(bus, loggingObjectPath, loggingInterface);
258 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
259 loggingInterface, "Create");
260 auto level =
261 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
262 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
263 Error);
Jayanth Othayothac95c562021-07-16 05:56:04 -0500264 method.append(event, level, additionalData);
Andrew Geissler61febf02021-06-22 17:19:32 -0500265 auto resp = bus.call(method);
266 }
Patrick Williams2246cca2021-09-02 09:32:52 -0500267 catch (const sdbusplus::exception::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500268 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500269 log<level::ERR>(fmt::format("sdbusplus D-Bus call exception",
270 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
271 loggingObjectPath, loggingInterface,
272 e.what())
273 .c_str());
274 ;
Andrew Geissler61febf02021-06-22 17:19:32 -0500275
276 throw std::runtime_error(
277 "Error in invoking D-Bus logging create interface");
278 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500279 catch (const std::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500280 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500281 log<level::ERR>(
282 fmt::format("D-bus call exception", "EXCEPTION={}", e.what())
283 .c_str());
Andrew Geissler61febf02021-06-22 17:19:32 -0500284 throw e;
285 }
286}
287
Brad Bishopf6783cd2020-10-27 19:25:09 -0400288FFDCFile::FFDCFile(const json& pHALCalloutData) :
289 calloutData(pHALCalloutData.dump()),
290 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
291{
292 prepareFFDCFile();
293}
294
295FFDCFile::~FFDCFile()
296{
297 removeCalloutFile();
298}
299
300int FFDCFile::getFileFD() const
301{
302 return fileFD;
303}
304
305void FFDCFile::prepareFFDCFile()
306{
307 createCalloutFile();
308 writeCalloutData();
309 setCalloutFileSeekPos();
310}
311
312void FFDCFile::createCalloutFile()
313{
314 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
315
316 if (fileFD == -1)
317 {
318 log<level::ERR>(fmt::format("Failed to create phalPELCallouts "
319 "file({}), errorno({}) and errormsg({})",
320 calloutFile, errno, strerror(errno))
321 .c_str());
322 throw std::runtime_error("Failed to create phalPELCallouts file");
323 }
324}
325
326void FFDCFile::writeCalloutData()
327{
328 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
329
330 if (rc == -1)
331 {
332 log<level::ERR>(fmt::format("Failed to write phaPELCallout info "
333 "in file({}), errorno({}), errormsg({})",
334 calloutFile, errno, strerror(errno))
335 .c_str());
336 throw std::runtime_error("Failed to write phalPELCallouts info");
337 }
338 else if (rc != static_cast<ssize_t>(calloutData.size()))
339 {
340 log<level::WARNING>(fmt::format("Could not write all phal callout "
341 "info in file({}), written byte({}) "
342 "and total byte({})",
343 calloutFile, rc, calloutData.size())
344 .c_str());
345 }
346}
347
348void FFDCFile::setCalloutFileSeekPos()
349{
350 int rc = lseek(fileFD, 0, SEEK_SET);
351
352 if (rc == -1)
353 {
354 log<level::ERR>(fmt::format("Failed to set SEEK_SET for "
355 "phalPELCallouts in file({}), errorno({}) "
356 "and errormsg({})",
357 calloutFile, errno, strerror(errno))
358 .c_str());
359 throw std::runtime_error(
360 "Failed to set SEEK_SET for phalPELCallouts file");
361 }
362}
363
364void FFDCFile::removeCalloutFile()
365{
366 close(fileFD);
367 std::remove(calloutFile.c_str());
368}
369
370} // namespace pel
371} // namespace openpower