blob: 916d312352998ba594a986e1c465d690470bb3b7 [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,
34 const FFDCData& ffdcData)
35{
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(
80 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
81 Error);
82 method.append(event, level, additionalData, pelFFDCInfo);
83 auto response = bus.call(method);
84
85 // reply will be tuple containing bmc log id, platform log id
86 std::tuple<uint32_t, uint32_t> reply = {0, 0};
87
88 // parse dbus response into reply
89 response.read(reply);
90 plid = std::get<1>(reply); // platform log id is tuple "second"
91 }
92 catch (const sdbusplus::exception::exception& e)
93 {
94 lg2::error(
95 "D-Bus call exception OBJPATH={OBJPATH}, INTERFACE={INTERFACE}, "
96 "EXCEPTION={ERROR}",
97 "OBJPATH", loggingObjectPath, "INTERFACE", loggingInterface,
98 "ERROR", e);
99
100 throw;
101 }
102 catch (const std::exception& e)
103 {
104 throw;
105 }
106
107 return plid;
108}
109
110FFDCFile::FFDCFile(const json& pHALCalloutData) :
111 calloutData(pHALCalloutData.dump()),
112 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
113{
114 prepareFFDCFile();
115}
116
117FFDCFile::~FFDCFile()
118{
119 removeCalloutFile();
120}
121
122int FFDCFile::getFileFD() const
123{
124 return fileFD;
125}
126
127void FFDCFile::prepareFFDCFile()
128{
129 createCalloutFile();
130 writeCalloutData();
131 setCalloutFileSeekPos();
132}
133
134void FFDCFile::createCalloutFile()
135{
136 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
137
138 if (fileFD == -1)
139 {
140 lg2::error("Failed to create phalPELCallouts file({FILE}), "
141 "errorno({ERRNO}) and errormsg({ERRORMSG})",
142 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
143 strerror(errno));
144 throw std::runtime_error("Failed to create phalPELCallouts file");
145 }
146}
147
148void FFDCFile::writeCalloutData()
149{
150 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
151
152 if (rc == -1)
153 {
154 lg2::error("Failed to write phaPELCallout info in file({FILE}), "
155 "errorno({ERRNO}), errormsg({ERRORMSG})",
156 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
157 strerror(errno));
158 throw std::runtime_error("Failed to write phalPELCallouts info");
159 }
160 else if (rc != static_cast<ssize_t>(calloutData.size()))
161 {
162 lg2::warning("Could not write all phal callout info in file({FILE}), "
163 "written byte({WRITTEN}), total byte({TOTAL})",
164 "FILE", calloutFile, "WRITTEN", rc, "TOTAL",
165 calloutData.size());
166 }
167}
168
169void FFDCFile::setCalloutFileSeekPos()
170{
171 int rc = lseek(fileFD, 0, SEEK_SET);
172
173 if (rc == -1)
174 {
175 lg2::error("Failed to set SEEK_SET for phalPELCallouts in "
176 "file({FILE}), errorno({ERRNO}), errormsg({ERRORMSG})",
177 "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
178 strerror(errno));
179
180 throw std::runtime_error(
181 "Failed to set SEEK_SET for phalPELCallouts file");
182 }
183}
184
185void FFDCFile::removeCalloutFile()
186{
187 close(fileFD);
188 std::remove(calloutFile.c_str());
189}
190
191} // namespace openpower::dump::pel