blob: f6b15eee40fb7898cb5d4685e8b62b6e7a2c51d9 [file] [log] [blame]
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -05001#include "create_pel.hpp"
2
3#include "dump_utils.hpp"
4
5#include <fcntl.h>
6#include <libekb.H>
7#include <unistd.h>
8
9#include <phosphor-logging/elog.hpp>
10#include <phosphor-logging/lg2.hpp>
11#include <xyz/openbmc_project/Logging/Create/server.hpp>
12#include <xyz/openbmc_project/Logging/Entry/server.hpp>
13
14#include <cerrno>
15#include <cstdio>
16#include <cstdlib>
17#include <cstring>
18#include <format>
19#include <map>
20#include <stdexcept>
21#include <string>
22#include <tuple>
23#include <vector>
24
25namespace openpower::dump::pel
26{
27
28using namespace phosphor::logging;
29constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
30constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
31constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";
32
33uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
Dhruvaraj Subhashchandranf9f65b82022-10-13 06:46:43 -050034 const FFDCData& ffdcData, const Severity severity)
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050035{
36 uint32_t plid = 0;
37 std::unordered_map<std::string, std::string> additionalData = {
38 {"_PID", std::to_string(getpid())}, {"SBE_ERR_MSG", sbeError.what()}};
39 auto bus = sdbusplus::bus::new_default();
40
41 additionalData.emplace("_PID", std::to_string(getpid()));
42 additionalData.emplace("SBE_ERR_MSG", sbeError.what());
43
44 for (auto& data : ffdcData)
45 {
46 additionalData.emplace(data);
47 }
48
49 std::vector<std::tuple<
50 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
51 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
52 pelFFDCInfo;
53
54 // get SBE ffdc file descriptor
55 auto fd = sbeError.getFd();
56
57 // Negative fd value indicates error case or invalid file
58 // No need of special processing , just log error with additional ffdc.
59 if (fd > 0)
60 {
61 // Refer phosphor-logging/extensions/openpower-pels/README.md section
62 // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
63 // for details of related to createPEL with SBE FFDC information
64 // usin g CreateWithFFDCFiles api.
65 pelFFDCInfo.emplace_back(
66 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
67 Create::FFDCFormat::Custom,
68 static_cast<uint8_t>(0xCB),
69 static_cast<uint8_t>(0x01), sbeError.getFd()));
70 }
71 try
72 {
73 auto service = util::getService(bus, opLoggingInterface,
74 loggingObjectPath);
75 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
76 opLoggingInterface,
77 "CreatePELWithFFDCFiles");
78 auto level =
79 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
Dhruvaraj Subhashchandranf9f65b82022-10-13 06:46:43 -050080 severity);
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050081 method.append(event, level, additionalData, pelFFDCInfo);
82 auto response = bus.call(method);
83
84 // reply will be tuple containing bmc log id, platform log id
85 std::tuple<uint32_t, uint32_t> reply = {0, 0};
86
87 // parse dbus response into reply
88 response.read(reply);
89 plid = std::get<1>(reply); // platform log id is tuple "second"
90 }
91 catch (const sdbusplus::exception::exception& e)
92 {
93 lg2::error(
94 "D-Bus call exception OBJPATH={OBJPATH}, INTERFACE={INTERFACE}, "
95 "EXCEPTION={ERROR}",
96 "OBJPATH", loggingObjectPath, "INTERFACE", loggingInterface,
97 "ERROR", e);
98
99 throw;
100 }
101 catch (const std::exception& e)
102 {
103 throw;
104 }
105
106 return plid;
107}
108
109FFDCFile::FFDCFile(const json& pHALCalloutData) :
110 calloutData(pHALCalloutData.dump()),
111 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
112{
113 prepareFFDCFile();
114}
115
116FFDCFile::~FFDCFile()
117{
118 removeCalloutFile();
119}
120
121int FFDCFile::getFileFD() const
122{
123 return fileFD;
124}
125
126void FFDCFile::prepareFFDCFile()
127{
128 createCalloutFile();
129 writeCalloutData();
130 setCalloutFileSeekPos();
131}
132
133void FFDCFile::createCalloutFile()
134{
135 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
136
137 if (fileFD == -1)
138 {
139 lg2::error("Failed to create phalPELCallouts file({FILE}), "
140 "errorno({ERRNO}) and errormsg({ERRORMSG})",
141 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
142 strerror(errno));
143 throw std::runtime_error("Failed to create phalPELCallouts file");
144 }
145}
146
147void FFDCFile::writeCalloutData()
148{
149 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
150
151 if (rc == -1)
152 {
153 lg2::error("Failed to write phaPELCallout info in file({FILE}), "
154 "errorno({ERRNO}), errormsg({ERRORMSG})",
155 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
156 strerror(errno));
157 throw std::runtime_error("Failed to write phalPELCallouts info");
158 }
159 else if (rc != static_cast<ssize_t>(calloutData.size()))
160 {
161 lg2::warning("Could not write all phal callout info in file({FILE}), "
162 "written byte({WRITTEN}), total byte({TOTAL})",
163 "FILE", calloutFile, "WRITTEN", rc, "TOTAL",
164 calloutData.size());
165 }
166}
167
168void FFDCFile::setCalloutFileSeekPos()
169{
170 int rc = lseek(fileFD, 0, SEEK_SET);
171
172 if (rc == -1)
173 {
174 lg2::error("Failed to set SEEK_SET for phalPELCallouts in "
175 "file({FILE}), errorno({ERRNO}), errormsg({ERRORMSG})",
176 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
177 strerror(errno));
178
179 throw std::runtime_error(
180 "Failed to set SEEK_SET for phalPELCallouts file");
181 }
182}
183
184void FFDCFile::removeCalloutFile()
185{
186 close(fileFD);
187 std::remove(calloutFile.c_str());
188}
189
190} // namespace openpower::dump::pel