blob: b3fdd4ec93f31810cb87c894e06dbdacc766b1e2 [file] [log] [blame]
Brad Bishopf6783cd2020-10-27 19:25:09 -04001#include "create_pel.hpp"
2
Jayanth Othayothc4831812021-06-08 01:33:40 -05003#include "util.hpp"
4
Brad Bishopf6783cd2020-10-27 19:25:09 -04005#include <fcntl.h>
6#include <fmt/format.h>
7#include <libekb.H>
8#include <unistd.h>
9
Brad Bishop5e5d4452020-10-27 19:46:13 -040010#include <phosphor-logging/elog.hpp>
11#include <xyz/openbmc_project/Logging/Create/server.hpp>
12#include <xyz/openbmc_project/Logging/Entry/server.hpp>
13
Brad Bishopf6783cd2020-10-27 19:25:09 -040014#include <cerrno>
15#include <cstdio>
16#include <cstdlib>
17#include <cstring>
18#include <map>
Brad Bishopf6783cd2020-10-27 19:25:09 -040019#include <stdexcept>
20#include <string>
21#include <tuple>
22#include <vector>
Brad Bishopf6783cd2020-10-27 19:25:09 -040023
24namespace openpower
25{
26using namespace phosphor::logging;
27
Brad Bishopf6783cd2020-10-27 19:25:09 -040028namespace pel
29{
Andrew Geissler61febf02021-06-22 17:19:32 -050030
31constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
32constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
Jayanth Othayothfe37aea2021-10-07 04:41:26 -050033constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";
Andrew Geissler61febf02021-06-22 17:19:32 -050034
Brad Bishopf6783cd2020-10-27 19:25:09 -040035void createBootErrorPEL(const FFDCData& ffdcData, const json& calloutData)
36{
Brad Bishopf6783cd2020-10-27 19:25:09 -040037 std::map<std::string, std::string> additionalData;
38 auto bus = sdbusplus::bus::new_default();
39 additionalData.emplace("_PID", std::to_string(getpid()));
40 for (auto& data : ffdcData)
41 {
42 additionalData.emplace(data);
43 }
44
45 try
46 {
47 FFDCFile ffdcFile(calloutData);
48
49 std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging::
50 server::Create::FFDCFormat,
51 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
52 pelCalloutInfo;
53
54 pelCalloutInfo.push_back(
55 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
56 Create::FFDCFormat::JSON,
57 static_cast<uint8_t>(0xCA),
58 static_cast<uint8_t>(0x01), ffdcFile.getFileFD()));
59
60 static constexpr auto bootErrorMessage =
61 "org.open_power.PHAL.Error.Boot";
62 std::string service =
63 util::getService(bus, loggingObjectPath, loggingInterface);
64 auto method =
65 bus.new_method_call(service.c_str(), loggingObjectPath,
66 loggingInterface, "CreateWithFFDCFiles");
67 auto level =
68 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
69 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
70 Error);
71 method.append(bootErrorMessage, level, additionalData, pelCalloutInfo);
72 auto resp = bus.call(method);
73 }
Patrick Williams2246cca2021-09-02 09:32:52 -050074 catch (const sdbusplus::exception::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -040075 {
76 log<level::ERR>("D-Bus call exception",
77 entry("OBJPATH=%s", loggingObjectPath),
78 entry("INTERFACE=%s", loggingInterface),
79 entry("EXCEPTION=%s", e.what()));
80
81 throw std::runtime_error(
82 "Error in invoking D-Bus logging create interface");
83 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -050084 catch (const std::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -040085 {
86 throw e;
87 }
88}
89
Jayanth Othayothfe37aea2021-10-07 04:41:26 -050090uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
91 const FFDCData& ffdcData)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -050092{
Jayanth Othayothfe37aea2021-10-07 04:41:26 -050093 uint32_t plid = 0;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -050094 std::map<std::string, std::string> additionalData;
95 auto bus = sdbusplus::bus::new_default();
96
97 additionalData.emplace("_PID", std::to_string(getpid()));
98 additionalData.emplace("SBE_ERR_MSG", sbeError.what());
99
100 for (auto& data : ffdcData)
101 {
102 additionalData.emplace(data);
103 }
104
105 std::vector<std::tuple<
106 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
107 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
108 pelFFDCInfo;
109
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500110 // get SBE ffdc file descriptor
111 auto fd = sbeError.getFd();
112
113 // Negative fd value indicates error case or invalid file
114 // No need of special processing , just log error with additional ffdc.
115 if (fd > 0)
116 {
117 // Refer phosphor-logging/extensions/openpower-pels/README.md section
118 // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
119 // for details of related to createPEL with SBE FFDC information
120 // usin g CreateWithFFDCFiles api.
121 pelFFDCInfo.push_back(
122 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
123 Create::FFDCFormat::Custom,
124 static_cast<uint8_t>(0xCB),
125 static_cast<uint8_t>(0x01), sbeError.getFd()));
126 }
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500127 try
128 {
129 std::string service =
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500130 util::getService(bus, loggingObjectPath, opLoggingInterface);
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500131 auto method =
132 bus.new_method_call(service.c_str(), loggingObjectPath,
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500133 opLoggingInterface, "CreatePELWithFFDCFiles");
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500134 auto level =
135 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
136 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
137 Error);
138 method.append(event, level, additionalData, pelFFDCInfo);
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500139 auto response = bus.call(method);
140
141 // reply will be tuple containing bmc log id, platform log id
142 std::tuple<uint32_t, uint32_t> reply = {0, 0};
143
144 // parse dbus response into reply
145 response.read(reply);
146 plid = std::get<1>(reply); // platform log id is tuple "second"
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500147 }
148 catch (const sdbusplus::exception::exception& e)
149 {
150 log<level::ERR>(fmt::format("D-Bus call exception",
151 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
152 loggingObjectPath, loggingInterface,
153 e.what())
154 .c_str());
155 throw std::runtime_error(
156 "Error in invoking D-Bus logging create interface");
157 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500158 catch (const std::exception& e)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500159 {
160 throw e;
161 }
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500162
163 return plid;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500164}
165
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500166void createPEL(const std::string& event, const FFDCData& ffdcData)
Andrew Geissler61febf02021-06-22 17:19:32 -0500167{
168 std::map<std::string, std::string> additionalData;
169 auto bus = sdbusplus::bus::new_default();
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500170
Andrew Geissler61febf02021-06-22 17:19:32 -0500171 additionalData.emplace("_PID", std::to_string(getpid()));
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500172 for (auto& data : ffdcData)
173 {
174 additionalData.emplace(data);
175 }
Andrew Geissler61febf02021-06-22 17:19:32 -0500176
177 try
178 {
Andrew Geissler61febf02021-06-22 17:19:32 -0500179 std::string service =
180 util::getService(bus, loggingObjectPath, loggingInterface);
181 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
182 loggingInterface, "Create");
183 auto level =
184 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
185 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
186 Error);
Jayanth Othayothac95c562021-07-16 05:56:04 -0500187 method.append(event, level, additionalData);
Andrew Geissler61febf02021-06-22 17:19:32 -0500188 auto resp = bus.call(method);
189 }
Patrick Williams2246cca2021-09-02 09:32:52 -0500190 catch (const sdbusplus::exception::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500191 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500192 log<level::ERR>(fmt::format("sdbusplus D-Bus call exception",
193 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
194 loggingObjectPath, loggingInterface,
195 e.what())
196 .c_str());
197 ;
Andrew Geissler61febf02021-06-22 17:19:32 -0500198
199 throw std::runtime_error(
200 "Error in invoking D-Bus logging create interface");
201 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500202 catch (const std::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500203 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500204 log<level::ERR>(
205 fmt::format("D-bus call exception", "EXCEPTION={}", e.what())
206 .c_str());
Andrew Geissler61febf02021-06-22 17:19:32 -0500207 throw e;
208 }
209}
210
Brad Bishopf6783cd2020-10-27 19:25:09 -0400211FFDCFile::FFDCFile(const json& pHALCalloutData) :
212 calloutData(pHALCalloutData.dump()),
213 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
214{
215 prepareFFDCFile();
216}
217
218FFDCFile::~FFDCFile()
219{
220 removeCalloutFile();
221}
222
223int FFDCFile::getFileFD() const
224{
225 return fileFD;
226}
227
228void FFDCFile::prepareFFDCFile()
229{
230 createCalloutFile();
231 writeCalloutData();
232 setCalloutFileSeekPos();
233}
234
235void FFDCFile::createCalloutFile()
236{
237 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
238
239 if (fileFD == -1)
240 {
241 log<level::ERR>(fmt::format("Failed to create phalPELCallouts "
242 "file({}), errorno({}) and errormsg({})",
243 calloutFile, errno, strerror(errno))
244 .c_str());
245 throw std::runtime_error("Failed to create phalPELCallouts file");
246 }
247}
248
249void FFDCFile::writeCalloutData()
250{
251 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
252
253 if (rc == -1)
254 {
255 log<level::ERR>(fmt::format("Failed to write phaPELCallout info "
256 "in file({}), errorno({}), errormsg({})",
257 calloutFile, errno, strerror(errno))
258 .c_str());
259 throw std::runtime_error("Failed to write phalPELCallouts info");
260 }
261 else if (rc != static_cast<ssize_t>(calloutData.size()))
262 {
263 log<level::WARNING>(fmt::format("Could not write all phal callout "
264 "info in file({}), written byte({}) "
265 "and total byte({})",
266 calloutFile, rc, calloutData.size())
267 .c_str());
268 }
269}
270
271void FFDCFile::setCalloutFileSeekPos()
272{
273 int rc = lseek(fileFD, 0, SEEK_SET);
274
275 if (rc == -1)
276 {
277 log<level::ERR>(fmt::format("Failed to set SEEK_SET for "
278 "phalPELCallouts in file({}), errorno({}) "
279 "and errormsg({})",
280 calloutFile, errno, strerror(errno))
281 .c_str());
282 throw std::runtime_error(
283 "Failed to set SEEK_SET for phalPELCallouts file");
284 }
285}
286
287void FFDCFile::removeCalloutFile()
288{
289 close(fileFD);
290 std::remove(calloutFile.c_str());
291}
292
293} // namespace pel
294} // namespace openpower