blob: 4ca8bb0d2e44bc61d0f43840d3e9f57d3d5117c7 [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{
30void createBootErrorPEL(const FFDCData& ffdcData, const json& calloutData)
31{
32 constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
33 constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
34
35 std::map<std::string, std::string> additionalData;
36 auto bus = sdbusplus::bus::new_default();
37 additionalData.emplace("_PID", std::to_string(getpid()));
38 for (auto& data : ffdcData)
39 {
40 additionalData.emplace(data);
41 }
42
43 try
44 {
45 FFDCFile ffdcFile(calloutData);
46
47 std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging::
48 server::Create::FFDCFormat,
49 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
50 pelCalloutInfo;
51
52 pelCalloutInfo.push_back(
53 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
54 Create::FFDCFormat::JSON,
55 static_cast<uint8_t>(0xCA),
56 static_cast<uint8_t>(0x01), ffdcFile.getFileFD()));
57
58 static constexpr auto bootErrorMessage =
59 "org.open_power.PHAL.Error.Boot";
60 std::string service =
61 util::getService(bus, loggingObjectPath, loggingInterface);
62 auto method =
63 bus.new_method_call(service.c_str(), loggingObjectPath,
64 loggingInterface, "CreateWithFFDCFiles");
65 auto level =
66 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
67 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
68 Error);
69 method.append(bootErrorMessage, level, additionalData, pelCalloutInfo);
70 auto resp = bus.call(method);
71 }
72 catch (const sdbusplus::exception::SdBusError& e)
73 {
74 log<level::ERR>("D-Bus call exception",
75 entry("OBJPATH=%s", loggingObjectPath),
76 entry("INTERFACE=%s", loggingInterface),
77 entry("EXCEPTION=%s", e.what()));
78
79 throw std::runtime_error(
80 "Error in invoking D-Bus logging create interface");
81 }
82 catch (std::exception& e)
83 {
84 throw e;
85 }
86}
87
88FFDCFile::FFDCFile(const json& pHALCalloutData) :
89 calloutData(pHALCalloutData.dump()),
90 calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
91{
92 prepareFFDCFile();
93}
94
95FFDCFile::~FFDCFile()
96{
97 removeCalloutFile();
98}
99
100int FFDCFile::getFileFD() const
101{
102 return fileFD;
103}
104
105void FFDCFile::prepareFFDCFile()
106{
107 createCalloutFile();
108 writeCalloutData();
109 setCalloutFileSeekPos();
110}
111
112void FFDCFile::createCalloutFile()
113{
114 fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);
115
116 if (fileFD == -1)
117 {
118 log<level::ERR>(fmt::format("Failed to create phalPELCallouts "
119 "file({}), errorno({}) and errormsg({})",
120 calloutFile, errno, strerror(errno))
121 .c_str());
122 throw std::runtime_error("Failed to create phalPELCallouts file");
123 }
124}
125
126void FFDCFile::writeCalloutData()
127{
128 ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());
129
130 if (rc == -1)
131 {
132 log<level::ERR>(fmt::format("Failed to write phaPELCallout info "
133 "in file({}), errorno({}), errormsg({})",
134 calloutFile, errno, strerror(errno))
135 .c_str());
136 throw std::runtime_error("Failed to write phalPELCallouts info");
137 }
138 else if (rc != static_cast<ssize_t>(calloutData.size()))
139 {
140 log<level::WARNING>(fmt::format("Could not write all phal callout "
141 "info in file({}), written byte({}) "
142 "and total byte({})",
143 calloutFile, rc, calloutData.size())
144 .c_str());
145 }
146}
147
148void FFDCFile::setCalloutFileSeekPos()
149{
150 int rc = lseek(fileFD, 0, SEEK_SET);
151
152 if (rc == -1)
153 {
154 log<level::ERR>(fmt::format("Failed to set SEEK_SET for "
155 "phalPELCallouts in file({}), errorno({}) "
156 "and errormsg({})",
157 calloutFile, errno, strerror(errno))
158 .c_str());
159 throw std::runtime_error(
160 "Failed to set SEEK_SET for phalPELCallouts file");
161 }
162}
163
164void FFDCFile::removeCalloutFile()
165{
166 close(fileFD);
167 std::remove(calloutFile.c_str());
168}
169
170} // namespace pel
171} // namespace openpower