blob: 13be9ba8c3a65c5053c5a3351dd61393c31d175d [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
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -060035void createErrorPEL(const std::string& event, const json& calloutData,
36 const FFDCData& ffdcData)
Brad Bishopf6783cd2020-10-27 19:25:09 -040037{
Brad Bishopf6783cd2020-10-27 19:25:09 -040038 std::map<std::string, std::string> additionalData;
39 auto bus = sdbusplus::bus::new_default();
40 additionalData.emplace("_PID", std::to_string(getpid()));
41 for (auto& data : ffdcData)
42 {
43 additionalData.emplace(data);
44 }
45
46 try
47 {
48 FFDCFile ffdcFile(calloutData);
49
50 std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging::
51 server::Create::FFDCFormat,
52 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
53 pelCalloutInfo;
54
55 pelCalloutInfo.push_back(
56 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
57 Create::FFDCFormat::JSON,
58 static_cast<uint8_t>(0xCA),
59 static_cast<uint8_t>(0x01), ffdcFile.getFileFD()));
60
Brad Bishopf6783cd2020-10-27 19:25:09 -040061 std::string service =
62 util::getService(bus, loggingObjectPath, loggingInterface);
63 auto method =
64 bus.new_method_call(service.c_str(), loggingObjectPath,
65 loggingInterface, "CreateWithFFDCFiles");
66 auto level =
67 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
68 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
69 Error);
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -060070 method.append(event, level, additionalData, pelCalloutInfo);
Brad Bishopf6783cd2020-10-27 19:25:09 -040071 auto resp = bus.call(method);
72 }
Patrick Williams2246cca2021-09-02 09:32:52 -050073 catch (const sdbusplus::exception::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -040074 {
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -060075 log<level::ERR>(
76 fmt::format("D-Bus call exception",
77 "OBJPATH={}, INTERFACE={}, event={}, EXCEPTION={}",
78 loggingObjectPath, loggingInterface, event, e.what())
79 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -040080 throw std::runtime_error(
81 "Error in invoking D-Bus logging create interface");
82 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -050083 catch (const std::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -040084 {
85 throw e;
86 }
87}
88
Jayanth Othayothfe37aea2021-10-07 04:41:26 -050089uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
Marri Devender Rao2b30dea2021-12-17 02:38:30 -060090 const FFDCData& ffdcData, const Severity severity)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -050091{
Jayanth Othayothfe37aea2021-10-07 04:41:26 -050092 uint32_t plid = 0;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -050093 std::map<std::string, std::string> additionalData;
94 auto bus = sdbusplus::bus::new_default();
95
96 additionalData.emplace("_PID", std::to_string(getpid()));
97 additionalData.emplace("SBE_ERR_MSG", sbeError.what());
98
99 for (auto& data : ffdcData)
100 {
101 additionalData.emplace(data);
102 }
103
104 std::vector<std::tuple<
105 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
106 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
107 pelFFDCInfo;
108
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500109 // get SBE ffdc file descriptor
110 auto fd = sbeError.getFd();
111
112 // Negative fd value indicates error case or invalid file
113 // No need of special processing , just log error with additional ffdc.
114 if (fd > 0)
115 {
116 // Refer phosphor-logging/extensions/openpower-pels/README.md section
117 // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
118 // for details of related to createPEL with SBE FFDC information
119 // usin g CreateWithFFDCFiles api.
120 pelFFDCInfo.push_back(
121 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
122 Create::FFDCFormat::Custom,
123 static_cast<uint8_t>(0xCB),
124 static_cast<uint8_t>(0x01), sbeError.getFd()));
125 }
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500126 try
127 {
128 std::string service =
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500129 util::getService(bus, loggingObjectPath, opLoggingInterface);
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500130 auto method =
131 bus.new_method_call(service.c_str(), loggingObjectPath,
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500132 opLoggingInterface, "CreatePELWithFFDCFiles");
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500133 auto level =
134 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Marri Devender Rao2b30dea2021-12-17 02:38:30 -0600135 severity);
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500136 method.append(event, level, additionalData, pelFFDCInfo);
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500137 auto response = bus.call(method);
138
139 // reply will be tuple containing bmc log id, platform log id
140 std::tuple<uint32_t, uint32_t> reply = {0, 0};
141
142 // parse dbus response into reply
143 response.read(reply);
144 plid = std::get<1>(reply); // platform log id is tuple "second"
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500145 }
146 catch (const sdbusplus::exception::exception& e)
147 {
148 log<level::ERR>(fmt::format("D-Bus call exception",
149 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
150 loggingObjectPath, loggingInterface,
151 e.what())
152 .c_str());
153 throw std::runtime_error(
154 "Error in invoking D-Bus logging create interface");
155 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500156 catch (const std::exception& e)
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500157 {
158 throw e;
159 }
Jayanth Othayothfe37aea2021-10-07 04:41:26 -0500160
161 return plid;
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -0500162}
163
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500164void createPEL(const std::string& event, const FFDCData& ffdcData)
Andrew Geissler61febf02021-06-22 17:19:32 -0500165{
166 std::map<std::string, std::string> additionalData;
167 auto bus = sdbusplus::bus::new_default();
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500168
Andrew Geissler61febf02021-06-22 17:19:32 -0500169 additionalData.emplace("_PID", std::to_string(getpid()));
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500170 for (auto& data : ffdcData)
171 {
172 additionalData.emplace(data);
173 }
Andrew Geissler61febf02021-06-22 17:19:32 -0500174
175 try
176 {
Andrew Geissler61febf02021-06-22 17:19:32 -0500177 std::string service =
178 util::getService(bus, loggingObjectPath, loggingInterface);
179 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
180 loggingInterface, "Create");
181 auto level =
182 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
183 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
184 Error);
Jayanth Othayothac95c562021-07-16 05:56:04 -0500185 method.append(event, level, additionalData);
Andrew Geissler61febf02021-06-22 17:19:32 -0500186 auto resp = bus.call(method);
187 }
Patrick Williams2246cca2021-09-02 09:32:52 -0500188 catch (const sdbusplus::exception::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500189 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500190 log<level::ERR>(fmt::format("sdbusplus D-Bus call exception",
191 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
192 loggingObjectPath, loggingInterface,
193 e.what())
194 .c_str());
195 ;
Andrew Geissler61febf02021-06-22 17:19:32 -0500196
197 throw std::runtime_error(
198 "Error in invoking D-Bus logging create interface");
199 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500200 catch (const std::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500201 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500202 log<level::ERR>(
203 fmt::format("D-bus call exception", "EXCEPTION={}", e.what())
204 .c_str());
Andrew Geissler61febf02021-06-22 17:19:32 -0500205 throw e;
206 }
207}
208
Brad Bishopf6783cd2020-10-27 19:25:09 -0400209FFDCFile::FFDCFile(const json& pHALCalloutData) :
210 calloutData(pHALCalloutData.dump()),
211 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
212{
213 prepareFFDCFile();
214}
215
216FFDCFile::~FFDCFile()
217{
218 removeCalloutFile();
219}
220
221int FFDCFile::getFileFD() const
222{
223 return fileFD;
224}
225
226void FFDCFile::prepareFFDCFile()
227{
228 createCalloutFile();
229 writeCalloutData();
230 setCalloutFileSeekPos();
231}
232
233void FFDCFile::createCalloutFile()
234{
235 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
236
237 if (fileFD == -1)
238 {
239 log<level::ERR>(fmt::format("Failed to create phalPELCallouts "
240 "file({}), errorno({}) and errormsg({})",
241 calloutFile, errno, strerror(errno))
242 .c_str());
243 throw std::runtime_error("Failed to create phalPELCallouts file");
244 }
245}
246
247void FFDCFile::writeCalloutData()
248{
249 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
250
251 if (rc == -1)
252 {
253 log<level::ERR>(fmt::format("Failed to write phaPELCallout info "
254 "in file({}), errorno({}), errormsg({})",
255 calloutFile, errno, strerror(errno))
256 .c_str());
257 throw std::runtime_error("Failed to write phalPELCallouts info");
258 }
259 else if (rc != static_cast<ssize_t>(calloutData.size()))
260 {
261 log<level::WARNING>(fmt::format("Could not write all phal callout "
262 "info in file({}), written byte({}) "
263 "and total byte({})",
264 calloutFile, rc, calloutData.size())
265 .c_str());
266 }
267}
268
269void FFDCFile::setCalloutFileSeekPos()
270{
271 int rc = lseek(fileFD, 0, SEEK_SET);
272
273 if (rc == -1)
274 {
275 log<level::ERR>(fmt::format("Failed to set SEEK_SET for "
276 "phalPELCallouts in file({}), errorno({}) "
277 "and errormsg({})",
278 calloutFile, errno, strerror(errno))
279 .c_str());
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 pel
292} // namespace openpower