blob: c10f32c78c66e324e3670a580826ca841288c8e5 [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";
33
Brad Bishopf6783cd2020-10-27 19:25:09 -040034void createBootErrorPEL(const FFDCData& ffdcData, const json& calloutData)
35{
Brad Bishopf6783cd2020-10-27 19:25:09 -040036 std::map<std::string, std::string> additionalData;
37 auto bus = sdbusplus::bus::new_default();
38 additionalData.emplace("_PID", std::to_string(getpid()));
39 for (auto& data : ffdcData)
40 {
41 additionalData.emplace(data);
42 }
43
44 try
45 {
46 FFDCFile ffdcFile(calloutData);
47
48 std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging::
49 server::Create::FFDCFormat,
50 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
51 pelCalloutInfo;
52
53 pelCalloutInfo.push_back(
54 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
55 Create::FFDCFormat::JSON,
56 static_cast<uint8_t>(0xCA),
57 static_cast<uint8_t>(0x01), ffdcFile.getFileFD()));
58
59 static constexpr auto bootErrorMessage =
60 "org.open_power.PHAL.Error.Boot";
61 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);
70 method.append(bootErrorMessage, level, additionalData, pelCalloutInfo);
71 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 {
75 log<level::ERR>("D-Bus call exception",
76 entry("OBJPATH=%s", loggingObjectPath),
77 entry("INTERFACE=%s", loggingInterface),
78 entry("EXCEPTION=%s", e.what()));
79
80 throw std::runtime_error(
81 "Error in invoking D-Bus logging create interface");
82 }
83 catch (std::exception& e)
84 {
85 throw e;
86 }
87}
88
Jayanth Othayoth2eb31ad2021-09-20 07:13:28 -050089void createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
90 const FFDCData& ffdcData)
91{
92 std::map<std::string, std::string> additionalData;
93 auto bus = sdbusplus::bus::new_default();
94
95 additionalData.emplace("_PID", std::to_string(getpid()));
96 additionalData.emplace("SBE_ERR_MSG", sbeError.what());
97
98 for (auto& data : ffdcData)
99 {
100 additionalData.emplace(data);
101 }
102
103 std::vector<std::tuple<
104 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
105 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
106 pelFFDCInfo;
107
108 // Refer phosphor-logging/extensions/openpower-pels/README.md section
109 // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
110 // for details of related to createPEL with SBE FFDC information
111 // usin g CreateWithFFDCFiles api.
112 pelFFDCInfo.push_back(
113 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
114 Create::FFDCFormat::Custom,
115 static_cast<uint8_t>(0xCB), static_cast<uint8_t>(0x01),
116 sbeError.getFd()));
117 try
118 {
119 std::string service =
120 util::getService(bus, loggingObjectPath, loggingInterface);
121 auto method =
122 bus.new_method_call(service.c_str(), loggingObjectPath,
123 loggingInterface, "CreateWithFFDCFiles");
124 auto level =
125 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
126 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
127 Error);
128 method.append(event, level, additionalData, pelFFDCInfo);
129 auto resp = bus.call(method);
130 }
131 catch (const sdbusplus::exception::exception& e)
132 {
133 log<level::ERR>(fmt::format("D-Bus call exception",
134 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
135 loggingObjectPath, loggingInterface,
136 e.what())
137 .c_str());
138 throw std::runtime_error(
139 "Error in invoking D-Bus logging create interface");
140 }
141 catch (std::exception& e)
142 {
143 throw e;
144 }
145}
146
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500147void createPEL(const std::string& event, const FFDCData& ffdcData)
Andrew Geissler61febf02021-06-22 17:19:32 -0500148{
149 std::map<std::string, std::string> additionalData;
150 auto bus = sdbusplus::bus::new_default();
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500151
Andrew Geissler61febf02021-06-22 17:19:32 -0500152 additionalData.emplace("_PID", std::to_string(getpid()));
Jayanth Othayotha8d2f712021-09-20 07:02:51 -0500153 for (auto& data : ffdcData)
154 {
155 additionalData.emplace(data);
156 }
Andrew Geissler61febf02021-06-22 17:19:32 -0500157
158 try
159 {
Andrew Geissler61febf02021-06-22 17:19:32 -0500160 std::string service =
161 util::getService(bus, loggingObjectPath, loggingInterface);
162 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
163 loggingInterface, "Create");
164 auto level =
165 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
166 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
167 Error);
Jayanth Othayothac95c562021-07-16 05:56:04 -0500168 method.append(event, level, additionalData);
Andrew Geissler61febf02021-06-22 17:19:32 -0500169 auto resp = bus.call(method);
170 }
Patrick Williams2246cca2021-09-02 09:32:52 -0500171 catch (const sdbusplus::exception::exception& e)
Andrew Geissler61febf02021-06-22 17:19:32 -0500172 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500173 log<level::ERR>(fmt::format("sdbusplus D-Bus call exception",
174 "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
175 loggingObjectPath, loggingInterface,
176 e.what())
177 .c_str());
178 ;
Andrew Geissler61febf02021-06-22 17:19:32 -0500179
180 throw std::runtime_error(
181 "Error in invoking D-Bus logging create interface");
182 }
183 catch (std::exception& e)
184 {
Jayanth Othayothac95c562021-07-16 05:56:04 -0500185 log<level::ERR>(
186 fmt::format("D-bus call exception", "EXCEPTION={}", e.what())
187 .c_str());
Andrew Geissler61febf02021-06-22 17:19:32 -0500188 throw e;
189 }
190}
191
Brad Bishopf6783cd2020-10-27 19:25:09 -0400192FFDCFile::FFDCFile(const json& pHALCalloutData) :
193 calloutData(pHALCalloutData.dump()),
194 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
195{
196 prepareFFDCFile();
197}
198
199FFDCFile::~FFDCFile()
200{
201 removeCalloutFile();
202}
203
204int FFDCFile::getFileFD() const
205{
206 return fileFD;
207}
208
209void FFDCFile::prepareFFDCFile()
210{
211 createCalloutFile();
212 writeCalloutData();
213 setCalloutFileSeekPos();
214}
215
216void FFDCFile::createCalloutFile()
217{
218 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
219
220 if (fileFD == -1)
221 {
222 log<level::ERR>(fmt::format("Failed to create phalPELCallouts "
223 "file({}), errorno({}) and errormsg({})",
224 calloutFile, errno, strerror(errno))
225 .c_str());
226 throw std::runtime_error("Failed to create phalPELCallouts file");
227 }
228}
229
230void FFDCFile::writeCalloutData()
231{
232 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
233
234 if (rc == -1)
235 {
236 log<level::ERR>(fmt::format("Failed to write phaPELCallout info "
237 "in file({}), errorno({}), errormsg({})",
238 calloutFile, errno, strerror(errno))
239 .c_str());
240 throw std::runtime_error("Failed to write phalPELCallouts info");
241 }
242 else if (rc != static_cast<ssize_t>(calloutData.size()))
243 {
244 log<level::WARNING>(fmt::format("Could not write all phal callout "
245 "info in file({}), written byte({}) "
246 "and total byte({})",
247 calloutFile, rc, calloutData.size())
248 .c_str());
249 }
250}
251
252void FFDCFile::setCalloutFileSeekPos()
253{
254 int rc = lseek(fileFD, 0, SEEK_SET);
255
256 if (rc == -1)
257 {
258 log<level::ERR>(fmt::format("Failed to set SEEK_SET for "
259 "phalPELCallouts in file({}), errorno({}) "
260 "and errormsg({})",
261 calloutFile, errno, strerror(errno))
262 .c_str());
263 throw std::runtime_error(
264 "Failed to set SEEK_SET for phalPELCallouts file");
265 }
266}
267
268void FFDCFile::removeCalloutFile()
269{
270 close(fileFD);
271 std::remove(calloutFile.c_str());
272}
273
274} // namespace pel
275} // namespace openpower